1 
2 /*********************************************************************/
3 /*  bibView: Administration of BibTeX-Databases                      */
4 /*           (Verwaltung von BibTeX-Literaturdatenbanken)            */
5 /*                                                                   */
6 /*  Module:  gui_card.c                                              */
7 /*                                                                   */
8 /*             GUI: Card Windows                                     */
9 /*             -                                                     */
10 /*                                                                   */
11 /*  Author:  Holger Martin,  martinh@informatik.tu-muenchen.de       */
12 /*           Peter M. Urban, urban@informatik.tu-muenchen.de         */
13 /*                                                                   */
14 /*  History:                                                         */
15 /*    12.19.91  PMU  created                                         */
16 /*    05.26.92       Version 1.0 released                            */
17 /*                                                                   */
18 /*  Copyright 1992 TU MUENCHEN                                       */
19 /*    See ./Copyright for complete rights and liability information. */
20 /*                                                                   */
21 /*********************************************************************/
22 
23 #include <stdio.h>
24 #include <X11/Intrinsic.h>
25 #include <X11/Shell.h>
26 #include <X11/StringDefs.h>
27 #include <X11/Xaw/Form.h>
28 #include <X11/Xaw/Paned.h>
29 #include <X11/Xaw/Box.h>
30 #include <X11/Xaw/Command.h>
31 #include <X11/Xaw/MenuButton.h>
32 #include <X11/Xaw/SimpleMenu.h>
33 #include <X11/Xaw/SmeBSB.h>
34 #include <X11/Xaw/SmeLine.h>
35 #include <X11/Xaw/Text.h>
36 #include <X11/Xaw/AsciiText.h>
37 #include <X11/Xaw/Viewport.h>
38 #include "bibview.h"
39 
40 
41 /* macros and definitions */
42 /* ---------------------- */
43 
44 
45 /* local function prototypes */
46 /* ------------------------- */
47 static Errcode calcNextCardWinPos (Widget desk, int n, Position *x, Position *y);
48 static Errcode calcNextCardIconPos (Widget desk, int curIcon, Position *x, Position *y);
49 static void createWidgets (BibPtr bp, CardPtr cp);
50 static Errcode saveWidgets (CardPtr cp);
51 
52 /* external global variables */
53 /* ------------------------- */
54 extern Widget topLevel, desktop;
55 extern Pixmap crdIconPixmap;
56 extern UserDefFld userDefFlds[];
57 extern OptionsRec options;
58 
59 extern int max_fields;
60 extern char sort_field[];
61 
62 
63 /* exported global variables */
64 /* ---------------------- */
65 
66 
67 /* local global variables */
68 /* ------------------------- */
69 Pixel back, fore, focus, reqback, auth_ed_back;
70 
71 
72 extern void string_event();
73 extern CardPtr getCardPtr();
74 static void forward_focus();
75 static void backward_focus();
76 static void set_focus();
77 static void close_card();
78 static void next_card();
79 static void save_card();
80 static void save_close_card();
81 
82 static XtActionsRec actions[] = {
83    "forward_focus", forward_focus,
84    "backward_focus", backward_focus,
85    "set_focus", set_focus,
86    "string", string_event,
87    "close", close_card,
88    "next", next_card,
89    "save", save_card,
90    "saveclose", save_close_card
91 };
92 
93 #ifdef ACTION_PROBLEM
94 static int first_in = 1;
95 #endif
96 
97 
98 /*********************************************************************/
99 /* next_card                                                         */
100 /*     calls ccdNextCardCmd                                          */
101 /*********************************************************************/
next_card(w)102 static void next_card(w)
103     Widget w;
104 {
105  CardPtr cp;
106 
107  if (strcmp(XtName(w),"field")!=0) return;
108  cp = getCardPtr(w);
109  if (cp==NULL){
110     return;
111  }
112  if (cp->new)
113     ccdNextCardCmd(w, (XtPointer)cp, NULL);
114  else
115     ccdNextChangeCmd(w, (XtPointer)cp, NULL);
116  }
117 
118 /*********************************************************************/
119 /* close_card                                                        */
120 /*     calls ccdCloseCardCmd                                         */
121 /*********************************************************************/
close_card(w)122 static void close_card(w)
123     Widget w;
124 {
125  CardPtr cp;
126 
127  if (strcmp(XtName(w),"field")!=0) return;
128  cp = getCardPtr(w);
129  if (cp==NULL){
130     return;
131  }
132  ccdCloseCardCmd(w, (XtPointer)cp, NULL);
133  }
134 
135 
136 /*********************************************************************/
137 /* saveCard                                                          */
138 /*     calls ccdSaveCardCmd                                          */
139 /*********************************************************************/
save_card(w)140 static void save_card(w)
141     Widget w;
142 {
143  CardPtr cp;
144 
145  if (strcmp(XtName(w),"field")!=0) return;
146  cp = getCardPtr(w);
147  if (cp==NULL){
148     return;
149  }
150  if (cp->new)
151     ccdSaveCardCmd(w, (XtPointer)cp, NULL);
152  else
153     ccdChangeCardCmd(w, (XtPointer)cp, NULL);
154  }
155 
156 
157 /*********************************************************************/
158 /* save_close_card                                                   */
159 /*     calls ccdSaveCardCmd  and ccdCloseCardCmd                     */
160 /*********************************************************************/
save_close_card(w)161 static void save_close_card(w)
162     Widget w;
163 {
164  CardPtr cp;
165 
166  if (strcmp(XtName(w),"field")!=0) return;
167  cp = getCardPtr(w);
168  if (cp==NULL){
169     return;
170  }
171  if (cp->new)
172     ccdSaveCardCmd(w, (XtPointer)cp, NULL);
173  else
174     ccdChangeCardCmd(w, (XtPointer)cp, NULL);
175  ccdCloseCardCmd(w, (XtPointer)cp, NULL);
176  }
177 
178 
179 /*********************************************************************/
180 /* forward_focus:                                                    */
181 /*    moves the focus of a field to the next field                   */
182 /*********************************************************************/
forward_focus(Widget w)183 static void forward_focus(Widget w)
184 {
185  BibPtr bp;
186  CardPtr cp;
187  CardWidgetsPtr cwp;
188  int i;
189 
190  if (!cotFocus())
191     return;
192  bp = glbFirstBibListEl();
193  while (bp!=NULL){
194     cp = glbFirstCardListEl(bp);
195     while (cp!=NULL){
196        cwp = &cp->cw->ct.cw;
197        if (w == cwp->mainkey){
198           XtVaSetValues(cwp->mainkey, XtNborderColor, fore, NULL);
199           if (cwp->owntype){
200              XtSetKeyboardFocus(XtParent(w), cwp->owntype);
201              XtVaSetValues(cwp->owntype, XtNborderColor, focus, NULL);
202              return;
203              }
204           else {
205              for (i=0; i< MAX_FIELDS; i++)
206             	if (cwp->wfield[2*i+1]){
207                 XtVaSetValues(cwp->wfield[2*i+1], XtNborderColor, focus, NULL);
208                 XtSetKeyboardFocus(XtParent(w), cwp->wfield[2*i+1]);
209 	        return;
210 	        }
211              if (i == MAX_FIELDS){
212                XtSetKeyboardFocus(XtParent(w), cwp->mainkey);
213                XtVaSetValues(cwp->mainkey, XtNborderColor, focus, NULL);
214 	       return;
215 	       }
216              }
217           }
218        if (w == cwp->owntype){
219           XtVaSetValues(cwp->owntype, XtNborderColor, fore, NULL);
220           for (i=0; i< MAX_FIELDS; i++)
221              if (cwp->wfield[2*i+1]){
222                 XtSetKeyboardFocus(XtParent(w), cwp->wfield[2*i+1]);
223                 XtVaSetValues(cwp->wfield[2*i+1], XtNborderColor, focus, NULL);
224                 return;
225                 }
226           if (i == MAX_FIELDS){
227              XtVaSetValues(cwp->mainkey, XtNborderColor, focus, NULL);
228              XtSetKeyboardFocus(XtParent(w), cwp->mainkey);
229 	     return;
230 	     }
231        }
232        for (i=0; i< MAX_FIELDS; i++)
233          if (w == cwp->wfield[2*i+1]){
234             XtVaSetValues(cwp->wfield[2*i+1], XtNborderColor, fore, NULL);
235             for (i=i+1; i< MAX_FIELDS; i++)
236               if (cwp->wfield[2*i+1]){
237                  XtSetKeyboardFocus(XtParent(w), cwp->wfield[2*i+1]);
238                  XtVaSetValues(cwp->wfield[2*i+1], XtNborderColor, focus, NULL);
239                  return;
240                  }
241             if (i == MAX_FIELDS){
242                XtSetKeyboardFocus(XtParent(w), cwp->mainkey);
243                XtVaSetValues(cwp->mainkey, XtNborderColor, focus, NULL);
244                return;
245                }
246          }
247        cp = glbNextCardListEl(bp,cp);
248        }
249     bp = glbNextBibListEl(bp);
250     }
251 }
252 
253 /*********************************************************************/
254 /* forward_focus:                                                    */
255 /*    moves the focus to the previous field                          */
256 /*********************************************************************/
backward_focus(Widget w)257 static void backward_focus(Widget w)
258 {
259  BibPtr bp;
260  CardPtr cp;
261  CardWidgetsPtr cwp;
262  int i;
263 
264  if (!cotFocus())
265     return;
266  bp = glbFirstBibListEl();
267  while (bp!=NULL){
268     cp = glbFirstCardListEl(bp);
269     while (cp!=NULL){
270       cwp = &cp->cw->ct.cw;
271       if (w == cwp->mainkey){
272          XtVaSetValues(cwp->mainkey, XtNborderColor, fore, NULL);
273          for (i=MAX_FIELDS-1; i>=0; i--)
274             if (cwp->wfield[2*i+1]){
275                XtVaSetValues(cwp->wfield[2*i+1], XtNborderColor, focus, NULL);
276                XtSetKeyboardFocus(XtParent(w), cwp->wfield[2*i+1]);
277                return;
278                }
279          if (i < 0){
280             if (cwp->owntype){
281                XtVaSetValues(cwp->owntype, XtNborderColor, focus, NULL);
282                XtSetKeyboardFocus(XtParent(w), cwp->owntype);
283                return;
284                }
285             else{
286                XtSetKeyboardFocus(XtParent(w), cwp->mainkey);
287                XtVaSetValues(cwp->mainkey, XtNborderColor, fore, NULL);
288        	       return;
289      	       }
290             }
291          }
292       if (w == cwp->owntype){
293          XtVaSetValues(cwp->owntype, XtNborderColor, fore, NULL);
294          XtSetKeyboardFocus(XtParent(w), cwp->mainkey);
295          XtVaSetValues(cwp->mainkey, XtNborderColor, focus, NULL);
296          return;
297          }
298       for (i=MAX_FIELDS-1; i>=0; i--)
299          if (w == cwp->wfield[2*i+1]){
300             XtVaSetValues(cwp->wfield[2*i+1], XtNborderColor, fore, NULL);
301             for (i=i-1; i>=0; i--)
302                if (cwp->wfield[2*i+1]){
303                   XtSetKeyboardFocus(XtParent(w), cwp->wfield[2*i+1]);
304                   XtVaSetValues(cwp->wfield[2*i+1],
305 		      XtNborderColor, focus, NULL);
306                   return;
307                   }
308             if (i < 0){
309                if (cwp->owntype){
310                   XtSetKeyboardFocus(XtParent(w), cwp->owntype);
311                   XtVaSetValues(cwp->owntype, XtNborderColor, focus, NULL);
312                   return;
313                   }
314                else{
315                   XtSetKeyboardFocus(XtParent(w), cwp->mainkey);
316                   XtVaSetValues(cwp->mainkey, XtNborderColor, focus, NULL);
317                   return;
318                   }
319             }
320          }
321        cp = glbNextCardListEl(bp,cp);
322        }
323     bp = glbNextBibListEl(bp);
324     }
325 }
326 
327 /*********************************************************************/
328 /* set_focus:                                                        */
329 /*    moves the focus to the field in which the left mouse           */
330 /*    button is pressed                                              */
331 /*********************************************************************/
set_focus(Widget w)332 static void set_focus(Widget w)
333 {
334  BibPtr bp;
335  CardPtr cp;
336  CardWidgetsPtr cwp;
337  int i;
338 
339  if (!cotFocus())
340     return;
341  bp = glbFirstBibListEl();
342  while (bp!=NULL){
343     cp = glbFirstCardListEl(bp);
344     while (cp!=NULL){
345        cwp = &cp->cw->ct.cw;
346        XtVaSetValues(cwp->mainkey, XtNborderColor, fore, NULL);
347        if (cwp->owntype)
348           XtVaSetValues(cwp->mainkey, XtNborderColor, fore, NULL);
349        for (i=0; i< MAX_FIELDS; i++)
350           if (cwp->wfield[2*i+1])
351              XtVaSetValues(cwp->wfield[2*i+1], XtNborderColor,
352 		fore, NULL);
353        cp = glbNextCardListEl(bp,cp);
354        }
355     bp = glbNextBibListEl(bp);
356     }
357  XtSetKeyboardFocus(XtParent(w), w);
358  XtVaSetValues(w, XtNborderColor, focus, NULL);
359 }
360 
361 
362 /*********************************************************************/
363 /* gucOpenCardWin:                                                   */
364 /*    Creates an instance of a card window                           */
365 /*********************************************************************/
366 Errcode
gucOpenCardWin(BibPtr bp,CardPtr cp,Boolean isNew)367 gucOpenCardWin (BibPtr bp, CardPtr cp, Boolean isNew)
368 {
369 CardWinPtr cw;
370 CardWidgetsPtr cwp;
371 Dimension height;
372 
373 #ifdef ACTION_PROBLEM
374    if (first_in){
375 #endif
376    XtAppAddActions(XtWidgetToApplicationContext(topLevel), actions,
377 		  XtNumber(actions));
378 #ifdef ACTION_PROBLEM
379    first_in = 0;
380    }
381 #endif
382    reqback = options.reqColor;
383    auth_ed_back = options.authedColor;
384 
385    /* allocate memory for new element of window list */
386    if ((cw = (CardWinPtr) XtCalloc(1, sizeof(CardWin))) == NULL) {
387       /* error-handling is done in control modules */
388       return(ERR_NOMALLOC);
389    }
390 
391    /* allocate memory for text buffers of card widget */
392    /* not needed: handled by widget */
393 
394    /* build label of new shell */
395    cw->shellName = (String)XtCalloc(strlen(bp->filename) +
396 	             strlen(cp->cd->cardtypestr)+4,
397 	                               sizeof(char));
398    if (cw->shellName == NULL) {
399       XtFree((char *)cw);
400       return(ERR_NOMALLOC);
401    }
402    sprintf(cw->shellName, "%s: %s", bp->filename,
403 				    cp->cd->cardtypestr);
404 
405    /* create popup shell fornew file */
406    cw->cardShell = XtVaCreatePopupShell("cardShell",
407                      topLevelShellWidgetClass, topLevel,
408                      XtNtransientFor, bp->bw->bibShell,
409                      XtNwindowGroup, XtWindow(bp->bw->bibShell),
410                      XtNtitle, cw->shellName,
411                      XtNiconPixmap, crdIconPixmap,
412                      XtNiconName, cp->cd->mainkey, NULL);
413 
414    /* create widgets for card */
415    cw->cardWin = XtVaCreateManagedWidget("cardWin",
416 		   panedWidgetClass, cw->cardShell, NULL);
417    cw->cmdBox = XtVaCreateManagedWidget("commandBox",
418 		  boxWidgetClass, cw->cardWin, NULL);
419    cw->duplicate = XtVaCreateManagedWidget("duplicate",
420 		 menuButtonWidgetClass, cw->cmdBox, NULL);
421    cw->userDef = XtVaCreateManagedWidget("userDef",
422 	           commandWidgetClass, cw->cmdBox, NULL);
423    cw->annote = XtVaCreateManagedWidget("annote",
424 	           commandWidgetClass, cw->cmdBox,
425 		   XtNlabel, glbFldToName(nannote), NULL);
426    cw->delete = XtVaCreateManagedWidget("delete",
427 	          commandWidgetClass, cw->cmdBox, NULL);
428    cw->change = XtVaCreateManagedWidget("save",
429          	  commandWidgetClass, cw->cmdBox, NULL);
430    cw->copy = XtVaCreateManagedWidget("copy",
431 	        commandWidgetClass, cw->cmdBox, NULL);
432    cw->crossref = XtVaCreateManagedWidget("crossref",
433 	        commandWidgetClass, cw->cmdBox, NULL);
434    cw->next = XtVaCreateManagedWidget("next",
435 	        commandWidgetClass, cw->cmdBox, NULL);
436    cw->close = XtVaCreateManagedWidget("quit",
437 	         commandWidgetClass, cw->cmdBox, NULL);
438 
439    glbCreateTypeMenu("duplicateMenu", cw->duplicate,
440 		     &cw->duplicateMenu, ccdDuplicateCardCmd, (XtPointer) cp);
441    XtAddCallback(cw->close, XtNcallback, ccdCloseCardCmd, (XtPointer)cp);
442    XtAddCallback(cw->userDef, XtNcallback, ccdUserdataCmd, (XtPointer)cp);
443    XtAddCallback(cw->delete, XtNcallback, ccdDeleteCardCmd, (XtPointer)cp);
444    XtAddCallback(cw->annote, XtNcallback, ccdAnnoteCardCmd, (XtPointer)cp);
445    if (isNew)
446       XtAddCallback(cw->change, XtNcallback, ccdSaveCardCmd, (XtPointer)cp);
447    else
448       XtAddCallback(cw->change, XtNcallback, ccdChangeCardCmd, (XtPointer)cp);
449    XtAddCallback(cw->copy, XtNcallback, ccdCopyCardCmd, (XtPointer)cp);
450    XtAddCallback(cw->crossref, XtNcallback, ccdOpenCrossrefCmd, (XtPointer)cp);
451    if (isNew)
452       XtAddCallback(cw->next, XtNcallback, ccdNextCardCmd, (XtPointer)cp);
453    else
454       XtAddCallback(cw->next, XtNcallback, ccdNextChangeCmd, (XtPointer)cp);
455 
456    /* create card window desktop */
457    cw->cardDesk = XtVaCreateManagedWidget("carddesk",
458 	            viewportWidgetClass, cw->cardWin,
459 		    XtNshowGrip, True,
460 		    XtNallowVert, True,
461 		    NULL);
462    cw->cardFlds = XtVaCreateManagedWidget(glbTypeToName(cp->cd->cardtype),
463 	            formWidgetClass, cw->cardDesk, NULL);
464 
465    /* set card pointer to new struct, new window created */
466    cp->cw = cw;
467    cp->aw = NULL;
468    cp->new = isNew;
469    bp->noOfCardWins++;
470 
471    /* Position window near bibliography desktop */
472    calcNextCardWinPos(bp->bw->bibdesk, bp->nextCardPos, &cw->winX, &cw->winY);
473    XtVaSetValues(cw->cardShell,
474                  XtNx, cw->winX,
475                  XtNy, cw->winY, NULL);
476 
477    /* if option on, set icon position on desktop */
478    if (cotIconizeOnDesktop()) {
479       calcNextCardIconPos(bp->bw->bibdesk, bp->noOfCardWins, &cw->iconX, &cw->iconY);
480       XtVaSetValues(cw->cardShell,
481                     XtNiconX, cw->iconX,
482                     XtNiconY, cw->iconY, NULL);
483    }
484    bp->nextCardPos++;
485 
486    /* build only widgets for specific card type */
487    createWidgets(bp, cp);
488    cwp = &cp->cw->ct.cw;
489    XtPopup(cw->cardShell, XtGrabNone);
490    XtVaGetValues(cw->cardShell, XtNheight, &height, NULL);
491    if (height > HeightOfScreen(XtScreen(topLevel)) - 100)
492       XtVaSetValues(cw->cardShell, XtNheight,
493 	   HeightOfScreen(XtScreen(topLevel)) - 100, NULL);
494 
495    XtVaGetValues(cwp->mainkey, XtNbackground, &back, NULL);
496    XtVaGetValues(cwp->mainkey, XtNborderColor, &fore, NULL);
497    focus = options.focusColor;
498    if (cotFocus()){
499       XtSetKeyboardFocus(cw->cardFlds, cwp->mainkey);
500       XtVaSetValues(cwp->mainkey, XtNborderColor, focus, NULL);
501       }
502 
503    return(OK);
504 }
505 
506 
507 /*********************************************************************/
508 /* gucAuthorChanged:                                                 */
509 /*    Returns true, if user made changes to standard BibTeX fields   */
510 /*********************************************************************/
511 #define WidgetChanged(w) (XawAsciiSourceChanged(XawTextGetSource(w)))
512 Boolean
gucAuthorChanged(CardPtr cp)513 gucAuthorChanged (CardPtr cp)
514 {
515 CardWidgetsPtr cwp = &cp->cw->ct.cw;	/* ptr to widget ids */
516 int field;
517 
518   field = cp->cd->sorted;
519 
520   if (field != -1){
521     if (sort_field[field] == 'n'){
522       if (cwp->wfield[2*field+1] && WidgetChanged(cwp->wfield[2*field+1]))
523          return(TRUE);
524       else
525          return(FALSE);
526       }
527     else
528       return(FALSE);
529     }
530   else
531       return(FALSE);
532 }
533 
534 
535 /*********************************************************************/
536 /* gucStdFldsChanged:                                                */
537 /*    Returns true, if user made changes to standard BibTeX fields   */
538 /*********************************************************************/
539 Boolean
gucStdFldsChanged(CardPtr cp)540 gucStdFldsChanged (CardPtr cp)
541 {
542 CardWidgetsPtr cwp = &cp->cw->ct.cw;	/* ptr to widget ids */
543 int i;
544 
545    if (cwp->mainkey && WidgetChanged(cwp->mainkey))
546       return(TRUE);
547    if (cwp->annote && (cp->cd->annoteChanged==TRUE))
548       return(TRUE);
549    for (i=0; i<max_fields; i++) {
550       if (i!=nannote)
551          if (cwp->wfield[2*i+1] && WidgetChanged(cwp->wfield[2*i+1]))
552             return(TRUE);
553    }
554    return(FALSE);
555 }
556 #undef WidgetChanged
557 
558 
559 /*********************************************************************/
560 /* gucSaveCardData:                                                  */
561 /*    Save data from card window into new card                       */
562 /*********************************************************************/
563 Errcode
gucSaveCardData(CardPtr cp)564 gucSaveCardData (CardPtr cp)
565 {
566 Errcode status;
567 CardType type;
568 UserFld *ufield;
569 String annotefield, typestr, authorsort;
570 
571    /* save reusable data */
572    type = cp->cd->cardtype;
573    typestr = glbNewString(cp->cd->cardtypestr);
574    if ((status = gucSaveUserFields(cp)) != OK)
575       return(status);
576    ufield = cp->cd->ufield;
577    cp->cd->ufield = NULL;
578 
579    if (gucAuthorChanged(cp)){
580       XtFree(cp->cd->authorsort);
581       cp->cd->authorsort=NULL;
582       }
583 
584    annotefield = glbNewString(cp->cd->field[nannote]);
585    authorsort =  glbNewString(cp->cd->authorsort);
586 
587    /* save annote field */
588    /* delete old card data */
589    dbtDeleteCard(&cp->cd);
590 
591    if ((status = dbtMakeCard(&cp->cd)) != DBT_OK)
592       return(status);
593 
594    /* build only widgets for specific card type */
595    cp->cd->cardtype = type;
596    cp->cd->ufield = ufield;
597    cp->cd->cardtypestr = typestr;
598    cp->cd->field[nannote] = annotefield;
599    cp->cd->authorsort = authorsort;
600    if ((status = saveWidgets(cp)) != OK)
601       return(status);
602 
603    return(OK);
604 }
605 
606 
607 /*********************************************************************/
608 /* gucCloseCardCmd:                                                  */
609 /*    Callback for quit command in card window                       */
610 /*********************************************************************/
611 void
gucCloseCardCmd(Widget w,XtPointer clientData,XtPointer callData)612 gucCloseCardCmd (Widget w, XtPointer clientData, XtPointer callData)
613 {
614 CardPtr cp = (CardPtr)clientData;
615 Errcode status;
616 
617    if ((status = gucCloseCardWin(cp)) != OK) {
618       guwError(status);
619    }
620 }
621 
622 
623 /*********************************************************************/
624 /* gucCloseCardWin:                                                  */
625 /*    Close card window                                              */
626 /*********************************************************************/
627 Errcode
gucCloseCardWin(CardPtr cp)628 gucCloseCardWin (CardPtr cp)
629 {
630 BibPtr bp = (BibPtr)cp->bp;
631 
632    if (cp->aw != NULL) {
633        XtPopdown(cp->aw->annoteShell);
634        XtFree((char *)cp->aw->shellName);
635        XtFree((char *)cp->aw);
636        cp->aw = NULL;
637        }
638    XtPopdown(cp->cw->cardShell);
639    bp->noOfCardWins--;
640    if (glbLastCardListEl(bp) == cp)
641       bp->nextCardPos -= 1;
642    XtFree((char *)cp->cw->shellName);
643    XtFree((char *)cp->cw);
644    glbDelCardListEl(bp, cp);
645    if (glbFirstCardListEl(bp) == NULL)
646       bp->nextCardPos = 0;
647    return(OK);
648 }
649 
650 
651 /*********************************************************************/
652 /* gucOpenUserFields:                                                */
653 /*    Extend editable fields in current window with user fields      */
654 /*********************************************************************/
655 Errcode
gucOpenUserFields(CardPtr cp)656 gucOpenUserFields (CardPtr cp)
657 {
658 Widget card = cp->cw->cardDesk;		/* parent widget */
659 UserFld **root, *cup;                   /* ptr to user fields */
660 UserFld *up1, *up;
661 UserFld newUserFld;
662 ListNode *udp;
663 Widget prevWidget;
664 Boolean found;
665 Dimension dheight, min;
666 Errcode status;
667 int i;
668 
669    root = &cp->cd->ufield;
670    cup = cp->cd->ufield;
671 
672    XawPanedSetRefigureMode(cp->cw->cardWin, False);
673 
674    /* save current dimensions of shell for later resize */
675    XtVaGetValues(cp->cw->cardShell,
676 		 XtNheight, &cp->cw->height,
677 		 XtNwidth,  &cp->cw->width,
678 		 XtNborderWidth, &cp->cw->borderWidth, NULL);
679 
680    /* keep old desktop same size while user defs are shown */
681    XtVaGetValues(card,
682 		 XtNheight, &dheight,
683 		 XtNmin, &min, NULL);
684    XtVaSetValues(card,
685 		 XtNmin, dheight, NULL);
686 
687    /* create neu widgets for user def fields */
688    cp->cw->usrFldVport = XtVaCreateWidget("userFldVport",
689 			   viewportWidgetClass, cp->cw->cardWin,
690 			   XtNshowGrip, True,
691 			   XtNallowVert, True, NULL);
692    cp->cw->usrFldDesk  = XtVaCreateWidget("userFldDesk",
693 			   formWidgetClass, cp->cw->usrFldVport,
694 			   NULL);
695    cp->cw->usrFldHead  = XtVaCreateManagedWidget("userFldHead",
696 			   labelWidgetClass, cp->cw->usrFldDesk,
697 			   XtNleft, XtChainLeft,
698 			   XtNtop, XtChainTop, NULL);
699    prevWidget = cp->cw->usrFldHead;
700 
701    /* open already existing fields first */
702    up = cup;
703    while (up != NULL) {
704       up->fldLabel =    XtVaCreateManagedWidget("userFieldL",
705 			     asciiTextWidgetClass, cp->cw->usrFldDesk,
706 			     XtNstring, up->fldName,
707 			     XtNfromVert, prevWidget,
708 			     XtNleft, XtChainLeft, NULL);
709       up->fldText  =    XtVaCreateManagedWidget("userField",
710 			     asciiTextWidgetClass, cp->cw->usrFldDesk,
711 			     XtNstring, up->fldData,
712 			     XtNfromVert, prevWidget,
713 			     XtNfromHoriz, up->fldLabel, NULL);
714       XtAddCallback(XawTextGetSource(up->fldText),
715 		    XtNcallback, ccdSetChangeFlag, (XtPointer)cp);
716       prevWidget = up->fldText;
717       up = up->next;
718    } /* endwhile */
719 
720    /* open default fields not opened already */
721    udp = userDefFlds[cp->cd->cardtype];
722    while (udp != NULL) {
723       up1 = cup;
724       found = FALSE;
725       while (up1 != NULL) {
726 	 if (strcmp(up1->fldName, udp->data) == 0) {
727 	    found = TRUE;
728 	    break;
729 	 }
730 	 up1 = up1->next;
731       }
732 
733       if (!found) {
734          newUserFld.fldName = glbNewString(udp->data);
735          newUserFld.fldData = "";
736 	 newUserFld.fldLabel = XtVaCreateManagedWidget("userFieldL",
737 			     asciiTextWidgetClass, cp->cw->usrFldDesk,
738 			     XtNstring, udp->data,
739 			     XtNfromVert, prevWidget,
740 			     XtNleft, XtChainLeft, NULL);
741 	 newUserFld.fldText  = XtVaCreateManagedWidget("userField",
742 			     asciiTextWidgetClass, cp->cw->usrFldDesk,
743 			     XtNstring, newUserFld.fldData,
744 			     XtNfromVert, prevWidget,
745 			     XtNfromHoriz, newUserFld.fldLabel, NULL);
746 	 XtAddCallback(XawTextGetSource(newUserFld.fldText),
747 		       XtNcallback, ccdSetChangeFlag, (XtPointer)cp);
748          prevWidget = newUserFld.fldText;
749          if ((status = dbtAppendUserFld(root, &newUserFld)) != DBT_OK)
750 	    guwError(status);
751       }
752       udp = udp->next;
753    }
754 
755    /* open MAX_NEW_USER_FLDS fields for any input */
756    for (i = 0; i < MAX_NEW_USERDEF_FLDS; i++) {
757       newUserFld.fldName = "";
758       newUserFld.fldData = "";
759       newUserFld.fldLabel = XtVaCreateManagedWidget("userFieldL",
760 			  asciiTextWidgetClass, cp->cw->usrFldDesk,
761 			  XtNstring, newUserFld.fldName,
762 			  XtNfromVert, prevWidget,
763 			  XtNleft, XtChainLeft, NULL);
764       newUserFld.fldText  = XtVaCreateManagedWidget("userField",
765 			  asciiTextWidgetClass, cp->cw->usrFldDesk,
766 			  XtNstring, newUserFld.fldData,
767 			  XtNfromVert, prevWidget,
768 			  XtNfromHoriz, newUserFld.fldLabel, NULL);
769       XtAddCallback(XawTextGetSource(newUserFld.fldText),
770 		    XtNcallback, ccdSetChangeFlag, (XtPointer)cp);
771       prevWidget = newUserFld.fldText;
772       if ((status = dbtAppendUserFld(root, &newUserFld)) != DBT_OK)
773 	 guwError(status);
774    }
775 
776    XtManageChild(cp->cw->usrFldDesk);
777    XtManageChild(cp->cw->usrFldVport);
778    XawPanedSetRefigureMode(cp->cw->cardWin, True);
779    cp->extended = TRUE;
780    return(OK);
781 }
782 
783 /*********************************************************************/
784 /* gucCloseUserFields:                                               */
785 /*    Remove user fields from card window                            */
786 /*********************************************************************/
787 Errcode
gucCloseUserFields(CardPtr cp)788 gucCloseUserFields (CardPtr cp)
789 {
790 CardWinPtr cw = cp->cw;
791 Errcode status;
792 
793    if ((status = gucSaveUserFields(cp)) != OK)
794       guwError(status);
795 
796    cp->extended = FALSE;
797    XtDestroyWidget(cw->usrFldVport);
798    XtResizeWidget(cw->cardShell, cw->width, cw->height, cw->borderWidth);
799    return(OK);
800 }
801 
802 
803 /*********************************************************************/
804 /* gucSaveUserFields:                                                */
805 /*    Save data in user fields to card (temp or real)                */
806 /*********************************************************************/
807 Errcode
gucSaveUserFields(CardPtr cp)808 gucSaveUserFields (CardPtr cp)
809 {
810 UserFld newFld, *tfield = NULL, *up;
811 Errcode status;
812 String str;
813 
814    if (!cp->extended)
815       return(OK);
816 
817    up = cp->cd->ufield;
818    while (up != NULL) {
819       XtVaGetValues(up->fldLabel, XtNstring, &str, NULL);
820       if (glbIsStringEmpty(str)) {
821 	 up = up->next;
822 	 continue;
823       }
824       newFld.fldLabel = up->fldLabel;
825       newFld.fldText = up->fldText;
826       if ((newFld.fldName = glbNewString(str)) == NULL)
827 	 return(ERR_NOMALLOC);
828       XtVaGetValues(up->fldText, XtNstring, &str, NULL);
829       if ((newFld.fldData = glbNewString(str)) == NULL)
830 	 return(ERR_NOMALLOC);
831       if ((status = dbtAppendUserFld(&tfield, &newFld)) != DBT_OK)
832 	 guwError(status);
833       up = up->next;
834    } /* endwhile */
835 
836    dbtDeleteAllUserFld(&cp->cd->ufield);
837    cp->cd->ufield = tfield;
838    return(OK);
839 }
840 
841 
842 /*********************************************************************/
843 /* gucCascadeCmd:                                                    */
844 /*    Callback for cascade command                                   */
845 /*********************************************************************/
846 void
gucCascadeCmd(Widget w,XtPointer clientData,XtPointer callData)847 gucCascadeCmd (Widget w, XtPointer clientData, XtPointer callData)
848 {
849 BibPtr bp = (BibPtr)clientData;
850 Errcode status;
851 
852    if ((status = gucCascade(bp)) != OK)
853       guwError(status);
854    if ((status = gueCascade(bp)) != OK)
855       guwError(status);
856    if ((status = gulCascade(bp)) != OK)
857       guwError(status);
858 }
859 
860 
861 /*********************************************************************/
862 /* gucCascade:                                                       */
863 /*    Layout card windows of a bibliography                          */
864 /*********************************************************************/
865 Errcode
gucCascade(BibPtr bp)866 gucCascade (BibPtr bp)
867 {
868    gucSetWindowCoords(bp, FALSE);
869    if (cotIconizeOnDesktop())
870       gucSetIconCoords(bp, FALSE);
871    return(OK);
872 }
873 
874 
875 /*********************************************************************/
876 /* gucSetWindowCoords:                                               */
877 /*    Set positions of card windows                                  */
878 /*********************************************************************/
879 Errcode
gucSetWindowCoords(BibPtr bp,Boolean calcOnly)880 gucSetWindowCoords (BibPtr bp, Boolean calcOnly)
881 {
882 CardPtr cp;
883 int i;
884 
885    cp = glbFirstCardListEl(bp);
886    for (i = 1; i <= bp->noOfCardWins; i++) {
887       calcNextCardWinPos(bp->bw->bibdesk, i, &cp->cw->winX, &cp->cw->winY);
888       if (!calcOnly) {
889          XtVaSetValues(cp->cw->cardShell,
890                        XtNx, cp->cw->winX,
891 		       XtNy, cp->cw->winY, NULL);
892 	 if (XtIsRealized(cp->cw->cardShell)) {
893 	    XRaiseWindow(XtDisplay(cp->cw->cardShell),
894 			 XtWindow(cp->cw->cardShell));
895 	 }
896       } /* endif */
897       cp = glbNextCardListEl(bp, cp);
898    } /* endfor */
899 
900    return(OK);
901 }
902 
903 
904 /*********************************************************************/
905 /* gucSetIconCoords:                                                 */
906 /*    Set positions of card window icons                             */
907 /*********************************************************************/
908 Errcode
gucSetIconCoords(BibPtr bp,Boolean calcOnly)909 gucSetIconCoords (BibPtr bp, Boolean calcOnly)
910 {
911 CardPtr cp;
912 int curIcon = 0;
913 
914    if ((cp = glbFirstCardListEl(bp)) != NULL) {
915       calcNextCardIconPos(bp->bw->bibdesk, curIcon, &cp->cw->iconX, &cp->cw->iconY);
916       if (!calcOnly) {
917          XtVaSetValues(cp->cw->cardShell,
918 		       XtNiconX, cp->cw->iconX,
919 		       XtNiconY, cp->cw->iconY, NULL);
920       }
921 
922       while ((cp = glbNextCardListEl(bp, cp)) != NULL) {
923          curIcon++;
924          calcNextCardIconPos(bp->bw->bibdesk, curIcon, &cp->cw->iconX, &cp->cw->iconY);
925          if (!calcOnly) {
926             XtVaSetValues(cp->cw->cardShell,
927 		          XtNiconX, cp->cw->iconX,
928 		          XtNiconY, cp->cw->iconY, NULL);
929          }
930       }  /* endwhile */
931    } /* endif */
932 
933    return(OK);
934 }
935 
936 
937 /*********************************************************************/
938 /* gucUnsetIconCoords:                                               */
939 /*    Unset positions of card window icons                           */
940 /*********************************************************************/
941 Errcode
gucUnsetIconCoords(BibPtr bp,Boolean calcOnly)942 gucUnsetIconCoords (BibPtr bp, Boolean calcOnly)
943 {
944 CardPtr cp;
945 
946    if ((cp = glbFirstCardListEl(bp)) != NULL) {
947       cp->cw->iconX = cp->cw->iconY = -1;
948       if (!calcOnly) {
949          XtVaSetValues(cp->cw->cardShell,
950 		       XtNiconX, cp->cw->iconX,
951 		       XtNiconY, cp->cw->iconY, NULL);
952       }
953 
954       while ((cp = glbNextCardListEl(bp, cp)) != NULL) {
955          cp->cw->iconX = cp->cw->iconY = -1;
956          if (!calcOnly) {
957             XtVaSetValues(cp->cw->cardShell,
958 		          XtNiconX, cp->cw->iconX,
959 		          XtNiconY, cp->cw->iconY, NULL);
960          }
961       }  /* endwhile */
962    } /* endif */
963 
964    return(OK);
965 }
966 
967 
968 
969 /*********************************************************************/
970 /* LOCAL FUNCTIONS                                                   */
971 /*********************************************************************/
972 
973 /*********************************************************************/
974 /* calcNextCardWinPos:                                               */
975 /*    Calculate coords of next card window                           */
976 /*********************************************************************/
977 static Errcode
calcNextCardWinPos(Widget desk,int n,Position * x,Position * y)978 calcNextCardWinPos (Widget desk, int n, Position *x, Position *y)
979 {
980 Dimension dwidth, dheight;
981 
982    XtVaGetValues(desk,
983 		 XtNwidth, &dwidth,
984 		 XtNheight, &dheight, NULL);
985    XtTranslateCoords(desk,
986 		     (n+2) * (Position)CARDWIN_MARGIN,
987 		     (n+2) * (Position)CARDWIN_MARGIN,
988 		     x, y);
989 
990    return(OK);
991 }
992 
993 
994 /*********************************************************************/
995 /* calcNextCardIconPos:                                              */
996 /*    Calculate coords of next card window icon                      */
997 /*********************************************************************/
998 static Errcode
calcNextCardIconPos(Widget desk,int curIcon,Position * x,Position * y)999 calcNextCardIconPos (Widget desk, int curIcon, Position *x, Position *y)
1000 {
1001 Position curX, curY;
1002 
1003    if (curIcon == 0) { /* position 1st bibwin */
1004       curX = 1;
1005       curY = CARD_ICON_MARGIN;
1006       XtTranslateCoords(desk,
1007 		       curX, curY,
1008 		       x, y);
1009    }
1010    else {  /* position icon after curIcon */
1011       curX = curIcon * (CARD_ICON_MARGIN + CARD_ICON_WIDTH);
1012       curY = CARD_ICON_MARGIN;
1013       XtTranslateCoords(desk,
1014 		       curX, curY,
1015 		       x, y);
1016    }
1017 }
1018 
1019 
1020 /*********************************************************************/
1021 /* createWidgets:                                                    */
1022 /*    Creates widgets depending on card type                         */
1023 /*********************************************************************/
1024 static void
createWidgets(BibPtr bp,CardPtr cp)1025 createWidgets(BibPtr bp, CardPtr cp)
1026 {
1027 CardWidgetsPtr cwp = &cp->cw->ct.cw;	/* ptr to widget ids */
1028 CardDataPtr cdp = cp->cd;		/* ptr to real card data */
1029 Widget card = cp->cw->cardFlds;		/* parent widget */
1030 Widget aktwidget;
1031 int i;
1032 
1033    for (i=0; i<MAX_FIELDS; i++){
1034       cwp->wfield[2*i]   = NULL;
1035       cwp->wfield[2*i+1] = NULL;
1036       }
1037 
1038    cdp->annoteChanged = FALSE;
1039    cwp->mainkeyL = 	XtVaCreateManagedWidget("fieldLabel",
1040 	           	  labelWidgetClass, card,
1041 		   	  XtNtop, XtChainTop,
1042 			  XtNlabel, "BibTeX-Key",
1043 		   	  XtNleft, XtChainLeft, NULL);
1044    cwp->mainkey = 	XtVaCreateManagedWidget("field",
1045 	          	  asciiTextWidgetClass, card,
1046 		  	  XtNstring, cdp->mainkey,
1047 		  	  XtNtop, XtChainTop,
1048 		  	  XtNfromHoriz, cwp->mainkeyL,
1049 			  NULL);
1050    aktwidget = cwp->mainkey;
1051    if (cdp->cardtype == MAX_BIBTEX_TYPES){
1052       cwp->owntypeL = 	XtVaCreateManagedWidget("fieldLabel",
1053    	           	  labelWidgetClass, card,
1054 		    	  XtNfromVert, aktwidget,
1055 		    	  XtNlabel, "BibTeX-Type",
1056 		   	  XtNleft, XtChainLeft, NULL);
1057       cwp->owntype = 	XtVaCreateManagedWidget("field",
1058 	          	  asciiTextWidgetClass, card,
1059 		  	  XtNstring, cdp->cardtypestr,
1060 		    	  XtNfromVert, aktwidget,
1061 		  	  XtNfromHoriz, cwp->owntypeL, NULL);
1062       aktwidget = cwp->owntype;
1063    }
1064    for (i=0; i<max_fields; i++) {
1065       if ((i!=nannote) && isstandardfield(i, cdp->cardtype)){
1066          cwp->wfield[2*i] = 	XtVaCreateManagedWidget("fieldLabel",
1067 	           	  labelWidgetClass, card,
1068 			  XtNlabel, glbFldToName(i),
1069 		    	  XtNfromVert, aktwidget,
1070 		   	  XtNleft, XtChainLeft, NULL);
1071          cwp->wfield[2*i+1] = 	XtVaCreateManagedWidget("field",
1072 	          	  asciiTextWidgetClass, card,
1073 		  	  XtNstring, cdp->field[i],
1074 		    	  XtNfromVert, aktwidget,
1075 		  	  XtNfromHoriz, cwp->wfield[2*i], NULL);
1076       if (((i == nauthor) || (i == neditor)) &&
1077 	   ((cdp->cardtype==book) || (cdp->cardtype==inbook))){
1078          XtVaSetValues(cwp->wfield[2*i+1], XtNborderWidth, 3, NULL);
1079          XtVaSetValues(cwp->wfield[2*i+1], XtNbackground, auth_ed_back, NULL);
1080 	 }
1081       else if (((i == nchapter) || (i == npages)) &&
1082 	   (cdp->cardtype==inbook)){
1083          XtVaSetValues(cwp->wfield[2*i+1], XtNborderWidth, 3, NULL);
1084          XtVaSetValues(cwp->wfield[2*i+1], XtNbackground, auth_ed_back, NULL);
1085 	 }
1086       else if (isrequiredfield(i, cdp->cardtype)){
1087          XtVaSetValues(cwp->wfield[2*i+1], XtNborderWidth, 3, NULL);
1088          XtVaSetValues(cwp->wfield[2*i+1], XtNbackground, reqback, NULL);
1089 	 }
1090       aktwidget = cwp->wfield[2*i+1];
1091       }
1092    }
1093 }
1094 
1095 
1096 /*********************************************************************/
1097 /* saveWidgets:                                                      */
1098 /*    Saves data from widget to new card                             */
1099 /*********************************************************************/
1100 static Errcode
saveWidgets(CardPtr cp)1101 saveWidgets (CardPtr cp)
1102 {
1103 CardWidgetsPtr cwp = &cp->cw->ct.cw;	/* ptr to widget ids */
1104 CardDataPtr cdp = cp->cd;		/* ptr to real card data */
1105 String str;
1106 int i;
1107 
1108    XtVaGetValues(cwp->mainkey, XtNstring, &str, NULL);
1109    if ((cdp->mainkey = glbNewString(str)) == NULL)
1110       return(ERR_NOMALLOC);
1111    if (cdp->cardtype == MAX_BIBTEX_TYPES){
1112      XtVaGetValues(cwp->owntype, XtNstring, &str, NULL);
1113      if ((cdp->cardtypestr = glbNewString(str)) == NULL)
1114         return(ERR_NOMALLOC);
1115      }
1116    for (i=0; i<max_fields;i++) {
1117       if ((i!=nannote) && isstandardfield(i, cdp->cardtype)){
1118          XtVaGetValues(cwp->wfield[2*i+1], XtNstring, &str, NULL);
1119          if ((cdp->field[i] = glbNewString(str)) == NULL)
1120             return(ERR_NOMALLOC);
1121       }
1122    }
1123    return(OK);
1124 }
1125 
1126