/*********************************************************************/
/*  bibView: Administration of BibTeX-Databases                      */
/*           (Verwaltung von BibTeX-Literaturdatenbanken)            */
/*                                                                   */
/*  Module:  gui_card.c                                              */
/*                                                                   */
/*             GUI: Card Windows                                     */
/*             -                                                     */
/*                                                                   */
/*  Author:  Holger Martin,  martinh@informatik.tu-muenchen.de       */
/*           Peter M. Urban, urban@informatik.tu-muenchen.de         */
/*                                                                   */
/*  History:                                                         */
/*    12.19.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 <X11/Xaw/Text.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Viewport.h>
#include "bibview.h"


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


/* local function prototypes */
/* ------------------------- */
static Errcode calcNextCardWinPos (Widget desk, int n, Position *x, Position *y);
static Errcode calcNextCardIconPos (Widget desk, int curIcon, Position *x, Position *y);
static void createWidgets (BibPtr bp, CardPtr cp);
static Errcode saveWidgets (CardPtr cp);

/* external global variables */
/* ------------------------- */
extern Widget topLevel, desktop;
extern Pixmap crdIconPixmap;
extern UserDefFld userDefFlds[];

extern int max_fields;
extern char sort_field[];


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


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


/*********************************************************************/
/* gucOpenCardWin:                                                   */
/*    Creates an instance of a card window                           */
/*********************************************************************/
Errcode
gucOpenCardWin (BibPtr bp, CardPtr cp, Boolean isNew)
{
CardWinPtr cw;

   /* allocate memory for new element of window list */
   if ((cw = (CardWinPtr) XtCalloc(1, sizeof(CardWin))) == NULL) {
      /* error-handling is done in control modules */
      return(ERR_NOMALLOC);
   }

   /* allocate memory for text buffers of card widget */
   /* not needed: handled by widget */

   /* build label of new shell */
   cw->shellName = (String)XtCalloc(strlen(bp->filename) +
	             strlen(cp->cd->cardtypestr)+4,
	                               sizeof(char)); 
   if (cw->shellName == NULL) {
      XtFree((char *)cw);
      return(ERR_NOMALLOC);
   }
   sprintf(cw->shellName, "%s: %s", bp->filename, 
				    cp->cd->cardtypestr);

   /* create popup shell for new file */
   cw->cardShell = XtVaCreatePopupShell("cardShell",
                     topLevelShellWidgetClass, topLevel,
                     XtNtransientFor, bp->bw->bibShell,
                     XtNwindowGroup, XtWindow(bp->bw->bibShell), 
                     XtNtitle, cw->shellName,
                     XtNiconPixmap, crdIconPixmap,
                     XtNiconName, cp->cd->mainkey, NULL);

   /* create widgets for card */
   cw->cardWin = XtVaCreateManagedWidget("cardWin",
		   panedWidgetClass, cw->cardShell, NULL);
   cw->cmdBox = XtVaCreateManagedWidget("commandBox", 
		  boxWidgetClass, cw->cardWin, NULL);
   cw->duplicate = XtVaCreateManagedWidget("duplicate", 
		 menuButtonWidgetClass, cw->cmdBox, NULL);
   cw->userDef = XtVaCreateManagedWidget("userDef", 
	           commandWidgetClass, cw->cmdBox, NULL);
   cw->annote = XtVaCreateManagedWidget("annote", 
	           commandWidgetClass, cw->cmdBox, NULL);
   cw->delete = XtVaCreateManagedWidget("delete", 
	          commandWidgetClass, cw->cmdBox, NULL);
   cw->change = XtVaCreateManagedWidget("save", 
         	  commandWidgetClass, cw->cmdBox, NULL);
   cw->copy = XtVaCreateManagedWidget("copy", 
	        commandWidgetClass, cw->cmdBox, NULL);
   cw->close = XtVaCreateManagedWidget("quit", 
	         commandWidgetClass, cw->cmdBox, NULL);

   glbCreateTypeMenu("duplicateMenu", cw->duplicate, 
		     &cw->duplicateMenu, ccdDuplicateCardCmd, (XtPointer) cp);
   XtAddCallback(cw->close, XtNcallback, ccdCloseCardCmd, (XtPointer)cp);
   XtAddCallback(cw->userDef, XtNcallback, ccdUserdataCmd, (XtPointer)cp);
   XtAddCallback(cw->delete, XtNcallback, ccdDeleteCardCmd, (XtPointer)cp);
   XtAddCallback(cw->annote, XtNcallback, ccdAnnoteCardCmd, (XtPointer)cp);
   if (isNew)
      XtAddCallback(cw->change, XtNcallback, ccdSaveCardCmd, (XtPointer)cp);
   else
      XtAddCallback(cw->change, XtNcallback, ccdChangeCardCmd, (XtPointer)cp);
   XtAddCallback(cw->copy, XtNcallback, ccdCopyCardCmd, (XtPointer)cp);

   /* create card window desktop */
   cw->cardDesk = XtVaCreateManagedWidget("carddesk",  
	            formWidgetClass, cw->cardWin);
   cw->cardFlds = XtVaCreateManagedWidget(glbTypeToName(cp->cd->cardtype), 
	            formWidgetClass, cw->cardDesk, NULL);

   /* set card pointer to new struct, new window created */
   cp->cw = cw;
   cp->aw = NULL;
   bp->noOfCardWins++;

   /* Position window near bibliography desktop */
   calcNextCardWinPos(bp->bw->bibdesk, bp->nextCardPos, &cw->winX, &cw->winY);
   XtVaSetValues(cw->cardShell,
                 XtNx, cw->winX,
                 XtNy, cw->winY, NULL);

   /* if option on, set icon position on desktop */
   if (cotIconizeOnDesktop()) {
      calcNextCardIconPos(bp->bw->bibdesk, bp->noOfCardWins, &cw->iconX, &cw->iconY);
      XtVaSetValues(cw->cardShell,
                    XtNiconX, cw->iconX,
                    XtNiconY, cw->iconY, NULL);
   }
   bp->nextCardPos++;

   /* build only widgets for specific card type */
   createWidgets(bp, cp);

   XtPopup(cw->cardShell, XtGrabNone);
   return(OK);
}


