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

« back to all changes in this revision

Viewing changes to prim/tw3/libsrc/termcap.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
 
 
30
.TYPE           Module
 
31
.IDENTIFICATION termcap.c
 
32
.AUTHOR         Francois Ochsenbein [ESO-IPG]
 
33
.LANGUAGE       C
 
34
.KEYWORDS       Termcap
 
35
.ENVIRONMENT    TermWindows
 
36
 
 
37
.COMMENTS       The main program loads the TermCapFile into a binary
 
38
                structure in SYS$LOGIN.
 
39
 
 
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.
 
45
 
 
46
\begin{TeX}
 
47
 
 
48
\bigskip
 
49
\bigskip
 
50
 
 
51
{\bf Description of TERMCAPS}
 
52
 
 
53
 
 
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.
 
57
 
 
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}
 
61
     It is
 
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.
 
66
 
 
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
 
71
     entry).
 
72
 
 
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
 
79
     EMACS\_TERM command.)
 
80
 
 
81
          The remainder of the fields are specified  as  two  letter  field
 
82
     names.  These may be followed by a field value.  For instance:
 
83
 
 
84
\begin{quote}
 
85
               {\tt up=\b Eu:}\\
 
86
                {\tt li\#24:}\\
 
87
               {\tt ul:}
 
88
\end{quote}
 
89
 
 
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
 
93
        a booloean value).
 
94
{\em Note added by Fran\c cois Ochsenbein:}
 
95
        The `@' instead of `=' or `\#' means that 
 
96
{\em the capability does not exist.}
 
97
 
 
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). 
 
101
 
 
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.
 
111
 
 
112
 
 
113
$$\begin{tabular}{|llp{33em}|} \hline
 
114
 Field          &Padding   &Meaning \\
 
115
        \hline
 
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
 
128
                                   display.\\
 
129
 {\tt   cm=}    &P      &Moves the cursor;  see below.\\
 
130
 {\tt   co\#}   &       &Specifies  the  number  of  columns  per
 
131
                                   line.\\
 
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 
 
141
                                terminals).\\
 
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
 
157
                                   being inserted.\\
 
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
 
187
                                   overstriking.\\
 
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).\\
 
192
        \hline
 
193
\end{tabular}$$
 
194
 
 
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'
 
208
     string.)
 
209
 
 
210
 
 
211
          The string values for each name can have  the  following  special
 
212
     character sequences:
 
213
 
 
214
$$\begin{tabular}{|ll|} \hline
 
215
 
 
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 (:).\\
 
227
\hline
 
228
\end{tabular}$$
 
229
 
 
230
 
 
231
 
 
232
          Note:  You must use \b072 or \b: to represent a colon (`:') 
 
233
                in a field.
 
234
 
 
235
 
 
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:
 
240
 
 
241
$$\begin{tabular}{|lp{33em}|} \hline
 
242
 
 
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
 
250
                         Control-A).\\
 
251
 {\tt     \%+x } &      Use the ASCII character corresponding to the  line
 
252
                         or   column  number  plus  the  ASCII  number  for
 
253
                         character `x'.\\
 
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
 
263
                         140.\\
 
264
\hline
 
265
\end{tabular}$$
 
266
 
 
267
 
 
268
          For example:
 
269
 
 
270
\begin{center}
 
271
                  {\tt cm=\b E[\%d;\%dm}
 
272
\end{center}
 
273
 
 
274
     translates to ESCAPE, left bracket, the line number, a semicolon,  the
 
275
     column number, then a lowercase M.
 
276
 
 
277
 
 
278
 
 
279
{\bf \^{ }S And \^{ }Q Handling}
 
280
 
 
281
          If your terminal (or communications link) uses \^{ }Q and  \^{ }S  
 
282
        (X-on,
 
283
     X-off)  for  synchronization,  then  you  should  set  xon-protocol as
 
284
     follows:
 
285
 
 
286
\begin{quote}
 
287
{\tt (set-terminal-characteristic "xon-protocol" 1) }
 
288
\end{quote}
 
289
 
 
290
 
 
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.
 
297
 
 
298
 
 
299
          If you set xon-mode to 1, then you  must  also  have  TTSYNC  and
 
300
     HOSTSYNC set with the Set Terminal VMS command.
 
301
 
 
302
 
 
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  
 
306
        \^{ }\^{ }-
 
307
     (Control-uparrow-s,  and  Control-uparrow-q),  although  some  of  the
 
308
     oltimers use Control-\b\  and Control-H.
 
309
\end{TeX}
 
310
 
 
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
 
319
                of memory)
 
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)
 
