
 
/***************************************************************************
 *                                                                         *
 * Alberi:  Graphical Language Interface for POSTGRES                      *
 *                                                                         *
 * Copyright (c) 1992, 1993 The University of Georgia Research             *
 *                          Foundation, Inc.                               *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 * Designer and Programmer:  Ruben Robles                                  *
 * Email:  ruben@pollux.cs.uga.edu or rubenr3@aol.com or                   *
 *         rubenr3@psi.com@aol.com                                         *
 *                                                                         *
 * Modified by:		K.J. Kochut                                        *
 *			Department of Computer Science                     *
 *			University of Georgia                              *
 *			Athens, GA 30602                                   *
 *                                                                         *
 * Send comments/fixes/improvements/modifications to:                      *
 *                                                                         *
 *                     kochut@cs.uga.edu                                   *
 *                                                                         *
 ***************************************************************************/

#include <sys/param.h>

#include <xview/xview.h>
#include <xview/textsw.h>
#include <xview/panel.h>

/* slingshot headers */

#include <sspkg/canshell.h>
#include <sspkg/rectobj.h>
#include <sspkg/drawobj.h>
#include <sspkg/tree.h>
#include <sspkg/array.h>
#include <sspkg/list.h>

/* POSTGRES headers */

#include <tmp/c.h>
#include <tmp/libpq-fe.h>

#include "all_ui.h"
#include "externs.h"

#include "constants.h"
#include "grays.h"
#include "funcs.h"

extern Array_tile   target_tile, qual_tile;
extern char query_buffer[];
const char *heading = "retrieve (";


/*
 * Event callback function for `textpane1'.
 *
 * (Event in the DIRECT POSTQUEL INTERFACE)
 */
Notify_value
query_processing(win, event, arg, type)
     Xv_window		win;
     Event	       *event;
     Notify_arg		arg;
     Notify_event_type 	type;
{
  first_window1_objects	*ip = (first_window1_objects *)
    				xv_get(win, XV_KEY_DATA, INSTANCE);

  static int backslash = 0;
  static int inc_file = 0;
  char temp_q[8196];
  /* char query_buffer[1024]; */ 
  static int buffer_length; 
  char *app = "\\g";
  char *nl = "\n";        

  if (event_is_up(event) && event_is_ascii(event) && event_id(event) == '\\')
    if (!backslash)
      backslash = 1;
    else backslash = 0;
        
        /*  Process F7 to indicate submit query or \g */

  if ( event_is_up(event)
       && ((event_is_key_top(event) && (event_id(event) == KEY_TOP(7))
	    || (backslash
		&& event_is_ascii(event)
		&& event_id(event) == 'g'))) )  {

    backslash = 0;
    buffer_length = xv_get(win, TEXTSW_LENGTH);
                    /* Copy contents of the query window */
    		    /* into the buffer                   */
    xv_get(win, TEXTSW_CONTENTS, 0, query_buffer, buffer_length); 
    query_buffer[buffer_length] = '\0';

    if ( Verbose )
      textsw_insert(first_window1->textpane3, nl, 1);
                  
    strcpy(temp_q, clean_query(query_buffer));

    if ( Verbose ) {
      textsw_insert(first_window1->textpane3,
		    "Query sent to Postgres Backend:\n", 32);

      textsw_insert(first_window1->textpane3, temp_q, strlen(temp_q));
      textsw_insert(first_window1->textpane3, nl, 1);
    }
  
    if (handle_execution(temp_q, first_window1) == 1)
      backend_error( "Postgres backend returned error" );
    else {
      xv_set(first_window1->window1, FRAME_LEFT_FOOTER, "No errors", NULL);
      if ( temp_q[0] )
	insert_in_command_stack(temp_q);
      xv_set(win, TEXTSW_CONTENTS, "", NULL);     /* Clear query window */
      bzero(query_buffer, buffer_length); 	  /* and query_buffer   */
      buffer_length = 0;
    }
    
  }

  if ( event_is_up(event)
       && (backslash && event_is_ascii(event) && event_id(event) == 'q') ) {
    backslash = 0;
    quit();
  }

  if ( event_is_up(event)
       && (backslash && event_is_ascii(event) && event_id(event) == 'r') ) {
    backslash = 0;
    xv_set(win, TEXTSW_CONTENTS, "", NULL);
  }
        
  if ( event_is_up(event)
       && (backslash && event_is_ascii(event) && event_id(event) == 'i') ) {
    backslash = 0;
    inc_file = 1;
  }

  if ( event_is_up(event)
       && (inc_file && event_is_ascii(event) && event_id(event) == 13) ) {
    Textsw_status status;
    
    buffer_length = xv_get(win, TEXTSW_LENGTH);
    xv_get(win, TEXTSW_CONTENTS, 2, query_buffer, buffer_length - 2);
    xv_set(win, TEXTSW_CONTENTS, "", NULL); /* Clear query window */
    xv_set(win, TEXTSW_STATUS, &status,
	        TEXTSW_INSERT_FROM_FILE, query_buffer, NULL);
                  
    bzero(query_buffer, buffer_length-2); /* query_buffer[0] = 0 */
    buffer_length = 0;
    buffer_length = xv_get(win, TEXTSW_LENGTH);
				/* Copy contents of the query window */
				/* into the buffer                   */
    xv_get(win, TEXTSW_CONTENTS, 0, query_buffer, buffer_length);
 
    if ( Verbose )
      textsw_insert(first_window1->textpane3, nl, 1);

    strcpy(temp_q, clean_query(query_buffer));

    if ( Verbose ) {
      textsw_insert(first_window1->textpane3,
		    "Query sent to Postgres Backend:\n", 32);

      textsw_insert(first_window1->textpane3, temp_q, strlen(temp_q));
      textsw_insert(first_window1->textpane3, nl, 1);
    }
    
    if (handle_execution(temp_q, first_window1) == 1)
      backend_error( "Postgres backend returned error" );
    else {
      xv_set(first_window1->window1, FRAME_LEFT_FOOTER, "No errors", NULL);  
      xv_set(win, TEXTSW_CONTENTS, "", NULL); /* Clear query window */
      bzero(query_buffer, buffer_length);     /* and query_buffer   */
      buffer_length = 0;
      if ( temp_q[0] )
	insert_in_command_stack(temp_q);
    }

    inc_file = 0;
                  
  }
	
  return notify_next_event_func( win, (Notify_event) event, arg, type );
}


