1
/*===========================================================================
2
Copyright (C) 1986-2009 European Southern Observatory (ESO)
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.
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.
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,
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
26
===========================================================================*/
28
/*+++++++++++++++++++++++++++
30
.IDENTIFICATION txdisplay.c
31
.AUTHOR Francois Ochsenbein [ESO-IPG]
33
.KEYWORDS Display ``TeX-like'' text
34
.ENVIRONMENT TermWindows
36
.COMMENTS This module contains routines to output a ``TeX-like'' text
37
on a window. A complete macro substitution is performed
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
46
The available macros are listed in the table.
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 \\
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
69
\multicolumn{2}{|c|}{{\em Line Justifications}} \\ \hline \hline
70
{\tt\b centerline\{{\em text}\}} & Issue a line with {\em text}
72
(see also {\tt center} environment)\\
73
{\tt\b leftline\{{\em text}\}} & Issue a line with {\em text}
75
(see also {\tt left} environment)\\
76
{\tt\b rightline\{{\em text}\}} & Issue a line with {\em text}
78
(see also {\tt right} environment)\\
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}
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}
98
{\tt\{enumerate\}} & Start an enumerated list;
99
{\tt\b item} starts each item \\
100
{\tt \{alphaenumerate\}} & Enumerated list using
102
{\tt \{Alphaenumerate\}} & Enumerated list using
104
{\tt \{more\}}\{{\em name}\} & Text which can be retrieved,
106
{\tt \{table\}\{{\em pos}\}\{{\em w}\}} &
108
See explanations in the text. \\
110
\multicolumn{2}{|c|}{{\em Environment-specific macros}} \\ \hline \hline
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
123
\multicolumn{2}{|c|}{{\em Miscellaneous}} \\ \hline \hline
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}\}}&
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}
144
{\bf Table Environment}
147
The 2 parameters of the {\tt\b begin\{table\}} or
148
{\tt\b columns} macros specify:
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}.
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.
175
{\bf more environment}
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})
182
The text between {\tt\b begin\{more\}\{Ccode\}} and {\tt\b end\{more\}}
183
will never be displayed on a window.
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} \\
193
\ &single stretchable blank &
197
\b n &new paragraph &
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 &
213
r &rule over one column &
215
R &rule all over table &
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.
228
Added CentreColumns, LeftColumns, RightColumns.
229
.VERSION 2.1 28-Sep-1987: For Forms, added Macros
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'
258
----------------------------------------------------------------------------*/
260
#define DEBUG 0 /* For debugging only */
262
#define PM_LEVEL LEVEL_TX
264
#include <midas_def.h>
276
#define HSIZE 300 /* Size of h-table */
279
extern int tv_bell();
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();
287
extern int pm_enter(), pm_iexit(), pm_tr2(), pm_ed_i();
289
extern int eh_ed_as(), eh_put1(), eh_put();
291
extern int tex_exec(), tex_unit(), tex_getparm(), tex_mexec();
292
extern int tex_input(), tex_load(), tex_list();
294
extern int tx_jr(), tx_jc(), tx_justify();
297
static char item_ed[3];
298
static char zero = EOS;
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 */
309
#define ForceJustification 0x01
310
#define NoJustification 0x02
311
#define JustificationDone 0x04
312
#define AnchoredPosition 0x08
316
short count; /* For enumerate */
319
static DEPTH *pd, *pd0; /* Pointer to current environment */
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
328
#define _MARKER1_ 0x8000 /* 2 markers are used to allow */
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])
339
/* Static variables used for communication between routines */
341
static TeX htex = { /* The TeX header */
342
NULL_PTR(H_TABLE), NULL_FCT(int), NULL_FCT(int), NULL_PTR(char),
345
static BUFFER *depth_buf = NULL_PTR(BUFFER);
347
static BUFFER line_buf = BUF_Init(char, 80);
348
/* This buffer contains the `blank' line */
350
static BUFFER field_names = BUF_Init(char, 128);
351
/* This buffer contains the Marked Field Names */
353
static BUFFER field_def = BUF_Init(short int, 48);
354
/* This buffer contains the Column Ranges of each field */
356
static BUFFER More = BUF_Init(char, 128);
357
/* This buffer contains the C Code in the Ccode env. */
359
static BUFFER aux = BUF_Init(char, 24);
360
/* This buffer contains the temporary output */
362
static BUFFER oMore = BUF_Init(int, 4);
363
/* This buffer contains the offsets in More env. */
365
static BUFFER *inaux = NULL_PTR(BUFFER); /* When output redirected */
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;
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];
382
static int (*external_action)() = NULL_FCT(int);
383
/* User-defined function for math symbols */
385
static WINDOW *ws = NULL_WINDOW; /* Used Window */
387
static ACHAR current_blank = ' '; /* Blank attr of begin of line */
389
static int txopt = 1; /* Centering Option */
391
int tx_out(), tx_action();
396
/*==========================================================================
398
*==========================================================================*/
401
.PURPOSE Positions in the current environment.
406
pd0 = BUF_ItemPosition(depth_buf, DEPTH), pd = pd0;
407
if (pd0->cols) pd += (1 + pd->col_no);
412
/*==========================================================================
414
*==========================================================================*/
415
static int init_line()
425
if (CurrentColumn() > 0) i++;
427
if (BottomReached()) FINISH;
429
for (j = 0; j < line_buf.used; j++)
431
if (line_buf.buf[j] == 1) ws->pos = i + j,
432
tw_rule(ws, _DOWN_, ws->dim[0]);
437
do_init_line = 0; /* Performed... */
442
/*==========================================================================
444
*==========================================================================*/
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
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}}\
460
\\def\\qquad{\\ \\ \\ \\ }\
461
\\def\\SkipLine{\03/\04}\
462
\\def\\bell{\03b\04}\
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}}\
508
htex.output = tx_out, htex.action = tx_action;
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);
520
/*==========================================================================
522
*==========================================================================*/
523
static int tx_init(str, clear_option)
525
.PURPOSE Initialisation: TeX, buffers, etc
527
.REMARKS Important actions as \03action\04
529
char *str; /* IN: String to display */
530
int clear_option; /* IN: Option to clear Window before display */
533
int old_offset, old_used;
539
if_not(depth_buf) /* Not yet initialized */
540
{ oscfill(blanks, sizeof(blanks), ' ');
541
if_not(depth_buf = BUF_Open(DEPTH, 24, 24))
543
if_not(htex.macros) tx_tex(); /* Initialise TeX macros */
546
/* Do all initialisations */
548
MARGIN = (Columns()+4)/10;
551
inaux = NULL_PTR(BUFFER);
552
last_issued_char = ' ';
553
BUF_Clear(&field_def);
554
BUF_Clear(&field_names);
558
if (Fields(ws)) BUF_Clear(Fields(ws));
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 ... */
564
WindowIsActive = (ws->flags & Echo);
567
if (clear_option) ClearWindow(ws);
568
blank_lines = (CurrentColumn() == 0 ? 1 : 0);
570
tw_uflag(ws, 1); /* Window completely modified */
573
/* Initialise: set flags, and if the text is starting (non-null str)
574
* initialize depth to zero, default justification, etc ... */
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;
587
BUF_StackItem(depth_buf, DEPTH, &column);
588
BUF_Clear(&line_buf);
593
/* Reset All Line Limits */
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))
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];
607
depth_buf->used = old_used;
608
depth_buf->offset = old_offset ;
611
SetAttr(ws, pd0->attr);
612
current_blank = ws->attr;
614
/* In the case of a continuation in the Tab environment,
615
* initialize the first line. This is done with init_line */
617
if (table_depth) init_line();
623
/*==========================================================================
625
*==========================================================================*/
628
.PURPOSE Create a new column
636
if ( (j == _RIGHT_) || (j == _CENTER_))
637
column.flags |= ForceJustification;
638
BUF_AppendItem(depth_buf, DEPTH, &column);
647
/*==========================================================================
649
*==========================================================================*/
650
static int Mark(pos, len)
652
.PURPOSE Mark characters from pos, length len
656
int pos; /* IN: Position for marker */
657
int len; /* IN: Number of characters to mark */
662
{ pa = Aij(ws, pos/Columns(), pos%Columns());
667
return((pos + len < ws->marker[1] ? OK : NOK));
670
/*==========================================================================
672
*==========================================================================*/
673
static int tx_smart()
675
.PURPOSE Justify the text in column, accordings to pd->smart.
677
.REMARKS No justification if left adjustement, or line is empty.
678
The flag NoJustification or JustificationDone are taken into account.
682
int i, len, j, justify;
684
if (pd->flags & NoJustification) FINISH;
685
if (pd->flags & JustificationDone)
686
{ pd->flags &= ~JustificationDone;
689
if (blank_lines) FINISH;
690
if (htex.mode == _TeX_VERBATIM_) FINISH;
691
if (htex.mode & _TeX_OBEY_) FINISH;
693
switch( justify = (pd->smart & 7) )
694
{ default: justify = _JUSTIFY_;
696
case _LEFT_ : case _RIGHT_ : case _CENTER_:
701
pa = Aij(ws, i, pd->col_lim[0]);
702
len = pd->col_lim[1] - pd->col_lim[0];
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]);
710
else current_blank = ws->attr_init;
713
{ case _LEFT_ : /* tx_jl(pa, len, current_blank); */
715
case _RIGHT_ : tx_jr(pa, len, current_blank);
717
case _CENTER_: tx_jc(pa, len, current_blank);
720
tx_justify(pa, len, current_blank);
723
current_blank = ws->attr;
725
ws->pos = Position(i, pd->col_lim[1]); /* Correct position */
726
if (CurrentColumn() == 0)
728
else blank_lines = 0;
734
/*==========================================================================
736
*==========================================================================*/
737
static int tx_blank()
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 !
751
if ((j <= pd->col_lim[0]) && (!(pd->flags & AnchoredPosition)))
753
if (j >= pd->col_lim[1]) FINISH;
754
if (last_issued_char == ' ') FINISH; /* Don't issue 2 blanks */
756
last_issued_char = ' ', j++;
758
if (j == pd->col_lim[1]) /* Must justify, no blank */
760
else /* Insert blank */
761
{ Write(ws, &last_issued_char, 1);
763
if (pd->flags & InField)
764
Mark(ws->pos - 1, 1);
771
/*==========================================================================
773
*==========================================================================*/
776
.PURPOSE Insert blanks according to hfill_no.
781
int j, right_lim, remaining_blanks;
784
pa = Aij(ws, CurrentLine(), 0); /* Line beginning */
785
remaining_blanks = pd->col_lim[1] - CurrentColumn();
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;
793
pd->flags |= NoJustification; /* Already justified */
798
/*==========================================================================
800
*==========================================================================*/
803
.PURPOSE Issue a new line.
805
.REMARKS Newline may imply some skips...
811
pd->flags &= ~AnchoredPosition;
813
if (BottomReached()) FINISH;
815
if (hfill_no) tx_hfil(); /* Horizontal Fill */
816
if (pd->flags & ForceJustification) tx_smart();
819
if (i < pd->line_lim[0]) i = pd->line_lim[0];
821
i = pd->line_lim[1] + 1;
822
ws->pos = Position(i, 0); /* New position */
825
pd->flags &= ~(NoJustification | JustificationDone);
826
last_issued_char = ' ';
828
/* In the Tab Environment, the new line is initialized
829
* when the position is at column 0. */
831
if (do_init_line) init_line();
837
/*==========================================================================
839
*==========================================================================*/
842
.PURPOSE Insert lines according to vfill_no.
847
int old_pos, i, remaining_lines;
849
if(blank_lines == 0) tx_nl() ;
853
remaining_lines = Lines() - i;
854
if (remaining_lines <= 0) FINISH;
856
for ( ; vfill_no > 0; vfill_no--)
857
{ tw_goto(ws, vfill[vfill_no - 1], 0);
858
i = remaining_lines / vfill_no;
860
old_pos += i*ws->dim[1];
861
remaining_lines -= i;
869
/*==========================================================================
871
*==========================================================================*/
872
static int tabright(text, len)
874
.PURPOSE Justify the text at right of next `tab'
875
.RETURNS Written Length
878
char *text; /* IN : text to issue */
879
int len; /* IN : Len of text */
883
if (inaux == &aux) inaux = NULL_PTR(BUFFER);
885
i = CurrentLine(), j = CurrentColumn();
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++;
890
nb = (j+len-pd->col_lim[0])%MARGIN;
891
if (nb) nb = (MARGIN - 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];
897
ws->pos = Position(i, j);
898
pd->flags |= JustificationDone;
900
if (len > 0) i = tx_out(text, len);
905
/*==========================================================================
907
*==========================================================================*/
910
.PURPOSE Issue a new line in Table Environment
912
.REMARKS Newline may imply some skips...
918
pd0->line_lim[0] = MAX(i, pd0->line_lim[1]);
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];
927
if (do_init_line) init_line();
929
last_issued_char = ' ';
934
/*==========================================================================
936
*==========================================================================*/
937
static int clear_down(pd)
939
.PURPOSE Clear the bottom of the table
943
DEPTH *pd; /* IN: Column concerned */
946
int i, j, len, old_pos;
949
len = pd->col_lim[1] - pd->col_lim[0];
952
if (CurrentColumn() > pd->col_lim[0]) i++;
953
i = MAX(i , pd->line_lim[1]);
955
j = i-1; /* Where to start tx_mrule */
957
ws->pos = Position(j, pd->col_lim[0]);
959
for (; i < ws->dim[0]; i++)
961
pa = Aij(ws, i, pd->col_lim[0]);
962
for (j = len; --j >= 0; pa++) *pa = ws->attr_init;
972
/*==========================================================================
974
*==========================================================================*/
975
static int open_depth()
977
.PURPOSE Do operations for opening a depth
983
BUF_StackItem(depth_buf, DEPTH, pd); /* Copy this depth */
987
pd->tex_mode = htex.mode;
988
pd->flags &= ~ForceJustification;
993
/*==========================================================================
995
*==========================================================================*/
996
static int close_depth()
998
.PURPOSE Do operations for closing a depth
1003
unsigned char old_attr;
1006
old_attr = pd->attr;
1007
old_lim[0] = pd0->line_lim[1];
1008
old_lim[1] = pd->line_lim[1];
1010
if (depth_buf->offset <= sizeof(int))
1011
ERROR("Too many }");
1013
if (pd->flags & ForceJustification) tx_smart();
1014
BUF_Unstack(depth_buf);
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]);
1026
/*==========================================================================
1028
*==========================================================================*/
1029
static int full_width(pd, width)
1031
.PURPOSE Compute the full width of a column
1033
.REMARKS Adds the bars
1035
DEPTH *pd; /* IN: Column concerned */
1036
short width[2]; /* OUT: Column Limits (right limit excluded)*/
1039
width[0] = pd->col_lim[0]; width[1] = pd->col_lim[1];
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]++;
1046
return(width[1] - width[0]);
1049
/*==========================================================================
1051
*==========================================================================*/
1052
static int tr_line(pd, old, new)
1054
.PURPOSE Modify the line buffer.
1055
.RETURNS Number of modifications.
1056
.REMARKS Adds the bars
1058
DEPTH *pd; /* IN: Column concerned */
1059
int old; /* IN: Values to change */
1060
int new; /* IN: Replacement */
1066
for (p = line_buf.buf + pd->col_lim[0], i = pd->col_lim[1] - pd->col_lim[0];
1069
if (*p == old) count++, *p = new;
1075
/*==========================================================================
1077
*==========================================================================*/
1078
static int tx_tab0(opt)
1080
.PURPOSE Write / Wipe Vertical Rules (until End of Window)
1082
.REMARKS Starting at current line...
1084
int opt; /* IN: Option 1 to add, 0 to remove vertical bars */
1087
int ic, i, j, old_pos;
1090
if (line_buf.used == 0)
1092
BUF_AllocateItems(&line_buf, char, ic);
1093
oscfill(line_buf.buf, ic, 0); /* Clear Vertical Rules */
1097
{ tr_line(pd0, 1, 0); /* Suppress */
1102
i = old_pos / Columns(); /* Current Line */
1104
for (ic = pd0->cols, pc = pd0+1; --ic >= 0; pc++)
1105
{ full_width(pc, lim);
1106
if (pc->smart & _LEFT_BAR_)
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_)
1113
ws->pos = Position(i, j),
1114
line_buf.buf[j] = 1,
1115
tw_rule(ws, _DOWN_, ws->dim[0]);
1122
/*==========================================================================
1124
*==========================================================================*/
1125
static int tx_tab1()
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
1136
pd0->cols = 0, pd0->smart = 0;
1139
for (p = htex.ap; *p ; p++)
1141
{ case '|': if (column.smart&7)
1142
column.smart |= _RIGHT_BAR_, new_col();
1143
else column.smart |= _LEFT_BAR_;
1145
case ' ': column.smart |= (column.smart&7 ?
1146
_RIGHT_BLANK_ : _LEFT_BLANK_);
1148
case '{': p += 1 + tex_unit(p+1, 1024); /* Length arbitrary */
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)
1160
if (column.smart&7) new_col();
1162
return ((int)pd0->cols);
1165
/*==========================================================================
1167
*==========================================================================*/
1168
static int tx_tab2()
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
1178
int i, left_position, status;
1185
left_position = pd0->col_lim[0];
1187
for (p = htex.ap, pc = pd0+1; pd0->col_no < pd0->cols;
1188
pc++, (pd0->col_no)++)
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;
1197
{ i = pd0->col_lim[1] - left_position;
1198
if (pc->smart & _RIGHT_BAR_) i--;
1199
if (pc->smart & _RIGHT_BLANK_) 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;
1206
if (pc->smart & _RIGHT_BAR_) left_position++;
1207
if (pc->smart & _RIGHT_BLANK_) left_position++;
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;
1212
if (isTeX(*p,_TeX_PUNCT_)) p++;
1216
/* If spaces remain, center table */
1218
i = pd0->col_lim[1] - left_position;
1219
if (i < 0) status = NOK;
1222
ERR_ED_STRING("The table cannot fit on window: ", htex.ap);
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;
1235
/*==========================================================================
1237
*==========================================================================*/
1238
static int open_table()
1240
.PURPOSE Do operations for opening a table
1246
tex_getparm(1); tx_tab1();
1247
tex_getparm(2); tx_tab2();
1253
/*==========================================================================*/
1254
static int open_more()
1256
.PURPOSE Do operations for opening a {more}{...} environment
1265
tex_getparm(1); /* More name */
1266
l = strlen(htex.ap);
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;
1278
/*==========================================================================*/
1279
static int open_env()
1281
.PURPOSE Do operations for opening a new environment
1282
.RETURNS OK / NOK (not possible)
1291
i = CurrentLine(); /* Current position */
1292
env = *(htex.ap+1); /* Environment to open */
1294
/* Some lines at least must exist before starting */
1296
if (env == 'm') min_lines = -1;
1297
else if (env == 't') min_lines = (table_depth ? 1:3);
1300
if (i >= Lines() - min_lines)
1303
if(blank_lines == 0) tx_nl();
1305
open_depth(); /* Copy this depth */
1308
pd->line_lim[0] = CurrentLine(); pd->line_lim[1] = pd->line_lim[0];
1310
if (env == 'm') /* more */
1314
if (env == 't') /* Tabular Environment */
1320
/*==========================================================================
1322
*==========================================================================*/
1323
static int close_table()
1325
.PURPOSE Do operations for closing a table
1331
clear_down(pd0); /* Clear the bottom of Columns */
1338
/*==========================================================================*/
1339
static int close_env()
1341
.PURPOSE Do operations for closing an environment
1351
ERR_ED_STRING("Mismatching begin/end env.: ", p);
1353
if (pd0->env == 'm') /* More */
1354
inaux = NULL_PTR(BUFFER),
1355
BUF_AppendItem(&More, char, &zero);
1357
if (pd0->env == 't') /* Ending Table Env */
1360
if(blank_lines == 0) tx_nl() ;
1362
return(close_depth());
1365
/*==========================================================================
1367
*==========================================================================*/
1368
static int tx_item()
1370
.PURPOSE Write an `item'
1371
.RETURNS OK / NOK (line full)
1372
.REMARKS Item issued in Bold
1378
if(blank_lines == 0) tx_nl() ;
1379
if (BottomReached()) return(NOK);
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] = ' ';
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] = '=';
1394
old_attr = SetAttr(ws, _BOLD_);
1395
i = tx_out(item_ed, 2);
1396
SetAttr(ws, old_attr);
1400
else tx_out(item_ed+2, sizeof(item_ed)-2),
1401
pd->col_lim[0] += sizeof(item_ed),
1407
/*==========================================================================
1409
*==========================================================================*/
1410
static int multicol(str)
1412
.PURPOSE Interprets the `multicolumn' environment
1413
.RETURNS Length of string taken into account
1416
char *str; /* IN: multicolumn specification (starting with `m') */
1422
for (p = str; *++p == '\0'; ) ;
1424
if (*p == '0') /* Close Multicol Env */
1426
do_init_line = tr_line(pd, 2, 1);
1431
status = depth_buf->offset;
1432
open_depth(); /* Create a new depth */
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 */
1438
tex_getparm(1); /* Number of columns */
1440
pm->flags |= ForceJustification;
1444
if ((int)(pd0->col_no + nc) > (int)pd0->cols)
1445
status = NOK, nc = pd0->cols - pd0->col_no;
1448
status = NOK, nc = 1;
1450
pd0->col_i = nc; /* Increment for next column */
1452
pm->col_lim[0] = pd->col_lim[0];
1453
pm->col_lim[1] = (pd + nc - 1)->col_lim[1];
1456
/* Modify the current line sketch */
1458
if (tr_line(pm, 1, 2)) clear_down(pm);
1460
/* Chose smart attr */
1464
{ case '|': case ' ':
1465
if_not(iscntrl(*p)) goto ChoseSmart; /* If |c| */
1466
default : pm->smart = _JUSTIFY_, pm->flags &= ~ForceJustification;
1468
case 'l': pm->smart = _LEFT_; break;
1469
case 'r': pm->smart = _RIGHT_; break;
1470
case 'c': pm->smart = _CENTER_; break;
1472
while ( (*p == '|') || (*p == ' ')) p++;
1475
/* Position at correct position */
1477
/* ws->pos = Position(i, pm->col_lim[0]); */
1479
if_not(status) ERR_ED_STRING("Bad \\multicolumn ", htex.ap);
1484
/*==========================================================================
1486
*==========================================================================*/
1487
static int tx_crule()
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.
1495
short lim[2], alim[2];
1499
status = NOK; /* Default status */
1502
if (rule_lines) i--, ws->pos -= ws->dim[1];
1504
if (BottomReached()) FINISH;
1511
alim[0] = pd0->col_no + 1; /* Column Number */
1514
if (*p) /* There are parameters */
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);
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; }
1526
full_width(pd0 + alim[0], lim); /* lim[0] = Left */
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;
1533
full_width(pd0 + alim[1], alim); /* alim[1] = Right */
1535
len = alim[1] - lim[0];
1538
if (len > 0) ws->pos = Position(i, lim[0]),
1539
tw_rule(ws, _RIGHT_, len);
1541
++i; ws->pos = Position(i, 0);
1542
nltab(); rule_lines = 1;
1549
/*==========================================================================
1551
*==========================================================================*/
1552
static int tx_rule()
1554
.PURPOSE Draw a horizontal rule over the complete window / table.
1555
.RETURNS OK / NOK (Window full)
1561
if (BottomReached()) return(NOK);
1562
if (blank_lines == 0) tx_nl();
1563
if (do_init_line) init_line();
1568
/* Now replace blanks by horizontal bars */
1570
ws->pos = Position(i, pd0->col_lim[0]);
1571
tw_rule(ws, _RIGHT_, pd0->col_lim[1] - pd0->col_lim[0]) ;
1573
++i; ws->pos = Position(i, 0);
1574
nltab(); rule_lines = 1;
1579
/*==========================================================================
1581
*==========================================================================*/
1582
static int tx_mark()
1584
.PURPOSE Mark the starting point of a field.
1585
.RETURNS OK / NOK (Window full)
1591
/* Save Field name, Field Type, Field Picture */
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);
1600
/* Save current column position */
1602
BUF_AppendItems(&field_def, short int, &pd->col_lim[0], 2);
1604
pd->flags |= InField; /* Next output will be flagged */
1605
marked = 0; /* Count of marked bytes */
1610
/*==========================================================================
1612
*==========================================================================*/
1613
static int get_marked(st)
1615
.PURPOSE Retrieve marked fields.
1616
.RETURNS Number of fields
1617
.REMARKS If a field lies over several lines, complete lines are assumed.
1619
int st; /* IN: Completion Status of Field */
1621
char *fname; /* Field Name */
1622
TWFIELD *fdef; /* Field Definition */
1623
short *f, *fe; /* Current Column */
1626
char **stored_address;
1628
MID_STATIC TWFIELD twfield0 = {(char *)0};
1630
/* Issue Error Message if Bad Status */
1633
{ ERROR("The Form doesn't fit on the Window...");
1637
/* Allocate first the Field Buffer connected with window */
1640
{ Fields(ws) = BUF_Open(char, field_names.used +
1641
sizeof(TWFIELD)*(1 + field_def.used / (3*sizeof(short int))),
1647
/* ... and retrieve fields successively */
1649
f = (short int *)(field_def.buf); /* First column range */
1650
fe = (short int *)(field_def.buf + field_def.used);
1652
for (; f < fe; f += 3)
1653
{ fdef = BUF_AllocateItem(b, TWFIELD);
1655
fdef->dim[1] = f[1] - f[0]; /* Field Width */
1656
fdef->dim[1] = MIN(fdef->dim[1], f[2]);
1658
i = 0, j = f[0], pa = Aij(ws, 0, j);
1660
while (!(*pa & _MARKER1_)) /* Find Start of Marked Text */
1662
{ j = f[0], i++, pa = Aij(ws, i, j);
1663
if (i >= Lines()) break; /* Bottom of Window */
1668
{ b->used -= sizeof(TWFIELD);
1669
break; /* Bottom of Window */
1673
fdef->home[0] = i, fdef->home[1] = j;
1674
fdef->dim[0] = (f[2] + fdef->dim[1] -1)/fdef->dim[1];
1677
i = b->used / sizeof(TWFIELD); /* Number of Fields */
1679
BUF_AppendItem(b, TWFIELD, &twfield0); /* End indicator */
1682
/* Copy now the Names into the Buffer associated to Window */
1684
b->offset = b->used; /* Mark beginning of names */
1685
BUF_AppendItems(b, char, field_names.buf, field_names.used);
1687
/* Indicate positions of names */
1689
fdef = (TWFIELD *)(b->buf);
1690
fname= b->buf + b->offset; /* First name address */
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);
1702
/*==========================================================================
1704
*==========================================================================*/
1705
static int tx_finish(st)
1707
.PURPOSE Terminate Display: actions of \vfill's, non-terminated tables,
1708
retrieve marked fields.
1712
int st; /* IN: Status as OK / NOK / EOF */
1716
if (hfill_no) tx_hfil();
1718
/* Insert supplementary blank lines */
1721
tx_vfil(), vfill_no = 0;
1723
/* Get the Marked Lines */
1725
if (field_def.used) get_marked(st);
1727
if ( (st == OK) && (depth_buf->offset > sizeof(int)))
1728
ERROR("Missing } or \\end");
1730
if (WindowIsActive) ActiveWindow(ws);
1735
/*==========================================================================
1737
*==========================================================================*/
1740
.PURPOSE Change options.
1741
.RETURNS Old options.
1744
int opt; /* IN: New option 0 = Don't Center */
1753
/*==========================================================================
1755
*==========================================================================*/
1756
char *tx_symbol(str)
1758
.PURPOSE Retrieve the translation of a definition
1759
.RETURNS Pointer to the translated definition
1762
char *str; /* IN: String to translate */
1764
return(tex_symbol(str));
1767
int tx_def(symbol, synonym)
1769
.PURPOSE Set a symbol in the TeX definitions.
1773
char *symbol; /* IN: Symbol to define */
1774
char *synonym; /* IN: Equivalence */
1778
tx_tex(); /* Install the TeX structure */
1780
def = MEM_GET(char, 12 + strlen(symbol) + strlen(synonym));
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, "}");
1790
LOG_ED_STRING("Added: ", def);
1792
status = TeX_Execute(&htex, def, strlen(def));
1798
/*==========================================================================
1800
*==========================================================================*/
1801
int tx_display(w, str, len, clear_option)
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.
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 \
1815
register int status;
1817
ENTER("tx_display");
1820
TRACE_ED_STR2("String to display:", str, len);
1824
tx_init(str, clear_option);
1827
/* Execute TeX. The routines tx_out collects the words
1828
* for output, while tx_action is triggered for each action.
1831
status = TeX_Execute(&htex, str, len);
1833
/* Terminate: vfill adjustments, non-terminated tables,
1834
* and retrieve marked fields
1843
/*==========================================================================
1845
*==========================================================================*/
1846
int tx_mdisplay(w, str, nstrings, clear_option)
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.
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 \
1866
register int status;
1868
ENTER("tx_mdisplay");
1871
TRACE_ED_I("Number of string to display:", nstrings);
1875
tx_init(str, clear_option);
1878
/* Execute TeX. The routines tx_out collects the words
1879
* for output, while tx_action is triggered for each action.
1882
status = TeX_ExecuteArray(&htex, str, nstrings);
1884
/* Terminate: vfill adjustments, non-terminated tables,
1885
* and retrieve marked fields
1894
/*==========================================================================
1896
*==========================================================================*/
1897
int tx_fdisplay(w, fid, len, clear_option)
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.
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 \
1911
register int status;
1913
ENTER("tx_fdisplay");
1916
tx_init(blanks, clear_option); /* Non-null char pointer */
1918
/* Load text to process */
1920
TeX_Load(&htex, fid, len);
1922
/* Execute TeX. The routines tx_out collects the words
1923
* for output, while tx_action is triggered for each action.
1926
status = TeX_Continue(&htex);
1928
/* Terminate: vfill adjustments, non-terminated tables,
1929
* and retrieve marked fields
1938
/*==========================================================================
1940
*==========================================================================*/
1941
int tx_file(w, fname, clear_option)
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.
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 \
1954
register int status;
1959
tx_init(fname, clear_option); /* Non-null char pointer */
1961
/* Load text to process */
1963
TeX_Include(&htex, fname);
1965
/* Execute TeX. The routines tx_out collects the words
1966
* for output, while tx_action is triggered for each action.
1969
status = TeX_Continue(&htex);
1971
/* Terminate: vfill adjustments, non-terminated tables,
1972
* and retrieve marked fields
1981
/*==========================================================================
1983
*==========================================================================*/
1984
TWFIELD *tx_fields(w)
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.
1990
WINDOW *w; /* IN: Window concerned */
1995
ENTER("*tx_fields");
1997
f = NULL_PTR(TWFIELD);
2001
if (b->used) f = (TWFIELD *)b->buf;
2003
EXIT_PTR(TWFIELD, f);
2006
/*==========================================================================
2008
*==========================================================================*/
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.
2016
char *name; /* IN: `more' name to find */
2023
if (!name) { /* Get the Next one */
2024
if (oMore.offset >= oMore.used) {
2026
EXIT_PTR(char, 0); /* Indicates End */
2028
pi = (int *)(oMore.buf + oMore.offset);
2029
oMore.offset += sizeof(int);
2033
for (i=SET_Items(&oMore, int), pi=SET_FirstItem(&oMore, int); --i >= 0; pi++)
2036
if (strcomp(name, p) == 0) break; /* Topic Found */
2038
if (i < 0) p = NULL_PTR(char);
2039
else p += 1 + strlen(name);
2045
/*==========================================================================
2047
*==========================================================================*/
2050
.PURPOSE Define an action routine in case of mathematical symbols
2053
.REMARKS Use NULL_FCT to take standard action (ignore)
2055
int (*f)(); /* IN: Function with arguments (string, length) \
2056
to call when $ ^ _ are encountered */
2058
external_action = f;
2063
/*==========================================================================
2065
*==========================================================================*/
2066
int tx_out(str, len)
2068
.PURPOSE This is the output routine.
2069
.RETURNS Number of bytes processed.
2072
char *str; /* text to output */
2073
int len; /* Length of text */
2075
int output_bytes, j, m;
2077
/* ENTER("tx_out"); */
2080
TRACE_ED_STR2("Output=>",str,len);
2084
{ BUF_AppendItems(inaux, char, str, len);
2085
j = inaux->used; /* Save */
2086
BUF_AppendItem(inaux, char, &zero);
2087
inaux->used = j; /* Restore */
2092
if (len < 0) FINISH;
2095
j = CurrentColumn();
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,
2102
else pd->flags &= ~AnchoredPosition;
2104
if (BottomReached()) FINISH;
2106
if ((htex.mode != _TeX_VERBATIM_) && (j + len > pd->col_lim[1]))
2107
/* Doesn't fit on the line ... */
2109
if (blank_lines == 0) tx_nl();
2110
if (BottomReached()) FINISH;
2114
m = ws->pos; /* Position for marker */
2115
output_bytes = Write(ws, str, len);
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);
2127
/* EXIT(output_bytes); */
2128
return(output_bytes);
2131
/*==========================================================================
2133
*==========================================================================*/
2134
int tx_action(str, len)
2136
.PURPOSE This is the action routine.
2137
.RETURNS Number of bytes processed.
2140
char *str; /* text to output */
2141
int len; /* Length of text */
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";
2150
/* ENTER("tx_action"); */
2153
TRACE_ED_STR2("Action: ",str,len);
2156
p = str, pe = str+len;
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;
2164
else if (*htex.ap == _TeX_END_) /* Close env. */
2165
if_not(close_env()) FINISH;
2170
case '{' : /* New Depth */
2171
if (BottomReached()) FINISH;
2175
case '}': /* Old depth */
2179
case '\0': case '\\': /* NUL's may be found after macro substitutions */
2182
case '$': case '^': case '_': /* Mathematical symbols */
2183
if (external_action)
2184
{ if_not(i = (*external_action)(p, pe-p))
2188
else no_math_action[1] = *p, WARNING(no_math_action);
2191
case ' ': /* Stretchable blank */
2193
{ if ((inaux->used) && (inaux->buf[inaux->used-1] != ' '))
2196
else tx_blank(); /* Always possible */
2199
case '\r': /* New Line */
2201
if (inaux) { tx_out("\n", 1); break; }
2202
if (blank_lines == 0) tx_nl() ;
2203
if (pd->env == 't') tx_set(), nltab();
2206
case '\n': /* New paragraph */
2207
if(inaux) { tx_out("\n", 1); break; }
2208
while (blank_lines <= 1)
2209
{ if (BottomReached()) break;
2214
case '/': /* Skip Line */
2215
if(inaux) { tx_out("\n", 1); break; }
2216
if(blank_lines == 0) tx_nl() ;
2220
case '&': /* Tab in Tabular, or `tab' outside */
2221
if(inaux) { tx_out("&", 1); break; }
2224
if (CurrentColumn() > pd->col_lim[0])
2226
pd->line_lim[1] += 1;
2227
pd0->line_lim[1] = MAX(pd0->line_lim[1], pd->line_lim[1]);
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 */
2233
if (pd0->col_no >= pd0->cols) {
2234
WARNING("Too many &'s");
2235
pd0->col_no = j; /* Restore ... */
2239
ws->pos = Position(pd0->line_lim[0], pd->col_lim[0]);
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 */
2249
Bell(); /* Ring Bell */
2252
case 'f': /* Fill vertical or horizontal */
2254
fill_error[10] = *++p;
2255
if (*p == 'v') /* Vertical Fill */
2256
{ if (vfill_no >= MAX_MARKED)
2257
{ ERROR(fill_error);
2260
if(blank_lines == 0) tx_nl() ;
2261
vfill[vfill_no++] = CurrentLine();
2263
else /* Horizontal Fill */
2264
{ if (hfill_no >= MAX_MARKED)
2265
{ ERROR(fill_error);
2268
hfill[hfill_no++] = CurrentColumn();
2272
case 'F': /* Mark Field or Redefine Columns */
2274
if (BottomReached()) FINISH;
2276
{ case 's': tx_mark(); /* Start */
2278
case 'e': /* End Field */
2279
if (marked == 0) /* Null Field: At least one byte! */
2281
BUF_AppendItem(&field_def, short, &marked); /* Length */
2282
pd->flags &= ~InField;
2284
case 't': /* Redefine Columns in a Table */
2286
close_depth(), open_depth();
2288
if ((rule_lines) && (ws->pos >= ws->dim[1]))
2289
ws->pos -= ws->dim[1];
2292
if(rule_lines) tx_rule();
2299
case 'J': /* Justification specifications */
2300
if (BottomReached()) FINISH;
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)
2311
inaux = NULL_PTR(BUFFER);
2313
default : tx_smart(); break;
2317
case 'M': /* Move Margins */
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;}
2327
case 'I': /* indent */
2328
tx_out(blanks, MARGIN);
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 */
2337
ws->pos = Position(i,j);
2338
pd->flags |= AnchoredPosition;
2342
{ if_not(tx_out(blanks, 1)) FINISH;
2343
j = MIN(pd->col_lim[1] - CurrentColumn(), i-1);
2345
{ j = MIN(j, sizeof(blanks));
2351
case 'V': /* Test remaining lines */
2354
if (i >= Lines()) continue;
2355
if ((ws->pos + i*Columns()) <= ws->marker[1])
2357
p = str; /* Stop here, tx_action will return 0 */
2359
case 'H': /* Test remaining cols */
2362
if ((CurrentColumn()+i) > pd->col_lim[1])
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");
2372
case 'm': /* Multicolumn */
2374
if (BottomReached()) FINISH;
2380
tx_crule(); tx_set();
2384
tx_rule(); tx_set();
2387
case 'V': /* Video Attributes */
2389
old_attr = pd->attr; /* Current Attribute */
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;
2399
j = CurrentColumn();
2401
if (old_attr != pd->attr) SetAttr(ws, pd->attr);
2402
if (j <= pd->col_lim[0]) current_blank = ws->attr;
2406
bad_action[1] = *p, WARNING(bad_action);
2407
p = str - 1; /* Means EOF */
2416
/*==========================================================================
2418
*==========================================================================*/
2421
.PURPOSE List, in the Log File, the list of macros
2422
.RETURNS Number of non-uused symbols
2423
.REMARKS For debugging purposes.
2430
n = tex_list(&htex);