source: git/Singular/fehelp.cc @ 84a6a7

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