/*********************************************************************/
/*  bibView: Administration of BibTeX-Databases                      */
/*           (Verwaltung von BibTeX-Literaturdatenbanken)            */
/*                                                                   */
/*  Module:  ctl_serv.c                                              */
/*                                                                   */
/*             Services Control                                      */
/*             - Menu function Check                                 */
/*             - Menu function Collate                               */
/*                                                                   */
/*  Author:  Holger Martin,  martinh@informatik.tu-muenchen.de       */
/*           Peter M. Urban, urban@informatik.tu-muenchen.de         */
/*                                                                   */
/*  History:                                                         */
/*    26.02.92  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/Shell.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/Box.h>
#include "FileNom.h"
#include "bibview.h"


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


/* imported global variables */
/* ------------------------- */
extern XtAppContext app_context;
extern Widget topLevel, mainMenu, desktop;
extern Pixmap questPixmap;


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


/* local function prototypes */
/* ------------------------- */
static Errcode cseCollateSrc (BibPtr bp);
static Errcode cseCollateDest (BibPtr bp);
static void cancelCheck (Widget w, XtPointer clientData, XtPointer callData);
static Errcode checkBibFile (BibPtr bp);
static void CancelLoad (Widget w, XtPointer clientData, XtPointer callData);
static void confirmMacroQuit (BibPtr bp);
static void macroQuitOkCmd (Widget w, XtPointer clientData, XtPointer callData);
static void saveMacroQuitCmd (Widget w, XtPointer clientData, XtPointer callData);
static void LoadCfgFile (Widget w, XtPointer clientData, XtPointer callData);


/* local global variables */
/* ---------------------- */
static BibPtr gbp = NULL;
static chkOkMsg = True;


/*********************************************************************/
/* COLLATE (MERGE) BIBLIOGRAPHY FUNCTIONS                            */
/*********************************************************************/

/*********************************************************************/
/* cseCollateBibCmd:                                                 */
/*    Callback function for command collate in service menu          */
/*********************************************************************/
void
cseCollateBibCmd (Widget w, XtPointer clientData, XtPointer callData)
{
Errcode status;

   if ((status = guwSelectBib("collSrcHead", cseCollateSrc)) != OK)
      guwWarning(status);
}


/*********************************************************************/
/* cseCollateSrc:                                                    */
/*    Collate bibs with source bp                                    */
/*********************************************************************/
static Errcode
cseCollateSrc (BibPtr bp)
{
Errcode status;

   gbp = bp;
   if ((status = guwSelectBib("collDestHead", cseCollateDest)) != OK)
      guwWarning(status);
   return(OK);
}


/*********************************************************************/
/* cseCollateDest:                                                   */
/*    Collate bibs with dest in bp, src in gbp                       */
/*********************************************************************/
static Errcode
cseCollateDest (BibPtr bp)
{
int status;

   if ((status = cseCollateBibs(gbp, bp)) != OK)
      guwError(status);

   return(OK);
}


/*********************************************************************/
/* cseCollateBibs:                                                   */
/*    Collate two bibs, src is inserted to dest                      */
/*********************************************************************/
Errcode
cseCollateBibs (BibPtr sbp, BibPtr dbp)
{
CardListNode *clp, *cl = NULL;
CardListNode *dclp = NULL;
CardListNode *dcl = NULL;
Errcode status;

   /* check bibs: can't be equal */
   if (sbp->treeIdx == dbp->treeIdx) {
      return(ERR_COLL_SAME_BIB);
   }

   /* make list of all cards in src bib */
   if ((status = dbtBuildList(sbp->treeIdx, &cl, sbp->sortedby)) != DBT_OK) {
      return(status);
   }
   
   if (gulListWinExists(dbp))
      dclp = dcl = dbp->lw->cardLst;

   /* add all cards from list to dest bib */
   for (clp = cl; clp != NULL; clp = clp->next) {
      if ((status = dbtInsert(dbp, clp->data)) != DBT_OK)
	 guwError(status);
      if (dclp != NULL){
         if ((status = dbtCardListInsert(&dcl, clp->data, dbp->sortedby)) != DBT_OK){
	    guwError(status);
            return(status);
            }
         }
   }

   if (gulListWinExists(dbp)) {
      dbp->lw->cardLst = NULL;
      if  ((status = gulReplaceListData(dbp, dcl)) != OK) {
	 guwError(status);
	 gulCloseListWin(dbp);
      }
   }

   /* !!! HOLGER: Liste wegschmeissen */
   dbtCardListDelete(&cl);
   dbp->changed = TRUE;
   return(OK);
}



/*********************************************************************/
/* CHECK BIBLIOGRAPHY FUNCTIONS                                      */
/*********************************************************************/

/*********************************************************************/
/* cseCheckBibCmd:                                                   */
/*    Callback function for command check in services menu           */
/*********************************************************************/
void
cseCheckBibCmd (Widget w, XtPointer clientData, XtPointer callData)
{
Errcode status;

   if ((status = guwSelectBib("checkHead", checkBibFile)) != OK)
      guwWarning(status);
}


