/*********************************************************************/
/*  bibView: Administration of BibTeX-Databases                      */
/*           (Verwaltung von BibTeX-Literaturdatenbanken)            */
/*                                                                   */
/*  Module:  gui_bibl.c                                              */
/*                                                                   */
/*             GUI: Bibliography Window                              */
/*             - Menu functions New                                  */
/*                                                                   */
/*  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/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/SmeLine.h>
#include "bibview.h"


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

/* structure for pulldown menu items */
typedef struct {
   String name;		/* Xt name (instance) of item */
   XtCallbackProc cb;	/* associated callback function */
} MenuEntry;


/* local function prototypes */
/* ------------------------- */
static Errcode calcNextBibWinPos (int n, Position *x, Position *y);
static Errcode calcNextBibIconPos (int curIcon, Position *x, Position *y);
static void createMenu (String menuName, MenuEntry item[], Widget parent, Widget *menu, BibPtr bp);

/* external global variables */
/* ------------------------- */
extern Widget topLevel, desktop;
extern Pixmap bvIconPixmap;


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


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


static MenuEntry windowEntry[] = {
   { "line1", NULL },
   { "item1",  gucCascadeCmd },
   { NULL, NULL }
};

static int noOfBibWins = 0;
static int nextBibPos = 0;



/*********************************************************************/
/* gubOpenBibWin:                                                    */
/*    Creates an instance of a bibliography window                   */
/*********************************************************************/
int
gubOpenBibWin (BibPtr bp)
{
BibWinPtr bw;

   /* allocate memory for new element of window list */
   if ((bw = (BibWinPtr) XtMalloc(sizeof(BibWin))) == NULL) {
      /* error-handling is done in control modules */
      return(ERR_NOMALLOC);
   }

   /* allocate memory for label of new shell */
   if ((bw->shellName = 
      (String) XtCalloc(strlen(PROGNAME)+strlen(bp->filename)+4, 
		      sizeof(char))) == NULL) {
      return(ERR_NOMALLOC);
   }

   bp->bw = bw;
   sprintf(bw->shellName, "%s: %s", PROGNAME, bp->filename);

   /* create popup shell for new file */
   bw->bibShell = XtVaCreatePopupShell("bibShell",
		  topLevelShellWidgetClass, desktop, 
/*  		  XtNtransient, TRUE,
		  XtNwindowGroup, XtWindow(topLevel), */
		  XtNtitle, bw->shellName, 
		  XtNiconPixmap, bvIconPixmap,
		  XtNiconName, bp->filename, NULL);
   bw->bibWin = XtVaCreateManagedWidget("bibWin",
		  panedWidgetClass, bw->bibShell, NULL);

   /* create command buttons */
   bw->cmdBox = XtVaCreateManagedWidget("commandBox", 
		  boxWidgetClass, bw->bibWin, NULL);
   bw->new = XtVaCreateManagedWidget("new", 
	       menuButtonWidgetClass, bw->cmdBox, NULL);  
   bw->search = XtVaCreateManagedWidget("search", 
	          commandWidgetClass, bw->cmdBox, NULL);
   bw->list = XtVaCreateManagedWidget("list", 
	        commandWidgetClass, bw->cmdBox, NULL);
   bw->macro = XtVaCreateManagedWidget("macro", 
	        commandWidgetClass, bw->cmdBox, NULL);
   bw->print = XtVaCreateManagedWidget("print", 
	         commandWidgetClass, bw->cmdBox, NULL);
   bw->save = XtVaCreateManagedWidget("save", 
	        commandWidgetClass, bw->cmdBox, NULL);
   bw->close = XtVaCreateManagedWidget("close", 
	         commandWidgetClass, bw->cmdBox, NULL);
   bw->window = XtVaCreateManagedWidget("window", 
	         menuButtonWidgetClass, bw->cmdBox, NULL); 

   /* make pulldownmenus for command boxes */
   glbCreateTypeMenu("newMenu", bw->new, 
      &bw->newMenu, ccdNewCardCmd, bp);
   createMenu("windowMenu", windowEntry, bw->window, &bw->windowMenu, bp); 

   XtAddCallback(bw->search, XtNcallback, csrSearchCmd, (XtPointer)bp);
   XtAddCallback(bw->print, XtNcallback, cprPrintCmd, (XtPointer)bp);
   XtAddCallback(bw->list, XtNcallback, csrListCmd, (XtPointer)bp);
   XtAddCallback(bw->macro, XtNcallback, cseMacrosCmd, (XtPointer)bp);
   XtAddCallback(bw->save, XtNcallback, csaSaveCmd, (XtPointer)bp);
   XtAddCallback(bw->close, XtNcallback, csaCloseCmd, (XtPointer)bp);

   /* create bibliography window desktop */
   bw->bibdesk = XtVaCreateManagedWidget("bibdesk",
                   formWidgetClass, bw->bibWin, NULL); 

   /* Position window near main desktop */
   noOfBibWins++;
   calcNextBibWinPos(nextBibPos, &bw->winX, &bw->winY);
   XtVaSetValues(bw->bibShell,
		 XtNx, bw->winX,
		 XtNy, bw->winY, NULL);
   nextBibPos++;

   /* if option on, set icon position on desktop */
   if (cotIconizeOnDesktop()) {
      calcNextBibIconPos(noOfBibWins, &bw->iconX, &bw->iconY);
      XtVaSetValues(bw->bibShell,
		    XtNiconX, bw->iconX,
		    XtNiconY, bw->iconY, NULL);
   }

   XtPopup(bw->bibShell, XtGrabNone);
   return(OK);
}


