/* Trying to isolate SUMA's help functions so that they can be used from AFNI */ #include #include #include #include #include #include #include "mrilib.h" #include "niml.h" #include "../niml/niml_private.h" #include "suma_objs.h" /* 21 Apr 2020 */ #include /*------------------------------------------------------------*/ #ifndef _MCW_XUTIL_HEADER_ /* 10 Jul 2020 */ extern void MCW_register_hint( RwcWidget , char * ) ; extern void MCW_reghint_children( RwcWidget , char * ) ; extern void MCW_register_help( RwcWidget , char * ) ; extern void MCW_reghelp_children( RwcWidget , char * ) ; #endif /*------------------------------------------------------------*/ static DList *All_GUI_Help = NULL; static char *DocumentedWidgets = NULL; /*!< Widget names for which a Sphinx documentation entry has been created */ char *SUMA_get_DocumentedWidgets(void) { return(DocumentedWidgets); } char *SUMA_set_DocumentedWidgets(char **s) { static char FuncName[]={"SUMA_set_DocumentedWidgets"}; if (!s || !*s) { SUMA_S_Err("Come on friend!"); SUMA_RETURN(DocumentedWidgets); } SUMA_ifree(DocumentedWidgets); DocumentedWidgets = *s; *s = NULL; SUMA_RETURN(DocumentedWidgets); } void SUMA_free_DocumentedWidgets(void) { SUMA_ifree(DocumentedWidgets); return; } void SUMA_Free_Widget_Help(void *data) { static char FuncName[]={"SUMA_Free_Widget_Help"}; GUI_WIDGET_HELP *gwh = (GUI_WIDGET_HELP *)data; SUMA_ENTRY; if (data) SUMA_free(data); SUMA_RETURNe; } /* Format help key string */ char * SUMA_hkf_eng(char *keyi, TFORM target, char *cm) { static char FuncName[]={"SUMA_hkf_eng"}; static char ss[20][512]; char key1[256], key2[256], *direc="kbd"; static int c; char *s, cs[5]={""}, *wname_URI=NULL; int ichar=-1; if (!cm) cm = ""; ++c; if (c > 19) c = 0; s = (char *)ss[c]; s[0] = s[511] = '\0'; if (!keyi) return(s); switch (target) { default: case TXT: /* SUMA */ /* Actually COMMA, PERIOD, STAR mods are not needed, leave for posterity.*/ if (strstr(keyi,"COMMA")) { snprintf(key1, 255, ","); } else if (strstr(keyi,"PERIOD")) { snprintf(key1, 255, "."); } else if (strstr(keyi,"STAR")) { snprintf(key1, 255, "*"); } else { snprintf(key1, 255, "%s", keyi); } snprintf(s, 511, " %s", key1); return(s); break; case SPX: /* Sphinx */ if (strstr(keyi,"->") == keyi) { /* Won't work if you pass key with blanks before '->' But why do such a thing? */ snprintf(key1, 255, "%s", keyi+2); snprintf(key2, 255, "%s", keyi+2); direc = "menuselection"; } else { snprintf(key1, 255, "%s", keyi); snprintf(key2, 255, "%s", keyi); direc = "kbd"; } if (key1[1] == '\0') { ichar = 0; } else if (key1[strlen(key1)-2] == '+'){ ichar = strlen(key1)-1; } else ichar = -1; if (ichar > -1) { if (SUMA_IS_UPPER_C(key1[ichar])) { sprintf(cs,"UC_"); } else { sprintf(cs,"LC_"); } } else { cs[0] = '\0'; } #if 0 /* Good for sphinx, not good for having permalinks ! */ snprintf(s, 511, "\n.. _%s%s%s:\n\n:%s:`%s`" , cm, cs, deblank_allname(key1,'_') , direc, deblank_name(key2)); #elif 1 /* Good for sphinx and for permalinks */ direc = ""; snprintf(s, 511, "\n.. _%s%s%s:\n\n:ref:`%s %s<%s%s%s>`" , cm, cs, deblank_allname(key1,'_') , deblank_name(key2), direc, cm, cs, deblank_allname(key1,'_')); #else /* Brute force, and a pain, as you can see below. Left here as illustration for 'raw html use */ /* Note that I endup with two labels for the key, one as an html permalink and another sphinx one preceding the text of the first line. The reason this was done has to do with how the help for each key is defined explicitly in a series of SUMA_StringAppend() calls. I could skip the second (sphinx) label but then my html page would have ':' at the beginning of each line. The solution would be to store the help for each key much as I do for each widget and make SUMA_hkf() take the 1st line and body (a parallel to the widget hint and help) as options. That's a lot of tediousness I don't care for quite yet. */ wname_URI = SUMA_append_replace_string(cm, deblank_allname(key1,'_'),cs,0); SUMA_Sphinx_Widget_Name_2_Link(wname_URI); snprintf(s, 511, "\n" ".. _%s%s%s:\n" "\n" ".. only:: latex or latexpdf\n" "\n" " :%s:`%s`\n" "\n" "..\n" "\n" ".. only:: html\n" "\n" " .. raw:: html\n" "\n" "
\n" "