void
query_drop( canvas_shell, rectobj, drop_canvas_shell, drop_rectobj, drop_event )
     Canvas_shell canvas_shell;
     Rectobj rectobj;
     Canvas_shell drop_canvas_shell;
     Rectobj drop_rectobj;
     Event *drop_event;
{
  Rectobj_list *a_list;
  Rectobj a_rectobj;
  static char the_drop_query[8196], temp_q[8196];
  char retrieve[8196];

  char *last_comma = "";
  int len;

  the_drop_query[0] = '\0';
  
  strcpy(the_drop_query, heading); 
  a_list = get_selected_list();

  /* extract the names on the list.  There are two cases:
   * 1)  classes:  take the name and construct
   			"retrieve (class1.all, class2.all, ...)"
   * 2)  attributes:  check the class and construct
   			"retrieve (class.att1, class.att2, ...)"
   */

  list_for(a_list) {
       
    a_rectobj = RECTOBJ_LIST_HANDLE(a_list);
    if ( (int) xv_get(a_rectobj, XV_KEY_DATA, TYPE) )  /* an attribute!!! */ {
      sprintf(retrieve, "%s.%s, ",
	      (char *) xv_get(a_rectobj, XV_KEY_DATA, CLASS),
	      (char *) xv_get(a_rectobj, DRAWTEXT_STRING));
      strcat(the_drop_query, retrieve);
    }
    else {
      sprintf(retrieve, "%s.all, ",
	      (char *) xv_get(a_rectobj, DRAWTEXT_STRING));
      strcat(the_drop_query, retrieve);  
    }
  }
  last_comma = strrchr(the_drop_query, ',');
  *last_comma = ')';
  
  strcpy(query_buffer, the_drop_query);
     
  len = strlen(the_drop_query);
  bzero(the_drop_query, len);
  len = strlen(retrieve);
  bzero(retrieve, len);
  len = strlen(last_comma);
  bzero(last_comma, len);
  
  xv_set((Xv_window) xv_get(drop_canvas_shell, XV_OWNER), 
	 FRAME_LEFT_FOOTER, (char *) xv_get(rectobj, DRAWTEXT_STRING),  
	 FRAME_RIGHT_FOOTER, "Dropped",
	 NULL);
 
  if ( Verbose ) 
    textsw_insert(first_window1->textpane3, "\n", 1);
                  
  strcpy(temp_q, clean_query(query_buffer));
  if ( Verbose ) {
    textsw_insert(first_window1->textpane3,
		  "Query sent to Postgres Backend:\n", 32);
    textsw_insert(first_window1->textpane3, temp_q, strlen(temp_q));
    textsw_insert(first_window1->textpane3, "\n", 1);
  }
  
  if (handle_execution(temp_q, first_window1) == 1)
    backend_error( "Postgres backend returned error" );
  else {
    xv_set(first_window1->window1, FRAME_LEFT_FOOTER, "No errors", NULL);  
    bzero(query_buffer, strlen(query_buffer));	  /* and query_buffer   */
    if(temp_q[0]) insert_in_command_stack(temp_q);
  }
  
}