/*********************************************************************/
/* gubNoOfOpenBibs:                                                  */
/*    Returns number of opened bibliogarohies                        */
/*********************************************************************/
int
gubNoOfOpenBibs (void)
{
   return(noOfBibWins);
}


/*********************************************************************/
/* gubCloseBibWinCmd:                                                */
/*    Callback for close bibwin command                              */
/*********************************************************************/
void
gubCloseBibWinCmd (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;
Errcode status;

   if ((status = gubCloseBibWin(bp)) != OK) {
      guwError(status);
   }
}


/*********************************************************************/
/* gubCloseBibWin:                                                   */
/*    Close a bibliography window                                    */
/*********************************************************************/
Errcode
gubCloseBibWin (BibPtr bp)
{
CardPtr cp;
Errcode status;

   /* close all opened card windows */
   while ((cp = glbFirstCardListEl(bp)) != NULL) {
      if ((status = gucCloseCardWin(cp)) != OK) {
         guwError(status);
      }
   }

   /* close possibly opened list window */
   if (bp->lw != NULL) {
      if ((status = gulCloseListWin(bp)) != OK) {
         guwError(status);
      }
   }

   /* close possibly opened macro window */
   if (bp->mw != NULL) {
      if ((status = gueCloseMacroWin(bp)) != OK) {
         guwError(status);
      }
   }

   /* close possibly opened error window */
   if (bp->ew != NULL) {
      if ((status = gueCloseBibErrWin(bp)) != OK) {
         guwError(status);
      }
   }

   /* close this bibliography window */
   XtPopdown(bp->bw->bibShell); 
   noOfBibWins--;
   nextBibPos --;
   XtFree((char *)bp->bw->shellName);
   XtFree((char *)bp->bw);
   glbDelBibListEl(bp);
   if (glbFirstBibListEl() == NULL)
      nextBibPos = 0;

   return(OK);
}


/*********************************************************************/
/* gubCascadeCmd:                                                    */
/*    Callback for Cascade-Function                                  */
/*********************************************************************/
void
gubCascadeCmd (Widget w, XtPointer clientData, XtPointer callData)
{
Errcode status;

   if ((status = gubCascade()) != OK) {
      guwWarning(status);
   }
}


