/************************************************************************/
/* Module : callback.c					                */
/* Purpose: widget callback module for Mpsql     	                */
/* By     : Keith R. Davis					        */
/* Date   : 12/8/95					                */
/* Notes  : Copyright(c) 1996 White River Software			*/
/************************************************************************/

#include <Xm/Xm.h>		/* motif lib header		*/
#include <Xm/PushB.h>		/* push button widget header	*/
#include <Xm/RowColumn.h>	/* row/col widget header	*/
#include <Xm/Label.h>		/* label widget header		*/
#include <Xm/List.h>            /* list widget header           */
#include <Xm/TextF.h>		/* text widget header		*/
#include <Xm/MessageB.h>	/* message box header	        */
#include <Xm/FileSB.h>          /* file selection widget header */
#include <string.h>		/* string lib header		*/
#include <stdio.h>              /* stdio header                 */

#include "pixmap.h"             /* pixmap header                */
#include "mquel.h"              /* mquel header                 */
#include "menu.h"		/* menu header		        */
#include "callback.h"           /* callback header              */
#include "llist.h"              /* linked list header           */
#include "db.h"                 /* db header                    */
#include "util.h"               /* utility func. header         */

/************************************************************************/
/* Function: DeleteWindowCallback                                       */
/* Purpose : handles processing for WM_DELETE_WINDOW message            */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void DeleteWindowCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  /* close database & remove linked list */ 
  DB_Close();
  LLIST_Remove();
  exit(0);
}

/************************************************************************/
/* Function: ConnectCallback                                            */
/* Purpose : handles database connection request                        */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void ConnectCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  const char *title = "Connect";                   /* dialog title string            */
  Widget rc;                                       /* rowcol widget for dialog       */
  static Widget connect_dialog = NULL;             /* dialog widget                  */

  if(!connect_dialog){
    connect_dialog = XmCreateMessageDialog(AppWidgetsPtr->mainwindow, "connectdialog", NULL, 0);
  
    /* remove uneeded children */
    XtUnmanageChild(XmMessageBoxGetChild(connect_dialog, XmDIALOG_HELP_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(connect_dialog, XmDIALOG_SYMBOL_LABEL));
    XtUnmanageChild(XmMessageBoxGetChild(connect_dialog, XmDIALOG_MESSAGE_LABEL));

    /* setup dialog */
    XtVaSetValues(connect_dialog,
		  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		  XtVaTypedArg, XmNdialogTitle, XmRString,
		  title, strlen(title)+1,
		  NULL);

    rc = XtVaCreateManagedWidget("rc", xmRowColumnWidgetClass, connect_dialog,
				 XmNnumColumns, 2,
				 XmNpacking, XmPACK_COLUMN,
				 XmNorientation, XmVERTICAL,
				 NULL);

    XtCreateManagedWidget("Database name:", xmLabelWidgetClass, rc, NULL, 0);
    XtCreateManagedWidget("Host name:", xmLabelWidgetClass, rc, NULL, 0);
    XtCreateManagedWidget("Port:", xmLabelWidgetClass, rc, NULL, 0);

    AppWidgetsPtr->database = XtVaCreateManagedWidget("database", xmTextFieldWidgetClass,
						      rc,
						      XmNmaxLength, DB_NAME_SZ,
						      NULL);
    AppWidgetsPtr->host = XtVaCreateManagedWidget("host", xmTextFieldWidgetClass,
						  rc, 
						  XmNmaxLength, HOST_NAME_SZ,
						  NULL);
    AppWidgetsPtr->port = XtVaCreateManagedWidget("port", xmTextFieldWidgetClass,
						rc, 
						XmNmaxLength, PORT_NAME_SZ,
						NULL);
    /* add callbacks */
    XtAddCallback(connect_dialog, XmNokCallback, ConnectOKCallback, NULL);
  }

  if(dbname != NULL)
    XmTextSetString(AppWidgetsPtr->database, dbname);
  if(host != NULL)
    XmTextSetString(AppWidgetsPtr->host, host);
  if(port != NULL)
    XmTextSetString(AppWidgetsPtr->port, port);

  XtManageChild(connect_dialog);
}

