~ubuntu-branches/debian/jessie/eso-midas/jessie

« back to all changes in this revision

Viewing changes to prim/tw3/libsrc/thelp.c

  • Committer: Package Import Robot
  • Author(s): Ole Streicher
  • Date: 2014-04-22 14:44:58 UTC
  • Revision ID: package-import@ubuntu.com-20140422144458-okiwi1assxkkiz39
Tags: upstream-13.09pl1.2+dfsg
ImportĀ upstreamĀ versionĀ 13.09pl1.2+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*===========================================================================
 
2
  Copyright (C) 1988-2009 European Southern Observatory (ESO)
 
3
 
 
4
  This program is free software; you can redistribute it and/or 
 
5
  modify it under the terms of the GNU General Public License as 
 
6
  published by the Free Software Foundation; either version 2 of 
 
7
  the License, or (at your option) any later version.
 
8
 
 
9
  This program is distributed in the hope that it will be useful,
 
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
  GNU General Public License for more details.
 
13
 
 
14
  You should have received a copy of the GNU General Public 
 
15
  License along with this program; if not, write to the Free 
 
16
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
 
17
  MA 02139, USA.
 
18
 
 
19
  Corresponding concerning ESO-MIDAS should be addressed as follows:
 
20
        Internet e-mail: midas@eso.org
 
21
        Postal address: European Southern Observatory
 
22
                        Data Management Division 
 
23
                        Karl-Schwarzschild-Strasse 2
 
24
                        D 85748 Garching bei Muenchen 
 
25
                        GERMANY
 
26
===========================================================================*/
 
27
 
 
28
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
29
 
 
30
.TYPE           Module
 
31
.IDENTIFICATION thelp.c
 
32
.AUTHOR         Francois Ochsenbein [ESO-IPG]
 
33
.LANGUAGE       C
 
34
.KEYWORDS       Hierarchical Help using TermWindows
 
35
.ENVIRONMENT    TermWindows
 
36
 
 
37
 
 
38
.COMMENTS       The module uses actions starting with `H'
 
39
                The \Help and \HelpLoad macros contain four parameters:
 
40
\begin{TeX}
 
41
\begin{enumerate}
 
42
\item The level, a number starting from 0 up to 9
 
43
\item   The topic, or filename for HelpLoad
 
44
\item   A short explanation, for survey purposes.
 
45
\item   The context specification, as a set of words separated by commas.
 
46
\end{enumerate}
 
47
 
 
48
A located topic starts {\em just after} the {\tt\b Help} found macro.
 
49
 
 
50
\end{TeX}
 
51
 
 
52
        The \HelpIndex has 7 parameters:
 
53
\begin{TeX}
 
54
\begin{enumerate}
 
55
\item The level, a number starting from 0 up to 9
 
56
\item   The topic, or filename for HelpLoad
 
57
\item   A short explanation, for survey purposes.
 
58
\item   The context specification, as a set of words separated by commas.
 
59
\item   The name of the file where the help is included
 
60
\item   The starting position just following the \b Help
 
61
\item   The number of bytes to load.
 
62
\end{enumerate}
 
63
 
 
64
\end{TeX}
 
65
 
 
66
.VERSION 1.0    13-May-1988: Creation
 
67
.VERSION 1.1    07-Nov-1988: Possibility of an index with macro \HelpIndex
 
68
.VERSION 1.2    05-Dec-1988: Check if \Help commented out...
 
69
.VERSION 1.3    20-Jan-1989: th_set: allows NULL pointer without crash...
 
70
.VERSION 1.4    03-Mar-1989: Corrected bug signaled by Jeannine:
 
71
                        \Help is always triggered, even if it's commented...
 
72
.VERSION 1.5    29-Mar-1989: Default extension for files = .tex
 
73
.VERSION 1.6    23-May-1989: Modified documentation
 
74
.VERSION 1.7    22-Jun-1989: Modified th_set: ONLY ADDRESSES are kept...
 
75
.VERSION 1.8    05-Apr-1990: Modified PromptKey: The prompt "? for subtopics"
 
76
                                appears only if subtopics do exist..
 
77
.VERSION 1.9    09-Sep-1990: Bug corrected in load_file: fname is saved
 
78
                                in a independant location.
 
79
.VERSION 1.91   21-Nov-1990: Routine th_setsep to define the list
 
80
                                of separators between topics.
 
81
.VERSION 2.0    04-Dec-1990: Allow Several Indexes to be Merged.
 
82
                        (see th_merge)
 
83
.VERSION 2.1    07-Jun-1991: Added th_loc routine
 
84
 
 
85
 090901         last modif
 
86
--------------------------------------------------------------------------*/
 
87
 
 
88
#define DEBUG           0       /* For debugging only           */
 
89
 
 
90
#include <stdlib.h>
 
91
 
 
92
 
 
93
#define PM_LEVEL        LEVEL_TX
 
94
#define MAX_TOPIC       31      /* Maximal length for topic comparison  */
 
95
 
 
96
#include <stesodef.h>
 
97
#include <twhelp.h>
 
98
#include <tw.h>
 
99
#include <atype.h>
 
100
#include <str.h>
 
101
#include <tex.h>
 
102
#include <buffer.h>
 
103
 
 
104
#include <proto_os.h>
 
105
 
 
106
#define reply_size      40
 
107
#define default_ext     ".tex"
 
108
#define FileDate(f)     fi_date(NameFile(f,default_ext))
 
109
 
 
110
#define _REDISPLAY_     10
 
111
#define _PROMPT_        11
 
112
#define _SUMMARY_       12
 
113
#define _BAD_INDEX_     -3
 
114
 
 
115
 
 
116
extern int mm_free();
 
117
 
 
118
extern int tv_bell(), tv_dim(), tv_getcc();
 
119
 
 
120
extern int fi_open(), fi_gets(), fi_close(), fi_load();
 
121
 
 
122
extern int ty_close(), ty_display(), ty_end(), ty_mdisplay();
 
123
extern int ty_more();
 
124
 
 
125
extern int tw_fill(), tw_attr(), tw_uattr(), tw_r(), tw_goto(), tw_rule();
 
126
extern int tw_st(), tw_uflag(), tw_chars(), tw_copw(), tw_flags();
 
127
extern int tw_uw(), tw_write(), tw_il(), tw_clear(), tw_dc();
 
128
extern int tw_nl(), tw_upw(), tw_uc(), tw_mvc(), tw_copy();
 
129
extern int tw_mrule(), tw_cus(), tw_gc2(), tw_close(), tw_cur();
 
130
extern int tw_cline(), tw_home(), tw_tra(), tw_wa();
 
131
extern int tw_awhere(), tw_agoto(), tw_gc1(), tw_get1(), tw_wf();
 
132
 
 
133
extern int pm_enter(), pm_iexit(), pm_tr2(), pm_ed_i(), pm_ed_trace();
 
134
 
 
135
extern int eh_ed_i(), eh_ed_as(), eh_put1(), eh_put();
 
136
 
 
137
extern int tex_exec(), tex_unit(), tex_getparm(), tex_mexec(), tex_tell();
 
138
extern int tex_input(), tex_load(), tex_list(), tex_getvparm();
 
139
 
 
140
extern int tx_jr(), tx_jc(), tx_justify();
 
141
extern int tx_display(), tx_option();
 
142
extern int tx_fdisplay(), tx_file(), tx_mdisplay();
 
143
 
 
144
 
 
145
static  int     TheDoc = 0;             /* DOC Folder           */
 
146
static  WINDOW *helpw = NULL_WINDOW;    /* Small ^G Window      */
 
147
static  TeX     *htex = NULL_PTR(TeX);
 
148
TeX     *tx_tex();
 
149
 
 
150
typedef struct {
 
151
        char *start;
 
152
        char *end;
 
153
   }    PIECE;          /* Piece of text to use with DisplayArray */
 
154
 
 
155
static PIECE loaded_file;       /* Just loaded file     */
 
156
 
 
157
 
 
158
typedef struct {
 
159
        char    level;          /* Level 0-9            */
 
160
        char    flag;           /* '@' to load a file   */
 
161
        short   ltopic;         /* Proposed topic length*/
 
162
        char    *topic;         /* The topic address    */
 
163
        char    *got_topic;     /* The got topic address*/
 
164
        char    *hpos;          /* Where exactly is \Help */
 
165
        char    *pos;           /* Where exactly in current piece */
 
166
        int     piece;          /* Position in PIECE    */
 
167
        int     ofile;          /* Filenames Position   */
 
168
        long    fpos;           /* Position in File     */
 
169
        int     ltext;          /* Text length          */
 
170
   }    TOPIC;  
 
171
 
 
172
typedef struct {
 
173
        int     ofile;          /* Filenames Position   */
 
174
        long    fpos;           /* Position in File     */
 
175
        int     ltext;          /* Text length          */
 
176
        char    text[1];        /* Filename + Text      */
 
177
   }    LOADED; 
 
178
 
 
179
static  LOADED *loaded = NULL_PTR(LOADED);
 
180
 
 
181
static  TOPIC
 
182
        topics[10] = {  /* Current topic to look for */
 
183
        {'0', 0, 0, (char *)0, (char *)0, (char *)0, 0}, {'1'}, {'2'}, 
 
184
        {'3'}, {'4'}, {'5'}, {'6'}, {'7'}, {'8'}, {'9'}};
 
185
 
 
186
static  TOPIC   topc;
 
187
 
 
188
static  char    *located_help = (char *)0;      /* Used by th_loc */
 
189
static  char    help_flag;      /* Used for communication with th_act */
 
190
static  char    level_found;    /* Used for communication with th_act */
 
191
static  char    reply[reply_size];
 
192
static  char    blank = ' ';
 
193
static  int     subtopics = 0;  /* Used for communication with EdTop  */
 
194
 
 
195
static TWHELP   help;   /* Contains the Help definitions: windows + buffer */
 
196
 
 
197
static BUFFER   *list;          /* This buffer collects title + subtopics */
 
198
static BUFFER   *filenames;     /* This buffer collects filenames         */
 
199
static char     *tit3 = (char *)0;
 
200
static int      ltit3 = 0;
 
201
 
 
202
static unsigned char sep_table[256];
 
203
static char *sep_top = (char *)0;               /* Default Separators */
 
204
 
 
205
#define FINISH          goto FIN
 
206
 
 
207
#define HELP_MACRO      "\\Help"
 
208
#define HELP_INDEX      "\\HelpIndex"
 
209
#define default_title   " Help"
 
210
 
 
211
        /* MONITOR(TXHELP); */
 
212
 
 
213
 
 
214
/*==========================================================================
 
215
 *                      Interfaces to Doc
 
216
 *==========================================================================*/
 
217
static int myOpenDocText(str,len)
 
218
/*+++
 
219
.PURPOSE Interface to OpenDocText
 
220
.RETURNS NOK if not completely displayed / OK otherwise
 
221
---*/
 
222
        char    *str;   /* IN: TeX string to display */
 
223
        int     len;    /* IN: Length of Text   */
 
224
{
 
225
  CloseDoc(TheDoc);
 
226
  TheDoc = OpenDocText(help.w[1], str, len);
 
227
  RaiseWindow(help.w[1]);
 
228
  return(atLastDocPage(TheDoc));
 
229
}
 
230
 
 
231
static int myOpenDocArray(str,n)
 
232
/*+++
 
233
.PURPOSE Interface to OpenDocText
 
234
.RETURNS NOK if not completely displayed / OK otherwise
 
235
---*/
 
236
        char    **str;  /* IN: TeX strings to display */
 
237
        int     n;      /* IN: How many strings */
 
238
{
 
239
  CloseDoc(TheDoc);
 
240
  TheDoc = OpenDocArray(help.w[1], str, n);
 
241
  RaiseWindow(help.w[1]);
 
242
  return(atLastDocPage(TheDoc));
 
243
}
 
244
 
 
245
static int get_tit3()
 
246
/*+++
 
247
.PURPOSE Get the 3rd parameter of Title
 
248
.RETURNS Length of Text
 
249
---*/
 
250
{
 
251
        int l3;
 
252
        char *p;
 
253
 
 
254
  l3 = tex_getvparm(3);         /* The short explanation */
 
255
  p = (l3 > 0 ? htex->ap : "");
 
256
  if (l3 < 0)   l3 = 0;
 
257
  if (l3 >= ltit3)              /* Must expand  */
 
258
        ltit3 = 1 + (l3|7), tit3 = MEM_EXP(char, tit3, ltit3);
 
259
  oscopy (tit3, p, l3);
 
260
  tit3[l3] = EOS;
 
261
  return(l3);
 
262
}
 
263
 
 
264
/*==========================================================================
 
265
 *                      act0
 
266
 *==========================================================================*/
 
267
static int act0(str, len)
 
268
/*+++
 
269
.PURPOSE Action Routine to execute definitions in a help file
 
270
.RETURNS len (does nothing)
 
271
.REMARKS 
 
272
---*/
 
273
        char    *str;   /* IN: Action string, should start with H */
 
274
        int     len;    /* IN: Length of action string */
 
275
{
 
276
  return(len);
 
277
}  
 
278
 
 
279
/*==========================================================================
 
280
 *                      CheckContext
 
281
 *==========================================================================*/
 
282
static int CheckContext()
 
283
/*+++
 
284
.PURPOSE Checks if the context is OK
 
285
.RETURNS OK / NOK
 
286
.REMARKS Context is a string in help; if the 4th parameter of \Help
 
287
        includes something, the same string must be in help.context
 
288
---*/
 
289
{
 
290
        char    *p;
 
291
        int     status;
 
292
        
 
293
  status = OK;
 
294
  
 
295
  tex_getparm(4);               /* Get 4th parameter                    */
 
296
  if (*(htex->ap) == EOS)       /* No  4th parameter => always valid    */
 
297
        FINISH;
 
298
  
 
299
                                /* Check if 4th parameter includes context */
 
300
  p = htex->ap + stritem(htex->ap, help.context, "\t, ");
 
301
                                /* Separators may be , blank tab */
 
302
  if (*p == EOS)        status = NOK;
 
303
  
 
304
  FIN:
 
305
  return(status);
 
306
}  
 
307
 
 
308
/*==========================================================================
 
309
 *                      th_act
 
310
 *==========================================================================*/
 
311
static int th_act(str, len)
 
312
/*+++
 
313
.PURPOSE Action Routine to interpret the `\Help' Macros
 