328
 
 
329
 090831         last modif
 
330
----------------------------------------------------------------------------*/
 
331
 
 
332
#define DEBUG           0       /* For debugging only           */
 
333
 
 
334
#define PM_LEVEL        LEVEL_TU
 
335
 
 
336
#define         TW_MACROS       0       /* Don't use TermWindows Macros */
 
337
#define         TW_import       0       
 
338
#define         TW_STRUCT       0       /* Do not use window Structures         */
 
339
 
 
340
 
 
341
#include        <midas_def.h>
 
342
#include        <twset.h>
 
343
 
 
344
 
 
345
extern int eh_ed_str2(), eh_ed_as();
 
346
extern int pm_enter(), pm_ed_tr2(), pm_iexit(), pm_ed_trace();
 
347
 
 
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)
 
351
 
 
352
#define FINISH          goto FIN
 
353
 
 
354
#ifdef  call
 
355
#undef  call
 
356
#endif
 
357
#define call(x)         if (!(status = x))              FINISH  \
 
358
                                /* Exit on error                        */
 
359
 
 
360
MID_STATIC INDEX  ind={{' ',' '},0};
 
361
static int fn;                  /* TermCap File Number */
 
362
static TERM *terms;
 
363
 
 
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:";
 
366
 
 
367
                /* Macros just to improve readibility   */
 
368
 
 
369
#define         NCAPS                   (terms->ns)
 
370
#define         CAPLIST                 (terms->caplist)
 
371
#define         CAPSIZE                 (terms->size)
 
372
#define         CAPTOP                  (terms->captop)
 
373
 
 
374
 
 
375
/*      MONITOR(TERMCAP); */
 
376
 
 
377
/*===========================================================================*/
 
378
static int strloc(str, c)
 
379
/*+++++++
 
380
.PURPOSE Locate the first occurence of character `c'
 
381
.RETURNS Index within str of char c; length of str if not found.
 
382
---------*/
 
383
        char *str;      /* IN: string to scan   */
 
384
        char c;         /* IN: char to locate   */
 
385
{
 
386
        register char *p;
 
387
 
 
388
  for (p=str; *p; p++)
 
389
        if (*p == c)    break;
 
390
  return(p-str);
 
391
}
 
392
 
 
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.
 
402
-----------*/
 
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       */
 
406
{   
 
407
        register char *p1, *pe;
 
408
        register int i;
 
409
 
 
410
  i = strlen(s2);
 
411
  if (i == 0)   i = 1;
 
412
  
 
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 */
 
417
        {       p1--;
 
418
                if_not (*(sep + strloc(sep, *(p1++))))
 
419
                {       p1 += i;
 
420
                        continue;
 
421
                }
 
422
        }
 
423
        p1 += i;                        /* Check following char */
 
424
        if_not(*p1)     break;          /* Located at end : OK  */
 
425
        if(*(sep + strloc(sep, *p1)))   /* Separator found      */
 
426
                        break;
 
427
  }
 
428
 
 
429
  return(p1-s1);
 
430
}
 
431
 
 
432
/*==========================================================================
 
433
 *                      f_gets
 
434
 *==========================================================================*/
 
435
static int f_gets (buf, len)
 
436
/*+++
 
437
.PURPOSE Interface to file reading
 
438
.RETURNS OK / NOK / EOF
 
439
.REMARKS On return, always terminated by EOS.
 
440
---------*/
 
441
        char    *buf;   /* OUT: text, EOS-terminated    */
 
442
        int     len;    /* IN: Size of buffer           */
 
