/*********************************************************************/
/*  bibView: Administration of BibTeX-Databases                      */
/*           (Verwaltung von BibTeX-Literaturdatenbanken)            */
/*                                                                   */
/*  Module:  ctl_prt.c                                               */
/*                                                                   */
/*             Print Control                                         */
/*             - Print BibTeX File                                   */
/*             - Print list                                          */
/*                                                                   */
/*  Author:  Holger Martin,  martinh@informatik.tu-muenchen.de       */
/*           Peter M. Urban, urban@informatik.tu-muenchen.de         */
/*                                                                   */
/*  History:                                                         */
/*    18.02.92  HM   created                                         */
/*    05.26.92       Version 1.0 released                            */
/*                                                                   */
/*  Copyright 1992 TU MUENCHEN                                       */
/*    See ./Copyright for complete rights and liability information. */
/*                                                                   */
/*********************************************************************/

#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/Box.h>
#include "FileNom.h"
#include "bibview.h"


/* macros and definitions */
/* ---------------------- */
#define MAXTEX  20000

#define BIB      0
#define LIST     1

/* imported global variables */
/* ------------------------- */
extern XtAppContext app_context;
extern Widget topLevel, mainMenu, desktop;
extern Pixmap questPixmap;
extern char *latexHeader, *latexFooter;
extern int max_linelen, max_fields;

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

char *style_file;


/* local function prototypes */
/* ------------------------- */
static void getFilename (BibPtr bp, int type);
static void cancelGetFname (Widget w, XtPointer clientData, XtPointer callData);
static void getFnameListOk (Widget w, XtPointer clientData, XtPointer callData);
static void getFnameBibOk (Widget w, XtPointer clientData, XtPointer callData);

static void getListFilename (BibPtr bp);
static void cancelListGetFname (Widget w, XtPointer clientData, XtPointer callData);
static void getListFnameOk (Widget w, XtPointer clientData, XtPointer callData);


static Errcode printBegDoc (FILE *fp, String fname);
static Errcode printEndDoc (FILE *fp);
static Errcode printList      (FILE *fp, BibPtr bp, int type);
static Errcode printBibList   (FILE *fp, BibPtr bp, int type);
static Errcode printCard   (FILE *fp, CardDataPtr cd);
static void WriteLineToArray(char *inh);


/* local global variables */
/* ---------------------- */
static char texline[MAXTEX];


/*********************************************************************/
/* cprPrintBibCmd:                                                   */
/*    Callback function for command print in main menu               */
/*********************************************************************/
void 
cprPrintBibCmd (Widget widget, XtPointer clientData, XtPointer callData)
{
Errcode status;

   if ((status = guwSelectBib("printHead", cprPrintBib)) != OK)
      guwWarning(status);
}


/*********************************************************************/
/* cprPrintCmd:                                                      */
/*    Callback function for command print in main menu               */
/*********************************************************************/
void 
cprPrintCmd (Widget widget, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;
Errcode status;

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


/*********************************************************************/
/* cprPrintBib:                                                      */
/*    Callback function for command print in main menu               */
/*********************************************************************/
Errcode
cprPrintBib (BibPtr bp)
{
   getFilename(bp, BIB);
   return(OK);
}


/*********************************************************************/
/* cprPrintListCmd:                                                  */
/*    Callback function for command print in list window             */
/*********************************************************************/
void 
cprPrintListCmd(Widget widget, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr) clientData;
   
   getFilename(bp, LIST);
}


