source: git/Singular/fehelp.cc @ 019f80

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