/************************************************************************/
/* Function: ConnectOKCallback                                          */
/* Purpose : calls DB_Connect()                                         */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void ConnectOKCallback(Widget w, XtPointer clientData, XtPointer callData)
{
  strcpy(dbname, doubleTrim((char*)XmTextGetString(AppWidgetsPtr->database)));
  strcpy(host, doubleTrim((char*)XmTextGetString(AppWidgetsPtr->host)));
  strcpy(port, doubleTrim((char*)XmTextGetString(AppWidgetsPtr->port)));

  if((strlen(dbname) == 0) || (strlen(host) == 0) || (strlen(port) == 0))
    ErrorMsg("Connect", "Make sure all fields are filled!");
  else
    DB_Connect();
}

/************************************************************************/
/* Function: NewCallback                                                */
/* Purpose : handles new buffer request                                 */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void NewCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  if((buffer_curr = DB_OpenScratchBuffer()) != NULL)
    buffer_curr = DB_SetBuffer(buffer_curr);
}

/************************************************************************/
/* Function: OpenCallback                                               */
/* Purpose : handles open file request                                  */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void OpenCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  const char *title = "Open";           /* dialog title string          */     
  Widget text = (Widget)clientdata;     /* selected file info           */
  static Widget open_dialog = NULL;     /* dialog widget                */

  if(!open_dialog){
    open_dialog = XmCreateFileSelectionDialog(AppWidgetsPtr->mainwindow,
					      "OpenFileDialog",
					      NULL, 0);
    /* setup dialog */
    XtVaSetValues(open_dialog,
		  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		  XtVaTypedArg, XmNdialogTitle, XmRString,
		  title, strlen(title)+1,
		  NULL);

    /* add callbacks */
    XtAddCallback(open_dialog, XmNokCallback, OpenOKCallback, NULL);
    XtAddCallback(open_dialog, XmNcancelCallback, OpenCancelCallback, NULL);
  }
  XtManageChild(open_dialog);
}

/************************************************************************/
/* Function: OpenOKCallback                                             */
/* Purpose : calls DB_OpenFile()                                        */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   : file errors handled by DB_OpenFile()                       */
/************************************************************************/

void OpenOKCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  char *filename;         /* file to open               */

  /* get the filename selected */
  XmFileSelectionBoxCallbackStruct *cbs =
    (XmFileSelectionBoxCallbackStruct*)callData;

  XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &filename);

  /* close dialog */
  XtUnmanageChild(w);

  /* open the file */
  DB_OpenFile(filename);
}

/************************************************************************/
/* Function: OpenCancelCallback                                         */
/* Purpose : closes open file dialog on cancel                          */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void OpenCancelCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  XtUnmanageChild(w);
}

/************************************************************************/
/* Function: SaveCallback                                               */
/* Purpose : handles save file request                                  */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   : file errors handled by DB_SaveFile()                       */
/************************************************************************/

void SaveCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  if(strcmp(buffer_curr->filename, "scratch") == 0)
    SaveAsCallback(NULL, NULL, NULL);
  else
    DB_SaveFile(buffer_curr);
}

/************************************************************************/
/* Function: SaveAsCallback                                             */
/* Purpose : handles save as file request                               */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void SaveAsCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  const char *title = "Save As";          /* dialog title string        */
  Widget text = (Widget)clientdata;       /* selected file data         */
  static Widget save_dialog = NULL;       /* dialog widget              */

  if(!save_dialog){
    save_dialog = XmCreateFileSelectionDialog(AppWidgetsPtr->mainwindow,
					      "SaveFileDialog",
					      NULL, 0);

    /* setup dialog */
    XtVaSetValues(save_dialog,
		  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		  XtVaTypedArg, XmNdialogTitle, XmRString,
		  title, strlen(title)+1,
		  NULL);

    /* add callbacks */
    XtAddCallback(save_dialog, XmNokCallback, SaveAsOKCallback, NULL);
    XtAddCallback(save_dialog, XmNcancelCallback, SaveAsCancelCallback, NULL);
  }
  XtManageChild(save_dialog);
}

