source: git/Singular/fehelp.cc @ bee06d

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