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

« back to all changes in this revision

Viewing changes to prim/tw3/libsrc/txdisplay.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) 1986-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
.TYPE           Module
 
30
.IDENTIFICATION txdisplay.c
 
31
.AUTHOR         Francois Ochsenbein [ESO-IPG]
 
32
.LANGUAGE       C
 
33
.KEYWORDS       Display ``TeX-like'' text
 
34
.ENVIRONMENT    TermWindows
 
35
 
 
36
.COMMENTS       This module contains routines to output a ``TeX-like'' text
 
37
                on a window. A complete macro substitution is performed
 
38
                (cf tex.c module).
 
39
 
 
40
\begin{TeX}
 
41
 
 
42
The text to process follows some of the 
 
43
\LaTeX\footnote{Leslie Lamport, Addison-Wesley Publishing Company} conventions:
 
44
it includes both the text and ``macros'' that specify
 
45
processing options.
 
46
The available macros are listed in the table.
 
47
 
 
48
\begin{table}[htbp]
 
49
$$\begin{tabular}{|lp{30em}|} \hline
 
50
        Name    &       Explanation \\                  \hline
 
51
{\tt\b b}       &       Issue a single backslash (\b)   \\
 
52
{\tt\b$x$}                      &       Issue symbol $x$, with possibilities
 
53
                                        \{ \} \% \$ \& \_ \^{ } \# space \\
 
54
\hline \hline
 
55
\multicolumn{2}{|c|}{{\em Blanks and Line Position}} \\ \hline \hline 
 
56
{\tt\b\b}                       &       Break the current line          \\
 
57
{\tt\b quad}    {\tt\b qquad}   &       Issue 2 or 4 blanks     \\
 
58
{\tt \~{ }}                     &       Issue a single non-breakable blank \\
 
59
{\tt\b Hspace\{$n$\}}           &       Issue $n$ non-breakable blanks  \\
 
60
{\tt\b tab}                     &       Align to next ``tab''           \\
 
61
{\tt\b SkipLine}                &       Issue a single blank line       \\
 
62
{\tt\b indent}                  &       Indentation     \\
 
63
{\tt\b hfill}                   &       Horizontal Stretchable space    \\
 
64
{\tt\b vfill}                   &       Vertical Stretchable space \\   
 