443
{
 
444
        register int status;
 
445
 
 
446
  status = osaread(fn, buf, len);
 
447
  if (status >= len)
 
448
        ERR_ED_STR2("Too long TermCapFile record: ", buf, 30);
 
449
  if (status >= 0)      status = OK;
 
450
#if DEBUG
 
451
  printf("Read from TermCapFile: %s\n",buf);
 
452
#endif 
 
453
 
 
454
  return(status);
 
455
}
 
456
 
 
457
/*==========================================================================
 
458
 *                      tu_encode
 
459
 *==========================================================================*/
 
460
static int tu_encode (str)
 
461
/*++++++++++++++
 
462
.PURPOSE Encode capabilities followed by the `=' sign, i.e.
 
463
\begin{TeX}
 
464
\begin{itemize}
 
465
        \item interpretation of delays into number of ms 
 
466
                (limited to 255)
 
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
 
470
                capability.
 
471
\end{itemize}
 
472
\end{TeX}
 
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        */
 
478
{
 
479
        register char *p1, *p2;
 
480
        register int delay;
 
481
        MID_STATIC char delay_flag = '=';
 
482
 
 
483
  ENTER("+tu_encode");
 
484
 
 
485
  TRACE_ED_STR2("Coding capability ",str,4);
 
486
 
 
487
  p1 = str;
 
488
  if (*p1 != ':')  {    ERR_ED_STR2("Bad TermCapability=>",str,4);
 
489
                        FINISH;
 
490
                   }
 
491
  p1 += 1;
 
492
  if (*p1)      p1 += 2;        /* Not Followed by EOS  */
 
493
 
 
494
  *str = 0;
 
495
  switch(*(p1))         /* Test char following the cap_code     */
 
496
  { case '@' :                  /* Nothing to code      */
 
497
        p1++;
 
498
    case ':' :  case EOS:       /* Nothing to code      */
 
499
        goto FIN;
 
500
    case '=' : break;
 
501
    default  :                  /* Do not code, but compute length      */
 
502
        delay = oscloc(p1, 80, ':');    /* Length */
 
503
        *str = delay - 1, p1 += delay;
 
504
        goto FIN;
 
505
  }
 
506
 
 
507
        /* Here, only if cap_code followed by `='. p1 and p2 are used
 
508
                as pointers to input / output string    */
 
509
  p1 = str+4, p2 = p1;
 
510
 
 
511
        /* Compute the delays, i.e. digits followed by optional `*'     */
 
512
  delay_flag = '=';
 
513
  for( delay = 0; isdigit(*p1); p1++) 
 
514
  {     delay *= 10;
 
515
        delay += (*p1 - '0');
 
516
        delay_flag = 'd';
 
517
  }
 
518
  if(*p1 == '*')        p1++, delay_flag = 'D';
 
519
 
 
520
  for(; *p1 != ':'; p2++)       /* The `:' indicates the end */
 
521
  {     switch(*p1)     
 
522
        { case '^':     /* Control Char */ 
 
523
                *p2 = (*(++p1)) & 037;
 
524
                p1++; break;
 
525
          case '\\':    /* Escape - Look next char      */
 
526
                p1++, *p2 = 0;
 
527
                switch(*p1)
 
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 */
 
535
                        case '3':
 
536
                        while(isdigit(*p1))
 
537
                        {       *(unsigned char *)p2 *= 8; 
 
538
                                *(unsigned char *)p2 += *(p1++) - '0';
 
539
                        }
 
540
                        /*      *p2 &= 0177;    /. Convert to ASCII     */
 
541
                        break;
 
542
                  default:      /* case '^': case '\\': and others      */
 
543
                        *p2 = *(p1++); break;
 
544
                } break;
 
545
          case '%':     /* May be a format      */
 
546
                if (*(++p1) == '%')     *p2 = *(p1++);  /* `%' sign     */
 
547
                        else            *p2 = FORMAT;
 
548
                break;
 
549
          default:      /* Normal char          */
 
550
                *p2 = *(p1++);
 
551
        }
 
552
  }
 
553
 
 
554
        /* Write the length of the coded string */
 