/*********************************************************************/
/* gucStdFldsChanged:                                                */
/*    Returns true, if user made changes to standard BibTeX fields   */
/*********************************************************************/
#define WidgetChanged(w) (XawAsciiSourceChanged(XawTextGetSource(w)))
Boolean
gucAuthorChanged (CardPtr cp)
{
CardWidgetsPtr cwp = &cp->cw->ct.cw;	/* ptr to widget ids */
int field;
 
  field = cp->cd->sorted;

  if (field != -1){
    if (sort_field[field] == 'n'){
      if (cwp->wfield[2*field+1] && WidgetChanged(cwp->wfield[2*field+1])) 
         return(TRUE);
      else
         return(FALSE);
      }
    else
      return(FALSE);
    }
  else
      return(FALSE);
}

Boolean
gucStdFldsChanged (CardPtr cp)
{
CardWidgetsPtr cwp = &cp->cw->ct.cw;	/* ptr to widget ids */
int i;

   if (cwp->mainkey && WidgetChanged(cwp->mainkey)) 
      return(TRUE);
   if (cwp->annote && (cp->cd->annoteChanged==TRUE))
      return(TRUE);
   for (i=0; i<max_fields; i++) {  
      if (i!=nannote)
         if (cwp->wfield[2*i+1] && WidgetChanged(cwp->wfield[2*i+1])) 
            return(TRUE);
   }
   return(FALSE);
}
#undef WidgetChanged


/*********************************************************************/
/* gucSaveCardData:                                                  */
/*    Save data from card window into new card                       */
/*********************************************************************/
Errcode
gucSaveCardData (CardPtr cp)
{
Errcode status;
CardType type;
UserFld *ufield;
String annotefield, typestr, authorsort;

   /* save reusable data */
   type = cp->cd->cardtype;
   typestr = glbNewString(cp->cd->cardtypestr);
   if ((status = gucSaveUserFields(cp)) != OK)
      return(status);
   ufield = cp->cd->ufield;
   cp->cd->ufield = NULL;

   if (gucAuthorChanged(cp)){
      XtFree(cp->cd->authorsort);
      cp->cd->authorsort=NULL;
      }

   annotefield = glbNewString(cp->cd->field[nannote]);
   authorsort =  glbNewString(cp->cd->authorsort);

   /* save annote field */
   /* delete old card data */
   dbtDeleteCard(&cp->cd);

   if ((status = dbtMakeCard(&cp->cd)) != DBT_OK) 
      return(status);

   /* build only widgets for specific card type */
   cp->cd->cardtype = type;
   cp->cd->ufield = ufield;
   cp->cd->cardtypestr = typestr;
   cp->cd->field[nannote] = annotefield;
   cp->cd->authorsort = authorsort;
   if ((status = saveWidgets(cp)) != OK)
      return(status);

   return(OK);
}


