/*********************************************************************/
/*  bibView: Administration of BibTeX-Databases                      */
/*           (Verwaltung von BibTeX-Literaturdatenbanken)            */
/*                                                                   */
/*  Module:  ctl_srch.c                                              */
/*                                                                   */
/*             Search commands                                       */
/*             - Search for specified items                          */
/*             - Display all items in a list                         */
/*                                                                   */
/*  Author:  Holger Martin,  martinh@informatik.tu-muenchen.de       */
/*           Peter M. Urban, urban@informatik.tu-muenchen.de         */
/*                                                                   */
/*  History:                                                         */
/*    12.16.91  PMU  created                                         */
/*    05.26.92       Version 1.0 released                            */
/*                                                                   */
/*  Copyright 1992 TU MUENCHEN                                       */
/*    See ./Copyright for complete rights and liability information. */
/*                                                                   */
/*********************************************************************/

#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/SmeLine.h>
#include <X11/Xaw/AsciiText.h>
#include "bibview.h"
#include "ComboBo.h"


/* imported global variables */
/* ------------------------- */
extern Widget topLevel, desktop, mainMenu;
extern PredefLists predefLst;

extern int max_fields;
extern char is_search_field[]; 


/* macros and definitions */
/* ---------------------- */

/* structure for searches */
typedef struct {
   BibPtr bp;                  /* bib to search in */
   Widget srchShell,           /* window widgets */
	  srchWin,
	  cmdBox,
	  cancel,
	  ok,
	  fldVport,
	  fldDesk,
	  fldHead,
	  fields,
	  cbAllFields,         /* widgets for search fields */
	  cbBibType,           
	  cbMainkey,
	  cbUserfield1,
	  cbUsercont1,
	  cbUserfield2,
	  cbUsercont2;
   Widget field[MAX_FIELDS];
   char *ufn1, *ufc1;
   char *ufn2, *ufc2;
} SearchWin, *SearchWinPtr;


/* local function prototypes */
/* ------------------------- */
static void srchOkCmd(Widget widget, XtPointer clientData, XtPointer callData);
static void srchQuitCmd(Widget widget, XtPointer clientData, XtPointer callData);


/* exported variables */
/* ------------------ */


/* local global variables */
/* ---------------------- */