/*********************************************************************/
/* cseCheckBib:                                                      */
/*    Checks opened bibliography for inconsistencies                 */
/*********************************************************************/
Errcode
cseCheckBib (BibPtr bp, Boolean sayOkMsg)
{
Errcode status;

   chkOkMsg = sayOkMsg;
   if ((status = checkBibFile(bp)) != OK)
      guwWarning(status);
   chkOkMsg = True;

   return(status);
}


/*********************************************************************/
/* checkBibFile:                                                     */
/*    Callback function for OK button in file select box             */
/*********************************************************************/
static Errcode
checkBibFile (BibPtr bp)
{
CardListNode *cl = NULL;
Errcode status;

   /* search for illegal cards */
   if ((status = dbtCheckAllCards(bp->treeIdx, &cl)) != DBT_OK) {
      /* HOLGER: Liste wegschmeissen */
      return(status);
   }

   /* check for illegal cards found */
   if (cl == NULL) {
      if (chkOkMsg) guwNotice(ERR_NO_ILLEGAL_CARDS);
      return(OK);
   }
   else {
      if (gulListWinExists(bp)){ 
         if ((status = gulReplaceListData(bp, cl)) != OK) {
            return(status);
         }
         if (XtIsRealized(bp->lw->lstShell)) {
            XRaiseWindow(XtDisplay(bp->lw->lstShell),
                         XtWindow(bp->lw->lstShell));
         }
      }
      else if ((status = gulOpenListWin(bp, cl)) != OK) {
	 return(status);
      }
      guwWarning(ERR_ILLEGAL_CARDS);
   }

   return(OK);
}



/*********************************************************************/
/* EDIT MACRO COMMAND FUNCTIONS                                      */
/*********************************************************************/

/*********************************************************************/
/* cseEditMacrosCmd:                                                 */
/*    Callback function for command macros in services menu          */
/*********************************************************************/
void
cseEditMacrosCmd (Widget w, XtPointer clientData, XtPointer callData)
{
Errcode status;

   if ((status = guwSelectBib("macroHead", cseEditMacros)) != OK)
      guwWarning(status);
}


/*********************************************************************/
/* cseMacrosCmd:                                                     */
/*    Callback function for command macros in bib window             */
/*********************************************************************/
void
cseMacrosCmd (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;
Errcode status;

   if ((status = cseEditMacros(bp)) != OK)
      guwWarning(status);
}


/*********************************************************************/
/* cseEditMacros:                                                    */
/*    Open shell to edit temp file containing macros                 */
/*********************************************************************/
Errcode
cseEditMacros (BibPtr bp)
{
Errcode status;
int fh;

   /* window opened already? */
   if (gueMacroWinExists(bp)) {
      if (XtIsRealized(bp->mw->macShell)) {
	 XRaiseWindow(XtDisplay(bp->mw->macShell),
		      XtWindow(bp->mw->macShell));
      }
      return(OK);
   }

   /* open new temp file? */
   if (bp->macrofile == NULL) {
#ifdef NO_TEMPNAM
      bp->macrofile = (char *)tmpnam(NULL);
#else
      bp->macrofile = (char *)tempnam(NULL, NULL);
#endif
      if (bp->macrofile == NULL)
	 return(ERR_NOMALLOC);
      if ((fh = creat(bp->macrofile, 0700)) == -1)
	 return(ERR_NO_OPEN_TMP);
      close(fh);
   }

   /* open macro window, widget takes care of file handling */
   if ((status = gueOpenMacroWin(bp)) != OK)
      return(status);

   return(OK);
}


/*********************************************************************/
/* cseSetMacroChangeFlag:                                            */
/*    Callback of text widget, sets flags when buffer changes        */
/*********************************************************************/
void
cseSetMacroChangeFlag (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;

   bp->mw->changed = TRUE;
}


/*********************************************************************/
/* cseSaveMacrosCmd:                                                 */
/*    Callback for save  command in macro window                     */
/*********************************************************************/
void
cseSaveMacrosCmd (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;
Errcode status;

   if ((status = gueSaveMacrosToFile(bp)) != OK) {
      guwError(status);
      return;
   }
   bp->mw->changed = FALSE;
}


/*********************************************************************/
/* cseQuitMacrosCmd:                                                 */
/*    Callback for close command in macro window                     */
/*********************************************************************/
void
cseQuitMacrosCmd (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;
Errcode status;

   /* macros changed, confirm close w/o saving */
   if (bp->mw->changed) {
      confirmMacroQuit(bp);
      return;
   }

   if ((status = gueCloseMacroWin(bp)) != OK)
      guwError(status);
}