/*********************************************************************/
/* gucCloseCardCmd:                                                  */
/*    Callback for quit command in card window                       */
/*********************************************************************/
void
gucCloseCardCmd (Widget w, XtPointer clientData, XtPointer callData)
{
CardPtr cp = (CardPtr)clientData;
Errcode status;

   if ((status = gucCloseCardWin(cp)) != OK) {
      guwError(status);
   }
}


/*********************************************************************/
/* gucCloseCardWin:                                                  */
/*    Close card window                                              */
/*********************************************************************/
Errcode
gucCloseCardWin (CardPtr cp)
{
BibPtr bp = (BibPtr)cp->bp;
  
   if (cp->aw != NULL) {
       XtPopdown(cp->aw->annoteShell);
       XtFree((char *)cp->aw->shellName);
       XtFree((char *)cp->aw);
       cp->aw = NULL;
       }
   XtPopdown(cp->cw->cardShell);
   bp->noOfCardWins--;
   if (glbLastCardListEl(bp) == cp)
      bp->nextCardPos -= 1;
   XtFree((char *)cp->cw->shellName);
   XtFree((char *)cp->cw);
   glbDelCardListEl(bp, cp);
   if (glbFirstCardListEl(bp) == NULL)
      bp->nextCardPos = 0;
   return(OK);
}


/*********************************************************************/
/* gucOpenUserFields:                                                */
/*    Extend editable fields in current window with user fields      */
/*********************************************************************/
Errcode
gucOpenUserFields (CardPtr cp)
{
Widget card = cp->cw->cardDesk;		/* parent widget */
UserFld **root, *cup;                   /* ptr to user fields */
UserFld *up1, *up;
UserFld newUserFld;
ListNode *udp;
Widget prevWidget;
Boolean found;
Dimension dheight, min;
Errcode status;
int i;

   root = &cp->cd->ufield;
   cup = cp->cd->ufield;

   XawPanedSetRefigureMode(cp->cw->cardWin, False);

   /* save current dimensions of shell for later resize */
   XtVaGetValues(cp->cw->cardShell,
		 XtNheight, &cp->cw->height,
		 XtNwidth,  &cp->cw->width,
		 XtNborderWidth, &cp->cw->borderWidth, NULL);

   /* keep old desktop same size while user defs are shown */
   XtVaGetValues(card, 
		 XtNheight, &dheight, 
		 XtNmin, &min, NULL);
   XtVaSetValues(card,
		 XtNmin, dheight, NULL);

   /* create neu widgets for user def fields */
   cp->cw->usrFldVport = XtVaCreateWidget("userFldVport",
			   viewportWidgetClass, cp->cw->cardWin, 
			   XtNshowGrip, True, 
			   XtNallowVert, True, NULL);
   cp->cw->usrFldDesk  = XtVaCreateWidget("userFldDesk",
			   formWidgetClass, cp->cw->usrFldVport, 
			   NULL);
   cp->cw->usrFldHead  = XtVaCreateManagedWidget("userFldHead",
			   labelWidgetClass, cp->cw->usrFldDesk,
			   XtNleft, XtChainLeft,
			   XtNtop, XtChainTop, NULL);
   prevWidget = cp->cw->usrFldHead;

   /* open already existing fields first */
   up = cup;
   while (up != NULL) {
      up->fldLabel =    XtVaCreateManagedWidget("userFieldL", 
			     asciiTextWidgetClass, cp->cw->usrFldDesk, 
			     XtNstring, up->fldName,
			     XtNfromVert, prevWidget,
			     XtNleft, XtChainLeft, NULL);
      up->fldText  =    XtVaCreateManagedWidget("userField", 
			     asciiTextWidgetClass, cp->cw->usrFldDesk, 
			     XtNstring, up->fldData,
			     XtNfromVert, prevWidget,
			     XtNfromHoriz, up->fldLabel, NULL);
      XtAddCallback(XawTextGetSource(up->fldText),
		    XtNcallback, ccdSetChangeFlag, (XtPointer)cp);
      prevWidget = up->fldText;
      up = up->next;
   } /* endwhile */
      
   /* open default fields not opened already */
   udp = userDefFlds[cp->cd->cardtype];
   while (udp != NULL) {
      up1 = cup;
      found = FALSE;
      while (up1 != NULL) {
	 if (strcmp(up1->fldName, udp->data) == 0) {
	    found = TRUE;
	    break;
	 }
	 up1 = up1->next;
      }

      if (!found) {
         newUserFld.fldName = glbNewString(udp->data);
         newUserFld.fldData = "";
	 newUserFld.fldLabel = XtVaCreateManagedWidget("userFieldL", 
			     asciiTextWidgetClass, cp->cw->usrFldDesk, 
			     XtNstring, udp->data,
			     XtNfromVert, prevWidget,
			     XtNleft, XtChainLeft, NULL);
	 newUserFld.fldText  = XtVaCreateManagedWidget("userField", 
			     asciiTextWidgetClass, cp->cw->usrFldDesk, 
			     XtNstring, newUserFld.fldData,
			     XtNfromVert, prevWidget,
			     XtNfromHoriz, newUserFld.fldLabel, NULL);
	 XtAddCallback(XawTextGetSource(newUserFld.fldText),
		       XtNcallback, ccdSetChangeFlag, (XtPointer)cp);
         prevWidget = newUserFld.fldText;
         if ((status = dbtAppendUserFld(root, &newUserFld)) != DBT_OK)
	    guwError(status);
      }
      udp = udp->next;
   }

   /* open MAX_NEW_USER_FLDS fields for any input */
   for (i = 0; i < MAX_NEW_USERDEF_FLDS; i++) {
      newUserFld.fldName = "";
      newUserFld.fldData = "";
      newUserFld.fldLabel = XtVaCreateManagedWidget("userFieldL", 
			  asciiTextWidgetClass, cp->cw->usrFldDesk, 
			  XtNstring, newUserFld.fldName,
			  XtNfromVert, prevWidget,
			  XtNleft, XtChainLeft, NULL);
      newUserFld.fldText  = XtVaCreateManagedWidget("userField", 
			  asciiTextWidgetClass, cp->cw->usrFldDesk, 
			  XtNstring, newUserFld.fldData,
			  XtNfromVert, prevWidget,
			  XtNfromHoriz, newUserFld.fldLabel, NULL);
      XtAddCallback(XawTextGetSource(newUserFld.fldText),
		    XtNcallback, ccdSetChangeFlag, (XtPointer)cp);
      prevWidget = newUserFld.fldText;
      if ((status = dbtAppendUserFld(root, &newUserFld)) != DBT_OK)
	 guwError(status);
   }

   XtManageChild(cp->cw->usrFldDesk);
   XtManageChild(cp->cw->usrFldVport);
   XawPanedSetRefigureMode(cp->cw->cardWin, True);
   cp->extended = TRUE;
   return(OK);
}