void
submmit_the_query_proc(paint_window, event, canvas_shell, rectobj)
     Xv_window paint_window;
     Event *event;
     Canvas_shell canvas_shell;
     Rectobj rectobj;
{ 

  /* Walk through the retrieve_shell, from_list, and qual_shell 
   * to construct the query, send it, and print the output or errors 
   * Ok, I'm trying to make this callback more general to simplify
   * a little this already growing code.  The way to go in this is
   * to check what system is visible (using the XV_SHOW attribute)
   * depending on this then the constructors I'm gonna to call.
   * There are similar cases when submitting retrieve, append, delete,
   * replace; and in the case of create, addattr; rename and destroy
   * are special cases which are going to be treated in a separate 
   * routine. The from and where construtor are reusable in all the
   * cases, routines for append, delete, replace has to be written.
   * This is here just as a reminder that you "just do it"
   */

   char *retrieve, *from, *where, temp[8196], query_buffer[8196], temp_q[8196];
   Bool command;
   Bool Retrieve, Where, Attrib, Inherit, Addattr;
  /* First construct the retrieve part and get the string */

   xv_set(marco, FRAME_BUSY, TRUE, NULL); 

   Retrieve = (Bool) xv_get(target_frame, XV_SHOW);
   Where = (Bool) xv_get(qual_frame, XV_SHOW);
   Attrib = (Bool) xv_get(attrib_creation_frame, XV_SHOW);
   Inherit = (Bool) xv_get(inheritance_frame, XV_SHOW);
   Addattr = (Bool) xv_get(attrib_addition_frame, XV_SHOW);

   temp[0] = '\0';
   command = (Retrieve && Where) || (Attrib && Inherit) || (Addattr);


   if((Retrieve && Where) && !(Attrib || Inherit) && !Addattr) {
   							
     (void) strcpy(temp, retrieve_constructor());

     strcat(temp, from_constructor());
     strcat(temp, where_constructor());
     
   }
   else if ((Attrib && Inherit) && !(Retrieve || Where) && !Addattr) {
							
     (void) strcpy(temp, create_constructor());
     strcat(temp, inheritance_constructor());
 
   } 
   else if (Addattr && !(Retrieve || Where) && !(Attrib || Inherit)) {
     (void) strcpy(temp, addattr_constructor());
   }



   if(command) {
     strcpy(query_buffer, temp);

  
     xv_set((Frame) xv_get(canvas_shell, XV_OWNER), 
	    FRAME_LEFT_FOOTER, "Query...",  
	    FRAME_RIGHT_FOOTER, "Submmited",
	    NULL);
 
     if ( Verbose )
       textsw_insert(first_window1->textpane3, "\n", 1);
                  
     strcpy(temp_q, clean_query(query_buffer));
 
     if ( Verbose ) {
       textsw_insert(first_window1->textpane3, 
		     "Query sent to Postgres Backend:\n", 32);
                  
       textsw_insert(first_window1->textpane3, temp_q, strlen(temp_q));
       textsw_insert(first_window1->textpane3, "\n", 1); 
     }
 
     if (handle_execution(temp_q, first_window1) == 1)
       backend_error( "Postgres backend returned error");
     else { 
       xv_set(first_window1->window1, FRAME_LEFT_FOOTER, "No errors", NULL);
       bzero(query_buffer, strlen(query_buffer));   /* and query_buffer   */
/*       xv_set( target_frame, FRAME_LEFT_FOOTER, "", NULL ); */

       if ( temp_q[0] )
	 insert_in_command_stack(temp_q);
     }

     if((char *) strstr(temp_q, "create") || 
	(char *) strstr(temp_q, "retrieve into") || 
	(char *) strstr(temp_q, "addattr")) {
       update_schema();
     }

   } /* If there is command windows visible do the preceeding ... */
   xv_set(marco, FRAME_BUSY, FALSE, NULL); 
 }

/* Walk through the retrieve_shell, from_list, and qual_shell 
 * to construct the query, send it, and print the output or errors 
 */