/*********************************************************************/
/* gubCascade:                                                       */
/*    Layout the bibliography windows                                */
/*********************************************************************/
Errcode
gubCascade (void)
{
   gubSetWindowCoords(FALSE);
   if (cotIconizeOnDesktop())
      gubSetIconCoords(FALSE);
   return(OK);
}


/*********************************************************************/
/* gubSetWindowCoords:                                               */
/*    Set positions of bibliography windows                          */
/*********************************************************************/
Errcode
gubSetWindowCoords (Boolean calcOnly)
{
BibPtr bp;
Errcode status;
int i;
 
   if ((bp = glbFirstBibListEl()) == NULL)
      return(OK);
   for (i = 0; i < noOfBibWins; i++) {
      calcNextBibWinPos(i, &bp->bw->winX, &bp->bw->winY);
      if (!calcOnly) {
         XtVaSetValues(bp->bw->bibShell,
                       XtNx, bp->bw->winX,
		       XtNy, bp->bw->winY, NULL);
	 if (XtIsRealized(bp->bw->bibShell)) {
            XRaiseWindow(XtDisplay(bp->bw->bibShell),
		         XtWindow(bp->bw->bibShell));
	 }
      }
      bp = glbNextBibListEl(bp);
   } /* endfor */

   bp = glbFirstBibListEl();
   for (i = 0; i < noOfBibWins; i++) {
      if ((status = gucCascade(bp)) != OK)
         guwWarning(status);
      if ((status = gueCascade(bp)) != OK)
         guwWarning(status);
      if ((status = gulCascade(bp)) != OK)
         guwWarning(status);
      bp = glbNextBibListEl(bp);
   } /* endfor */

   return(OK);
}


/*********************************************************************/
/* gubSetIconCoords:                                                 */
/*    Set positions of bibliography windows icons                    */
/*********************************************************************/
Errcode
gubSetIconCoords (Boolean calcOnly)
{
BibPtr bp;
int curIcon = 0;
 
   if ((bp = glbFirstBibListEl()) != NULL) {
      calcNextBibIconPos(curIcon, &bp->bw->iconX, &bp->bw->iconY);
      if (!calcOnly) {
         XtVaSetValues(bp->bw->bibShell,
		       XtNiconX, bp->bw->iconX,
		       XtNiconY, bp->bw->iconY, NULL);
      }

      while ((bp = glbNextBibListEl(bp)) != NULL) {
         curIcon++;
         calcNextBibIconPos(curIcon, &bp->bw->iconX, &bp->bw->iconY);
         if (!calcOnly) {
            XtVaSetValues(bp->bw->bibShell,
		          XtNiconX, bp->bw->iconX,
		          XtNiconY, bp->bw->iconY, NULL);
         }
      }  /* endwhile */
   } /* endif */

   return(OK);
}


/*********************************************************************/
/* gubUnsetIconCoords:                                               */
/*    Set positions of bibliography windows icons                    */
/*********************************************************************/
Errcode
gubUnsetIconCoords (Boolean calcOnly)
{
BibPtr bp;
 
   if ((bp = glbFirstBibListEl()) != NULL) {
      bp->bw->iconX = bp->bw->iconY = -1;
      if (!calcOnly) {
         XtVaSetValues(bp->bw->bibShell,
		       XtNiconX, bp->bw->iconX,
		       XtNiconY, bp->bw->iconY, NULL);
      }

      while ((bp = glbNextBibListEl(bp)) != NULL) {
         bp->bw->iconX = bp->bw->iconY = -1;
         if (!calcOnly) {
            XtVaSetValues(bp->bw->bibShell,
		          XtNiconX, bp->bw->iconX,
		          XtNiconY, bp->bw->iconY, NULL);
         }
      }  /* endwhile */
   } /* endif */

   return(OK);
}