314
.RETURNS 0      (must stop)
 
315
.REMARKS Context checking and \HelpIndex check.
 
316
---*/
 
317
        char    *str;   /* IN: Action string, should start with H */
 
318
        int     len;    /* IN: Length of action string */
 
319
{
 
320
        
 
321
  if (*str != 'H')      FINISH;
 
322
  
 
323
  if (help.context)
 
324
        if (*help.context)
 
325
                if_not(CheckContext())
 
326
                        FINISH;
 
327
          
 
328
  tex_getparm(1);       /* Indicates Level */
 
329
 
 
330
  if ((help.indexed == 0) && (str[1] == ':'))   FINISH;
 
331
  
 
332
  level_found = '0' + atoi(htex->ap);
 
333
  help_flag   = str[1]; /* @ for HelpLoad  */
 
334
 
 
335
  tex_getparm(2);       /* Get argument = Topic or File Name */
 
336
  
 
337
  FIN:
 
338
  return(0);
 
339
}  
 
340
 
 
341
/*==========================================================================
 
342
 *                      th_out
 
343
 *==========================================================================*/
 
344
static int th_out(str, len)
 
345
/*+++
 
346
.PURPOSE Output Routine to interpret the `\Help' Macros
 
347
.RETURNS 0      (must stop)
 
348
.REMARKS 
 
349
---*/
 
350
        char    *str;   /* IN: Action string, should start with H */
 
351
        int     len;    /* IN: Length of action string */
 
352
{
 
353
  return(0);            /* Must stop, should NEVER be called !!! */
 
354
}  
 
355
 
 
356
/*==========================================================================*/
 
357
static int next_help(str, len)
 
358
/*+++
 
359
.PURPOSE Locate next \Help
 
360
.RETURNS Offset found
 
361
.REMARKS Check if not in comment ...
 
362
---*/
 
363
        char    *str;   /* IN: Text in which locate \Help       */
 
364
        int     len;    /* IN: Length of str    */
 
365
{
 
366
        char    *b, *be, *bc;
 
367
        int     is_a_comment;
 
368
 
 
369
  b = str, be = b + len;
 
370
  while(b < be)
 
371
  {     b += oscindex(b, be-b, HELP_MACRO, sizeof(HELP_MACRO)-1);
 
372
        if (b >= be)    break;
 
373
                /* Check if it's not a comment... */
 
374
        is_a_comment = FALSE;
 
375
        for (bc = b; (bc > str) && (*bc != '\n'); bc--)
 
376
        {
 
377
                if ((*bc == '%') && (*(bc-1) != '\\'))  /* It's a comment */
 
378
                { is_a_comment = TRUE; break; }
 
379
        }
 
380
        if (is_a_comment)       b += sizeof(HELP_MACRO) -1;
 
381
        else                    break;
 
382
  }
 
383
  return(b - str);
 
384
}
 
385
 
 
386
/*==========================================================================
 
387
 *                      Help Merging
 
388
 *==========================================================================*/
 
389
static int which_help(str, len, topic)
 
390
/*+++
 
391
.PURPOSE interpret the next Help as (level+Text)
 
392
.RETURNS Offset found
 
393
.REMARKS The actions th_act are assumed to be in effect.
 
394
---*/
 
395
        char    *str;   /* IN: Text in which locate \Help       */
 
396
        int     len;    /* IN: Length of str    */
 
397
        char    *topic; /* OUT: Level + Topic, assumed size MAX_TOPIC+1 */
 
398
{
 
399
        char    *p, *pe;
 
400
 
 
401
  p = str; pe = p + len;
 
402
  *topic = 0;
 
403
  p += next_help(p, pe-p);
 
404
  if (p < pe) {
 
405
        tex_exec(htex, p, pe-p);
 
406
        *topic = level_found;
 
407
        strncopy(topic+1, MAX_TOPIC, htex->ap);
 
408
  }
 
409
  return(p - str);
 
410
}
 
