/*********************************************************************/
/*  bibView: Administration of BibTeX-Databases                      */
/*           (Verwaltung von BibTeX-Literaturdatenbanken)            */
/*                                                                   */
/*  Module:  gui_widg.c                                              */
/*                                                                   */
/*             GUI: Widgets and misc functions                       */
/*             - Notice/Warning/Error windows                        */
/*                                                                   */
/*  Author:  Holger Martin,  martinh@informatik.tu-muenchen.de       */
/*           Peter M. Urban, urban@informatik.tu-muenchen.de         */
/*                                                                   */
/*  History:                                                         */
/*    12.05.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/Shell.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/List.h>
#include "bibview.h"


/* imported global variables */
/* ------------------------- */
extern Widget topLevel, desktop, mainMenu;
extern Pixmap errorPixmap;
extern Pixmap warnPixmap;
extern Pixmap noticePixmap;
extern Pixmap confirmPixmap;
extern Pixmap progInfoPixmap;
extern Pixmap questPixmap;


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


/* local global variables */
/* ---------------------- */
static Widget selShell;
static BibPtr *bibptrArgv;
static String *bibselArgv;
static int    bibselArgc;


/* local function prototypes */
/* ------------------------- */
static void selectBibOK (Widget w, XtPointer ClientData, XtPointer CallData);
static void selectBibCancel (Widget w, XtPointer ClientData, XtPointer CallData);
static void closeMsgWin (Widget w, XtPointer clientData, XtPointer callData);
static void closeProgInfoWin (Widget w, XtPointer clientData, XtPointer callData);


/*********************************************************************/
/* guwSelectBib:                                                     */
/*    Display List of opened bibs to select one                      */
/*********************************************************************/
Errcode
guwSelectBib(String head, CtlFuncPtr ctlFunc)
{
static Widget selForm, selLabel, selVport, selList, selQuit;
BibPtr bp;
Position dx, dy, x, y;
int i = 0;

   /* check number of opened bibs */
   if ((bibselArgc = gubNoOfOpenBibs()) == 0)
      return(ERR_NOBIBOPEN);

   /* create argv for list */
   if ((bibselArgv = (String *)XtCalloc(bibselArgc, sizeof(String))) == NULL) 
      return(ERR_NOMALLOC);
   if ((bibptrArgv = (BibPtr *)XtCalloc(bibselArgc, sizeof(BibPtr))) == NULL) {
      XtFree((char *)bibselArgv);
      return(ERR_NOMALLOC);
   }
   bp = glbFirstBibListEl();
   i = 0;
   while (bp != NULL) {
      bibptrArgv[i] = bp;
      bibselArgv[i] = bp->filepath;
      bp = glbNextBibListEl(bp);
      i++;
   }

   /* display window */
   XtVaGetValues(desktop,
                 XtNx, &dx,
                 XtNy, &dy, NULL);
   XtTranslateCoords(desktop,
                     (Position)dx + SUBWIN_MARGIN,
                     (Position)dy + SUBWIN_MARGIN,
                     &x, &y);
   selShell = XtVaCreatePopupShell("bibselShell",
	        transientShellWidgetClass, topLevel, 
		XtNx, x, XtNy, y, NULL);
   selForm  = XtVaCreateManagedWidget("bibselWin",
	        formWidgetClass, selShell, NULL);
   selLabel = XtVaCreateManagedWidget(head,
	        labelWidgetClass, selForm,
		XtNborderWidth, 0,
	        XtNleft, XtChainLeft,
	        XtNtop, XtChainTop, NULL);
   selVport = XtVaCreateManagedWidget("bibselVport",
		viewportWidgetClass, selForm,
		XtNallowVert, True,
		XtNfromVert, selLabel, NULL);
   selList  = XtVaCreateManagedWidget("bibselLst",
		listWidgetClass, selVport,
		XtNnumberStrings, bibselArgc,
		XtNlist, bibselArgv, 
		XtNforceColumns, True,
		XtNdefaultColumns, 1, NULL);
   selQuit  = XtVaCreateManagedWidget("cancel",
	        commandWidgetClass, selForm, 
		XtNfromVert, selVport,
		XtNleft, XtChainLeft, NULL);

   XtAddCallback(selList, XtNcallback, selectBibOK, (XtPointer)ctlFunc);
   XtAddCallback(selQuit, XtNcallback, selectBibCancel, NULL);

   XtSetSensitive(mainMenu, FALSE);
   gubSetSensitive(NULL, FALSE);
   XtPopup(selShell, XtGrabNonexclusive);
   return(OK);
}