/************************************************************************/
/* Function: SaveAsOKCallback                                           */
/* Purpose : calls DB_SaveFile()                                        */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   : file errors handled by DB_SaveFile()                       */
/************************************************************************/

void SaveAsOKCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  char *filename;            /* filename to save as                     */
  char tmp_fn[MAX_PATH_LEN]; /* tmp filename                            */

  /* get filename */
  XmFileSelectionBoxCallbackStruct *cbs =
    (XmFileSelectionBoxCallbackStruct*)callData;

  XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &filename);

  XtUnmanageChild(w);

  /* save the file & copy new filename to linked list node holding the buffered file data */
  strcpy(tmp_fn, buffer_curr->filename);
  strcpy(buffer_curr->filename, filename);

  if(!DB_SaveFile(buffer_curr))
    strcpy(buffer_curr->filename, tmp_fn);
}

/************************************************************************/
/* Function: SaveAsCancelCallback                                       */
/* Purpose : closes save as file dialog on cancel                       */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void SaveAsCancelCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  XtUnmanageChild(w);
}

/************************************************************************/
/* Function: CloseCallback                                              */
/* Purpose : handles exit application request                           */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void CloseCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  /* dialog message strings */
  const char *title = "Quit";
  const char *quit_msg = "Unsaved modified buffers exist.\nContinue without saving?";
  
  /* dialog widget */
  static Widget close_dialog = NULL;

  /* check linked list for modified buffers & if so, prompt user ...*/
  if(DB_ChkModBuffers()){

    if(!close_dialog){
      close_dialog = XmCreateQuestionDialog(AppWidgetsPtr->mainwindow, "closedialog", NULL, 0);
    
      /* remove uneeded children */
      XtUnmanageChild(XmMessageBoxGetChild(close_dialog, XmDIALOG_HELP_BUTTON));
    
      /* setup dialog */
      XtVaSetValues(close_dialog,
		    XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		    XtVaTypedArg, XmNdialogTitle, XmRString,
		    title, strlen(title)+1,
		    XtVaTypedArg, XmNmessageString, XmRString,
		    quit_msg, strlen(quit_msg)+1, NULL);
	
      /* add callbacks */
      XtAddCallback(close_dialog, XmNokCallback, ReallyQuitCallback, NULL);
    }
    XtManageChild(close_dialog);
  }
  else {
    /* shutdown application */
    DB_Close();
    LLIST_Remove();
    exit(0);
  }
}

/************************************************************************/
/* Function: ReallyQuitCallback                                         */
/* Purpose : handles exit application request                           */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   : if the app has modified buffers on close, this will force  */
/*           closing with out saving...(OK button)                      */
/************************************************************************/

void ReallyQuitCallback(Widget w, XtPointer clientData, XtPointer callData)
{
    DB_Close();
    LLIST_Remove();
    exit(0);
}

/************************************************************************/
/* Function: CutCallback                                                */
/* Purpose : handles cuting of selected text to clipboard               */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void CutCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  XmTextCut(AppWidgetsPtr->sqlwindow, XtLastTimestampProcessed(XtDisplay(w)));
}

/************************************************************************/
/* Function: CopyCallback                                               */
/* Purpose : handles copying of selected text to clipboard              */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void CopyCallback(Widget w, XtPointer clientdata, XtPointer callData)
{ 
  if((char*)XmTextGetSelection(AppWidgetsPtr->sqlwindow) != NULL)
    XmTextCopy(AppWidgetsPtr->sqlwindow, XtLastTimestampProcessed(XtDisplay(w)));
  else if((char*)XmTextGetSelection(AppWidgetsPtr->resultwindow) != NULL)
    XmTextCopy(AppWidgetsPtr->resultwindow, XtLastTimestampProcessed(XtDisplay(w)));
}