/*********************************************************************/
/* gucCloseUserFields:                                               */
/*    Remove user fields from card window                            */
/*********************************************************************/
Errcode
gucCloseUserFields (CardPtr cp)
{
CardWinPtr cw = cp->cw;
Errcode status;

   if ((status = gucSaveUserFields(cp)) != OK)
      guwError(status);

   cp->extended = FALSE;
   XtDestroyWidget(cw->usrFldVport);
   XtResizeWidget(cw->cardShell, cw->width, cw->height, cw->borderWidth);
   return(OK);
}


/*********************************************************************/
/* gucSaveUserFields:                                                */
/*    Save data in user fields to card (temp or real)                */
/*********************************************************************/
Errcode
gucSaveUserFields (CardPtr cp)
{
UserFld newFld, *tfield = NULL, *up;
Errcode status;
String str;

   if (!cp->extended)
      return(OK);

   up = cp->cd->ufield;
   while (up != NULL) {
      XtVaGetValues(up->fldLabel, XtNstring, &str, NULL);
      if (glbIsStringEmpty(str)) {
	 up = up->next;
	 continue;
      }
      newFld.fldLabel = up->fldLabel;
      newFld.fldText = up->fldText;
      if ((newFld.fldName = glbNewString(str)) == NULL)
	 return(ERR_NOMALLOC);
      XtVaGetValues(up->fldText, XtNstring, &str, NULL);
      if ((newFld.fldData = glbNewString(str)) == NULL)
	 return(ERR_NOMALLOC);
      if ((status = dbtAppendUserFld(&tfield, &newFld)) != DBT_OK)
	 guwError(status);
      up = up->next;
   } /* endwhile */

   dbtDeleteAllUserFld(&cp->cd->ufield);
   cp->cd->ufield = tfield;
   return(OK);
}


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

   if ((status = gucCascade(bp)) != OK) 
      guwError(status);
   if ((status = gueCascade(bp)) != OK)
      guwError(status);
   if ((status = gulCascade(bp)) != OK)
      guwError(status);
}


