source: git/Singular/fehelp.cc @ 08c2d6

spielwiese
Last change on this file since 08c2d6 was 08c2d6, checked in by Hans Schönemann <hannes@…>, 15 years ago
*hannes: gcc 4.4 git-svn-id: file:///usr/local/Singular/svn/trunk@11914 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 32.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: help system
6* versin $Id: fehelp.cc,v 1.58 2009-06-21 14:10:18 Singular Exp $
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"
17#include <mylimits.h>
18#include "tok.h"
19#include "omalloc.h"
20#include "febase.h"
21#include "ipid.h"
22#include "ipshell.h"
23#include "libparse.h"
24#include "feOpt.h"
25#include "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 "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#ifdef HAVE_NS
780    yylplex(str, libnamebuf, &lib_style, IDROOT, FALSE, GET_INFO);
781#else
782    yylplex(str, libnamebuf, &lib_style, GET_INFO);
783#endif /* HAVE_NS */
784    reinit_yylp();
785    if(lib_style == OLD_LIBSTYLE)
786    {
787      char buf[256];
788      fseek(fp, 0, SEEK_SET);
789      Warn( "library %s has an old format. Please fix it for the next time",
790            str);
791      if (str != s) omFree(str);
792      BOOLEAN found=FALSE;
793      while (fgets( buf, sizeof(buf), fp))
794      {
795        if (strncmp(buf,"//",2)==0)
796        {
797          if (found) return TRUE;
798        }
799        else if ((strncmp(buf,"proc ",5)==0)||(strncmp(buf,"LIB ",4)==0))
800        {
801          if (!found) WarnS("no help part in library found");
802          return TRUE;
803        }
804        else
805        {
806          found=TRUE;
807          PrintS(buf);
808        }
809      }
810    }
811    else
812    {
813      if (str != s) omFree(str);
814      fclose( yylpin );
815      PrintS(text_buffer);
816      omFree(text_buffer);
817      text_buffer=NULL;
818    }
819    return TRUE;
820  }
821
822  if (str != s) omFree(str);
823  return FALSE;
824}
825
826static long heKeyChksum(char* key)
827{
828  if (key == NULL || *key == '\0') return 0;
829#ifdef HAVE_NS
830  idhdl h=IDROOT->get(key,myynest);
831#else
832  idhdl h=idroot->get(key,myynest);
833#endif /* HAVE_NS */
834  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
835  {
836    procinfo *pi = IDPROC(h);
837    if (pi != NULL) return pi->data.s.help_chksum;
838  }
839  return 0;
840}
841
842/*****************************************************************
843 *
844 * Implementation : Help Browsers
845 *
846 *****************************************************************/
847
848static BOOLEAN feHelpCalled = FALSE;
849
850static void heBrowserHelp(heEntry hentry)
851{
852  // check checksums of procs
853  int kchksum = (hentry != NULL && hentry->chksum > 0 ?
854                 heKeyChksum(hentry->key) : 0);
855  if (kchksum  && kchksum != hentry->chksum && heOnlineHelp(hentry->key))
856    return;
857
858  if (heCurrentHelpBrowser == NULL) feHelpBrowser(NULL, 0);
859  assume(heCurrentHelpBrowser != NULL);
860  if (! feHelpCalled)
861  {
862    Warn("Displaying help in browser '%s'.", heCurrentHelpBrowser->browser);
863    //if (strcmp(heCurrentHelpBrowser->browser, "netscape") == 0 &&
864    //    feResource('h', 0) == NULL)
865    //{
866    //  Warn("Using URL '%s'.", feResource('u', 0));
867    //}
868    Warn("Use 'system(\"--browser\", <browser>);' to change browser,");
869    char* browsers = StringSetS("where <browser> can be: ");
870    int i = 0;
871    i = 0;
872    while (heHelpBrowsers[i].browser != NULL)
873    {
874      if (heHelpBrowsers[i].init_proc(0,i))
875        StringAppend("\"%s\", ", heHelpBrowsers[i].browser);
876      i++;
877    }
878    if (browsers[strlen(browsers)-2] == ',')
879    {
880      browsers[strlen(browsers)-2] = '.';
881      browsers[strlen(browsers)-1] = '\0';
882    }
883    WarnS(browsers);
884  }
885
886  heCurrentHelpBrowser->help_proc(hentry, heCurrentHelpBrowserIndex);
887  feHelpCalled = TRUE;
888}
889
890#define MAX_SYSCMD_LEN MAXPATHLEN*2
891static BOOLEAN heGenInit(int warn, int br)
892{
893  if (heHelpBrowsers[br].required==NULL) return TRUE;
894  const char *p=heHelpBrowsers[br].required;
895  while (*p>'\0')
896  {
897    switch (*p)
898    {
899      case '#': break;
900      case ' ': break;
901      case 'i': /* singular.hlp */
902      case 'x': /* singular.idx */
903      case 'C': /* chm file Manual.chm */
904      case 'h': /* html dir */
905               if (feResource(*p, warn) == NULL)
906               {
907                 if (warn) Warn("ressource `%c` not found",*p);
908                 return FALSE;
909               }
910               break;
911      case 'D': /* DISPLAY */
912               if (getenv("DISPLAY") == NULL)
913               {
914                 if (warn) WarnS("ressource `D` not found");
915                 return FALSE;
916               }
917               break;
918      case 'E': /* executable: E:xterm: */
919      case 'O': /* OS: O:ix86Mac-darwin/ppcMac-darwin: */
920               {
921                 char name[128];
922                 char exec[128];
923                 char op=*p;
924                 memset(name,0,128);
925                 int i=0;
926                 p++;
927                 while (((*p==':')||(*p<=' ')) && (*p!='\0')) p++;
928                 while((i<127) && (*p>' ') && (*p!=':'))
929                 {
930                   name[i]=*p; p++; i++;
931                 }
932                 if (i==0) return FALSE;
933
934                 if ((op=='O') && (strcmp(name,S_UNAME)!=0))
935                   return FALSE;
936                 if ((op=='E') && (omFindExec(name,exec)==NULL))
937                 {
938                   if (warn) Warn("executable `%s` not found",name);
939                   return FALSE;
940                 }
941               }
942               break;
943      default: Warn("unknown char %c",*p);
944               break;
945    }
946    p++;
947  }
948  return TRUE;
949}
950
951#ifdef ix86_Win
952
953static void heHtmlHelp(heEntry hentry, int br)
954{
955  char url[MAXPATHLEN];
956  char* html_dir = feResource('h' /*"HtmlDir"*/);
957  sprintf(url, "%s/%s",
958          (html_dir != NULL ? html_dir : feResource('u' /*"ManualUrl"*/)),
959          (hentry!=NULL && *(hentry->url)!='\0' ? hentry->url : "index.htm"));
960
961  heOpenWinntUrl(url, (html_dir != NULL ? 1 : 0));
962}
963
964static void heWinHtmlHelp(heEntry hentry, int br)
965// Function to call the Microsoft HTML Help System
966// Uses API Call Function in sing_win.cc
967{
968  char keyw[MAX_HE_ENTRY_LENGTH];
969  if ((hentry!=NULL)&&(hentry->key!=NULL))
970    strcpy(keyw,hentry->key);
971  else
972    strcpy(keyw," ");
973  char* helppath = feResource('C' /*"CHM Datei"*/);
974  heOpenWinHtmlHelp(keyw,helppath);
975}
976
977static void heWinHelp(heEntry hentry, int br)
978{
979  char keyw[MAX_HE_ENTRY_LENGTH];
980  if ((hentry!=NULL)&&(hentry->key!=NULL))
981    strcpy(keyw,hentry->key);
982  else
983    strcpy(keyw," ");
984  char* helppath = feResource('h' /*"HtmlDir"*/);
985  const char *filename="/Manual.hlp";
986  int helppath_len=0;
987  if (helppath!=NULL) helppath_len=strlen(helppath);
988  char *callpath=(char *)omAlloc0(helppath_len+strlen(filename)+1);
989  if ((helppath!=NULL) && (*helppath>' '))
990    strcpy(callpath,helppath);
991  strcat(callpath,filename);
992  heOpenWinntHlp(keyw,callpath);
993  omfree(callpath);
994}
995#endif
996static void heGenHelp(heEntry hentry, int br)
997{
998  char sys[MAX_SYSCMD_LEN];
999  char url[MAXPATHLEN];
1000  const char *p=heHelpBrowsers[br].action;
1001  if (p==NULL) {PrintS("no action ?\n"); return;}
1002  memset(sys,0,MAX_SYSCMD_LEN);
1003  int i=0;
1004  while ((*p>'\0')&& (i<MAX_SYSCMD_LEN))
1005  {
1006    if ((*p)=='%')
1007    {
1008      p++;
1009      switch (*p)
1010      {
1011        case 'f': /* local html:file */
1012        case 'h': /* local html:URL */
1013        case 'H': /* www html */
1014                 {
1015                   char temp[256];
1016                   char *htmldir = feResource('h' /*"HtmlDir"*/);
1017                   if ((*p=='h')&&(htmldir!=NULL))
1018                     strcat(sys,"file://localhost");
1019                   else if ((*p=='H')||(htmldir==NULL))
1020                     htmldir = feResource('u' /* %H -> "ManualUrl"*/);
1021                     /* always defined */
1022                   if (hentry != NULL && *(hentry->url) != '\0')
1023                   #ifdef HAVE_VSNPRINTF
1024                     snprintf(temp,256,"%s/%s", htmldir, hentry->url);
1025                   else
1026                     snprintf(temp,256,"%s/index.htm", htmldir);
1027                   #else
1028                     sprintf(temp,"%s/%s", htmldir, hentry->url);
1029                   else
1030                     sprintf(temp,"%s/index.htm", htmldir);
1031                   #endif
1032                   strcat(sys,temp);
1033                   if ((*p)=='f')
1034                   { // remove #SEC
1035                     char *pp=(char *)strchr(sys,'#');
1036                     if (pp!=NULL)
1037                     {
1038                       *pp='\0';
1039                       i=strlen(sys);
1040                       memset(pp,0,MAX_SYSCMD_LEN-i);
1041                     }
1042                   }
1043                   i=strlen(sys);
1044                   break;
1045                 }
1046        case 'i': /* singular.hlp */
1047                 {
1048                   char *i_res=feResource('i');
1049                   if (i_res!=NULL) strcat(sys,i_res);
1050                   else
1051                   {
1052                     WarnS("singular.hlp not found");
1053                     return;
1054                   }
1055                   i=strlen(sys);
1056                   break;
1057                 }
1058        case 'n': /* info node */
1059                 {
1060                   char temp[256];
1061                   if ((hentry!=NULL) && (*(hentry->node) != '\0'))
1062                     sprintf(temp,"%s",hentry->node);
1063                   //else if ((hentry!=NULL) && (hentry->key!=NULL))
1064                   //  sprintf(temp,"Index '%s'",hentry->key);
1065                   else
1066                     sprintf(temp,"Top");
1067                   strcat(sys,temp);
1068                   i=strlen(sys);
1069                   break;
1070                 }
1071        default: break;
1072      }
1073      p++;
1074    }
1075    else
1076    {
1077      sys[i]=*p;
1078      p++;i++;
1079    }
1080  }
1081  Print("running `%s`\n",sys);
1082  int dummy=system(sys);
1083}
1084
1085#ifdef ix86_Win
1086static void heHtmlHelp(heEntry hentry)
1087{
1088  char url[MAXPATHLEN];
1089  char* html_dir = feResource('h' /*"HtmlDir"*/);
1090  sprintf(url, "%s/%s",
1091          (html_dir != NULL ? html_dir : feResource('u' /*"ManualUrl"*/)),
1092          (hentry!=NULL && *(hentry->url)!='\0' ? hentry->url : "index.htm"));
1093
1094  heOpenWinntUrl(url, (html_dir != NULL ? 1 : 0));
1095}
1096
1097static void heWinHelp(heEntry hentry)
1098{
1099  char keyw[MAX_HE_ENTRY_LENGTH];
1100  if ((hentry!=NULL)&&(hentry->key!=NULL))
1101    strcpy(keyw,hentry->key);
1102  else
1103    strcpy(keyw," ");
1104  char* helppath = feResource('h' /*"HtmlDir"*/);
1105  const char *filename="/Manual.hlp";
1106  int helppath_len=0;
1107  if (helppath!=NULL) helppath_len=strlen(helppath);
1108  char *callpath=(char *)omAlloc0(helppath_len+strlen(filename)+1);
1109  if ((helppath!=NULL) && (*helppath>' '))
1110    strcpy(callpath,helppath);
1111  strcat(callpath,filename);
1112  heOpenWinntHlp(keyw,callpath);
1113  omfree(callpath);
1114}
1115#endif
1116
1117static BOOLEAN heDummyInit(int warn, int br)
1118{
1119  return TRUE;
1120}
1121static void heDummyHelp(heEntry hentry, int br)
1122{
1123  Werror("No functioning help browser available.");
1124}
1125
1126static BOOLEAN heEmacsInit(int warn, int br)
1127{
1128  return TRUE;
1129}
1130static void heEmacsHelp(heEntry hentry, int br)
1131{
1132  WarnS("Your help command could not be executed. Use");
1133  Warn("C-h C-s %s",
1134       (hentry != NULL && *(hentry->node) != '\0' ? hentry->node : "Top"));
1135  Warn("to enter the Singular online help. For general");
1136  Warn("information on Singular running under Emacs, type C-h m.");
1137}
1138static int singular_manual(char *str);
1139static void heBuiltinHelp(heEntry hentry, int br)
1140{
1141  char* node = omStrDup(hentry != NULL && *(hentry->node) != '\0' ?
1142                       hentry->node : "Top");
1143  singular_manual(node);
1144  omFree(node);
1145}
1146
1147
1148/* ========================================================================== */
1149// old, stupid builtin_help
1150// This could be implemented much more clever, but I'm too lazy to do this now
1151//
1152#define HELP_OK        0
1153#define FIN_INDEX    '\037'
1154#define HELP_NOT_OPEN  1
1155#define HELP_NOT_FOUND 2
1156#define BUF_LEN        256
1157#define IDX_LEN        64
1158#define MAX_LINES      21
1159
1160static inline char tolow(char p)
1161{
1162  if (('A'<=p)&&(p<='Z')) return p | 040;
1163  return p;
1164}
1165
1166/*************************************************/
1167static int show(unsigned long offset, char *close)
1168{ char buffer[BUF_LEN+1];
1169  int  lines = 0;
1170  FILE * help;
1171
1172  if( (help = fopen(feResource('i'), "rb")) == NULL)
1173    return HELP_NOT_OPEN;
1174
1175  fseek(help,  (long)(offset+1), (int)0);
1176  while( (!feof(help))
1177        && (*fgets(buffer, BUF_LEN, help) != EOF)
1178        && (buffer[0] != FIN_INDEX))
1179  {
1180    printf("%s", buffer);
1181    if(lines++> MAX_LINES)
1182    {
1183      printf("\n Press <RETURN> to continue or x to exit help.\n");
1184      fflush(stdout);
1185      *close = (char)getchar();
1186      if(*close=='x')
1187      {
1188        getchar();
1189        break;
1190      }
1191      lines=0;
1192    }
1193  }
1194  if(*close!='x')
1195  {
1196    printf("\nEnd of part. Press <RETURN> to continue or x to exit help.\n");
1197    fflush(stdout);
1198    *close = (char)getchar();
1199    if(*close=='x')
1200      getchar();
1201  }
1202  fclose(help);
1203  return HELP_OK;
1204}
1205
1206/*************************************************/
1207static int singular_manual(char *str)
1208{ FILE *index=NULL;
1209  unsigned long offset;
1210  char *p,close=' ';
1211  int done = 0;
1212  char buffer[BUF_LEN+1],
1213       Index[IDX_LEN+1],
1214       String[IDX_LEN+1];
1215  Print("HELP >>%s>>\n",str);
1216
1217  if( (index = fopen(feResource('i'), "rb")) == NULL)
1218  {
1219    return HELP_NOT_OPEN;
1220  }
1221
1222  for(p=str; *p; p++) *p = tolow(*p);/* */
1223  do
1224  {
1225    p--;
1226  }
1227  while ((p != str) && (*p<=' '));
1228  p++;
1229  *p='\0';
1230  (void)sprintf(String, " %s ", str);
1231
1232  while(!feof(index)
1233        && (fgets(buffer, BUF_LEN, index) != (char *)0)
1234        && (buffer[0] != FIN_INDEX));
1235
1236  while(!feof(index))
1237  {
1238    char* dummy=fgets(buffer, BUF_LEN, index); /* */
1239    (void)sscanf(buffer, "Node:%[^\177]\177%ld\n", Index, &offset);
1240    for(p=Index; *p; p++) *p = tolow(*p);/* */
1241    (void)strcat(Index, " ");
1242    if( strstr(Index, String)!=NULL)
1243    {
1244      done++; (void)show(offset, &close);
1245    }
1246    Index[0]='\0';
1247    if(close=='x')
1248    break;
1249  }
1250  if (index != NULL) (void)fclose(index);
1251  if(! done)
1252  {
1253    Warn("`%s` not found",String);
1254    return HELP_NOT_FOUND;
1255  }
1256  return HELP_OK;
1257}
1258/*************************************************/
Note: See TracBrowser for help on using the repository browser.