/*********************************************************************/
/* confirmMacroQuit:                                                 */
/*    Opens dialogbox for user to confirm closing without saving     */
/*********************************************************************/
static void
confirmMacroQuit (BibPtr bp)
{
Position dx, dy, x, y;

   XtVaGetValues(desktop,
                 XtNx, &dx,
                 XtNy, &dy, NULL);
   XtTranslateCoords(desktop,
                     (Position)dx + SUBWIN_MARGIN,
                     (Position)dy + SUBWIN_MARGIN,
                     &x, &y);
   guwConfirmClose (x,y,saveMacroQuitCmd,macroQuitOkCmd); 
   gbp = bp;
}


/*********************************************************************/
/* saveMacroQuitCmd:                                                 */
/*    Callback function for SAVE & QUIT butoon in confirm box        */
/*********************************************************************/
static void
saveMacroQuitCmd (Widget w, XtPointer clientData, XtPointer callData)
{
Widget shell = (Widget)clientData;

   /* remove confirm shell */
   XtPopdown(shell);

   /* save and close macro editing window */
/*   if ((status = gueSaveMacrosToFile(gbp)) != OK)
      guwError(status);
   if ((status = gueCloseMacroWin(gbp)) != OK)
      guwError(status);
   gbp = NULL; */

   /* enable menus */
   XtSetSensitive(mainMenu, TRUE);
   gubSetSensitive(NULL, TRUE);
}


/*********************************************************************/
/* macroQuitOkCmd:                                                   */
/*    Callback function for OK button in confirm box                 */
/*********************************************************************/
static void
macroQuitOkCmd (Widget w, XtPointer clientData, XtPointer callData)
{
Widget shell = (Widget)clientData;
Errcode status;

   /* remove confirm shell */
   XtPopdown(shell);

   /* close macro editing window */
   if ((status = gueCloseMacroWin(gbp)) != OK)
      guwError(status);
   gbp = NULL;

   /* enable menus */
   XtSetSensitive(mainMenu, TRUE);
   gubSetSensitive(NULL, TRUE);
}



/*********************************************************************/
/* LOAD C0NFIGURATION FUNCTIONS                                      */
/*********************************************************************/

/*********************************************************************/
/* cseLoadConfigCmd:                                                 */
/*    Callback function for menu load config in services menu        */
/*********************************************************************/
void
cseLoadConfigCmd (Widget w, XtPointer clientData, XtPointer callData)
{
static Widget fsbShell, fsbBox, fsbDialog;
Position dx, dy, x, y;

   XtVaGetValues(desktop,
                 XtNx, &dx,
                 XtNy, &dy, NULL);
   XtTranslateCoords(desktop,
                     (Position)dx + SUBWIN_MARGIN,
                     (Position)dy + SUBWIN_MARGIN,
                     &x, &y);
   fsbShell  = XtVaCreatePopupShell("fileSelectBoxShell",
	         topLevelShellWidgetClass, desktop, 
	 	 XtNx, x, XtNy, y, NULL);
   fsbBox    = XtVaCreateManagedWidget("fileSelectBox",
                 boxWidgetClass, fsbShell, NULL);
               XtVaCreateManagedWidget("configLoadHead",
                 labelWidgetClass, fsbBox,
                 XtNborderWidth, 0, NULL);
   fsbDialog = XtVaCreateManagedWidget("loadFileBoxShell",
                fileNominatorWidgetClass, fsbBox,
                XtNborderWidth, 0, NULL);

   XtAddCallback(fsbDialog, XtNcancelCallback, CancelLoad, fsbShell);
   XtAddCallback(fsbDialog, XtNselectCallback, LoadCfgFile, fsbDialog);

   XtSetSensitive(mainMenu, FALSE);
   gubSetSensitive(NULL, FALSE);
   XtPopup(fsbShell, XtGrabNonexclusive);
}


/*********************************************************************/
/* CancelLoad:                                                       */
/*    Callback function for CANCEL button in file select box         */
/*********************************************************************/
static void
CancelLoad (Widget w, XtPointer clientData, XtPointer callData)
{
Widget dialog = (Widget)clientData;

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

}


/*********************************************************************/
/* LoadConfigFile:                                                   */
/*    Callback function for OK button in file select box             */
/*********************************************************************/
static void
LoadCfgFile (Widget w, XtPointer clientData, XtPointer callData)
{
Widget dialog = (Widget)clientData;
String filepath;
int status;

   /* get and keep filename */
   filepath = (String)FileNominatorGetFullFileName(dialog);
   if (filepath == NULL)
      {XtSetSensitive(mainMenu, TRUE);
       gubSetSensitive(NULL, TRUE);
       XtPopdown(XtParent(XtParent(dialog)));
       guwError(NO_VALID_FILENAME);
       }

   /* remove file select box */
   XtSetSensitive(mainMenu, TRUE);
   gubSetSensitive(NULL, TRUE);
   XtPopdown(XtParent(XtParent(dialog)));

   /* read config file */
   if ((status = rcfReadCfgFile(filepath)) != OK)
      guwError(status);

}