555
  *str = p2 - str - 4;
 
556
 
 
557
        /* Insert the delay --- limited to 255 ms !     */
 
558
  if (delay)
 
559
  {     *(str+3) = delay_flag;
 
560
        *(unsigned char *)p2   = MIN(delay, 255);
 
561
  }
 
562
 
 
563
#if DEBUG
 
564
  TRACE_ED_STR2("Coded:",str+4,*str);
 
565
  if(*(str+3) != '=')   TRACE_ED_I("Delay is ",*(str + 4 + *str));
 
566
#endif
 
567
 
 
568
  FIN:
 
569
  EXIT(p1 - str);
 
570
}
 
571
        
 
572
/*==========================================================================
 
573
 *                      tu_append
 
574
 *==========================================================================*/
 
575
static int tu_append (buffer, len)
 
576
/*+++++++++
 
577
.PURPOSE Append into the TERMCAP list the specified buffer.
 
578
.RETURNS OK / NOK
 
579
.REMARKS Not traced.
 
580
---------*/
 
581
        char *buffer;           /* IN: Buffer to copy           */
 
582
        int  len;               /* IN: Length of buffer         */
 
583
{
 
584
        register int n;
 
585
 
 
586
  if (len <= 0)         return(OK);
 
587
 
 
588
                                /* Test for 2 consecutive : */
 
589
  if ( (*buffer == ':') && (CAPTOP > 0)) 
 
590
        if (*(CAPLIST + CAPTOP -1) == ':')      len--,  buffer++;
 
591
 
 
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    */
 
598
        CAPSIZE = n;
 
599
  }
 
600
                                /* Copy caplist to area         */
 
601
  CAPTOP += oscopy(CAPLIST + CAPTOP, buffer, len);
 
602
 
 
603
  return(OK);
 
604
}
 
605
 
 
606
/*==========================================================================
 
607
 *                      tu_x1
 
608
 *==========================================================================*/
 
609
static int tu_x1 ()
 
610
/*++++++++++
 
611
.PURPOSE Encodes the capabilities and generates the index by capability
 
612
.RETURNS OK/NOK
 
613
.REMARKS The first encountered capability wins if duplicates
 
614
        exist --- however, input sequences are stored several times
 
615
        when duplicates exist.
 
616
-----------------*/
 
617
{
 
618
        register int i,j;
 
619
        INDEX   *idx;           /* Starting address of index by capability */
 
620
        int     flag, status;
 
621
        
 
622
#if DEBUG
 
623
        MID_STATIC char cap3[] = "xx: ";
 
624
#endif
 
625
 
 
626
  ENTER("tu_x1");
 
627
 
 
628
  status = NOK;
 
629
  NCAPS = 0;                    /* No sequences         */
 
630
 
 
631
        /* Scan the caplist - each cap starts and ends with `:' */
 
632
 
 
633
  for ( i = 0; isgraph(*(CAPLIST+i)) ;  i += j)
 
634
  {     idx = (INDEX *) (CAPLIST + terms->index);       
 
635
                                        /* May have been reallocated... */
 
636
        j = i + 1;
 
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             */
 
640
 
 
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]));
 
646
        }
 
647
        j = tu_encode(i + CAPLIST);
 
648
        if (j < 3)                      /* Don't add to index   */
 
649
        {       flag = 1;
 
650
                if (j <= 0)     FINISH;
 
651
        }
 
652
        if(flag)        continue;       /* Already exists       */
 
653
 
 
654
        NCAPS++;                        /* Add a new entry      */
 
655
        call(tu_append((char *)&ind,sizeof(ind)));
 
656
                        /* Encode the capabilities              */
 
657
  }
 
658
 
 
659
                /* Sorting via a simple interchange             */
 
660
#if DEBUG
 
661
  TRACE_ED_I("Sorting capabilities ",NCAPS);
 
662
#endif
 
663
  status = OK;
 
664
  if (NCAPS < 2)        FINISH;
 
665
 
 
666
  flag = NCAPS-1;       
 
667
 
 
668
  idx = (INDEX *) (CAPLIST + terms->index);
 
