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
/*++++++++++++++++++++++++++++++++++++++++++++++++++
31
.IDENTIFICATION termcap.c
32
.AUTHOR Francois Ochsenbein [ESO-IPG]
35
.ENVIRONMENT TermWindows
37
.COMMENTS The main program loads the TermCapFile into a binary
38
structure in SYS$LOGIN.
40
This module provides tools to read the TERMCAP file and to
41
prepare a TERM structure (defined in TERMINAL.H) which
42
receives the TermCapabilities in a form usable by ZT Libraries.
43
For usage in TermWindows, this module is NOT required
44
if it is assumed that a binary copy of the TERM already exists.
51
{\bf Description of TERMCAPS}
54
TERMCAP is the file EMACS uses to acquire the terminal specific
55
commands and escape sequences for updating the display. This file is
56
an ASCII text file that can be modified with any text editor.
58
The TERMCAP method of updating a display was developed by William
59
Joy at the University of California at Berkeley for UNIX
60
\footnote{UNIX is a trademark of Bell Laboratories}
62
employed by many UNIX programs, some of which run on VMS. Because
63
EMACS uses a nearly identical method of reading the TERMCAP file as
64
other programs, the same TERMCAP file can be shared between several
65
screen manipulation programs.
67
The TERMCAP file contains a series of entries that describe the
68
capabilities of various terminals. Each entry is composed of fields
69
separated by colons (`:'). There can be several lines per entry (by
70
placing a `\b' at the end of each line, except the last line of the
73
The first field is the name of the terminal to which the ensuing
74
fields apply. This field can specify several synonyms for the
75
terminal; the synonyms are separated by vertical bars (`$|$'). The
76
field, as with all fields, are terminated by a colon. Note that EMACS
77
distinguishes between upper and lower case alphabetics in this field
78
(and in all fields; hence the reason for quotes on the DEFINE
81
The remainder of the fields are specified as two letter field
82
names. These may be followed by a field value. For instance:
90
are all valid fields. The field name can be separated from the field
91
value by either a `=' (the equal-sign designates a string), or `\#'
92
(the sharp designates a number), or a `:' (the column designates
94
{\em Note added by Fran\c cois Ochsenbein:}
95
The `@' instead of `=' or `\#' means that
96
{\em the capability does not exist.}
98
The two letter field names that EMACS uses are described in the
99
following table. Note that some TERMCAP entries may have more (which
100
are ignore by EMACS).
102
{\em Note added by Fran\c cois Ochsenbein:}
103
All capabilities are not described here; the
104
usage of various other capabilities are explained in each
105
module making use of TERMCAP.\\
106
Let's just mention here {\tt V}$x$ for video attributes,
107
{\tt G}$x$ for graphic characters,
108
{\tt F}$x$ for function keys,
109
{\tt k}$x$ for keypad keys,
110
and {\tt K}$x$ for special keys.
113
$$\begin{tabular}{|llp{33em}|} \hline
114
Field &Padding &Meaning \\
116
{\tt al=} &P* &Adds a new line to the screen, pushing
117
lines below it down.\\
118
{\tt am} & &Boolean value (automatic margin, \ie
119
cursor wraps from right margin to next line).\\
120
{\tt bc=} & &Moves the cursor left (typically
121
backspace or \^{ }H).\\
122
{\tt cb= } &P &Erase text from the left margin to the cursor.\\
123
{\tt cd=} &P &Erases text from the cursor to the
124
end of the display.\\
125
{\tt ce=} &P &Erases text from the cursor to the
126
rightmost column in the display.\\
127
{\tt cl=} &P* &Erases all text on all lines on the
129
{\tt cm=} &P &Moves the cursor; see below.\\
130
{\tt co\#} & &Specifies the number of columns per
132
{\tt cs= } &P &Defines a scrolling region.\\
133
{\tt cu= } &P &Erase text from the top of the display to the cursor.\\
134
{\tt dc= } &P* &Deletes the current character, moving
135
all characters at the right of the
136
deleted character left by one.\\
137
{\tt dl=} &P* &Deletes the current line, moving all
138
lines below it up by one.\\
139
{\tt dm=} & &Enters Delete Character mode.\\
140
{\tt do=} & &Moves the cursor down (line-feed on hard
142
{\tt ed=} & &Exits Delete Character mode.\\
143
{\tt ei=} & &Exits Insert Character mode. (Each
144
character sent to the terminal will
145
replace the character under (or to the
146
right of) the cursor.\\
147
{\tt ho=} &P &Move the cursor to home position
148
( the top left corner).\\
149
{\tt ic=} &P &Inserts one character space, moving all
150
characters to the right of the cursor
151
right by one space.\\
152
{\tt im=} &P &Enter Insert Character mode. (Each
153
character sent to the terminal will move
154
all characters to the right of the
155
cursor right by one.\\
156
{\tt ip=} &P* &Inserts padding after the character
158
{\tt is=} &P &Initialize the display.\\
159
{\tt ke=} & &Exit keypad mode (disable the keypad).\\
160
{\tt kn\#} & &Number of keypad keys.
161
Cursor arrows are {\tt kl=}(left),
162
{\tt kr=}(right), {\tt ku=}(up),
163
{\tt kd=}(down), {\tt kh=}(home).\\
164
{\tt ks=} & &Start keypad mode (enable the keypad).\\
165
{\tt li\#} & &Specifies the number of lines on the display.\\
166
{\tt nd=} & &Moves the cursor right by one character.\\
167
{\tt pc=} & &Definition of the padding char (NUL is default).\\
168
{\tt rc=} & &Restore saved cursor position and attributes.\\
169
{\tt sc=} & &Save cursor position and attributes.\\
170
{\tt se=} & &Exit {\sl stand-out} mode. (All subsequent
171
characters will appear normally.)\\
172
{\tt sf=} &P &Scroll forward (up) the display. The cursor
173
remains at the same position.\\
174
{\tt so=} & &Enter {\sl stand-out} mode. (All subsequent
175
characters will appear highlighted in
176
some fashion. This may be blinking,
177
bold, reverse video, ...)\\
178
{\tt sr=} &P &Scroll Reverse (down) the display.\\
179
{\tt tc=} & &This field means that sequences are
180
to be found with the name provided after the `='.\\
181
{\tt te=} & &This string is sent to the terminal when
182
EMACS exits or redraws the display.\\
183
{\tt ti=} & &This string is sent to the terminal when
184
EMACS starts up or redraws the display.\\
185
{\tt ue= } & &Exit {\sl underscore} mode (synonym is {\tt Vu}).\\
186
{\tt ul } & &Terminal underlines without
188
{\tt up=} &P* &Moves the cursor up one line,
189
maintaining the same column.\\
190
{\tt us= } & &Enter {\sl underscore} mode.\\
191
{\tt vb=} & &Flashes the screen (for a visible bell).\\
195
For each of the field names mentioned in the table
196
that end with `=', you should
197
include the sequence of characters that effect the behavior listed to
198
the right of the name. Fields with P or P* next to them can have a
199
time delay whenever the field is output (to permit terminals to do
200
internal processing). If a delay is needed then you may put a number
201
(indicating milliseconds) immediately to the right of the `=', but
202
before the first character of the string. Additionally, for `dc',
203
`dl', `al', `cl', `ip', and `up', you can put an `*' after the number
204
but before the first character of the string. The `*' states that the
205
delay is to be repeated for each time the string is sent to the
206
terminal. (For example: if EMACS needs to insert 3 blank lines, then
207
it will `execute the delay' between each of the issuances of the `al'
211
The string values for each name can have the following special
214
$$\begin{tabular}{|ll|} \hline
216
{\tt \b E } & ASCII Escape character.\\
217
{\tt \^{ }x } & The ASCII control character `x'.\\
218
{\tt \b nnn } & The ASCII character represented by octal nnn.\\
219
{\tt \b n } & The Control-J (linefeed) character.\\
220
{\tt \b r } & Control-M (Carriage-return).\\
221
{\tt \b t } & Tab (Control-I).\\
222
{\tt \b b } & Backspace (Control-H).\\
223
{\tt \b f } & Formfeed (Control-L).\\
224
{\tt \b\^\ } & A single caret (\^{ }).\\
225
{\tt \b\b } & A single backslash (\b).\\
226
{\tt \b: } & The column character (:).\\
232
Note: You must use \b072 or \b: to represent a colon (`:')
236
The value of the `cm' field has a special interpretation. EMACS
237
treats it as a function that is called with two parameters: first the
238
line, and then the column that the cursor is to go to. Within the
239
string, the following character sequences have a special meaning:
241
$$\begin{tabular}{|lp{33em}|} \hline
243
{\tt \%d } & Replaced with the line or column number.\\
244
{\tt \%2 } & Replaced with the line or column number using a
245
two digit, zero filled field.\\
246
{\tt \%3 } & Replaced with the line or column number using a
247
three digit, zero filled field.\\
248
{\tt \%. } & Use the ASCII character corresponding to the line
249
or column number (line or column 1 would produce a
251
{\tt \%+x } & Use the ASCII character corresponding to the line
252
or column number plus the ASCII number for
254
{\tt \%>xy } & If the line or column number is greater than an
255
ASCII `x', then add an ASCII `y' to it. (`x' and
256
`y' are characters.)\\
257
{\tt \%r } & Output the column, then line. (Emacs defaults to
258
line and then column.)\\
259
{\tt \%i } & Add one to both the columns and line numbers
260
(Emacs defaults to zero biased lines and columns).\\
261
{\tt \%\% } & Output a single `\%'.\\
262
{\tt \%n } & Exclusive-or the line and column number with octal
271
{\tt cm=\b E[\%d;\%dm}
274
translates to ESCAPE, left bracket, the line number, a semicolon, the
275
column number, then a lowercase M.
279
{\bf \^{ }S And \^{ }Q Handling}
281
If your terminal (or communications link) uses \^{ }Q and \^{ }S
283
X-off) for synchronization, then you should set xon-protocol as
287
{\tt (set-terminal-characteristic "xon-protocol" 1) }
291
This will tell Emacs to intercept and act on these characters;
292
\^{ }S will be recognized as telling Emacs to stop sending characters, and
293
\^{ }Q will tell Emacs to continue sending them. Any bindings that these
294
characters have will behave unpredictably. Any MLisp functions you
295
write can use the global variable xon-mode to determine if it should
296
ignore or act on \^{ }Q and \^{ }S.
299
If you set xon-mode to 1, then you must also have TTSYNC and
300
HOSTSYNC set with the Set Terminal VMS command.
303
When xon-mode is set, then you will have to rebind any functions
304
that are bound to the \^{ }S and \^{ }Q keys (typically search-forward an
305
quote-character). The conventional rebindings are \^{ }\^{ } -s and
307
(Control-uparrow-s, and Control-uparrow-q), although some of the
308
oltimers use Control-\b\ and Control-H.
311
.VERSION 1.0 01-Jul-1986: Creation
312
.VERSION 2.0 10-Jun-1987:
313
For version '2', only functions required to CREATE the
314
TERMCAP Area are here.
315
The characters may be 8 bits.
316
.VERSION 2.2 23-Jun-1987: Adapted UNIX
317
.VERSION 2.3 23-Nov-1987: Removed Bug which occured in tu_x1,
318
and caused crashes for some terminals (due to reallocation
320
.VERSION 3.0 15-May-1988: Version '3'. Use stritem function to locate
321
the device name in the list.
322
.VERSION 3.1 28-Mar-1989: Removed bug in stritem (if 2nd string is of length 0)
323
.VERSION 3.2 09-May-1989: Modified f_gets to eliminate bad messages in
324
case of unknown terminal.
325
.VERSION 3.3 14-Jul-1989: Modified error logging in tu_load.
326
.VERSION 3.4 24-Aug-1989: Don't modify term structure when terminal not
327
found (may be looked in a new file)
330
----------------------------------------------------------------------------*/
332
#define DEBUG 0 /* For debugging only */
334
#define PM_LEVEL LEVEL_TU
336
#define TW_MACROS 0 /* Don't use TermWindows Macros */
338
#define TW_STRUCT 0 /* Do not use window Structures */
341
#include <midas_def.h>
345
extern int eh_ed_str2(), eh_ed_as();
346
extern int pm_enter(), pm_ed_tr2(), pm_iexit(), pm_ed_trace();
348
#define ESC 033 /* Code for ASCII escape character */
349
#define strbspan_(str,mask,table) oscbspan((unsigned char *)str,strlen(str),mask,table)
350
#define strbspan(str,mask) strbspan_(str,mask,main_ascii)
352
#define FINISH goto FIN
357
#define call(x) if (!(status = x)) FINISH \
360
MID_STATIC INDEX ind={{' ',' '},0};
361
static int fn; /* TermCap File Number */
364
/* MID_RSTATIC char defaults[]=":bc:nd:do:up:cm:nl=\r\n:ff=\f:_H=^H:li#60:co#132:";*/
365
MID_RSTATIC char defaults[]=":nd= :nl=\r\n:ff=\f:_H=^H:li#60:co#132:";
367
/* Macros just to improve readibility */
369
#define NCAPS (terms->ns)
370
#define CAPLIST (terms->caplist)
371
#define CAPSIZE (terms->size)
372
#define CAPTOP (terms->captop)
375
/* MONITOR(TERMCAP); */
377
/*===========================================================================*/
378
static int strloc(str, c)
380
.PURPOSE Locate the first occurence of character `c'
381
.RETURNS Index within str of char c; length of str if not found.
383
char *str; /* IN: string to scan */
384
char c; /* IN: char to locate */
393
/*===========================================================================*/
394
static int stritem( s1, s2, sep)
395
/*++++++++++++++++++++++++
396
.PURPOSE Locates a substring within a string, which must be followed / preceded
397
by separator(s) characters
398
.RETURNS Index within first string of second string. The index
399
is the length of the first string for mismatch.
400
.REMARKS Locate is made case-sensitive.
401
.METHOD Use index, then check preceding / following char.
403
char *s1; /* IN: address of first string (source) */
404
char *s2; /* IN: address of 2nd string (object to find) */
405
char *sep; /* IN: list of separators */
407
register char *p1, *pe;
413
for (p1 = s1, pe = p1 + strlen(p1); *p1; )
414
{ p1 += oscindex(p1, pe-p1, s2, i);
415
if_not(*p1) break; /* Not Found */
416
if (p1 > s1) /* Check preceding char */
418
if_not (*(sep + strloc(sep, *(p1++))))
423
p1 += i; /* Check following char */
424
if_not(*p1) break; /* Located at end : OK */
425
if(*(sep + strloc(sep, *p1))) /* Separator found */
432
/*==========================================================================
434
*==========================================================================*/
435
static int f_gets (buf, len)
437
.PURPOSE Interface to file reading
438
.RETURNS OK / NOK / EOF
439
.REMARKS On return, always terminated by EOS.
441
char *buf; /* OUT: text, EOS-terminated */
442
int len; /* IN: Size of buffer */
446
status = osaread(fn, buf, len);
448
ERR_ED_STR2("Too long TermCapFile record: ", buf, 30);
449
if (status >= 0) status = OK;
451
printf("Read from TermCapFile: %s\n",buf);
457
/*==========================================================================
459
*==========================================================================*/
460
static int tu_encode (str)
462
.PURPOSE Encode capabilities followed by the `=' sign, i.e.
465
\item interpretation of delays into number of ms
467
\item interpretation of \b ooo (octal codes)
468
\item replacement of the \% format by FORMAT char (0x`FE')
469
\item replacement of the starting `:' by the length of the coded
473
.RETURNS Length of capability
474
.REMARKS An existing delay is flagged by `d' (no repetition),
475
or `D' (repeated delay indicated by P*) in place of the `='.
476
-----------------------*/
477
char *str; /* MOD: The cap string to encode */
479
register char *p1, *p2;
481
MID_STATIC char delay_flag = '=';
485
TRACE_ED_STR2("Coding capability ",str,4);
488
if (*p1 != ':') { ERR_ED_STR2("Bad TermCapability=>",str,4);
492
if (*p1) p1 += 2; /* Not Followed by EOS */
495
switch(*(p1)) /* Test char following the cap_code */
496
{ case '@' : /* Nothing to code */
498
case ':' : case EOS: /* Nothing to code */
501
default : /* Do not code, but compute length */
502
delay = oscloc(p1, 80, ':'); /* Length */
503
*str = delay - 1, p1 += delay;
507
/* Here, only if cap_code followed by `='. p1 and p2 are used
508
as pointers to input / output string */
511
/* Compute the delays, i.e. digits followed by optional `*' */
513
for( delay = 0; isdigit(*p1); p1++)
515
delay += (*p1 - '0');
518
if(*p1 == '*') p1++, delay_flag = 'D';
520
for(; *p1 != ':'; p2++) /* The `:' indicates the end */
522
{ case '^': /* Control Char */
523
*p2 = (*(++p1)) & 037;
525
case '\\': /* Escape - Look next char */
528
{ case 'E': case 'e': *p2 = ESC; p1++; break;
529
case 'n': *p2 = '\n'; p1++; break; /* Newline */
530
case 'r': *p2 = '\r'; p1++; break; /* <Return> */
531
case 't': *p2 = '\t'; p1++; break; /* Horiz. Tab */
532
case 'b': *p2 = '\b'; p1++; break; /* Backspace */
533
case 'f': *p2 = '\f'; p1++; break; /* Form Feed */
534
case '0': case '1': case '2': /* Octal number */
537
{ *(unsigned char *)p2 *= 8;
538
*(unsigned char *)p2 += *(p1++) - '0';
540
/* *p2 &= 0177; /. Convert to ASCII */
542
default: /* case '^': case '\\': and others */
543
*p2 = *(p1++); break;
545
case '%': /* May be a format */
546
if (*(++p1) == '%') *p2 = *(p1++); /* `%' sign */
549
default: /* Normal char */
554
/* Write the length of the coded string */
557
/* Insert the delay --- limited to 255 ms ! */
559
{ *(str+3) = delay_flag;
560
*(unsigned char *)p2 = MIN(delay, 255);
564
TRACE_ED_STR2("Coded:",str+4,*str);
565
if(*(str+3) != '=') TRACE_ED_I("Delay is ",*(str + 4 + *str));
572
/*==========================================================================
574
*==========================================================================*/
575
static int tu_append (buffer, len)
577
.PURPOSE Append into the TERMCAP list the specified buffer.
581
char *buffer; /* IN: Buffer to copy */
582
int len; /* IN: Length of buffer */
586
if (len <= 0) return(OK);
588
/* Test for 2 consecutive : */
589
if ( (*buffer == ':') && (CAPTOP > 0))
590
if (*(CAPLIST + CAPTOP -1) == ':') len--, buffer++;
592
/* Test if area large enough, with one spare byte */
593
if ( (CAPTOP + len) >= CAPSIZE) /* Reallocate */
594
{ /* TRACE("Reallocation of Termcap Area");*/
595
n = CAPSIZE + MAX (MEM_AMOUNT,len); /* Required memory */
596
CAPLIST = MEM_EXP(char, CAPLIST, n);
597
if (!CAPLIST) return(NOK); /* Allocation failed */
600
/* Copy caplist to area */
601
CAPTOP += oscopy(CAPLIST + CAPTOP, buffer, len);
606
/*==========================================================================
608
*==========================================================================*/
611
.PURPOSE Encodes the capabilities and generates the index by capability
613
.REMARKS The first encountered capability wins if duplicates
614
exist --- however, input sequences are stored several times
615
when duplicates exist.
619
INDEX *idx; /* Starting address of index by capability */
623
MID_STATIC char cap3[] = "xx: ";
629
NCAPS = 0; /* No sequences */
631
/* Scan the caplist - each cap starts and ends with `:' */
633
for ( i = 0; isgraph(*(CAPLIST+i)) ; i += j)
634
{ idx = (INDEX *) (CAPLIST + terms->index);
635
/* May have been reallocated... */
637
ind.cap[0] = *(CAPLIST+j++); /* First char of capcode */
638
ind.cap[1] = *(CAPLIST+j); /* Second char of capcode */
639
ind.icap = i; /* Index of capcode */
641
flag = 0; /* Check if entry aleady exists */
642
if( (ind.cap[0] != 'k') && (ind.cap[0] != 'K') && (ind.cap[0] != 'F'))
643
{ for (j=0; (j<NCAPS) && (flag == 0); j++)
644
flag = ((idx[j].cap[0] == ind.cap[0]) &&
645
(idx[j].cap[1] == ind.cap[1]));
647
j = tu_encode(i + CAPLIST);
648
if (j < 3) /* Don't add to index */
652
if(flag) continue; /* Already exists */
654
NCAPS++; /* Add a new entry */
655
call(tu_append((char *)&ind,sizeof(ind)));
656
/* Encode the capabilities */
659
/* Sorting via a simple interchange */
661
TRACE_ED_I("Sorting capabilities ",NCAPS);
664
if (NCAPS < 2) FINISH;
668
idx = (INDEX *) (CAPLIST + terms->index);
670
for (i=0; i<flag; i++)
671
{ for (j=i+1; j < NCAPS; j++)
672
{ if (idx[i].cap[0] < idx[j].cap[0]) continue;
673
if (idx[i].cap[0] == idx[j].cap[0])
674
if (idx[i].cap[1] <= idx[j].cap[1]) continue;
675
ind = idx[i]; idx[i] = idx[j]; idx[j] = ind;
680
TRACE("Sorted Capabilities");
681
for (i=0; i<NCAPS; i++)
682
{ cap3[0] = idx[i].cap[0], cap3[1] = idx[i].cap[1];
683
TRACE_ED_STR2(cap3, 4+CAPLIST+idx[i].icap, *(CAPLIST+idx[i].icap));
691
/*==========================================================================
693
*==========================================================================*/
696
.PURPOSE Generates the index by sequences (made with short integers)
698
.REMARKS To be meaningful, capabilities should be coded.
699
Only those caps beginning with `k', `K' or `F' are retained
700
(functions that are read on the terminal)
704
register char *p1, *p2;
705
INDEX *idx1; /* Starting address of index by capability */
706
short int *idx; /* Starting address of index by sequence */
715
/* Simply use the index by capcodes ---
716
Keep only capcodes starting with 'k', 'K' or 'F' */
718
terms->nsr = 0; /* No readable sequence */
721
for (i=0; i<NCAPS; i++)
722
{ idx1 = (INDEX *) (CAPLIST + terms->index);
723
flag = idx1[i].cap[0];
724
if (flag == 'k' || flag == 'K' || flag == 'F')
725
{ call(tu_append((char *)&idx1[i].icap, sizeof(short int)));
732
TRACE_ED_I("Sorting capabilities: ",(terms->nsr));
736
if ((terms->nsr) < 2) FINISH;
738
flag = 1; /* Indicates sort not complete */
739
idx = (short int *) (CAPLIST + terms->indexr);
743
for (i=0; i<(terms->nsr) -1; i++)
744
{ p1 = CAPLIST + idx[i] + 4;
745
p2 = CAPLIST + idx[i+1] + 4;
746
while (*p1 == *p2) p1++, p2++;
747
if (*p1 <= *p2) continue;
748
temp = idx[i]; idx[i] = idx[i+1]; idx[i+1] = temp;
753
/* Flag in `specials' chars that start escape sequences */
755
for (i=0; i<(terms->nsr); i++)
756
{ p1 = CAPLIST + idx[i] + 4;
757
if (*(unsigned char *)p1 < 32) terms->specials |=
758
MASK(*(unsigned char *)p1);
762
for (i=0; i<(terms->nsr); i++)
763
TRACE_ED_STR2("Caps sorted by sequence: ",
764
CAPLIST + idx[i] + 1 ,2);
771
/*==========================================================================
773
*==========================================================================*/
774
static int tu_build ()
776
.PURPOSE Generates the 2 indexes (by capcode - by sequences), and
787
*(CAPLIST + CAPTOP++) = EOS; /* Terminate the string */
789
/* Adjust the captop to a correct boundary */
791
CAPTOP = ((CAPTOP + sizeof(char *)-1)/sizeof(char *)) * sizeof(char *);
793
/* Save this position in term.index */
794
terms->index = CAPTOP;
796
/* Encode capabilities and generate the index by capabilities */
799
/* Generate the index by sequences */
800
CAPTOP = ((CAPTOP + sizeof(char *)-1)/sizeof(char *)) * sizeof(char *);
801
terms->indexr = CAPTOP;
809
/*==========================================================================
811
*==========================================================================*/
812
static int tu_fetch (device)
814
.PURPOSE Search the TERMCAP file for a specified device, and append the
815
caplist into CAPLIST.
816
.RETURNS NOK if device not found, OK otherwise
819
char *device; /* IN: EOS-terminated device name */
826
TRACE_ED_STRING("Looking for Device=>",device);
828
while ((status = f_gets(buffer,sizeof(buffer))) == OK)
829
{ if (buffer[0] == '#')
830
continue; /* Comment line */
831
if (isspace(buffer[0])) continue; /* Not useful */
832
i = stritem(buffer,device,":|");
833
/* Followed / preceded by : or | */
834
if (buffer[i]) break;
836
if (status != OK) FINISH; /* Device not found */
838
/* Now, load the caplist, which starts right now, at the :
839
* Note that the `\' indicates a continuation on the next line */
841
i = strloc(buffer, ':'); /* Starting scanning point */
843
for (; status == OK; status = f_gets(buffer,sizeof(buffer)))
844
{ if (buffer[0] == '#') /* Line commented out */
846
if (i == 0) i = oscspan((unsigned char *)buffer,sizeof(buffer), _SPACE_, main_ascii);
847
if (i<=0) break; /* List must start with blank or so */
848
j = strbspan(buffer,_SPACE_); /* Offset of last char */
849
l = j-i; /* Length of the termlist */
850
if (buffer[j] != '\\') l++;
851
call(tu_append(&buffer[i],l));
852
/* Test for continuation char \ */
853
if (buffer[j] != '\\') break;
856
if (status == NOK) FINISH;
859
TRACE_ED_STR2("CapList: ",CAPLIST,CAPTOP);
862
if (status != OK) status = NOK;
866
/*==========================================================================
868
*==========================================================================*/
869
static int tu_scan (device)
871
.PURPOSE Open the specified TERMCAP file for the named device, expanding
872
the ``tc='' references.
873
.RETURNS NOK if device not found, OK otherwise
876
char *device; /* IN: EOS-terminated device name */
881
/* ENTER("tu_scan"); */
883
TRACE_ED_STRING("Look for device: ", device);
886
/* Now, fetch the successive entries */
890
{ if (tu_fetch(tc_device) != OK)
891
{ ERR_ED_STRING("This device is unknown: ",tc_device);
894
*(CAPLIST + CAPTOP) = EOS; /* Terminate the string */
895
/* Locate last field */
896
p = CAPLIST + oscbloc(CAPLIST, CAPTOP, '=');
898
if (*(--p) != 'c') break; /* Should match "tc=" */
899
if (*(--p) != 't') break; /* Should match "tc=" */
900
/* An expansion is required - Reset the captop size in
901
* the term, and get the alternate device name */
902
tc_device++; /* Starting char of alternate device name */
903
*(CAPLIST + CAPTOP - 1) = EOS; /* Replace the : */
904
CAPTOP = p - CAPLIST; /* Last field is deleted */
915
/*==========================================================================
917
*==========================================================================*/
918
int tu_load (file_name, device, term)
920
.PURPOSE Load to TERM structure the specified device.
921
.RETURNS NOK if device or file not found, OK otherwise
922
.REMARKS Appends some defautt capabilities.
924
char *file_name; /* IN: EOS-terminated TERMCAP file name */
925
char *device; /* IN: EOS-terminated device name */
926
TERM *term; /* MOD: Area to receive capabilities */
932
TRACE_ED_STRING("TermCapFile: ", file_name);
937
/* First, open the TERMCAP file */
939
fn = osaopen(file_name,READ);
940
if (fn <= 0) ERR_ED_STRING("Bad TermCap File: ", file_name);
941
else status = tu_scan(device);
944
tu_append(defaults, sizeof(defaults)-1);
946
status &= tu_build();
949
TRACE_ED_STR2("CapList ",terms->caplist, terms->captop);