411
 
 
412
static PIECE *MergeHelp(p1, q2)
 
413
/*+++
 
414
.PURPOSE Merge two loaded helps into a single index
 
415
.RETURNS The merged piece
 
416
.REMARKS Works properly only for Sorted Indexed Helps. p1 and q2 are freed.
 
417
---*/
 
418
        PIECE   *p1;    /* IN: First Help tree  */
 
419
        PIECE   *q2;    /* IN: Second Help tree */
 
420
{
 
421
        char    *b1, *b2, *c1, *c2;
 
422
        char    top1[MAX_TOPIC+1], top2[MAX_TOPIC+1];
 
423
        int     i;
 
424
        int     (*old_act)(), (*old_out)();
 
425
        static  PIECE   p;
 
426
 
 
427
        /* Allocate first the new Piece */
 
428
 
 
429
  old_act = htex->action, old_out = htex->output;
 
430
  htex->action = th_act,   htex->output = th_out;   
 
431
  i = (p1->end - p1->start) + (q2->end - q2->start);
 
432
  p.start = MEM_GET(char, i);   p.end = p.start;
 
433
  
 
434
  b1 = c1 = p1->start;  b2 = c2 = q2->start;
 
435
  c2 += which_help(c2, q2->end - c2, top2);     if (top2[0] != '0')     FINISH;
 
436
  c2++;
 
437
  c2 += which_help(c2, q2->end - c2, top2);     if (top2[0] != '1')     FINISH;
 
438
  b2 = c2;              /* Ignore 2nd help tree until first topic */
 
439
  c1 += which_help(c1, p1->end - c1, top1);     if (top1[0] != '0')     FINISH;
 
440
  c1++;
 
441
  c1 += which_help(c1, p1->end - c1, top1);     if (top1[0] != '1')     FINISH;
 
442
  p.end += oscopy(p.end, b1, c1-b1);
 
443
  b1 = c1; 
 
444
  while ( (c1 < p1->end) && (c2 < q2->end)) {
 
445
        i = top2[0] - top1[0];
 
446
        if (i == 0) i = studiff(top1, top2);
 
447
        if (i <= 0) {   /* top1 comes first */
 
448
                ++c1;
 
449
                c1 += which_help(c1, p1->end - c1, top1);
 
450
                p.end += oscopy(p.end, b1, c1-b1);
 
451
                b1 = c1;
 
452
        }
 
453
        if (i >= 0) {   /* top2 comes first */
 
454
                ++c2;
 
455
                c2 += which_help(c2, q2->end - c2, top2);
 
456
                if (i)  p.end += oscopy(p.end, b2, c2-b2);
 
457
                b2 = c2;
 
458
        }
 
459
  }
 
460
 
 
461
  FIN:
 
462
  p.end += oscopy(p.end, b1, p1->end - b1);     /* Append rest  */
 
463
  p.end += oscopy(p.end, b2, q2->end - b2);     /* Append rest  */
 
464
  MEM_FREE(p1->start);  MEM_FREE(q2->start);
 
465
  htex->action = old_act,   htex->output = old_out;   
 
466
 
 
467
  return(&p);
 
468
}
 
469
 
 
470
/*==========================================================================
 
471
 *                      Reset anything at specified level
 
472
 *==========================================================================*/
 
473
static int Reset(lev)
 
474
/*+++
 
475
.PURPOSE Reset the list of subtopics to specified level:
 
476
        title and starting point of subtopics.
 
477
.RETURNS The level
 
478
.REMARKS 
 
479
---*/
 
480
        int     lev;    /* IN: The current level */
 
481
{
 
482
        char    *b;
 
483
        int     i;
 
484
        
 
485
                /* First, reset the Title in the List buffer */
 
486
 
 
487
  for (b = list->buf, i = 0; i <= lev; i++)
 
488
        b += oscloc(b, list->offset, ' ') + 1;
 
489
  list->offset = b - list->buf;
 
490
  list->used   = list->offset;
 
491
  
 
492
                /* Second, reset starting point of subtopic */
 
493
  
 
494
  i = lev+1;
 
495
  if (i <= 9)
 
496
  {     topics[i].piece = topics[lev].piece;
 
497
        topics[i].pos   = topics[lev].pos;
 
498
        topics[i].ltopic= 0;
 
499
  }
 
500
 
 
501
  return(lev);
 
502
}
 
503
 
 
504
/*==========================================================================
 
505
 *                      LocHelp
 
506
 *==========================================================================*/
 
507
static int LocHelp(t)
 
508
/*+++
 
509
.PURPOSE Locate the next `\Help' macro
 
510
.RETURNS Level (t->level) as a number / -1 if end found
 
511
.REMARKS On return, t->pos AND t->hpos point to the text starting with \Help
 
512
        The context is checked.
 
513
        If the index is not loaded, \HelpIndex is ignored.
 
514
---*/
 
515
        TOPIC   *t;     /* MOD: Starting search point */
 
516
{
 
517
        PIECE   *p;
 
518
        int     got, flag;
 
519
        int     (*old_act)(), (*old_out)();
 
520
        
 
521
  got = -1;
 
522
  t->got_topic = NULL_PTR(char);
 
523
  old_act = htex->action, old_out = htex->output;
 
524
  htex->action = th_act,   htex->output = th_out;   
 
525
 
 
526
 
 
527
  flag = 0;                     /* Indicates starting of a new piece */
 
528
  
 
529
  while(1)                      /* Loop over pieces */
 
530
  {     if (t->piece >= help.buf->used) FINISH;
 
531
        p = (PIECE *)(help.buf->buf + t->piece);
 
532
        if (flag)       t->pos = p->start;
 
533
        flag = 0;
 
534
        if (t->pos >= p->end)
 
535
        {       t->piece += sizeof(PIECE);
 
536
                flag = 1;
 
537
                continue;
 
538
        }
 
539
        t->pos += next_help(t->pos, p->end - t->pos);
 
540
        if (t->pos >= p->end)   continue;       /* Not found */
 
541
 
 
542
                /* Something starting with \Help found  
 
543
                 * Interpret with the TeX parser -- 
 
544
                 * but be sure it's not a comment!      */
 
545
 
 
546
#if 0
 
547
        for (st = t->pos; st > p->start; st--)
 
548
                if ( (*st == '\n') || (*st == '%'))     break;
 
549
 
 
550
        if (*st == '%')         /* It's a comment       */
 
551
                { t->pos += 1; continue; }
 
552
#endif
 
553
        level_found = '\0';
 
554
        tex_exec(htex, t->pos, p->end - t->pos);
 
555
        if (level_found)                break;  
 
556
        t->pos += 1;
 
557
  }
 
558
 
 
559
        /* Here if a \Help macro found: level is stored as level_found,
 
560
         * and the found topic / filename as htex->ap.
 
561
         */
 
562
 
 
563
  t->level = level_found;
 
564
  t->flag  = help_flag;
 
565
  t->hpos  = t->pos;
 
566
  t->got_topic = htex->ap;
 
567
  got = level_found - '0';
 
568
  
 
569
  FIN:
 
570
  htex->action = old_act,   htex->output = old_out;   
 
571
  return(got);
 
572
}
 
573
 
 
574
/*==========================================================================
 
575
 *                      Sorry (no help available...)
 
576
 *==========================================================================*/
 
577
static int Sorry(asked, exit_option)
 
578
/*+++
 
579
.PURPOSE Display the "Sorry" message ...
 
580
.RETURNS OK 
 
581
.REMARKS 
 
582
---*/
 
583
        char    *asked;         /* IN: What was asked for and not found */
 
584
        int     exit_option;    /* IN: 1 to log error, 0 to output on window */
 
585
{
 
586
        static char *sp[] = {"Sorry, no such", NULL_PTR(char)};
 
587
        int     i;
 
588
 
 
589
  if (exit_option)
 
590
        ERR_ED_STRING("Topic not found: ", asked);
 
591
  else
 
592
  {     sp[1] = help.title;
 
593
        ClearWindow(help.w[0]);
 
594
        SetAttr(help.w[0], _BOLD_|_BLINK_|_REVERSE_);
 
595
        for (i = 0; i < ITEMS(sp); i++)
 
596
                Put(help.w[0], sp[i]);
 
597
        SetAttr(help.w[0], _NORMAL_);
 
598
        WriteBinary(help.w[0], list->buf, list->offset);
 
599
        SetAttr(help.w[0], _UNDERSCORE_);
 
600
        Put(help.w[0], asked);
 
601
        SetAttr(help.w[0], _NORMAL_);
 
602
        Bell();
 
603
        RaiseWindow(help.w[0]);
 
604
  }
 
605
 
 
606
  return(OK);
 
607
}
 
608
 
 
609
/*==========================================================================
 
610
 *                      BadIndex
 
611
 *==========================================================================*/
 
612
static int BadIndex()
 
613
/*+++
 
614
.PURPOSE Display a message if index is too old. Execute the bad_index.
 
615
.RETURNS _BAD_INDEX_
 
616
.REMARKS Replace \HelpIndex by \HelpLoad and replace arg. 2,3,4 by blanks
 
617
---*/
 
