source: git/kernel/fehelp.cc @ 788529d

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