/*********************************************************************/
/* gucCascade:                                                       */
/*    Layout card windows of a bibliography                          */
/*********************************************************************/
Errcode
gucCascade (BibPtr bp)
{
   gucSetWindowCoords(bp, FALSE);
   if (cotIconizeOnDesktop())
      gucSetIconCoords(bp, FALSE);
   return(OK);
}


/*********************************************************************/
/* gucSetWindowCoords:                                               */
/*    Set positions of card windows                                  */
/*********************************************************************/
Errcode
gucSetWindowCoords (BibPtr bp, Boolean calcOnly)
{
CardPtr cp;
int i;

   cp = glbFirstCardListEl(bp);
   for (i = 1; i <= bp->noOfCardWins; i++) {
      calcNextCardWinPos(bp->bw->bibdesk, i, &cp->cw->winX, &cp->cw->winY);
      if (!calcOnly) {
         XtVaSetValues(cp->cw->cardShell,
                       XtNx, cp->cw->winX,
		       XtNy, cp->cw->winY, NULL);
	 if (XtIsRealized(cp->cw->cardShell)) {
	    XRaiseWindow(XtDisplay(cp->cw->cardShell),
			 XtWindow(cp->cw->cardShell));
	 }
      } /* endif */
      cp = glbNextCardListEl(bp, cp);
   } /* endfor */

   return(OK);
}


/*********************************************************************/
/* gucSetIconCoords:                                                 */
/*    Set positions of card window icons                             */
/*********************************************************************/
Errcode
gucSetIconCoords (BibPtr bp, Boolean calcOnly)
{
CardPtr cp;
int curIcon = 0;
 
   if ((cp = glbFirstCardListEl(bp)) != NULL) {
      calcNextCardIconPos(bp->bw->bibdesk, curIcon, &cp->cw->iconX, &cp->cw->iconY);
      if (!calcOnly) {
         XtVaSetValues(cp->cw->cardShell,
		       XtNiconX, cp->cw->iconX,
		       XtNiconY, cp->cw->iconY, NULL);
      }

      while ((cp = glbNextCardListEl(bp, cp)) != NULL) {
         curIcon++;
         calcNextCardIconPos(bp->bw->bibdesk, curIcon, &cp->cw->iconX, &cp->cw->iconY);
         if (!calcOnly) {
            XtVaSetValues(cp->cw->cardShell,
		          XtNiconX, cp->cw->iconX,
		          XtNiconY, cp->cw->iconY, NULL);
         }
      }  /* endwhile */
   } /* endif */

   return(OK);
}


/*********************************************************************/
/* gucUnsetIconCoords:                                               */
/*    Unset positions of card window icons                           */
/*********************************************************************/
Errcode
gucUnsetIconCoords (BibPtr bp, Boolean calcOnly)
{
CardPtr cp;
 
   if ((cp = glbFirstCardListEl(bp)) != NULL) {
      cp->cw->iconX = cp->cw->iconY = -1;
      if (!calcOnly) {
         XtVaSetValues(cp->cw->cardShell,
		       XtNiconX, cp->cw->iconX,
		       XtNiconY, cp->cw->iconY, NULL);
      }

      while ((cp = glbNextCardListEl(bp, cp)) != NULL) {
         cp->cw->iconX = cp->cw->iconY = -1;
         if (!calcOnly) {
            XtVaSetValues(cp->cw->cardShell,
		          XtNiconX, cp->cw->iconX,
		          XtNiconY, cp->cw->iconY, NULL);
         }
      }  /* endwhile */
   } /* endif */

   return(OK);
}



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

/*********************************************************************/
/* calcNextCardWinPos:                                               */
/*    Calculate coords of next card window                           */
/*********************************************************************/
static Errcode
calcNextCardWinPos (Widget desk, int n, Position *x, Position *y)
{
Dimension dwidth, dheight;

   XtVaGetValues(desk,
		 XtNwidth, &dwidth,
		 XtNheight, &dheight, NULL);
   XtTranslateCoords(desk,
		     (n+2) * (Position)CARDWIN_MARGIN,
		     (n+2) * (Position)CARDWIN_MARGIN,
		     x, y);

   return(OK);
}