618
{
 
619
        int     k;
 
620
 
 
621
  ERR_ED_STRING("File was modified: ", htex->ap);
 
622
 
 
623
  ClearWindow(help.w[0]);
 
624
  SetAttr(help.w[0], _BOLD_|_BLINK_|_REVERSE_);
 
625
  PutCentered(help.w[0], " Index Invalid ");
 
626
  SetAttr(help.w[0], _NORMAL_);
 
627
  RaiseWindow(help.w[0]);
 
628
  
 
629
        /* Modify \HelpIndex{0} to \HelpLoad{0} */
 
630
 
 
631
  topc.piece = 0;
 
632
  topc.pos = ((PIECE *)(help.buf->buf))->start;
 
633
  LocHelp(&topc);
 
634
  oscopy(topc.pos+5, "Load ", 5);
 
635
  topc.pos += 1 + oscloc(topc.pos, 200, '{');
 
636
  for (k=3; --k>=0; )
 
637
  {     topc.pos += oscloc(topc.pos, 200, '{');
 
638
        *(topc.pos) = ' ';
 
639
        oscfill(topc.pos, oscloc(topc.pos, 200, '{'), ' ');
 
640
  }
 
641
  
 
642
  if (help.bad_index)   oshcmd(help.bad_index, 
 
643
        NULL_PTR(char), NULL_PTR(char), NULL_PTR(char));
 
644
 
 
645
  return(_BAD_INDEX_);
 
646
}
 
647
 
 
648
/*==========================================================================
 
649
 *                      oFile
 
650
 *==========================================================================*/
 
651
static int oFile(filename)
 
652
/*+++
 
653
.PURPOSE Save filename in `filenames' buffer.
 
654
.RETURNS Position in `filenames' buffer where file name is saved.
 
655
.REMARKS Check if filname already exists. The default extension is added.
 
656
---*/
 
657
        char    *filename;      /* IN: File to save */
 
658
{
 
659
        int     l, o;
 
660
        char    *p, *complete_filename;
 
661
 
 
662
  complete_filename = NameFile(filename, default_ext);
 
663
  l = strlen(complete_filename) + 1;
 
664
  
 
665
  for (o=0; o < filenames->used; )
 
666
  {     p = filenames->buf + o;
 
667
        if (oscomp(p, complete_filename, l) == 0)       break;
 
668
        o += 1 + strlen(p);
 
669
  }
 
670
 
 
671
        /* If not yet existing, add in buffer   */
 
672
        
 
673
  if (o >= filenames->used)
 
674
  {     o = filenames->used;
 
675
        BUF_AppendItems(filenames, char, complete_filename, l);
 
676
  }
 
677
 
 
678
  return(o);
 
679
}
 
680
 
 
681
/*==========================================================================
 
682
 *                      load_file
 
683
 *==========================================================================*/
 
684
static int load_file(filename)
 
685
/*+++
 
686
.PURPOSE Load a file in a new allocated piece of memory.
 
687
        This piece is detailed in the static loaded_file.
 
688
.RETURNS --- OK (no remaining text)
 
689
        --- NOK (file not found)
 
690
.REMARKS Execute definitions in the loaded file, until the first \Help.
 
691
        Default extension is .tex
 
692
---*/
 
693
        char    *filename;      /* IN: File to load */
 
694
{
 
695
        char    *b, *fname;
 
696
        int     status, fid, lb;
 
697
        unsigned int l;
 
698
        long    fs;
 
699
        int     (*old_act)(), (*old_out)();
 
700
 
 
701
        /* Open first the File. If fails, return */
 
702
 
 
703
  status = NOK;
 
704
  fname = strsave(NameFile(filename, default_ext));
 
705
 
 
706
  fs = fi_size(fname);          /* Size of File */
 
707
 
 
708
  if_not(fid = fi_open(fname, READ|RECORD_MODE))
 
709
        FINISH;
 
710
 
 
711
  l  = fs;
 
712
  if (l == 0)   FINISH;
 
713
 
 
714
        /* Allocate memory to copy file */
 
715
        
 
716
  if_not ( b = MEM_GET(char, l))
 
717
        FINISH;
 
718
 
 
719
  loaded_file.start = b;
 
720
  loaded_file.end   = b + l;
 
721
        
 
722
        /* Read file until first \Help  */
 
723
  
 
724
  for (fs=0; fi_gets(fid, b, loaded_file.end - b) > 0; fs = fi_tell(fid))
 
725
  {     if (*b == '%')  continue;       /* Comment line...      */
 
726
        lb = strlen(b);
 
727
        if (*(b + oscindex(b, lb, HELP_MACRO, sizeof(HELP_MACRO)-1)))
 
728
                break;
 
729
        b += lb;
 
730
        *(b++) = '\n';
 
731
  }
 
732
  fi_close(fid);
 
733
                
 
734
        /* Execute the TeX definitions before the first \Help */
 
735
        
 
736
  old_act = htex->action, old_out = htex->output;
 
737
  htex->action = act0,   htex->output = act0;   
 
738
  TeX_Execute(htex, loaded_file.start, b - loaded_file.start);
 
739
  htex->action = old_act,   htex->output = old_out;   
 
740
  
 
741
        /* Load the Remaining part of the File */
 
742
 
 
743
  l = (loaded_file.end - loaded_file.start) - fs;
 
744
  MEM_FREE(loaded_file.start);
 
745
  b = MEM_GET(char, l);
 
746
  loaded_file.start = b;
 
747
  loaded_file.end   = b + fi_load(fname, fs, b, l);
 
748
 
 
749
  status = OK;
 
750
  
 
751
  FIN:
 
752
  strfree(fname);               /* Release the memory */
 
753
  return(status);
 
754
}
 
755
 
 
756
/*==========================================================================
 
757
 *                      load_help
 
758
 *==========================================================================*/
 
759
static int load_help(filename, start_level)
 
760
/*+++
 
761
.PURPOSE Load a new help file (triggered by \HelpLoad).
 
762
        It modifies the levels of the loaded file.
 
763
.RETURNS OK  / NOK (something failed)
 
764
.REMARKS 
 
765
---*/
 
766
        char    *filename;      /* IN: File to load */
 
767
        char    start_level;    /* IN: Lowest level     */
 
768
{
 
769
        int     status, i;
 
770
        char    *b;
 
771
 
 
772
  status = NOK;
 
773
  if_not(load_file(filename))   FINISH;
 
774
 
 
775
  status = OK;
 
776
  if (start_level <= '0')       FINISH;
 
777
  
 
778
  b = loaded_file.start; 
 
779
  i = start_level - '0';
 
780
  
 
781
  while (b < loaded_file.end)
 
782
  {     b += next_help(b, loaded_file.end - b);
 
783
        b += oscspan((unsigned char *)b, loaded_file.end - b, _ALPHA_|_PUNCT_|_SPACE_,
 
784
                main_ascii);            /* Skip until digit */
 
785
        if (b >= loaded_file.end)       break;
 
786
        *b += i;                /* Modify the Level     */
 
787
  }     
 
788
 
 
789
  FIN:
 
790
  return(status);
 
791
}
 
792
 
 
793
/*==========================================================================
 
794
 *                      help_load
 
795
 *==========================================================================*/
 
796
static int help_load(t)
 
797
/*+++
 
798
.PURPOSE Treats the `\HelpLoad{lev}{filename}' macro
 
799
.RETURNS OK  / NOK (something failed)
 
800
.REMARKS Filename is given as t->got_topic, level as t->level
 
801
---*/
 
802
        TOPIC   *t;     /* IN: The current topic        */
 
803
{
 
804
        PIECE   *p;
 
805
        char    *b;
 
806
        int     status, l;
 
807
        
 
808
        /* 1. The filename is in t->got_topic; load it */
 
809
 
 
810
  status = NOK;
 
811
 
 
812
  b = t->pos + tex_tell();      /* Position just following the \Help */
 
813
  t->flag = '.';                        /* File is now loaded           */
 
814
 
 
815
  if_not(load_help(t->got_topic, t->level))     FINISH;
 
816
  
 
817
        /* 2. Allocate two new PIECE items in help:
 
818
         *      - 1 for the new file
 
819
         *      - 1 for the second part following the \HelpLoad
 
820
         * These items must be located where we are.
 
821
         */
 
822
         
 
823
  help.buf->offset = t->piece;
 
824
  l = help.buf->used - help.buf->offset;        /* Length of 2nd part */
 
825
  
 
826
  if_not(BUF_AllocateItems(help.buf, PIECE, 2)) FINISH;
 
827
 
 
828
  p = BUF_ItemPosition(help.buf, PIECE);
 
829
  oscopy((char *)(p+2), (char *)p, l);          /* Duplicates current piece */
 
830
 
 
831
        /* 3. Modify the current length (stops just before \HelpLoad    */
 
832
  
 
833
  p->end = t->pos;
 
834
  
 
835
        /* 4. Insert the loaded file    */
 
836
        
 
837
  *++p = loaded_file;
 
838
  
 
839
        /* 5. Modify the 2nd part (starts just after \HelpLoad  */
 
840
 
 
841
  ++p;
 
842
  p->start = b;
 
843
 
 
844
  status = OK;
 
845
  
 
846
  FIN:
 
847
  return(status);
 
848
}
 