void
menu_submmit(menu, menu_item)
     Menu menu;
     Menu_item menu_item;
{
  char *retrieve, *from, *where, temp[8196], query_buffer[8196], temp_q[8196];
  Bool command;
  Bool Retrieve, Where, Attrib, Inherit, Addattr;
  /* First construct the retrieve part and get the string */

  xv_set(marco, FRAME_BUSY, TRUE, NULL);

  Retrieve = (Bool) xv_get(target_frame, XV_SHOW);
  Where = (Bool) xv_get(qual_frame, XV_SHOW);
  Attrib = (Bool) xv_get(attrib_creation_frame, XV_SHOW);
  Inherit = (Bool) xv_get(inheritance_frame, XV_SHOW);
  Addattr = (Bool) xv_get(attrib_addition_frame, XV_SHOW);

  temp[0] = '\0';
  command = (Retrieve && Where) || (Attrib && Inherit) || (Addattr);

  if ( (Retrieve && Where) && !(Attrib || Inherit) && !Addattr ) {

    strcpy(temp, retrieve_constructor());
    strcat(temp, from_constructor());
    strcat(temp, where_constructor());

  }
  else if ( (Attrib && Inherit) && !(Retrieve || Where) && !Addattr ) {

    strcpy(temp, create_constructor());
    strcat(temp, inheritance_constructor());
 
  }
  else if ( Addattr && !(Retrieve || Where) && !(Attrib || Inherit) )
    strcpy(temp, addattr_constructor());

  if ( command ) {
    strcpy(query_buffer, temp);
  
    xv_set(marco, 
	   FRAME_LEFT_FOOTER, "Query...",  
	   FRAME_RIGHT_FOOTER, "Submmited",
	   NULL);
 
    if ( Verbose )
      textsw_insert(first_window1->textpane3, "\n", 1);
                  
    strcpy(temp_q, clean_query(query_buffer));
 
    if ( Verbose ) {
      textsw_insert( first_window1->textpane3,
		   "Query sent to Postgres Backend:\n", 32);

      textsw_insert( first_window1->textpane3, temp_q, strlen(temp_q));
      textsw_insert(first_window1->textpane3, "\n", 1); 
    }
 
    if ( handle_execution(temp_q, first_window1) == 1 )
      backend_error( "Postgres backend returned error" );
    else {
      xv_set(first_window1->window1, FRAME_LEFT_FOOTER, "No errors", NULL); 
      bzero( query_buffer, strlen(query_buffer) );
    		     /* query_buffer       */
      if ( temp_q[0] )
	insert_in_command_stack(temp_q);
    }

    if ( (char *) strstr(temp_q, "create" ) || 
	(char *) strstr(temp_q, "retrieve into") || 
	(char *) strstr(temp_q, "addattr"))
      update_schema();


  } /* If there are command windows visible do the preceeding ... */
  xv_set(marco, FRAME_BUSY, FALSE, NULL);
}


void
clean_the_icon_query(menu, menu_item)
     Menu menu;
     Menu_item menu_item;
{
   Array_tile the_array;
   Rectobj  the_element, a_class;
   Rectobj_list *the_class_list;
   Tree the_expression;
   Menu other_menu;
   
   xv_set(target_shell, RECTOBJ_ACCEPTS_DROP, TRUE,
	  RECTOBJ_DROP_PROC, adding_stuff_in_the_array, NULL); 
   the_array = target_tile;
   xv_set(expression_frame, FRAME_BUSY, TRUE, NULL);
   xv_set((Frame) xv_get((Canvas_shell) xv_get(the_array, XV_OWNER),
			 XV_OWNER),
	  FRAME_BUSY, TRUE, 
	  NULL);
   xv_set( target_frame, FRAME_LEFT_FOOTER, "", NULL );
   while(xv_get(the_array, ARRAY_TILE_POSITION, 0, 0)) {

     xv_set(the_array, ARRAY_TILE_AUTO_LAYOUT, FALSE, NULL); 
     the_element = (Rectobj) xv_get(the_array, ARRAY_TILE_POSITION, 0, 0);
     other_menu = (Menu) xv_get(the_element, RECTOBJ_MENU);          
     the_expression = (Tree) xv_get(the_element, XV_KEY_DATA, EXPRESSION_TREE);
    
   

     recursive_delete(the_expression, the_expression);  /* Kill the tree */
   
   
     xv_destroy(the_element);
     xv_destroy(other_menu);

     xv_set(the_array, ARRAY_TILE_AUTO_LAYOUT, TRUE, NULL);

     xv_set((Canvas_shell) xv_get(the_array, XV_OWNER),
	    CANVAS_MIN_PAINT_WIDTH, xv_get(the_array, XV_WIDTH) + 10,
	    CANVAS_MIN_PAINT_HEIGHT, xv_get(the_array, XV_HEIGHT) + 10,
	    NULL);
    
   }
   xv_set((Frame) xv_get((Canvas_shell) xv_get(the_array, XV_OWNER), XV_OWNER),
	  FRAME_BUSY, FALSE,
	  NULL);

   if ( (Tree) xv_get(qual_shell, XV_KEY_DATA, THE_ARRAY) )
     recursive_recursive_delete((Tree) xv_get(qual_shell,
					      XV_KEY_DATA, THE_ARRAY),
				(Tree) xv_get(qual_shell,
					      XV_KEY_DATA, THE_ARRAY));
   qual_tree = 0;
   xv_set(qual_shell, XV_KEY_DATA, THE_ARRAY, 0, NULL);
  
  xv_set(qual_frame, FRAME_BUSY, FALSE, NULL);
   /* cleared everything up then proceed to clear the instances */
   the_array = classes;
   the_class_list = (Rectobj_list *) xv_get(the_array, RECTOBJ_CHILDREN);
   list_for ( the_class_list ) {
     a_class = RECTOBJ_LIST_HANDLE(the_class_list);
     the_element = (Array_tile) xv_get(a_class, XV_KEY_DATA, INSTANCES);
     if(the_element) { 
       xv_destroy((Array_tile) the_element);
       xv_set(a_class, XV_KEY_DATA, INSTANCES, NULL, NULL );
     }
   }
   /* Finished */
   xv_set(expression_frame, FRAME_BUSY, FALSE, NULL);
}