669
 
 
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;
 
676
        }
 
677
  }
 
678
 
 
679
#if DEBUG
 
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));
 
684
  }
 
685
#endif
 
686
 
 
687
  FIN:
 
688
  EXIT(status);
 
689
}
 
690
 
 
691
/*==========================================================================
 
692
 *                      tu_x2
 
693
 *==========================================================================*/
 
694
static int tu_x2 ()
 
695
/*+++++++++++
 
696
.PURPOSE Generates the index by sequences (made with short integers)
 
697
.RETURNS OK/NOK
 
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)
 
701
-----------*/
 
702
{
 
703
        register int i;
 
704
        register char *p1, *p2;
 
705
        INDEX *idx1;            /* Starting address of index by capability */
 
706
        short int  *idx;        /* Starting address of index by sequence */
 
707
        short int temp;
 
708
        char    flag;
 
709
        int     status;
 
710
 
 
711
  ENTER("tu_x2");
 
712
 
 
713
  status = NOK;
 
714
  
 
715
        /* Simply use the index by capcodes ---
 
716
           Keep only capcodes starting with 'k', 'K' or 'F'     */
 
717
 
 
718
  terms->nsr = 0;               /* No readable sequence         */
 
719
  terms->specials = 0;
 
720
 
 
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)));
 
726
                (terms->nsr)++;
 
727
        }
 
728
  }
 
729
 
 
730
        /* Sort ... */
 
731
#if DEBUG
 
732
  TRACE_ED_I("Sorting capabilities: ",(terms->nsr));
 
733
#endif
 
734
 
 
735
  status = OK;
 
736
  if ((terms->nsr) < 2)         FINISH;
 
737
 
 
738
  flag = 1;     /* Indicates sort not complete  */
 
739
  idx  = (short int *) (CAPLIST + terms->indexr);
 
740
 
 
741
  while(flag)
 
742
  {     flag = 0;
 
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;
 
749
                flag = 1;
 
750
        }
 
751
  }
 
752
 
 
753
        /* Flag in `specials' chars that start escape sequences */
 
754
 
 
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);
 
759
  }
 
760
 
 
761
#if DEBUG
 
762
        for (i=0; i<(terms->nsr); i++)
 
763
                TRACE_ED_STR2("Caps sorted by sequence: ",
 
764
                        CAPLIST + idx[i] + 1 ,2);
 
765
#endif
 
766
 
 
767
  FIN:
 
768
  EXIT(status);
 
769
}
 
770
 
 
771
/*==========================================================================
 
772
 *                      tu_build
 
773
 *==========================================================================*/
 
774
static int tu_build ()
 
775
/*++++++++
 
776
.PURPOSE Generates the 2 indexes (by capcode - by sequences), and
 
777
        encodes the caps.
 
778
.RETURNS OK/NOK
 
779
.REMARKS 
 
780
----------*/
 
781
{
 
782
        int     status;
 
783
        
 
784
  ENTER("tu_build");
 
785
  status = NOK;
 
786
 
 
787
  *(CAPLIST + CAPTOP++) = EOS;  /* Terminate the string */
 
788
 
 
789
        /* Adjust the captop to a correct boundary      */
 
790
 
 
791
  CAPTOP = ((CAPTOP + sizeof(char *)-1)/sizeof(char *)) * sizeof(char *);
 
792
 
 
793
        /* Save this position in term.index     */
 
794
  terms->index = CAPTOP;
 
795
 
 
796
        /* Encode capabilities and generate the index by capabilities   */
 
797
  call(tu_x1());
 
798
 
 
799
        /* Generate the index by sequences      */
 
800
  CAPTOP = ((CAPTOP + sizeof(char *)-1)/sizeof(char *)) * sizeof(char *);
 
801
  terms->indexr = CAPTOP;
 
802
  call(tu_x2());
 
803
  status = OK;
 
804
 
 
805
  FIN:
 
806
  EXIT(status);
 
807
}
 
808
 
 
809
/*==========================================================================
 
810
 *                      tu_fetch
 
811
 *==========================================================================*/
 
