/* File: longtextdisp.c * Author: Fred Wobus (fw@sanger.ac.uk) * Copyright (C) J Thierry-Mieg and R Durbin, 1999 * ------------------------------------------------------------------- * 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: graphical display of longtext data * Exported functions: * longTextDisplay - DisplayFunc for "DtLongText" type * HISTORY: * Last edited: May 16 09:46 2003 (edgrif) * * Jan 28 09:19 1999 (fw): created to accomodate graphical routines * from longtext.c * Created: Thu Jan 28 09:12:27 1999 (fw) *------------------------------------------------------------------- */ /* $Id: longtextdisp.c,v 1.20 2003/05/16 08:47:48 edgrif Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include /*****************************************************************/ typedef struct LOOKSTUFF { int magic; /* == MAGIC */ KEY key ; Graph graph ; int activeBox, editing ; Stack textStack ; int myTextStack ; KEYSET box2key ; Array segs, /* array of SEG's from the obj */ boxIndex ; /* if >256 a SEG, else something special */ } *LOOK ; typedef struct { KEY key ; float x, dx ; unsigned int flag ; /* I use shift right operators */ } SEG ; #define segFormat "k2fi" static void longTextDestroy (void) ; static void longTextEditor (void) ; static void longTextRecover (void) ; #ifdef ACEDB_MAILER static void longTextMail (void) ; #endif static void longTextRead (void) ; static void longTextDecorate (void) ; static void generalGrep(void) ; static void longTextPick(int box, double x_unused, double y_unused, int modifier_unused); static void longTextDraw (LOOK look, BOOL reuse); static MENUOPT longTextMenu[] = { {graphDestroy, "Quit"}, {help,"Help"}, {graphPrint,"Print"}, {displayPreserve,"Preserve"}, {longTextDecorate, "Search"}, #if !defined(WIN32) {longTextEditor,"Edit"}, #endif {longTextRecover,"Save"}, #ifdef ACEDB_MAILER {longTextMail,"Mail"}, #endif {longTextRead,"Read"}, {generalGrep,"General Grep"}, {0, 0} } ; static int MAGIC = 464565 ; /* also use address as graphAss handle */ #define LOOKGET(name) LOOK look ; \ if (!graphAssFind (&MAGIC, &look)) \ messcrash ("graph not found in %s",name) ; \ if (look->magic != MAGIC) \ messcrash ("%s received a wrong pointer",name) /**************************************************************/ BOOL longTextDisplay (KEY key, KEY from, BOOL isOldGraph, void *unused) { LOOK look=(LOOK)messalloc(sizeof(struct LOOKSTUFF)) ; KEY curr = 0 ; look->magic = MAGIC; if (key && class(key) != _VLongText) goto abort ; if (! (look->textStack = stackGet(key))) goto abort ; look->key = key ; look->boxIndex = arrayCreate (64,SEG*) ; look->activeBox = 0 ; keySetDestroy(look->box2key) ; if (isOldGraph) { longTextDestroy () ; graphClear () ; graphGoto (0,0) ; graphRetitle (name (key)) ; graphAssRemove (&MAGIC) ; } else { displayCreate("DtLongText"); graphRetitle (name(key)) ; graphRegister (DESTROY, longTextDestroy) ; graphRegister (PICK, longTextPick) ; /* graphRegister (KEYBOARD, longTextKbd) ; graphRegister (MIDDLE_DOWN, longTextMiddleDown) ; */ graphMenu (longTextMenu) ; } look->graph = graphActive() ; look->myTextStack = stackExists(look->textStack) ; graphAssociate (&MAGIC, look) ; longTextDraw (look, curr) ; return TRUE ; abort : messfree (look) ; return FALSE ; } /* longTextDisplay */ /************************************************************/ static void longTextPick(int box, double x_unused, double y_unused, int modifier_unused) { LOOKGET("longTextPick") ; if (!box || ! keySetExists(look->box2key) || box >= keySetMax(look->box2key)) return ; if (box == look->activeBox) /* a second hit - follow it */ display (keySet(look->box2key, box), 0, 0) ; else { if (look->activeBox) graphBoxDraw(box, BLACK, YELLOW) ; graphBoxDraw(box, BLACK, RED) ; } look->activeBox = box ; } /************************************/ static void longTextRead (void) { char *cp = 0 ; Stack s ; ACEIN text_in = 0 ; static char directory[DIR_BUFFER_SIZE] = ""; static char filename[FIL_BUFFER_SIZE] = ""; LOOKGET("longTextRead") ; text_in = aceInCreateFromChooser (".ace-file to read from ?", directory, filename, "ace", "r", 0); if (!text_in) return; if (look->editing && messQuery ("You did not save the edited form of the former text, should I")) longTextRecover () ; look->editing = FALSE ; s = stackCreate(500) ; aceInSpecial (text_in,"\n\t") ; while ((cp = aceInCard(text_in))) { if (strcmp(cp,"***LongTextEnd***") == 0) break ; else pushText(s, cp) ; } aceInDestroy (text_in) ; stackDestroy(look->textStack) ; look->textStack = s ; return; } /* longTextRead */ /**************************************************************/ static KEYSET getClassList(void) { KEYSET classList = keySetCreate(), ks ; int i, j = 0 ; KEY key, key1, mySet ; unsigned char u ; KeySetDisp dummy ; if (keySetActive (&ks, &dummy)) { i = keySetMax(ks) ; j = 0 ; while (i--) { key = key1 = keySet(ks, i) ; if (class(key1) == _VModel) lexword2key (name(key1) + 1 , &key, _VClass) ; if (class(key) == _VClass && pickIsA(&key, &u) ) keySet(classList, j++) = key ; } } if (j > 0) return classList ; if (lexword2key("searchedClasses", &mySet, _VKeySet) && (ks = arrayGet(mySet, KEY, "k"))) { i = keySetMax(ks) ; j = 0 ; while (i--) { key = key1 = keySet(ks, i) ; if (class(key1) == _VModel) lexword2key (name(key1) + 1 , &key, _VClass) ; if (class(key) == _VClass && pickIsA(&key, &u) ) keySet(classList, j++) = key ; } } if (j == 0) { messout("This button searches the text for names in selected classes. " "Either those in the active keyset " "or by default those in the keySet called \"searchedClasses\".\n" "You must either select a keySet of classes " "or construct the default keySet \"searchedClasses\".") ; } return classList ; } /**************************************************************/ static void longTextDecorate (void) { int x = 1 , y = 4, maxx = 0, n , box ; char *cp , c ; Stack s ; KEY key, *classp=0 ; KEYSET classList = 0 ; LOOKGET("longTextDecorate") ; messStatus ("Searching the text") ; graphClear() ; graphButtons (longTextMenu, 3, 1.5, 60) ; s = look->textStack ; if (stackExists(s) != look->myTextStack) { messout("longTextDraw lost its stack, sorry") ; return ; } classList = getClassList() ; look->box2key = keySetReCreate(look->box2key) ; stackCursor(s, 0) ; while ((cp = stackNextText(s))) { ACEIN text_io = aceInCreateFromText(cp, "", 0); aceInSpecial(text_io,"") ; aceInCard(text_io) ; while (*cp && *cp == ' ') /* maintain indenting after decorate */ { ++x ; ++cp ; } while((cp = aceInWordCut(text_io, " .,/;:[]{}()!@#$%^&*+=\\|\"\'~",&c)) || c) { if (cp) { n = keySetMax(classList) ; if (n) { classp = arrp(classList, 0, KEY) ; while (n--) if (lexword2key(cp, &key, *classp++)) { keySet(look->box2key, box = graphBoxStart()) = key ; graphText (cp, x, y) ; graphBoxEnd() ; graphBoxDraw(box, BLACK, YELLOW) ; goto done ; } } graphText (cp, x, y) ; done: x += strlen(cp) ; if (x > maxx) maxx = x ; } if (c) graphText(messprintf("%c", c), x++, y) ; } x = 1 ; y++; aceInDestroy (text_io); } graphTextBounds( maxx + 2 , y+3) ; keySetDestroy(classList) ; graphRedraw() ; return; } /* longTextDecorate */ /**************************************************************/ static void longTextDraw (LOOK look, BOOL reuse) { int x = 1 , y = 4, maxx = 0 ; char *cp ; Stack s = look->textStack ; graphClear() ; graphButtons (longTextMenu, 3, 1.5, 60) ; if (stackExists(s) != look->myTextStack) { messout("longTextDraw lost its stack, sorry") ; return ; } stackCursor(s, 0) ; while ((cp = stackNextText(s))) { graphText (cp, x, y) ; x += strlen(cp) + 1 ; if (x > maxx) maxx = x ; x = 1 ; y++; } graphTextBounds( maxx + 2 , y+3) ; graphRedraw() ; } /**********************************/ #if !defined (WIN32) static void longTextEditor (void) { FILE *f = NULL ; static int n = 1 ; Stack s ; char *cp ; LOOKGET("longTextEditor") ; s = look->textStack ; if (!stackExists(s)) return ; /* It does this solely to bump up n to make a unique filename....ugh... */ while(filCheckName(messprintf("/tmp/acedb.editor.%d",n),"","r") || filCheckName(messprintf("/tmp/acedb.editor.%d.done",n),"","r")) { n++ ; } f = filopen(messprintf("/tmp/acedb.editor.%d",n),"","w") ; if (!f) { messprintf("Sorry, i cannot create the file %s", messprintf("/tmp/acedb.editor.%d",n),"w") ; return ; } stackCursor(s, 0) ; while ((cp = stackNextText(s))) fprintf(f, "%s\n", cp) ; filclose(f) ; system(messprintf("acedb_editor /tmp/acedb.editor.%d &", n)) ; look->editing = n++ ; displayPreserve() ; return ; } #endif /**********************************/ #ifdef ACEDB_MAILER static void longTextMail (void) { KEYSET ks ; KeySetDisp dummy; LOOKGET("longTextEditor") ; if (!stackExists(look->textStack)) return ; if (!keySetActive(&ks, &dummy)) { messout ("First select a keySet containing the recipients") ; return ; } acedbMailer(0, ks, look->textStack) ; } #endif /**********************************/ static void longTextRecover (void) { Stack s ; char *cp ; ACEIN text_io; ParseFuncReturn parsing ; char *err_txt ; LOOKGET("longTextRecover") ; if (look->editing == 0) return ; lao: text_io = aceInCreateFromFile (messprintf("/tmp/acedb.editor.%d.done",look->editing), "r", "", 0); if (!text_io) { if (!messQuery ("To store the edited text, first exit the text editor.\n" " Are you ready ?")) return ; else goto lao ; } aceInSpecial (text_io,"\n\t") ; parsing = longTextParse(text_io, look->key, &err_txt) ; if (parsing == PARSEFUNC_OK && (s = stackGet(look->key))) { stackClear(look->textStack) ; stackCursor(s, 0) ; while ((cp = stackNextText(s))) pushText(look->textStack,cp) ; stackDestroy(s) ; } else if (parsing == PARSEFUNC_ERR) messout("Failed to recover the file /tmp/acedb.editor.%d.done, " "longText parse failed, reason was: %s", look->editing, err_txt) ; else messout("I failed to recover the file /tmp/acedb.editor.%d.done", look->editing) ; aceInDestroy (text_io) ; look->editing = 0 ; longTextDraw (look, 0) ; return; } /* longTextRecover */ /**********************************/ /************************************************************/ /***************** Registered routines *********************/ static void longTextDestroy (void) { LOOKGET("longTextDestroy") ; if (look->editing && messQuery ("You did not save the edited form of this text, should I") ) longTextRecover () ; arrayDestroy(look->segs) ; arrayDestroy(look->boxIndex) ; stackDestroy(look->textStack) ; keySetDestroy(look->box2key) ; look->magic = 0 ; messfree (look) ; graphAssRemove (&MAGIC) ; } /**************************************************************/ /**************************************************************/ /* general LongText Analyser */ static void generalGrep(void) { static char dName[DIR_BUFFER_SIZE]="", filName[FIL_BUFFER_SIZE]="" ; KEY _Abstract, *ppp, *classp, key, *kp, ltk; char *cp, cutter; Stack s ; OBJ obj = 0 ; int i, nX = 0 , nLT = 0 , xn ; KEYSET xs = 0 , ks=0, ks1=0, classList=0 ; FILE *g, *f ; KeySetDisp dummy ; if (!lexword2key("Abstract",&_Abstract,0)) { messout ("Tag Abstract is absent from this database, " "nothing I can report, sorry") ; return ; } if (!keySetActive(&ks1, &dummy)) { messout ("First select a keyset containing Papers") ; return ; } if(!(classList = getClassList())) return ; if (!messQuery("This is a general grepper on all long texts,\n" "You ll be asked for on output file name.\n" "do you want to proceed ?")) return ; ks = query(ks1,"CLASS Paper ; Abstract") ; if (!keySetMax(ks)) { messout ("First select a keyset containing paper with abstracts") ; keySetDestroy (ks) ; return ; } f = filqueryopen(dName, filName, "ace", "w", "I need a place to export the Grep results") ; g = filopen(filName, "bad","w") ; if (!f || !g) { messout("Got a cancel file, i quit") ; if (f) filclose(f) ; if (g) filclose(g) ; keySetDestroy (ks) ; return ; } i = keySetMax(ks) ; ppp = arrp(ks, 0, KEY) - 1 ; while (ppp++, i--) { obj = bsCreate(*ppp) ; if (!obj) continue ; ltk = 0 ; bsGetKey (obj,_Abstract,<k) ; bsDestroy (obj) ; if (!ltk) continue ; s = stackGet(ltk) ; if (!stackExists(s)) continue ; nLT++ ; stackCursor(s,0) ; xs = keySetReCreate(xs) ; xn = 0 ; while (s && (cp = stackNextText(s))) { ACEIN fi = aceInCreateFromText (cp, "", 0); aceInSpecial(fi,"") ; aceInCard(fi) ; while((cp = aceInWordCut(fi," .,/;:[]{}()!@#$%^&*+=\\|\"\'~\n",&cutter)) || cutter) if (cp) { int n = keySetMax(classList) ; classp = arrp(classList, 0, KEY) ; while (n--) if (lexword2key(cp, &key, *classp++)) { keySet(xs, xn++) = key ; break ; } if (islower((int)*cp) && islower((int)*(cp+1)) && islower((int)*(cp+2))&& (*(cp+3) == '-') && isdigit((int)*(cp+4)) && !lexword2key(cp, &key, _VLocus)) fprintf(g, "Unknown Gene : %s\n", cp) ; } aceInDestroy (fi) ; } if (xn) { keySetSort(xs) ; keySetCompress(xs) ; fprintf(f, "\nPaper : %s\n", name(*ppp)) ; xn = keySetMax(xs) ; nX += xn ; kp = arrp(xs, 0, KEY) - 1 ; while (kp++, xn--) fprintf(f, "%s : %s \n", className(*kp), name(*kp)) ; } stackDestroy(s) ; } messout ("#*#*#*# Found %d XREF in %d LongTexts \n", nX, nLT) ; keySetDestroy(ks) ; filclose(f) ; filclose(g) ; keySetDestroy(classList) ; keySetDestroy(xs) ; } /************************** eof *******************************/