/*********************************************************************/
/* selectBibOK:                                                      */
/*    Callback for select bib list entries                           */
/*********************************************************************/
static void
selectBibOK (Widget w, XtPointer clientData, XtPointer callData)
{
XawListReturnStruct *item = (XawListReturnStruct*)callData;
CtlFuncPtr ctlFunc = (CtlFuncPtr)clientData;
BibPtr bp;

   XtPopdown(selShell);
   XSync(XtDisplay(selShell), 1);
   XtSetSensitive(mainMenu, TRUE);
   gubSetSensitive(NULL, TRUE);

   bp = bibptrArgv[item->list_index];
   XtFree((char *)bibptrArgv);
   XtFree((char *)bibselArgv);
   (ctlFunc) (bp);
}


/*********************************************************************/
/* selectBibCancel:                                                  */
/*    Callback for Cancel button of select bib shell                 */
/*********************************************************************/
static void
selectBibCancel (Widget w, XtPointer ClientData, XtPointer CallData)
{

   XtPopdown(selShell);
   XtFree((char *)bibptrArgv);
   XtFree((char *)bibselArgv);
   XtSetSensitive(mainMenu, TRUE);
   gubSetSensitive(NULL, TRUE);
}

/*********************************************************************/
/* guwConfirmClose:                                                  */
/*    Opens dialogbox for user to confirm closing without saving     */
/*********************************************************************/
void
guwConfirmClose (Position x, Position y, XtCallbackProc p1, XtCallbackProc p2)
{
static Widget conShell, conDialog, conOKButton, conQuitButton;

   conShell = XtVaCreatePopupShell("confirmQuitShell",
	        transientShellWidgetClass, topLevel, 
		XtNx, x, XtNy, y, NULL);
   conDialog = XtVaCreateManagedWidget("confirmQuitBox",
	         dialogWidgetClass, conShell, 
		 XtNicon, questPixmap, NULL);
   conOKButton = XtVaCreateManagedWidget("ok",
	           commandWidgetClass, conDialog, NULL);
   conQuitButton = XtVaCreateManagedWidget("cancel",
	           commandWidgetClass, conDialog, NULL);
   XtAddCallback(conQuitButton, XtNcallback, p1, conShell);
   XtAddCallback(conOKButton, XtNcallback, p2, conShell);

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


/*********************************************************************/
/* guwError:                                                         */
/*    Display error message in a popup shell on desktop              */
/*********************************************************************/
void
guwError (Errcode errcode)
{
static Widget errShell, errForm, errIcon, errType, errText, errOKButton;
char textLabel[20];
Window rw, cw;
int xw, yw;
int x, y;
unsigned int key_buttons;

   XQueryPointer(XtDisplay(topLevel), 
		 DefaultRootWindow(XtDisplay(topLevel)),
		 &rw, &cw, &x, &y, &xw, &yw, &key_buttons);
		 
   errShell = XtVaCreatePopupShell("errorShell",
	        transientShellWidgetClass, topLevel, 
		XtNx, x, XtNy, y, NULL);
   errForm = XtVaCreateManagedWidget("errorWin",
	       formWidgetClass, errShell, NULL);
   errIcon = XtVaCreateManagedWidget("errorIcon",
	       labelWidgetClass, errForm, 
	       XtNborderWidth, 0,
	       XtNtop, XtChainTop,
	       XtNleft, XtChainLeft,
	       XtNbitmap, errorPixmap, NULL);
   errType = XtVaCreateManagedWidget("type",
	       labelWidgetClass, errForm, 
	       XtNjustify, XtJustifyLeft,
	       XtNborderWidth, 0,
	       XtNtop, XtChainTop,
	       XtNfromHoriz, errIcon, NULL);
   sprintf(textLabel, "msgText%d", abs((int)errcode));
   errText = XtVaCreateManagedWidget(textLabel,
	       labelWidgetClass, errForm, 
	       XtNjustify, XtJustifyLeft,
	       XtNborderWidth, 0,
	       XtNfromVert, errType,
	       XtNfromHoriz, errIcon, NULL);
   errOKButton = XtVaCreateManagedWidget("ok",
	           commandWidgetClass, errForm, 
		   XtNfromVert, errText,
		   XtNbottom, XtChainBottom, 
		   XtNfromHoriz, errIcon, NULL);

   XtAddCallback(errOKButton, XtNcallback, closeMsgWin, errShell);

   XtSetSensitive(mainMenu, FALSE);
   gubSetSensitive(NULL, FALSE);
   if (cotBeepOnError())
      XBell(XtDisplay(topLevel), 100);
   XtPopup(errShell, XtGrabNonexclusive);
}


/*********************************************************************/
/* guwWarning:                                                       */
/*    Display warning message in a popup shell on desktop            */
/*********************************************************************/
void
guwWarning (Errcode errcode)
{
static Widget warnShell, warnForm, warnIcon, 
	      warnType, warnText, warnOKButton;
char textLabel[20],
     warnLabel[120];
Window rw, cw;
int xw, yw;
int x, y;
unsigned int key_buttons;

   XQueryPointer(XtDisplay(topLevel), 
		 DefaultRootWindow(XtDisplay(topLevel)),
		 &rw, &cw, &x, &y, &xw, &yw, &key_buttons);
		 
   warnShell    = XtVaCreatePopupShell("warnShell",
	            transientShellWidgetClass, topLevel, 
		    XtNx, x, XtNy, y, NULL);
   warnForm     = XtVaCreateManagedWidget("warnWin",
	            formWidgetClass, warnShell, NULL);
   warnIcon     = XtVaCreateManagedWidget("warnIcon",
	            labelWidgetClass, warnForm, 
	            XtNborderWidth, 0,
	            XtNtop, XtChainTop,
	            XtNleft, XtChainLeft,
	            XtNbitmap, warnPixmap, NULL);
   warnType     = XtVaCreateManagedWidget("type",
	            labelWidgetClass, warnForm, 
		    XtNjustify, XtJustifyLeft,
	            XtNborderWidth, 0,
	            XtNtop, XtChainTop,
	            XtNfromHoriz, warnIcon, NULL);
   sprintf(textLabel, "msgText%d", abs((int)errcode));
   if (errcode >= 200){
   #ifdef GERMAN
      sprintf(warnLabel, "Karte unvollstaendig: kein %s", 
			 glbFldToName(errcode-200));
   #else
      sprintf(warnLabel, "Card incomplete: no %s", glbFldToName(errcode-200));
   #endif
      warnText     = XtVaCreateManagedWidget(textLabel,
  	               labelWidgetClass, warnForm, 
		       XtNjustify, XtJustifyLeft,
	               XtNborderWidth, 0,
	               XtNfromVert, warnType,
	               XtNlabel, warnLabel,
	               XtNfromHoriz, warnIcon, NULL);
      }
   else 
   warnText     = XtVaCreateManagedWidget(textLabel,
	            labelWidgetClass, warnForm, 
		    XtNjustify, XtJustifyLeft,
	            XtNborderWidth, 0,
	            XtNfromVert, warnType,
	            XtNfromHoriz, warnIcon, NULL);
   warnOKButton = XtVaCreateManagedWidget("ok",
	            commandWidgetClass, warnForm, 
		    XtNfromVert, warnText,
		    XtNbottom, XtChainBottom, 
		    XtNfromHoriz, warnIcon, NULL);

   XtAddCallback(warnOKButton, XtNcallback, closeMsgWin, warnShell);

   XtSetSensitive(mainMenu, FALSE);
   gubSetSensitive(NULL, FALSE);
   if (cotBeepOnError())
      XBell(XtDisplay(topLevel), 100);
   XtPopup(warnShell, XtGrabNonexclusive);
}


/*********************************************************************/
/* guwNotice:                                                        */
/*    Display notice message in a popup shell on desktop             */
/*********************************************************************/
void
guwNotice (Errcode errcode)
{
static Widget noticeShell, noticeForm, noticeIcon, noticeType, 
	      noticeText, noticeOKButton;
char textLabel[20];
Window rw, cw;
int xw, yw;
int x, y;
unsigned int key_buttons;

   XQueryPointer(XtDisplay(topLevel), 
		 DefaultRootWindow(XtDisplay(topLevel)),
		 &rw, &cw, &x, &y, &xw, &yw, &key_buttons);
   
   noticeShell    = XtVaCreatePopupShell("noticeShell",
	              transientShellWidgetClass, topLevel, 
		      XtNx, x, XtNy, y, NULL);
   noticeForm     = XtVaCreateManagedWidget("noticeWin",
	              formWidgetClass, noticeShell, NULL);
   noticeIcon     = XtVaCreateManagedWidget("noticeIcon",
	              labelWidgetClass, noticeForm, 
	              XtNborderWidth, 0,
	              XtNtop, XtChainTop,
	              XtNleft, XtChainLeft,
	              XtNbitmap, noticePixmap, NULL);
   noticeType     = XtVaCreateManagedWidget("type",
	              labelWidgetClass, noticeForm, 
	              XtNborderWidth, 0,
		      XtNjustify, XtJustifyLeft,
	              XtNtop, XtChainTop,
	              XtNfromHoriz, noticeIcon, NULL);
   sprintf(textLabel, "msgText%d", abs((int)errcode));
   noticeText     = XtVaCreateManagedWidget(textLabel,
	              labelWidgetClass, noticeForm, 
	              XtNborderWidth, 0,
		      XtNjustify, XtJustifyLeft,
	              XtNfromVert, noticeType,
	              XtNfromHoriz, noticeIcon, NULL);
   noticeOKButton = XtVaCreateManagedWidget("ok",
	              commandWidgetClass, noticeForm, 
		      XtNfromVert, noticeText,
		      XtNbottom, XtChainBottom, 
		      XtNfromHoriz, noticeIcon, NULL);

   XtAddCallback(noticeOKButton, XtNcallback, closeMsgWin, noticeShell);

   XtSetSensitive(mainMenu, FALSE);
   gubSetSensitive(NULL, FALSE);
   if (cotBeepOnError())
      XBell(XtDisplay(topLevel), 100);
   XtPopup(noticeShell, XtGrabNonexclusive);
}


/*********************************************************************/
/* CloseMsgWin:                                                      */
/*    Callback function for OK button in message windows             */
/*********************************************************************/
static void
closeMsgWin (Widget w, XtPointer clientData, XtPointer callData)
{
Widget shell = (Widget)clientData;

   XtSetSensitive(mainMenu, TRUE);
   gubSetSensitive(NULL, TRUE);
   XtPopdown(shell);
}


/*********************************************************************/
/* guwProgInfo:                                                      */
/*    Display programm information                                   */
/*********************************************************************/
void
guwProgInfo (Widget w, XtPointer clientData, XtPointer callData)
{
static Widget piShell, piIcon;
Position dx, dy, x, y;

   XtVaGetValues(desktop,
                 XtNx, &dx,
                 XtNy, &dy, NULL);
   XtTranslateCoords(desktop,
                     (Position)dx + SUBWIN_MARGIN,
                     (Position)dy + SUBWIN_MARGIN,
                     &x, &y);
   piShell  = XtVaCreatePopupShell("progInfoShell",
	        transientShellWidgetClass, topLevel, 
		XtNx, x, XtNy, y, NULL);
   piIcon  = XtVaCreateManagedWidget("progInfo",
	       commandWidgetClass, piShell, 
	       XtNbitmap, progInfoPixmap, NULL);

   XtAddCallback(piIcon, XtNcallback, closeProgInfoWin, piShell);
   XtPopup(piShell, XtGrabNonexclusive);
}


/*********************************************************************/
/* CloseProgInfoWin:                                                 */
/*    Callback function for OK button in message windows             */
/*********************************************************************/
static void
closeProgInfoWin (Widget w, XtPointer clientData, XtPointer callData)
{
Widget shell = (Widget)clientData;

   XtPopdown(shell);
}