" "%s:

\n" "\n" "..\n" "\n" ":%s:`%s`", cm, cs, deblank_allname(key1,'_') , direc, deblank_name(key2), wname_URI, wname_URI, deblank_name(key2), deblank_name(key2), direc, deblank_name(key2)); SUMA_ifree(wname_URI); #endif return(s); break; } return(s); } char * SUMA_hkf(char *keyi, TFORM target) { /* for main suma area keys */ return(SUMA_hkf_eng(keyi,target,"")); } char * SUMA_hkcf(char *keyi, TFORM target) { /* for colormap area keys */ return(SUMA_hkf_eng(keyi,target,"CM_")); } char *SUMA_Sphinx_Widget_Name_2_Link(char *name) { static char FuncName[]={"SUMA_Sphinx_Widget_Name_2_Link"}; int m_i, m_c=0; SUMA_ENTRY; if (name) { SUMA_TO_LOWER(name); if (name[strlen(name)-1] == '.') name[strlen(name)-1]='\0'; for (m_i=0, m_c=0; m_i') { /* ignore it */ } else { name[m_c++] = name[m_i]; } } } name[m_c] = '\0'; SUMA_RETURN(name); } /* Format GUI section */ char * SUMA_gsf_eng(char *uwname, TFORM target, char **hintout, char **helpout) { static char FuncName[]={"SUMA_gsf_eng"}; static char ss[20][512], wnameclp[256]; char key1[256], key2[256], *direc="kbd", *lnm=NULL; static int c; char *s=NULL, *su=NULL, *shh=NULL, *sii=NULL, *stmp=NULL, *wname = NULL, *wname_URI=NULL; int ichar=-1, i, ntip=0; SUMA_Boolean found = NOPE; GUI_WIDGET_HELP *gwh=NULL, *gwhi=NULL; SUMA_Boolean LocalHead = NOPE; ++c; if (c > 19) c = 0; s = (char *)ss[c]; s[0] = s[511] = '\0'; if ((helpout && *helpout) || (hintout && *hintout)) { SUMA_S_Err("string init error"); return(s); } if (!uwname) return(s); /* make a copy, uwname is likely a static pointer from a convenience function. Could change underneath you */ wname = SUMA_copy_string(uwname); switch (target) { default: case TXT: /* SUMA */ snprintf(s, 511, " %s", wname); SUMA_ifree(wname); return(s); break; case WEB: SUMA_LH("Webbing with %s", wname); if (helpout || hintout) { SUMA_S_Err("Not supposed to call WEB as target with " "helpout or hintout"); SUMA_ifree(wname); return(s); } lnm = SUMA_copy_string(wname); if (!(gwh = SUMA_Get_GUI_Help(lnm, target, NULL, NULL,0))) { SUMA_S_Err("No help for %s\n", lnm); SUMA_suggest_GUI_Name_Match(lnm, 8, NULL); } SUMA_ifree(lnm); if (!gwh) { SUMA_ifree(wname); return(s); } found = NOPE; lnm = SUMA_copy_string(wname); if (gwh->type == 1) { /* a regular olde widget */ /* DO NOT rely on SUMA_is_Documented_Widget() outside of targ == WEB */ if (!SUMA_is_Documented_Widget(lnm)) { /* Not all widget in a table have entries so get rid of .c??, .r??, .[*], or .[*,*] and try again. */ ntip = strlen(lnm)-1; if (ntip > 4) { while (ntip > 0 &&lnm[ntip] != '.') --ntip; } if ( (strlen(lnm)-ntip) == 4 && (lnm[ntip+1] == 'r' || lnm[ntip+1] == 'c') && SUMA_IS_DIGIT(lnm[ntip+2]) && SUMA_IS_DIGIT(lnm[ntip+3]) ) { lnm[ntip] = '\0'; } else if ((strlen(lnm)-ntip) > 3 && lnm[strlen(lnm)-1] == ']' && lnm[ntip+1] == ']') { lnm[ntip] = '\0'; } /* try again */ if (SUMA_is_Documented_Widget(lnm)) { SUMA_LH("Found after much suffering as %s", lnm); found = YUP; } } else { SUMA_LH("Got Widget with %s, %s", s, lnm); found=YUP; } } snprintf(s,511,"https://afni.nimh.nih.gov/pub/dist/doc/htmldoc"); if (found) { SUMA_Sphinx_Widget_Name_2_Link(lnm); SUMA_strncat(s,"/SUMA/Controllers.html#", 511); SUMA_strncat(s,lnm,511); SUMA_ifree(sii); SUMA_ifree(lnm); } else { /* Either a container widget or a widget for which no match was found */ /* backup until you find a container widget then try for it */ gwhi = NULL; i = 1; while (!gwhi && i < gwh->name_lvl){ /* Try some guessing. Before March 4 2015 only headings had permalinks created by SPHINX. Now I manually insert permalinks for the vast majority of the widgets. Still, some widgets such as table cells, or frames, might not have their own entries so we try to get help from their container */ stmp = SUMA_copy_string(SUMA_Name_GUI_Help_eng(gwh,-i)); SUMA_LH("Now at %s", stmp); gwhi = SUMA_Get_GUI_Help(stmp, target, NULL, NULL, 0); if (gwhi && gwhi->type == 0) { SUMA_LH("Got one at %s!",stmp); } else { gwhi = NULL; /* try again */ } SUMA_ifree(stmp); ++i; /* keep going lower */ } gwh = gwhi; if (!gwh || gwh->name_lvl<1) { SUMA_LH("No good link found, going with default"); SUMA_ifree(wname); return(s); } /* Turn the container name to a link */ if (gwh->hint) { sii = SUMA_copy_string(gwh->hint); SUMA_Sphinx_Widget_Name_2_Link(sii); SUMA_strncat(s,"/SUMA/Controllers.html#", 511); SUMA_strncat(s,sii,511); SUMA_ifree(sii); } } SUMA_ifree(wname); return(s); break; case SPX: /* Sphinx */ if (!(gwh = SUMA_Get_GUI_Help(wname, target, &shh, &sii,3))) { SUMA_S_Err("No help for %s\n", wname); SUMA_suggest_GUI_Name_Match(wname, 8, NULL); shh = SUMA_copy_string(wname); sii = SUMA_copy_string(wname); } if (!sii) sii = SUMA_copy_string("No Hint"); if (helpout) *helpout = shh; if (hintout) *hintout = sii; if (!gwh) { if (!hintout) SUMA_ifree(sii); SUMA_ifree(wname); return(s); } su = (char *)SUMA_calloc(strlen(sii)+2, sizeof(char)); lnm = gwh->name[gwh->name_lvl-1]; snprintf(wnameclp, 255, "%s", lnm); if (strstr(wnameclp,".r00")) { /* get rid of .r00 */ wnameclp[strlen(lnm)-4]='\0'; } if (strstr(wnameclp,".c00")) { /* get rid of .c00 */ wnameclp[strlen(lnm)-4]='\0'; } switch (gwh->type) { case 0: /* container only */ if (gwh->name_lvl == 1) { for (i=0; iname_lvl == 2) { for (i=0; iname_lvl == 3) { for (i=0; iname_lvl == 4) { for (i=0; i`: %s\n" "\n", wname, wnameclp, wname, sii); #else /* Brute force, and a pain, as you can see below. Left here as illustration for 'raw html use */ /* The "only::" directives below are not necessary if we are only producing html output. I kept them in should we build other than html in the future */ wname_URI = SUMA_copy_string(wname); SUMA_Sphinx_Widget_Name_2_Link(wname_URI); snprintf(s, 511, "\n" " .. _%s:\n" "\n" " .. only:: latex or latexpdf\n" "\n" " **%s**:\n" "\n" " ..\n" "\n" " .. only:: html\n" "\n" " .. raw:: html\n" "\n" "
\n" "