/*********************************************************************/
/* calcNextCardIconPos:                                              */
/*    Calculate coords of next card window icon                      */
/*********************************************************************/
static Errcode
calcNextCardIconPos (Widget desk, int curIcon, Position *x, Position *y)
{
Position curX, curY;

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


/*********************************************************************/
/* createWidgets:                                                    */
/*    Creates widgets depending on card type                         */
/*********************************************************************/
static void
createWidgets(BibPtr bp, CardPtr cp)
{
CardWidgetsPtr cwp = &cp->cw->ct.cw;	/* ptr to widget ids */
CardDataPtr cdp = cp->cd;		/* ptr to real card data */
Widget card = cp->cw->cardFlds;		/* parent widget */
Widget aktwidget;
FieldName i;

   cdp->annoteChanged = FALSE;
   cwp->mainkeyL = 	XtVaCreateManagedWidget("fieldLabel", 
	           	  labelWidgetClass, card, 
		   	  XtNtop, XtChainTop, 
			  XtNlabel, "BibTeX-Key",
		   	  XtNleft, XtChainLeft, NULL);
   cwp->mainkey = 	XtVaCreateManagedWidget("field", 
	          	  asciiTextWidgetClass, card, 
		  	  XtNstring, cdp->mainkey,
		  	  XtNtop, XtChainTop, 
		  	  XtNfromHoriz, cwp->mainkeyL, 
			  NULL);
   aktwidget = cwp->mainkey;
   if (cdp->cardtype == MAX_BIBTEX_TYPES){
      cwp->owntypeL = 	XtVaCreateManagedWidget("fieldLabel", 
   	           	  labelWidgetClass, card, 
		    	  XtNfromVert, aktwidget, 
		    	  XtNlabel, "BibTeX-Type", 
		   	  XtNleft, XtChainLeft, NULL);
      cwp->owntype = 	XtVaCreateManagedWidget("field", 
	          	  asciiTextWidgetClass, card, 
		  	  XtNstring, cdp->cardtypestr, 
		    	  XtNfromVert, aktwidget, 
		  	  XtNfromHoriz, cwp->owntypeL, NULL);
      aktwidget = cwp->owntype;
   }
   for (i=0; i<max_fields; i++) {
      if ((i!=nannote) && isstandardfield(i, cdp->cardtype)){
         cwp->wfield[2*i] = 	XtVaCreateManagedWidget("fieldLabel", 
	           	  labelWidgetClass, card, 
			  XtNlabel, glbFldToName(i),
		    	  XtNfromVert, aktwidget, 
		   	  XtNleft, XtChainLeft, NULL);
         cwp->wfield[2*i+1] = 	XtVaCreateManagedWidget("field",
	          	  asciiTextWidgetClass, card, 
		  	  XtNstring, cdp->field[i], 
		    	  XtNfromVert, aktwidget, 
		  	  XtNfromHoriz, cwp->wfield[2*i], NULL);
      if (isrequiredfield(i, cdp->cardtype))
         XtVaSetValues(cwp->wfield[2*i+1], XtNborderWidth, 3, NULL);
      aktwidget = cwp->wfield[2*i+1];
      }
   }
}


/*********************************************************************/
/* saveWidgets:                                                      */
/*    Saves data from widget to new card                             */
/*********************************************************************/
static Errcode
saveWidgets (CardPtr cp)
{
CardWidgetsPtr cwp = &cp->cw->ct.cw;	/* ptr to widget ids */
CardDataPtr cdp = cp->cd;		/* ptr to real card data */
String str;
int i;

   XtVaGetValues(cwp->mainkey, XtNstring, &str, NULL);
   if ((cdp->mainkey = glbNewString(str)) == NULL)
      return(ERR_NOMALLOC);
   if (cdp->cardtype == MAX_BIBTEX_TYPES){
     XtVaGetValues(cwp->owntype, XtNstring, &str, NULL);
     if ((cdp->cardtypestr = glbNewString(str)) == NULL)
        return(ERR_NOMALLOC);
     }
   for (i=0; i<max_fields;i++) {
      if ((i!=nannote) && isstandardfield(i, cdp->cardtype)){
         XtVaGetValues(cwp->wfield[2*i+1], XtNstring, &str, NULL);
         if ((cdp->field[i] = glbNewString(str)) == NULL)
            return(ERR_NOMALLOC);
      }
   }
   return(OK);
}