/************************************************************************/
/* Function: PasteCallback                                              */
/* Purpose : handles pasting of text from the clipboard                 */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void PasteCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  XmTextPaste(AppWidgetsPtr->sqlwindow);
}

/************************************************************************/
/* Function: ClearResultCallback                                        */
/* Purpose : clears the result window                                   */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void ClearResultCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  XmTextSetString(AppWidgetsPtr->resultwindow, '\0');
}

/************************************************************************/
/* Function: SpoolCallback                                              */
/* Purpose : handles spool file definition                              */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void SpoolCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  const char *title = "Spool";                   /* dialog title        */
  Widget rc;                                     /* rowcol widget       */
  static Widget spool_dialog = NULL;             /* dialog widget       */

  if(!spool_dialog){
    spool_dialog = XmCreateMessageDialog(AppWidgetsPtr->mainwindow, "spooldialog", NULL, 0);
  
    /* remove uneeded children */
    XtUnmanageChild(XmMessageBoxGetChild(spool_dialog, XmDIALOG_HELP_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(spool_dialog, XmDIALOG_SYMBOL_LABEL));
    XtUnmanageChild(XmMessageBoxGetChild(spool_dialog, XmDIALOG_MESSAGE_LABEL));

    /* setup dialog */
    XtVaSetValues(spool_dialog,
		  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		  XtVaTypedArg, XmNdialogTitle, XmRString,
		  title, strlen(title)+1,
		  NULL);

    rc = XtVaCreateManagedWidget("rc", xmRowColumnWidgetClass, spool_dialog,
				 XmNnumColumns, 2,
				 XmNpacking, XmPACK_COLUMN,
				 XmNorientation, XmVERTICAL,
				 NULL);

    XtCreateManagedWidget("Enter spool filename:", xmLabelWidgetClass, rc, NULL, 0);
    AppWidgetsPtr->spoolfile = XtVaCreateManagedWidget("spoolfile", xmTextFieldWidgetClass,
						       rc,
						       XmNmaxLength, MAX_PATH_LEN,
						       NULL);

    /* add callback */
    XtAddCallback(spool_dialog, XmNokCallback, SpoolOKCallback, NULL);
  }

  if(spool_file != NULL)
    XmTextSetString(AppWidgetsPtr->spoolfile, spool_file);

  XtManageChild(spool_dialog);
}

/************************************************************************/
/* Function: SpoolOKCallback                                            */
/* Purpose : sets spool file name to user definition                    */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void SpoolOKCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  strcpy(spool_file, doubleTrim((char *)XmTextGetString(AppWidgetsPtr->spoolfile)));  
}

/************************************************************************/
/* Function: ColWidthCallback                                           */
/* Purpose : handles column width definition                            */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void ColWidthCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  const char *title = "Column Width";          /* dialog title          */
  Widget rc;                                   /* rowcol widget         */
  static Widget colwidth_dialog = NULL;        /* dialog widget         */
  char num_value[5];                           /* col width value       */

  if(!colwidth_dialog){
    colwidth_dialog = XmCreateMessageDialog(AppWidgetsPtr->mainwindow, 
					    "colwidthdialog", NULL, 0);
  
    /* remove uneeded children */
    XtUnmanageChild(XmMessageBoxGetChild(colwidth_dialog, XmDIALOG_HELP_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(colwidth_dialog, XmDIALOG_SYMBOL_LABEL));
    XtUnmanageChild(XmMessageBoxGetChild(colwidth_dialog, XmDIALOG_MESSAGE_LABEL));

    /* setup dialog */
    XtVaSetValues(colwidth_dialog,
		  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		  XtVaTypedArg, XmNdialogTitle, XmRString,
		  title, strlen(title)+1,
		  NULL);

    rc = XtVaCreateManagedWidget("rc", xmRowColumnWidgetClass, colwidth_dialog,
				 XmNnumColumns, 2,
				 XmNpacking, XmPACK_COLUMN,
				 XmNorientation, XmVERTICAL,
				 NULL);

    XtCreateManagedWidget("Enter column width:", xmLabelWidgetClass, rc, NULL, 0);
    AppWidgetsPtr->colwidth = XtVaCreateManagedWidget("colwidth", xmTextFieldWidgetClass,
						      rc,
						      XmNmaxLength, COL_SZ,
						      NULL);

    /* add callbacks */
    XtAddCallback(colwidth_dialog, XmNokCallback, ColWidthOKCallback, NULL);
  }

  XmTextSetString(AppWidgetsPtr->colwidth, itoa(col_width, num_value));

  XtManageChild(colwidth_dialog);
}