849
 
 
850
 
 
851
/*==========================================================================
 
852
 *                      LocTop
 
853
 *==========================================================================*/
 
854
static int LocTop(lev, opt, optl)
 
855
/*+++
 
856
.PURPOSE Locate the topic of specified level
 
857
.RETURNS Lev if found - another number otherwise
 
858
.REMARKS Comparison is case insensitive. On return, the current text
 
859
        starts just after the \Help.
 
860
---*/
 
861
        int     lev;    /* IN: Level to look for        */
 
862
        int     opt;    /* IN: 1 to add topic in title / 2 for Explanation */
 
863
        int     optl;   /* IN: 1 to locate file with text / 0 otherwise */
 
864
{
 
865
        int     i;
 
866
 
 
867
  for (topc = topics[lev]; (i = LocHelp(&topc)) >= lev; topc.pos += 1)
 
868
  {     if (i > lev)    continue;
 
869
                /* Check if a file was found. If yes, load it   */
 
870
        if (topc.flag == '@')
 
871
        {       help_load(&topc);
 
872
                continue;
 
873
        }
 
874
        if (osccomp(topc.topic, topc.got_topic, topc.ltopic) == 0)
 
875
                break;          /* Topic is found */
 
876
  }
 
877
 
 
878
  if (i != lev)         return(i);      /* Not Found    */
 
879
  
 
880
  if (opt & 2)  get_tit3();
 
881
  if (opt & 1)  {               /* Modify the title     */
 
882
        list->used = list->offset;
 
883
        BUF_AppendString(list, topc.got_topic);
 
884
        BUF_AppendItem(list, char, &blank);
 
885
        list->offset = list->used ;
 
886
  }
 
887
 
 
888
  if ((topc.flag == ':') && (optl))     /* From Index: Load Parameters  */
 
889
  {     tex_getparm(6); topc.fpos  = atol(htex->ap);  /*  Start of file */
 
890
        tex_getparm(7); topc.ltext = atoi(htex->ap);  /* Length in file */
 
891
        tex_getparm(5); topc.ofile = oFile(htex->ap); /* Filename       */
 
892
  }
 
893
 
 
894
  topc.pos += tex_tell();       /* Position after the \Help macro       */
 
895
  topics[lev] = topc;           /* Copy found topic     */
 
896
 
 
897
  return(lev);
 
898
}
 
899
 
 
900
/*==========================================================================
 
901
 *                      GetSubTop
 
902
 *==========================================================================*/
 
903
static int GetSubTop(lev)
 
904
/*+++
 
905
.PURPOSE Locate the subtopics of specified level
 
906
.RETURNS Number of subtopics
 
907
.REMARKS 
 
908
---*/
 
909
        int     lev;    /* IN: Level of Topic   */
 
910
{
 
911
        int     i, n, len;
 
912
        static  char ed[] = "\\CheckCols{00}\05\01";
 
913
 
 
914
  Reset(lev);
 
915
  
 
916
  BUF_AppendString(list,"\\vfill\n\\Rule\n");
 
917
  i = lev+1;
 
918
  
 
919
  for (n = 0; LocTop(i, 0, 0) == i; n++)
 
920
  {     len = strlen(topics[i].got_topic);
 
921
        ed[11] = '0' + len/10;
 
922
        ed[12] = '0' + len%10;
 
923
        BUF_AppendItems(list, char, ed, sizeof(ed)-1);
 
924
        BUF_AppendItems(list, char, topics[i].got_topic, len);
 
925
        BUF_AppendItems(list, char, "\05\02 \\tab", 7);
 
926
  }
 
927
 
 
928
  if (n == 0)   list->used = list->offset;      /* No subtopics */
 
929
  else          BUF_AppendItems(list, char, "\n\\SkipLine", 10);
 
930
 
 
931
  return(n);
 
932
}
 
933
  
 
934
/*==========================================================================
 
935
 *                      Prompt
 
936
 *==========================================================================*/
 
937
 
 
938
static WINDOW *CreateHelpWindow()
 
939
/*+++
 
940
.PURPOSE Create the customized help window
 
941
.RETURNS The window created
 
942
.REMARKS 
 
943
---*/
 
944
{
 
945
        WINDOW  *helpw;
 
946
#if 0
 
947
        static  char help_1[] = "Answer by non-ambiguous (sub)topic(s)\
 
948
 separated with blanks, or the keys:\n\\SkipLine\n\\begin{table}{c p}{3}\
 
949
{\\bf?}&to redisplay previous topic\\\\\
 
950
{\\bf\\b}&to list a summary\\\\\
 
951
{\\bf Ret}&to return to previous topic\\\\ ";
 
952
        static  char help_2[] = "{\\bf \\^A} & to Exit\\\\ ";
 
953
        static  char help_3[] = "\
 
954
\\end{table}\n\\SkipLine\nTopic names are {\\Vu case insensitive}.";
 
955
        static  char *help_text[] = { 
 
956
                help_1, help_1+sizeof(help_1)-1,
 
957
                help_2, help_2+sizeof(help_2)-1,
 
958
                help_3, help_3+sizeof(help_3)-1
 
959
                };
 
960
 
 
961
                        /* Create Help Window */
 
962
  help_2[7] = '@' + GetControl(TW_cc_EOF);
 
963
  if (helpw = OpenWindow("Help Topics", 0, -29, -18, 29, _REVERSE_,
 
964
        _TITLE_|_BORDER_|_BORDER2_|_DISPLAY_, 0))
 
965
        DisplayArray(helpw, help_text, ITEMS(help_text)/2);
 
966
#else
 
967
        static char help_text[] = "\
 
968
 Answer by non-ambiguous (sub)topics\n\
 
969
 separated with blanks, or the keys\n\n\
 
970
  \017^\04\016 to Exit\n\
 
971
 \017Ret\016 to return to previous topic\n\
 
972
   \017\\\016 to list a Summary\n\
 
973
   \017?\016 to redisplay previous topic\n\
 
974
  \017^B\016 to redisplay previous page\n\
 
975
   \017.\016 to display one more line\n\n\
 
976
 Topic names are \017case insensitive\016";
 
977
 
 
978
  help_text[strloc(help_text, '\04')] = '@' | GetControl (TW_cc_EOF );
 
979
  helpw = AdjustedWindow("Help on Help", help_text, 
 
980
        _REVERSE_, _BORDER_|_TITLE_, _UPRIGHT_);
 
981
#endif
 
982
 
 
983
  return(helpw);
 
984
}
 
985
 
 
986
static int Prompt1(opt)
 
987
/*+++
 
988
.PURPOSE Prompt for Continuation
 
989
.RETURNS -1 to stop / _SUMMARY_ to list the Summary (triggered by  \) /
 
990
                _REDISPLAY_ to redisplay the parent topic /
 
991
                _PROMPT_ when just Return was entered /
 
992
                OK if a subtopic was typed in
 
993
.REMARKS 
 
994
---*/
 
995
        int     opt;    /* IN: 1 if Bottom Reached  / 2 for Exit with Q */
 
996
{
 
997
        int     status, at_bottom, old_pos;
 
998
        static  char specials[] = " \02\04\06\025.\r?\\"; /* Those stop input */
 
999
 
 
1000
                        /* Special Keys are ^B ^D ^F ^U */
 
1001
  at_bottom = opt & 1;
 
1002
  status = 0;
 
1003
  old_pos = GetPosition(help.w[2]);
 
1004
  while (status == 0) {
 
1005
        SetPosition(help.w[2], old_pos);        
 
1006
        ClearRight(help.w[2]);
 
1007
        if (opt & 2) {
 
1008
                status = GetKey1(help.w[2], reply, specials);
 
1009
                if (status > 0) status = 0;
 
1010
        }
 
1011
        else    status = Gets1(help.w[2], reply, sizeof(reply), specials);
 
1012
        if ((status == OK) && (reply[0] == EOS))
 
1013
                status = 0, reply[0] = ' ';
 
1014
        if (status == 0)  switch(reply[0])   { 
 
1015
          case '\\':    status = _SUMMARY_;     break;
 
1016
          case '?':     status = _REDISPLAY_;   break;
 
1017
          case '\r':  case EOS:
 
1018
                if (at_bottom)  status = _PROMPT_;
 
1019
                else            reply[0] = ' '; break;
 
1020
        }
 
1021
        if (status)     continue;
 
1022
        status = MoreDoc(TheDoc, reply[0]);
 
1023
        at_bottom = atLastDocPage(TheDoc);
 
1024
        if (status == NOK)      Bell();
 
1025
        if (status == OK)       status = 0;
 
1026
  }
 
1027
 
 
1028
  FIN:
 
1029
  ClearWindow(help.w[2]);
 
1030
  return(status == 0 ? OK : status);
 
1031
}
 
1032
 
 
1033
static int Prompt(lev)
 
1034
/*+++
 
1035
.PURPOSE Inquire for a Topic
 
1036
.RETURNS -1 to stop / _SUMMARY_ to list the Summary (triggered by  \),
 
1037
                _REDISPLAY_ to redisplay the parent topic.
 
1038
.REMARKS A special Help window is used, in case of Control-K
 
1039
---*/
 