/*********************************************************************/
/* gubSetSensitive:                                                  */
/*    Set the sensitivity state of one or all bibl windows           */
/*********************************************************************/
void
gubSetSensitive (BibPtr bib, Boolean sensitive)
{
CardPtr card;
BibPtr hbib;

   if (bib == NULL) { /* set all bib windows and subs to sensitive? */
      hbib = glbFirstBibListEl();
      while (hbib != NULL) {
	 if (hbib->bw != NULL) {
	    XtSetSensitive(hbib->bw->bibWin, sensitive);
	    if (hbib->lw != NULL) /* handle list window */
	       XtSetSensitive(hbib->lw->lstWin, sensitive);
	    card = glbFirstCardListEl(hbib); /* handle all cards */
	    while (card != NULL) {
	       if (card->cw != NULL)
		  XtSetSensitive(card->cw->cardWin, sensitive);
	       if (card->aw != NULL)
		  XtSetSensitive(card->aw->annoteWin, sensitive);
	       card = glbNextCardListEl(hbib, card);
	    }
	 }
	 hbib = glbNextBibListEl(hbib);
      }
   }
   else { /* set only one bib win and subs to sensitive */
      if (glbIsBibListEl(bib) && bib->bw != NULL) {
         XtSetSensitive(bib->bw->bibWin, sensitive);
	 if (bib->lw != NULL) /* handle list window */
	    XtSetSensitive(bib->lw->lstWin, sensitive);
	 card = glbFirstCardListEl(bib); /* handle all cards */
	 while (card != NULL) {
	    if (card->cw != NULL)
	       XtSetSensitive(card->cw->cardWin, sensitive);
	    if (card->aw != NULL)
	       XtSetSensitive(card->aw->annoteWin, sensitive);
	    card = glbNextCardListEl(bib, card);
	 } /* endwhile */
      } /* endif */
   } /* endelse */
}


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

/*********************************************************************/
/* calcNextBibWinPos:                                                */
/*    Calculate coords of next bibliography window                   */
/*********************************************************************/
static Errcode
calcNextBibWinPos (int n, Position *x, Position *y)
{
   XtTranslateCoords(desktop,
		     (n + 1) * BIBWIN_MARGIN,
		     (n + 1) * BIBWIN_MARGIN,
		     x, y);
   return(OK);
}


/*********************************************************************/
/* calcNextBibIconPos:                                               */
/*    Calculate coords of next bibliography window icon              */
/*********************************************************************/
static Errcode
calcNextBibIconPos (int curIcon, Position *x, Position *y)
{
Position curX, curY;

   if (curIcon == 0) { /* position 1st bibwin */
      curX = 1;
      curY = BV_ICON_MARGIN;
      XtTranslateCoords(desktop,
		       curX, curY,
		       x, y);
   }
   else {  /* position icon after curIcon */
      curX = curIcon * (BV_ICON_MARGIN + BV_ICON_WIDTH);
      curY = BV_ICON_MARGIN;
      XtTranslateCoords(desktop,
		       curX, curY,
		       x, y);
   }
}


/*********************************************************************/
/* createMenu:                                                       */
/*    Build pulldown menus in a bibliography window                  */
/*********************************************************************/
static void
createMenu (String menuName, MenuEntry item[], Widget parent, Widget *menu, BibPtr bp)
{
static Widget w;
int i = 0;
String iname;

   *menu = XtVaCreatePopupShell(menuName, 
             simpleMenuWidgetClass, parent, NULL);
   i = 0;
   while ((iname = item[i].name) != NULL) { 
      if (strncmp("line", iname, 4) == 0)   /* use a line pane */
         w = XtVaCreateManagedWidget(iname,
               smeLineObjectClass, *menu, NULL);
      else {
         w = XtVaCreateManagedWidget(iname, 
	       smeBSBObjectClass, *menu, NULL);
         XtAddCallback(w, XtNcallback, item[i].cb, (XtPointer)bp);
      }
      i++;
   }
}

