/* file: mainpick.c * Author: Jean Thierry-Mieg (mieg@mrc-lmb.cam.ac.uk) * Copyright (C) J Thierry-Mieg and R Durbin, 1991 * ------------------------------------------------------------------- * 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 (MRC LMB, UK) rd@mrc-lmb.cam.ac.uk, and * Jean Thierry-Mieg (CRBM du CNRS, France) mieg@kaa.cnrs-mop.fr * * Description: * Exported functions: * HISTORY: * Last edited: Sep 22 14:43 2003 (edgrif) * * May 8 14:41 2000 (edgrif): Added "full reindex" option to Read Models. * * Dec 3 14:42 1998 (edgrif): Change calls to new interface to aceversion. * * Oct 22 11:45 1998 (edgrif): Remove dec. of pickDraw, put in acedb.h * * Jun 11 1:38 1996 (rbrusk): * - WIN32 letting double pickPick() do its thing in pickCreate() * * Jun 6 17:44 1996 (rd) * * Jun 5 1:38 1996 (rbrusk): * - TEXT_ENTRY_FUNC_CAST added to classDisplay() and grepDisplay() * callback arguments to graphTextScrollEntry() * * Jun 5 1:38 1996 (rbrusk): * - WIN32 port changes to 4.3 * * May 10 21:13 1996 (rd) * * Sep 12 17:45 1992 (rd): in classDisplay() added quick check if template is a valid object name (Alan's suggestion) * * Dec 6 13:28 1991 (mieg): autocompletion system * * Dec 2 20:59 1991 (mieg): if(isdisplayBlock) no autoPick * because this create a textBound on wrong graphtype somehow ? * * Nov 5 18:28 1991 (mieg): call to keySetShow changed * Created: Tue Nov 5 18:26:56 1991 (mieg) * CVS info: $Id: mainpick.c,v 1.164 2003/10/06 12:15:40 edgrif Exp $ *------------------------------------------------------------------- */ /* #define CHRONO to get Chrono in the admin menu */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for dnaAnalyse */ #include /* for readTreeFile et al. */ #include #include #include #include #include #include #include #include #include #include #include #include /************************************************************/ enum {ACTIVITY_LENGTH = 28, /* Max length of activity status indicator */ TEMPLATE_LENGTH = 256, OLD_TEMPLATE_LENGTH = 20} ; /* Must be smaller than TEMPLATE_LENGTH */ typedef struct PickStruct { magic_t *magic ; /* == &Pick_MAGIC */ int curr, currBox ; KEY currClasse ; char template[TEMPLATE_LENGTH] ; int templateBox ; char* grepText ; int grepBox , longGrepBox , m1, m2, m3, modeBox1, modeBox2 ; BOOL longGrep ; char whatdoIdoText[ACTIVITY_LENGTH] ; int whatdoIdoBox, classListBox ; Graph mainGraph ; Graph ksdisp_graph ; /* graph of KeySet window */ KEYSET oblist ; KeySetDisp ksdisp_handle ; int admin_box ; /* Need to dynamically change the menu. */ } *Pick ; #define PICKGET(myname) Pick pick ;\ \ if (!graphAssFind (&Pick_MAGIC, &pick)) \ messcrash ("%s can't find pointer",myname) ; \ if (pick->magic != &Pick_MAGIC) \ messcrash ("%s received a wrong pointer",myname) /************************************************************/ static void prefMainRedraw(BOOL pref_value) ; static void mainStatusDisplay (char *text, void *user_pointer); static void mainWindowResize (void); static void mainWindowPick (int k, double x, double y, int modifier_unused); static void mainWindowDestroy (void) ; static void mainWindowReReadClasses (void); /* upon model-change */ static void mainWindowCleanUp (void) ; static int pickClassComplete (char *cp, int len) ; static BOOL classListMenuCall (KEY k, int box) ; static void pickDoDrawOld (void); static void pickDoDrawNew (void) ; static void pickModeChoice1 (void) ; static void exitButtonAction (void); static void oldmenuSaveAction (void); static void oldmenuWriteAccess (void); static void oldmenuReadModels (void); static void oldmenuReadModelsAndReindex(void) ; static void doReadModels(BOOL complete_reindex) ; static void obDisplay (Pick pick, BOOL show1, int state); static BOOL classDisplay (void); static BOOL classDisplayNew (int curr); static void grepDisplay (char *entry); static void grepDisplayNew (int curr); static void serverOn (void); static void serverOff (void); static void swopSigCatchMenuText(char *sig_txt, int admin_box) ; static void saveAndKeepWriteAccess(void) ; static void saveCB(void *unused) ; static void quitCB(void *unused) ; /* these externs have to be removed and replaced with includes that declare the prototypes for these functions */ extern void oxgridCreate(void), alignMaps(void), updateData(void), addKeys(void), editPreferences(void), queryCreate(void), qbuildCreate(void), qbeCreate(void), alignMaps(void); #ifdef ACEMBLY extern void blyControl (void); #endif /* ACEMBLY */ #ifdef DEBUG extern void acedbtest(void); #endif /* DEBUG acedbtest */ #ifdef CHRONO extern void chronoShow(void); #endif #ifndef ACEMBLY /* oxgrid not included in acembly */ extern void oxgridCreate(void) ; extern BOOL oxgridPossible(void) ; #endif /* !ACEMBLY */ /************************************************************/ static magic_t Pick_MAGIC = "Pick"; static Pick mainPick = 0 ; static int firstClassBox = 0 ; static Array classList = 0 ; /* Array of FREEOPT */ static Array classLayout = 0 ; /* Array of LAYOUT */ static BOOL isNewLayout = TRUE ; /* mieg: new layout */ static VoidRoutine mainWindowQuitRoutine = 0; static char *pickFirstClass = 0; static int pickFirstBox = 0; static char *pickFirstTemplate = 0; /* long main menu for old-style main-window */ static MENU mainMenu ; MENUOPT mainMenuSpec[] = { { exitButtonAction, "Quit"}, { help , "Help"}, { graphCleanUp, "Clean up"}, { statusDisplayCreate,"Program status"}, #ifdef ACEMBLY { blyControl, "Acembly"}, #else { updateData, "Add Update File"}, { editPreferences, "Preferences"}, #endif { menuSpacer, ""}, #if defined(WIN32) { 0, "Query"}, #endif { queryCreate, "Query"}, #if !defined(MACINTOSH) { qbeCreate, "Query by Examples"}, #endif { qbuildCreate, "Query builder"}, { tableMaker, "Table Maker"}, { aqlDisplayCreate, "AQL Query"}, #if defined(WIN32) { 0, 0}, /* submenu trailer */ #endif { dnaAnalyse, "DNA Analysis"}, { menuSpacer, ""}, #ifndef ACEMBLY #if defined(WIN32) /* (rbrusk) July 17, 1998 - Dendrogram functions */ { 0, "Phylogenetic Trees"}, #endif { readTaxonomicTree, "Read Taxonomy File"}, { readDNATree, "Read DNA Tree File"}, { readProteinTree, "Read Protein Tree File"}, #if defined(WIN32) { 0, 0}, /* submenu trailer */ #endif /* option below added by jld */ { oxgridCreate, "Comparative Maps"}, #endif /* !ACEMBLY */ { menuSpacer, ""}, { addKeys, "Add-Alias-Rename"}, { parseControl, "Read .ace files"}, { alignMaps, "Align maps"}, { oldmenuReadModels, "Read models"}, { oldmenuReadModelsAndReindex, "Read models and full reindex"}, { dumpAll, "Dump"}, { dumpReadAll, "Read Dump Files"}, { sessionControl, "Session control"}, #ifdef CHRONO { menuSpacer, ""}, { chronoShow, "Chronometer"}, #endif /* CHRONO */ #ifdef DEBUG { menuSpacer, ""}, { acedbtest, "Test subroutine"}, #endif /* DEBUG acedbtest */ { menuSpacer , ""}, { oldmenuWriteAccess, "Write Access"} , { menuSpacer , "" }, { oldmenuSaveAction, "Save" }, { 0, 0 } /* end of menu marker */ }; /************************************************************/ static MENUOPT pickNewMenu[] = { { help, "Help"}, { graphPrint, "Print"}, #ifdef ACEMBLY { menuSpacer, ""}, { blyControl, "Acembly"}, #endif { graphDestroy,"Exit"}, { 0,0} } ; #ifndef ACEMBLY /* OXGRIDs not included in Acembly */ static MENUOPT pickNewOxMenu[] = { { graphDestroy, "Exit"}, { help, "Help"}, { graphPrint, "Print"}, { menuSpacer, ""}, { oxgridCreate, "Ox Grids"}, { 0,0 } } ; #endif /*************************************/ static FREEOPT queryButtonFreeMenu[] = { {8,"Query menu"}, {'h', "Help on Query"}, {0, ""}, { 'q', "Query"}, #if !defined(MACINTOSH) { 'b', "Query by Examples"}, #else /* always keep same number of lines */ {0, ""}, #endif { 'u', "Query builder"}, { 's', "Table Maker"}, { 'a', "AQL Query"}, { 'd', "DNA Analysis"}, } ; /*************************************/ /* Stuff for toggling signal catching, default is to catch signals so that */ /* acedb clear up is done. */ #define SIG_ON_TEXT "Turn Signal Catching On" #define SIG_OFF_TEXT "Turn Signal Catching Off" static FREEOPT adminButtonFreeMenu[] = { #if (defined CHRONO && defined DEBUG) {11, "Admin menu"}, #elif (defined CHRONO || defined DEBUG) {9, "Admin menu"}, #else {7, "Admin menu"}, #endif /* !CHRONO !DEBUG */ {'s', "Program Status"}, {'S', "Session Control"}, {'p', "Preferences"}, {'x', SIG_OFF_TEXT}, { 0, ""}, {'d', "Dump All"}, {'D', "Read Dump Files"}, #ifdef CHRONO {0,""}, {'c', "Chronometer"}, #endif /* CHRONO */ #ifdef DEBUG {0,""} {'t', "Test subroutine"}, #endif /* DEBUG acedbtest */ } ; /*************************************/ /* this menu is only displayed if write access is possible */ /* NOTE: * (1) if you change the number of items adjust the * integer in the first line to hold the new number of lines * (2) if you change the order of items be sure to adjust the * code which fiddles the menu-items 'Gain write access' * in pickDoDrawNew()! */ static FREEOPT editButtonFreeMenu[] = { {12, "Edit menu"}, {'u', "Add Update"}, {'A', "Align maps"}, {0,""}, {'r', "Read .ace file"}, {'a', "Add/Delete/Rename/Alias objects"}, {0,""}, {'T', "Create New Dendrogram"}, {'O', "Comparative Maps"}, {0,""}, {'m', "Read Models"}, {'M', "Read Models and full reindex"}, {'w', "Gain write access"} } ; /*************************************/ static FREEOPT saveButtonFreeMenu[] = { {3, "Save menu"}, {'s', "Save session and keep write access"}, {'t', "Save session and lose write access"}, {'d', "Drop write access (no save)"}, } ; /****************************************************************** ************************* public functions *********************** ******************************************************************/ void mainSetInitClass (char *initclass) { pickFirstClass = strnew (initclass, 0); return; } /* mainSetInitClass */ void mainSetInitTemplate (char *inittemplate) { pickFirstTemplate = strnew (inittemplate, 0); return; } /* mainSetInitTemplate */ /************************************************************/ VoidRoutine mainWindowQuitRegister (VoidRoutine func) { VoidRoutine old = mainWindowQuitRoutine; if (func) mainWindowQuitRoutine = func; return old; } /* mainWindowQuitRegister */ /****************************************************************/ /* These two short functions are application wide callbacks that get registered with graph * and are called from any window when the user presses Cntl-S for save or Cntl-Q for quit. * They get registered by pickCreate() and don't actually use the pointer passed in at the * moment. */ static void saveCB(void *unused) { saveAndKeepWriteAccess() ; return ; } static void quitCB(void *unused) { exitButtonAction() ; return ; } Graph pickCreate (void) { BOOL selectFirst = !isNewLayout ; struct messContextStruct statusContext; GlobalCallbacksStruct acedb_callbacks = {{saveCB, NULL}, {quitCB, NULL}} ; writeAccessPossible(); /* establish access status, get possible warning message out of the way */ mainPick = (Pick) messalloc (sizeof(struct PickStruct)); mainPick->magic = &Pick_MAGIC ; mainPick->grepText = (char*) messalloc (256) ; /* free'd in mainWindowDestroy */ /* Register a callback with prefsubs so that when user changes main */ /* window style we get called. */ if (!prefSetFunc("OLD_STYLE_MAIN_WINDOW", (void *)prefMainRedraw)) messcrash("Unable to set callback function for preference %s", "OLD_STYLE_MAIN_WINDOW") ; mainPick->mainGraph = displayCreate ("DtMain"); graphAssociate (&Pick_MAGIC, mainPick) ; graphRegister (PICK, mainWindowPick) ; graphRegister (RESIZE, mainWindowResize) ; graphRegister (DESTROY, mainWindowDestroy) ; graphRegisterGlobalCallbacks(&acedb_callbacks) ; pickFirstBox = 0; /* gets set if pickFirstClass matches a class */ pickDraw() ; messfree (pickFirstClass); messfree (pickFirstTemplate); /* pickDraw gets called again sometimes */ if (!pickFirstBox) pickFirstBox = 1 + firstClassBox ; /* pick the first voc */ else selectFirst = TRUE; mainPick->curr = 0 ; if (selectFirst) /* srk - replace this with select if desired behaviour is no keyset window _except_ when -initclass flag used */ { /* fake a double click - call twice to achieve selection */ mainWindowPick (pickFirstBox, 0, 0, 0) ; mainWindowPick (pickFirstBox, 0, 0, 0) ; } /* We have now drawn the mainwindow and the whatdoIdoBox, * so we can now register the routine that receives the * status strings by messStatus calls anywhare in the code */ statusContext.user_func = mainStatusDisplay; statusContext.user_pointer = (void*)mainPick; messStatusRegister (statusContext); /* We now have a main-window, which we can register to be * redrawn if write access changes and the buttons * and menus need to be redraw */ writeAccessChangeRegister (pickDraw); /* change class menu when models change -> the new models * may have added a new class to the list so we need to update it */ modelChangeRegister (mainWindowReReadClasses); graphActivate(mainPick->mainGraph) ; return mainPick->mainGraph ; } /* pickCreate */ /************************************************************/ void pickDraw (void) { Graph oldGraph = graphActive () ; if (!graphActivate (mainPick->mainGraph)) messcrash ("pickDraw() called before pickCreate() !"); { BOOL oldLayoutStyle = isNewLayout; isNewLayout = !prefValue ("OLD_STYLE_MAIN_WINDOW") ; if (oldLayoutStyle != isNewLayout) { mainPick->whatdoIdoBox = 0; mainPick->currBox = 0 ; mainPick->curr = 0 ; } } if (thisSession.subDataRelease) { char *title = NULL ; if ((title = sessionDBTitle()) == NULL) title = displayGetTitle("DtMain") ; if (sessionDbName()) graphRetitle(messprintf("%s, %s, %s %d-%d", aceGetVersionString(), title, sessionDbName(), thisSession.mainDataRelease, thisSession.subDataRelease)) ; else graphRetitle(messprintf("%s, %s, %d-%d", aceGetVersionString(), title, thisSession.mainDataRelease, thisSession.subDataRelease)) ; } else { char *title = NULL ; if ((title = sessionDBTitle()) == NULL) title = displayGetTitle("DtMain") ; if (sessionDbName()) graphRetitle(messprintf("%s, %s %s", aceGetVersionString(), title, sessionDbName())) ; else graphRetitle(messprintf("%s, %s", aceGetVersionString(), title)) ; } if (!classLayout) classLayout = layoutRead (0) ; classList = classListCreate (classList, TRUE, TRUE, FALSE, TRUE); if (isNewLayout) pickDoDrawNew() ; else pickDoDrawOld() ; graphActivate (oldGraph) ; } /* pickDraw */ /************************************************************/ void pickPopMain (void) { if(graphActivate(mainPick->mainGraph)) graphPop() ; } /************************************************************/ BOOL checkWriteAccess(void) /* interactive way to check, whether we have write access. * Used in by functions that need write access, but want to * enable the user to grab it, if we don't have it already, * and otherwise (when it returns FALSE) return from that func */ { if (isWriteAccess()) return TRUE; if (writeAccessPossible()) { if (messQuery("You do not have Write Access, " "shall I get it for you?")) { /* try to get it */ if (sessionGainWriteAccess()) /* it worked */ return TRUE; else /* we couldn't get it */ return FALSE; } else /* didn't want to gain write access */ return FALSE; } /* impossible to get write access */ messout("Sorry, you cannot gain Write Access"); return FALSE; } /* checkWriteAccess */ /************************************************************/ void mainApplyNewLayout (Array newLayout) /* accept new layout from layoutEditor and re-draw */ { arrayDestroy (classLayout) ; classLayout = newLayout; pickDoDrawNew() ; return; } /* mainApplyNewLayout */ /************************************************************/ void mainKeySetComplete (KEYSET ks, char *text, int len) /**** Auto completion system *********/ { int n, i ; char *cp, *cq ; KEYSET ks2 ; if (!keySetMax(ks)) /* no match */ { messbeep() ; goto ok ; } else if (keySetMax(ks) == 1) /* unique match */ { strncpy (text, name(keySet(ks,0)), len-1) ; goto ok ; } /* else multiple matches */ n = strlen(text) ; for (i = 0 ; i < n ; ++i) text[i] = 0 ; ks2 = keySetAlphaHeap(ks,keySetMax(ks)) ; cp = name (keySet (ks2, 0)) ; cq = name (keySet (ks2, keySetMax(ks2)-1)) ; keySetDestroy(ks2) ; for (i = 0 ; *cp && *cp == *cq && i < len-1 ; ++i, ++cp, ++cq) text[i] = *cp ; text[i] = 0 ; if (i > n) /* length increase */ goto ok ; ok: if (mainPick) { Graph oldGraph = graphActive() ; if (ks != mainPick->oblist) /* probably a useless kludge */ { keySetDestroy (mainPick->oblist) ; mainPick->oblist = ks ; } if (graphActivate (mainPick->mainGraph)) obDisplay (mainPick, FALSE, 3) ; /* no automatic display() if 1 */ graphActivate (oldGraph) ; } } /************************************************************/ int ksetClassComplete (char *text, int len, int classe) /* return number of possible completions */ { static KEYSET ks = 0 ; static int previousClass = 0 ; static int myKeySetId = 0 ; static char buffer[80] ; KEYSET ks2 ; char *cp, *cq ; int i, j , n ; if (myKeySetId != keySetExists(ks)) ks = 0 ; if (!text) { keySetDestroy(ks) ; return 0 ; } if (ks) { if (previousClass != classe) keySetDestroy(ks) ; else { /* check if search field just got longer */ cp = buffer ; cq = text ; n = 80 ; /* size of buffer */ while (--n && *cp && *cq == *cp){cp++; cq++;} if (!n || *cp) keySetDestroy (ks) ; } } strncpy(buffer, text, 79) ; if (!ks) { if (class(classe) == _VClass) ks = query (0, messprintf ("FIND %s IS \"%s*\"", name(classe), text)) ; else /* assume a true classe */ ks = query (0, messprintf ("FIND %s IS \"%s*\"", pickClass2Word(classe), text)) ; } else { ks2 = arrayCreate(keySetMax(ks), KEY) ; text[len-2] = 0 ; /* prevents running off end */ cp = text + strlen(text) ; *cp = '*' ; *(cp+1) = 0 ; for (i=0, j=0 ; i < keySetMax(ks) ; i++ ) if (pickMatch (name(keySet(ks,i)), text)) keySet(ks2,j++) = keySet(ks,i) ; *cp = 0 ; /* remove * from end */ keySetDestroy(ks) ; ks = ks2 ; } mainKeySetComplete (ks, text, len) ; myKeySetId = keySetExists(ks) ; previousClass = classe ; strncpy(buffer, text, 79) ; return keySetMax(ks) ; } /* ksetClassComplete */ /************************************************************/ Array classListCreate (Array oldList, BOOL listHidden, BOOL listVisible, BOOL listBuried, BOOL listAllTypes) /* if FALSE must have model */ { int max, i, j ; KEYSET ks, ksa ; Array newList; Stack s = stackCreate(50); BOOL arg = FALSE; unsigned char mask ; KEY key, model, table ; catText(s, "FIND Class"); if (listHidden) { catText(s, " HIDDEN"); arg = TRUE; } if (listVisible) { if (arg) catText(s, " OR"); catText(s, " VISIBLE"); arg = TRUE; } if (listBuried) { if (arg) catText(s, " OR"); catText(s, " BURIED"); } ks = queryLocalParametrized(0, stackText(s, 0), ""); stackDestroy(s); max = keySetMax (ks) ; ksa = keySetAlphaHeap (ks, max) ; keySetDestroy (ks) ; if (oldList) /* replace old array */ newList = arrayReCreate (oldList, max, FREEOPT) ; else newList = arrayCreate(max, FREEOPT); j = 1 ; for (i = 0 ; i < max ; i++) { key = table = keySet(ksa, i) ; pickIsA (&table, &mask) ; if (listAllTypes || (pickList [table].type == 'B' && (model = pickList [table].model) && iskey(model) == 2)) { arrayp(newList, j, FREEOPT)->key = key ; arrayp(newList, j, FREEOPT)->text = name(key) ; j++ ; } } arrayp(newList, 0, FREEOPT)->key = j - 1 ; arrayp(newList, 0, FREEOPT)->text = "Classes" ; keySetDestroy (ksa) ; return newList; } /* classListCreate */ void mainPickReport (int n) { BOOL bb = FALSE ; float line = .5 ; static int boxOn = 0, boxOff ; char *cp = 0 ; if (!externalServerState) return ; switch (n) { case -1: /* ask and draw */ bb = externalServerState (-1) ; /* ask */ graphText ("Server:", .5, line) ; boxOn = graphButton ("On", serverOn, 8.5, line) ; boxOff = graphButton ("Off", serverOff, 12.0, line) ; break ; case 1: bb = TRUE ; break ; case 0: case 2: bb = FALSE ; break ; default: break ; } if (!boxOn) return ; if (externalServerName) cp = externalServerName () ; if (cp) graphText(cp, 18, line); graphBoxDraw(boxOn, BLACK, bb ? PALEBLUE : WHITE) ; graphBoxDraw(boxOff, BLACK, !bb ? (n == 2 ? RED : PALEBLUE) : WHITE) ; } /* mainPickReport */ /****************************************************************** ************************ private functions *********************** ******************************************************************/ /* Callback function, called from prefsubs when user changes style of main */ /* window. */ static void prefMainRedraw(BOOL pref_value) { pickDraw() ; return ; } static void mainWindowResize (void) { isNewLayout = !prefValue ("OLD_STYLE_MAIN_WINDOW") ; if (!isNewLayout) { arrayDestroy (classLayout) ; classLayout = 0; /* force a re-create */ } pickDraw() ; return; } /* mainWindowResize */ static void mainWindowDestroy (void) { Graph g = graphActive() ; struct messContextStruct nullStatusContext = { NULL, NULL }; PICKGET("obDestroy") ; /* prevent any more status display, as this window is dying */ messStatusRegister (nullStatusContext); /* cannot allow any more drawing into the main window */ writeAccessChangeUnRegister (); /*******************************/ if (graphActivate(pick->ksdisp_graph)) graphDestroy () ; if (graphActivate(pick->mainGraph)) graphDestroy () ; graphActivate (g) ; graphAssRemove (&Pick_MAGIC) ; pick->magic = 0 ; if (pick->grepText) messfree (pick->grepText); messfree (pick) ; mainPick = 0 ; return; } /* mainWindowDestroy */ /************************************************************/ static void mainWindowPick (int k, double x, double y, int modifier_unused) { PICKGET("mainWindowPick") ; if (k == pick->templateBox) { graphCompletionEntry (pickClassComplete, pick->template,0,0,0,0) ; return ; } if (!k) { if (pick->currBox) graphBoxDraw (pick->currBox, BLACK, WHITE) ; pick->curr = 0 ; pick->currBox = 0 ; return ; } if (k == pick->grepBox) { if (pick->currBox) graphBoxDraw (pick->currBox, BLACK, WHITE) ; pick->curr = 0 ; pick->currBox = 0 ; graphTextScrollEntry (pick->grepText,0,0,0,0,0) ; } else if (k == pick->classListBox) { KEY key ; if (graphSelect (&key, arrp (classList, 0, FREEOPT))) classListMenuCall (key, 0) ; } if (k > firstClassBox && k <= firstClassBox + arrayMax(classLayout)) { pickModeChoice1() ; if (k != pick->currBox) { if (pick->currBox) graphBoxDraw (pick->currBox, BLACK, WHITE) ; pick->currBox = k ; if (isNewLayout)graphBoxDraw (pick->currBox, BLACK,PALEBLUE) ; else graphBoxDraw (pick->currBox, WHITE, BLACK) ; pick->curr = k - firstClassBox ; graphCompletionEntry (pickClassComplete,pick->template,0,0,0,0) ; } else if (!classDisplay () && strcmp (pick->template,"*")) { /* inappropriate template - display whole list */ strcpy (pick->template,"*") ; graphCompletionEntry (pickClassComplete,pick->template,0,0,0,0) ; classDisplay () ; } } return; } /* mainWindowPick */ static void pickLongGrep (void) { PICKGET("pickLong") ; pick->longGrep = TRUE ; grepDisplay("dummy"); return; } /* pickLongGrep */ /************************************************************/ static BOOL classListMenuCall (KEY classe, int box) { char *cp ; KEY key ; KEYSET ob ; BOOL resul ; char *nom ; int n, state = 1, ii , i, j ; PICKGET ("classListMenuCall") ; pick->currClasse = classe ; pick->oblist = keySetCreate() ; j = 0 ; lao: /* classe is a real Classe-key in _VClass */ for (ii = 0 ; ii < 256 ; ii++) { if (!classe && (pickType(ii) == 'X' || pickList[ii].visible == 'h' || !pickList[ii].name)) continue ; if (classe) { ii = classe ; nom = name(classe) ; } else nom = className(ii << 24) ; if (!strcmp("*", pick->template)) { if (classe && lexword2key (pick->template, &key, classe)) { ob = keySetCreate () ; keySet(ob, 0) = key ; } else { cp = messprintf( "FIND %s", nom) ; if (externalServer) { ob = externalServer (200, cp, 0, FALSE) ; if (keySetMax(pick->oblist) == 200) messout("I limited the importation to 200, type ** to get all %s(s)", name(classe)) ; } else ob = query(0, cp) ; } } else ob = query(0, messprintf( "FIND %s IS %s",nom, freeprotect(pick->template))) ; n = keySetMax(ob) ; for (i = 0 ; i < n ; i++) { keySet(pick->oblist,j++) = keySet(ob,i) ; } if (externalServer && !strcmp("*", pick->template) && j >= 200) { messout("I limited the importation to 200, type ** to get all %s(s)", nom) ; break ; } if (classe) break ; } if (state == 1 && !keySetMax(pick->oblist)) { cp = pick->template ; n = strlen(cp) ; if (n == 0 || (*(cp + n - 1) != '*' && n < (OLD_TEMPLATE_LENGTH - 1))) { strcat (pick->template, "*") ; graphBoxDraw (pick->templateBox, -1, -1) ; state = 2 ; goto lao ; } } resul = (keySetMax(pick->oblist) != 0) ; obDisplay (pick, TRUE, state) ; return resul ; } /* classListMenuCall */ /***********************************/ static void mainWindowCleanUp (void) { graphCleanUp() ; pickDraw() ; } /*************************************/ static void queryButtonFreeAction (KEY key, int box) { switch (key) { case 0: break ; case 'h': helpOn ("Query") ; break ; case 'q': queryCreate() ; break ; case 'b': qbeCreate() ; break ; case 'u': qbuildCreate() ; break ; case 's': tableMaker() ; break ; case 'a': aqlDisplayCreate() ; break ; case 'd': dnaAnalyse() ; break ; } } static void querySelector (void) { KEY k ; if (!graphSelect (&k,queryButtonFreeMenu)) return ; queryButtonFreeAction(k,0) ; } /***********************************/ static void adminButtonFreeAction (KEY key, int box) { PICKGET("adminButtonFreeAction") ; switch (key) { case 0: break ; case 's': statusDisplayCreate(); break ; case 'S': sessionControl() ; break ; case 'p': editPreferences() ; break ; case 'x': { /* Toggle signal handling on/off. */ char *sig_txt ; if (signalCatchStatus()) { sig_txt = SIG_ON_TEXT ; signalCatchOff(FALSE) ; } else { sig_txt = SIG_OFF_TEXT ; signalCatchOn(FALSE) ; } swopSigCatchMenuText(sig_txt, pick->admin_box) ; break ; } case 'd': dumpAll() ; break ; case 'D': dumpReadAll() ; break ; #ifdef CHRONO case 'c': chronoShow () ; break ; #endif #ifdef DEBUG case 't': acedbtest() ; break ; #endif /* DEBUG acedbtest */ } } /* adminButtonFreeAction */ static void adminSelector(void) { KEY k ; if (graphSelect(&k,adminButtonFreeMenu)) adminButtonFreeAction(k,0) ; return ; } /* adminSelector */ /***********************************/ static void editButtonFreeAction(KEY key, int box) { switch (key) { case 0: break ; case 'r': /* Read .ace file */ if (checkWriteAccess()) parseControl(); break ; case 'a': /* Add/Delete/Rename/Alias */ if (checkWriteAccess()) addKeys() ; break ; case 'A': /* Align maps */ if (checkWriteAccess()) alignMaps() ; break ; case 'w': sessionGainWriteAccess(); /* Gain Write Access */ /* will re-draw if write access status changes */ break; case 'T': /* Dendrogram trees */ dendrogramDisplay (0,0,0, NULL) ; break; case 'O': /* Oxgrid */ oxgridCreate() ; break; case 'm': doReadModels(FALSE) ; /* Just read models. */ break ; case 'M': doReadModels(TRUE) ; /* Read models + full reindex. */ break ; case 'u': updateData() ; break ; } pickDoDrawNew() ; } /* editButtonFreeAction */ static void editSelector(void) { KEY k ; /* graphEvent (RIGHT_DOWN, 3,3) ; */ if (!graphSelect (&k,editButtonFreeMenu)) return ; editButtonFreeAction(k,0) ; } /***********************************/ static void saveAndKeepWriteAccess(void) /* used by save button freemenu and the save button itself */ { if (isWriteAccess()) { #ifdef ED_G_NEVER_INCLUDE_THIS_CODE /* This results in the log file being closed, this is a temporary fix * as the logfile v.s. session close stuff needs sorting out. */ sessionClose (TRUE); /* close and save session, nothing will happen, if we don't have write access */ #endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ sessionMark (TRUE, 0) ; if (!sessionGainWriteAccess()) /* re-gain write access */ messout ("Sorry, it was not possible to re-gain write access " "after saving the last session."); } else { messout ("You don't have write access. Nothing to save."); } } /* saveAndKeepWriteAccess */ /***********************************/ static void saveAndLoseWriteAccess(void) /* used by save button freemenu */ { #ifdef ED_G_NEVER_INCLUDE_THIS_CODE /* This results in the log file being closed, this is a temporary fix * as the logfile v.s. session close stuff needs sorting out. */ sessionClose (TRUE) ; /* close and save session, nothing will happen, if we don't have write access */ #endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ sessionMark (TRUE, 0) ; } /* saveAndLoseWriteAccess */ /***********************************/ static void saveMenuFreeAction(KEY key, int box) { switch (key) { case 's': saveAndKeepWriteAccess(); break ; case 't': saveAndLoseWriteAccess(); break ; case 'd': sessionReleaseWriteAccess(); /* don't save, drop write access */ break; default: break; } } /* saveMenuFreeAction */ /***********************************/ static void exitButtonAction (void) { if (thisSession.session != 1 && !messQuery ("Do you really want to quit acedb?")) return; if (mainWindowQuitRoutine) (*mainWindowQuitRoutine)(); else { /* default action that needs to be performed when xace exits */ graphCleanUp () ; /* kills all open windows, forces displayed objects to cache */ writeAccessChangeUnRegister(); /* avoid unnecessary re-draws just before exiting */ /* release read/write locks and clean up temp-files is all done by aceQuit() */ if (isWriteAccess() && messQuery ("You did not save your work, should I ?")) sessionClose (TRUE); else sessionClose (FALSE); if (!getenv("ACEDB_NO_BANNER")) printf ("\n\nA bientot !\n") ; } exit (EXIT_SUCCESS); } /* exitButtonAction */ /***********************************/ static void serverOn (void) { BOOL bb=FALSE; if (externalServerState) bb = externalServerState (1) ; /* set */ mainPickReport (bb ? 1 : 2) ; } static void serverOff (void) { BOOL bb=FALSE; if (externalServerState) bb = externalServerState (0) ; /* unset */ mainPickReport (bb ? 1 : 0) ; } /************************************************************/ /**************** old main menu ****************************/ /************************************************************/ static void oldmenuSaveAction (void) { if (isWriteAccess()) { BOOL reGet = messQuery("Shall I retain Write Access after saving?"); sessionClose (TRUE) ; if (reGet) sessionGainWriteAccess(); } else sessionGainWriteAccess () ; /* try to grab it */ } /* menuSaveAction */ static void oldmenuWriteAccess (void) { /* can't use this function directly in menu definition, it returns a boolean success value (ignored here) */ sessionGainWriteAccess(); } /* menuWriteAccess */ static void oldmenuReadModels (void) { doReadModels(FALSE) ; return ; } /* menuReadModels */ static void oldmenuReadModelsAndReindex (void) { doReadModels(TRUE) ; return ; } /* menuReadModels */ /* Just calling readModels will not do a complete reindex, this sometimes */ /* seems to cause problems because queries start to not work correctly and */ /* do not find everything they should. The problem seems to go away after a */ /* complete reindex which takes longer. This code follows that in command.c */ /* for the "Read-models" command. So now users can do the complete reindex */ /* from xace as well as tace. */ static void doReadModels(BOOL complete_reindex) { if (complete_reindex) { if (messQuery("A complete reindex can take a long time for a large database, " "during this time no one else will be able to update the database. " "do you wish to continue ?")) bIndexInit(BINDEX_AFTER_READMODELS) ; } else readModels() ; return ; } static void pickDoDrawOld (void) { int box, i, y ; float line; LAYOUT *z ; if (!graphActivate (mainPick->mainGraph)) return ; graphClear() ; if (!mainMenu) { mainMenu = menuInitialise ("Main menu", (MENUSPEC*)mainMenuSpec) ; if (!writeAccessPossible()) { menuSuppress (mainMenu, "Save") ; menuSuppress (mainMenu, "Write Access") ; menuSuppress (mainMenu, "Add-Alias-Rename") ; } } if (writeAccessPossible()) { if (isWriteAccess()) { menuSetFlags (menuItem (mainMenu, "Write Access"), MENUFLAG_DISABLED) ; menuUnsetFlags (menuItem (mainMenu, "Save"), MENUFLAG_DISABLED) ; } else { menuUnsetFlags (menuItem (mainMenu, "Write Access"), MENUFLAG_DISABLED) ; menuSetFlags (menuItem (mainMenu, "Save"), MENUFLAG_DISABLED) ; } } graphNewMenu (mainMenu); /* drawing */ line = 0.5 ; if (externalServerState) { mainPickReport (-1) ; line += 2 ; } graphText ("Search: ", 0.5, line) ; box = graphButton("Help",help,35.,line) ; graphBoxMenu (box, 0) ; box = graphButton("Exit",exitButtonAction,41.,line) ; graphBoxMenu (box, 0) ; if (pickFirstTemplate) strcpy(mainPick->template, pickFirstTemplate); else strcpy (mainPick->template,"*") ; mainPick->templateBox = graphCompletionEntry(pickClassComplete, mainPick->template, OLD_TEMPLATE_LENGTH, 12.0, line, TEXT_ENTRY_FUNC_CAST classDisplay) ; line += 1.5 ; strcpy(mainPick->whatdoIdoText, ""); mainPick->whatdoIdoBox = graphBoxStart() ; graphTextPtr(mainPick->whatdoIdoText, 18, line, ACTIVITY_LENGTH) ; graphBoxEnd() ; line += .5 ; graphText ("In Class:", 0.5, line) ; mainPick->classListBox = box = graphMenuTriangle(TRUE, 9.7, line) ; graphBoxFreeMenu(box, (FreeMenuFunction) classListMenuCall, arrp (classList, 0, FREEOPT) ) ; line += 1 ; y = 0 ; firstClassBox = graphBoxStart () ; for (i = 0 ; i < arrayMax(classLayout) ; ++i) { int b = graphBoxStart () ; z = arrp(classLayout, i, LAYOUT) ; if (z->y > y) y = z->y ; graphText (name(z->key), z->x, z->y + line) ; if (pickFirstClass && (strcasecmp(name(z->key), pickFirstClass) == 0)) { pickFirstBox = b; } graphBoxEnd () ; } graphBoxEnd () ; graphNewBoxMenu(firstClassBox, mainMenu); line += y + 2 ; graphBoxStart() ; graphText ("Global Search: ", 0.5, line) ; graphBoxEnd () ; strcpy (mainPick->grepText, ""); mainPick->grepBox = graphTextScrollEntry (mainPick->grepText, 255, 16, 14.5, line, grepDisplay) ; if (lexMax(_VLongText) > 2) mainPick->longGrepBox = graphButton ("Long Search", pickLongGrep, 32.,line) ; messStatus ("dummy"); /* force redraw of whatdoIdoBox */ graphRedraw () ; } /* pickDoDrawOld */ static void pickModeChoice (int m1, int m2, int m3) { int i ; if (!isNewLayout) return; if (m1) { if (mainPick->m1 == m1) { m1-- ; if (!m1) m1 = 1 ; } if (!m2) { if (m1 == 1) m2 = 1 ; else m2 = 2 ; } i = 3 ; while (i--) graphBoxDraw (mainPick->modeBox1 + i + 1, BLACK, WHITE) ; mainPick->m1 = m1 ; i = m1 ; while (i--) graphBoxDraw (mainPick->modeBox1 + i + 1, BLACK, PALEBLUE) ; } if (m2) { graphBoxDraw (mainPick->modeBox2 + mainPick->m2, BLACK, WHITE) ; mainPick->m2 = m2 ; graphBoxDraw (mainPick->modeBox2 + mainPick->m2, BLACK, PALEBLUE) ; if (m2 == 2) mainWindowPick (0, 0, 0, 0) ; } return; } /* pickModeChoice */ static void pickModeChoice10 (void) { pickModeChoice(1,0,1) ; } static void pickModeChoice20(void) { pickModeChoice(2,0,3) ; } static void pickModeChoice30(void) { pickModeChoice(3,0,7) ; } static void pickModeChoice1 (void) { pickModeChoice(0,1,0) ; } static void pickModeChoice2 (void) { pickModeChoice(0,2,0) ; } /* static void pickModeChoice11 (void) { pickModeChoice(1,1,1) ; } static void pickModeChoice12 (void) { pickModeChoice(1,2,2) ; } static void pickModeChoice22 (void) { pickModeChoice(2,2,3) ; } static void pickModeChoice32 (void) { pickModeChoice(3,2,4) ; } */ static void modeSearchEntry (char *dummy) { mainPick->longGrep = FALSE ; switch (10 * mainPick->m1 + mainPick->m2) { case 11: /* names, selected class */ if (!mainPick->curr) { messout("Please select a class or search \"in all classes\"") ; return ; } classDisplayNew (mainPick->curr) ; break ; case 12: /* names, all classes */ classDisplayNew (0) ; break ; case 21: /* text, selected class */ if (!mainPick->curr) { messout("Please select a class or search \"in all classes\"") ; return ; } strcpy (mainPick->grepText, mainPick->template) ; grepDisplayNew (mainPick->curr) ; break ; case 22: /* text, all classes */ strcpy (mainPick->grepText, mainPick->template) ; grepDisplayNew (0) ; break ; case 31: case 32: /* long texts */ mainPick->longGrep = TRUE ; strcpy (mainPick->grepText, mainPick->template) ; grepDisplayNew (0) ; break ; } } static void otherClassChoice (void) { KEY key ; if (graphSelect (&key, arrp (classList, 0, FREEOPT))) classListMenuCall (key, 0) ; } /************************************************************/ static void pickDoDrawNew (void) { int box, i, y ; float line; LAYOUT *z ; int graphWidth, graphHeight ; if (!graphActivate (mainPick->mainGraph)) return ; graphClear() ; #ifndef ACEMBLY if (oxgridPossible()) graphMenu (pickNewOxMenu) ; else #endif /* background menu */ graphMenu (pickNewMenu) ; graphFitBounds (&graphWidth,&graphHeight) ; /* drawing */ line = 0.5 ; mainPick->curr = 0 ; mainPick->currBox = 0 ; /* server/client */ if (externalServerState) { mainPickReport (-1) ; line += 2 ; } /* menu bar */ if (writeAccessPossible()) { if (isWriteAccess()) { box = graphButton("Save..", saveAndKeepWriteAccess, 1., line) ; graphBoxFreeMenu (box, saveMenuFreeAction, saveButtonFreeMenu) ; /* exclude last menu option "Gain write access" */ editButtonFreeMenu[0].key = 11; } else { /* include "gain write access" */ editButtonFreeMenu[0].key = 12; } box = graphButton("Edit..", editSelector,9.,line) ; graphBoxFreeMenu (box, editButtonFreeAction, editButtonFreeMenu) ; } box = graphButton("Query..", querySelector,17.,line) ; graphBoxFreeMenu (box, queryButtonFreeAction, queryButtonFreeMenu) ; mainPick->admin_box = box = graphButton("Admin..", adminSelector,26.,line) ; swopSigCatchMenuText((signalCatchStatus() ? SIG_OFF_TEXT : SIG_ON_TEXT), box) ; graphBoxFreeMenu (box, adminButtonFreeAction, adminButtonFreeMenu) ; box = graphButton("Clear", mainWindowCleanUp,37.,line) ; graphBoxMenu(box, 0); box = graphButton("Help", help, 44.,line + 1.4) ; graphBoxMenu(box, 0); box = graphButton("Exit", exitButtonAction, 44.,line) ; graphBoxMenu(box, 0); line += 1.5 ; /* status */ *mainPick->whatdoIdoText = 0 ; graphText ("Status:", 1, line) ; mainPick->whatdoIdoBox = graphBoxStart() ; graphTextPtr(mainPick->whatdoIdoText, 10, line, ACTIVITY_LENGTH) ; graphBoxEnd() ; line += 1.8 ; /* search box */ /* strcpy (mainPick->template,"*") ; mainPick->templateBox = graphCompScrollEntry (pickClassComplete, mainPick->template, 250, 28,10.0, line, TEXT_ENTRY_FUNC_CAST modeSearch) ; */ graphText ("Search", 1, line +.1) ; mainPick->m1 = 1 ; mainPick->m2 = 1 ; mainPick->m3 = 1 ; mainPick->modeBox2 = graphBoxStart () ; box = graphButton ("in the selected class", pickModeChoice1, 8,line) ; graphBoxMenu(box, 0); graphText ("or", 31, line +.1) ; box = graphButton ("in all classes", pickModeChoice2, 34,line) ; graphBoxMenu(box, 0); graphBoxEnd () ; graphBoxDraw (mainPick->modeBox2 + mainPick->m2, BLACK, PALEBLUE) ; line += 1.6 ; mainPick->modeBox1 = graphBoxStart () ; graphText ("objects", .5, line + .1) ; box = graphButton ("named", pickModeChoice10, 8,line) ; graphBoxMenu(box, 0); graphText ("or", 14.9, line + .1) ; box = graphButton ("related to", pickModeChoice20, 17.9,line) ; graphBoxMenu(box, 0); if (lexMax(_VLongText) > 2) { /* graphText ("+",31.2, line) ; */ box = graphButton ("even in long texts", pickModeChoice30, 30.2,line) ; graphBoxMenu(box, 0); } else { graphBoxStart () ; graphBoxEnd () ;}/* empty box needed for counts */ graphBoxEnd () ; i = mainPick->m1 ; while (i--) graphBoxDraw (mainPick->modeBox1 + i + 1, BLACK, PALEBLUE) ; line += 1.5 ; if (pickFirstTemplate) strcpy(mainPick->template, pickFirstTemplate); else strcpy (mainPick->template,"*") ; mainPick->templateBox = graphCompScrollEntry (pickClassComplete, mainPick->template, 250, 30,10.0, line, modeSearchEntry) ; mainPick->grepBox = mainPick->templateBox; /* in new style window both boxes * in one */ mainPick->longGrepBox = 0; /* don't have this box in new style window */ line += 1.5 ; /* class list */ graphLine (0,line, graphWidth, line) ; line += .7 ; graphText ("Select a class:", 0.5, line) ; box = graphButton ("Other class ...", otherClassChoice, 22, line - .1); graphBoxFreeMenu (box,(FreeMenuFunction) classListMenuCall, arrp (classList, 0, FREEOPT)) ; box = graphButton ("Selection", layoutOpenEditor, 39, line - .1) ; graphBoxMenu(box, 0); line += 1.3 ; y = 0 ; firstClassBox = graphBoxStart () ; for (i = 0 ; i < arrayMax(classLayout) ; ++i) { int b = graphBoxStart () ; z = arrp(classLayout, i, LAYOUT) ; if (z->y > y) y = z->y ; graphText (name(z->key), z->x, z->y + line) ; if (pickFirstClass && (strcasecmp(name(z->key), pickFirstClass) == 0)) { pickFirstBox = b; } graphBoxEnd () ; } graphBoxEnd () ; /* the first classbox that contain the class-chooser boxes forms part of the background as well, so attach the bg-menu as well */ #ifndef ACEMBLY if (oxgridPossible()) graphBoxMenu (firstClassBox, pickNewOxMenu) ; else #endif graphBoxMenu (firstClassBox, pickNewMenu) ; line += y + 2 ; *(mainPick->grepText) = 0 ; messStatus ("Ready"); /* force redraw of whatdoIdoBox */ graphRedraw () ; } /* pickDoDrawNew */ /************************************************************/ static void mainWindowReReadClasses (void) /* called when models change */ { arrayDestroy (classLayout) ; classLayout = layoutRead (0); classList = classListCreate (classList, TRUE, /* listHidden */ TRUE, /* listVisible */ FALSE, /* !listBuried */ TRUE); /* listAllTypes */ return; } /* mainWindowReReadClasses */ /************************************************************/ static void mainStatusDisplay (char *text, void *user_pointer) /* registered using mainActivityRegister() as soon as the * mainGraph is properly drawn and the whatDoIdoBox is a valid box */ { #ifndef MACINTOSH /* non-MACINTOSH */ Pick pick = (Pick)user_pointer ; static char *old = "dummy" ; /* some impossible value */ Graph hold ; if (!pick) /* we don't have a mainWindow yet */ return ; if (pick->magic != &Pick_MAGIC) messcrash("messStatus func mainStatusDisplay() - received in valid " "user_pointer"); if (!text && !old) /* we're asking to reset, but it is already in 'Ready' state, * so we have nothing more to do in this function */ return; hold = graphActive() ; graphActivate(pick->mainGraph) ; if (!text) { old = 0 ; strcpy(pick->whatdoIdoText, "Ready") ; graphBoxDraw(pick->whatdoIdoBox,BLACK,PALEGREEN) ; } else if (text != old) { old = text ; strncpy(pick->whatdoIdoText, text, ACTIVITY_LENGTH-1) ; if (pick->whatdoIdoBox) graphBoxDraw(pick->whatdoIdoBox,BLACK,RED) ; } graphActivate(hold) ; #else /* MACINTOSH */ extern void StartAsyncSpinning (short period) ; extern void StopAsyncSpinning (void) ; static char *old = "dummy" ; /* some impossible value */ if (old != text ) { if (!text) { old = 0 ; StopAsyncSpinning () ; } else if (text != old) { old = text ; StartAsyncSpinning (8) ; } } #endif /* MACINTOSH */ } /* mainStatusDisplay */ static void obDisplay (Pick pick, BOOL show1, int state) /* state = 1 - template unchanged * 2 - added a star at end * 3 - autocomplete */ { /* then switch to the display graph (make if necessary) */ char *message; /* default message */ if (pick->currClasse) message = messprintf("%s:%s",name(pick->currClasse),pick->template) ; else message = messprintf("All classes:%s",pick->template) ; switch (state) { case 1: if (!keySetMax(pick->oblist)) { if (pick->currClasse) message = messprintf("No %s:%s %s", name(pick->currClasse), pick->template, "is the class correct ? ") ; else message = messprintf("No object named %s in any class", pick->template) ; } break ; case 2: if (keySetMax(pick->oblist)) { if (pick->currClasse) message = messprintf("%s:%s %s", name(pick->currClasse), pick->template, "No exact match, * appended") ; else message = messprintf("%s %s", pick->template, "No exact match in any class, * appended") ; } else { if (pick->currClasse) message = messprintf("No %s:%s %s", name(pick->currClasse), pick->template, " is the class correct ? ") ; else message = messprintf("No object named %s in any class", pick->template) ; } break ; case 3: if (keySetMax(pick->oblist) == 0) message = "No possible completion in this class" ; break; case 4: message = "To search text please specify a search string \n" " with at least 3 letters or digits.\n" "Authorized wild chars are\n" " * (any string), ? (single char)." ; break; case 5: if (!keySetMax(pick->oblist)) { state = 4 ; message = messprintf("%s Not found",pick->grepText) ; } else message = messprintf("Search %s",pick->grepText) ; break ; case 6: if (!keySetMax(pick->oblist)) { state = 4 ; message = messprintf("%s Not found",pick->grepText) ; } else message = messprintf("Long Search %s",pick->grepText) ; break ; case 7: if (!keySetMax(pick->oblist)) { state = 4 ; message = messprintf("Text %s Not found in any class", pick->grepText) ; } else message = messprintf("Search %s in all classes",pick->grepText) ; break ; case 8: if (!keySetMax(pick->oblist)) { state = 4 ; message = messprintf("%s Not found in any class", pick->grepText) ; } else message = messprintf("Long Search %s in all classes", pick->grepText) ; break ; case 9: message = messprintf("%s not found hit in selected class, \n" "searched all classes (no hit)", pick->grepText) ; break ; case 10: message = messprintf("%s not found in selected class, \n" "long-searched all classes (no hit)", pick->grepText) ; break ; } switch (state) { case 5: case 6: case 7: case 8: /* costly search, reply in new window */ displayCreate("DtKeySet"); graphRetitle(message) ; keySetMessageShow (pick->oblist,0,message) ; break ; default: /* fast search, reply in main window */ if (graphExists (pick->ksdisp_graph)) keySetMessageShow (pick->oblist, pick->ksdisp_handle, message) ; else { pick->ksdisp_graph = displayCreate("DtKeySet"); graphRetitle("Main KeySet") ; pick->ksdisp_handle = keySetMessageShow (pick->oblist,0,message) ; } break ; } if (keySetMax(pick->oblist) == 1 && show1) { KEY key = keySet(pick->oblist,0) ; display(key, 0, keySetGetShowAs (pick->ksdisp_handle, key)); } pick->oblist = 0 ; /* since given to keySetShow */ #if !defined(WIN32) /* The WIN32 user interface is nicer if I don't do this */ graphActivate (pick->mainGraph) ; #endif } /**************** text action **********************/ static BOOL classDisplay (void) /* displays current option list */ { char *cp ; PICKGET("classDisplay") ; if (!pick->curr) { messout("Please pick a class") ; return FALSE ; } cp = pick->template ; while (*cp == ' ') ++cp ; if (!*cp) { strcpy (pick->template, "*") ; graphBoxDraw (pick->templateBox, -1, -1) ; } graphCompletionEntry (pickClassComplete,pick->template,0,0,0,0) ; return classListMenuCall (arrp(classLayout,pick->curr-1,LAYOUT)->key, 0) ; } /* classDisplay */ /**************** text action **********************/ static BOOL classDisplayNew (int curr) /* displays current option list */ { char *cp ; PICKGET("classDisplay") ; cp = pick->template ; while (*cp == ' ') ++cp ; if (!*cp) { strcpy (pick->template, "*") ; graphBoxDraw (pick->templateBox, -1, -1) ; } graphCompletionEntry (pickClassComplete,pick->template,0,0,0,0) ; return classListMenuCall (curr ? arrp(classLayout,curr-1,LAYOUT)->key : 0, 0) ; } /* classDisplayNew */ /*************************************************/ static void grepDisplayNew (int curr) { KEYSET ob1 = 0, ob2 = 0, ob3 = 0; int n , state ; static int confirm = 0 ; char *cp,*cq ; static char localText[256] , lastText[256] ; PICKGET("grepDisplay") ; /* first check that the search text is non-trivial */ for (n = 0, cp = pick->grepText ; *cp ; ++cp) if (isprint((int)*cp) && *cp != '*' && *cp != '?') ++n ; if (n < 3) { /* messout ("To search text please specify a search string " "with at least 3 letters or digits." " Authorized wild chars are\n" "* (any string), ? (single char).") ; */ pick->longGrep = FALSE ; if (pick->longGrepBox) graphBoxDraw(pick->longGrepBox, BLACK, WHITE) ; pick->oblist = keySetCreate () ; obDisplay (pick, FALSE, 4) ; return ; } /* make localText with a '*' in front of and behind the grep text */ cp = pick->grepText ; if (*cp == '*') cq = localText ; else { *localText = '*' ; cq = localText+1 ; } while ((*cq++ = *cp++)) ; if (cq[-2] != '*') { cq[-1] = '*' ; *cq = 0 ; } /* If the text has not changed, wait for confirmation */ if(!strcmp(localText,lastText)) if(!confirm++) { if (pick->longGrepBox) graphBoxDraw(pick->longGrepBox, BLACK, WHITE) ; return ; } strncpy(lastText,localText,255) ; strncpy(pick->grepText,localText,255) ; confirm = 0 ; /* then do the search */ graphBoxDraw(pick->grepBox,BLACK,RED) ; if (pick->longGrep && pick->longGrepBox) graphBoxDraw(pick->longGrepBox, BLACK, YELLOW) ; if (externalServer) ob1 = externalServer (0, 0, localText, FALSE) ; else ob1 = queryGrep(0, localText) ; if (pick->longGrep) { graphBoxDraw(pick->grepBox,BLACK,YELLOW) ; if (pick->longGrepBox) graphBoxDraw(pick->longGrepBox, BLACK, RED) ; ob2 = longGrep(localText) ; ob3 = keySetOR(ob1, ob2) ; } else { ob3 = ob1 ; ob1 = 0 ; } keySetDestroy(ob1) ; keySetDestroy(ob2) ; graphBoxDraw(pick->grepBox,BLACK,YELLOW) ; state = pick->longGrep ? 6 : 5 ; pick->longGrep = FALSE ; if (pick->longGrepBox) graphBoxDraw(pick->longGrepBox, BLACK, WHITE) ; if (keySetMax(ob3) && curr) /* filter by single class */ { int n2 = keySetMax(ob3), n3 = 0 ; KEY *kp2, *kp3 ; KEY cc = arrp(classLayout, curr-1, LAYOUT)->key ; /* it is better to filter locally than to query, becausee of client/server */ ob2 = arrayCopy (ob3) ; kp2 = arrp(ob2, 0, KEY) ; kp3 = arrp(ob3, 0, KEY) ; while (n2--) { if (lexIsInClass(*kp2, cc)) { *kp3++ = *kp2 ; n3++ ;} kp2++ ; } keySetMax(ob3) = n3 ; if (n3) keySetDestroy (ob2) ; else { state += 4 ; /* report enlarged search */ keySetDestroy (ob3) ; ob3 = ob2 ; ob2 = 0 ; } } else state += 2 ; /* report general failure */ pick->oblist = ob3 ; obDisplay (pick, FALSE, state) ; } static void grepDisplay (char *entry) { grepDisplayNew(0) ; } /**************** pick Action ************/ static int pickClassComplete (char *cp, int len) { int i; PICKGET("pickClassComplete") ; if (!pick->curr) return 0 ; i = ksetClassComplete (cp, len, arrp(classLayout, pick->curr-1, LAYOUT)->key) ; return i; } /* pickClassComplete */ /* disgusting menu stuff...should use the new menu package.... */ static void swopSigCatchMenuText(char *sig_txt, int admin_box) { int i = 0 ; while (adminButtonFreeMenu[i].key != 'x') i++ ; adminButtonFreeMenu[i].text = sig_txt ; graphBoxFreeMenu(admin_box, adminButtonFreeAction, adminButtonFreeMenu) ; return ; } /****************************************/ /****************************************/