812
static int tu_fetch (device)
 
813
/*++++++++++++++
 
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
 
817
.REMARKS 
 
818
------------------*/
 
819
        char *device;           /* IN: EOS-terminated device name       */
 
820
{
 
821
        int i, j, l, status;
 
822
        char buffer[1024];
 
823
 
 
824
  ENTER("tu_fetch");
 
825
 
 
826
  TRACE_ED_STRING("Looking for Device=>",device);
 
827
 
 
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;
 
835
  }
 
836
  if (status != OK)     FINISH;         /* Device not found     */
 
837
 
 
838
        /* Now, load the caplist, which starts right now, at the :
 
839
         * Note that the `\' indicates a continuation on the next line  */
 
840
 
 
841
  i = strloc(buffer, ':');      /* Starting scanning point */
 
842
 
 
843
  for (; status == OK; status = f_gets(buffer,sizeof(buffer)))
 
844
  {     if (buffer[0] == '#')           /* Line commented out   */
 
845
                continue;
 
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;
 
854
        i = 0;
 
855
  }
 
856
  if (status == NOK)    FINISH;
 
857
 
 
858
  status = OK;
 
859
  TRACE_ED_STR2("CapList: ",CAPLIST,CAPTOP);
 
860
 
 
861
  FIN:
 
862
  if (status != OK)     status = NOK;
 
863
  EXIT(status);
 
864
}
 
865
 
 
866
/*==========================================================================
 
867
 *                      tu_scan
 
868
 *==========================================================================*/
 
869
static int tu_scan (device)
 
870
/*+++++++++++
 
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
 
874
.REMARKS 
 
875
---------------*/
 
876
        char *device;           /* IN: EOS-terminated device name       */
 
877
{
 
878
        char    *p, *tc_device;
 
879
        int     status;
 
880
 
 
881
  /* ENTER("tu_scan"); */
 
882
 
 
883
  TRACE_ED_STRING("Look for device: ", device);
 
884
  status = NOK;
 
885
 
 
886
        /* Now, fetch the successive entries            */
 
887
  tc_device = device;
 
888
 
 
889
  while(1)
 
890
  {     if (tu_fetch(tc_device) != OK) 
 
891
        {       ERR_ED_STRING("This device is unknown: ",tc_device);
 
892
                FINISH;;
 
893
        }       
 
894
        *(CAPLIST + CAPTOP) = EOS;      /* Terminate the string */
 
895
                        /* Locate last field    */
 
896
        p = CAPLIST + oscbloc(CAPLIST, CAPTOP, '=');
 
897
        tc_device = p;
 
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        */
 
905
        osaseek(fn, 0L, 0);
 
906
  }
 
907
 
 
908
  status = OK;
 
909
  osaclose(fn);
 
910
 
 
911
  FIN:
 
912
  return(status);
 
913
}
 
914
 
 
915
/*==========================================================================
 
916
 *                      tu_load
 
917
 *==========================================================================*/
 
918
int tu_load (file_name, device, term)
 
919
/*++++++++++++
 
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.
 
923
----------------*/
 
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 */
 
927
{
 
928
        int     status;
 
929
 
 
930
  ENTER("tu_load");
 
931
 
 
932
  TRACE_ED_STRING("TermCapFile: ", file_name);
 
933
  status = NOK;
 
934
 
 
935
  terms = term;
 
936
 
 
937
        /* First, open the TERMCAP file */
 
938
 
 
939
  fn = osaopen(file_name,READ);
 
940
  if (fn <= 0)  ERR_ED_STRING("Bad TermCap File: ", file_name);
 
941
  else          status = tu_scan(device);
 
942
  if (!status)  FINISH;
 
943
 
 
944
  tu_append(defaults, sizeof(defaults)-1);
 
945
 
 
946
  status &= tu_build(); 
 
947
 
 
948
#if DEBUG
 
949
        TRACE_ED_STR2("CapList       ",terms->caplist, terms->captop);
 
950
#endif
 
951
 
 
952
  FIN:
 
953
  EXIT(status);
 
954
}
 
955