/*********************************************************************/
/* cprPrintList:                                                     */
/*    Print a list of cards to file in LaTeX format                  */
/*********************************************************************/
Errcode
cprPrintList (BibPtr bp, String fname, int type)
{
FILE *fp;
Errcode status;

   /* make .bak file of original */
   if (fname == NULL)
      return(ERR_NO_OPEN_FILE);
   if (cotBackupBeforeSave())
      glbMakeBackup(fname);

   if ((fp = fopen(fname, "w")) == NULL) 
      return(ERR_NO_OPEN_FILE);
   if (latexHeader != NULL) {
      fprintf(fp,"%s\n", latexHeader);
   }
   else {
     if ((status = printBegDoc(fp, bp->filename)) != OK) {
	fclose(fp);
	return(status);
     }
   }

   if (cotPrintAsBib()){
      if ((status = printBibList(fp, bp, type)) != OK) {
         fclose(fp);
         return(status);
         }
      }
   else
      if ((status = printList(fp, bp, type)) != OK) {
         fclose(fp);
         return(status);
         }

   if (latexFooter != NULL) {
      fprintf(fp,"%s\n", latexFooter);
   }
   else {
     if ((status = printEndDoc(fp)) != OK) {
	fclose(fp);
	return(status);
     }
   }

   fclose(fp);
   return(OK);
}


/*********************************************************************/
/* cprSaveListCmd:                                                   */
/*    Callback function for command save in list window              */
/*********************************************************************/
void 
cprSaveListCmd(Widget widget, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;

   getListFilename(bp);
}

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

