/* File: biblio.c * Author: Richard Durbin * Copyright (C) J Thierry-Mieg and R Durbin, 1998 * ------------------------------------------------------------------- * Acedb is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt * ------------------------------------------------------------------- * This file is part of the ACEDB genome database package, written by * Richard Durbin (Sanger Centre, UK) rd@sanger.ac.uk, and * Jean Thierry-Mieg (CRBM du CNRS, France) mieg@crbm.cnrs-mop.fr * * Description: Displays any bibliographical information * for current object. * Exported functions: * biblioKey() * biblioKeySet() * HISTORY: * Last edited: May 6 10:36 2003 (edgrif) * Created: Tue Dec 15 16:55:20 1998 (fw) *------------------------------------------------------------------- */ /* $Id: biblio.c,v 1.48 2003/05/06 13:13:37 edgrif Exp $ */ #include "acedb.h" #include "aceio.h" #include "lex.h" #include "a.h" #include "whooks/sysclass.h" #include "whooks/classes.h" #include "whooks/systags.h" #include "whooks/tags.h" #include "query.h" #include "bs.h" #include "biblio.h" #include "pick.h" #include "client.h" #ifndef NON_GRAPHIC #include "graph.h" #include "display.h" /************************************************************/ static magic_t BIBLIO_MAGIC = "BIBLIO_MAGIC"; typedef struct BiblioStruct { magic_t *magic; /* == &BIBLIO_MAGIC */ KEYSET bibSet ; Stack s ; char *cp ; int zero, curr, width, numberRef, nbDiscard, format; int discardUp ; float pos ; BOOL showAbstracts, showNewNumbers ; Array discard, abstract, abstExists, newNumber, sortNumber, author, unDiscard ; } *BIBLIO ; static void biblioReDraw (void) ; static void biblioDoReDraw (BIBLIO biblio) ; static void biblioDraw80 (BIBLIO biblio) ; static void biblioPrepare (BIBLIO biblio) ; static void biblioFormatDump (ACEOUT biblio_out, BIBLIO biblio) ; static void formatNormal (void) ; static void formatCell (void) ; static void formatGenDev (void) ; static int nbBox = 5 ; /* nombre de boxes par reference */ static BOOL discarding = FALSE ; #define graphBoxBox(_box) { \ float _x1, _y1, _x2, _y2 ; \ graphBoxDim (_box, &_x1, &_y1, &_x2, &_y2) ; \ graphRectangle (_x1 - 0.4, _y1 - 0.1, _x2 + 0.4, _y2 + 0.1) ; \ } #define BIBLIOGET(name) BIBLIO biblio ; \ if (!graphAssFind (&BIBLIO_MAGIC, &biblio)) \ messcrash ("%s() could not find BIBLIO on graph",name) ; \ if (!biblio) \ messcrash ("%s() received NULL BIBLIO pointer",name) ; \ if (biblio->magic != &BIBLIO_MAGIC) \ messcrash ("%s received non-magic BIBLIO pointer",name) /*************************************************************************/ static void biblioDestroy(void) { BIBLIOGET ("biblioDestroy") ; keySetDestroy (biblio->bibSet) ; stackDestroy (biblio->s) ; arrayDestroy (biblio->discard) ; arrayDestroy (biblio->abstract) ; arrayDestroy (biblio->abstExists) ; arrayDestroy (biblio->newNumber) ; arrayDestroy (biblio->sortNumber) ; arrayDestroy (biblio->author) ; arrayDestroy (biblio->unDiscard) ; messfree (biblio->cp) ; biblio->magic = 0 ; messfree (biblio) ; return; } /* biblioDestroy */ /*************************************************************************/ static void biblioAbstracts (void) { int i ; BIBLIOGET ("BiblioAbstracts") ; if (!graphCheckEditors (graphActive(), 0)) return ; biblio->showAbstracts = !biblio->showAbstracts ; /* toggle */ if (biblio->showAbstracts) for (i = 0; i < arrayMax (biblio->bibSet); i++) array (biblio->abstract, i, char) = 1 ; else for (i = 0; i < arrayMax (biblio->bibSet); i++) array (biblio->abstract, i, char) = 0 ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; return; } /* biblioAbstracts */ /*************************************************************************/ static void biblioPrint80 (void) { Graph old = graphActive(); BIBLIOGET ("BiblioPrint80") ; if (!graphCheckEditors (graphActive(), 0)) return ; if (!biblio->bibSet || keySetMax(biblio->bibSet) == 0) { messout ("Nothing to export, this biblio is empty, , sorry") ; return ; } biblioDraw80(biblio); graphActivate (old); biblioReDraw(); return; } /* biblioPrint80 */ /*************************************************************************/ /* mhmp 06 mai 97 */ static void biblioPostBuffer (int ii) { int i = 0 ; char *cp, *cq, cc ; BIBLIOGET ("biblioPostBuffer") ; cp = cq = stackText(biblio->s, 0) ; while (i <= ii) { while (*cq && *cq != '\n') cq++ ; cp++ ; if (*cp == '_') i++ ; cp = ++cq ; } cp ++ ; while (TRUE) { while (*cq && *cq != '\n') cq++ ; cq++ ; if (*cq == '_' || !*cq) { cc = *cq ; *cq = 0 ; graphPostBuffer (cp) ; *cq++ = cc ; break ; } } return; } /* biblioPostBuffer */ /*************************************************************************/ static void biblioPick (int k, double x_unused, double y_unused, int modifier_unused) { int b, bb, i, j, ii = -1 ; float x1, y1, x2, y2 ; BIBLIOGET ("BiblioPick") ; if (!graphCheckEditors (graphActive(), 0)) return ; graphWhere (&x1, &y1, &x2, &y2); bb = k - biblio->zero ; b = bb / nbBox ; if (bb >= 0 && b < arrayMax (biblio->bibSet)) { j = -1 ; i = ii = -1 ; while (j != b) { i = i + 1 ; ii = array (biblio->sortNumber, i, int) -1 ; if (ii != -1 && !array (biblio->discard, ii, char)) j = j + 1 ; } biblio->pos = (y2 + y1)/2 ; if (!(bb % nbBox)) { biblioPostBuffer (b) ; if (bb == biblio->curr && bb >= 0 && ii != -1) display (keySet(biblio->bibSet, ii), 0, 0) ; else { if (biblio->curr > -1) { graphBoxDraw (biblio->zero + biblio->curr, BLACK, WHITE) ; graphBoxDraw (biblio->zero + biblio->curr + 2, BLACK, WHITE) ; } biblio->curr = bb ; graphBoxDraw (biblio->zero + biblio->curr, BLACK, YELLOW) ; if (ii != -1 && !array (biblio->abstExists, ii, char)) graphBoxDraw (biblio->zero + biblio->curr + 2, BLACK, YELLOW) ; } } else if (!((bb - 1) % nbBox)) { array (biblio->discard, ii, char) = 1 ; array (biblio->unDiscard, biblio->nbDiscard, int) = ii ; biblio->nbDiscard ++ ; discarding = TRUE ; biblio->numberRef = biblio->numberRef - 1 ; if (bb < biblio->curr) { biblio->curr = biblio->curr - nbBox ; biblio->discardUp ++ ; } biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; } else if (!((bb - 2) % nbBox)) if (array (biblio->abstExists, ii, char)) { array (biblio->abstract, ii, char) = !array (biblio->abstract, ii, char) ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; } } else { if (biblio->curr > -1) { graphBoxDraw (biblio->zero + biblio->curr, BLACK, WHITE) ; graphBoxDraw (biblio->zero + biblio->curr + 2, BLACK, WHITE) ; } biblio->curr = -1 ; } return; } /* biblioPick */ /*************************************************************************/ static void biblioSort (void) { int i, j, rmin, aux ; float min ; BIBLIOGET ("biblioSort") ; if (!graphCheckEditors (graphActive(), 0)) return ; for (i = 0; i < arrayMax (biblio->bibSet) - 1; i++) { min = array (biblio->newNumber, i, float); rmin = i ; for (j = i + 1; j < arrayMax (biblio->bibSet); j++) if (min > array (biblio->newNumber, j, float)) { min = array (biblio->newNumber, j, float) ; rmin = j ; } array (biblio->newNumber, rmin, float) = array (biblio->newNumber, i, float) ; array (biblio->newNumber, i, float) = min ; aux = array (biblio->sortNumber, i, int) ; array (biblio->sortNumber, i, int) = array (biblio->sortNumber, rmin, int) ; array (biblio->sortNumber, rmin, int) = aux ; } biblio->curr = -1 ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; return; } /* biblioSort */ /*************************************************************************/ static void biblioSortAuthor (void) { int i, j, rmin, aux ; char *a1, *a2 ; float auxf ; BIBLIOGET ("biblioSortAuthor") ; if (!graphCheckEditors (graphActive(), 0)) return ; for (i = 0; i < arrayMax (biblio->bibSet) - 1; i++) { a1 = array (biblio->author, i, char *) ; rmin = i ; for (j = i + 1; j < arrayMax (biblio->bibSet); j++) { a2 = array (biblio->author, j, char *) ; if (strcmp (a1, a2)>0) { a1 = a2 ; rmin = j ; } } array (biblio->author, rmin, char *) = array (biblio->author, i, char *) ; array (biblio->author, i, char *) = a1 ; auxf = array (biblio->newNumber, i, float) ; array (biblio->newNumber, i, float) = array (biblio->newNumber, rmin, float) ; array (biblio->newNumber, rmin, float) = auxf ; aux = array (biblio->sortNumber, i, int) ; array (biblio->sortNumber, i, int) = array (biblio->sortNumber, rmin, int) ; array (biblio->sortNumber, rmin, int) = aux ; } biblio->curr = -1 ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; return; } /* biblioSortAuthor */ /*************************************************************************/ static void biblioUnDiscard (void) { int i, ii ; BIBLIOGET ("biblioUnDiscard") ; if (!graphCheckEditors (graphActive(), 0)) return ; if (biblio->nbDiscard) { i = array (biblio->unDiscard, biblio->nbDiscard - 1, int) ; array (biblio->discard, i, char) = 0 ; biblio->nbDiscard -- ; biblio->numberRef ++ ; ii = 0 ; while (i + 1 != array(biblio->sortNumber, ii, int)) { ii++ ; } if (( ii-biblio->discardUp) * nbBox <= biblio->curr) { biblio->curr = biblio->curr + nbBox ; biblio->discardUp -- ; } } biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; return; } /* biblioUnDiscard */ /**********************************************************************/ static void biblioNewNumbers (void) { BIBLIOGET ("biblioNewNumbers") ; biblio->showNewNumbers = !biblio->showNewNumbers ; if (!graphCheckEditors (graphActive(), 0)) return ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; return; } /* biblioNewNumbers */ /**********************************************************************/ static void biblioRenumber (void) { int i, ii, jj ; BIBLIOGET ("biblioRenumber") ; jj = 0 ; for (i = 0; i < arrayMax (biblio->bibSet); i++) { ii = array(biblio->sortNumber, i, int) - 1 ; if(!array(biblio->discard, ii, char)) jj = jj+ 1 ; array (biblio->newNumber, i, float) = jj ; } biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; return; } /* biblioRenumber */ /************************************************************************/ static MENUOPT formatMenu[] = { { formatNormal, "Normal" }, { formatCell, "Cell" }, { formatGenDev, "Gen.& Dev."}, { 0,0} }; /***********************************************************************/ static void biblioFormat (void) { BIBLIOGET ("biblioFormat") ; biblio->format = -1 ; biblioDoReDraw (biblio) ; graphMenu(formatMenu) ; graphButtons (formatMenu, 17.5, 4.3, biblio->width) ; return; } /* biblioFormat */ /***********************************************************************/ static MENUOPT biblioMenu[] = { { graphDestroy,"Quit"}, { help,"Help"}, { biblioPrint80, "Print"}, { biblioAbstracts, "Abstract on/off"}, { biblioSortAuthor, "Sort by author"}, { biblioRenumber, "Renumber 1 ... n"}, { biblioSort, "Sort by number"}, { biblioUnDiscard, "UnDiscard"}, { biblioNewNumbers, "New numbers"}, { biblioFormat, "Format"}, {0,0} }; /***********************************************************************/ static void formatNormal (void) { BIBLIOGET ("formatNormal") ; biblio->format = 0 ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; graphMenu (biblioMenu) ; return; } /* formatNormal */ /**********************************************************************/ static void formatCell (void) { BIBLIOGET ("formatCell") ; biblio->format = 1 ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; graphMenu (biblioMenu) ; return; } /* formatCell */ /*************************************************************************/ static void formatGenDev (void) { BIBLIOGET ("formatGenDev") ; biblio->format = 2 ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; graphMenu (biblioMenu) ; return; } /* formatGenDev */ /*************************************************************************/ static void biblioDraw80 (BIBLIO biblio) { int box, n = 0, line = 0 ; char *cp, *cq, cc ; ACEOUT biblio_out; biblio->s = stackReCreate (biblio->s, 3000) ; biblio_out = aceOutCreateToStack (biblio->s, 0); biblio->width = 80; biblioFormatDump (biblio_out, biblio) ; aceOutDestroy (biblio_out); graphClear () ; graphText("Topic : ",1.,4.3) ; graphTextEntry(biblio->cp, 68, 9.,4.3,0) ; cp = cq = stackText(biblio->s, 0) ; n = 0 ; graphBoxStart () ; line = 6 ; while (TRUE) { while (*cq && *cq != '\n') cq++ ; cc = *cq ; *cq = 0 ; if (*cp == '_') { cp++ ; graphBoxEnd() ; box = graphBoxStart () ; if (!n++) biblio->zero = box ; } graphText(cp, 4, line++) ; if (!cc) break ; *cq++ = cc ; cp = cq ; } graphBoxEnd () ; graphTextBounds (80, line) ; graphRedraw () ; graphPrint () ; return; } /* biblioDraw80 */ static void biblioReDraw (void) { BIBLIOGET ("BiblioReDraw") ; biblioDoReDraw (biblio) ; } /**********************************************************/ static void biblioDoReDraw (BIBLIO biblio) { int box, i, ii, j, b, n = 0, line = 0 ; char *cp, *cq, cc ; graphClear () ; graphGoto ( 1, biblio->pos) ; graphText("Topic : ",1.,5.7) ; graphTextEntry(biblio->cp, 68, 9.,5.7,0) ; cp = cq = stackText(biblio->s, 0) ; n = 0 ; graphBoxStart () ; line = 7 ; while (TRUE) { while (*cq && *cq != '\n') cq++ ; cc = *cq ; *cq = 0 ; if (*cp == '_') { cp++ ; graphBoxEnd() ; box = graphBoxStart () ; if (!n++) biblio->zero = box ; box = graphBoxStart () ; graphText ("Discard", 30, line) ; graphBoxBox (box) ; graphBoxEnd () ; box = graphBoxStart () ; b = (box - biblio->zero) / nbBox ; j = -1 ; i = ii = -1 ; while (j != b) { i = i + 1 ; ii = array(biblio->sortNumber, i, int) - 1 ; if (!array (biblio->discard, ii, char)) j = j + 1 ; } if ( array (biblio->abstExists, ii, char)) { if (ii != -1 && !array (biblio->abstract, ii, char)) graphText ("Abstract on ", 40, line) ; else graphText ("Abstract off", 40, line) ; graphBoxBox (box) ; } else graphText (" ", 40, line) ; graphBoxEnd (); if (biblio->showNewNumbers) graphFloatEditor ("", arrp(biblio->newNumber, i, float), 55, line, 0) ; else { box = graphBoxStart() ; graphBoxEnd() ; box = graphBoxStart() ; graphBoxEnd() ; } } graphText(cp, 4, line++) ; if (!cc) break ; *cq++ = cc ; cp = cq ; /* after the \n */ } graphBoxEnd () ; if (!discarding) graphTextBounds (-1, line) ; else discarding = FALSE ; graphRedraw () ; if (biblio->curr < 0 || biblio->curr >= arrayMax(biblio->bibSet) * nbBox || biblio->zero + biblio->curr > n * nbBox) biblio->curr = -1 ; else { graphBoxDraw (biblio->zero + biblio->curr, BLACK, YELLOW) ; b = (biblio->curr) / nbBox ; j = -1 ; i = ii = -1 ; while (j != b) { i = i + 1 ; ii = array (biblio->sortNumber, i, int) -1 ; if (!array (biblio->discard, ii, char)) j = j + 1 ; } if (ii != -1 && !array (biblio->abstExists, ii, char)) graphBoxDraw (biblio->zero + biblio->curr + 2, BLACK, YELLOW) ; } box = graphButtons (biblioMenu, 10.0,1.0, biblio->width) ; if (biblio->showAbstracts) graphBoxDraw (box + 3, BLACK, LIGHTBLUE) ; if (biblio->nbDiscard) graphBoxDraw (box + 7, BLACK, LIGHTBLUE) ; if (biblio->showNewNumbers) graphBoxDraw (box + 8, BLACK, LIGHTBLUE) ; switch (biblio->format) { case -1: graphText (" ", 17.5, 4.4) ; break ; case 0: graphText ("Normal", 17.5, 4.4) ; break ; case 1: graphText ("Cell", 17.5, 4.4) ; break ; case 2: graphText ("GENES & DEVELOPMENT", 17.5, 4.4) ; break ; } return; } /* biblioDoReDraw */ /***********************************************************************/ static void biblioPrepare (BIBLIO biblio) { ACEOUT biblio_out; biblio->s = stackReCreate (biblio->s, 3000) ; biblio_out = aceOutCreateToStack (biblio->s, 0); biblio->width = 80; /* guess the size of the biblio graph * its real size is configured * in displays.wrm */ biblioFormatDump (biblio_out, biblio) ; aceOutDestroy (biblio_out); return; } /* biblioPrepare */ /***********************************************************************/ static void cellAuthor (Array aut, int j, char *author) { char *cc ; int i, lastSpace, k = 0, nbDot = 0, nbMinus = 0 ; cc = name (keySet (aut, j)) ; lastSpace = strlen(cc) - 1 ; /* cherche le blanc derriere le nom*/ for (i = 0; i < strlen(cc); i++) if (cc[i] == ' ') lastSpace = i ; /* compte . et - dans les initiales*/ for (i = lastSpace + 1; i < strlen(cc); i++) if (cc[i] == '-') nbMinus++ ; else if (cc[i] == '.') nbDot++ ; memset (author, 0, 200) ; /* initiales ? */ if (strlen (cc) - lastSpace > 4 + nbDot + nbMinus) lastSpace = strlen(cc) - 1 ; /* le nom */ for (i = 0; i <= lastSpace; i++) author[k++] = cc[i] ; if (author[k-1] == ' ') k = k -1 ; if (lastSpace != strlen(cc) - 1) { author[k++] = ',' ; author[k++] = ' ' ; } /* les initiales */ for (i=lastSpace + 1; inumberRef ; #endif aceOutxy (biblio_out, messprintf("Found %d ref", mmax),1,1); aut = arrayReCreate (aut, 20, BSunit) ; line = 3 ; for (i = 0; i < max; i++) { abst = 0 ; ii = i ; #ifndef NON_GRAPHIC ii = array (biblio->sortNumber, i, int) - 1 ; array( biblio->author, i, char *) = "zzzzzz" ; if (array (biblio->discard, ii, char)) continue ; #endif line++ ; ref=arr(bibSet,ii,KEY) ; j = i ; #ifndef NON_GRAPHIC j = array (biblio->newNumber, i, float) - 1; #endif aceOutxy (biblio_out, messprintf("_%d) ", j + 1), 0, line++) ; aceOutPrint (biblio_out, "%s", name(ref)) ; Ref = bsCreate(ref) ; if (!Ref) continue ; stackClear (buf) ; pushText (buf, "") ; if (bsFindTag (Ref, _Author) && bsFlatten (Ref, 1, aut)) { stackClear (buf) ; for (j=0 ; j < arrayMax(aut) ; j++) { cellAuthor (aut, j, author) ; catText (buf, messprintf ("%s", author)) ; if (j == arrayMax(aut) - 2) catText (buf, ", and ") ; else if (j != arrayMax (aut) - 1) catText (buf, ", ") ; #ifndef NON_GRAPHIC if (!j) array( biblio->author, i, char *) = name (keySet (aut, j)) ; #endif } } if (bsGetData (Ref,_Year,_Int,&ix)) catText (buf, messprintf (" (%d). ", ix)) ; if(bsGetKey (Ref,_Title,&text)) catText (buf, messprintf ("%s ", name(text))) ; if (bsGetKey (Ref, _Journal, &kk)) catText (buf, name (kk)) ; if (bsGetData (Ref, _Volume, _Int, &ix)) { catText (buf, messprintf (" %d",ix)) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) catText (buf, messprintf (" %s,", cp)) ; } else if (bsGetData (Ref, _Volume, _Text, &cp)) { catText (buf, messprintf (" %s,", cp)) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) catText (buf, messprintf (" %s", cp)) ; } if (bsGetData (Ref, _Page, _Int, &ix)) { catText (buf, messprintf (" %d",ix)) ; while (bsGetData (Ref,_bsRight,_Int,&ix)) catText (buf, messprintf ("-%d", ix)) ; catText (buf, ".") ; } else if (bsGetData (Ref,_Page, _Text, &cp)) { catText (buf, messprintf (" %s", cp)) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) catText (buf, messprintf ("-%s",cp)) ; catText (buf, ".") ; } uLinesText (stackText(buf,0),width - 4) ; while ((cp = uNextLine(stackText(buf,0)))) aceOutxy (biblio_out, cp, 4, line++); #ifndef NON_GRAPHIC if (showAbstracts || array (biblio->abstExists, ii, char)) { if (!array (biblio->abstract, ii, char)) { bsDestroy (Ref) ; continue ; } abst = 1; } #endif if (showAbstracts || abst) { if (bsGetKey (Ref, _Abstract, &text) && (abs = stackGet (text))) { stackClear (buf) ; stackCursor (abs, 0) ; nbLines = 0 ; nbEmpty = 0 ; while ((cp = stackNextText (abs))) { catText (buf, cp) ; catText (buf, "\n") ; nbLines++ ; if (strlen(cp)) nbEmpty = 0 ; else nbEmpty++ ; } stackDestroy (abs) ; uLinesText (stackText(buf,0),width - 6) ; for ( iabst = 1 ; iabst <= nbLines - nbEmpty ; iabst++) { cp = uNextLine(stackText(buf,0)) ; aceOutxy (biblio_out, cp, 6, line++); } } } bsDestroy(Ref) ; } arrayDestroy (aut); stackDestroy (buf) ; return; } /* biblioDumpCell */ /****************************************/ static void genDevAuthor (Array aut, int j, char *author) { char *cc ; int i, lastSpace , k = 0, nbDot = 0, nbMinus = 0 ; cc = name (keySet (aut, j)) ; lastSpace = strlen(cc) - 1 ; /* cherche le blanc derriere le nom */ for (i=0; i 4 + nbDot + nbMinus) lastSpace = strlen(cc) - 1 ; memset (author, 0, 200) ; /* initiales*/ for (i=lastSpace + 1; inumberRef ; #endif aceOutxy (biblio_out, messprintf("Found %d ref", mmax), 1, 1); aut = arrayReCreate (aut, 20, BSunit) ; line = 3 ; for (i = 0; i < max ; i++) { abst = 0 ; ii = i ; #ifndef NON_GRAPHIC ii = array (biblio->sortNumber, i, int) - 1 ; array( biblio->author, i, char *) = "zzzzzz" ; if (array (biblio->discard, ii, char)) continue ; #endif line++ ; ref=arr(bibSet,ii,KEY) ; j = i ; #ifndef NON_GRAPHIC j = array (biblio->newNumber, i, float) - 1; #endif aceOutxy (biblio_out, messprintf("_%d) ", j + 1), 0, line++) ; aceOutPrint (biblio_out, "%s", name(ref)) ; Ref = bsCreate(ref) ; if (!Ref) continue ; stackClear (buf) ; pushText (buf, "") ; if (bsFindTag (Ref, _Author) && bsFlatten (Ref, 1, aut)) { stackClear (buf) ; for (j=0 ; j < arrayMax(aut) ; j++) { if (!j) cellAuthor (aut, j, author) ; else genDevAuthor (aut, j, author) ; catText (buf, messprintf ("%s", author)) ; if (j == arrayMax(aut) - 2) { if (arrayMax (aut) > 2) catText (buf, ", and ") ; else catText (buf, " and ") ; } else { if (j != arrayMax (aut) - 1) catText (buf, ", ") ; } #ifndef NON_GRAPHIC if (!j) array( biblio->author, i, char *) = name (keySet (aut, j)) ; #endif /* !NON_GRAPHIC */ } if (arrayMax(aut) > 1) catText (buf, ".") ; } if (bsGetData (Ref,_Year,_Int,&ix)) catText (buf, messprintf (" %d. ", ix)) ; if(bsGetKey (Ref,_Title,&text)) catText (buf, messprintf ("%s ", name(text))) ; if (bsGetKey (Ref, _Journal, &kk)) catText (buf, name (kk)) ; if (bsGetData (Ref, _Volume, _Int, &ix)) { catText (buf, messprintf (" %d",ix)) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) catText (buf, messprintf (" %s", cp)) ; } else if (bsGetData (Ref, _Volume, _Text, &cp)) { catText (buf, messprintf (" %s:", cp)) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) catText (buf, messprintf (" %s", cp)) ; } if (bsGetData (Ref, _Page, _Int, &ix)) { catText (buf, messprintf (" %d:",ix)) ; while (bsGetData (Ref,_bsRight,_Int,&ix)) catText (buf, messprintf ("-%d", ix)) ; catText (buf, ".") ; } else if (bsGetData (Ref,_Page, _Text, &cp)) { catText (buf, messprintf (" %s", cp)) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) catText (buf, messprintf ("-%s",cp)) ; catText (buf, ".") ; } uLinesText (stackText(buf,0),width - 4) ; while ((cp = uNextLine(stackText(buf,0)))) aceOutxy (biblio_out, cp,4,line++); #ifndef NON_GRAPHIC if (showAbstracts || array (biblio->abstExists, ii, char)) { if (!array (biblio->abstract, ii, char)) { bsDestroy (Ref) ; continue ; } abst = 1; } #endif if (showAbstracts || abst) { if (bsGetKey (Ref, _Abstract, &text) && (abs = stackGet (text))) { stackClear (buf) ; stackCursor (abs, 0) ; nbLines = 0 ; nbEmpty = 0 ; while ((cp = stackNextText (abs))) { catText (buf, cp) ; catText (buf, "\n") ; nbLines++ ; if (strlen(cp)) nbEmpty = 0 ; else nbEmpty++ ; } stackDestroy (abs) ; uLinesText (stackText(buf,0),width - 6) ; for ( iabst = 1 ; iabst <= nbLines - nbEmpty ; iabst++) { cp = uNextLine(stackText(buf,0)) ; aceOutxy (biblio_out, cp, 6, line++); } } } bsDestroy(Ref) ; } arrayDestroy (aut); stackDestroy (buf) ; return; } /* biblioDumpGenDev */ /*************************************************************************/ static void biblioDisplay (char *title, KEYSET bibSet) { BIBLIO biblio ; int i ; OBJ obj ; KEY text ; if (!title || !keySetExists (bibSet)) messcrash ("biblioDisplay - received NULL title or " "invalid KEYSET bibSet") ; if (!keySetMax (bibSet)) { messout ("Sorry, no associated biblio") ; return ; } biblio = (BIBLIO) messalloc (sizeof(struct BiblioStruct)) ; biblio->magic = &BIBLIO_MAGIC ; biblio->bibSet = bibSet ; biblio->s = stackCreate (3000) ; biblio->curr = -1 ; biblio->nbDiscard = 0 ; biblio->discardUp = 0 ; biblio->format = -1 ; biblio->numberRef = arrayMax(biblio->bibSet) ; biblio->cp = messalloc(70) ; biblio->discard = arrayCreate (arrayMax(biblio->bibSet), char) ; biblio->abstract = arrayCreate (arrayMax(biblio->bibSet), char) ; biblio->abstExists = arrayCreate (arrayMax(biblio->bibSet), char) ; biblio->newNumber = arrayCreate (arrayMax(biblio->bibSet), float) ; biblio->sortNumber = arrayCreate (arrayMax(biblio->bibSet), int) ; biblio->author = arrayCreate (arrayMax(biblio->bibSet), char *) ; biblio->unDiscard = arrayCreate (arrayMax(biblio->bibSet), int) ; for (i = 0; i< arrayMax(biblio->bibSet); i++) { array (biblio->newNumber, i, float) = i + 1 ; array (biblio->sortNumber, i, int) = i + 1 ; if ((obj = bsCreate (arr (bibSet, i, KEY)))) { if (bsGetKey (obj, _Abstract, &text) && iskey(text)==2) array (biblio->abstExists, i, char) = 1 ; bsDestroy (obj) ; } } strncpy(biblio->cp, title, 70); biblio->cp[70-1] = '\0'; displayCreate ("DtBiblio") ; graphRetitle (title) ; graphMenu (biblioMenu) ; graphRegister (DESTROY, biblioDestroy) ; graphRegister (PICK, biblioPick) ; graphRegister (RESIZE, biblioReDraw) ; graphAssociate (&BIBLIO_MAGIC, biblio) ; biblioPrepare (biblio) ; biblioDoReDraw (biblio) ; return; } /* biblioDisplay */ /***********************************************************************/ static void biblioFormatDump (ACEOUT biblio_out, BIBLIO biblio) { switch (biblio->format) { case -1 : case 0 : biblioDump (biblio_out, biblio->bibSet, biblio->showAbstracts, biblio->width) ; break ; case 1 : biblioDumpCell (biblio_out, biblio->bibSet, biblio->showAbstracts, biblio->width) ; break ; case 2 : biblioDumpGenDev (biblio_out, biblio->bibSet, biblio->showAbstracts, biblio->width) ; break ; } return; } /* biblioFormatDump */ /***********************************************************************/ /*************** Public Graphic display functions *********************/ void biblioKeySet (char *title, KEYSET s) { char *cr; cr = strnew (title ? title : "Biblio", 0); biblioDisplay (cr, biblioFollow (s)) ; messfree (cr) ; return; } /* biblioKeySet */ /***********/ void biblioKey (KEY key) { KEYSET set = keySetCreate() ; keySet(set,0) = key ; biblioKeySet (messprintf("Bibliography attached to %s", name(key)), set) ; } /* biblioKey */ #endif /* NON_GRAPHIC */ /***********************************************************************/ /*************** Public elementary functions *************************/ static BOOL biblioKeyPossible2 (KEY key, BOOL doOpen) { KEYSET ks = 0 ; int i ; KEY *kp ; BOOL found = FALSE ; if (!key || !class(key) || (pickType(key) != 'B')) return FALSE ; else if (class(key) == _VPaper || class(key) == _VLongText) return TRUE ; else if (!bsIsClassInClass (class(key), _VPaper)) return FALSE ; if (!doOpen) return TRUE ; ks = bsKeySet(key) ; if (!ks) return FALSE ; kp = arrp(ks, 0, KEY) - 1 ; i = keySetMax(ks) ; while (kp++, i--) if (class(*kp) == _VPaper) { found = TRUE ; break ; } keySetDestroy (ks) ; return found ; } /* biblioKeyPossible2 */ BOOL biblioKeyPossible (KEY key) { return biblioKeyPossible2 (key, TRUE) ; } BOOL biblioPossible (KEYSET s) { KEY key = 0 ; int i , dx, max ; if (!keySetExists (s) || !(max = keySetMax (s))) return FALSE ; /* try just on class names, very cheap */ dx = max/60 ; if (!dx) dx = 1 ; for (i = 0; i < max ; i += dx) { key = keySet(s, i) ; if (class(key) == _VPaper || class(key) == _VLongText) return TRUE ; } /* try again, opening just the models */ dx = max/10 ; if (!dx) dx = 1 ; for (i = 0; i < max ; i += dx) { key = keySet(s, i) ; if (biblioKeyPossible2 (key, FALSE)) goto maybe ; } return FALSE ; maybe: if ((TRUE || externalServer) && max > 1 ) return TRUE ; /* do not wait on server, or probably on any machine */ /* try again, possibly opening objects */ dx = max/10 ; if (!dx) dx = 1 ; for (i = 0; i < max ; i += dx) { key = keySet(s, i) ; if (biblioKeyPossible2 (key, TRUE)) return TRUE ; } return FALSE ; } /* biblioPossible */ KEYSET biblioFollow (KEYSET s) { KEYSET bib1, bib2, bib3, biba ; bib1 = query (s, "NEIGHBOURS") ; /* was {>Paper} $| {>Reference} $| {>Quoted_in}") ; */ bib2 = keySetOR (s, bib1) ; bib3 = query (bib2, "CLASS Paper") ; biba = keySetAlphaHeap(bib3, keySetMax(bib3)) ; keySetDestroy(bib1); keySetDestroy(bib2); keySetDestroy(bib3); return biba ; } /* biblioFollow */ /***********************************************************************/ void biblioDump (ACEOUT biblio_out, KEYSET bibSet, BOOL showAbstracts, int width) { static Array aut = 0 ; int i, j, max, mmax, line, ix, ii, nbLines, nbEmpty, iabst ; char *cp, abst ; KEY text, kk; OBJ Ref ; KEY ref ; Stack abs, buf = stackCreate (3000) ; #ifndef NON_GRAPHIC /* do not use BIBLIOGET here, cause it is used by gifaceserver */ BIBLIO biblio = 0 ; if (graphActive()) { if (!graphAssFind (&BIBLIO_MAGIC, &biblio)) biblio = 0 ; if (biblio && biblio->magic != &BIBLIO_MAGIC) biblio = 0 ; } #endif if (width <= 0) width = 1 << 24 ; if (!keySetExists(bibSet) || !(max = keySetMax(bibSet))) { aceOutPrint (biblio_out, "Sorry, no related bibliography") ; return ; } mmax = max ; #ifndef NON_GRAPHIC mmax = biblio ? biblio->numberRef : max ; #endif aceOutxy (biblio_out, messprintf("Found %d ref", mmax),1,1); aut = arrayReCreate (aut, 20, BSunit) ; line = 3; for (i = 0; i < max; i++) { abst = 0 ; ii = i ; #ifndef NON_GRAPHIC if(biblio) { ii = array (biblio->sortNumber, i, int) - 1 ; array( biblio->author, i, char *) = "zzzzzz" ; if (array (biblio->discard, ii, char)) continue ; } #endif line++ ; ref=arr(bibSet,ii,KEY) ; j = i ; #ifndef NON_GRAPHIC if (biblio) j = array (biblio->newNumber, i, float) - 1; #endif aceOutxy (biblio_out, messprintf("_%d) ", j + 1), 0, line++) ; aceOutPrint (biblio_out, "%s", name(ref)) ; Ref = bsCreate(ref) ; if (!Ref) continue ; stackClear (buf) ; if(bsGetKey (Ref,_Title,&text)) { pushText (buf, name(text)) ; uLinesText (stackText(buf,0),width - 4) ; while ((cp = uNextLine(stackText(buf,0)))) aceOutxy (biblio_out, cp, 4, line++); } if (bsFindTag (Ref, _Author) && bsFlatten (Ref, 1, aut)) { stackClear (buf) ; for (j=0 ; j < arrayMax(aut) ; j++) { if (j) catText (buf, messprintf (", %s", name(keySet(aut,j)))) ; else { catText (buf, name(keySet(aut,j))) ; #ifndef NON_GRAPHIC if (biblio) array( biblio->author, i, char *) = name (keySet (aut, j)) ; #endif } } catText (buf, ".") ; uLinesText (stackText(buf,0),width - 4) ; while ((cp = uNextLine(stackText(buf,0)))) aceOutxy (biblio_out, cp, 4, line++); } j = 0 ; if (bsGetKey (Ref, _Journal, &kk)) { j = 1 ; aceOutxy (biblio_out, name(kk), 4, line++) ; } if (bsGetData (Ref, _Volume, _Int, &ix)) { if (!j) { j = 1 ; aceOutxy (biblio_out, " ", 4, line++) ; } aceOutPrint (biblio_out, " %d",ix) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) aceOutPrint (biblio_out, " %s", cp) ; } else if (bsGetData (Ref, _Volume, _Text, &cp)) { if (!j) { j = 1 ; aceOutxy (biblio_out, " ", 4, line++) ; } aceOutPrint (biblio_out, " ") ; aceOutPrint (biblio_out, "%s", cp) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) aceOutPrint (biblio_out, " %s", cp) ; } if (bsGetData (Ref, _Page, _Int, &ix)) { if (!j) { j = 1 ; aceOutxy (biblio_out, " ", 4, line++) ; } aceOutPrint (biblio_out, ": %d",ix) ; while (bsGetData (Ref,_bsRight,_Int,&ix)) aceOutPrint (biblio_out, "-%d", ix) ; } else if (bsGetData (Ref,_Page, _Text, &cp)) { if (!j) { j = 1 ; aceOutxy (biblio_out, " ", 4, line++) ; } aceOutPrint (biblio_out, ", %s", cp) ; while (bsGetData (Ref,_bsRight,_Text,&cp)) aceOutPrint (biblio_out, "-%s",cp) ; } if (bsGetData (Ref,_Year,_Int,&ix)) { if (!j) { j = 1 ; aceOutxy (biblio_out, " ", 4, line++) ; } aceOutPrint (biblio_out, " (%d)",ix) ; } #ifndef NON_GRAPHIC if (biblio &&(showAbstracts || array (biblio->abstExists, ii, char))) { if (!array (biblio->abstract, ii, char)) { bsDestroy (Ref) ; continue ; } abst = 1; } #endif if (showAbstracts || abst) { if (bsGetKey (Ref, _Abstract, &text) && (abs = stackGet (text))) { stackClear (buf) ; stackCursor (abs, 0) ; nbLines = 0 ;/* mhmp 07/05/97 */ nbEmpty = 0 ; while ((cp = stackNextText (abs))) { catText (buf, cp) ; catText (buf, "\n") ; nbLines++ ; if (strlen(cp)) nbEmpty = 0 ; else nbEmpty++ ; } stackDestroy (abs) ; uLinesText (stackText(buf,0),width - 6) ; for ( iabst = 1 ; iabst <= nbLines - nbEmpty ; iabst++) { cp = uNextLine(stackText(buf,0)) ; aceOutxy (biblio_out, cp, 6, line++); } } } bsDestroy(Ref) ; } arrayDestroy (aut); stackDestroy (buf) ; return; } /* biblioDump */ /***********************************************************************/ /***********************************************************************/