/************************************************************************/
/* Function: ColWidthCallback                                           */
/* Purpose : set column width to user definition                        */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void ColWidthOKCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  col_width = atoi(doubleTrim((char *)XmTextGetString(AppWidgetsPtr->colwidth)));
}

/************************************************************************/
/* Function: SaveOptCallback                                            */
/* Purpose : saves user defined options                                 */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void SaveOptCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  MQUEL_SaveOptions();
}

/************************************************************************/
/* Function: AboutCallback                                              */
/* Purpose : displays the about box                                     */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void AboutCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  /* dialog message strings */
  const char *title = "About";
  const char *info = "MPSQL\nv1.5.0\n\nBy Keith R. Davis\nEmail: (keidav@whidbey.com)\n\nCopyright (c) 1996-97 White River Software";
  Widget rc, picture;
  static Widget about_dialog = NULL;

  if(!about_dialog){
    about_dialog = XmCreateMessageDialog(AppWidgetsPtr->mainwindow, "aboutdialog", NULL, 0);
  
    /* remove uneeded children */
    XtUnmanageChild(XmMessageBoxGetChild(about_dialog, XmDIALOG_HELP_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(about_dialog, XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(about_dialog, XmDIALOG_SYMBOL_LABEL));
    XtUnmanageChild(XmMessageBoxGetChild(about_dialog, XmDIALOG_MESSAGE_LABEL));

    /* setup dialog */
    XtVaSetValues(about_dialog,
		  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		  XtVaTypedArg, XmNdialogTitle, XmRString,
		  title, strlen(title)+1,
		  NULL);

    rc = XtVaCreateManagedWidget("rc", xmRowColumnWidgetClass, about_dialog,
				 XmNnumColumns, 2,
				 XmNpacking, XmPACK_TIGHT,
				 XmNorientation, XmHORIZONTAL,
				 NULL);

    picture =  XtVaCreateManagedWidget("", 
				       xmLabelWidgetClass, rc,
				       XmNmarginWidth, 15,
				       XmNmarginHeight, 20,
				       XmNalignment, XmALIGNMENT_CENTER,
				       NULL);

    /* set label image */
    InstallLabeledPixmap(picture, about_xpm,0);

    XtVaCreateManagedWidget("info", 
			    xmLabelWidgetClass, rc,
			    XtVaTypedArg, XmNlabelString, XmRString,
			    info, strlen(info)+1,
			    XmNalignment, XmALIGNMENT_CENTER,
			    NULL);
  }
  XtManageChild(about_dialog);
}

/************************************************************************/
/* Function: PrintCallback                                              */
/* Purpose : handles printer definition & submits print job             */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void PrintCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  const char *title = "Print";               /* dialog title            */
  Widget rc;                                 /* rowcol widget           */
  static Widget print_dialog = NULL;         /* dialog widget           */

  if(!print_dialog){
    print_dialog = XmCreateMessageDialog(AppWidgetsPtr->mainwindow, "printdialog", NULL, 0);
  
    /* remove uneeded children */
    XtUnmanageChild(XmMessageBoxGetChild(print_dialog, XmDIALOG_HELP_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(print_dialog, XmDIALOG_SYMBOL_LABEL));
    XtUnmanageChild(XmMessageBoxGetChild(print_dialog, XmDIALOG_MESSAGE_LABEL));

    /* setup dialog */
    XtVaSetValues(print_dialog,
		  XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		  XtVaTypedArg, XmNdialogTitle, XmRString,
		  title, strlen(title)+1,
		  NULL);

    rc = XtVaCreateManagedWidget("rc", xmRowColumnWidgetClass, print_dialog,
				 XmNnumColumns, 2,
				 XmNpacking, XmPACK_COLUMN,
				 XmNorientation, XmVERTICAL,
				 NULL);

    XtCreateManagedWidget("Enter target printer:", xmLabelWidgetClass, rc, NULL, 0);
    AppWidgetsPtr->printer = XtVaCreateManagedWidget("printer", xmTextFieldWidgetClass,
						     rc,
						     XmNmaxLength, PRINT_NAME_SZ,
						     NULL);

    /* add callback */
    XtAddCallback(print_dialog, XmNokCallback, PrintOKCallback, NULL);
  }

  if(printer != NULL)
    XmTextSetString(AppWidgetsPtr->printer, printer);

  XtManageChild(print_dialog);
}

/************************************************************************/
/* Function: PrintOKCallback                                            */
/* Purpose : calls DB_PrintBuffer()                                     */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void PrintOKCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  strcpy(printer, doubleTrim((char*)XmTextGetString(AppWidgetsPtr->printer)));
  if(strlen(printer) == 0)
    ErrorMsg("Print", "You must specify a printer!");
  DB_PrintBuffer(buffer_curr, printer);
}

