source: git/Singular/fehelp.cc @ 457d8d6

spielwiese
Last change on this file since 457d8d6 was 358fa44, checked in by Viktor Levandovskyy <levandov@…>, 23 years ago
further win adoption git-svn-id: file:///usr/local/Singular/svn/trunk@5237 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 26.3 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 "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    yylplex(str, libnamebuf, &lib_style, GET_INFO);
604#endif /* HAVE_NAMESPACES */
605    reinit_yylp();
606    if(lib_style == OLD_LIBSTYLE)
607    {
608      char buf[256];
609      fseek(fp, 0, SEEK_SET);
610      Warn( "library %s has an old format. Please fix it for the next time",
611            str);
612      if (str != s) omFree(str);
613      BOOLEAN found=FALSE;
614      while (fgets( buf, sizeof(buf), fp))
615      {
616        if (strncmp(buf,"//",2)==0)
617        {
618          if (found) return TRUE;
619        }
620        else if ((strncmp(buf,"proc ",5)==0)||(strncmp(buf,"LIB ",4)==0))
621        {
622          if (!found) WarnS("no help part in library found");
623          return TRUE;
624        }
625        else
626        {
627          found=TRUE;
628          PrintS(buf);
629        }
630      }
631    }
632    else
633    {
634      if (str != s) omFree(str);
635      fclose( yylpin );
636      PrintS(text_buffer);
637      omFree(text_buffer);
638      text_buffer=NULL;
639    }
640    return TRUE;
641  }
642
643  if (str != s) omFree(str);
644  return FALSE;
645}
646
647static long heKeyChksum(char* key)
648{
649  if (key == NULL || *key == '\0') return 0;
650#ifdef HAVE_NAMESPACES
651  idhdl h, ns;
652  iiname2hdl(key, &ns, &h);
653#else /* HAVE_NAMESPACES */
654  idhdl h=idroot->get(key,myynest);
655#endif /* HAVE_NAMESPACES */
656  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
657  {
658    procinfo *pi = IDPROC(h);
659    if (pi != NULL) return pi->data.s.help_chksum;
660  }
661  return 0;
662}
663
664/*****************************************************************
665 *
666 * Implementation : Help Browsers
667 *
668 *****************************************************************/
669
670static BOOLEAN feHelpCalled = FALSE;
671
672static void heBrowserHelp(heEntry hentry)
673{
674  // check checksums of procs
675  int kchksum = (hentry != NULL && hentry->chksum > 0 ?
676                 heKeyChksum(hentry->key) : 0);
677  if (kchksum  && kchksum != hentry->chksum && heOnlineHelp(hentry->key))
678    return;
679
680  if (heCurrentHelpBrowser == NULL) feHelpBrowser(NULL, 0);
681  assume(heCurrentHelpBrowser != NULL);
682  if (! feHelpCalled)
683  {
684    Warn("Displaying help in browser '%s'.", heCurrentHelpBrowser->browser);
685    if (strcmp(heCurrentHelpBrowser->browser, "netscape") == 0 &&
686        feResource('h', 0) == NULL)
687    {
688      Warn("Using URL '%s'.", feResource('u', 0));
689    }
690    Warn("Use 'system(\"--browser\", <browser>);' to change browser,");
691    char* browsers = StringSetS("where <browser> can be: ");
692    int i = 0;
693    i = 0;
694    while (heHelpBrowsers[i].browser != NULL)
695    {
696      if (heHelpBrowsers[i].init_proc(0))
697        StringAppend("\"%s\", ", heHelpBrowsers[i].browser);
698      i++;
699    }
700    if (browsers[strlen(browsers)-2] == ',')
701    {
702      browsers[strlen(browsers)-2] = '.';
703      browsers[strlen(browsers)-1] = '\0';
704    }
705    WarnS(browsers);
706  }
707
708  heCurrentHelpBrowser->help_proc(hentry);
709  feHelpCalled = TRUE;
710}
711
712#define MAX_SYSCMD_LEN MAXPATHLEN*2
713// browser functions
714static BOOLEAN heInfoInit(int warn)
715{
716  if (feResource('i', warn) == NULL)
717  {
718    if (warn) WarnS("'info' help browser not available: no InfoFile");
719    return FALSE;
720  }
721  if (feResource('I') == NULL)
722  {
723    if (warn)
724      WarnS("'info' help browser not available: no 'info' program found");
725    return FALSE;
726  }
727  return TRUE;
728}
729static void heInfoHelp(heEntry hentry)
730{
731  char sys[MAX_SYSCMD_LEN];
732
733  if (hentry != NULL && *(hentry->key) != '\0')
734  {
735    if (*(hentry->node) != '\0')
736      sprintf(sys, "%s -f %s --node='%s'",
737              feResource('I'), feResource('i'), hentry->node);
738    else
739      sprintf(sys, "%s -f %s Index '%s'",
740              feResource('I'), feResource('i'), hentry->key);
741  }
742  else
743    sprintf(sys, "%s -f %s --node=Top", feResource('I'), feResource('i'));
744  system(sys);
745}
746
747#if ! defined(macintosh)
748static BOOLEAN heNetscapeInit(int warn)
749{
750  if (feResource('N' /*"netscape"*/, warn) == NULL)
751  {
752    if (warn) WarnS("'netscape' help browser not available: no 'netscape' program found");
753    return FALSE;
754  }
755#ifndef WINNT
756  if (getenv("DISPLAY") == NULL)
757  {
758    if (warn) WarnS("'netscape' help browser not available:");
759    if (warn) WarnS("Environment variable DISPLAY not set");
760    return FALSE;
761  }
762#endif
763 
764  if (feResource('h' /*"HtmlDir"*/, (feOptValue(FE_OPT_ALLOW_NET)? 0 : warn)) 
765      == NULL)
766  {
767    if (warn) WarnS("No local HtmlDir found.");
768    if (feOptValue(FE_OPT_ALLOW_NET))
769    {
770      if (warn) Warn("Using URL '%s' instead.", feResource('u' /*"ManualUrl"*/, warn));
771    }
772    else
773      return FALSE;
774  }
775  return TRUE;
776}
777
778static void heNetscapeHelp(heEntry hentry)
779{
780  char sys[MAX_SYSCMD_LEN];
781  char url[MAXPATHLEN];
782  char* htmldir = feResource('h' /*"HtmlDir"*/);
783  char* urltype;
784
785  if (htmldir == NULL)
786  {
787    urltype = "";
788    htmldir = feResource('u' /*"ManualUrl"*/);
789  }
790  else
791  {
792    urltype = "file:";
793  }
794
795  if (hentry != NULL && *(hentry->url) != '\0')
796  {
797    sprintf(url, "%s%s/%s", urltype, htmldir, hentry->url);
798  }
799  else
800  {
801    sprintf(url, "%s%s/index.htm", urltype, htmldir);
802  }
803#ifndef WINNT
804  sprintf(sys, "%s --remote 'OpenUrl(%s)' > /dev/null 2>&1",
805#else
806  sprintf(sys, "%s %s", 
807#endif
808          feResource('N' /*"netscape"*/), url);
809
810  // --remote exits with status != 0 if netscaep isn't already running
811  if (system(sys) != 0)
812  {
813    sprintf(sys, "%s %s &", feResource('N' /*"netscape"*/), url);
814    system(sys);
815  }
816  else
817  {
818    if (! feHelpCalled)
819    {
820      Warn("Help is displayed in already running 'netscape'.");
821    }
822  }
823}
824
825#ifdef ix86_Win
826static void heHtmlHelp(heEntry hentry)
827{
828  char url[MAXPATHLEN];
829  char* html_dir = feResource('h' /*"HtmlDir"*/);
830  sprintf(url, "%s/%s",
831          (html_dir != NULL ? html_dir : feResource('u' /*"ManualUrl"*/)),
832          (hentry!=NULL && *(hentry->url)!='\0' ? hentry->url : "index.htm"));
833
834  heOpenWinntUrl(url, (html_dir != NULL ? 1 : 0));
835}
836
837static void heWinHelp(heEntry hentry)
838{
839  char keyw[MAX_HE_ENTRY_LENGTH];
840  strcat(keyw,hentry->key);
841  char* helppath = feResource('h' /*"HtmlDir"*/);
842  const char *filename="/Manual.hlp";
843  helppath = strcat(helppath,filename);
844
845  heOpenWinntHlp(keyw,helppath);
846}
847
848#endif
849
850static BOOLEAN heXinfoInit(int warn)
851{
852#ifndef WINNT
853  if (getenv("DISPLAY") == NULL)
854  {
855    if (warn) WarnS("'xinfo' help browser not available:");
856    if (warn) WarnS("Environment variable DISPLAY not set");
857    return FALSE;
858  }
859#endif
860  if (feResource('i', warn) == NULL)
861  {
862    if (warn) WarnS("'xinfo' help browser not available: no InfoFile");
863    return FALSE;
864  }
865  if (feResource('I', warn) == NULL)
866  {
867    if (warn) WarnS("'xinfo' help browser not available: no 'info' program found");
868    return FALSE;
869  }
870  if (feResource('X', warn) == NULL)
871  {
872    if (warn) WarnS("'xinfo' help browser not available: no 'xterm' program found");
873    return FALSE;
874  }
875  return TRUE;
876}
877static void heXinfoHelp(heEntry hentry)
878{
879  char sys[MAX_SYSCMD_LEN];
880
881#ifdef WINNT
882#define EXTRA_XTERM_ARGS "+vb -sb -fb Courier-bold-13 -tn linux -cr Red3"
883#else
884#define EXTRA_XTERM_ARGS ""
885#endif
886
887  if (hentry != NULL && *(hentry->key) != '\0')
888  {
889    if (*(hentry->node) != '\0')
890      sprintf(sys, "%s %s -e %s -f %s --node='%s' &",
891              feResource('X'), EXTRA_XTERM_ARGS, 
892              feResource('I'), feResource('i'), hentry->node);
893    else
894      sprintf(sys, "%s %s -e %s -f %s Index '%s' &",
895              feResource('X'), EXTRA_XTERM_ARGS,
896              feResource('I'), feResource('i'), hentry->key);
897  }
898  else
899    sprintf(sys, "%s %s -e %s -f %s --node=Top &",
900            feResource('X'), EXTRA_XTERM_ARGS,
901            feResource('I'), feResource('i'));
902  system(sys);
903}
904
905static BOOLEAN heTkinfoInit(int warn)
906{
907#ifndef WINNT
908  if (getenv("DISPLAY") == NULL)
909  {
910    if (warn) WarnS("'tkinfo' help browser not available:");
911    if (warn) WarnS("Environment variable DISPLAY not set");
912    return FALSE;
913  }
914#endif
915  if (feResource('i', warn) == NULL)
916  {
917    if (warn) WarnS("'tkinfo' help browser not available: no InfoFile");
918    return FALSE;
919  }
920  if (feResource('T', warn) == NULL)
921  {
922    if (warn) WarnS("'tkinfo' help browser not available: no 'tkinfo' program found");
923    return FALSE;
924  }
925  return TRUE;
926}
927static void heTkinfoHelp(heEntry hentry)
928{
929  char sys[MAX_SYSCMD_LEN];
930  if (hentry != NULL && *(hentry->node) != '\0')
931  {
932    sprintf(sys, "%s '(%s)%s' &",
933            feResource('T'), feResource('i'), hentry->node);
934  }
935  else
936  {
937    sprintf(sys, "%s %s &",
938            feResource('T'), feResource('i'));
939  }
940  system(sys);
941}
942#endif // ! defined(macintosh)
943
944static BOOLEAN heDummyInit(int warn)
945{
946  return TRUE;
947}
948static void heDummyHelp(heEntry hentry)
949{
950  Werror("No functioning help browser available.");
951}
952
953static BOOLEAN heEmacsInit(int warn)
954{
955  return TRUE;
956}
957static void heEmacsHelp(heEntry hentry)
958{
959  WarnS("Your help command could not be executed. Use");
960  Warn("C-h C-s %s",
961       (hentry != NULL && *(hentry->node) != '\0' ? hentry->node : "Top"));
962  Warn("to enter the Singular online help. For general");
963  Warn("information on Singular running under Emacs, type C-h m.");
964}
965static BOOLEAN heBuiltinInit(int warn)
966{
967  if (feResource('i', warn) == NULL)
968  {
969    if (warn) WarnS("'builtin' help browser not available: no InfoFile");
970    return FALSE;
971  }
972  return TRUE;
973}
974static int singular_manual(char *str);
975static void heBuiltinHelp(heEntry hentry)
976{
977  char* node = omStrDup(hentry != NULL && *(hentry->node) != '\0' ?
978                       hentry->node : "Top");
979  singular_manual(node);
980  omFree(node);
981}
982
983
984/* ========================================================================== */
985// old, stupid builtin_help
986// This could be implemented much more clever, but I'm too lazy to do this now
987//
988#define HELP_OK        0
989#define FIN_INDEX    '\037'
990#define not  !
991#define HELP_NOT_OPEN  1
992#define HELP_NOT_FOUND 2
993#define BUF_LEN        256
994#define IDX_LEN        64
995#define MAX_LINES      21
996
997#ifdef macintosh
998static char tolow(char p)
999#else
1000static inline char tolow(char p)
1001#endif
1002{
1003  if (('A'<=p)&&(p<='Z')) return p | 040;
1004  return p;
1005}
1006
1007/*************************************************/
1008static int show(unsigned long offset,FILE *help, char *close)
1009{ char buffer[BUF_LEN+1];
1010  int  lines = 0;
1011
1012  if( help== NULL)
1013    if( (help = fopen(feResource('i'), "rb")) == NULL)
1014      return HELP_NOT_OPEN;
1015
1016  fseek(help,  (long)(offset+1), (int)0);
1017  while( !feof(help)
1018        && *fgets(buffer, BUF_LEN, help) != EOF
1019        && buffer[0] != FIN_INDEX)
1020  {
1021    printf("%s", buffer);
1022    if(lines++> MAX_LINES)
1023    {
1024#ifdef macintosh
1025      printf("\n Press <RETURN> to continue or x and <RETURN> to exit help.\n");
1026#else
1027      printf("\n Press <RETURN> to continue or x to exit help.\n");
1028#endif
1029      fflush(stdout);
1030      *close = (char)getchar();
1031      if(*close=='x')
1032      {
1033        getchar();
1034        break;
1035      }
1036      lines=0;
1037    }
1038  }
1039  if(*close!='x')
1040  {
1041#ifdef macintosh
1042    printf("\nEnd of part. Press <RETURN> to continue or x and <RETURN> to exit help.\n");
1043#else
1044    printf("\nEnd of part. Press <RETURN> to continue or x to exit help.\n");
1045#endif
1046    fflush(stdout);
1047    *close = (char)getchar();
1048    if(*close=='x')
1049      getchar();
1050  }
1051  return HELP_OK;
1052}
1053
1054/*************************************************/
1055static int singular_manual(char *str)
1056{ FILE *index=NULL,*help=NULL;
1057  unsigned long offset;
1058  char *p,close;
1059  int done = 0;
1060  char buffer[BUF_LEN+1],
1061       Index[IDX_LEN+1],
1062       String[IDX_LEN+1];
1063
1064  if( (index = fopen(feResource('i'), "rb")) == NULL)
1065  {
1066    return HELP_NOT_OPEN;
1067  }
1068
1069  for(p=str; *p; p++) *p = tolow(*p);/* */
1070  do
1071  {
1072    p--;
1073  }
1074  while ((p != str) && (*p<=' '));
1075  p++;
1076  *p='\0';
1077  (void)sprintf(String, " %s ", str);
1078
1079  while(!feof(index)
1080        && fgets(buffer, BUF_LEN, index) != (char *)0
1081        && buffer[0] != FIN_INDEX);
1082
1083  while(!feof(index))
1084  {
1085    (void)fgets(buffer, BUF_LEN, index); /* */
1086    (void)sscanf(buffer, "Node:%[^\177]\177%ld\n", Index, &offset);
1087    for(p=Index; *p; p++) *p = tolow(*p);/* */
1088    (void)strcat(Index, " ");
1089    if( strstr(Index, String)!=NULL)
1090    {
1091      done++; (void)show(offset, help, &close);
1092    }
1093    Index[0]='\0';
1094    if(close=='x')
1095    break;
1096  }
1097  if (index != NULL) (void)fclose(index);
1098  if (help != NULL) (void)fclose(help);
1099  if(not done)
1100  {
1101    Warn("`%s` not found",String);
1102    return HELP_NOT_FOUND;
1103  }
1104  return HELP_OK;
1105}
1106/*************************************************/
Note: See TracBrowser for help on using the repository browser.