/*********************************************************************/
/* csrSearchCmd:                                                     */
/*    Callback function for search menu entry                        */
/*********************************************************************/
void 
csrSearchCmd (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;
SearchWinPtr sw;
Position x, y;
int i;


   if ((sw = (SearchWinPtr) XtMalloc(sizeof(SearchWin))) == NULL) {
      guwError(ERR_NOMALLOC);
      return;
   }
   
   XtTranslateCoords(bp->bw->bibdesk,
		     SUBWIN_MARGIN, SUBWIN_MARGIN,
		     &x, &y);

   sw->bp = bp;
   sw->srchShell      = XtVaCreatePopupShell("srchShell", 
	                  topLevelShellWidgetClass, topLevel, 
	                  XtNx, x, XtNy, y, NULL);
   sw->srchWin        = XtVaCreateManagedWidget("srchWin", 
	                  panedWidgetClass, sw->srchShell, NULL);
   sw->cmdBox         = XtVaCreateManagedWidget("commandBox", 
	                  boxWidgetClass, sw->srchWin, NULL);
   sw->ok             = XtVaCreateManagedWidget("ok", 
	                  commandWidgetClass, sw->cmdBox, NULL);
   sw->cancel         = XtVaCreateManagedWidget("cancel", 
	                  commandWidgetClass, sw->cmdBox, NULL);
   sw->fldVport       = XtVaCreateManagedWidget("srchVport", 
	                  viewportWidgetClass, sw->srchWin, 
		          XtNallowVert, True, NULL);
   sw->fields         = XtVaCreateManagedWidget("srchFlds", 
	                  boxWidgetClass, sw->fldVport, NULL);
   sw->cbAllFields    = XtVaCreateManagedWidget("cbAllFields", 
		          comboBoxWidgetClass, sw->fields,
		          XtNrcList,  predefLst.allfields, NULL); 
   sw->cbBibType      = XtVaCreateManagedWidget("cbBibType", 
		          comboBoxWidgetClass, sw->fields,
		          XtNrcList,  predefLst.bibtype, NULL); 
   sw->cbMainkey      = XtVaCreateManagedWidget("cbMainkey", 
		          comboBoxWidgetClass, sw->fields,
		          XtNrcList,  predefLst.mainkey, NULL); 
   for (i=0; i<max_fields; i++){
      if (is_search_field[i] == '1')  
         sw->field[i] = XtVaCreateManagedWidget("cbField",
		        comboBoxWidgetClass, sw->fields,
			XtNname, glbFldToName(i),
		        XtNrcList,  predefLst.field[i], NULL); 
      }
   sw->ufn1 = "";
   sw->ufc1 = ""; 
   sw->ufn2 = "";
   sw->ufc2 = ""; 

   sw->fldDesk         = XtVaCreateManagedWidget("fldDesk", 
	                  formWidgetClass, sw->fields,
		          NULL);
   sw->fldHead         = XtVaCreateManagedWidget("fldHead", 
	                  labelWidgetClass, sw->fldDesk,
			  XtNleft, XtChainLeft,
			  XtNtop, XtChainTop, NULL);
   sw->cbUserfield1    = XtVaCreateManagedWidget("cbUserfield1", 
		          asciiTextWidgetClass, sw->fldDesk,
			  XtNeditType, XawtextEdit, 
			  XtNstring, sw->ufn1,
			  XtNfromVert, sw->fldHead,
			  XtNleft, XtChainLeft,
			  NULL);
   sw->cbUsercont1     = XtVaCreateManagedWidget("cbUsercont1", 
		          asciiTextWidgetClass, sw->fldDesk,
			  XtNeditType, XawtextEdit,
			  XtNstring, sw->ufc1,
			  XtNfromVert, sw->fldHead,
        	 	  XtNfromHoriz, sw->cbUserfield1,  
			  NULL);
   sw->cbUserfield2    = XtVaCreateManagedWidget("cbUserfield2", 
		          asciiTextWidgetClass, sw->fldDesk,
			  XtNeditType, XawtextEdit, 
			  XtNstring, sw->ufn2,
			  XtNfromVert, sw->cbUsercont1, 
			  XtNleft, XtChainLeft, NULL);
   sw->cbUsercont2     = XtVaCreateManagedWidget("cbUsercont2", 
		          asciiTextWidgetClass, sw->fldDesk,
			  XtNeditType, XawtextEdit,
			  XtNstring, sw->ufc2,
			  XtNfromVert, sw->cbUsercont1,
			  XtNfromHoriz, sw->cbUserfield2, 
			  NULL);

   XtAddCallback(sw->ok, XtNcallback, srchOkCmd, (XtPointer)sw);
   XtAddCallback(sw->cancel, XtNcallback, srchQuitCmd, (XtPointer)sw);

   XtSetSensitive(mainMenu, FALSE);
   gubSetSensitive(NULL, FALSE);
   XtPopup(sw->srchShell, XtGrabNone);
}


/*********************************************************************/
/* csrListCmd:                                                       */
/*    Callback function for list menu entry                          */
/*********************************************************************/
void 
csrListCmd (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr) clientData;
CardListNode *cl = NULL;
int status;

   /* build list */
   if ((status = dbtBuildList(bp->treeIdx, &cl, bp->sortedby)) != OK) {
      guwError(status); 
      return;
   }

   /* display list */
   if (cl == NULL) {
      guwNotice(DBT_ENOMATCH);
      return;
   }
   /* display list */
   if (gulListWinExists(bp)) {
      if ((status = gulReplaceListData(bp, cl)) != OK) {
	 guwError(status);
      }
      if (XtIsRealized(bp->lw->lstShell)) {
         XRaiseWindow(XtDisplay(bp->lw->lstShell),
		      XtWindow(bp->lw->lstShell));
      }
   }
   else {
      if ((status = gulOpenListWin(bp, cl)) != OK) {
	 guwError(status);
      }
   }
}



/*********************************************************************/
/* csrDisplayCardCmd:                                                */
/*    Callback for list entries                                      */
/*********************************************************************/
void
csrDisplayCardCmd (Widget w, XtPointer clientData, XtPointer callData)
{
XawListReturnStruct *item = (XawListReturnStruct*)callData;
BibPtr bp = (BibPtr)clientData;
CardListNode *cn = bp->lw->cardLst;
CardPtr cp;
Errcode status;
int i;

   XawListUnhighlight(bp->lw->list);

   for (i=0; i < item->list_index; i++)
      cn = cn->next;

   /* check if card displayed already */
   if ((cp = glbFindCard(bp, cn->data)) != NULL) {
      if (XtIsRealized(cp->cw->cardShell)) {
	 XRaiseWindow(XtDisplay(cp->cw->cardShell),
		      XtWindow(cp->cw->cardShell));
      }
      return;
   }


   /* create new internal data for a card window */
   if ((status = glbNewCardListEl(bp, &cp, cn->data)) != OK) {
      guwError(status);
      return;
   }

   /* open the window */
   if ((status = gucOpenCardWin(bp, cp, FALSE)) != OK)
      guwError(status);
}