/************************************************************************/
/* Function: ExecSQLCallback                                            */
/* Purpose : calls DB_SubmitQy()                                        */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void ExecSQLCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  DB_SubmitQy();
}

/************************************************************************/
/* Function: CascadeCallback                                            */
/* Purpose : creates a menu of open buffers to select.                  */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void CascadeCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  int i;
  static Widget btn[255];
  static int list_cnt = 0;
  LLISTbuffer *curr;    
  char tmp[4];

  for(i = 0; i < list_cnt; i++)
    XtUnrealizeWidget(btn[i]);

  for(i = 0; i < list_cnt; i++)
    XtDestroyWidget(btn[i]);

  list_cnt = LLIST_Count();

  for(i = 0; i < list_cnt; i++){
    curr = LLIST_Get(i+1);
    btn[i] = XtVaCreateManagedWidget(itoa(i, tmp),
				     xmPushButtonWidgetClass,
				     AppWidgetsPtr->buffermenu,
				     XtVaTypedArg, XmNlabelString, XmRString,
				     curr->filename, strlen(curr->filename)+1,
				     NULL);
    XtAddCallback(btn[i], XmNactivateCallback, BufferCallback, NULL);
  }
}

/************************************************************************/
/* Function: BufferCallback                                             */
/* Purpose : sets the SQL window to the selected buffer                 */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void BufferCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  LLISTbuffer *curr;

  curr = LLIST_Get(atoi(XtName(w)) + 1);
  buffer_curr = DB_SetBuffer(curr);
}

/************************************************************************/
/* Function: TextModifiedCallback                                       */
/* Purpose : flags a buffer as modified if text changes                 */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void TextModifiedCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  buffer_curr->modified = 1;
}

/************************************************************************/
/* Function: DeleteBufferCallback                                       */
/* Purpose : handles user request to delete the current buffer          */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void DeleteBufferCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  /* dial title strings */
  const char *title = "Delete Buffer";
  const char *del_msg = "Buffer has been modified,\ndelete without saving changes?";
  static Widget del_dialog = NULL;

  /* if the buffer is modified prompt the user to continue delete */
  if(buffer_curr->modified == 1){
    if(!del_dialog){
      del_dialog = XmCreateQuestionDialog(AppWidgetsPtr->mainwindow, "deldialog", NULL, 0);
    
      /* remove uneeded children */
      XtUnmanageChild(XmMessageBoxGetChild(del_dialog, XmDIALOG_HELP_BUTTON));
    
      /* setup dialog */
      XtVaSetValues(del_dialog,
		    XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		    XtVaTypedArg, XmNdialogTitle, XmRString,
		    title, strlen(title)+1,
		    XtVaTypedArg, XmNmessageString, XmRString,
		    del_msg, strlen(del_msg)+1, NULL);
    
      /* add callback */
      XtAddCallback(del_dialog, XmNokCallback, DeleteBufferOKCallback, NULL);
    }
    
    XtManageChild(del_dialog);
  }
  else
    DB_DeleteBuffer(buffer_curr);
}

