source: git/Singular/fehelp.cc @ 6e3652

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