source: git/Singular/fehelp.cc @ a3bc95e

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