/************************************************************************/
/* Function: DeleteBufferOKCallback                                     */
/* Purpose : deletes the current buffer on user confirmation            */
/* Params  : standard callback stuff                                    */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void DeleteBufferOKCallback(Widget w, XtPointer clientdata, XtPointer callData)
{
  DB_DeleteBuffer(buffer_curr);
}

/************************************************************************/
/* Function: ErrorMsg                                                   */
/* Purpose : displays a basic message box with an error string          */
/* Params  : title : dialog title                                       */
/*           msg : dialog box message string                            */
/* Returns : nothing                                                    */
/* Notes   :                                                            */
/************************************************************************/

void ErrorMsg(char *title, char *msg)
{ 
  /* dialog widget */
  static Widget error_dialog = NULL;

  if(!error_dialog){
    error_dialog = XmCreateErrorDialog(AppWidgetsPtr->mainwindow, "errordialog", NULL, 0);
    
    /* remove uneeded children */
    XtUnmanageChild(XmMessageBoxGetChild(error_dialog, XmDIALOG_HELP_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(error_dialog, XmDIALOG_CANCEL_BUTTON));
 
  }
  /* setup dialog */
  XtVaSetValues(error_dialog,
		XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
		XtVaTypedArg, XmNdialogTitle, XmRString,
		title, strlen(title)+1,
		XtVaTypedArg, XmNmessageString, XmRString,
		msg, strlen(msg)+1, NULL);
 
  XtManageChild(error_dialog);
}

/************************************************************************/
/* Function: GetColSeparator                                            */
/* Purpose : returns the column separator character                     */
/* Params  :                                                            */
/* Returns : char to set                                                */
/* Notes   :                                                            */
/************************************************************************/

char GetColSeparator(void)
{
  if(XmToggleButtonGetState(AppWidgetsPtr->none))
    return '\0';
  else if(XmToggleButtonGetState(AppWidgetsPtr->tab))
    return '\t';
  else if(XmToggleButtonGetState(AppWidgetsPtr->space))
    return ' ';
  else if(XmToggleButtonGetState(AppWidgetsPtr->comma))
    return ',';
}

/************************************************************************/
/* Function: GetColSeparatorId                                          */
/* Purpose : returns the column separator character const               */
/* Params  :                                                            */
/* Returns : 0: NONE, 1: TAB, 2: SPACE, 3: COMMA                        */
/* Notes   :                                                            */
/************************************************************************/

int GetColSeparatorId(void)
{
  if(XmToggleButtonGetState(AppWidgetsPtr->none))
    return NONE;
  else if(XmToggleButtonGetState(AppWidgetsPtr->tab))
    return TAB;
  else if(XmToggleButtonGetState(AppWidgetsPtr->space))
    return SPACE;
  else if(XmToggleButtonGetState(AppWidgetsPtr->comma))
    return COMMA;
}

/************************************************************************/
/* Function: SetColSeparator                                            */
/* Purpose : handles setting column separator character                 */
/* Params  : sep_value : int represent char to set                      */
/*           0: NONE, 1: TAB, 2: SPACE, 3: COMMA                        */
/* Returns :                                                            */
/* Notes   :                                                            */
/************************************************************************/

void SetColSeparator(int sep_value)
{
  if(sep_value == NONE)
    XmToggleButtonSetState(AppWidgetsPtr->none, 1, TRUE);
  else if(sep_value == TAB)
    XmToggleButtonSetState(AppWidgetsPtr->tab, 1, TRUE);
  else if(sep_value == SPACE)
    XmToggleButtonSetState(AppWidgetsPtr->space, 1, TRUE);
  else if(sep_value == COMMA)
    XmToggleButtonSetState(AppWidgetsPtr->comma, 1, TRUE);
}