void
show_query_system(menu, menu_item)
     Menu menu;
     Menu_item menu_item;
{
    Rect position_and_size_info, other;
    int FRAMEUNITWIDTH, FRAMELEFTUNITHEIGHT, FRAMERIGHTUNITHEIGHT;
    const int iter = 0, y;

    FRAMEUNITWIDTH = 
      ((int) xv_get(marco, XV_WIDTH) +
       (int) xv_get(first_window1->window1, XV_WIDTH) - 10) / 3;
    FRAMELEFTUNITHEIGHT = ((int) xv_get(marco, XV_HEIGHT) - 100) / 4;
    FRAMERIGHTUNITHEIGHT = ((int) xv_get(marco, XV_HEIGHT) / 3);

    frame_get_rect(marco, &other);
    
    xv_set(attrib_creation_frame, 
	   FRAME_CMD_PUSHPIN_IN, FALSE, 
	   XV_SHOW, FALSE, 
	   NULL);
    xv_set(inheritance_frame,
	   FRAME_CMD_PUSHPIN_IN, FALSE,
	   XV_SHOW, FALSE, 
	   NULL);
    xv_set(attrib_addition_frame, 
	   FRAME_CMD_PUSHPIN_IN, FALSE, 
	   XV_SHOW, FALSE, 
	   NULL);

    xv_set(target_frame, XV_SHOW, TRUE, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
    xv_set(target_shell, 
	   RECTOBJ_ACCEPTS_DROP, TRUE, 
	   RECTOBJ_DROP_PROC, adding_stuff_in_the_array,
	   NULL);
    xv_set(qual_frame, XV_SHOW, TRUE, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
    xv_set(expression_frame, XV_SHOW, TRUE, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
    /* iter++; */

}

void
hide_query_system(menu, menu_item)
     Menu menu;
     Menu_item menu_item;
{
  xv_set(attrib_creation_frame, 
	 FRAME_CMD_PUSHPIN_IN, FALSE,
	 XV_SHOW, FALSE, 
	 NULL);
  xv_set(inheritance_frame, 
	 FRAME_CMD_PUSHPIN_IN, FALSE, 
	 XV_SHOW, FALSE, 
	 NULL);
  xv_set(attrib_addition_frame, 
	 FRAME_CMD_PUSHPIN_IN, FALSE, 
	 XV_SHOW, FALSE, 
	 NULL);
  xv_set(target_frame, FRAME_CMD_PUSHPIN_IN, FALSE, XV_SHOW, FALSE, NULL);
  xv_set(target_shell,
	 RECTOBJ_ACCEPTS_DROP, TRUE,
	 RECTOBJ_DROP_PROC, adding_stuff_in_the_array,
	 NULL);
  xv_set(expression_frame, FRAME_CMD_PUSHPIN_IN, FALSE, XV_SHOW, FALSE, NULL);
  xv_set(qual_frame, FRAME_CMD_PUSHPIN_IN, FALSE, XV_SHOW, FALSE, NULL);

}