/*********************************************************************/
/*  LOCAL FUNCTIONS                                                  */
/*********************************************************************/

/*********************************************************************/
/*  srchOkCmd:                                                       */
/*    Callback for ok-button in search window                        */
/*********************************************************************/
static void
srchOkCmd (Widget widget, XtPointer clientData, XtPointer callData)
{
SearchWinPtr sw = (SearchWinPtr)clientData;
BibPtr bp = sw->bp;
CardListNode *cl = NULL;
CardData *wcCard = NULL;
String s;
Errcode status;
char *ausgabe1, *ausgabe2;
UserFld *helpufield1 = NULL;
UserFld *helpufield2 = NULL;
int i;

   /* make new search card */
   if ((status = (int)dbtMakeCard(&wcCard)) != OK) {
     guwError(status);
     return;
   }

   /* retrieve data from search window */
   /* the field authorsort of a card is used (or abused) to
      indicate if a search should take place in all fields
      */
   if ((s = ComboBoxGetString(sw->cbAllFields)) != NULL)
      wcCard->authorsort = glbNewString(s);
   if ((s = ComboBoxGetString(sw->cbBibType)) != NULL)
      wcCard->cardtypestr = glbNewString(s);
   if ((s = ComboBoxGetString(sw->cbMainkey)) != NULL)
      wcCard->mainkey = glbNewString(s);
   for (i=0; i<max_fields; i++)
      if ((is_search_field[i]=='1') 
	  && ((s = ComboBoxGetString(sw->field[i])) != NULL))
         wcCard->field[i] = glbNewString(s);
   XtVaGetValues(sw->cbUserfield1, XtNstring, &ausgabe1, NULL);
   if (ausgabe1 != NULL && *ausgabe1 != '\0'){
      XtVaGetValues(sw->cbUsercont1, XtNstring, &ausgabe2, NULL);
      if (ausgabe2 != NULL && *ausgabe2 != '\0'){
         dbtMakeUserFld(&helpufield1);
         helpufield1->fldName = glbNewString(ausgabe1);
         helpufield1->fldData = glbNewString(ausgabe2);
         dbtAppendUserFld(&wcCard->ufield, helpufield1);
	 }
      }

   XtVaGetValues(sw->cbUserfield2, XtNstring, &ausgabe1, NULL);
   if (ausgabe1 != NULL && *ausgabe1 != '\0'){
      XtVaGetValues(sw->cbUsercont2, XtNstring, &ausgabe2, NULL);
      if (ausgabe2 != NULL && *ausgabe2 != '\0'){
         dbtMakeUserFld(&helpufield2);
         helpufield2->fldName = glbNewString(ausgabe1);
         helpufield2->fldData = glbNewString(ausgabe2);
         dbtAppendUserFld(&wcCard->ufield, helpufield2);
	 }
      }
   /* enable menus */
   XtSetSensitive(mainMenu, TRUE);
   gubSetSensitive(NULL, TRUE);
   XtPopdown(sw->srchShell);
   XtFree((char *)sw);

   /* build list with wildcard search */
  if ((status = dbtSearchList(bp->treeIdx, wcCard, &cl, bp->sortedby)) != OK) {
      guwError(status); 
      return;
   } 
 
   dbtDeleteCard(&wcCard);  

   if (cl == NULL) {
      guwNotice(DBT_ENOMATCH);
      return;
   }

   /* display list */
   if (gulListWinExists(bp)) {
      if ((status = gulReplaceListData(bp, cl)) != OK) {
	 guwError(status);
      }
      if (XtIsRealized(bp->lw->lstShell)) {
         XRaiseWindow(XtDisplay(bp->lw->lstShell),
		      XtWindow(bp->lw->lstShell));
      }
   }
   else {
      if ((status = gulOpenListWin(bp, cl)) != OK) {
	 guwError(status);
      }
   }
}


/*********************************************************************/
/*  srchQuitCmd:                                                     */
/*    Callback for cancel-button in search window                    */
/*********************************************************************/
static void
srchQuitCmd (Widget widget, XtPointer clientData, XtPointer callData)
{
SearchWinPtr sw = (SearchWinPtr)clientData;

   XtSetSensitive(mainMenu, TRUE);
   gubSetSensitive(NULL, TRUE);

   XtPopdown(sw->srchShell);
   XtFree((char *)sw);
}