65
{\tt\b tabright\{{\em text}\}   &       Align rightmost letter of {\em text} to
 
66
                                        next ``tab''            \\
 
67
%
 
68
\hline \hline
 
69
\multicolumn{2}{|c|}{{\em Line Justifications}} \\      \hline \hline 
 
70
{\tt\b centerline\{{\em text}\}}        &       Issue a line with {\em text} 
 
71
                                                centered.
 
72
                                        (see also {\tt center} environment)\\
 
73
{\tt\b leftline\{{\em text}\}}  &       Issue a line with {\em text} 
 
74
                                                adjusted to the left 
 
75
                                        (see also {\tt left} environment)\\
 
76
{\tt\b rightline\{{\em text}\}} &       Issue a line with {\em text} 
 
77
                                                adjusted to the right 
 
78
                                        (see also {\tt right} environment)\\
 
79
\hline \hline
 
80
\multicolumn{2}{|c|}{{\em Video Attributes}} \\ \hline \hline 
 
81
{\tt\b VB} or {\tt\b bf}        &       use {\bf Boldface} attribute    \\
 
82
{\tt\b Vu} or {\tt\b sl}        &       use {\sl Underscore} attribute  \\
 
83
{\tt\b Vr} or {\tt\b em} or{ \tt\b it}  & use {\em Reverse} attribute   \\
 
84
{\tt\b Vb}                      &       use {\tt Blink} attribute       \\
 
85
{\tt\b fbox\{{\em text}\}}      &       use \fbox{Bold+Reverse+Blink}
 
86
                                                attribute       \\      
 
87
%
 
88
\hline \hline
 
89
\multicolumn{2}{|c|}{{\em Environments}} \\     \hline \hline 
 
90
{\tt\{verbatim\}}               &       Display text as it is   \\
 
91
{\tt\{center\}}                 &       Centering text          \\
 
92
{\tt\{left\}} \quad{\tt\{right\}} &     Left-aligned / Right-adjusted text, 
 
93
                                        also called raggedright / raggedleft\\
 
94
{\tt\{indent\}}                 &       Push left margin        \\
 
95
{\tt\{quote\}}          &       Push left and right margins     \\
 
96
{\tt\{itemize\}}                &       Itemized  list; {\tt\b item}
 
97
                                        starts each item                \\
 
98
{\tt\{enumerate\}}              &       Start an enumerated list;
 
99
                                        {\tt\b item} starts each item   \\
 
100
{\tt \{alphaenumerate\}}        &       Enumerated list using 
 
101
                                                lowercase letters\\
 
102
{\tt \{Alphaenumerate\}}        &       Enumerated list using 
 
103
                                                uppercase letters\\
 
104
{\tt \{more\}}\{{\em name}\}    &       Text which can be retrieved, 
 
105
                                        but not displayed \\
 
106
{\tt \{table\}\{{\em pos}\}\{{\em w}\}} & 
 
107
                Table environment. 
 
108
                See explanations in the text.   \\
 
109
\hline \hline
 
110
\multicolumn{2}{|c|}{{\em Environment-specific macros}} \\      \hline \hline 
 
111
%
 
112
{\tt\b item}                    &       Specifies a new element in the 
 
113
                                 itemize / enumerate list\\
 
114
{\tt\b crule\{$c_1$--$c_2$\}} {\tt\b Rule}      &Issue a horizontal line over 
 
115
                                        one columns $c_1$ to $c_2$ and whole table      \\
 
116
{\tt\b len\{{\em text}\}}       &       Computes length of {\em text} \\
 
117
{\tt\b multicolumn\{$n$\}\{{\em j}\}\{{\em text}\}} 
 
118
                        &       define a column spreading over $n$
 
119
                                columns with {\em j} justification.\\
 
120
{\tt\b columns\{{\em pos}\}\{{\em w}\}} & redefine columns in 
 
121
                Table environment\\
 
122
\hline \hline
 
123
\multicolumn{2}{|c|}{{\em Miscellaneous}} \\    \hline \hline 
 
124
%
 
125
{\tt\b bell}                    &       Ring the terminal bell  \\
 
126
{\tt\b input\{{\em filename}\}}  & Get text to process from {\em filename} \\
 
127
{\tt\b def\b{\em name\#}\dots\{{\em equivalence}\}}
 
128
                                & Macro definition      \\
 
129
{\tt\b today}\quad {\tt\b time}\quad {\tt\b now}
 
130
                                & Date, time, date+time editions\\
 
131
{\tt\b EOF}                     & End of text indicator (stops when found) \\
 
132
{\tt\b iftrue} {\tt\b iffalse}
 
133
{\tt\b else} {\tt\b fi} &       Conditional tests \\
 
134
{\tt\b CheckLines\{$n$\}}       &       Terminate if less than  $n$ lines 
 
135
                                                remain on the current window \\
 
136
{\tt\b FormField\{{\em name}\}\{{\em type}\}\{{\em pic}\}\{{\em text}\}}&
 
137
                                Define a named field
 
138
                                which can be retrieved in the calling program
 
139
                                \via {\em GetMarkedFields}\\ 
 
140
\hline\end{tabular}$$
 
141
\caption{\label{macro:tex}TermDisplay macros}\end{table}
 
142
 
 
143
\medskip
 
144
{\bf Table Environment} 
 
145
 
 
146
\label{env:table}
 
147
The 2 parameters of the {\tt\b begin\{table\}} or 
 
148
{\tt\b columns} macros specify:
 
149
\begin{enumerate}
 
150
\item The {\em pos} parameter, similar to the \LaTeX:
 
151
        possibilities of \quad l \quad r \quad c \quad p \quad for left, 
 
152
        right, centered or justified text,
 
153
        $|$ for a vertical line separating columns,
 
154
        and blanks before / after the $|$ .
 
155
\item The {\em w} parameter specifies the {\em width} of
 
156
        each column, as number of characters separated
 
157
        by commas or blanks; if the last column width is
 
158
        not specified, it is assumed to use the {\em remaining space}.
 
159
\end{enumerate}
 
160
 
 
161
Examples:
 
162
\begin{itemize}
 
163
\item   {\tt\b begin\{table\}\{|r |p|\}\{5,50\}} will create a table with 2 columns:
 
164
        a right-adjusted column (with a blank at the left of the
 
165
        second $|$) of 5 characters, and a justified column
 
166
        with 50 characters; the complete width of the table is 59 characters
 
167
        (don't forget the space required by the vertical lines and blanks!)
 
168
\item   {\tt\b begin\{table\}\{rcp\}\{5,10\}} will create a table with 3 columns:
 
169
        a right-adjusted column of 5 characters, a centered column of 10 
 
170
        characters, and a justified column of 65 characters if the
 
171
        width of the window is 80 characters.
 
172
\end{itemize}
 
173
 
 
174
\medskip
 
175
{\bf more environment} 
 
176
\label{env:Ccode}
 
177
 
 
178
The text between {\tt\b begin\{more\}\{Ccode\}} and {\tt\b end\{more\}}
 
179
contains C instructions (cf {\bf cc} module) which can be retrieved with
 
180
the {\em tx\_more{Ccode}} function, then compiled (see {\em cc\_compile})
 
181
and executed. 
 
182
The text between {\tt\b begin\{more\}\{Ccode\}} and {\tt\b end\{more\}}
 
183
will never be displayed on a window.
 
184
 
 
185
\medskip
 
186
 
 
187
The program uses a {\em tex\_action} routine; the characters passed to
 
188
this routine have the following meaning:
 
189
$$\begin{tabular}{|ll||ll|} \hline
 
190
\multicolumn{2}{|c||}{\em Single character actions} &
 
191
\multicolumn{2}{|c|}{\em Two character actions} \\
 
192
\hline
 
193
\       &single stretchable blank       &
 
194
        &       \\
 
195
\b r    &new line       &
 
196
        &       \\
 
197
\b n    &new paragraph          &
 
198
        &       \\
 
199
0       &begin / end environments       &
 
200
        F       &Field definitions\\
 
201
\{      &open a new environment         &
 
202
        f       &fill horizontal / vertical\\
 
203
\}      &return to previous environment &
 
204
        J       &justification specifications\\
 
205
/       &issue a blank line             &
 
206
        M       &Move margins operations\\
 
207
\&      &start next column of a table   &
 
208
        m       &multicolumn definitions\\
 
209
t       &start at next `tab'            &
 
210
        V       &Video attributes specifications\\
 
211
b       &ring terminal bell             &
 
212
        &       \\
 
213
r       &rule over one column   & 
 
214
        &       \\
 
215
R       &rule all over table    &
 
216
        &       \\
 
217
\hline
 
218
\end{tabular}$$
 
219
 
 
220
 
 
221
\end{TeX}
 
222
 
 
223
.VERSION 1.0    24-Sep-1986:    Creation
 
224
.VERSION 1.1    30-Jan-1987:    Redefinition of internal functions as static
 
225
.VERSION 1.2    01-Jun-1987:    Added \ul macro (underline)
 
226
.VERSION 2.0    02-Jul-1987:    Version '2' of TermWindows.
 
227
                                Removed LastRule.
 
228
                                Added CentreColumns, LeftColumns, RightColumns.
 
229
.VERSION 2.1    28-Sep-1987:    For Forms, added Macros
 
230
                                \Field{name}{text}
 
231
                                \Hspace{len}
 
232
.VERSION 3.0    29-Apr-1988:    Version '3', with complete macro processing.
 
233
.VERSION 3.1    08-Dec-1988:    \tab action does not indent if the
 
234
                                cursor is at a line beginning.
 
235
                        Added environment {Ccode}, which accumulates the
 
236
                        text into the Ccode buffer, and which can be
 
237
                        retrieved via tx_ccode.
 
238
.VERSION 3.2    31-Jan-1989:    \columns{}{} to redefine columns of a table
 
239
.VERSION 3.3    01-Mar-1989:    Replaced Ccode by {more}{Ccode}.
 
240
                        Added tx_symbol() to translate a symbol.
 
241
.VERSION 3.31   14-Mar-1989:    Removed bug in tx_action,
 
242
                        at tx_item call, and tx_item
 
243
                        (Syndrome: item tag disappeared at top of page)
 
244
.VERSION 3.32   26-May-1989:    Added tx_def to define a symbol.
 
245
.VERSION 3.4    29-Jun-1989:    Redesigned table editions.
 
246
.VERSION 3.5    24-Jul-1989:    Removed bug in tx_rule / nltab
 
247
.VERSION 3.51   16-Aug-1989:    Added close_table as a separate routine.
 
248
.VERSION 3.6    19-Mar-1990:    Removed bug in tx_action.
 
249
.VERSION 3.7    21-Nov-1990:    Added obeylines / obeyspaces + 
 
250
                                begin{group}/end{group}
 
251
.VERSION 3.8    04-Dec-1990: Removed bug in tabright, alignment was not correct
 
252
                                when linesize not a multiple of MARGIN..
 
253
                                Also allow negative Hspace
 
254
.VERSION 3.9    10-Jun-1991: Modified tx_more to allow several `more'
 
255
                        environments
 
256
 
 
257
 090901         last modif
 
258
----------------------------------------------------------------------------*/
 
259
 
 
260
#define DEBUG           0       /* For debugging only           */
 
261
 
 
262
#define PM_LEVEL        LEVEL_TX
 
263
 
 
264
#include <midas_def.h>
 
265
 
 
266
#include <stdlib.h>
 
267
 
 
268
 
 
269
 
 
270
#include <twset.h>
 
271
#include <tex.h>
 
272
#include <atex.h>
 
273
#include <buffer.h>
 
274
#include <str.h>
 
275
 
 
276
#define HSIZE   300             /* Size of h-table      */
 
277
 
 
278
 
 
279
extern int tv_bell();
 
280
 
 
281
extern int tw_fill(), tw_attr(), tw_uattr(), tw_r(), tw_goto(), tw_rule();
 
282
extern int tw_st(), tw_uflag(), tw_chars(), tw_copw(), tw_flags();
 
283
extern int tw_uw(), tw_write(), tw_il(), tw_clear(), tw_dc();
 
284
extern int tw_nl(), tw_upw(), tw_uc(), tw_mvc(), tw_copy();
 
285
extern int tw_mrule();
 
286
 
 
287
extern int pm_enter(), pm_iexit(), pm_tr2(), pm_ed_i();
 
288
 
 
289
extern int eh_ed_as(), eh_put1(), eh_put();
 
290
 
 
291
extern int tex_exec(), tex_unit(), tex_getparm(), tex_mexec();
 
292
extern int tex_input(), tex_load(), tex_list();
 
293
 
 
294
extern int tx_jr(), tx_jc(), tx_justify(); 
 
295
 
 
296
 
 
297
static  char item_ed[3];
 
298
static  char zero = EOS;
 
299
 
 
300
typedef struct {
 
301
        short int col_lim[2];
 
302
        short int line_lim[2];          /* [0] = Top next & / [1] = Next \\ */
 
303
        unsigned char smart;            /* Smart (justify) attribute    */
 
304
        unsigned char attr;             /* Attribute for this depth     */
 
305
        unsigned char cols;             /* Number of columns this depth */
 
306
        unsigned char col_no;           /* Current column number        */
 
307
        unsigned char col_i;            /* Increment column number      */
 
308
        unsigned char flags;    
 
309
#define ForceJustification      0x01
 
310
#define NoJustification         0x02
 
311
#define JustificationDone       0x04
 
312
#define AnchoredPosition        0x08
 
313
#define InField                 0x10
 
314
        char  tex_mode;
 
315
        char  env;      
 
316
        short count;                    /* For enumerate                */
 
317
   }    DEPTH;
 
318
 
 
319
static DEPTH *pd, *pd0; /* Pointer to current environment */
 
320
static DEPTH column;
 
321
 
 
322
#define _JUSTIFY_       (_LEFT_+_RIGHT_)
 
323
#define _LEFT_BAR_      0x10
 
324
#define _RIGHT_BAR_     0x20
 
325
#define _LEFT_BLANK_    0x40
 
326
#define _RIGHT_BLANK_   0x80
 
327
 
 
328
#define _MARKER1_       0x8000          /* 2 markers are used to allow  */
 
329
static  short   marked;
 
330
 
 
331
#define Lines()         (ws->dim[0])
 
332
#define Columns()       (ws->dim[1])
 
333
#define Position(i,j)   ((i)*(ws->dim[1]) + j)
 
334
#define CurrentLine()   (ws->pos / ws->dim[1])
 
335
#define CurrentColumn() (ws->pos % ws->dim[1])
 
336
#define BottomReached() (ws->pos >= ws->marker[1])
 
337
 
 
338
 
 
339
        /* Static variables used for communication between routines */
 
340
 
 
341
static TeX      htex = {        /* The TeX header       */
 
342
        NULL_PTR(H_TABLE), NULL_FCT(int), NULL_FCT(int), NULL_PTR(char),
 
343
        0,0,0};
 
344
 
 
345
static BUFFER   *depth_buf = NULL_PTR(BUFFER);
 
346
 
 
347
static BUFFER   line_buf = BUF_Init(char, 80);
 
348
                /* This buffer contains the `blank' line */
 
349
 
 
350
static BUFFER   field_names = BUF_Init(char, 128);
 
351
                /* This buffer contains the Marked Field Names */
 
352
 
 
353
static BUFFER   field_def = BUF_Init(short int, 48);
 
354
                /* This buffer contains the Column Ranges of each field */
 
355
 
 
356
static BUFFER   More = BUF_Init(char, 128);
 
357
                /* This buffer contains the C Code in the Ccode env. */
 
358
 
 
359
static BUFFER   aux = BUF_Init(char, 24);
 
360
                /* This buffer contains the temporary output    */
 
361
 
 
362
static BUFFER   oMore = BUF_Init(int, 4);
 
363
                /* This buffer contains the offsets in More env. */
 
364
 
 
365
static BUFFER   *inaux = NULL_PTR(BUFFER);      /* When output redirected */
 
366
 
 
367
static short    MARGIN; /* Margin Size, computed as 1/10 of window width */
 
368
static char     WindowIsActive  = 0;
 
369
static char     blank_lines     = 0;
 
370
static char     rule_lines      = 0;
 
371
static char     do_init_line    = 0;
 
372
static char     last_issued_char = EOS;
 
373
static char     table_depth = 0;
 
374
 
 
375
#define MAX_MARKED      6
 
376
static int      vfill_no = 0;
 
377
static int      hfill_no = 0;
 
378
static short    vfill[MAX_MARKED];
 
379
static short    hfill[MAX_MARKED];
 
380
static char     blanks[32];
 
381
 
 
382
static int      (*external_action)() = NULL_FCT(int);
 
383
                                /* User-defined function for math symbols */
 
384
 
 
385
static WINDOW   *ws = NULL_WINDOW;              /* Used Window           */
 
386
 
 
387
static ACHAR    current_blank = ' ';    /* Blank attr of begin of line */
 
388
 
 
389
static int      txopt = 1;              /* Centering Option     */
 
390
 
 
391
int tx_out(), tx_action();
 
392
 
 
393
        MONITOR(TXDISPLAY);
 
394
 
 
395
 
 
396
/*==========================================================================
 
397
 *                      tx_set
 
398
 *==========================================================================*/
 
399
static int tx_set()
 
400
/*+++
 
401
.PURPOSE Positions in the current environment.
 
402
.RETURNS OK
 
403
.REMARKS Not traced
 
404
---*/
 
405
{
 
406
  pd0 = BUF_ItemPosition(depth_buf, DEPTH), pd = pd0;
 
407
  if (pd0->cols)        pd += (1 + pd->col_no);
 
408
 
 
409
  return(OK);
 
410
}
 
411
 
 
412
/*==========================================================================
 
413
 *                      init_line
 
414
 *==========================================================================*/
 
415
static int init_line()
 
416
/*+++
 
417
.PURPOSE Write Rules
 
418
.RETURNS OK
 
419
.REMARKS 
 
420
---*/
 
421
{
 
422
        int     i, j;
 
423
 
 
424
  i = CurrentLine();
 
425
  if (CurrentColumn() > 0)      i++;
 
426
  i = Position(i, 0);
 
427
  if (BottomReached())  FINISH;
 
428
 
 
429
  for (j = 0; j < line_buf.used; j++)
 
430
  {
 
431
        if (line_buf.buf[j] == 1)       ws->pos = i + j,
 
432
                                        tw_rule(ws, _DOWN_, ws->dim[0]);
 
433
  }
 
434
 
 
435
  FIN:
 
436
  ws->pos = i;
 
437
  do_init_line = 0;     /* Performed... */
 
438
 
 
439
  return(OK);
 
440
}
 
441
  
 
442
/*==========================================================================
 
443
 *                      tx_tex
 
444
 *==========================================================================*/
 
445
TeX *tx_tex()
 
446
/*+++
 
447
.PURPOSE Retrieve the TeX structure (macro table, etc); initilize if not done.
 
448
.RETURNS Pointer to the TeX structure used by TermDisplay.
 
449
.REMARKS The macros H-table is created if necessary
 
450
---*/
 
451
{
 
452
        MID_STATIC char definitions[] = "\
 
453
\\def\\indent{\03MI\04}\
 
454
\\def\\vfill{\03fv\04}\
 
455
\\def\\hfill{\03fh\04}\
 
456
\\def\\Hspace#1{\\action{Mh}}\
 
457
\\def\\CheckLines#1{\\action{MV}}\
 
458
\\def\\CheckCols#1{\\action{MH}}\
 
459
\\def\\quad{\\ \\ }\
 
460
\\def\\qquad{\\ \\ \\ \\ }\
 
461
\\def\\SkipLine{\03/\04}\
 
462
\\def\\bell{\03b\04}\
 
463
\\def\\VB{\03VB\04}\
 
464
\\def\\Vr{\03Vr\04}\
 
465
\\def\\VR{\03VR\04}\
 
466
\\def\\Vu{\03Vu\04}\
 
467
\\def\\Vn{\03Vn\04}\
 
468
\\def\\Vb{\03Vb\04}\
 
469
\\def\\Jl{\03Jl\04}\
 
470
\\def\\Jr{\03Jr\04}\
 
471
\\def\\Jc{\03Jc\04}\
 
472
\\def\\Jf{\03Jf\04}\
 
473
\\def\\Jj{\03Jj\04}\
 
474
\\def\\bf{\\VB}\
 
475
\\def\\em{\\VR}\
 
476
\\def\\rm{\\Vn}\
 
477
\\def\\it{\\Vr}\
 
478
\\def\\sl{\\Vu}\
 
479
\\def\\fbox#1{{\\action{VrVBVb}#1}}\
 
480
\\def\\item{\\action{Mi}}\
 
481
\\def\\crule#1{\\action{r}}\
 
482
\\def\\Rule{\\action{R}}\
 
483
\\def\\tab{\\action{t}}";
 
484
        MID_STATIC char def_env[] = "\
 
485
\\def\\tabright#1{\\action{Jt}#1\\action{J0}}\
 
486
\\def\\centerline#1{\\\\{\\Jc\\Jf#1}\\\\}\
 
487
\\def\\leftline#1{\\\\{\\Jl\\Jf#1}\\\\}\
 
488
\\def\\rightline#1{\\\\{\\Jr\\Jf#1}\\\\}\
 
489
\\defenv\\left{\\0\\action{JlJf}}{\\0}\
 
490
\\defenv\\right{\\0\\action{JrJf}}{\\0}\
 
491
\\defenv\\center{\\0\\action{JcJf}}{\\0}\
 
492
\\defenv\\quote{\\0\\action{MlMr}}{\\0}\
 
493
\\defenv\\itemize{\\0\\action{Ml}}{\\0}\
 
494
\\defenv\\indent{\\0\\action{Ml}}{\\0}\
 
495
\\defenv\\enumerate{\\0\\action{Ml}}{\\0}\
 
496
\\defenv\\alphaenumerate{\\0\\action{Ml}}{\\0}\
 
497
\\defenv\\Alphaenumerate{\\0\\action{Ml}}{\\0}\
 
498
\\defenv\\group{\\0}{\\0}\
 
499
\\defenv\\more#1{\\0}{\\0}\
 
500
\\defenv\\table#1#2{\\0}{\\0}";
 
501
        MID_STATIC char def_ff[] = "\
 
502
\\def\\columns#1#2{\\action{Ft}}\
 
503
\\def\\multicolumn#1#2#3{\\action{m#2}#3\\action{m0}}\
 
504
\\def\\FormField#4{\\action{Fs}#4\\action{Fe}}\
 
505
\\def\\Field#2{\\FormField{#1}{}{}{#2}}\
 
506
";
 
507
 
 
508
  htex.output = tx_out, htex.action = tx_action;
 
509
 
 
510
  if_not(htex.macros)
 
511
  {     htex.macros = h_create (HSIZE);
 
512
        TeX_Execute(&htex, definitions, sizeof(definitions)-1);
 
513
        TeX_Execute(&htex, def_env, sizeof(def_env)-1);
 
514
        TeX_Execute(&htex, def_ff , sizeof(def_ff )-1);
 
515
  }
 
516
 
 
517
  return(&htex);
 
518
}
 
519
 
 
520
/*==========================================================================
 
521
 *                      tx_init
 
522
 *==========================================================================*/
 
523
static int tx_init(str, clear_option)
 
524
/*+++
 
525
.PURPOSE Initialisation: TeX, buffers, etc
 
526
.RETURNS OK  / NOK 
 
527
.REMARKS Important actions as \03action\04
 
528
---*/
 
529
        char    *str;   /* IN: String to display        */
 
530
        int     clear_option;   /* IN: Option to clear Window before display */
 
531
{
 
532
        int status, i;
 
533
        int old_offset, old_used;
 
534
 
 
535
  ENTER("tx_init");
 
536
 
 
537
  status = NOK;
 
538
 
 
539
  if_not(depth_buf)     /* Not yet initialized */
 
540
  {     oscfill(blanks, sizeof(blanks), ' ');
 
541
        if_not(depth_buf = BUF_Open(DEPTH, 24, 24))
 
542
                FINISH;
 
543
        if_not(htex.macros)     tx_tex();       /* Initialise TeX macros */
 
544
  }
 
545
 
 
546
        /* Do all initialisations */
 
547
 
 
548
  MARGIN        = (Columns()+4)/10;
 
549
  vfill_no      = 0;
 
550
  hfill_no      = 0;
 
551
  inaux         = NULL_PTR(BUFFER);
 
552
  last_issued_char = ' ';
 
553
  BUF_Clear(&field_def);
 
554
  BUF_Clear(&field_names);
 
555
  BUF_Clear(&More);
 
556
  BUF_Clear(&aux);
 
557
  BUF_Clear(&oMore);
 
558
  if (Fields(ws))       BUF_Clear(Fields(ws));
 
559
 
 
560
        /* Be sure that window is not Active. It is useless to output
 
561
         * data on the screen immediately --- moreover, justifications
 
562
         * etc must be performed before presenting the nice result ... */
 
563
 
 
564
  WindowIsActive = (ws->flags & Echo);
 
565
  DeactiveWindow(ws);
 
566
 
 
567
  if (clear_option)     ClearWindow(ws);
 
568
  blank_lines   = (CurrentColumn() == 0 ? 1 : 0);
 
569
 
 
570
  tw_uflag(ws, 1);              /* Window completely modified */
 
571
 
 
572
 
 
573
        /* Initialise: set flags, and if the text is starting (non-null str)
 
574
         * initialize depth to zero, default justification, etc ...     */
 
575
 
 
576
  if (str)              /* A new string to display      */
 
577
  {     BUF_Clear(depth_buf);
 
578
        column.col_lim[0] = 0, column.col_lim[1] = Columns();
 
579
        column.line_lim[0] = 0, column.line_lim[1] = 0;
 
580
        column.smart = 0;
 
581
        column.attr = 0;
 
582
        column.cols = 0;
 
583
        column.col_no = 0;
 
584
        column.col_i  = 1;
 
585
        column.env    = 0;
 
586
        column.count  = 0;
 
587
        BUF_StackItem(depth_buf, DEPTH, &column);
 
588
        BUF_Clear(&line_buf); 
 
589
        table_depth = 0;
 
590
        rule_lines  = 0;
 
591
  }
 
592
 
 
593
                /* Reset All Line Limits */
 
594
 
 
595
  tx_set();
 
596
  pd0->line_lim[1] = CurrentLine();
 
597
  pd0->line_lim[0] = pd0->line_lim[1];
 
598
  old_used   = depth_buf->used;
 
599
  old_offset = depth_buf->offset;
 
600
  for ( pd = pd0; pd; pd = BUF_UnstackItem(depth_buf, DEPTH))
 
601
  {
 
602
        for (i = pd->cols; i-- >= 0; pd++)
 
603
        {       pd->line_lim[0] = pd0->line_lim[0];
 
604
                pd->line_lim[1] = pd0->line_lim[1];
 
605
        }
 
606
  }
 
607
  depth_buf->used   = old_used;
 
608
  depth_buf->offset = old_offset ;
 
609
 
 
610
  tx_set();
 
611
  SetAttr(ws, pd0->attr);
 
612
  current_blank = ws->attr;
 
613
 
 
614
        /* In the case of a continuation in the Tab environment,
 
615
         * initialize the first line. This is done with init_line       */
 
616
 
 
617
  if (table_depth)              init_line();
 
618
 
 
619
  FIN:
 
620
  EXIT(status);
 
621
}
 
622
 
 
623
/*==========================================================================
 
624
 *                      new_col
 
625
 *==========================================================================*/
 
626
static int new_col()
 
627
/*+++
 
628
.PURPOSE Create a new column
 
629
.RETURNS OK
 
630
.REMARKS 
 
631
---*/
 
632
{
 
633
        unsigned char j;
 
634
 
 
635
  j = column.smart&7;
 
636
  if ( (j == _RIGHT_) || (j == _CENTER_))
 
637
        column.flags |= ForceJustification;
 
638
  BUF_AppendItem(depth_buf, DEPTH, &column);
 
639
  tx_set();
 
640
  pd0->cols += 1;
 
641
  column.smart = 0;
 
642
  column.flags = 0;
 
643
  
 
644
  return(OK);
 
645
}
 
646
 
 
647
/*==========================================================================
 
648
 *                      Mark
 
649
 *==========================================================================*/
 
650
static int Mark(pos, len)
 
651
/*+++
 
652
.PURPOSE Mark characters from pos, length len
 
653
.RETURNS OK / NOK
 
654
.REMARKS 
 
655
---*/
 
656
        int pos;        /* IN: Position for marker */
 
657
        int len;        /* IN: Number of characters to mark     */
 
658
{
 
659
        ACHAR   *pa;
 
660
 
 
661
  if (marked == 0)      
 
662
  {     pa = Aij(ws, pos/Columns(),  pos%Columns());
 
663
        *pa |= _MARKER1_;
 
664
  }
 
665
  marked += len;
 
666
  
 
667
  return((pos + len < ws->marker[1] ? OK : NOK));
 
668
}
 
669
 
 
670
/*==========================================================================
 
671
 *                      tx_smart
 
672
 *==========================================================================*/
 
673
static int tx_smart()
 
674
/*+++
 
675
.PURPOSE Justify the text in column, accordings to pd->smart.
 
676
.RETURNS OK 
 
677
.REMARKS No justification if left adjustement, or line is empty.
 
678
        The flag NoJustification or JustificationDone are taken into account.
 
679
---*/
 
680
{
 
681
        register ACHAR *pa;
 
682
        int     i, len, j, justify;
 
683
 
 
684
  if (pd->flags & NoJustification)      FINISH;
 
685
  if (pd->flags & JustificationDone)
 
686
  {     pd->flags &= ~JustificationDone;
 
687
        FINISH;
 
688
  }
 
689
  if (blank_lines)                      FINISH;
 
690
  if (htex.mode == _TeX_VERBATIM_)      FINISH;
 
691
  if (htex.mode &  _TeX_OBEY_)          FINISH;
 
692
 
 
693
  switch( justify = (pd->smart & 7) )
 
694
  {  default: justify = _JUSTIFY_;
 
695
        break;
 
696
     case _LEFT_ : case _RIGHT_ : case _CENTER_: 
 
697
        break;
 
698
  }
 
699
 
 
700
  i  = CurrentLine();
 
701
  pa = Aij(ws, i, pd->col_lim[0]);
 
702
  len = pd->col_lim[1] - pd->col_lim[0];
 
703
 
 
704
  if ((current_blank != ws->attr_init) && (current_blank == ws->attr) &&
 
705
        (justify != _JUSTIFY_))
 
706
  {     for (j = len; --j >=0; pa++) 
 
707
                if (*pa == ws->attr_init)       *pa = current_blank;
 
708
        pa = Aij(ws, i, pd->col_lim[0]);
 
709
  }
 
710
  else  current_blank = ws->attr_init;  
 
711
  
 
712
  switch( justify )
 
713
  {     case _LEFT_ :   /* tx_jl(pa, len, current_blank); */
 
714
                        break;
 
715
        case _RIGHT_ :  tx_jr(pa, len, current_blank);
 
716
                        break;
 
717
        case _CENTER_:  tx_jc(pa, len, current_blank);
 
718
                        break;
 
719
        case _JUSTIFY_:
 
720
                        tx_justify(pa, len, current_blank);
 
721
                        break;
 
722
  }
 
723
  current_blank = ws->attr;
 
724
 
 
725
  ws->pos = Position(i, pd->col_lim[1]);        /* Correct position */
 
726
  if (CurrentColumn() == 0)
 
727
        blank_lines  = 1;
 
728
  else  blank_lines  = 0;
 
729
  
 
730
  FIN:
 
731
  return(OK);
 
732
}
 
733
   
 
734
/*==========================================================================
 
735
 *                      tx_blank
 
736
 *==========================================================================*/
 
737
static int tx_blank()
 
738
/*+++
 
739
.PURPOSE Output a stretchable blank on a window: 
 
740
        don't output blanks on margins, don't repeat spaces.
 
741
.RETURNS --- OK if blank not needed or correctly output 
 
742
        --- NOK if there is no more room to issue the character.
 
743
.REMARKS The blank uses the current attribute --- but Blinking or
 
744
                Bold blanks are made normal !
 
745
---*/
 
746
{
 
747
        register int    j;
 
748
 
 
749
  tx_set();
 
750
  j = CurrentColumn();
 
751
  if ((j <= pd->col_lim[0]) && (!(pd->flags & AnchoredPosition)))
 
752
                                FINISH;
 
753
  if (j >= pd->col_lim[1])      FINISH;
 
754
  if (last_issued_char == ' ')  FINISH;         /* Don't issue 2 blanks */
 
755
 
 
756
  last_issued_char = ' ', j++;
 
757
 
 
758
  if (j == pd->col_lim[1])                      /* Must justify, no blank */
 
759
        tx_smart();
 
760
  else                                          /* Insert blank           */
 
761
  {     Write(ws, &last_issued_char, 1);
 
762
        rule_lines = 0;
 
763
        if (pd->flags & InField)
 
764
                Mark(ws->pos - 1, 1);
 
765
  }
 
766
 
 
767
  FIN:
 
768
  return(OK);
 
769
}
 
770
 
 
771
/*==========================================================================
 
772
 *                      tx_hfil
 
773
 *==========================================================================*/
 
774
static int tx_hfil()
 
775
/*+++
 
776
.PURPOSE Insert blanks according to hfill_no.
 
777
.RETURNS OK
 
778
.REMARKS Not traced
 
779
---*/
 
780
{
 
781
        int j, right_lim, remaining_blanks;
 
782
        ACHAR *pa;
 
783
        
 
784
  pa = Aij(ws, CurrentLine(), 0);       /* Line beginning */
 
785
  remaining_blanks =  pd->col_lim[1] - CurrentColumn();
 
786
 
 
787
  for (right_lim = pd->col_lim[1]; hfill_no > 0; right_lim=hfill[--hfill_no]+j)
 
788
  {     j = hfill[hfill_no - 1];
 
789
        tx_jr(pa + j, right_lim - j, ws->attr_init);
 
790
        j = remaining_blanks / hfill_no;
 
791
        remaining_blanks -= j;
 
792
  }
 
793
  pd->flags |= NoJustification;         /* Already justified */
 
794
 
 
795
  return(OK);
 
796
}
 
797
 
 
798
/*==========================================================================
 
799
 *                      tx_nl
 
800
 *==========================================================================*/
 
801
static int tx_nl()
 
802
/*+++
 
803
.PURPOSE Issue a new line.
 
804
.RETURNS OK
 
805
.REMARKS Newline may imply some skips...
 
806
---*/
 
807
{
 
808
        register int i;
 
809
 
 
810
  tx_set();
 
811
  pd->flags &= ~AnchoredPosition;
 
812
 
 
813
  if (BottomReached())          FINISH;
 
814
 
 
815
  if (hfill_no) tx_hfil();              /* Horizontal Fill */
 
816
  if (pd->flags & ForceJustification)   tx_smart();
 
817
 
 
818
  i = CurrentLine();
 
819
  if (i < pd->line_lim[0])      i = pd->line_lim[0];
 
820
  pd->line_lim[1] = i;
 
821
  i = pd->line_lim[1] + 1;
 
822
  ws->pos = Position(i, 0);             /* New position */
 
823
 
 
824
  blank_lines += 1;
 
825
  pd->flags &= ~(NoJustification | JustificationDone);
 
826
  last_issued_char = ' ';
 
827
 
 
828
        /* In the Tab Environment, the new line is initialized
 
829
         * when the position is at column 0. */
 
830
 
 
831
  if (do_init_line)     init_line();
 
832
  
 
833
  FIN:
 
834
  return(OK);
 
835
}
 
836
 
 
837
/*==========================================================================
 
838
 *                      tx_vfil
 
839
 *==========================================================================*/
 
840
static int tx_vfil()
 
841
/*+++
 
842
.PURPOSE Insert lines according to vfill_no.
 
843
.RETURNS OK
 
844
.REMARKS Not traced
 
845
---*/
 
846
{
 
847
        int old_pos, i, remaining_lines;
 
848
        
 
849
  if(blank_lines == 0)  tx_nl() ;
 
850
  
 
851
  old_pos = ws->pos;
 
852
  i = CurrentLine();
 
853
  remaining_lines = Lines() - i;
 
854
  if (remaining_lines <= 0)     FINISH;
 
855
 
 
856
  for ( ; vfill_no > 0; vfill_no--)
 
857
  {     tw_goto(ws, vfill[vfill_no - 1], 0);
 
858
        i = remaining_lines / vfill_no;
 
859
        tw_il(ws, i);
 
860
        old_pos += i*ws->dim[1];
 
861
        remaining_lines -= i;
 
862
  }
 
863
  ws->pos = old_pos;
 
864
 
 
865
  FIN:
 
866
  return(OK);
 
867
}
 
868
 
 
869
/*==========================================================================
 
870
 *                      tabright
 
871
 *==========================================================================*/
 
872
static int tabright(text, len)
 
873
/*+++
 
874
.PURPOSE Justify the text at right of next `tab'
 
875
.RETURNS Written Length
 
876
.REMARKS 
 
877
---*/
 
878
        char    *text;  /* IN : text to issue   */
 
879
        int     len;    /* IN : Len of text     */
 
880
{
 
881
        int     i, j, nb;
 
882
        
 
883
  if (inaux == &aux)    inaux = NULL_PTR(BUFFER);
 
884
 
 
885
  i = CurrentLine(), j = CurrentColumn();
 
886
 
 
887
  if (j < pd->col_lim[0])       j = pd->col_lim[0];
 
888
  if ((j+len) > pd->col_lim[1]) j = pd->col_lim[0], i++;
 
889
  
 
890
  nb = (j+len-pd->col_lim[0])%MARGIN;
 
891
  if (nb) nb = (MARGIN - nb);
 
892
  j += nb;
 
893
  if ((j+len) > pd->col_lim[1]) {       /* Try to remove blanks */
 
894
        j = pd->col_lim[1] - len;
 
895
        if (j < pd->col_lim[0]) j = pd->col_lim[0];
 
896
  }
 
897
  ws->pos = Position(i, j);
 
898
  pd->flags |= JustificationDone;
 
899
 
 
900
  if (len > 0)  i = tx_out(text, len);
 
901
  else          i = 0;
 
902
  return(i);
 
903
}
 
904
 
 
905
/*==========================================================================
 
906
 *                      nltab
 
907
 *==========================================================================*/
 
908
static int nltab()
 
909
/*+++
 
910
.PURPOSE Issue a new line in Table Environment
 
911
.RETURNS OK
 
912
.REMARKS Newline may imply some skips...
 
913
---*/
 
914
{
 
915
        int     i, j;
 
916
 
 
917
  i = CurrentLine();
 
918
  pd0->line_lim[0] = MAX(i, pd0->line_lim[1]);
 
919
 
 
920
  pd0->col_no = 0, pd0->col_i = 1;
 
921
  pd0->line_lim[1] = pd0->line_lim[0];
 
922
  ws->pos = Position(pd0->line_lim[0], 0);
 
923
  for (j = pd0->cols, pd = pd0+1; --j >= 0; pd++)
 
924
        pd->line_lim[0] = pd0->line_lim[0],
 
925
        pd->line_lim[1] = pd0->line_lim[1];
 
926
 
 
927
  if (do_init_line)     init_line();
 
928
  blank_lines = 1;
 
929
  last_issued_char = ' ';
 
930
 
 
931
  return(OK);
 
932
}
 
933
 
 
934
/*==========================================================================
 
935
 *                      clear_down
 
936
 *==========================================================================*/
 
937
static int clear_down(pd)
 
938
/*+++
 
939
.PURPOSE Clear the bottom of the table
 
940
.RETURNS OK
 
941
.REMARKS 
 
942
---*/
 
943
        DEPTH   *pd;            /* IN: Column concerned */
 
944
{
 
945
        ACHAR   *pa;
 
946
        int     i, j, len, old_pos;
 
947
 
 
948
  old_pos = ws->pos;
 
949
  len = pd->col_lim[1] - pd->col_lim[0]; 
 
950
  
 
951
  i = CurrentLine();
 
952
  if (CurrentColumn() > pd->col_lim[0]) i++;
 
953
  i = MAX(i , pd->line_lim[1]);
 
954
 
 
955
  j = i-1;      /* Where to start tx_mrule */
 
956
  if (j < 0)    j = 0;
 
957
  ws->pos = Position(j, pd->col_lim[0]);
 
958
 
 
959
  for (; i < ws->dim[0]; i++)
 
960
  {
 
961
        pa = Aij(ws, i, pd->col_lim[0]);
 
962
        for (j = len; --j >= 0; pa++)   *pa = ws->attr_init; 
 
963
  }
 
964
 
 
965
  tw_mrule(ws, len);
 
966
 
 
967
  ws->pos = old_pos;
 
968
  
 
969
  return(OK);
 
970
}
 
971
  
 
972
/*==========================================================================
 
973
 *                      open_depth
 
974
 *==========================================================================*/
 
975
static int open_depth()
 
976
/*+++
 
977
.PURPOSE Do operations for opening a depth
 
978
.RETURNS OK 
 
979
.REMARKS 
 
980
---*/
 
981
{
 
982
 
 
983
  BUF_StackItem(depth_buf, DEPTH, pd);  /* Copy this depth */
 
984
  tx_set();
 
985
 
 
986
  pd->env = 0;
 
987
  pd->tex_mode = htex.mode;
 
988
  pd->flags &= ~ForceJustification;
 
989
 
 
990
  return(OK);
 
991
}
 
992
 
 
993
/*==========================================================================
 
994
 *                      close_depth
 
995
 *==========================================================================*/
 
996
static int close_depth()
 
997
/*+++
 
998
.PURPOSE Do operations for closing a depth
 
999
.RETURNS OK 
 
1000
.REMARKS 
 
1001
---*/
 
1002
{
 
1003
        unsigned char old_attr;
 
1004
        short   old_lim[2];
 
1005
        
 
1006
  old_attr = pd->attr;
 
1007
  old_lim[0] = pd0->line_lim[1];
 
1008
  old_lim[1] =  pd->line_lim[1];
 
1009
  
 
1010
  if (depth_buf->offset <= sizeof(int))
 
1011
        ERROR("Too many }");
 
1012
  else  {
 
1013
        if (pd->flags & ForceJustification)     tx_smart();
 
1014
        BUF_Unstack(depth_buf);
 
1015
        tx_set();
 
1016
        htex.mode = pd->tex_mode;
 
1017
        if (old_attr != pd->attr)       SetAttr(ws, pd->attr);
 
1018
        /* pd->line_lim[0] = old_lim[0], */
 
1019
        pd0->line_lim[1] = MAX(pd0->line_lim[1], old_lim[0]);
 
1020
         pd->line_lim[1] = MAX( pd->line_lim[1], old_lim[1]);
 
1021
  }
 
1022
  
 
1023
  return(OK);
 
1024
}
 
1025
 
 
1026
/*==========================================================================
 
1027
 *                      full_width
 
1028
 *==========================================================================*/
 
1029
static int full_width(pd, width)
 
1030
/*+++
 
1031
.PURPOSE Compute the full width of a column
 
1032
.RETURNS The width.
 
1033
.REMARKS Adds the bars
 
1034
---*/
 
1035
        DEPTH   *pd;            /* IN: Column concerned */
 
1036
        short   width[2];       /* OUT: Column Limits (right limit excluded)*/
 
1037
{
 
1038
 
 
1039
  width[0] = pd->col_lim[0];    width[1] = pd->col_lim[1];
 
1040
  
 
1041
  if (pd->smart & _LEFT_BLANK_)         width[0]--;
 
1042
  if (pd->smart & _LEFT_BAR_)           width[0]--;
 
1043
  if (pd->smart & _RIGHT_BLANK_)        width[1]++;
 
1044
  if (pd->smart & _RIGHT_BAR_)          width[1]++;
 
1045
  
 
1046
  return(width[1] - width[0]);
 
1047
}
 
1048
  
 
1049
/*==========================================================================
 
1050
 *                      tr_line
 
1051
 *==========================================================================*/
 
1052
static int tr_line(pd, old, new)
 
1053
/*+++
 
1054
.PURPOSE Modify the line buffer.
 
1055
.RETURNS Number of modifications.
 
1056
.REMARKS Adds the bars
 
1057
---*/
 
1058
        DEPTH   *pd;            /* IN: Column concerned */
 
1059
        int     old;            /* IN: Values to change */
 
1060
        int     new;            /* IN: Replacement      */
 
1061
{
 
1062
        char    *p;
 
1063
        int     i, count;
 
1064
 
 
1065
  count = 0;
 
1066
  for (p = line_buf.buf + pd->col_lim[0], i = pd->col_lim[1] - pd->col_lim[0];
 
1067
        --i >= 0; p++)
 
1068
  {
 
1069
        if (*p == old)  count++, *p = new;
 
1070
  }
 
1071
 
 
1072
  return(count);
 
1073
}
 
1074
  
 
1075
/*==========================================================================
 
1076
 *                      tx_tab0
 
1077
 *==========================================================================*/
 
1078
static int tx_tab0(opt)
 
1079
/*+++
 
1080
.PURPOSE Write / Wipe Vertical Rules (until End of Window)
 
1081
.RETURNS OK 
 
1082
.REMARKS Starting at current line...
 
1083
---*/
 
1084
        int     opt;    /* IN: Option 1 to add, 0 to remove vertical bars */
 
1085
{
 
1086
        DEPTH   *pc;
 
1087
        int     ic, i, j, old_pos;
 
1088
        short   lim[2];
 
1089
 
 
1090
  if (line_buf.used == 0)
 
1091
  {     ic = Columns();
 
1092
        BUF_AllocateItems(&line_buf, char, ic);
 
1093
        oscfill(line_buf.buf, ic, 0);           /* Clear Vertical Rules */
 
1094
  }
 
1095
 
 
1096
  if (opt == 0)  
 
1097
  {     tr_line(pd0, 1, 0);     /* Suppress */
 
1098
        return(OK);
 
1099
  }
 
1100
 
 
1101
  old_pos = ws->pos;
 
1102
  i = old_pos / Columns();      /* Current Line */
 
1103
 
 
1104
  for (ic = pd0->cols, pc = pd0+1; --ic >= 0; pc++)
 
1105
  {     full_width(pc, lim);
 
1106
        if (pc->smart & _LEFT_BAR_)     
 
1107
                j = lim[0],
 
1108
                ws->pos = Position(i, j),
 
1109
                line_buf.buf[j] = 1,
 
1110
                tw_rule(ws, _DOWN_, ws->dim[0]);
 
1111
        if (pc->smart & _RIGHT_BAR_)    
 
1112
                j = lim[1]-1,
 
1113
                ws->pos = Position(i, j),
 
1114
                line_buf.buf[j] = 1,
 
1115
                tw_rule(ws, _DOWN_, ws->dim[0]);
 
1116
  }
 
1117
  ws->pos = old_pos;
 
1118
  
 
1119
  return(OK);
 
1120
}
 
1121
  
 
1122
/*==========================================================================
 
1123
 *                      tx_tab1
 
1124
 *==========================================================================*/
 
1125
static int tx_tab1()
 
1126
/*+++
 
1127
.PURPOSE Interpret the first field of a tabular environment, made of
 
1128
        | l r c p{} (column definitions)
 
1129
.RETURNS Number of defined columns
 
1130
.REMARKS 
 
1131
---*/
 
1132
{
 
1133
        char    *p;
 
1134
        unsigned char j;
 
1135
 
 
1136
  pd0->cols = 0, pd0->smart = 0;
 
1137
  column = *pd0;
 
1138
 
 
1139
  for (p = htex.ap; *p ; p++)
 
1140
  {     switch(*p)
 
1141
        { case '|':     if (column.smart&7)
 
1142
                                column.smart |= _RIGHT_BAR_, new_col();
 
1143
                        else    column.smart |= _LEFT_BAR_;
 
1144
                        continue;
 
1145
          case ' ':     column.smart |= (column.smart&7 ? 
 
1146
                                _RIGHT_BLANK_ : _LEFT_BLANK_);
 
1147
          default:      continue;
 
1148
          case '{':     p += 1 + tex_unit(p+1, 1024);   /* Length arbitrary */
 
1149
                                                continue;
 
1150
          case 'l':     j = _LEFT_;     goto NEW_COL;
 
1151
          case 'r':     j = _RIGHT_;    goto NEW_COL;
 
1152
          case 'c':     j = _CENTER_;   goto NEW_COL;
 
1153
          case 'p':     j = _JUSTIFY_;
 
1154
          NEW_COL:      if (column.smart&7)
 
1155
                                new_col();
 
1156
                        column.smart |= j;
 
1157
                        break;
 
1158
        }
 
1159
  }
 
1160
  if (column.smart&7)   new_col();
 
1161
 
 
1162
  return ((int)pd0->cols);
 
1163
}
 
1164
 
 
1165
/*==========================================================================
 
1166
 *                      tx_tab2
 
1167
 *==========================================================================*/
 
1168
static int tx_tab2()
 
1169
/*+++
 
1170
.PURPOSE Interpret the second field of a tabular environment, 
 
1171
        indicating the column width.
 
1172
.RETURNS OK / NOK (table cannot fit)
 
1173
.REMARKS The last column width is computed, or the table is centered on
 
1174
        the window.
 
1175
---*/
 
1176
{
 
1177
        char    *p;
 
1178
        int     i, left_position, status;
 
1179
        DEPTH   *pc;
 
1180
 
 
1181
  status = OK;
 
1182
 
 
1183
  pd0->col_no = 0;
 
1184
 
 
1185
  left_position  = pd0->col_lim[0];
 
1186
 
 
1187
  for (p = htex.ap, pc = pd0+1; pd0->col_no < pd0->cols; 
 
1188
        pc++, (pd0->col_no)++)
 
1189
  {     i = 0;
 
1190
        while (isTeX(*p,_TeX_SPACE_))   p++;
 
1191
        while (isTeX(*p,_TeX_DIGIT_))
 
1192
                i = i*10 + (*(p++) - '0');
 
1193
        if (pc->smart & _LEFT_BAR_)     left_position++;
 
1194
        if (pc->smart & _LEFT_BLANK_)   left_position++;
 
1195
        pc->col_lim[0] = left_position;
 
1196
        if (i == 0)
 
1197
        {       i = pd0->col_lim[1] - left_position;
 
1198
                if (pc->smart & _RIGHT_BAR_)    i--;
 
1199
                if (pc->smart & _RIGHT_BLANK_)  i--;
 
1200
        }
 
1201
        left_position += i;
 
1202
        if (left_position > pd0->col_lim[1])    /* Too large text ... */
 
1203
                status = NOK, left_position = pd0->col_lim[1];
 
1204
        pc->col_lim[1] = left_position;
 
1205
 
 
1206
        if (pc->smart & _RIGHT_BAR_)    left_position++;
 
1207
        if (pc->smart & _RIGHT_BLANK_)  left_position++;
 
1208
 
 
1209
        if (pc->col_lim[1] <= pc->col_lim[0])   /* Too large text ... */
 
1210
                status = NOK, pc->col_lim[0] = pc->col_lim[1] - 1;
 
1211
 
 
1212
        if (isTeX(*p,_TeX_PUNCT_))      p++;
 
1213
  }
 
1214
  pd0->col_no = 0;
 
1215
 
 
1216
        /* If spaces remain, center table       */
 
1217
 
 
1218
  i = pd0->col_lim[1] - left_position;
 
1219
  if (i < 0)    status = NOK;
 
1220
 
 
1221
  if_not(status)
 
1222
        ERR_ED_STRING("The table cannot fit on window: ", htex.ap);
 
1223
 
 
1224
  else                                          /* Remaining blanks */
 
1225
  {     pd0->col_lim[1] = left_position;
 
1226
        left_position = ( txopt & 1 ? i/2 : 0);
 
1227
        for (pc = pd0, i = pd0->cols; i-- >= 0; pc++)
 
1228
                pc->col_lim[0] += left_position, 
 
1229
                pc->col_lim[1] += left_position;
 
1230
  }
 
1231
 
 
1232
  return(status);
 
1233
}
 
1234
 
 
1235
/*==========================================================================
 
1236
 *                      open_env
 
1237
 *==========================================================================*/
 
1238
static int open_table()
 
1239
/*+++
 
1240
.PURPOSE Do operations for opening a table
 
1241
.RETURNS OK 
 
1242
.REMARKS 
 
1243
---*/
 
1244
{
 
1245
  pd->env = 't';
 
1246
  tex_getparm(1);       tx_tab1();
 
1247
  tex_getparm(2);       tx_tab2();
 
1248
  tx_tab0(1);
 
1249
  table_depth++;
 
1250
  return(OK);
 
1251
}
 
1252
 
 
1253
/*==========================================================================*/
 
1254
static int open_more()
 
1255
/*+++
 
1256
.PURPOSE Do operations for opening a {more}{...} environment
 
1257
.RETURNS OK 
 
1258
.REMARKS 
 
1259
---*/
 
1260
{
 
1261
        int     i, l;
 
1262
        char    *p;
 
1263
        
 
1264
  pd->env = 'm';
 
1265
  tex_getparm(1);       /* More name */
 
1266
  l = strlen(htex.ap);
 
1267
 
 
1268
  i = More.used;
 
1269
  BUF_AppendItem(&oMore, int, &(More.used));
 
1270
  BUF_AppendItems(&More, char, htex.ap, l+1);   /* Copy Name */
 
1271
  p = More.buf + i;             /* Name address */
 
1272
  strred(p);            /* Suppress blanks in name */
 
1273
  More.used = i + strlen(p) + 1;
 
1274
 
 
1275
  return(OK);
 
1276
}
 
1277
 
 
1278
/*==========================================================================*/
 
1279
static int open_env()
 
1280
/*+++
 
1281
.PURPOSE Do operations for opening a new environment
 
1282
.RETURNS OK / NOK (not possible)
 
1283
.REMARKS 
 
1284
---*/
 
1285
{
 
1286
        int     i;
 
1287
        char    env;
 
1288
        int     min_lines;
 
1289
        
 
1290
 
 
1291
  i = CurrentLine();    /* Current position     */
 
1292
  env = *(htex.ap+1);   /* Environment to open  */
 
1293
 
 
1294
        /* Some lines at least must exist before starting */
 
1295
 
 
1296
  if (env == 'm')       min_lines = -1;
 
1297
  else if (env == 't')  min_lines = (table_depth ? 1:3);
 
1298
  else                  min_lines = 2;
 
1299
  
 
1300
  if (i >= Lines() - min_lines)
 
1301
        return(NOK);
 
1302
 
 
1303
  if(blank_lines == 0)          tx_nl();
 
1304
 
 
1305
  open_depth();         /* Copy this depth */
 
1306
  pd->env = env;
 
1307
  pd->count = 0;
 
1308
  pd->line_lim[0] = CurrentLine();      pd->line_lim[1] = pd->line_lim[0];
 
1309
  
 
1310
  if (env == 'm')       /* more */
 
1311
        inaux = &More,
 
1312
        open_more();
 
1313
 
 
1314
  if (env == 't')               /* Tabular Environment */
 
1315
        open_table(); 
 
1316
 
 
1317
  return(OK);
 
1318
}
 
1319
 
 
1320
/*==========================================================================
 
1321
 *                      close_env
 
1322
 *==========================================================================*/
 
1323
static int close_table()
 
1324
/*+++
 
1325
.PURPOSE Do operations for closing a table
 
1326
.RETURNS OK 
 
1327
.REMARKS 
 
1328
---*/
 
1329
{
 
1330
  do_init_line = 0;
 
1331
  clear_down(pd0);      /* Clear the bottom of Columns */
 
1332
  tx_tab0(0);
 
1333
  table_depth--;
 
1334
 
 
1335
  return(OK);
 
1336
}
 
1337
 
 
1338
/*==========================================================================*/
 
1339
static int close_env()
 
1340
/*+++
 
1341
.PURPOSE Do operations for closing an environment
 
1342
.RETURNS OK 
 
1343
.REMARKS 
 
1344
---*/
 
1345
{
 
1346
        char *p;
 
1347
 
 
1348
  p = htex.ap + 1;
 
1349
 
 
1350
  if (pd->env != *p)
 
1351
        ERR_ED_STRING("Mismatching begin/end env.: ", p);
 
1352
 
 
1353
  if (pd0->env == 'm')  /* More */
 
1354
        inaux = NULL_PTR(BUFFER),
 
1355
        BUF_AppendItem(&More, char, &zero);
 
1356
 
 
1357
  if (pd0->env == 't')  /* Ending Table Env */
 
1358
        close_table();
 
1359
 
 
1360
  if(blank_lines == 0)  tx_nl() ;
 
1361
 
 
1362
  return(close_depth());
 
1363
}
 
1364
 
 
1365
/*==========================================================================
 
1366
 *                      tx_item
 
1367
 *==========================================================================*/
 
1368
static int tx_item()
 
1369
/*+++
 
1370
.PURPOSE Write an `item'
 
1371
.RETURNS OK / NOK (line full)
 
1372
.REMARKS Item issued in Bold
 
1373
---*/
 
1374
{
 
1375
        int i, old_attr;
 
1376
 
 
1377
 
 
1378
  if(blank_lines == 0)  tx_nl() ;
 
1379
  if (BottomReached())  return(NOK);
 
1380
  
 
1381
  pd->count += 1;       /* Item number */
 
1382
  pd->col_lim[0] -= sizeof(item_ed);
 
1383
  if (pd->col_lim[0] < 0)       pd->col_lim[0] = 0;
 
1384
  ws->pos = Position(CurrentLine(), pd->col_lim[0]);
 
1385
  item_ed[0] = pd->count, item_ed[1] = '>', item_ed[2] = ' ';
 
1386
 
 
1387
  switch(pd->env)
 
1388
  { case 'e':   item_ed[0] += '0';      break;
 
1389
    case 'a':   item_ed[0] += 'a'-1;    break;
 
1390
    case 'A':   item_ed[0] += 'A'-1;    break;
 
1391
    default:    item_ed[0] = '=';
 
1392
  }
 
1393
 
 
1394
  old_attr = SetAttr(ws, _BOLD_);
 
1395
  i = tx_out(item_ed, 2);
 
1396
  SetAttr(ws, old_attr);
 
1397
  if (i == 0)
 
1398
        pd->count -= 1, 
 
1399
        i = NOK;
 
1400
  else  tx_out(item_ed+2, sizeof(item_ed)-2),
 
1401
        pd->col_lim[0] += sizeof(item_ed),
 
1402
        i = OK;
 
1403
 
 
1404
  return(i);
 
1405
}
 
1406
 
 
1407
/*==========================================================================
 
1408
 *                      multicol
 
1409
 *==========================================================================*/
 
1410
static int multicol(str)
 
1411
/*+++
 
1412
.PURPOSE Interprets the `multicolumn' environment
 
1413
.RETURNS Length of string taken into account
 
1414
.REMARKS 
 
1415
---*/
 
1416
        char    *str;   /* IN: multicolumn specification (starting with `m') */
 
1417
{
 
1418
        int     nc, status;
 
1419
        DEPTH   *pm;
 
1420
        char    *p;
 
1421
 
 
1422
  for (p = str; *++p == '\0'; ) ;
 
1423
 
 
1424
  if (*p == '0')        /* Close Multicol Env */
 
1425
  {
 
1426
        do_init_line = tr_line(pd, 2, 1);
 
1427
        close_depth();
 
1428
        return(1);
 
1429
  }
 
1430
  
 
1431
  status = depth_buf->offset;
 
1432
  open_depth();                         /* Create a new depth */
 
1433
  pm = pd;
 
1434
  pd0 = (DEPTH *)(depth_buf->buf + status);     /* In case of expansion */
 
1435
  pd  = pd0 + 1 + pd0->col_no;
 
1436
  pd->flags |= JustificationDone;               /* Don't justify old columns */
 
1437
  
 
1438
  tex_getparm(1);       /* Number of columns */
 
1439
  nc = atoi(htex.ap);   
 
1440
  pm->flags |= ForceJustification;
 
1441
  pm->smart = 0;
 
1442
  status = OK;
 
1443
  
 
1444
  if ((int)(pd0->col_no + nc) > (int)pd0->cols)
 
1445
        status = NOK, nc = pd0->cols - pd0->col_no;
 
1446
  
 
1447
  if (nc < 1)
 
1448
        status = NOK, nc = 1;
 
1449
  
 
1450
  pd0->col_i = nc;      /* Increment for next column */
 
1451
 
 
1452
  pm->col_lim[0] = pd->col_lim[0];
 
1453
  pm->col_lim[1] = (pd + nc - 1)->col_lim[1];
 
1454
 
 
1455
 
 
1456
                        /* Modify the current line sketch */
 
1457
 
 
1458
  if (tr_line(pm, 1, 2))        clear_down(pm);
 
1459
 
 
1460
        /* Chose smart attr */
 
1461
        
 
1462
  ChoseSmart:
 
1463
  switch(*(p++))
 
1464
  { case '|': case ' ': 
 
1465
        if_not(iscntrl(*p))     goto ChoseSmart;        /* If |c| */
 
1466
    default : pm->smart = _JUSTIFY_, pm->flags &= ~ForceJustification;
 
1467
        break;
 
1468
    case 'l': pm->smart = _LEFT_;       break;
 
1469
    case 'r': pm->smart = _RIGHT_;      break;
 
1470
    case 'c': pm->smart = _CENTER_;     break;
 
1471
  }
 
1472
  while ( (*p == '|') || (*p == ' '))   p++;
 
1473
  --p;
 
1474
 
 
1475
                        /* Position at correct position */
 
1476
 
 
1477
  /* ws->pos = Position(i, pm->col_lim[0]); */
 
1478
 
 
1479
  if_not(status)        ERR_ED_STRING("Bad \\multicolumn ", htex.ap);
 
1480
 
 
1481
  return(p-str);
 
1482
}
 
1483
 
 
1484
/*==========================================================================
 
1485
 *                      tx_crule
 
1486
 *==========================================================================*/
 
1487
static int tx_crule()
 
1488
/*+++
 
1489
.PURPOSE Draw a horizontal rule some columns (\crule).
 
1490
.RETURNS OK / NOK (Bad column)
 
1491
.REMARKS Argument normally contains 2 parameters separated by a dash.
 
1492
---*/
 
1493
{
 
1494
        int     i, len, status;
 
1495
        short   lim[2], alim[2];
 
1496
        char    *p;
 
1497
        DEPTH   *pd;
 
1498
 
 
1499
  status = NOK;         /* Default status */
 
1500
  pd0->col_no = 0;
 
1501
  i = CurrentLine();
 
1502
  if (rule_lines)       i--, ws->pos -= ws->dim[1];
 
1503
 
 
1504
  if (BottomReached())  FINISH;
 
1505
  
 
1506
  len = 0;
 
1507
  tex_getparm(1);
 
1508
 
 
1509
  p = htex.ap;
 
1510
 
 
1511
  alim[0] = pd0->col_no + 1;    /* Column Number */
 
1512
  alim[1] = alim[0];
 
1513
  
 
1514
  if (*p)       /* There are parameters */
 
1515
  {
 
1516
        p += strloc(p, '-');
 
1517
        if (*p == '-')  alim[0] = atoi(htex.ap), 
 
1518
                        alim[1] = atoi(++p);    /* Two Parameters */
 
1519
        else            alim[1] = alim[0] + atoi(htex.ap);
 
1520
  }                                             
 
1521
  if (  (alim[0] < 1)           ||
 
1522
        (alim[1] < alim[0])     ||
 
1523
        (alim[1] > (int)pd0->cols))
 
1524
                { ERR_ED_STRING("Bad \\crule ", htex.ap); FINISH; }
 
1525
 
 
1526
  full_width(pd0 + alim[0], lim);       /* lim[0] = Left  */
 
1527
 
 
1528
  if (alim[0] > 1)      /* Check if preceding column has a Right Bar */
 
1529
  {     pd = pd0 + (alim[0] - 1);
 
1530
        if (pd->smart & _RIGHT_BAR_)    lim[0] -= 1;
 
1531
  }
 
1532
 
 
1533
  full_width(pd0 + alim[1], alim);      /* alim[1] = Right */
 
1534
 
 
1535
  len = alim[1] - lim[0];
 
1536
 
 
1537
  i = CurrentLine(); 
 
1538
  if (len > 0)  ws->pos = Position(i, lim[0]),
 
1539
                tw_rule(ws, _RIGHT_, len);
 
1540
                
 
1541
  ++i;          ws->pos = Position(i, 0);
 
1542
  nltab();      rule_lines = 1;
 
1543
  status = OK;
 
1544
 
 
1545
  FIN:
 
1546
  return(status);
 
1547
}
 
1548
 
 
1549
/*==========================================================================
 
1550
 *                      tx_rule
 
1551
 *==========================================================================*/
 
1552
static int tx_rule()
 
1553
/*+++
 
1554
.PURPOSE Draw a horizontal rule over the complete window / table.
 
1555
.RETURNS OK / NOK (Window full)
 
1556
.REMARKS 
 
1557
---*/
 
1558
{
 
1559
        int     i;
 
1560
        
 
1561
  if (BottomReached())  return(NOK);
 
1562
  if (blank_lines == 0) tx_nl();
 
1563
  if (do_init_line)     init_line();
 
1564
 
 
1565
  pd0->col_no = 0;
 
1566
  i = CurrentLine();
 
1567
 
 
1568
        /* Now replace blanks by horizontal bars */
 
1569
        
 
1570
  ws->pos = Position(i, pd0->col_lim[0]);
 
1571
  tw_rule(ws, _RIGHT_, pd0->col_lim[1] - pd0->col_lim[0]) ; 
 
1572
 
 
1573
  ++i;          ws->pos = Position(i, 0);
 
1574
  nltab();      rule_lines = 1;
 
1575
 
 
1576
  return(OK);
 
1577
}
 
1578
 
 
1579
/*==========================================================================
 
1580
 *                      tx_mark
 
1581
 *==========================================================================*/
 
1582
static int tx_mark()
 
1583
/*+++
 
1584
.PURPOSE Mark the starting point of a field.
 
1585
.RETURNS OK / NOK (Window full)
 
1586
.REMARKS 
 
1587
---*/
 
1588
{
 
1589
        int     i, l;
 
1590
        
 
1591
        /* Save Field name, Field Type, Field Picture   */
 
1592
 
 
1593
  for (i = 1; i <= 3; i++)
 
1594
  {     tex_getparm(i);         /* Get Param    */
 
1595
        l = strlen(htex.ap);    /* Param Length */
 
1596
        BUF_AppendItems(&field_names, char, htex.ap, l+1);
 
1597
  }
 
1598
  
 
1599
  
 
1600
        /* Save current column position */
 
1601
  
 
1602
  BUF_AppendItems(&field_def, short int, &pd->col_lim[0], 2);
 
1603
  
 
1604
  pd->flags |= InField;         /* Next output will be flagged */
 
1605
  marked  = 0;                  /* Count of marked bytes        */
 
1606
 
 
1607
  return(OK);
 
1608
}
 
1609
 
 
1610
/*==========================================================================
 
1611
 *                      get_marked
 
1612
 *==========================================================================*/
 
1613
static int get_marked(st)
 
1614
/*+++
 
1615
.PURPOSE Retrieve marked fields.
 
1616
.RETURNS Number of fields
 
1617
.REMARKS If a field lies over several lines, complete lines are assumed.
 
1618
---*/
 
1619
        int     st;     /* IN: Completion Status of Field       */
 
1620
{
 
1621
        char    *fname;         /* Field Name           */
 
1622
        TWFIELD *fdef;          /* Field Definition     */
 
1623
        short   *f, *fe;        /* Current Column       */
 
1624
        ACHAR   *pa;
 
1625
        short   i, j;
 
1626
        char    **stored_address;
 
1627
        BUFFER  *b;
 
1628
        MID_STATIC      TWFIELD twfield0 = {(char *)0};
 
1629
 
 
1630
        /* Issue Error Message if Bad Status */
 
1631
 
 
1632
  if (st == NOK)
 
1633
  {     ERROR("The Form doesn't fit on the Window...");
 
1634
        return(0);
 
1635
  }
 
1636
 
 
1637
        /* Allocate first the Field Buffer connected with window */
 
1638
 
 
1639
  if_not(Fields(ws))
 
1640
  {     Fields(ws) = BUF_Open(char, field_names.used + 
 
1641
                sizeof(TWFIELD)*(1 + field_def.used / (3*sizeof(short int))), 
 
1642
                8*sizeof(TWFIELD));
 
1643
  }
 
1644
  b = Fields(ws);
 
1645
  BUF_Clear(b);
 
1646
 
 
1647
        /* ... and retrieve fields successively */
 
1648
 
 
1649
  f  = (short int *)(field_def.buf);            /* First column range */
 
1650
  fe = (short int *)(field_def.buf + field_def.used);
 
1651
 
 
1652
  for (; f < fe; f += 3)
 
1653
  {     fdef = BUF_AllocateItem(b, TWFIELD);
 
1654
 
 
1655
        fdef->dim[1] = f[1] - f[0];     /* Field Width */
 
1656
        fdef->dim[1] = MIN(fdef->dim[1], f[2]);
 
1657
 
 
1658
        i = 0, j = f[0], pa = Aij(ws, 0, j);
 
1659
        
 
1660
        while (!(*pa & _MARKER1_))      /* Find Start of Marked Text */
 
1661
        {       if (++j >= f[1])
 
1662
                {       j = f[0], i++, pa = Aij(ws, i, j);
 
1663
                        if (i >= Lines())       break;  /* Bottom of Window */
 
1664
                }
 
1665
                else    pa++;
 
1666
        }
 
1667
        if (i >= Lines())
 
1668
        {       b->used -= sizeof(TWFIELD);
 
1669
                break;  /* Bottom of Window */
 
1670
        }
 
1671
        *pa &= ~_MARKER1_;
 
1672
 
 
1673
        fdef->home[0] = i, fdef->home[1] = j;
 
1674
        fdef->dim[0] = (f[2] + fdef->dim[1] -1)/fdef->dim[1];
 
1675
  }
 
1676
  
 
1677
  i = b->used / sizeof(TWFIELD);                /* Number of Fields */
 
1678
 
 
1679
  BUF_AppendItem(b, TWFIELD, &twfield0);        /* End indicator */
 
1680
 
 
1681
 
 
1682
        /* Copy now the Names into the Buffer associated to Window */
 
1683
        
 
1684
  b->offset = b->used;                          /* Mark beginning of names */
 
1685
  BUF_AppendItems(b, char, field_names.buf, field_names.used);
 
1686
  
 
1687
        /* Indicate positions of names  */
 
1688
        
 
1689
  fdef = (TWFIELD *)(b->buf);
 
1690
  fname= b->buf + b->offset;            /* First name address */
 
1691
  
 
1692
  for (j = i; --j >= 0; fdef++)
 
1693
  {     for (stored_address = &(fdef->name); 
 
1694
             stored_address <= (&fdef->pic); stored_address++)
 
1695
                *stored_address = fname, 
 
1696
                fname += 1 + strlen(fname);
 
1697
  }
 
1698
 
 
1699
  return(i);
 
1700
}
 
1701
 
 
1702
/*==========================================================================
 
1703
 *                      tx_finish
 
1704
 *==========================================================================*/
 
1705
static int tx_finish(st)
 
1706
/*+++
 
1707
.PURPOSE Terminate Display: actions of \vfill's, non-terminated tables,
 
1708
                retrieve marked fields.
 
1709
.RETURNS st  
 
1710
.REMARKS 
 
1711
---*/
 
1712
        int     st;     /* IN: Status as OK / NOK / EOF */
 
1713
{
 
1714
  ENTER("tx_finish");
 
1715
 
 
1716
  if (hfill_no) tx_hfil();
 
1717
 
 
1718
        /* Insert supplementary blank lines     */
 
1719
 
 
1720
  if(vfill_no > 0) 
 
1721
        tx_vfil(), vfill_no = 0;
 
1722
 
 
1723
        /* Get the Marked Lines */
 
1724
 
 
1725
  if (field_def.used)   get_marked(st);
 
1726
  
 
1727
  if ( (st == OK) && (depth_buf->offset > sizeof(int)))
 
1728
        ERROR("Missing } or \\end");
 
1729
        
 
1730
  if (WindowIsActive)   ActiveWindow(ws);
 
1731
 
 
1732
  EXIT(st);
 
1733
}
 
1734
 
 
1735
/*==========================================================================
 
1736
 *                      tx_option
 
1737
 *==========================================================================*/
 
1738
int tx_option(opt)
 
1739
/*+++
 
1740
.PURPOSE Change options.
 
1741
.RETURNS Old options.
 
1742
.REMARKS 
 
1743
---*/
 
1744
        int     opt;    /* IN: New option 0 = Don't Center      */
 
1745
{
 
1746
        int     old_opt;
 
1747
  
 
1748
  old_opt = txopt;
 
1749
  txopt = opt;
 
1750
  return(old_opt);
 
1751
}
 
1752
 
 
1753
/*==========================================================================
 
1754
 *                      tx_symbol
 
1755
 *==========================================================================*/
 
1756
char *tx_symbol(str)
 
1757
/*+++
 
1758
.PURPOSE Retrieve the translation of a definition
 
1759
.RETURNS Pointer to the translated definition
 
1760
.REMARKS 
 
1761
---*/
 
1762
        char    *str;   /* IN: String to translate      */
 
1763
{
 
1764
  return(tex_symbol(str));
 
1765
}
 
1766
 
 
1767
int tx_def(symbol, synonym)
 
1768
/*+++
 
1769
.PURPOSE Set a symbol in the TeX definitions.
 
1770
.RETURNS 1
 
1771
.REMARKS 
 
1772
---*/
 
1773
        char    *symbol;        /* IN: Symbol to define */
 
1774
        char    *synonym;       /* IN: Equivalence      */
 
1775
{
 
1776
        char    *def, *p;
 
1777
        
 
1778
  tx_tex();                     /* Install the TeX structure */
 
1779
 
 
1780
  def = MEM_GET(char, 12  + strlen(symbol) + strlen(synonym));
 
1781
  
 
1782
  p = def + strcopy(def, "\\def");
 
1783
  if (*symbol != '\\')  *(p++) = '\\';
 
1784
  p += strcopy(p, symbol);
 
1785
  p += strcopy(p, "{");
 
1786
  p += strcopy(p, synonym);
 
1787
  p += strcopy(p, "}");
 
1788
  
 
1789
#if DEBUG
 
1790
  LOG_ED_STRING("Added: ", def);
 
1791
#endif
 
1792
  status = TeX_Execute(&htex, def, strlen(def));
 
1793
  MEM_FREE(def);
 
1794
  
 
1795
  return(1);
 
1796
}
 
1797
 
 
1798
/*==========================================================================
 
1799
 *                      tx_display
 
1800
 *==========================================================================*/
 
1801
int tx_display(w, str, len, clear_option)
 
1802
/*+++
 
1803
.PURPOSE Display a text on the window.
 
1804
.RETURNS --- OK (no remaining text)
 
1805
        --- NOK (text did not fit on the window)
 
1806
        --- EOF: the \EOF macro was fond in the text.
 
1807
.REMARKS 
 
1808
---*/
 
1809
        WINDOW  *w;     /* IN: Window to echo the processed text */
 
1810
        char    *str;   /* IN: text to display, or NULL (continuation )*/
 
1811
        int     len;    /* IN: Length of text   */
 
1812
        int     clear_option;   /* IN: Option 1 to clear window \
 
1813
                                        before display  */
 
1814
{
 
1815
        register int    status;
 
1816
 
 
1817
  ENTER("tx_display");
 
1818
 
 
1819
#if DEBUG
 
1820
  TRACE_ED_STR2("String to display:", str, len);
 
1821
#endif
 
1822
 
 
1823
  ws = w;
 
1824
  tx_init(str, clear_option);
 
1825
 
 
1826
 
 
1827
        /* Execute TeX. The routines tx_out collects the words
 
1828
         * for output, while tx_action is triggered for each action.
 
1829
         */
 
1830
 
 
1831
  status = TeX_Execute(&htex, str, len);
 
1832
 
 
1833
        /* Terminate: vfill adjustments, non-terminated tables,
 
1834
         * and retrieve marked fields
 
1835
         */
 
1836
 
 
1837
  tx_finish(status);
 
1838
 
 
1839
  EXIT(status);
 
1840
 
 
1841
}
 
1842
 
 
1843
/*==========================================================================
 
1844
 *                      tx_mdisplay
 
1845
 *==========================================================================*/
 
1846
int tx_mdisplay(w, str, nstrings, clear_option)
 
1847
/*+++
 
1848
.PURPOSE Display a text on the window made of several pieces of text.
 
1849
        The pieces are provided by the array of strings str made of
 
1850
        (2*nstrings) pointers, specifying nstrings times (start, end).
 
1851
        (a pointer to the end of a string is the byte just following
 
1852
        the last byte of the string, i.e. the address of the null character
 
1853
        for a standard string)
 
1854
.RETURNS --- OK (no remaining text)
 
1855
        --- NOK (text did not fit on the window)
 
1856
        --- EOF: the \EOF macro was fond in the text.
 
1857
.REMARKS 
 
1858
---*/
 
1859
        WINDOW  *w;     /* IN: Window to echo the processed text */
 
1860
        char    **str;  /* IN: Array of strings to display, \
 
1861
                                as n* (start, end) */
 
1862
        int     nstrings; /* IN: Number of strings      */
 
1863
        int     clear_option;   /* IN: Option 1 to clear window \
 
1864
                                        before display  */
 
1865
{
 
1866
        register int    status;
 
1867
 
 
1868
  ENTER("tx_mdisplay");
 
1869
 
 
1870
#if DEBUG
 
1871
  TRACE_ED_I("Number of string to display:", nstrings);
 
1872
#endif
 
1873
 
 
1874
  ws = w;
 
1875
  tx_init(str, clear_option);
 
1876
 
 
1877
 
 
1878
        /* Execute TeX. The routines tx_out collects the words
 
1879
         * for output, while tx_action is triggered for each action.
 
1880
         */
 
1881
 
 
1882
  status = TeX_ExecuteArray(&htex, str, nstrings);
 
1883
 
 
1884
        /* Terminate: vfill adjustments, non-terminated tables,
 
1885
         * and retrieve marked fields
 
1886
         */
 
1887
 
 
1888
  tx_finish(status);
 
1889
 
 
1890
  EXIT(status);
 
1891
 
 
1892
}
 
1893
 
 
1894
/*==========================================================================
 
1895
 *                      tx_fdisplay
 
1896
 *==========================================================================*/
 
1897
int tx_fdisplay(w, fid, len, clear_option)
 
1898
/*+++
 
1899
.PURPOSE Display a file extract on the window.
 
1900
.RETURNS --- OK (no remaining text)
 
1901
        --- NOK (text did not fit on the window)
 
1902
        --- EOF the \EOF macro was found in the text.
 
1903
.REMARKS 
 
1904
---*/
 
1905
        WINDOW  *w;     /* IN: Window to echo the processed text        */
 
1906
        int     fid;    /* IN: File number (opened by fi_open)  */
 
1907
        int     len;    /* IN: Maximal number of bytes to read  */
 
1908
        int     clear_option;   /* IN: Option 1 to clear window \
 
1909
                                        before display  */
 
1910
{
 
1911
        register int    status;
 
1912
 
 
1913
  ENTER("tx_fdisplay");
 
1914
 
 
1915
  ws = w;
 
1916
  tx_init(blanks, clear_option);        /* Non-null char pointer */
 
1917
 
 
1918
        /* Load text to process */
 
1919
 
 
1920
  TeX_Load(&htex, fid, len);
 
1921
 
 
1922
        /* Execute TeX. The routines tx_out collects the words
 
1923
         * for output, while tx_action is triggered for each action.
 
1924
         */
 
1925
 
 
1926
  status = TeX_Continue(&htex);
 
1927
 
 
1928
        /* Terminate: vfill adjustments, non-terminated tables,
 
1929
         * and retrieve marked fields
 
1930
         */
 
1931
 
 
1932
  tx_finish(status);
 
1933
 
 
1934
  EXIT(status);
 
1935
 
 
1936
}
 
1937
 
 
1938
/*==========================================================================
 
1939
 *                      tx_file
 
1940
 *==========================================================================*/
 
1941
int tx_file(w, fname, clear_option)
 
1942
/*+++
 
1943
.PURPOSE Display a complete file extract on the window.
 
1944
.RETURNS --- OK (no remaining text)
 
1945
        --- NOK (text did not fit on the window)
 
1946
        --- EOF the \EOF macro was found in the text.
 
1947
.REMARKS 
 
1948
---*/
 
1949
        WINDOW  *w;     /* IN: Window to echo the processed text        */
 
1950
        char    *fname; /* IN: File name        */
 
1951
        int     clear_option;   /* IN: Option 1 to clear window \
 
1952
                                        before display  */
 
1953
{
 
1954
        register int    status;
 
1955
 
 
1956
  ENTER("tx_file");
 
1957
 
 
1958
  ws = w;
 
1959
  tx_init(fname, clear_option); /* Non-null char pointer */
 
1960
 
 
1961
        /* Load text to process */
 
1962
 
 
1963
  TeX_Include(&htex, fname);
 
1964
 
 
1965
        /* Execute TeX. The routines tx_out collects the words
 
1966
         * for output, while tx_action is triggered for each action.
 
1967
         */
 
1968
 
 
1969
  status = TeX_Continue(&htex);
 
1970
 
 
1971
        /* Terminate: vfill adjustments, non-terminated tables,
 
1972
         * and retrieve marked fields
 
1973
         */
 
1974
 
 
1975
  tx_finish(status);
 
1976
 
 
1977
  EXIT(status);
 
1978
 
 
1979
}
 
1980
 
 
1981
/*==========================================================================
 
1982
 *                      tx_fields
 
1983
 *==========================================================================*/
 
1984
TWFIELD *tx_fields(w)
 
1985
/*+++
 
1986
.PURPOSE Retrieve the marked fields in a window.
 
1987
.RETURNS Address of first TWFIELD / null pointer if no field was defined.
 
1988
.REMARKS The last valid field is followed by a null name, i.e. (char *)0.
 
1989
---*/
 
1990
        WINDOW *w;      /* IN: Window concerned */
 
1991
{
 
1992
        TWFIELD *f;
 
1993
        BUFFER  *b;
 
1994
 
 
1995
  ENTER("*tx_fields");
 
1996
 
 
1997
  f = NULL_PTR(TWFIELD);
 
1998
  
 
1999
  b = Fields(w);
 
2000
  if (b)        
 
2001
        if (b->used)    f = (TWFIELD *)b->buf;
 
2002
  
 
2003
  EXIT_PTR(TWFIELD, f);
 
2004
}
 
2005
 
 
2006
/*==========================================================================
 
2007
 *                      tx_more
 
2008
 *==========================================================================*/
 
2009
char *tx_more(name)
 
2010
/*+++
 
2011
.PURPOSE Retrieve the `more' (between \begin{more}{name} and \end{more})
 
2012
.RETURNS Address of code / NULL if none
 
2013
.REMARKS When `name' is NULL, return the NEXT more value as the
 
2014
        two strings concatenated.
 
2015
---*/
 
2016
        char    *name;  /* IN: `more' name to find */
 
2017
{
 
2018
        char    *p;
 
2019
        int     i, *pi;
 
2020
        
 
2021
  ENTER("*tx_more");
 
2022
 
 
2023
  if (!name)  {         /* Get the Next one */
 
2024
        if (oMore.offset >= oMore.used) {
 
2025
                oMore.offset = 0;
 
2026
                EXIT_PTR(char, 0);      /* Indicates End */
 
2027
        }
 
2028
        pi = (int *)(oMore.buf + oMore.offset);
 
2029
        oMore.offset += sizeof(int);
 
2030
        p = More.buf + *pi;
 
2031
        EXIT_PTR(char, p);
 
2032
  }
 
2033
  for (i=SET_Items(&oMore, int), pi=SET_FirstItem(&oMore, int); --i >= 0; pi++)
 
2034
  {
 
2035
        p = More.buf + *pi;
 
2036
        if (strcomp(name, p) == 0)      break;          /* Topic Found */
 
2037
  }
 
2038
  if (i < 0)    p = NULL_PTR(char);
 
2039
  else          p += 1 + strlen(name);
 
2040
 
 
2041
  
 
2042
  EXIT_PTR(char, p);
 
2043
}
 
2044
 
 
2045
/*==========================================================================
 
2046
 *                      tx_math
 
2047
 *==========================================================================*/
 
2048
int tx_math(f)
 
2049
/*+++
 
2050
.PURPOSE Define an action routine in case of mathematical symbols
 
2051
        ($ ^ _)
 
2052
.RETURNS OK 
 
2053
.REMARKS Use NULL_FCT to take standard action (ignore)
 
2054
---*/
 
2055
        int (*f)();     /* IN: Function with arguments (string, length) \
 
2056
                          to call when $ ^ _ are encountered */
 
2057
{
 
2058
  external_action = f;
 
2059
  
 
2060
  return(OK);
 
2061
}
 
2062
 
 
2063
/*==========================================================================
 
2064
 *                      tx_out
 
2065
 *==========================================================================*/
 
2066
int tx_out(str, len)
 
2067
/*+++
 
2068
.PURPOSE This is the output routine.
 
2069
.RETURNS Number of bytes processed.
 
2070
.REMARKS 
 
2071
---*/
 
2072
        char    *str;           /* text to output       */
 
2073
        int     len;            /* Length of text       */
 
2074
{
 
2075
        int     output_bytes, j, m;
 
2076
 
 
2077
/*  ENTER("tx_out"); */
 
2078
 
 
2079
#if DEBUG
 
2080
        TRACE_ED_STR2("Output=>",str,len);
 
2081
#endif
 
2082
 
 
2083
  if (inaux)
 
2084
  {     BUF_AppendItems(inaux, char, str, len);
 
2085
        j = inaux->used;        /* Save */
 
2086
        BUF_AppendItem(inaux, char, &zero);
 
2087
        inaux->used = j;        /* Restore */
 
2088
        return(len);
 
2089
  }
 
2090
 
 
2091
  output_bytes = 0;
 
2092
  if (len < 0)          FINISH;
 
2093
  tx_set();
 
2094
 
 
2095
  j = CurrentColumn();
 
2096
  
 
2097
  if (j < pd->col_lim[0]) {             /* Position at Left Margin      */
 
2098
        if (pd->flags & AnchoredPosition) ;
 
2099
        else    ws->pos += pd->col_lim[0] - j,
 
2100
                j = pd->col_lim[0];
 
2101
  }
 
2102
  else  pd->flags &= ~AnchoredPosition;
 
2103
 
 
2104
  if (BottomReached())  FINISH;
 
2105
 
 
2106
  if ((htex.mode != _TeX_VERBATIM_) && (j + len > pd->col_lim[1]))
 
2107
                                /* Doesn't fit on the line ... */
 
2108
  {     tx_smart();
 
2109
        if (blank_lines == 0)   tx_nl();
 
2110
        if (BottomReached())    FINISH;
 
2111
        j = pd->col_lim[0];
 
2112
        ws->pos += j;
 
2113
  }
 
2114
  m = ws->pos;                          /* Position for marker */
 
2115
  output_bytes = Write(ws, str, len);
 
2116
 
 
2117
  if (output_bytes > 0)
 
2118
  {     last_issued_char = *(str+output_bytes-1);
 
2119
        blank_lines = 0;        rule_lines = 0;
 
2120
        if ((j + len) == Columns())     /* On a new line... */
 
2121
                blank_lines++, last_issued_char = ' ';
 
2122
        if (pd->flags & InField)
 
2123
                Mark(m, output_bytes);
 
2124
  }
 
2125
 
 
2126
  FIN:
 
2127
 /* EXIT(output_bytes); */
 
2128
  return(output_bytes); 
 
2129
}
 
2130
 
 
2131
/*==========================================================================
 
2132
 *                      tx_action
 
2133
 *==========================================================================*/
 
2134
int tx_action(str, len)
 
2135
/*+++
 
2136
.PURPOSE This is the action routine.
 
2137
.RETURNS Number of bytes processed.
 
2138
.REMARKS 
 
2139
---*/
 
2140
        char    *str;           /* text to output       */
 
2141
        int     len;            /* Length of text       */
 
2142
{
 
2143
        char    *p, *pe;
 
2144
        int     i, j;
 
2145
        unsigned char old_attr;
 
2146
        MID_STATIC  char fill_error[] = "Too many \\vfill's";
 
2147
        MID_STATIC  char no_math_action[] = "`$' ignored";
 
2148
        MID_STATIC  char bad_action[] = "`$' action stopped";
 
2149
 
 
2150
  /* ENTER("tx_action"); */
 
2151
 
 
2152
#if DEBUG
 
2153
        TRACE_ED_STR2("Action: ",str,len);
 
2154
#endif
 
2155
 
 
2156
  p = str, pe = str+len;
 
2157
  tx_set();
 
2158
 
 
2159
  for (; p < pe; p++) switch(*p)
 
2160
  { case '0':           /* begin / end Environment */
 
2161
        if (*htex.ap == _TeX_BEGIN_)    /* New env. */
 
2162
                if_not(open_env())      FINISH;
 
2163
                else;
 
2164
        else    if (*htex.ap == _TeX_END_)      /* Close env. */
 
2165
                if_not(close_env())     FINISH;
 
2166
                else;
 
2167
        else;
 
2168
        break;
 
2169
 
 
2170
    case '{' :          /* New Depth */
 
2171
        if (BottomReached())    FINISH;
 
2172
        open_depth();
 
2173
        break;
 
2174
 
 
2175
    case '}':           /* Old depth    */
 
2176
        close_depth();
 
2177
        break;
 
2178
 
 
2179
    case '\0': case '\\': /* NUL's may be found after macro substitutions */
 
2180
        continue;
 
2181
 
 
2182
    case '$': case '^': case '_':       /* Mathematical symbols */
 
2183
        if (external_action)
 
2184
        {       if_not(i = (*external_action)(p, pe-p))
 
2185
                        FINISH;
 
2186
                p += i-1;
 
2187
        }
 
2188
        else    no_math_action[1] = *p, WARNING(no_math_action);
 
2189
        break;
 
2190
 
 
2191
    case ' ':           /* Stretchable blank */
 
2192
        if(inaux)       
 
2193
        {       if ((inaux->used) && (inaux->buf[inaux->used-1] != ' '))
 
2194
                        tx_out(blanks, 1);
 
2195
        }
 
2196
        else            tx_blank();     /* Always possible   */
 
2197
        break;
 
2198
 
 
2199
    case '\r':          /* New Line     */
 
2200
    case_newline:
 
2201
        if (inaux)      { tx_out("\n", 1); break; }
 
2202
        if (blank_lines == 0)   tx_nl() ;
 
2203
        if (pd->env == 't')     tx_set(), nltab();
 
2204
        break;
 
2205
 
 
2206
    case '\n':          /* New paragraph */
 
2207
        if(inaux)       { tx_out("\n", 1); break; }
 
2208
        while (blank_lines <= 1)
 
2209
        {       if (BottomReached())    break;
 
2210
                tx_nl() ;
 
2211
        }
 
2212
        break;
 
2213
 
 
2214
    case '/':           /* Skip Line */
 
2215
        if(inaux)       { tx_out("\n", 1); break; }
 
2216
        if(blank_lines == 0)    tx_nl() ;
 
2217
        tx_nl() ;
 
2218
        break;
 
2219
 
 
2220
    case '&':           /* Tab in Tabular, or `tab' outside     */
 
2221
        if(inaux)       { tx_out("&", 1); break; }
 
2222
        if (pd->env == 't')
 
2223
        {
 
2224
                if (CurrentColumn() > pd->col_lim[0])
 
2225
                        tx_smart(),
 
2226
                        pd->line_lim[1] += 1;
 
2227
                pd0->line_lim[1] = MAX(pd0->line_lim[1], pd->line_lim[1]);
 
2228
 
 
2229
                if (hfill_no)   tx_hfil();      /* Horizontal Fill */
 
2230
                j = pd0->col_no;                /* save in case bad & */
 
2231
                pd0->col_no += pd0->col_i;      /* Increment column */
 
2232
                pd0->col_i  = 1;
 
2233
                if (pd0->col_no >= pd0->cols) {
 
2234
                    WARNING("Too many &'s"); 
 
2235
                    pd0->col_no  = j;           /* Restore ...  */
 
2236
                    goto case_newline; 
 
2237
                }
 
2238
                tx_set();
 
2239
                ws->pos = Position(pd0->line_lim[0], pd->col_lim[0]);
 
2240
                break;
 
2241
        }
 
2242
    case 't':   /* Put a Tab */
 
2243
        if(inaux)       { tx_out("\t", 1); break; }
 
2244
        tx_blank();                     /* At least one blank   */
 
2245
        tabright(blanks, 0);            /* Go to next tab       */
 
2246
        break;
 
2247
 
 
2248
    case 'b':
 
2249
        Bell(); /* Ring Bell    */
 
2250
        break;
 
2251
 
 
2252
    case 'f':                   /* Fill vertical or horizontal */
 
2253
        if(inaux)       break; 
 
2254
        fill_error[10] = *++p;
 
2255
        if (*p == 'v')  /* Vertical Fill        */
 
2256
        {       if (vfill_no >= MAX_MARKED)
 
2257
                {       ERROR(fill_error);
 
2258
                        continue;
 
2259
                }
 
2260
                if(blank_lines == 0)    tx_nl() ;
 
2261
                vfill[vfill_no++] = CurrentLine();
 
2262
        }
 
2263
        else                    /* Horizontal Fill      */
 
2264
        {       if (hfill_no >= MAX_MARKED)
 
2265
                {       ERROR(fill_error);
 
2266
                        continue;
 
2267
                }
 
2268
                hfill[hfill_no++] = CurrentColumn();
 
2269
        }
 
2270
        continue;
 
2271
 
 
2272
    case 'F':                   /* Mark Field  or Redefine Columns */
 
2273
        if(inaux)       break;
 
2274
        if (BottomReached())    FINISH;
 
2275
        switch(*++p)
 
2276
        { case 's':     tx_mark();      /* Start */
 
2277
                break;
 
2278
          case 'e':                     /* End Field */
 
2279
                if (marked == 0)        /* Null Field: At least one byte! */
 
2280
                        tx_out(blanks, 1);
 
2281
                BUF_AppendItem(&field_def, short, &marked);     /* Length */
 
2282
                pd->flags &= ~InField;
 
2283
                break;
 
2284
          case 't':                     /* Redefine Columns in a Table */
 
2285
                close_table();
 
2286
                close_depth(),  open_depth();
 
2287
                j = ws->pos;
 
2288
                if ((rule_lines) && (ws->pos >= ws->dim[1]))
 
2289
                        ws->pos -= ws->dim[1];
 
2290
                open_table();
 
2291
                tx_set();
 
2292
                if(rule_lines)  tx_rule();
 
2293
                else            nltab();
 
2294
                ws->pos = j;
 
2295
                break;
 
2296
        }
 
2297
        break;
 
2298
 
 
2299
    case 'J':   /* Justification specifications */
 
2300
        if (BottomReached())    FINISH;
 
2301
        switch(*++p)
 
2302
        { case 'l': pd->smart = _LEFT_;         break;
 
2303
          case 'r': pd->smart = _RIGHT_;        break;
 
2304
          case 'c': pd->smart = _CENTER_;       break;
 
2305
          case 'j': pd->smart = _JUSTIFY_;      break;
 
2306
          case 'f': pd->flags |= ForceJustification;    break;
 
2307
          case 't': inaux = &aux; BUF_Clear(inaux);     break; /* Justfy Tab */
 
2308
          case '0': /* End Tab   */
 
2309
                if (tabright(aux.buf, aux.used) != aux.used)
 
2310
                        { --p; FINISH; }
 
2311
                inaux = NULL_PTR(BUFFER);
 
2312
                break;
 
2313
          default : tx_smart();         break;
 
2314
        }
 
2315
        break;
 
2316
 
 
2317
    case 'M':   /* Move Margins */
 
2318
        if(inaux)       break;
 
2319
        switch(*++p)
 
2320
        { case 'l': pd->col_lim[0] += MARGIN;           break;
 
2321
          case 'r': pd->col_lim[1] -= MARGIN;           break;
 
2322
          case 'L': pd->col_lim[0] -= MARGIN;           break;
 
2323
          case 'R': pd->col_lim[1] += MARGIN;           break;
 
2324
          case 'i':             /* Item */
 
2325
                if_not(tx_item())       { p--; FINISH;}
 
2326
                break;
 
2327
          case 'I':             /* indent */
 
2328
                tx_out(blanks, MARGIN);
 
2329
                continue;
 
2330
          case 'h':             /* hspace */
 
2331
                tex_getparm(1); i = atoi(htex.ap); j = CurrentColumn();
 
2332
                if (j < pd->col_lim[0]) j = pd->col_lim[0];
 
2333
                if (i < 0) {    /* Left Move */
 
2334
                        j += i; 
 
2335
                        if (j < 0)      j = 0;
 
2336
                        i = CurrentLine();
 
2337
                        ws->pos = Position(i,j);
 
2338
                        pd->flags |= AnchoredPosition;
 
2339
                        continue;
 
2340
                }
 
2341
                for ( ; i > 0; i--)
 
2342
                {       if_not(tx_out(blanks, 1))       FINISH;
 
2343
                        j = MIN(pd->col_lim[1] - CurrentColumn(), i-1);
 
2344
                        if (j > 0)
 
2345
                        {       j = MIN(j, sizeof(blanks));
 
2346
                                tx_out(blanks, j);
 
2347
                                i -= j;
 
2348
                        }
 
2349
                }
 
2350
                continue;
 
2351
          case 'V':             /* Test remaining lines */
 
2352
                tex_getparm(1);
 
2353
                i = atoi(htex.ap);
 
2354
                if (i >= Lines())       continue;
 
2355
                if ((ws->pos + i*Columns()) <= ws->marker[1])
 
2356
                                        continue;
 
2357
                p = str;        /* Stop here, tx_action will return 0 */
 
2358
                FINISH; 
 
2359
          case 'H':             /* Test remaining cols */
 
2360
                tex_getparm(1);
 
2361
                i = atoi(htex.ap);
 
2362
                if ((CurrentColumn()+i) > pd->col_lim[1])
 
2363
                                tx_nl();
 
2364
                continue;
 
2365
        }
 
2366
        if (pd->col_lim[0] < 0)
 
2367
                pd->col_lim[0] = 0, ERROR("Negative Left Margin");
 
2368
        if (pd->col_lim[1] > Columns())
 
2369
                pd->col_lim[1] = Columns(), ERROR("Bad Right Margin");
 
2370
        continue;
 
2371
 
 
2372
    case 'm':   /* Multicolumn */
 
2373
        if(inaux)       break;
 
2374
        if (BottomReached())    FINISH;
 
2375
        p += multicol(p);
 
2376
        break;
 
2377
 
 
2378
    case 'r':
 
2379
        if(inaux)       break;
 
2380
        tx_crule();     tx_set();
 
2381
        continue;
 
2382
    case 'R':
 
2383
        if(inaux)       break;
 
2384
        tx_rule();      tx_set();
 
2385
        continue;
 
2386
 
 
2387
    case 'V':   /* Video Attributes */
 
2388
        if(inaux)       break;
 
2389
        old_attr = pd->attr;    /* Current Attribute */
 
2390
        switch(*++p)
 
2391
        { case 'B': i = old_attr | _BOLD_;      break;
 
2392
          case 'b': i = old_attr | _BLINK_;     break;
 
2393
          case 'u': i = old_attr | _UNDERSCORE_;break;
 
2394
          case 'r': i = old_attr | _REVERSE_;   break;
 
2395
          case 'R': i = old_attr ^ _REVERSE_;   break;
 
2396
          case 'n': i = 0;                      break;
 
2397
          default : i = old_attr;               break;
 
2398
        }
 
2399
        j = CurrentColumn();
 
2400
        pd->attr = i;
 
2401
        if (old_attr != pd->attr)       SetAttr(ws, pd->attr);
 
2402
        if (j <= pd->col_lim[0])        current_blank = ws->attr;
 
2403
        break;
 
2404
 
 
2405
    default:
 
2406
        bad_action[1] = *p, WARNING(bad_action);
 
2407
        p = str - 1;            /* Means EOF */
 
2408
        FINISH;
 
2409
  }
 
2410
 
 
2411
  FIN:
 
2412
  /* EXIT(p-str); */
 
2413
  return(p-str);
 
2414
}
 
2415
 
 
2416
/*==========================================================================
 
2417
 *                      tx_list
 
2418
 *==========================================================================*/
 
2419
int tx_list()
 
2420
/*+++
 
2421
.PURPOSE List, in the Log File, the list of macros
 
2422
.RETURNS Number of non-uused symbols
 
2423
.REMARKS For debugging purposes.
 
2424
---*/
 
2425
{
 
2426
        int n;
 
2427
 
 
2428
  ENTER("+tx_list");
 
2429
 
 
2430
  n = tex_list(&htex);
 
2431
 
 
2432
  EXIT(n);
 
2433
}