source: git/Singular/fehelp.cc @ bb4fa2

spielwiese
Last change on this file since bb4fa2 was bb4fa2, checked in by Olaf Bachmann <obachman@…>, 25 years ago
* small changes in help/Resource stuff git-svn-id: file:///usr/local/Singular/svn/trunk@3406 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 23.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: help system
6*/
7
8#include <string.h>
9#include <unistd.h>
10#include <stdio.h>
11#include <stddef.h>
12#include <stdlib.h>
13#include <time.h>
14#include <limits.h>
15
16#include "mod2.h"
17#include "tok.h"
18#include "mmemory.h"
19#include "febase.h"
20#include "ipid.h"
21#include "ipshell.h"
22#include "libparse.h"
23
24/*****************************************************************
25 *
26 * Declarations: Data  structures
27 *
28 *****************************************************************/
29#define MAX_HE_ENTRY_LENGTH 60
30typedef struct 
31{
32  char key[MAX_HE_ENTRY_LENGTH];
33  char node[MAX_HE_ENTRY_LENGTH];
34  char url[MAX_HE_ENTRY_LENGTH];
35  long  chksum;
36} heEntry_s;
37typedef  heEntry_s * heEntry;
38
39typedef void (*heBrowserHelpProc)(heEntry hentry);
40typedef BOOLEAN (*heBrowserInitProc)(int warn);
41
42typedef struct
43{
44  char* browser;
45  heBrowserInitProc init_proc;
46  heBrowserHelpProc help_proc;
47} heBrowser_s;
48typedef heBrowser_s * heBrowser;
49
50/*****************************************************************
51 *
52 * Declarations: Local functions
53 *
54 *****************************************************************/
55static char* strclean(char* str); 
56static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry);
57static int heReKey2Entry (char* filename, char* key, heEntry hentry);
58static BOOLEAN strmatch(char* s, char* re);
59static BOOLEAN heOnlineHelp(char* s);
60static void heBrowserHelp(heEntry hentry);
61static long heKeyChksum(char* key);
62
63// browser functions
64static BOOLEAN heInfoInit(int);    static void heInfoHelp(heEntry hentry);
65#if ! defined(WINNT) && ! defined(macintosh)
66static BOOLEAN heNetscapeInit(int);static void heNetscapeHelp(heEntry hentry);
67static BOOLEAN heXinfoInit(int);   static void heXinfoHelp(heEntry hentry);
68static BOOLEAN heTkinfoInit(int);  static void heTkinfoHelp(heEntry hentry);
69#endif
70static BOOLEAN heBuiltinInit(int); static void heBuiltinHelp(heEntry hentry);
71static BOOLEAN heDummyInit(int);   static void heDummyHelp(heEntry hentry);
72static BOOLEAN heEmacsInit(int);   static void heEmacsHelp(heEntry hentry);
73
74static heBrowser heCurrentHelpBrowser = NULL;
75
76
77/*****************************************************************
78 *
79 * Definition: available help browsers
80 *
81 *****************************************************************/
82// order is improtant -- first possible help is choosen
83static heBrowser_s heHelpBrowsers[] =
84{
85#if ! defined(WINNT) && ! defined(macintosh)
86  { "netscape", heNetscapeInit, heNetscapeHelp},
87  { "tkinfo",   heTkinfoInit,   heTkinfoHelp},
88  { "xinfo",    heXinfoInit,    heXinfoHelp},
89#endif
90  { "info",     heInfoInit,     heInfoHelp},
91  { "builtin",  heBuiltinInit,  heBuiltinHelp},
92  { "dummy",    heDummyInit,    heDummyHelp},
93  { "emacs",    heEmacsInit,    heEmacsHelp},
94  { NULL, NULL, NULL} // must be the last record
95};
96
97/*****************************************************************
98 *
99 * Implementation: public function
100 *
101 *****************************************************************/
102void feHelp(char *str)
103{
104  str = strclean(str);
105  if (str == NULL) {heBrowserHelp(NULL); return;}
106
107  if (strlen(str) > MAX_HE_ENTRY_LENGTH - 2)  // need room for extra **
108    str[MAX_HE_ENTRY_LENGTH - 3] = '\0';
109
110  BOOLEAN key_is_regexp = (strchr(str, '*') != NULL);
111  heEntry_s hentry;
112  char* idxfile = feResource("IdxFile");
113 
114  // Try exact match of help string with key in index
115  if (!key_is_regexp && idxfile != NULL && heKey2Entry(idxfile, str, &hentry))
116  {
117    heBrowserHelp(&hentry);
118    return;
119  }
120
121  if (! key_is_regexp && heOnlineHelp(str)) return;
122 
123  // Try to match approximately with key in index file
124  if (idxfile != NULL)
125  {
126    char* matches = StringSetS("");
127    int found = heReKey2Entry(idxfile, str, &hentry);
128
129    // Try to match with str*
130    if (found == 0)
131    {
132      char mkey[MAX_HE_ENTRY_LENGTH];
133      strcpy(mkey, str);
134      strcat(mkey, "*");
135      found = heReKey2Entry(idxfile, mkey, &hentry);
136      // Try to match with *str*
137      if (found == 0)
138      {
139        mkey[0] = '*';
140        strcpy(mkey + 1, str);
141        strcat(mkey, "*");
142        found = heReKey2Entry(idxfile, mkey, &hentry);
143      }
144     
145      // Print warning and return if nothing found
146      if (found == 0)
147      {
148        Warn("No help for topic '%s' (not even for '*%s*')", str, str);
149        WarnS("Try '?;'       for general help");
150        WarnS("or  '?Index;'  for all available help topics");
151        return;
152      }
153    }
154
155    // do help if unique match was found
156    if (found == 1)
157    {
158      heBrowserHelp(&hentry);
159      return;
160    }
161    // Print warning about multiple matches and return
162    if (key_is_regexp)
163      Warn("No unique help for '%s'", str);
164    else
165      Warn("No help for topic '%s'", str);
166    Warn("Try one of");
167    PrintS(matches);
168    PrintS("\n");
169    return;
170  }
171 
172  // no idx file, let Browsers deal with it, if they can
173  strcpy(hentry.key, str);
174  *hentry.node = '\0';
175  *hentry.url = '\0';
176  hentry.chksum = 0;
177  heBrowserHelp(&hentry);
178}
179
180char* feHelpBrowser(char* which, int warn)
181{
182  int i = 0;
183  extern void mainSetSingOptionValue(const char* name, char* value);
184  char* mainGetSingOptionValue(const char* name);
185
186  // if no argument, see what we have as value to the option
187  if (which == NULL || *which == '\0') 
188    which = mainGetSingOptionValue("browser");
189 
190  // if no argument, choose first available help browser
191  if (which == NULL || *which == '\0')
192  {
193    // unles one is already set
194    if (heCurrentHelpBrowser != NULL) goto Finish;
195   
196    while (heHelpBrowsers[i].browser != NULL)
197    {
198      if (heHelpBrowsers[i].init_proc(0)) 
199      {
200        heCurrentHelpBrowser = &(heHelpBrowsers[i]);
201        return heCurrentHelpBrowser->browser;
202      }
203      i++;
204    }
205    // should never get here
206    feReportBug("");
207  }
208
209  // with argument, find matching help browser
210  while (heHelpBrowsers[i].browser != NULL &&
211         strcmp(heHelpBrowsers[i].browser, which) != 0)
212  {i++;}
213 
214  if (heHelpBrowsers[i].browser == NULL) 
215  {
216    if (warn) Warn("No help browser '%s' available", which);
217  }
218  else
219  {
220    // see whether we can init it
221    if (heHelpBrowsers[i].init_proc(warn))
222    {
223      heCurrentHelpBrowser = &(heHelpBrowsers[i]);
224      goto Finish;
225    }
226  }
227     
228  // something went wrong
229  if (heCurrentHelpBrowser == NULL) 
230  {
231    // choose first available help browser
232    mainSetSingOptionValue("browser", "");
233    feHelpBrowser();
234    assume(heCurrentHelpBrowser != NULL);
235    if (warn) 
236      Warn("Setting help browser to '%s'", heCurrentHelpBrowser->browser);
237    return heCurrentHelpBrowser->browser;
238  }
239  else
240  {
241    // or, leave as is
242    if (warn) 
243      Warn("Help browser stays at '%s'",  heCurrentHelpBrowser->browser);
244  }
245
246  Finish:
247  mainSetSingOptionValue("browser", heCurrentHelpBrowser->browser);
248  return heCurrentHelpBrowser->browser;
249}
250
251void feStringAppendBrowsers(int warn)
252{
253  int i;
254 
255  if (warn)
256  {
257    i = 0;
258    while (heHelpBrowsers[i].browser != NULL)
259    {
260      heHelpBrowsers[i].init_proc(warn);
261      i++;
262    }
263  }
264  StringAppendS("Available HelpBrowsers: ");
265 
266  i = 0;
267  while (heHelpBrowsers[i].browser != NULL)
268  {
269    if (heHelpBrowsers[i].init_proc(0)) 
270      StringAppend("%s, ", heHelpBrowsers[i].browser);
271    i++;
272  }
273  StringAppend("\nCurrent HelpBrowser: %s ", feHelpBrowser());
274}
275 
276
277/*****************************************************************
278 *
279 * Implementation: local function
280 *
281 *****************************************************************/
282// Remove whitspaces from beginning and end, return NULL if only whitespaces
283static char* strclean(char* str)
284{
285  if (str == NULL) return NULL;
286  char *s=str;
287  while (*s <= ' ' && *s != '\0') s++;
288  if (*s == '\0') return NULL;
289  char *ss=s;
290  while (*ss!='\0') ss++;
291  ss--;
292  while (*ss <= ' ' && *ss != '\0')
293  {
294    *ss='\0';
295    ss--;
296  }
297  if (*ss == '\0') return NULL;
298  return s;
299}
300
301// Finds help entry for key:
302// returns filled-in hentry and TRUE, on success
303// FALSE, on failure
304// Assumes that lines of idx file have the following form
305// key\tnode\turl\tchksum\n (chksum ma be empty, then it is set to -1)
306// and that lines are sorted alpahbetically w.r.t. index entries
307static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry)
308{
309  FILE* fd;
310  char c, k;
311  int kl, i;
312  *(hentry->key) = '\0';
313  *(hentry->url) = '\0';
314  *(hentry->node) = '\0';
315  hentry->chksum = 0;
316  if (filename == NULL || key == NULL)  return FALSE;
317  fd = fopen(filename, "r");
318  if (fd == NULL) return FALSE;
319  kl = strlen(key);
320
321  k = key[0];
322  i = 0;
323  while ((c = getc(fd)) != EOF)
324  {
325    if (c < k) 
326    {
327      /* Skip line */
328      while (getc(fd) != '\n') {};
329      if (i) 
330      {
331        i=0;
332        k=key[0];
333      }
334    }
335    else if (c == k)
336    {
337      i++;
338      if (i == kl)
339      {
340        // \t must follow, otherwise only substring match
341        if (getc(fd) != '\t') goto Failure;
342
343        // Now we found an exact match
344        if (hentry->key != key) strcpy(hentry->key, key);
345        // get node
346        i = 0;
347        while ((c = getc(fd)) != '\t' && c != EOF)
348        {
349          hentry->node[i] = c;
350          i++;
351        }
352        if (c == EOF) goto Failure;
353       
354        // get url
355        hentry->node[i] = '\0';
356        i = 0;
357        while ((c = getc(fd)) != '\t' && c != EOF)
358        {
359          hentry->url[i] = c;
360          i++;
361        }
362        if (c == EOF) goto Failure;
363
364        // get chksum
365        hentry->url[i] = '\0';
366
367        if (fscanf(fd, "%ld\n", &(hentry->chksum)) != 1)
368        {
369          hentry->chksum = -1;
370        }
371        fclose(fd);
372        return TRUE;
373      }
374      else if (i > kl) 
375      {
376        goto Failure;
377      }
378      else
379      {
380        k = key[i];
381      }
382    }
383    else
384    {
385      goto Failure;
386    }
387  }
388  Failure:
389  fclose(fd);
390  return FALSE;
391}
392
393// return TRUE if s matches re
394// FALSE, otherwise
395// does not distinguish lower and upper cases
396// inteprets * as wildcard
397static BOOLEAN strmatch(char* s, char* re)
398{
399  if (s == NULL || *s == '\0') 
400    return (re == NULL || *re == '\0' || strcmp(re, "*") == 0);
401  if (re == NULL || *re == '\0') return FALSE;
402
403  int i;
404  char ls[MAX_HE_ENTRY_LENGTH + 1];
405  char rs[MAX_HE_ENTRY_LENGTH + 1];
406  char *l, *r, *ll, *rr;
407 
408  // make everything to lower case
409  i=1;
410  ls[0] = '\0';
411  do
412  {
413    if (*s >= 'A' && *s <= 'Z') ls[i] = *s + ('a' - 'A');
414    else ls[i] = *s;
415    i++;
416    s++;
417  } while (*s != '\0');
418  ls[i] = '\0';
419  l = &(ls[1]);
420 
421  i=1;
422  rs[0] = '\0';
423  do
424  {
425    if (*re >= 'A' && *re <= 'Z') rs[i]= *re + ('a' - 'A');
426    else rs[i] = *re;
427    i++;
428    re++;
429  } while (*re != '\0');
430  rs[i] = '\0';
431  r = &(rs[1]);
432 
433  // chopp of exact matches from beginning and end
434  while (*r != '*' && *r != '\0' && *l != '\0')
435  {
436    if (*r != *l) return FALSE;
437    *r = '\0';
438    *s = '\0';
439    r++;
440    l++;
441  }
442  if (*r == '\0') return (*l == '\0');
443  if (*r == '*' && r[1] == '\0') return TRUE;
444  if (*l == '\0') return FALSE;
445
446  rr = &r[strlen(r) - 1];
447  ll = &l[strlen(l) - 1];
448  while (*rr != '*' && *rr != '\0' && *ll != '\0')
449  {
450    if (*rr != *ll) return FALSE;
451    *rr = '\0';
452    *ll = '\0';
453    rr--;
454    ll--;
455  }
456  if (*rr == '\0') return (*ll == '\0');
457  if (*rr == '*' && rr[-1] == '\0') return TRUE;
458  if (*ll == '\0') return FALSE;
459 
460  // now *r starts with a * and ends with a *
461  r++;
462  *rr = '\0'; rr--;
463  while (*r != '\0')
464  {
465    rr = r + 1;
466    while (*rr != '*' && *rr != '\0') rr++;
467    if (*rr == '*') 
468    {
469      *rr = '\0';
470      rr++;
471    }
472    l = strstr(l, r);
473    if (l == NULL) return FALSE;
474    r = rr;
475  }
476  return TRUE;
477}
478
479// similar to heKey2Entry, except that
480// key is taken as regexp (see above)
481// and number of matches is returned
482// if number of matches > 0, then hentry contains entry for first match
483// if number of matches > 1, matches are printed as komma-separated
484// into global string
485static int heReKey2Entry (char* filename, char* key, heEntry hentry)
486{
487  int i = 0;
488  FILE* fd;
489  char index_key[MAX_HE_ENTRY_LENGTH];
490 
491  if (filename == NULL || key == NULL)  return 0;
492  fd = fopen(filename, "r");
493  if (fd == NULL) return 0;
494  while (fscanf(fd, "%[^\t]\t%*[^\n]\n", index_key) == 1)
495  {
496    if (strmatch(index_key, key))
497    {
498      i++;
499      if (i == 1)
500      {
501        heKey2Entry(filename, index_key, hentry);
502      }
503      else if (i == 2)
504      {
505        StringAppend("?%s; ?%s;", hentry->key, index_key);
506      }
507      else
508      {
509        StringAppend(" ?%s;", index_key);
510      }
511    }
512  }
513  fclose(fd);
514  return i;
515}
516
517// try to find the help string as a loaded procedure or library
518// if found, display the help and return TRUE
519// otherwise, return FALSE
520static BOOLEAN heOnlineHelp(char* s)
521{
522#ifdef HAVE_NAMESPACES
523  idhdl h, ns;
524  iiname2hdl(s, &ns, &h);
525#else /* HAVE_NAMESPACES */
526  idhdl h=idroot->get(s,myynest);
527#endif /* HAVE_NAMESPACES */
528
529  // try help for a procedure
530  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
531  {
532    char *lib=iiGetLibName(IDPROC(h));
533    if((lib!=NULL)&&(*lib!='\0'))
534    {
535      Print("// proc %s from lib %s\n",s,lib);
536      s=iiGetLibProcBuffer(IDPROC(h), 0);
537      PrintS(s);
538      FreeL((ADDRESS)s);
539      return TRUE;
540    }
541    return FALSE;
542  }
543 
544  // try help for a library
545  int ls = strlen(s);
546  char* str = NULL;
547  // chekc that it ends with "[.,_]lib"
548  if (strlen(s) >=4 &&  strcmp(&s[ls-3], "lib") == 0)
549  {
550    if (s[ls - 4] == '.') str = s;
551    else
552    {
553      str = mstrdup(s);
554      str[ls - 4] = '.';
555    }
556  }
557  else
558  {
559    return FALSE;
560  }
561
562  char libnamebuf[128];
563  FILE *fp=NULL;
564  if ((str[1]!='\0') && ((fp=feFopen(str,"rb", libnamebuf))!=NULL))
565  {
566    extern FILE *yylpin;
567    lib_style_types lib_style; // = OLD_LIBSTYLE;
568 
569    yylpin = fp;
570#ifdef HAVE_NAMESPACES
571    yylplex(str, libnamebuf, &lib_style, IDROOT, FALSE, GET_INFO);
572#else /* HAVE_NAMESPACES */
573    yylplex(str, libnamebuf, &lib_style, GET_INFO);
574#endif /* HAVE_NAMESPACES */
575    reinit_yylp();
576    if(lib_style == OLD_LIBSTYLE)
577    {
578      char buf[256];
579      fseek(fp, 0, SEEK_SET);
580      Warn( "library %s has an old format. Please fix it for the next time",
581            str);
582      if (str != s) FreeL(str);
583      BOOLEAN found=FALSE;
584      while (fgets( buf, sizeof(buf), fp))
585      {
586        if (strncmp(buf,"//",2)==0)
587        {
588          if (found) return TRUE;
589        }
590        else if ((strncmp(buf,"proc ",5)==0)||(strncmp(buf,"LIB ",4)==0))
591        {
592          if (!found) WarnS("no help part in library found");
593          return TRUE;
594        }
595        else
596        {
597          found=TRUE;
598          PrintS(buf);
599        }
600      }
601    }
602    else
603    {
604      if (str != s) FreeL(str);
605      fclose( yylpin );
606      PrintS(text_buffer);
607      FreeL(text_buffer);
608      text_buffer=NULL;
609    }
610    return TRUE;
611  }
612
613  if (str != s) FreeL(str);
614  return FALSE;
615}
616
617static long heKeyChksum(char* key)
618{
619  if (key == NULL || *key == '\0') return 0;
620#ifdef HAVE_NAMESPACES
621  idhdl h, ns;
622  iiname2hdl(key, &ns, &h);
623#else /* HAVE_NAMESPACES */
624  idhdl h=idroot->get(key,myynest);
625#endif /* HAVE_NAMESPACES */
626  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
627  {
628    procinfo *pi = IDPROC(h);
629    if (pi != NULL) return pi->data.s.help_chksum;
630  }
631  return 0;
632}
633
634/*****************************************************************
635 *
636 * Implementation : Help Browsers
637 *
638 *****************************************************************/
639   
640static void heBrowserHelp(heEntry hentry)
641{
642  // check checksums of procs
643  int kchksum = (hentry != NULL && hentry->chksum > 0 ? 
644                 heKeyChksum(hentry->key) : 0);
645  if (kchksum  && kchksum != hentry->chksum && heOnlineHelp(hentry->key)) 
646    return;
647 
648  if (heCurrentHelpBrowser == NULL) feHelpBrowser();
649  assume(heCurrentHelpBrowser != NULL);
650  Warn("Displaying help in browser '%s'.", heCurrentHelpBrowser->browser);
651  Warn("Use 'system(\"--browser\", \"<browser>\");' to change browser");
652  Warn("Use 'system(\"browsers\");'                 for available browsers");
653  heCurrentHelpBrowser->help_proc(hentry);
654}
655
656#define MAX_SYSCMD_LEN MAXPATHLEN*2
657// browser functions
658static BOOLEAN heInfoInit(int warn)
659{
660  if (feResource('i', warn) == NULL)
661  {
662    if (warn) WarnS("'info' help browser not available: no InfoFile");
663    return FALSE;
664  }
665  if (feResource('I') == NULL)
666  {
667    if (warn) 
668      WarnS("'info' help browser not available: no 'info' program found");
669    return FALSE;
670  }
671  return TRUE;
672}
673static void heInfoHelp(heEntry hentry)
674{
675  char sys[MAX_SYSCMD_LEN];
676
677  if (hentry != NULL && *(hentry->key) != '\0')
678  {
679    if (*(hentry->node) != '\0') 
680      sprintf(sys, "%s -f %s --node='%s'", 
681              feResource('I'), feResource('i'), hentry->node);
682    else
683      sprintf(sys, "%s -f %s Index '%s'", 
684              feResource('I'), feResource('i'), hentry->key);
685  }
686  else
687    sprintf(sys, "%s -f %s --node=Top", feResource('I'), feResource('i'));
688  system(sys);
689}
690
691#if ! defined(WINNT) && ! defined(macintosh)
692static BOOLEAN heNetscapeInit(int warn)
693{
694  if (feResource("netscape", warn) == NULL)
695  {
696    if (warn) WarnS("'netscape' help browser not available: no 'netscape' program found");
697    return FALSE;
698  }
699  if (getenv("DISPLAY") == NULL)
700  {
701    if (warn) WarnS("'netscape' help browser not available:");
702    if (warn) WarnS("Environment variable DISPLAY not set");
703    return FALSE;
704  }
705 
706  if (feResource("HtmlDir", warn) == NULL)
707  {
708    if (warn) WarnS("no local HtmlDir found");
709    if (warn) Warn("using %s instead", feResource("ManualUrl", warn));
710  }
711  return TRUE;
712}
713static void heNetscapeHelp(heEntry hentry)
714{
715  char sys[MAX_SYSCMD_LEN];
716  char url[MAXPATHLEN];
717  char* htmldir = feResource("HtmlDir");
718  char* urltype;
719 
720  if (htmldir == NULL) 
721  {
722    urltype = "";
723    htmldir = feResource("ManualUrl");
724  }
725  else
726  {
727    urltype = "file:";
728  }
729
730  if (hentry != NULL && *(hentry->url) != '\0')
731  {
732    sprintf(url, "%s%s/%s", urltype, htmldir, hentry->url);
733  }
734  else
735  {
736    sprintf(url, "%s%s/index.htm", urltype, htmldir);
737  }
738  sprintf(sys, "%s --remote 'OpenUrl(%s)' > /dev/null 2>&1", 
739          feResource("netscape"), url);
740 
741  // --remote exits with status != 0 if netscaep isn't already running
742  if (system(sys) != 0)
743  {
744    sprintf(sys, "%s %s &", feResource("netscape"), url);
745    system(sys);
746  }
747}
748
749static BOOLEAN heXinfoInit(int warn)
750{
751  if (getenv("DISPLAY") == NULL)
752  {
753    if (warn) WarnS("'xinfo' help browser not available:");
754    if (warn) WarnS("Environment variable DISPLAY not set");
755    return FALSE;
756  }
757  if (feResource('i', warn) == NULL)
758  {
759    if (warn) WarnS("'xinfo' help browser not available: no InfoFile");
760    return FALSE;
761  }
762  if (feResource('I', warn) == NULL)
763  {
764    if (warn) WarnS("'xinfo' help browser not available: no 'info' program found");
765    return FALSE;
766  }
767  if (feResource('X', warn) == NULL)
768  {
769    if (warn) WarnS("'xinfo' help browser not available: no 'xterm' program found");
770    return FALSE;
771  }
772  return TRUE;
773}
774static void heXinfoHelp(heEntry hentry)
775{
776  char sys[MAX_SYSCMD_LEN];
777
778  if (hentry != NULL && *(hentry->key) != '\0')
779  {
780    if (*(hentry->node) != '\0') 
781      sprintf(sys, "%s -e %s -f %s --node='%s' &", 
782              feResource('X'), feResource('I'), feResource('i'), hentry->node);
783    else
784      sprintf(sys, "%s -e %s -f %s Index '%s' &", 
785              feResource('X'), feResource('I'), feResource('i'), hentry->key);
786  }
787  else
788    sprintf(sys, "%s -e %s -f %s --node=Top &", 
789            feResource('X'), feResource('I'), feResource('i'));
790  system(sys);
791}
792
793static BOOLEAN heTkinfoInit(int warn)
794{
795  if (getenv("DISPLAY") == NULL)
796  {
797    if (warn) WarnS("'tkinfo' help browser not available:");
798    if (warn) WarnS("Environment variable DISPLAY not set");
799    return FALSE;
800  }
801  if (feResource('i', warn) == NULL)
802  {
803    if (warn) WarnS("'tkinfo' help browser not available: no InfoFile");
804    return FALSE;
805  }
806  if (feResource('T', warn) == NULL)
807  {
808    if (warn) WarnS("'tkinfo' help browser not available: no 'tkinfo' program found");
809    return FALSE;
810  }
811  return TRUE;
812}
813static void heTkinfoHelp(heEntry hentry)
814{
815  char sys[MAX_SYSCMD_LEN];
816  if (hentry != NULL && *(hentry->node) != '\0')
817  {
818    sprintf(sys, "%s '(%s)%s' &", 
819            feResource('T'), feResource('i'), hentry->node);
820  }
821  else
822  {
823    sprintf(sys, "%s %s &", 
824            feResource('T'), feResource('i'));
825  }
826  system(sys);
827}
828#endif // ! defined(WINNT) && ! defined(macintosh)
829
830static BOOLEAN heDummyInit(int warn)
831{
832  return TRUE;
833}
834static void heDummyHelp(heEntry hentry)
835{
836  Werror("No functioning help browser available.");
837}
838
839static BOOLEAN heEmacsInit(int warn)
840{
841  return TRUE;
842}
843static void heEmacsHelp(heEntry hentry)
844{
845  WarnS("Your help command could not be executed. Use");
846  Warn("C-h C-s %s", 
847       (hentry != NULL && *(hentry->node) != '\0' ? hentry->node : "Top"));
848  Warn("to enter the Singular online help. For general");
849  Warn("information on Singular running under Emacs, type C-h m");
850}
851static BOOLEAN heBuiltinInit(int warn)
852{
853  if (feResource('i', warn) == NULL)
854  {
855    if (warn) WarnS("'builtin' help browser not available: no InfoFile");
856    return FALSE;
857  }
858  return TRUE;
859}
860static int singular_manual(char *str);
861static void heBuiltinHelp(heEntry hentry)
862{
863  char* node = mstrdup(hentry != NULL && *(hentry->node) != '\0' ? 
864                       hentry->node : "Top");
865  singular_manual(node);
866  FreeL(node);
867}
868
869 
870/* ========================================================================== */
871// old, stupid builtin_help
872// This could be implemented much more clever, but I'm too lazy to do this now
873//
874#define HELP_OK        0
875#define FIN_INDEX    '\037'
876#define not  !
877#define HELP_NOT_OPEN  1
878#define HELP_NOT_FOUND 2
879#define BUF_LEN        256
880#define IDX_LEN        64
881#define MAX_LINES      21
882
883#ifdef macintosh
884static char tolow(char p)
885#else
886static inline char tolow(char p)
887#endif
888{
889  if (('A'<=p)&&(p<='Z')) return p | 040;
890  return p;
891}
892
893/*************************************************/
894static int show(unsigned long offset,FILE *help, char *close)
895{ char buffer[BUF_LEN+1];
896  int  lines = 0;
897
898  if( help== NULL)
899    if( (help = fopen(feResource('i'), "rb")) == NULL)
900      return HELP_NOT_OPEN;
901
902  fseek(help,  (long)(offset+1), (int)0);
903  while( !feof(help)
904        && *fgets(buffer, BUF_LEN, help) != EOF
905        && buffer[0] != FIN_INDEX)
906  {
907    printf("%s", buffer);
908    if(lines++> MAX_LINES)
909    {
910#ifdef macintosh
911      printf("\n Press <RETURN> to continue or x and <RETURN> to exit help.\n");
912#else
913      printf("\n Press <RETURN> to continue or x to exit help.\n");
914#endif
915      fflush(stdout);
916      *close = (char)getchar();
917      if(*close=='x')
918      {
919        getchar();
920        break;
921      }
922      lines=0;
923    }
924  }
925  if(*close!='x')
926  {
927#ifdef macintosh
928    printf("\nEnd of part. Press <RETURN> to continue or x and <RETURN> to exit help.\n");
929#else
930    printf("\nEnd of part. Press <RETURN> to continue or x to exit help.\n");
931#endif
932    fflush(stdout);
933    *close = (char)getchar();
934    if(*close=='x')
935      getchar();
936  }
937  return HELP_OK;
938}
939
940/*************************************************/
941static int singular_manual(char *str)
942{ FILE *index=NULL,*help=NULL;
943  unsigned long offset;
944  char *p,close;
945  int done = 0;
946  char buffer[BUF_LEN+1],
947       Index[IDX_LEN+1],
948       String[IDX_LEN+1];
949
950  if( (index = fopen(feResource('i'), "rb")) == NULL)
951  {
952    return HELP_NOT_OPEN;
953  }
954
955  for(p=str; *p; p++) *p = tolow(*p);/* */
956  do
957  {
958    p--;
959  }
960  while ((p != str) && (*p<=' '));
961  p++;
962  *p='\0';
963  (void)sprintf(String, " %s ", str);
964
965  while(!feof(index)
966        && fgets(buffer, BUF_LEN, index) != (char *)0
967        && buffer[0] != FIN_INDEX);
968
969  while(!feof(index))
970  {
971    (void)fgets(buffer, BUF_LEN, index); /* */
972    (void)sscanf(buffer, "Node:%[^\177]\177%ld\n", Index, &offset);
973    for(p=Index; *p; p++) *p = tolow(*p);/* */
974    (void)strcat(Index, " ");
975    if( strstr(Index, String)!=NULL)
976    {
977      done++; (void)show(offset, help, &close);
978    }
979    Index[0]='\0';
980    if(close=='x')
981    break;
982  }
983  if (index != NULL) (void)fclose(index);
984  if (help != NULL) (void)fclose(help);
985  if(not done)
986  {
987    Warn("`%s` not found",String);
988    return HELP_NOT_FOUND;
989  }
990  return HELP_OK;
991}
992/*************************************************/
Note: See TracBrowser for help on using the repository browser.