/* File: display.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: ** Class sensitive object display ** * Shares and reuse display windows. * Exported functions: * display * displays a Key according to diplayType * if displayType==0, it defaults according to classes.wrm. * Each display type reuses its own window until that window has * been preserved with displayPreserve. * * displayBlock * puts up a message over the current active window and blocks * the display system until a key has been picked somewhere. * the rest of the program still runs. * The registered function receives as parameter the picked key * and, implicitly, the graph it was picked from, which is * active. * * displayUnBlock * Clears out. * * displayRepeatBlock * Reactivates the current blocking function. * * isDisplayBlocked * should be called by clients to prevent access to blocked displays * * displayPreserve * preserves the object, so that the next object of that class * will not reuse its window. * HISTORY: * Last edited: Jan 22 14:16 2004 (rnc) * Created: Sun Dec 1 17:29:54 1991 (mieg) * CVS info: $Id: display.c,v 1.52 2004/01/22 14:22:13 rnc Exp $ *------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* for dnaAnalyse() */ #include /* for queryCreate() */ #include /* for sessionControl() */ /*#include */ #include /* for qbeCreate, qbuildCreate */ #include #include #include #include #include /*#include */ #include #include #include #include #if defined(ZMAP) #include #endif /*********************************************************************/ /**************** program-wide globals *******************************/ /*********************************************************************/ BOOL isGifDisplay = FALSE ; /* used to signal that the graphical session is non-interactive. may be used to unset useless buttons etc */ BOOL displayReportGif = TRUE ; /* if TRUE and isGifDisplay == TRUE then we comment on each display() call to say which object was displayed and how */ /*********************************************************************/ typedef struct AcedbDisplayStruct AcedbDisplay ; struct AcedbDisplayStruct { char title[42], help[32] ; float x, y, width, height ; int type ; /* from GraphType */ } ; /************************************/ static BOOL doDisplay(KEY key, KEY from, char *displayName, void *display_data) ; static void setGraphType (char *displayName, int type); static void setGraphTypes (void); static AcedbDisplay *getDp (char *displayName, KEY *displayKey); static void readDisplayDefaults(void); /* displays.wrm */ static void setDisplayFunctions(void); static Array dArray = 0 ; static Array displayFuncArray = 0 ; static Array previous = 0 ; static Graph blockGraph = 0 ; static BOOL isRepeatBlock = FALSE ; static BlockFunc blockFunc ; #define MAXDISPMENU 30 static FREEOPT dispOptMenu[MAXDISPMENU] = { {1, ""}, {0, "Graph"}, /* shorter name, not too inacurate */ {0, "Text"}, }; static FREEOPT displayOptions[] = { {10, "display options"}, {'g', "GraphType"}, /* ignored in displays.wrm */ {'t', "Title"}, {'w', "Width"}, {'h', "Height"}, {'x', "Xposition"}, {'y', "Yposition"}, {'m', "Menu"}, {'a', "Help"}, {'c', "Columns"}, {'r', "Rows"}, } ; /************************************************************/ /* Must be called before any other display functions. */ void displayInit (void) { /* Set up the static arrays for holding display info. */ dArray = arrayCreate (12, AcedbDisplay) ; displayFuncArray = arrayCreate (32, DisplayFunc) ; previous = arrayCreate (32, Graph) ; /* hook up the display types with their display functions, * This will init the class 'Display' with all the types * the code knows about, this way we can verify the validity * of a vertain displayName when we get to parse displays.wrm */ setDisplayFunctions(); /* parse options.wrm again, but now also set the displayKey for * each class. We do that after we set the display functions. * This makes sure that all displays we have at this point are * actually represented by generic display functions in the code. */ pickGetClassProperties(TRUE); sysClassDisplayTypes(); /* after parsing options.wrm * to override user settings that * would otherwise corrupt */ /* The graphtypes are a code issue, so we set all the defaults * here, thus initialising all possible names in the class 'display' */ setGraphTypes() ; /* now parse displays.wrm to allow the user to override the * defaults geometry etc. for each display. We do that after * setGraphTypes, where all the display types are added to * the class 'Display' that the code knows about. * Options for other displays are ignored.*/ readDisplayDefaults(); return; } /* displayInit */ /*********************************************************************/ /* displayName is now the name of an element of the display sysclass */ /* */ /* */ /* This is the old function, it's used in most of the code but doesn't allow */ /* any data to be passed through by the caller which is sometimes necessary, */ /* hence the new display call. */ /* */ /* This old call always passes in NULL for the display_data. */ /* */ /* the old and new functions are temporary to allow code to work while I */ /* migrate from the old to the new call which allows user data to be passed */ /* through. */ /* */ BOOL display(KEY key, KEY from, char *displayName) { BOOL result ; result = doDisplay(key, from, displayName, NULL) ; return result ; } /* The new call which allows user data to be passed through to the actual */ /* display routine. */ /* */ BOOL displayApp(KEY key, KEY from, char *displayName, void *display_data) { BOOL result ; result = doDisplay(key, from, displayName, display_data) ; return result ; } /* Both the above routines call this one to do the actual work. */ /* */ static BOOL doDisplay(KEY key, KEY from, char *displayName, void *display_data) { BOOL result = FALSE ; KEY displayKey = KEY_UNDEFINED ; Graph g = graphActive() ; /* save */ BOOL gReuse ; DisplayFunc theFunc ; if (!key && !from) messcrash("Call to display() with zero \"key\" and zero \"from\" and displayName = %s.", displayName ? displayName : "(NULL)") ; if (!previous) messcrash("doDisplay() called before displayInit().") ; if (graphActivate (blockGraph)) { (*blockFunc) (key) ; if (isRepeatBlock) isRepeatBlock = FALSE ; else { if (graphActivate (blockGraph)) graphUnMessage () ; blockGraph = 0 ; } graphActivate (g) ; return FALSE ; } /* * Xclient stuff....get object and neighbours */ if (externalServer) externalServer(key, 0, 0, TRUE) ; if (iskey(key) != 2) return FALSE ; /* display must be TREE for the model */ if (!KEYKEY(key) && pickType(key) == 'B') displayName = "TREE" ; if (!displayName) displayKey = pickDisplayKey(key) ; else if (!lexword2key(displayName, &displayKey, _VDisplay)) { messerror ("Display type %s unknown", displayName ? displayName : "(NULL)") ; return FALSE ; /* not displayable */ } if (displayKey == 0) return FALSE ; /* not displayable */ if ((g = array(previous, KEYKEY(displayKey), Graph))) { if (graphActivate(g)) { gReuse = TRUE ; } else { array(previous, KEYKEY(displayKey), Graph) = 0 ; gReuse = FALSE ; } } else gReuse = FALSE; /* Call the display function, if it fails (e.g. because user did not select * an appropriate display type) then: if display type is not objects * natural display type ask user if they want to use the natural one, * otherwise try the tree display as its the most basic object display. */ if ((theFunc = array(displayFuncArray,KEYKEY(displayKey), DisplayFunc))) { result = theFunc(key, from, gReuse, display_data) ; if (!result) { KEY objdisp_key = pickDisplayKey(key) ; BOOL new_display = TRUE ; if (!key) /* Deal with missing key param. */ { key = from ; from = KEY_UNDEFINED ; } if (objdisp_key) { if (objdisp_key != displayKey) { if ((new_display = messQuery("Sorry, object \"%s\" cannot be displayed with " "the \"%s\" display. " "Do you want to display it using the " "\"%s\" display instead ?", nameWithClass(key), name(displayKey), name(objdisp_key)))) displayKey = objdisp_key ; } else { KEY treedisp_key ; if (lexword2key("TREE", &treedisp_key, _VDisplay) && displayKey != treedisp_key) displayKey = treedisp_key ; } if (new_display) { if ((theFunc = array(displayFuncArray, KEYKEY(displayKey), DisplayFunc))) { if ((g = array(previous, KEYKEY(displayKey), Graph))) { if (graphActivate(g)) { gReuse = TRUE ; } else { array(previous, KEYKEY(displayKey), Graph) = 0 ; gReuse = FALSE ; } } else gReuse = FALSE; if (!(result = theFunc(key, from, gReuse, display_data))) messerror ("Sorry, cannot display object \"%s\" with \"%s\" display.", nameWithClass(key), name(displayKey)) ; } } } } if (result) { array(previous, KEYKEY(displayKey), Graph) = graphActive() ; graphPop () ; if (isGifDisplay && displayReportGif) messout("%s %s \"%s\"\n", name(displayKey), className(key), name(key)); } } return result ; } /**********************************/ void displayPreserve (void) { Graph g = graphActive() ; int i ; if (!previous) messcrash("displayPreserve() called before displayInit().") ; i = arrayMax(previous) ; while (i--) if (array(previous,i, Graph) == g) array(previous,i, Graph) = 0 ; return ; } /**************************************/ BOOL displayBlock (BlockFunc func, char *message) { messStatus ("Select by double-clicking") ; /* mhmp nov 97 */ if (graphExists(blockGraph)) /* mieg june 1 */ return FALSE ; blockGraph = graphActive() ; isRepeatBlock = FALSE ; blockFunc = func ; /* if (!getenv("ACEDB_NO_GRAB_WINDOW"))*/ if(!prefValue("NO_MESSAGE_WHEN_DISPLAY_BLOCK")) { graphMessage (messprintf ("%s\n\n%s", "Select an object by double-clicking as\n" "though you were going to display it.", message ? message : "")) ; } return TRUE ; } /**************************************/ void displayRepeatBlock (void) { isRepeatBlock = TRUE ; } /**************************************/ void displayUnBlock(void) { if (blockGraph) /* prevent callback recursion */ { blockGraph = 0 ; graphUnMessage () ; } isRepeatBlock = FALSE ; blockFunc = 0 ; } /**************************************/ BOOL isDisplayBlocked (void) { return (blockGraph != 0) ; } /******************************************/ /******************************************/ /**** next section supports some simple and generic display types ***/ BOOL displayAs (KEY key, KEY from, BOOL isOldGraph, void *app_data) { OBJ obj ; KEY tag, newkey ; if (!(obj = bsCreate (key))) return FALSE ; if (bsFindTag (obj, str2tag ("Display_as")) && bsGetKeyTags (obj, _bsRight, &tag) && bsGetKey (obj, _bsRight, &newkey)) { bsDestroy (obj) ; display (newkey, from, 0) ; return TRUE ; } bsDestroy (obj) ; display (key, from, "TREE") ; return FALSE ; } static int escapeUrl(char *old, char *new) { int len = 0; char c; while ((c = *old++)) { switch (c) { case ' ': c = '+'; /* fall through */ default: if (new) *new++ = c; len++; continue; case '?': case '=': case '+': case '/': case '#': case '&': case '%': case '(': /* these two get mangled by the netscape call interface */ case ')': if (new) { sprintf(new, "%%%2.2X", c); new += 3; } len += 3; continue; } } if (new) *new = 0; return len+1; /* +1 for null terminator */ } BOOL doWWWDisplay (KEY key, KEY from, int recursecount) { OBJ obj, fromObj ; KEY template ; char *url = 0 ; STORE_HANDLE handle ; char *str, *new, *cname, *urlsave=0 ; /* init for compiler happiness */ BOOL result = FALSE ; Array a ; int i, len ; if (recursecount == 20) { messerror("Wild recursion detected in wwwDisplay!"); return FALSE; } if (!(obj = bsCreate (key))) return FALSE; if (bsGetText (obj, str2tag ("URL"), &url)) { BOOL ret; ret = graphWebBrowser(url); bsDestroy (obj); return ret; } if (bsGetKey (obj, str2tag ("Web_location"), &template)) { bsDestroy(obj) ; if (recursecount == 0) return doWWWDisplay (template, key, 1) ; else /* RD 010801 need to pass on original key as from */ return doWWWDisplay (template, from, recursecount+1) ; } if (from == key) { bsDestroy(obj); return FALSE; } handle = handleCreate() ; a = arrayHandleCreate( 10, BSunit, handle) ; /* RD 010801 rewrote next section to consider options correctly */ if (bsFindTag (obj, str2tag ("Reference_tag")) && bsFlatten (obj, 2, a) && (fromObj = bsCreate(from))) { for (i = 0 ; i < arrayMax(a) ; i += 2) if ((!arr(a,i+1,BSunit).s || !strcmp (className(from), arr(a,i+1,BSunit).s)) && bsGetText (fromObj, str2tag(arr(a,i,BSunit).s), &url)) { url = strnew(url, handle); break; } bsDestroy(fromObj); } if (!url && bsFindTag(obj, str2tag("Use_name"))) { if (bsGetText(obj, _bsRight, &cname)) do { /* search for matching class */ if (strcmp(cname, className(from)) == 0) { url = strnew(name(from), handle); break; } } while (bsGetText(obj, _bsDown, &cname)); else url = strnew(name(from), handle) ; /* no class constraint */ } if (!url) /* RD 010801 last chance: try class object */ { if (lexword2key (className(key), &template, _VClass)) { bsDestroy (obj) ; handleDestroy (handle) ; if (recursecount == 0) return doWWWDisplay (template, key, 1) ; else return doWWWDisplay (template, from, recursecount+1) ; } else /* shouldn't get here because there should be a class key */ messcrash ("Richard owes Simon a beer in doWWWdisplay") ; } if (bsFindTag (obj, str2tag("Rewrite")) && bsFlatten(obj, 4, a)) for( i=0; i < arrayMax(a); i +=4) { if ((str = arr(a, i+2, BSunit).s) && strlen(url) >= strlen(str) && strncmp(url, str, strlen(str)) == 0 ) { urlsave = url; /* in case we fail on the next test */ url += strlen(str); } else if (str) continue; /* no string matches */ if ((str = arr(a, i+3, BSunit).s) && (strlen(url) >= strlen(str) && strcmp(url+strlen(url)-strlen(str), str) == 0)) *(url+strlen(url)-strlen(str)) = 0; else if (str) /* no string matches */ { url=urlsave;/* restore */ continue; } /* now url has pref/postfixes removed, escape url-dangerous chars */ /* before adding new ones, only do this when using object name or */ /* reference tag, not a hard-specified URL */ new = (char *)halloc(escapeUrl(url, 0), handle); (void)escapeUrl(url, new); url = new; /* now add prefix and postfix */ len = 1+strlen(url); if (arr(a, i, BSunit).s) len += strlen(arr(a, i, BSunit).s); if (arr(a, i+1, BSunit).s) len += strlen(arr(a, i+1, BSunit).s); new = (char *)halloc(len, handle); if (arr(a, i, BSunit).s) strcpy(new, arr(a, i, BSunit).s); strcat(new, url); if (arr(a, i+1, BSunit).s) strcat(new, arr(a, i+1, BSunit).s); result = graphWebBrowser (new) ; goto done ; } done: bsDestroy (obj) ; handleDestroy (handle) ; return result ; } BOOL wwwDisplay (KEY key, KEY from, BOOL isOldGraph, void *unused) { return doWWWDisplay( key, from, 0); } /******************************************/ /********* Display Customization *********/ /******************************************/ Graph displayCreate(char *displayName) { AcedbDisplay *dp = 0 ; Graph g ; float x, y ; static Array a = 0 ; int i ; KEY key = 0 ; if (!displayName) return 0 ; /* by this time the displayName is guaranteed to exist in the * 'Display' class unless a new name comes along */ if (!(dp = getDp(displayName, &key))) messcrash("displayCreate() - unknown display %s\n" "possible programmer typo in calling code or " "the name isn't registered with the code, check " "setGraphTypes() and setDisplayFunctions() !", displayName); /***** A trick to prevent window superposition ***/ if (!a) a = arrayCreate(20, Graph) ; for (i = 0 ; i < arrayMax(a) ; i++) if (!graphExists(arr(a,i,Graph))) break ; x = dp->x + i/30.0 ; while (x > 1.0) x -= 1.0 ; /* prevent overflow HJC */ y = dp->y + i/30.0 ; while (y > 1.0) y -= 1.0 ; /* This is useful if the window manager does not * prompt the user, and is called by displayCreate */ g = graphCreate(dp->type , dp->title, x, y, dp->width, dp->height) ; /* if (dp->type == TEXT_HSCROLL) graphTextBounds(80, 24); */ if (g) graphHelp(dp->help) ; array(a,i,Graph) = g ; return g ; } /* displayCreate */ /**************************************/ /* WHO PUT THIS IN....AAGGGGHHHHH.... */ /* some display modules don't have public includes for the DisplayFunc yet */ extern BOOL pepDisplay (KEY, KEY, BOOL, void *), gMapDisplay (KEY, KEY, BOOL, void *), /* can't include gmap.h as it clashes with other includes */ alignDisplay (KEY, KEY, BOOL, void *), fingerPrintDisplay (KEY, KEY, BOOL, void *), multiTraceDisplay (KEY, KEY, BOOL, void *), metabDisplay (KEY, KEY, BOOL, void *), cMapDisplay (KEY, KEY, BOOL, void *), dendrogramDisplay(KEY, KEY, BOOL, void *), imageDisplay (KEY, KEY, BOOL, void *) ; /**************************************/ /* some Get/Set functions for display data. */ FREEOPT *displayGetShowTypesMenu(void) { return dispOptMenu; } /* displayGetShowTypesMenu */ char *displayGetTitle(char *displayName) { char *title = NULL ; AcedbDisplay *dp; if ((dp = getDp(displayName, 0))) title = dp->title ; return title ; } /* displayGetTitle */ /* Get the graph for the "current" display of the named display type * (e.g. "FMAP"), this may be GRAPH_NULL if there is no current display * of that type or all displays of that type are "preserved". */ Graph displayGetGraph(char *displayName) { Graph display_graph = GRAPH_NULL ; KEY displayKey = KEY_UNDEFINED ; if (!displayName || !*displayName || !lexword2key(displayName, &displayKey, _VDisplay)) messcrash("Invalid display type name: %s", (!displayName ? "NULL ptr" : (!*displayName ? "NULL string" : displayName))) ; display_graph = array(previous, KEYKEY(displayKey), Graph) ; return display_graph ; } /* Set the graph for the "current" display of the named display type * (e.g. "FMAP"), graph may be GRAPH_NULL to remove a particular displa * type from the list. */ void displaySetGraph(char *displayName, Graph graph) { KEY displayKey = KEY_UNDEFINED ; if (!displayName || !*displayName || !lexword2key(displayName, &displayKey, _VDisplay)) messcrash("Invalid display type name: %s", (!displayName ? "NULL ptr" : (!*displayName ? "NULL string" : displayName))) ; array(previous, KEYKEY(displayKey), Graph) = graph ; return ; } /* set default size for all displays, to be used after displayInit */ /* used by 'dimensions' in giface */ void displaySetSizes (int wpixels, int hpixels) { TABLE *displayList; int i; KEY d; displayList = aqlTable("select all class Display", (ACEOUT)NULL, 0); if (displayList) for (i = 0; i < tabMax(displayList, 0); i++) { d = KEYKEY(tabKey(displayList, i, 0)); if (arr(displayFuncArray, d, DisplayFunc)) { /* this is a real object display, with a DisplayFunc */ displaySetSize(name(tabKey(displayList, i, 0)), wpixels, hpixels); } } tableDestroy (displayList); return; } /* displaySetSizes */ void displaySetSize (char *displayName, int wpixels, int hpixels) { KEY displayKey ; Graph existingGraph, oldGraph = graphActive(); AcedbDisplay *dp; static float xfac = -1, yfac; float sw, sh, wfraction, hfraction ; int pw, ph; /* the width and height factors required by the graphPackage * are fractions given relative to window size of 900x900, * example window size of 450x450 pixels requires * wfraction, hfraction = 0.5 */ if (xfac == -1) { /* init only once, screen size doesn't change */ graphScreenSize (&sw, &sh, 0, 0, &pw, &ph) ; xfac = sw/pw ; yfac = sh/ph ; } wfraction = xfac * wpixels; hfraction = yfac * hpixels; dp = getDp(displayName, &displayKey); if (!dp) return; /* we're resetting dimensions, so next time we display a new * window should be opened with the new dimensions, we there * erase the record of a previous open window, to avoid reuse * of an old window with the old size. */ if ((existingGraph = array(previous,KEYKEY(displayKey), Graph)) && graphActivate(existingGraph)) { if (wfraction != dp->width || hfraction != dp->height) /* if we've changed the parameters, then force a new window next time, so the new dimension take effect */ array(previous,KEYKEY(displayKey), Graph) = 0; } dp->width = wfraction; dp->height = hfraction; graphActivate(oldGraph); return; } /* displaySetSize */ void displaySetSizeFromWindow (char *displayName) /* register current window size for next display create */ { float sx, sy, sw, sh ; int pw, ph; static float xfac = -1, yfac; if (xfac == -1) { /* init only once, screen size doesn't change */ graphScreenSize (&sw, &sh, 0, 0, &pw, &ph) ; xfac = sw/pw ; yfac = sh/ph ; } if (graphWindowSize (&sx, &sy, &sw, &sh)) displaySetSize (displayName, sw / xfac, sh / yfac) ; return; } /* displaySetSizeFromWindow */ BOOL displayIsObjectGeneric(char *displayName, KEY *keyp) /* only returns true if the given name is a valid display type * for generic object displays, * i.e. a display with registered function */ { KEY d, displayKey; if (lexword2key(displayName, &displayKey, _VDisplay)) { if (keyp) *keyp = displayKey; d = KEYKEY(displayKey); if (arr(displayFuncArray, d, DisplayFunc)) return TRUE; } if (keyp) *keyp = 0; return FALSE; } /* displayIsObjectGeneric */ BOOL displayIsValid(char *displayName, KEY *keyp) /* is true if the given name is any valid display name */ { KEY displayKey; if (lexword2key(displayName, &displayKey, _VDisplay)) { if (keyp) *keyp = displayKey; return TRUE; } if (keyp) *keyp = 0; return FALSE; } /* displayIsValid */ /**************** private functions *****************/ static void readDisplayDefaults(void) /* parse displays.wrm */ { AcedbDisplay *dp ; int line = 0 ; char *cp ; float x ; KEY option, displayKey, treeKey; FILE *fil = 0; char *filename = dbPathFilName("wspec", "displays", "wrm", "r", 0); if (filename) /* check first to avoid messerror */ { fil = filopen(filename, 0, "r"); messfree(filename); } if (!fil) { messerror("Cannot find display definition file : wspec/displays.wrm"); return; } dispOptMenu[0].key = 2; /* since this gets called twice... */ if (!lexword2key("TREE", &treeKey, _VDisplay)) messcrash("readDisplayDefaults() - can't find Display TREE to provide as display default"); dispOptMenu[2].key = treeKey ; /* provide a tree default unless overridden */ /* Defaults */ while(line ++ ,freeread(fil)) /* read _D... */ if ((cp = freeword()) && *cp++ == '_' && *cp++ == 'D') { if(!*cp) messExit("Error parsing line %d of wspec/displays.wrm", line); if (!(dp = getDp(cp, &displayKey))) { /* unrecognised display type */ #ifdef ABORT_ON_BAD_TYPE TABLE *displayList = aqlTable("select all class Display order", 0); Stack s = stackCreate(300); int i; /* present a list of types that have been defined before */ for (i = 0; i < tableMax(displayList); ++i) { catText(s, messprintf("%s\n", name(tabKey(displayList, i, 0)))); } messExit("Error in wspec/displays.wrm at line %d : " "unrecognised display type %s!\n" "Choose from possible types :\n" "%s", line, cp, popText(s)); #else continue; #endif /* ABORT_ON_BAD_TYPE */ } while (TRUE) { freenext() ; if (!freestep('-')) { if ((cp = freeword())) messExit ("Error in wspec/displays.wrm at line %d : " "option %s has to start with dash ('-') !", line, freepos()) ; else break ; } freenext() ; if (!freekey(&option, displayOptions)) messExit ("Error in wspec/displays.wrm at line %d : " "unknown option %s", line , freepos()) ; switch (option) { case 'm': cp = freeword(); if (dispOptMenu[0].key < MAXDISPMENU-1) { int where; if (displayKey == treeKey) where = 2; else where = ++dispOptMenu[0].key; dispOptMenu[where].key = displayKey; dispOptMenu[where].text = strnew(cp, 0); } break; case 't': cp = freeword() ; strncpy(dp->title, cp, 41) ; break ; case 'a': if ((cp = freeword())) strncpy(dp->help, cp, 31) ; break ; case 'g': /* GraphType (enum) IGNORED */ freeword() ; /* skip */ /* we don't allow the user anymore to set this parameter - * the graphType is a code issue, and it would be too * easy to crash the code by setting an unexpected * graphType in displays.wrm! */ break ; case 'x': if (!freefloat(&x)) messExit("Error in wspec/displays.wrm at line %d : " "Missing float x value at %s", line, freepos()) ; if (x < 0 || x > 1.3) messout ("Error in wspec/displays.wrm at line %d : " "x value %f out of range 0.0 .. 1.3", line, x ) ; else dp->x = x ; break ; case 'w': if (!freefloat(&x)) messExit("Error in wspec/displays.wrm at line %d : " "Missing float width value %s", line, freepos()) ; if (x > 1.3) messout ("Error in wspec/displays.wrm at line %d : " "width value %f out of range 0.0 .. 1.3", line, x ) ; else dp->width = x ; break ; case 'c': if (!freefloat(&x)) messExit("Error in wspec/displays.wrm at line %d : " "Missing float columns value %s", line, freepos()) ; /* negative width is interpreted in char/pixel units by the graph package. */ dp->width = -x ; break ; case 'y': if (!freefloat(&x)) messExit("Error in wspec/displays.wrm at line %d : " "Missing float y value at %s", line, freepos()) ; if (x < 0 || x > 1.0) messout ("Error in wspec/displays.wrm at line %d : " "y value %f out of range 0.0 .. 1.0", line, x ) ; else dp->y = x ; break ; case 'h': if (!freefloat(&x)) messExit("Error in wspec/displays.wrm at line %d : " "Missing float height value at %s", line, freepos()) ; if (x > 1.0) messout ("Error in wspec/displays.wrm at line %d : " "height value %f out of range 0.0 .. 1.0", line, x ) ; else dp->height = x ; break ; case 'r': if (!freefloat(&x)) messExit("Error in wspec/displays.wrm at line %d : " "Missing float rows value %s", line, freepos()) ; /* negative width is interpreted in char/pixel units by the graph package. */ dp->height = -x ; } } } filclose (fil); return; } /* readDisplayDefaults */ static AcedbDisplay *getDp (char *displayName, KEY *displayKey) { AcedbDisplay *dp ; KEY d, dKey; if (!lexword2key(displayName, &dKey, _VDisplay)) return 0; d = KEYKEY (dKey) ; if (!dArray) messcrash("getDp() called before displayInit"); dp = arrayp(dArray, d, AcedbDisplay) ; if (!dp->width && !dp->height) { dp->x = .001 ; dp->y = 0.001 ; dp->width = .5 ; dp->height = .3 ; strncpy(dp->title, displayName, 31) ; strncpy(dp->help, "", 31) ; } if (displayKey) *displayKey = dKey; return dp; } /* getDp */ static void setDisplayFunc(char *displayName, DisplayFunc f) { KEY displayKey = 0 ; /* although these displays may not have been defined in * displays.wrm, we make sure that they exist in the * class 'Display', because these are types that the code * is guaranteed to know about, because it links in functions * to deal with their display (hence lexaddkey...) */ lexaddkey (displayName, &displayKey, _VDisplay) ; array (displayFuncArray , KEYKEY (displayKey), DisplayFunc) = f ; return; } /* setDisplayFunc */ /************************************************************/ /* For each display type that is a generic object display, you must provide a display function and register it by a line of code in the following function : */ static void setDisplayFunctions (void) { /* System hooks */ setDisplayFunc ("TREE", treeDisplay) ; setDisplayFunc ("DtKeySet", keySetDisplay) ; setDisplayFunc ("DtForest", forestDisplay) ; setDisplayFunc ("DtLongText", longTextDisplay) ; setDisplayFunc ("DISPLAY_AS", displayAs) ; setDisplayFunc ("WWW", wwwDisplay) ; setDisplayFunc ("DtSpreadSheet", tableDisplay) ; setDisplayFunc ("DtTableResult", tableResultDisplay) ; /* Application hooks */ setDisplayFunc ("PMAP", pMapDisplay) ; setDisplayFunc ("GMAP", gMapDisplay) ; setDisplayFunc ("VMAP", vMapDisplay) ; setDisplayFunc ("FMAP", (DisplayFunc)fMapDisplay) ; #ifdef ZMAP setDisplayFunc ("ZMAP", (DisplayFunc)zMapCall) ; #endif setDisplayFunc ("CMAP", cMapDisplay) ; setDisplayFunc ("DtMULTIMAP", multiMapDisplay) ; setDisplayFunc ("DtPmapFingerprint", fingerPrintDisplay) ; setDisplayFunc ("PEPMAP", (DisplayFunc)pepDisplay) ; setDisplayFunc ("DtAlignment", alignDisplay) ; setDisplayFunc ("GRID", gridDisplay) ; setDisplayFunc ("DtImage", imageDisplay) ; setDisplayFunc ("METAB", metabDisplay) ; setDisplayFunc ("DtDendrogram", dendrogramDisplay) ; #ifdef ACEMBLY setDisplayFunc ("DtMultiTrace", multiTraceDisplay) ; #endif return; } /* setDisplayFunctions */ static void setGraphType (char *displayName, int type) { KEY displayKey = 0 ; AcedbDisplay *dp ; lexaddkey (displayName, &displayKey, _VDisplay) ; dp = getDp(displayName, 0); dp->type = type ; return; } /* setGraphType */ static void setGraphTypes (void) /* set here the type of all graphs to the types * that the code copes with */ { /* system display routines */ setGraphType ("TREE", TEXT_FULL_SCROLL) ; setGraphType ("DtKeySet", TEXT_FIT) ; setGraphType ("DtForest", TEXT_FIT) ; setGraphType ("DtChrono", TEXT_FULL_SCROLL) ; setGraphType ("DtLongText", TEXT_FULL_SCROLL) ; /* DISPLAY_AS and WWW have no graphs as such */ /* graphical display extensions */ setGraphType ("PMAP", TEXT_FIT) ; setGraphType ("GMAP", TEXT_FIT) ; setGraphType ("VMAP", TEXT_FIT) ; setGraphType ("FMAP", TEXT_HSCROLL) ; setGraphType ("CMAP", TEXT_FIT) ; setGraphType ("DtMULTIMAP", TEXT_FIT) ; setGraphType ("DtPmapFingerprint", TEXT_FULL_SCROLL) ; setGraphType ("PEPMAP", TEXT_FIT) ; setGraphType ("DtAlignment", TEXT_FULL_SCROLL) ; setGraphType ("GRID", TEXT_FULL_SCROLL) ; setGraphType ("DtImage", PIXEL_SCROLL) ; setGraphType ("METAB", TEXT_FULL_SCROLL) ; setGraphType ("DtDendrogram", TEXT_FULL_SCROLL) ; #ifdef ACEMBLY setGraphType ("DtMultiTrace", TEXT_FIT) ; #endif /* these display types are not generic, they can't be used for displaying objects, they are just here, so their size can be configured in displays.wrm */ setGraphType ("DtMain", TEXT_FIT) ; setGraphType ("DtLayoutEditor", TEXT_FIT) ; setGraphType ("DtPreferenceEditor", TEXT_SCROLL) ; setGraphType ("DtFile_Chooser", TEXT_SCROLL) ; setGraphType ("DtHelp", TEXT_FULL_SCROLL) ; setGraphType ("DtAce_Parser", TEXT_SCROLL) ; setGraphType ("DtDump", TEXT_SCROLL) ; setGraphType ("DtSession", TEXT_FULL_SCROLL) ; setGraphType ("DtStatus", TEXT_SCROLL) ; setGraphType ("DtUpdate", TEXT_SCROLL) ; setGraphType ("DtQuery", TEXT_SCROLL) ; setGraphType ("DtQueryBuilder", TEXT_FULL_SCROLL) ; setGraphType ("DtQueryByExample", TEXT_FULL_SCROLL) ; setGraphType ("DtSpreadSheet", TEXT_SCROLL) ; /* table-maker window */ setGraphType ("DtTableResult", TEXT_FULL_SCROLL) ; setGraphType ("DtAqlQuery", TEXT_FIT) ; setGraphType ("DtAction", TEXT_FIT) ; setGraphType ("DtBiblio", TEXT_FULL_SCROLL) ; setGraphType ("DtColControl", TEXT_FIT) ; setGraphType ("DtAlign", TEXT_FULL_SCROLL) ; setGraphType ("DtCodons", TEXT_FIT) ; setGraphType ("DtDnaTool", TEXT_SCROLL) ; setGraphType ("DtGel", TEXT_FIT) ; setGraphType ("DtAlias", TEXT_FIT) ; setGraphType ("DtHistogram", TEXT_FIT) ; setGraphType ("OXGRID", TEXT_FULL_SCROLL) ; setGraphType ("PAIRMAP", TEXT_FULL_SCROLL) ; setGraphType ("O2MMAP", TEXT_FULL_SCROLL) ; setGraphType ("OxgridChoose", TEXT_FULL_SCROLL) ; setGraphType ("SPECGRID", TEXT_FULL_SCROLL) ; #ifdef CHRONO setGraphType ("DtChrono", TEXT_SCROLL) ; #endif /* CHRONO */ return; } /* setGraphTypes */ /************ end of file ****************/