/*********************************************************************/
/* getFilename:                                                      */
/*    Opens dialogbox for user to enter name of file                 */
/*********************************************************************/
static void
getFilename (BibPtr bp, int type)
{
static Widget fsbShell, fsbBox, fsbDialog;
Position dx, dy, x, y;

   XtVaGetValues(desktop,
                 XtNx, &dx,
                 XtNy, &dy, NULL);
   XtTranslateCoords(desktop,
                     (Position)dx + SUBWIN_MARGIN,
                     (Position)dy + SUBWIN_MARGIN,
                     &x, &y);

   fsbShell  = XtVaCreatePopupShell("fileSelectBoxShell",
                 topLevelShellWidgetClass, desktop,
                 XtNx, x, XtNy, y, NULL);
   fsbBox    = XtVaCreateManagedWidget("fileSelectBox",
		 boxWidgetClass, fsbShell, NULL);
               XtVaCreateManagedWidget("filePrintHead",
		 labelWidgetClass, fsbBox, 
		 XtNborderWidth, 0, NULL);
   fsbDialog = XtVaCreateManagedWidget("fileSelectBox",
                 fileNominatorWidgetClass, fsbBox, 
		 XtNborderWidth, 0, NULL);
   
   XtAddCallback(fsbDialog, XtNcancelCallback, cancelGetFname, fsbShell);
   if (type == LIST)
      XtAddCallback(fsbDialog, XtNselectCallback, getFnameListOk, bp);
   else    
      XtAddCallback(fsbDialog, XtNselectCallback, getFnameBibOk, bp);

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


/*********************************************************************/
/* getListFilename:                                                  */
/*    Opens dialogbox for user to enter name of file                 */
/*********************************************************************/
static void
getListFilename (BibPtr bp)
{
static Widget fsbShell, fsbBox, fsbDialog;
Position dx, dy, x, y;

   XtVaGetValues(desktop,
                 XtNx, &dx,
                 XtNy, &dy, NULL);
   XtTranslateCoords(desktop,
                     (Position)dx + SUBWIN_MARGIN,
                     (Position)dy + SUBWIN_MARGIN,
                     &x, &y);

   fsbShell  = XtVaCreatePopupShell("fileSelectBoxShell",
                 topLevelShellWidgetClass, desktop,
                 XtNx, x, XtNy, y, NULL);
   fsbBox    = XtVaCreateManagedWidget("fileSelectBox",
		 boxWidgetClass, fsbShell, NULL);
               XtVaCreateManagedWidget("fileListSaveHead",
		 labelWidgetClass, fsbBox, 
		 XtNborderWidth, 0, NULL);
   fsbDialog = XtVaCreateManagedWidget("fileSelectBox",
                 fileNominatorWidgetClass, fsbBox, 
		 XtNborderWidth, 0, NULL);


   XtAddCallback(fsbDialog, XtNcancelCallback, cancelListGetFname, fsbShell);
   XtAddCallback(fsbDialog, XtNselectCallback, getListFnameOk, (XtPointer)bp);

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


/*********************************************************************/
/* cancelGetFname:                                                   */
/*    Callback function for CANCEL button in filename box            */
/*********************************************************************/
static void
cancelGetFname (Widget w, XtPointer clientData, XtPointer callData)
{
Widget shell = (Widget)clientData;

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


/*********************************************************************/
/* cancelListGetFname:                                               */
/*    Callback function for CANCEL button in filename box            */
/*********************************************************************/
static void
cancelListGetFname (Widget w, XtPointer clientData, XtPointer callData)
{
Widget shell = (Widget)clientData;

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


/*********************************************************************/
/* getFnameListOk:                                                   */
/*    Callback function for OK button in filename box                */
/*********************************************************************/
static void
getFnameListOk (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr) clientData;
String prtName;
int status;

   /* get filename and rename windows */
   prtName = (String)FileNominatorGetFullFileName(w);
   if (prtName == NULL){
      XtPopdown(XtParent(XtParent(w)));
      XtSetSensitive(mainMenu, TRUE);
      gubSetSensitive(NULL, TRUE);
      guwError(NO_VALID_FILENAME);
      return;
      }

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

   /* write out printfile to disk */
   if ((status = cprPrintList(bp, prtName, LIST)) != OK)
      guwError(status);

}


/*********************************************************************/
/* getFnameBibOk:                                                    */
/*    Callback function for OK button in filename box                */
/*********************************************************************/
static void
getFnameBibOk (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr) clientData;
String prtName;
int status;

   /* get filename and rename windows */
   prtName = (String)FileNominatorGetFullFileName(w);
   if (prtName == NULL){
      XtPopdown(XtParent(XtParent(w)));
      XtSetSensitive(mainMenu, TRUE);
      gubSetSensitive(NULL, TRUE);
      guwError(NO_VALID_FILENAME);
      return;
      }


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

   /* write out printfile to disk */
   if ((status = cprPrintList(bp, prtName, BIB)) != OK)
      guwError(status);

}



/*********************************************************************/
/* getListFnameOk:                                                   */
/*    Callback function for OK button in filename box                */
/*********************************************************************/
static void
getListFnameOk (Widget w, XtPointer clientData, XtPointer callData)
{
BibPtr bp = (BibPtr)clientData;
char tmpfile[MAX_FILEPATHLEN];
String prtName, prtPath;
int status;

   /* get filename and rename windows */
   prtName = (String)FileNominatorGetFileName(w);
   if (prtName == NULL){
      XtPopdown(XtParent(XtParent(w)));
      XtSetSensitive(mainMenu, TRUE);
      gubSetSensitive(NULL, TRUE);
      guwError(NO_VALID_FILENAME);
      return;
      }

   prtPath = (String)FileNominatorGetFullFileName(w);
   if (prtPath == NULL){
      XtPopdown(XtParent(XtParent(w)));
      XtSetSensitive(mainMenu, TRUE);
      gubSetSensitive(NULL, TRUE);
      guwError(NO_VALID_FILENAME);
      return;
      }

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

   /* make .bak file of original */
   strcpy(tmpfile, prtPath);
   if (glbCheckPath(prtPath, prtName) != OK){
      XtPopdown(XtParent(XtParent(w)));
      XtSetSensitive(mainMenu, TRUE);
      gubSetSensitive(NULL, TRUE);
      guwError(BIF_EWRITE);
      return;
      }

   if (cotBackupBeforeSave())
      glbMakeBackup(prtPath);

   /* write out printfile to disk */
   if ((status = bifFileListWrite(bp, bp->lw->cardLst, prtPath)) != OK)
      guwError(status);
}

/*********************************************************************/
/* printBegDoc:                                                      */
/*    Print begin of LaTeX file                                      */
/*********************************************************************/
static Errcode
printBegDoc (FILE *fp, String fname)
{
#ifdef GERMAN
   fprintf(fp, "\\documentstyle[german]{article}\n");
   fprintf(fp, "\\begin{document}\n");
   fprintf(fp, "{\\large \\bf Inhalt der Datei %s -- \\today}\n", fname);
#else
   fprintf(fp, "\\documentstyle{article}\n");
   fprintf(fp, "\\begin{document}\n");
   fprintf(fp, "{\\large \\bf Content of file %s -- \\today}\n", fname);
#endif
   return(OK);
}


/*********************************************************************/
/* printEndDoc:                                                      */
/*    Print end   of LaTeX file                                      */
/*********************************************************************/
static Errcode
printEndDoc (FILE *fp)
{
   fprintf(fp, "\\end{document}\n");
   return(OK);
}


/*********************************************************************/
/* printBibList:                                                     */
/*    Print list of cards to file                                    */
/*********************************************************************/
static Errcode
printBibList (FILE *fp, BibPtr bp, int type)
{
CardListNode *list;
char tmpfile[MAX_FILEPATHLEN];
int j, zaehler;
   
   strcpy(tmpfile, bp->filepath);
   for (j=0; tmpfile[j] != '\0'; j++){
     if (tmpfile[j] == '.'){
      if (!strcmp(&tmpfile[j], ".bib")){
	 tmpfile[j]='\0';
	 break;
         }
      }
     }
   
   fprintf(fp, "\\nocite{");
   if (type==LIST){
     zaehler = 8;
     list = bp->lw->cardLst;
     if (list != NULL){
      zaehler += strlen(list->data->mainkey);
      fprintf(fp, "%s", list->data->mainkey),
      list = list->next; 
      while (list != NULL) {                 
	 if (zaehler + strlen(list->data->mainkey) + 2 > max_linelen){
            fprintf(fp, "}\n\\nocite{%s", list->data->mainkey);
            zaehler=8+strlen(list->data->mainkey);
            list = list->next; 
            }		
	 else {
	    zaehler += strlen(list->data->mainkey) + 1;
            fprintf(fp, ",%s", list->data->mainkey);
            list = list->next; 
	    }
         }
      }
      fprintf(fp, "}\n\n");
     }
   else
      fprintf(fp, "*}\n\n");
   fprintf(fp, "\\bibliographystyle{%s}\n\n", style_file),
   fprintf(fp, "\\bibliography{%s}\n\n", tmpfile);
   return(OK);
}


/*********************************************************************/
/* printList:                                                        */
/*    Print list of cards to file                                    */
/*********************************************************************/
static Errcode
printList (FILE *fp, BibPtr bp, int type)
{
CardListNode *list, *hlist;
CardListNode *cl = NULL;
Errcode status;

   if (type == BIB){
      /* make list of all cards in src bib */
      if ((status = dbtBuildList(bp->treeIdx,  &cl, bp->sortedby)) != DBT_OK) {
         return(status);
      }
      list = cl;
   }
   else
     list = bp->lw->cardLst;
  
   hlist = list;
   fprintf(fp, "\\begin{enumerate}\n"); 
   while (hlist != NULL) {                 
      if ((status = printCard(fp, hlist->data)) != OK)
	 return(status); 

      hlist = hlist->next; 
   }  
   fprintf(fp, "\\end{enumerate}\n"); 
   if (type == BIB){
      if ((status = dbtCardListDelete(&list)) != OK)
	 return(status);  
      list = NULL;
      }
   return(OK);
}


/*********************************************************************/
/* printCard:                                                        */
/*    Print card to file                                             */
/*********************************************************************/
static Errcode
printCard (FILE *fp, CardDataPtr cd)
{
UserFld *hufield;
FieldName i;


   fprintf(fp, "\\item %s  %s\n", cd->cardtypestr, cd->mainkey); 
   fprintf(fp, "\\begin{tabbing}\n");
   fprintf(fp, "AAAAAAAAAAAAAAAAAAAA\\= \\kill\n");
   
   for (i=0; i<max_fields; i++){
      if (!glbIsStringEmpty(cd->field[i])) {
         WriteLineToArray(cd->field[i]);
         fprintf(fp, "\\bf %s \\>  \\parbox[t]{25em}{%s} \\\\ \n",
		 glbFldToName(i), texline);
      }
   }

/*   print userdefined fields  */
   hufield = cd->ufield;
   while (hufield != NULL) {
      WriteLineToArray(hufield->fldData);
      fprintf(fp, "\\bf %s \\>  \\parbox[t]{25em}{%s}  \\\\ \n",
		   hufield->fldName, texline);
      hufield = hufield->next;
   }  
   fprintf(fp, "\\end{tabbing}\n");
   return(OK);
}


/*********************************************************************/
/* writeLineToArray:                                                 */
/*                                                                   */
/*********************************************************************/
static void 
WriteLineToArray (char *inh)
{
int idx;
int makro = 2;    /* weder Makro, noch String */
char *tmp;

  idx = 0;
  while (*inh == ' ' || *inh == '\t' || *inh == '\n') {
    texline[idx] = *inh; 
    inh++;
    idx++;
  }
  if (*inh == '@') {
    texline[idx] = ' '; 
    makro = 1;
  }
  else {
    texline[idx] = '{'; 
    idx++;
    texline[idx] = *inh; 
    makro = 0;
  }
  idx++;
  inh++;
  while (*inh != '\0') {
    if (*inh == '@') {
      tmp = inh;
      tmp++;
      if (*tmp == '#') {                  /* KONKATENATION */
        if (makro == 1) {
                                          /* letzter Teil war ein MAKRO */ 
          texline[idx] = ' '; idx++; 
          texline[idx] = '\\'; idx++; 
          texline[idx] = '#'; idx++; 
          texline[idx] = ' '; idx++; 
          tmp++;
          while (*tmp == ' ' || *tmp == '\t' || *tmp == '\n') {
            texline[idx] = *tmp; 
            idx++;
            tmp++;
          }
          if (*tmp == '@') {              /* naechster Teil ist ein MAKRO */
            texline[idx] = ' '; idx++; 
            makro = 1;
          }
          else {
            texline[idx] = '{'; idx++; 
            texline[idx] = *tmp; 
            idx++;
                                          /* naechster Teil ist ein STRING */
            makro = 0;
          }
        }
        else if (makro == 0) {
                                          /* letzter Teil war ein STRING */ 
          texline[idx] = '}'; idx++; 
          texline[idx] = ' '; idx++; 
          texline[idx] = '\\'; idx++; 
          texline[idx] = '#'; idx++; 
          texline[idx] = ' '; idx++; 
          tmp++;
          while (*tmp == ' ' || *tmp == '\t' || *tmp == '\n') {
            texline[idx] = *tmp; 
            idx++;
            tmp++;
          }
          if (*tmp == '@') {              /* naechster Teil ist ein MAKRO */
            texline[idx] = ' '; idx++; 
            makro = 1;
          }
          else {
            texline[idx] = '{'; idx++; 
            texline[idx] = *tmp; 
            idx++;
            makro = 0;
          }
        }  /* else if makro == 0 */
        inh = tmp;
      }
      else {                              /* AFFE nicht schreiben */
        texline[idx] = ' '; idx++; 
        makro = 1;
      }
    }      /* if @ */
    else {
      texline[idx] = *inh; 
      idx++;
    }
    inh++;
  }  /* while */
  if (makro == 0) {
    texline[idx] = '}'; idx++; 
  }
  texline[idx] = ','; idx++; 
  texline[idx] = ' '; idx++; 
  texline[idx] = '\0'; idx++; 
}