" "%s: %s

\n" "\n" " ..\n" "\n", wname, wnameclp, wname_URI, wname_URI, wnameclp, wnameclp,sii); SUMA_ifree(wname_URI); #endif break; case 2: /* Just permalink, no text to appear on purpose */ wname_URI = SUMA_copy_string(wname); SUMA_Sphinx_Widget_Name_2_Link(wname_URI); snprintf(s, 511, "\n" ".. only:: html\n" "\n" " .. raw:: html\n" "\n" "
\n" "

" "

\n" "\n" "..\n" "\n", wname_URI, wname_URI, wnameclp); SUMA_ifree(wname_URI); break; default: SUMA_S_Err("Bad type %d", gwh->type); break; } if (!hintout) SUMA_ifree(sii); if (!helpout) SUMA_ifree(shh); SUMA_ifree(su); SUMA_ifree(wname); return(s); break; } return(s); } /* Register help for a widget. This is to replace all individual calls to MCW_register_help and _hint. Pointer to help is copied so make sure help is not freed. Widget help becoming centralized to help with auto generation of help webpage */ SUMA_Boolean SUMA_Register_Widget_Help(RwcWidget w, int type, char *name, char *hint, char *help) { static char FuncName[]={"SUMA_Register_Widget_Help"}; char *s=NULL, *st=NULL; SUMA_ENTRY; if (!SUMA_Register_GUI_Help(name, hint, help, w, type)) { SUMA_S_Err("Failed at string level registration"); SUMA_RETURN(NOPE); } if (w) { if (help) { s = SUMA_copy_string(help); s = SUMA_Sphinx_String_Edit(&s, TXT, 0); st = s; s = SUMA_Break_String(st, 60); SUMA_ifree(st); /* DO not free s, MCW_register_help uses the pointer as data to the help callback */ MCW_register_help(w, s); } if (hint) { /* Just make a copy of the hint and don't worry about what got passed! */ s = SUMA_copy_string(hint); MCW_register_hint(w, s); } } SUMA_RETURN(YUP); } SUMA_Boolean SUMA_Register_Widget_Children_Help(RwcWidget w, int type, char *name, char *hint, char *help) { static char FuncName[]={"SUMA_Register_Widget_Children_Help"}; char *s=NULL, *st=NULL; SUMA_ENTRY; if (!w || !help) { SUMA_S_Err("NULL widget!!! or No Help"); SUMA_RETURN(NOPE); } if (!SUMA_Register_GUI_Help(name, hint, help, w, type)) { SUMA_S_Err("Failed at string level registration"); SUMA_RETURN(NOPE); } if (help) { s = SUMA_copy_string(help); s = SUMA_Sphinx_String_Edit(&s, TXT, 0); st = s; s = SUMA_Break_String(st, 60); SUMA_ifree(st); /* DO not free s, MCW_register_help uses the pointer as data to the help callback */ MCW_reghelp_children(w, s); } if (hint) { /* Just make a copy of the hint and don't worry about what got passed! */ s = SUMA_copy_string(hint); MCW_register_hint(w, s); } SUMA_RETURN(YUP); } /*! Return the help and hint strings stored in the GUI help list. \param gname (char *)Name of widget \param format (int) 0: Default 1: Sphinx format \param helpout (char **): If Not NULL, this will contain the pointer to a copy of the help string formatted per format. Note that if helpout, *helpout must be NULL at the function call. You must also free *helpout when done with it. \param hintout (char **): If Not NULL, this will contain the pointer to a copy of the hint string formatted per format. if (hintout), *hintout must be NULL at function call. You must also free *hintout when done with it. \param whelp_off (int ): If non-zero, number of blank characters by which to offset the lines of a widget's help string \return gwh (GUI_WIDGET_HELP *) A pointer to the structure containing the widget help. NULL if nothing was found. */ GUI_WIDGET_HELP *SUMA_Get_GUI_Help( char *gname, TFORM format, char **helpout, char **hintout, int whelp_off) { static char FuncName[]={"SUMA_Get_GUI_Help"}; char *s = NULL, *ss=NULL; DListElmt *el = NULL; int nn; GUI_WIDGET_HELP *gwhc=NULL; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; if (!gname) { SUMA_S_Err("NULL name"); SUMA_RETURN(gwhc);} if (!All_GUI_Help || !dlist_size(All_GUI_Help)) { SUMA_S_Err("No help list"); SUMA_RETURN(gwhc); } if ((helpout && *helpout) || (hintout && *hintout)) { SUMA_S_Err("string init error"); SUMA_RETURN(gwhc); } /* Seek name in list */ SUMA_LH("Seeking %s", gname); /* Find name in list. Note that no attempt at fast search is done here even though the list is alphabetical... */ gwhc = NULL; do { if (!el) el = dlist_head(All_GUI_Help); else el = dlist_next(el); gwhc = (GUI_WIDGET_HELP *)el->data; ss = SUMA_Name_GUI_Help(gwhc); SUMA_LH("Comparing %s to %s (nn=%d)", ss, gname, strcmp(SUMA_Name_GUI_Help(gwhc), gname)); if (ss == gname) { /* Safety oblige */ SUMA_S_Crit("Collision handsome! Don't send me gname pointers " "returned by the evil SUMA_Name_GUI_Help()!"); } if ((nn = strcmp(ss, gname)) == 0) { el = NULL; } else { gwhc = NULL; } } while (el && el != dlist_tail(All_GUI_Help)); if (gwhc) { SUMA_LH("Got new: %s, nn=%d", SUMA_Name_GUI_Help(gwhc), nn); if (helpout) { *helpout = SUMA_copy_string(gwhc->help); if (gwhc->type == 1 && whelp_off) {/* widget and offset requested */ SUMA_Sphinx_String_Edit(helpout, format, whelp_off); } else { SUMA_Sphinx_String_Edit(helpout, format, 0); } } if (hintout) { *hintout = SUMA_copy_string(gwhc->hint); SUMA_Sphinx_String_Edit(hintout, format, 0); } } else { SUMA_LH("Got nothing for %s", gname); } SUMA_RETURN(gwhc); } /*! Return the help struct for a certain widget. */ GUI_WIDGET_HELP *SUMA_Get_Widget_Help( RwcWidget w ) { static char FuncName[]={"SUMA_Get_Widget_Help"}; char *s = NULL; DListElmt *el = NULL; int nn; GUI_WIDGET_HELP *gwhc=NULL; SUMA_ENTRY; if (!w) { SUMA_S_Err("NULL w"); SUMA_RETURN(gwhc);} if (!All_GUI_Help || !dlist_size(All_GUI_Help)) { SUMA_S_Err("No help list"); SUMA_RETURN(gwhc); } /* Find widget in list. */ gwhc = NULL; el = NULL; do { if (!el) el = dlist_head(All_GUI_Help); else el = dlist_next(el); gwhc = (GUI_WIDGET_HELP *)el->data; if (w == gwhc->w) { el = NULL; } else { gwhc = NULL; } } while (el && el != dlist_tail(All_GUI_Help)); if (!gwhc && (s = XtName(w))) { /* Try matching the hint to the widget name, This is done for container widgets */ el = NULL; do { if (!el) el = dlist_head(All_GUI_Help); else el = dlist_next(el); gwhc = (GUI_WIDGET_HELP *)el->data; if (gwhc->hint && !strcmp(s, gwhc->hint)) { el = NULL; } else { gwhc = NULL; } } while (el && el != dlist_tail(All_GUI_Help)); } SUMA_RETURN(gwhc); } void SUMA_Show_All_GUI_Help(DList *dl, FILE *fout, int detail, int format) { static char FuncName[]={"SUMA_Show_All_GUI_Help"}; char *s=NULL; SUMA_ENTRY; if (!fout) fout = stdout; s = SUMA_All_GUI_Help_Info(dl, detail, format); fprintf(fout, "%s", s); SUMA_ifree(s); SUMA_RETURNe; } int SUMA_Register_GUI_Help(char *which, char *hint, char *help, RwcWidget widget, int type) { static char FuncName[]={"SUMA_Register_GUI_Help"}; GUI_WIDGET_HELP *gwh=NULL, *gwhc=NULL; char *sstmp = NULL, *s=NULL, buf[64]={""}; DListElmt *el=NULL; static char WhinedNames[1025]={""}; int nn; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; if (!hint && !which) { SUMA_S_Err("No hint, no which"); SUMA_RETURN(NOPE); } if (!which) { /* get from hint if it has "which" string between ":which:" directives. ":which:SurfCont->more:which:hint goes here"*/ if ( !(strstr(hint,":which:") == hint) || !(sstmp = strstr(hint+strlen(":which:"),":which:")) ) { SUMA_S_Err("No which and no :which: in hint. No good"); SUMA_RETURN(NOPE); } which = hint+strlen(":which:"); hint = sstmp+strlen(":which:"); } gwh = (GUI_WIDGET_HELP *)SUMA_calloc(1,sizeof(GUI_WIDGET_HELP)); gwh->w = (void *)widget; gwh->type = type; /* 1, regular widget, 0, container widget, used for organizing the help, 2, a way to insert an html URI for widgets not individually tracked in the help. For now this is only done for table entries. */ /* parse which: SurfCont->more */ sstmp = which; gwh->name_lvl = 0; while( (s = strstr(sstmp, "->")) && gwh->name_lvl < 9 ) { if (s == sstmp) { SUMA_S_Err("Empty child in %s\n", which); SUMA_free(gwh); SUMA_RETURN(NOPE); } nn = s - sstmp; if (nn > 63) { SUMA_S_Err("Too wordy for me."); SUMA_free(gwh); SUMA_RETURN(NOPE); } strncpy(gwh->name[gwh->name_lvl], sstmp, nn); gwh->name[gwh->name_lvl][nn+1] = '\0'; sstmp = s+2; /* skip -> */ ++gwh->name_lvl; } /* copy last one */ strncpy(gwh->name[gwh->name_lvl], sstmp, 63); gwh->name[gwh->name_lvl][63] = '\0'; ++gwh->name_lvl; /* store the hint */ if (hint) { if (strlen(hint)>255) { SUMA_S_Err("Hint too long"); SUMA_free(gwh); SUMA_RETURN(NOPE); } strncpy(gwh->hint, hint, 255); gwh->hint[255] = '\0'; } /* store the help */ gwh->help = help; /* Put it all in */ if (!All_GUI_Help) { All_GUI_Help = (DList *)SUMA_calloc(1, sizeof(DList)); dlist_init(All_GUI_Help, SUMA_Free_Widget_Help); } /* insert in list */ if (!dlist_size(All_GUI_Help)) { dlist_ins_next(All_GUI_Help, dlist_head(All_GUI_Help), (void *)gwh); SUMA_RETURN(YUP); } SUMA_LH("Inserting '%s' with %s %s", SUMA_Name_GUI_Help(gwh), gwh->hint, gwh->help); /* Insert in alphabetical order */ el = dlist_head(All_GUI_Help); do { gwhc = (GUI_WIDGET_HELP *)el->data; if ((nn = strcmp(SUMA_Name_GUI_Help(gwhc), SUMA_Name_GUI_Help(gwh))) == 0) { snprintf(buf, 63, "%s;",SUMA_Name_GUI_Help(gwh)); if (LocalHead || !(sstmp=strstr(WhinedNames, buf))) { SUMA_S_Note("GUI Name %s already in use. No special help entry." "%s", SUMA_Name_GUI_Help(gwh), LocalHead ? "":"\nFurther warnings for this name curtailed."); if (!sstmp) SUMA_strncat(WhinedNames,buf, 1023); if (LocalHead) SUMA_DUMP_TRACE("Trace at duplicate GUI name"); SUMA_free(gwh); } SUMA_RETURN(YUP); } else if (nn < 0) { dlist_ins_next(All_GUI_Help, el, (void *)gwh); SUMA_RETURN(YUP); } else { el = dlist_next(el); } } while (el && el != dlist_tail(All_GUI_Help)); /* Reached bottom without going over, put on the top */ dlist_ins_prev(All_GUI_Help, dlist_head(All_GUI_Help), (void *)gwh); /* A debug for when you get to the bottom condition */ if (LocalHead) { SUMA_Show_All_GUI_Help(All_GUI_Help, NULL, 0, 0); } SUMA_RETURN(YUP); } char *SUMA_Name_GUI_Help(GUI_WIDGET_HELP *gwh) { static char FuncName[]={"SUMA_Name_GUI_Help"}; return(SUMA_Name_GUI_Help_eng(gwh, 0)); } char *SUMA_Name_GUI_Help_eng(GUI_WIDGET_HELP *gwh, int lvl) { static char FuncName[]={"SUMA_Name_GUI_Help_eng"}; static char sa[10][641], *s=NULL; static int nc=0; int k; SUMA_ENTRY; ++nc; if (nc > 9) nc = 0; s = (char *)sa[nc]; s[0] = '\0'; if (!gwh) SUMA_RETURN(s); if (lvl <= 0) lvl = gwh->name_lvl+lvl; if (lvl > gwh->name_lvl) lvl = gwh->name_lvl; for (k=0; kname[k], 640); if (k", 640); } SUMA_RETURN(s); } char *SUMA_All_GUI_Help_Info(DList *dl, int detail, int format) { static char FuncName[]={"SUMA_All_GUI_Help_Info"}; SUMA_STRING *SS=NULL; DListElmt *el=NULL; char *s=NULL; GUI_WIDGET_HELP *gwh=NULL; SUMA_ENTRY; SS = SUMA_StringAppend (NULL, NULL); if (!dl) { SS = SUMA_StringAppend(SS,"NULL dl"); } else { SS = SUMA_StringAppend_va(SS, "Help for %d widgets. Detail %d, Format %d\n" "--------------------------------------------\n", dlist_size(dl), detail, format); el = dlist_head(dl); do { gwh = (GUI_WIDGET_HELP *)el->data; if (!gwh) SUMA_StringAppend(SS,"NULL widget data!"); else { SUMA_StringAppend_va(SS,"Widget: %s (%p)\n", SUMA_Name_GUI_Help(gwh), gwh->w); if (detail > 0) SUMA_StringAppend_va(SS," hint: %s\n", gwh->hint); if (detail > 1) { s = SUMA_copy_string(gwh->help); switch (format) { case 0: SUMA_Sphinx_String_Edit(&s, TXT, 0); SUMA_StringAppend_va(SS," help: %s\n", s); SUMA_ifree(s); break; default: case 1: SUMA_Sphinx_String_Edit(&s, SPX, 0); SUMA_StringAppend_va(SS," help: %s\n", s); SUMA_ifree(s); break; } } SUMA_StringAppend_va(SS,"\n"); } el = dlist_next(el); } while (el); } SUMA_StringAppend_va(SS,"\n"); SUMA_SS2S(SS, s); SUMA_RETURN(s); } SUMA_Boolean SUMA_is_Documented_Widget(char *wname) { static char FuncName[]={"SUMA_is_Documented_Widget"}; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; if (!wname) SUMA_RETURN(NOPE); if (!DocumentedWidgets) { SUMA_S_Err("Must call SUMA_set_DocumentedWidgets() first!"); SUMA_RETURN(NOPE); } if (strstr(DocumentedWidgets, wname)) SUMA_RETURN(YUP); SUMA_LH("Widget %s not in:\n%s", wname, DocumentedWidgets); SUMA_RETURN(NOPE); } void SUMA_suggest_GUI_Name_Match(char *wname, int nmx, DList *dl) { static char FuncName[]={"SUMA_suggest_GUI_Name_Match"}; int i, nlot; char **lot=NULL, **slot=NULL; DListElmt *el=NULL; GUI_WIDGET_HELP *gwhc=NULL; SUMA_ENTRY; if (!dl) dl = All_GUI_Help; if (!dl || !dlist_size(dl)) { SUMA_S_Err("No list to be had"); SUMA_RETURNe; } lot = (char **)SUMA_calloc(dlist_size(dl), sizeof(char *)); nlot = 0; i = 0; gwhc = NULL; do { if (!el) el = dlist_head(dl); else el = dlist_next(el); gwhc = (GUI_WIDGET_HELP *)el->data; lot[i] = SUMA_copy_string(SUMA_Name_GUI_Help(gwhc)); ++i; } while (el && el != dlist_tail(dl)); nlot = i; slot = approx_str_sort(lot, nlot, wname, 0, NULL, 0, NULL, NULL); if (nmx < 0) nmx = nlot; fprintf(SUMA_STDERR, "Suggestions for %s\n" "---------------\n", wname); for (i=0; i < nlot && i < nmx; ++i) { fprintf(SUMA_STDERR, " %s\n", slot[i]); } for (i=0; i < nlot; ++i) { SUMA_ifree(lot[i]); SUMA_ifree(slot[i]); } SUMA_ifree(lot); SUMA_ifree(slot); SUMA_RETURNe; }