1040
        int     lev;    /* IN: Level / -1 for Continuation      */
 
1041
{
 
1042
        int     status;
 
1043
 
 
1044
  RaiseWindow(help.w[2]);
 
1045
  ActiveWindow(help.w[2]);
 
1046
  SetAttr(help.w[2], _REVERSE_);
 
1047
 
 
1048
  if (lev > 0)  
 
1049
  {     WriteBinary(help.w[2], list->buf, list->offset);
 
1050
        Put(help.w[2], "Subtopic ? ");
 
1051
  }
 
1052
  else  Put(help.w[2], " Topic ? ");
 
1053
 
 
1054
  SetAttr(help.w[2], _NORMAL_);
 
1055
  WriteBinary(help.w[2], &blank, 1);
 
1056
  status = Prompt1(1);
 
1057
 
 
1058
  return(status);
 
1059
}
 
1060
 
 
1061
static int PromptKey(opt)
 
1062
/*+++
 
1063
.PURPOSE Prompt for Continuation
 
1064
.RETURNS -1 to stop / _SUMMARY_ to list the Summary (triggered by  \),
 
1065
                _REDISPLAY_ to redisplay the parent topic.
 
1066
.REMARKS 
 
1067
---*/
 
1068
        int     opt;    /* IN: non-zero to display the ?        */
 
1069
{
 
1070
        int     status, opt1;
 
1071
 
 
1072
  RaiseWindow(help.w[2]);
 
1073
  ActiveWindow(help.w[2]);
 
1074
  SetAttr(help.w[2], _REVERSE_);
 
1075
  Put(help.w[2], " <Return> to continue");
 
1076
  Put(help.w[2], ", ");
 
1077
  SetAttr(help.w[2], _REVERSE_|_BOLD_);
 
1078
  opt1 = 0;             /* Option for Prompt1 */
 
1079
  if (opt) {
 
1080
        Put(help.w[2], "?");
 
1081
        SetAttr(help.w[2], _REVERSE_);
 
1082
        Put(help.w[2], " for list of subtopics");
 
1083
  } 
 
1084
  else {
 
1085
        Put(help.w[2], "q");
 
1086
        SetAttr(help.w[2], _REVERSE_);
 
1087
        Put(help.w[2], " to quit");
 
1088
        opt1 = 2;       /* Allow to Exit with Q */
 
1089
  }
 
1090
 
 
1091
  Put(help.w[2], " ");
 
1092
  SetAttr(help.w[2], _NORMAL_);
 
1093
  status = Prompt1(opt1);
 
1094
 
 
1095
  return(status);
 
1096
}
 
1097
 
 
1098
/*==========================================================================
 
1099
 *                      GetSummary
 
1100
 *==========================================================================*/
 
1101
static int GetSummary(lev)
 
1102
/*+++
 
1103
.PURPOSE Prepare complete list of all subtopics
 
1104
.RETURNS OK
 
1105
.REMARKS 
 
1106
---*/
 
1107
        int     lev;    /* IN: Level of Topic   */
 
1108
{
 
1109
        int     i, l, l3, m;
 
1110
        char    *b, buf[80];
 
1111
 
 
1112
  Reset(lev);
 
1113
  topc = topics[lev];
 
1114
  BUF_AppendString(list, "\\begin{table}{ l p }{$$}");
 
1115
  m = 0;                /* Size of first column */
 
1116
  
 
1117
  while ( (i = LocHelp(&topc)) > lev)
 
1118
  {     if (topc.flag == '@')
 
1119
        {       help_load(&topc);
 
1120
                continue;
 
1121
        }
 
1122
        l = (i-lev-1)*4;        /* Length of first column       */
 
1123
        b = buf + oscfill(buf, l, '~');
 
1124
        *(b++) = '{';
 
1125
        if (l == 0)     b += strcopy(b, "\\bf");
 
1126
        *(b++) = '\05'; *(b++) = '\01'; /* begin{verbatim} */
 
1127
        BUF_AppendItems(list, char, buf, b-buf);
 
1128
        BUF_AppendString(list, topc.got_topic);
 
1129
        BUF_AppendItems(list, char, "\05\02}&", 4);
 
1130
        l += 1 + strlen(topc.got_topic);
 
1131
        m = MAX(m, l);
 
1132
        l3 = get_tit3();                /* The short explanation */
 
1133
        if (l3 > 0)     BUF_AppendItems(list, char, tit3, l3);
 
1134
        BUF_AppendItems(list, char, "\\\\", sizeof("\\\\")-1);
 
1135
        topc.pos += 1;
 
1136
  }
 
1137
 
 
1138
  BUF_AppendString(list, "\n\\end{table}");
 
1139
  b  = list->buf + list->offset;
 
1140
  b += oscloc(b, 80, '$');
 
1141
  *(b++) = '0' + m/10, *(b++) = '0' + m%10;
 
1142
 
 
1143
  return(OK);
 
1144
}
 
1145
  
 
1146
/*==========================================================================
 
1147
 *                      EdTop
 
1148
 *==========================================================================*/
 
1149
static int EdTop(lev)
 
1150
/*+++
 
1151
.PURPOSE Edit the found Topic and list of Subtopics
 
1152
.RETURNS _EOF_ / _INTERRUPT_ / _PROMPT_ / OK (something was typed) / 
 
1153
         _REDISPLAY_ (no subtopic, and ? was typed) / _SUMMARY_
 
1154
.REMARKS The static subtopics contains in return the number of found subtopics.
 
1155
        The relevant file is loaded if help is indexed.
 
1156
---*/
 
1157
        int     lev;    /* IN: Level of Topic   */
 
1158
{
 
1159
        PIECE   *p;
 
1160
        static  char *as[4];
 
1161
        int     status;
 
1162
 
 
1163
        /* Locate Text  */
 
1164
 
 
1165
  p = (PIECE *)(help.buf->buf + topics[lev].piece);
 
1166
 
 
1167
        /* If help is indexed, load the file    */
 
1168
 
 
1169
  if (topics[lev].flag == ':')
 
1170
  {
 
1171
        if ((loaded) && (loaded->fpos == topics[lev].fpos)
 
1172
                     && (loaded->ofile== topics[lev].ofile))
 
1173
                ;                       /* Topic already loaded */
 
1174
        else
 
1175
        {       loaded = (LOADED *)mm_expand(loaded, sizeof(LOADED)+
 
1176
                        topics[lev].ltext);
 
1177
                loaded->ofile = topics[lev].ofile;
 
1178
                if (fi_date(filenames->buf + loaded->ofile) > help.date)  
 
1179
                        return(BadIndex());     /* File was modified... */
 
1180
                loaded->fpos  = topics[lev].fpos;
 
1181
                loaded->ltext = topics[lev].ltext;
 
1182
                as[0] = loaded->text;
 
1183
                loaded->ltext = fi_load(filenames->buf + loaded->ofile,
 
1184
                                        loaded->fpos,   /* Pos in file  */
 
1185
                                        as[0], loaded->ltext);
 
1186
                as[1] = as[0] + loaded->ltext;
 
1187
        }
 
1188
  }
 
1189
  else  as[0] = topics[lev].pos, as[1] = p->end;
 
1190
 
 
1191
        /* Edit the title in the help.w[0] window */
 
1192
 
 
1193
  ClearWindow(help.w[0]);
 
1194
  SetAttr(help.w[0], _BOLD_),
 
1195
  Put(help.w[0],help.title),
 
1196
  Put(help.w[0],": "),
 
1197
  SetAttr(help.w[0], _NORMAL_);
 
1198
 
 
1199
  if (help.flags & 2)           /* Use Short Title */
 
1200
        ShowString(help.w[0], tit3);
 
1201
  else  WriteBinary(help.w[0], list->buf, list->offset);
 
1202
  TouchWindow(help.w[0]);       /* Display the Title */
 
1203
 
 
1204
        /* Locate the Subtopics */
 
1205
 
 
1206
  subtopics = GetSubTop(lev);
 
1207
 
 
1208
        /* Now, edit the text + list of subtopics       */
 
1209
 
 
1210
  as[2] = list->buf + list->offset, as[3] = list->buf + list->used;
 
1211
  
 
1212
  status = myOpenDocArray(as, 2);
 
1213
  while(status == 0) {
 
1214
        status = PromptKey(subtopics);
 
1215
        if (status < 0)         FINISH;
 
1216
        switch(status) {
 
1217
          case _REDISPLAY_ :    /* Display subtopics */
 
1218
                if (subtopics == 0)
 
1219
                        { Bell(); FINISH;}
 
1220
                status = myOpenDocText(as[2], as[3] - as[2]);
 
1221
                break;
 
1222
          case _PROMPT_ :       /* Display Continuation */
 
1223
                break;
 
1224
          case _SUMMARY_ :      
 
1225
                status = _SUMMARY_;
 
1226
                FINISH;
 
1227
          default:              /* A text was typed ahead */
 
1228
                status = OK;
 
1229
                FINISH;
 
1230
        }
 
1231
        RaiseWindow(help.w[1]);
 
1232
  }
 
1233
  status = _PROMPT_;
 
1234
 
 
1235
  FIN:
 
1236
  return(status);
 
1237
}
 
1238
  
 
1239
/*==========================================================================
 
1240
 *                      EdSummary
 
1241
 *==========================================================================*/
 
1242
static int EdSummary(lev)
 
1243
/*+++
 
1244
.PURPOSE Display the Summary
 
1245
.RETURNS _EOF_ / _INTERRUPT_ / _PROMPT_ / OK (something was typed) / 
 
1246
        _REDISPLAY_ (no subtopic, and ? was typed)
 
1247
.REMARKS 
 
1248
---*/
 
1249
        int     lev;    /* IN: Level of Topic   */
 
1250
{
 
1251
        int     status;
 
1252
 
 
1253
        /* First, edit the title in the help.w[0] window */
 
1254
 
 
1255
  ClearWindow(help.w[0]);
 
1256
  SetAttr(help.w[0], _BOLD_);
 
1257
  Put(help.w[0], help.title);
 
1258
  Put(help.w[0], " Summary:");
 
1259
  SetAttr(help.w[0], _NORMAL_);
 
1260
  WriteBinary(help.w[0], list->buf, list->offset);
 
1261
  TouchWindow(help.w[0]);       /* Display the Title */
 
1262
 
 
1263
  status = myOpenDocText(list->buf + list->offset, list->used - list->offset);
 
1264
 
 
1265
  while(status == 0) {
 
1266
        status = PromptKey(1);
 
1267
        if (status < 0)         FINISH;
 
1268
        switch(status) {
 
1269
          case _REDISPLAY_ :    /* Redisplay subtopics */
 
1270
                GetSubTop(lev);
 
1271
                status = myOpenDocText(list->buf + list->offset,
 
1272
                        list->used - list->offset);
 
1273
                break;
 
1274
          case _PROMPT_ :       /* Terminated (at bottom) */
 
1275
                break;
 
1276
          case _SUMMARY_ :      
 
1277
                MoreDoc(TheDoc, 'g');   /* Display Top  */
 
1278
                status = 0;
 
1279
                break;
 
1280
          default:              /* A text was typed ahead */
 
1281
                status = OK;
 
1282
                FINISH;
 
1283
        }
 
1284
        RaiseWindow(help.w[1]);
 
1285
  }
 
1286
  status = _PROMPT_;
 
1287
 
 
1288
  FIN:
 
1289
  return(status);
 
1290
}
 
1291
  
 
1292
/***************************************************************
 
1293
 *              P U B L I C     R O U T I N E S
 
1294
 ****************************************************************/
 
1295
 
 
1296
/*==========================================================================
 
1297
 *                      th_topsep
 
1298
 *==========================================================================*/
 
1299
int th_topsep(list)
 
1300
/*+++
 
1301
.PURPOSE Define the list of topic separator characters
 
1302
.RETURNS OK
 
1303
.REMARKS Default is blank.
 
1304
---*/
 
1305
        char *list;     /* IN: Available characters as separators */
 
1306
{
 
1307
  strset(sep_table, list);
 
1308
  sep_top = list;               /* Tells it's initialized */
 
1309
  return(OK);
 
1310
}       
 
1311
 
 
1312
/*==========================================================================
 
1313
 *                      th_init
 
1314
 *==========================================================================*/
 
1315
TWHELP *th_init(filename, wt, w, wd)
 
1316
/*+++
 
1317
.PURPOSE Initialize Help procedure: definition of \Help macro,
 
1318
        set the three windows.
 
1319
.RETURNS --- OK 
 
1320
        --- NOK (error of file doesn't exist)
 
1321
.REMARKS Default extension for filename = .tex
 
1322
---*/
 
1323
        char   *filename;       /* IN: Name of help file */
 
1324
        WINDOW *wt;     /* IN: Window for Help titles   */
 
1325
        WINDOW *w;      /* IN: Window for Help display  */
 
1326
        WINDOW *wd;     /* IN: Window for dialogue      */
 
1327
{
 
1328
        TWHELP  *h;
 
1329
        int     (*old_act)(), (*old_out)();
 
1330
        short int screen_size[2];
 
1331
        static char definitions[] = 
 
1332
                "\\def\\Help#4{\\action{H.}}\\def\\HelpLoad#4{\\action{H@}}\
 
1333
\\def\\HelpIndex#7{\\action{H:}}\\def\\fromHelpFiles#1{}";
 
1334
 
 
1335
  ENTER("*th_init");
 
1336
 
 
1337
  TRACE_ED_STRING("Help file:", filename);
 
1338
 
 
1339
        /* Load the definitions */
 
1340
        
 
1341
  if_not(htex)
 
1342
  {     htex = tx_tex();
 
1343
 
 
1344
        if (!sep_top)   th_topsep(" ");         /* Topic Separators */
 
1345
        
 
1346
        old_act = htex->action, old_out = htex->output;
 
1347
        htex->action = act0,   htex->output = act0;   
 
1348
        TeX_Execute(htex, definitions, sizeof(definitions)-1);
 
1349
        htex->action = old_act,   htex->output = old_out;   
 
1350
        list = BUF_Open(char, 256, 128);
 
1351
        filenames = BUF_Open(char, 0, 128);
 
1352
        tit3 = strsave("");
 
1353
  }
 
1354
 
 
1355
        /* Initialize the TWHELP structure */
 
1356
 
 
1357
  h = NULL_PTR(TWHELP);
 
1358
  help.w[0] = wt;
 
1359
  help.w[1] = w;
 
1360
  help.w[2] = wd;
 
1361
  help.buf  = NULL_PTR(BUFFER);
 
1362
  help.date = FileDate(filename);
 
1363
  help.title    = default_title;
 
1364
  help.context  = NULL_PTR(char);
 
1365
  help.bad_index = NULL_PTR(char);
 
1366
  help.indexed  = 0;
 
1367
 
 
1368
        /* Load Help file       */
 
1369
 
 
1370
  if_not (load_file(filename))  FINISH;
 
1371
 
 
1372
  if_not(help.buf = BUF_Open(PIECE, 1, 16))     /* Allocate buffer */
 
1373
        FINISH;
 
1374
        
 
1375
 
 
1376
        /* Check if Help is Indexed     */
 
1377
  if (oscomp(loaded_file.start, HELP_INDEX, sizeof(HELP_INDEX)-1) == 0)
 
1378
        help.indexed = 1;
 
1379
 
 
1380
  BUF_AppendItem(help.buf, PIECE, &loaded_file);
 
1381
                                        /* Add this piece to the buffer */
 
1382
 
 
1383
 
 
1384
        /* If windows are NULL, use defaults    */
 
1385
 
 
1386
  ScreenSize(screen_size);
 
1387
 
 
1388
  if_not(help.w[1])             /* No main Window for Help Display      */
 
1389
  {     help.w[1] = OpenWindow("$help", 0, 0, screen_size[0]-2, 0, 
 
1390
                _NORMAL_, _DISPLAY_, 0);
 
1391
        CursorTo(help.w[1], 1, 0);
 
1392
        SetAttr(help.w[1], _GRAPHICS_);
 
1393
        Fill(help.w[1], RuleChar(_HORIZONTAL_), screen_size[1]);
 
1394
        SetAttr(help.w[1], _NORMAL_);
 
1395
        help.w[0] = OpenSubWindow(help.w[1], ".help", 0, 0, 1, 0, 
 
1396
                _NORMAL_, _DISPLAY_, 0);        /* Title of Help Display */
 
1397
        help.w[1] = OpenSubWindow(help.w[1], "=help", 2, 0, 0, 0, 
 
1398
                _NORMAL_, _DISPLAY_, 0);
 
1399
  }
 
1400
 
 
1401
 
 
1402
  if_not(help.w[2])             /* No Dialogue Window for Help Display  */
 
1403
        help.w[2] = OpenWindow("?help", -2, 0, 2, 0, _NORMAL_, 0, 5);
 
1404
 
 
1405
  h = MEM_GET(TWHELP, 1);
 
1406
  if (h)        *h = help;
 
1407
 
 
1408
  FIN:
 
1409
  EXIT_PTR(TWHELP, h);
 
1410
}
 
1411
 
 
1412
int th_merge(help, filename)
 
1413
/*+++
 
1414
.PURPOSE Merge a Help with another one. The help must just have been
 
1415
        opened, and the two help files MUST BE INDEXED.
 
1416
.RETURNS --- OK / NOK
 
1417
.REMARKS Default extension for filename = .tex
 
1418
---*/
 
1419
        TWHELP  *help;          /* MOD: Main Help       */
 
1420
        char   *filename;       /* IN: Name of help file */
 
1421
{
 
1422
        int     status;
 
1423
        BUFFER  *b;
 
1424
        PIECE   *p;
 
1425
 
 
1426
  ENTER("th_merge");
 
1427
 
 
1428
  status = NOK;
 
1429
  if_not (help->indexed)        { ERROR("Help not Indexed"); FINISH; }
 
1430
  b = help->buf;
 
1431
  if (b->used != sizeof(PIECE)) { ERROR("Help was used..."); FINISH; }
 
1432
 
 
1433
  if_not((load_file(filename))) FINISH;
 
1434
 
 
1435
  if ((p = MergeHelp((PIECE *)(b->buf)), &loaded_file)) {
 
1436
        help->date = oshtime(); /* Be sure no Bad Index Error */
 
1437
        BUF_Clear(b);
 
1438
        BUF_AppendItem(b, PIECE, p);
 
1439
        status = OK;
 
1440
  }
 
1441
 
 
1442
  FIN:
 
1443
  EXIT(status);
 
1444
}
 
1445
 
 
1446
/*==========================================================================
 
1447
 *                      th_set
 
1448
 *==========================================================================*/
 
1449
char *th_set(helpin, context, opt)
 
1450
/*+++
 
1451
.PURPOSE Defines the Help Context / Title / What to do if index too old
 
1452
.RETURNS The old Context.
 
1453
.REMARKS Only address is kept... Use therefore e.g. strsave before calling...
 
1454
---*/
 
1455
        TWHELP  *helpin;        /* IN: The loaded Help  */
 
1456
        char    *context;       /* IN: Context */
 
1457
        int     opt;            /* IN: 0 for Title / 1 for Context */
 
1458
{
 
1459
        char    *old_context, **aa;
 
1460
 
 
1461
  ENTER("*th_set");
 
1462
 
 
1463
        /* Copy context to a new piece of memory */
 
1464
 
 
1465
  old_context = NULL_PTR(char);
 
1466
  
 
1467
  switch(opt)
 
1468
  { case 0: case 1: case 2:     aa = &(helpin->title);
 
1469
        break;
 
1470
    default:    ERR_ED_I("Bad option: ", opt);
 
1471
        FINISH;
 
1472
  }
 
1473
 
 
1474
  old_context = aa[opt];
 
1475
 
 
1476
  aa[opt] = context;
 
1477
  
 
1478
  FIN:
 
1479
  EXITp(old_context);
 
1480
}
 
1481
  
 
1482
int th_oset(helpin, mask, opt)
 
1483
/*+++
 
1484
.PURPOSE Define the Option Context
 
1485
.RETURNS The old Option Context.
 
1486
---*/
 
1487
        TWHELP  *helpin;        /* IN: The loaded Help  */
 
1488
        int     mask;           /* IN: Which option     */
 
1489
        int     opt;            /* IN: 0 for Clear / 1 for Set */
 
1490
{
 
1491
        int     old_option;
 
1492
 
 
1493
  old_option = helpin->flags & mask;
 
1494
  if (opt)
 
1495
        helpin->flags |= mask;
 
1496
  else  helpin->flags &= ~mask;
 
1497
 
 
1498
  return(old_option);
 
1499
}
 
1500
 
 
1501
/*==========================================================================
 
1502
 *                      th_help
 
1503
 *==========================================================================*/
 
1504
int th_help(helpin, topic, exit_option)
 
1505
/*+++
 
1506
.PURPOSE Display help on `topic'
 
1507
.RETURNS OK / NOK (error reported) / EOF (the user typed EOF) / -3 (Bad Index)
 
1508
.REMARKS 
 
1509
---*/
 
1510
        TWHELP  *helpin;        /* IN: The loaded Help  */
 
1511
        char    *topic; /* IN: Topics (separated by blanks) to display */
 
1512
        int     exit_option;    /* IN: non-zero to exit immediately after \
 
1513
                                        display, -1 for locate only */
 
1514
{
 
1515
        char *b, x;
 
1516
        int level, level_step, i, status;
 
1517
        WINDOW  *old_helpw;
 
1518
 
 
1519
  ENTER("th_help");
 
1520
 
 
1521
  strfree(located_help), located_help = (char *)0;
 
1522
  if (topic)
 
1523
  {     TRACE_ED_STRING("Topic: ", topic);
 
1524
        i = strlen(topic);
 
1525
        i = MIN(i, sizeof(reply)-1);
 
1526
        oscopy(reply, topic, i);
 
1527
  }
 
1528
  else  i = 0;
 
1529
  reply[i] = EOS;
 
1530
 
 
1531
  if (!helpw)   helpw = CreateHelpWindow();
 
1532
  old_helpw = help.w[2]->help;
 
1533
  AttachHelpWindow(help.w[2],helpw);
 
1534
 
 
1535
  TheDoc = 0;
 
1536
  help   = *helpin;     
 
1537
  help.flags |= 1;              /* Edit in Top Window   */
 
1538
  status = 1;
 
1539
  level  = 0;                   /* Starting Level       */
 
1540
  level_step = 1;               /* Decrease by this amount for _PROMPT_ */
 
1541
  topics[0].piece = 0;
 
1542
  topics[0].pos = ((PIECE *)(help.buf->buf))->start;
 
1543
 
 
1544
  BUF_Clear(filenames); 
 
1545
  LocTop(0, 0, 1);              /* Find level 0 (start) */
 
1546
 
 
1547
  if_not(exit_option)   ClearWindow(help.w[2]);
 
1548
 
 
1549
  BUF_Clear(list); 
 
1550
  BUF_AppendItem(list, char, &blank);   /* Initialize list buffer */
 
1551
  
 
1552
  while ((status >= 0) && (level >= 0)) {
 
1553
        Reset(level);
 
1554
        if (level_step < 1)     level_step = 1;
 
1555
 
 
1556
        switch(status) {
 
1557
 
 
1558
          case _REDISPLAY_:
 
1559
                Reset(level);
 
1560
                goto EDIT_TOP;
 
1561
 
 
1562
          case _PROMPT_:        /* Get the topic */
 
1563
                status = Prompt(level);
 
1564
                if (status == _PROMPT_) level-= level_step, level_step = 1;
 
1565
                continue;
 
1566
        
 
1567
          case _SUMMARY_:       /* List the Summary */
 
1568
                GetSummary(level);
 
1569
                status = EdSummary(level);
 
1570
                continue;
 
1571
        }
 
1572
 
 
1573
                /* Locate topics separated by blanks    */
 
1574
 
 
1575
        TRACE_ED_STRING("Reply is: ", reply);
 
1576
        level_step = 1;
 
1577
        for (b = reply; *b; ) {
 
1578
                i = strspan_(b, 1, sep_table);
 
1579
                if (i)  {
 
1580
                        if (*b != ' ')  level_step += 1;
 
1581
                        b += i;
 
1582
                }
 
1583
                if_not(*b)      break;
 
1584
                Reset(level);
 
1585
                if (++level > 9)        level = 9;
 
1586
                topics[level].topic = b;
 
1587
                topics[level].ltopic = strscan_(b, 1, sep_table);
 
1588
                if (LocTop(level, help.flags, 1) != level) {
 
1589
                        if (exit_option >=  0)  Sorry(b, exit_option);
 
1590
                        if (exit_option)        FINISH;
 
1591
                        level -= level_step, level_step = 1;
 
1592
                        status = _PROMPT_;
 
1593
                        break;
 
1594
                }
 
1595
                b += topics[level].ltopic;
 
1596
        }
 
1597
        if (status == _PROMPT_) continue;
 
1598
 
 
1599
 
 
1600
                /* Edit located Topic   */
 
1601
 
 
1602
        EDIT_TOP:
 
1603
        if (exit_option >=  0)  status = EdTop(level);  
 
1604
        else {
 
1605
                b = topics[level].pos;  x = *b; *b = 0;
 
1606
                located_help = strsave(topics[level].hpos);
 
1607
                *b = x;
 
1608
        }
 
1609
        if (exit_option)        FINISH;
 
1610
        if (status < 0)         FINISH;
 
1611
        if (status == _REDISPLAY_) continue;
 
1612
        if (subtopics == 0)     level -= level_step, level_step = 1;
 
1613
  }
 
1614
 
 
1615
  FIN:
 
1616
  AttachHelpWindow(help.w[2],old_helpw);
 
1617
  CloseDoc(TheDoc), TheDoc = 0;
 
1618
 
 
1619
  if (status >= 0)      status = OK;
 
1620
  else if (status == _BAD_INDEX_)       helpin->indexed = 0;
 
1621
  if (loaded)           /* Free allocated memory if Index       */
 
1622
        MEM_FREE(loaded), loaded = NULL_PTR(LOADED);
 
1623
  EXIT(status);
 
1624
}
 
1625
 
 
1626
/*==========================================================================
 
1627
 *                      th_loc
 
1628
 *==========================================================================*/
 
1629
char *th_loc(helpin, topic, option)
 
1630
/*+++
 
1631
.PURPOSE Retrieve the named topic
 
1632
.RETURNS String starting at the \Help keyword \ NULL
 
1633
.REMARKS 
 
1634
---*/
 
1635
        TWHELP  *helpin;        /* IN: The loaded Help  */
 
1636
        char    *topic; /* IN: Topics (separated by blanks) to display */
 
1637
        int     option; /* For future use option        */
 
1638
{
 
1639
  ENTER("*th_help");
 
1640
        strfree(located_help); located_help = (char *)0;
 
1641
        if (th_help(helpin, topic, -1) != OK)
 
1642
                strfree(located_help), located_help = (char *)0;
 
1643
  EXITp(located_help);
 
1644
}