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

« back to all changes in this revision

Viewing changes to libsrc/tw/tvgets.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
/* @(#)tvgets.c 19.1 (ES0-DMD) 02/25/03 13:58:14 */
 
2
/*===========================================================================
 
3
  Copyright (C) 1995 European Southern Observatory (ESO)
 
4
 
 
5
  This program is free software; you can redistribute it and/or 
 
6
  modify it under the terms of the GNU General Public License as 
 
7
  published by the Free Software Foundation; either version 2 of 
 
8
  the License, or (at your option) any later version.
 
9
 
 
10
  This program is distributed in the hope that it will be useful,
 
11
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
  GNU General Public License for more details.
 
14
 
 
15
  You should have received a copy of the GNU General Public 
 
16
  License along with this program; if not, write to the Free 
 
17
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
 
18
  MA 02139, USA.
 
19
 
 
20
  Corresponding concerning ESO-MIDAS should be addressed as follows:
 
21
        Internet e-mail: midas@eso.org
 
22
        Postal address: European Southern Observatory
 
23
                        Data Management Division 
 
24
                        Karl-Schwarzschild-Strasse 2
 
25
                        D 85748 Garching bei Muenchen 
 
26
                        GERMANY
 
27
===========================================================================*/
 
28
 
 
29
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
30
 
 
31
.TYPE           Module
 
32
.IDENTIFICATION tvgets.c
 
33
.AUTHOR         Francois Ochsenbein [ESO-IPG]
 
34
.LANGUAGE       C
 
35
.KEYWORDS       On-line input editing
 
36
.ENVIRONMENT    TermWindows
 
37
.COMMENTS       This module contains routines to perform command input,
 
38
                at the Terminal Level
 
39
\begin{TeX}
 
40
\\
 
41
This module is only there to be able to use on-line editiing
 
42
facilities without any window. Unlike tw\_gets functions,
 
43
commands are not stacked, and the memory is limited to
 
44
what was just typed.
 
45
 
 
46
The default actions of control characters are defined as TW\_cc\_default
 
47
in {\tt twparam.h}, with choices UNIX-like, VMS-like or a third
 
48
set. The action of each control character may be modified with the
 
49
tv\_setcc(control\_character, action) (DefineControl) function.
 
50
 
 
51
The characters that stop output may be defined via the tv\_stopin
 
52
funtion.
 
53
 
 
54
\end{TeX}
 
55
 
 
56
.VERSION 3.0    14-Apr-1988: Creation for MIDAS usage.
 
57
.VERSION 3.1    05-Oct-1988: Modifications for MIDAS: Command Stacking allowed.
 
58
.VERSION 3.2    21-Feb-1990: Suppress all warnings
 
59
 
 
60
-----------------------------------------------------------------------*/
 
61
 
 
62
#define DEBUG           0               /* For debugging        */
 
63
 
 
64
#define PM_LEVEL        LEVEL_TV
 
65
 
 
66
#define TW_import       0       
 
67
#define TW_STRUCT       0       /* Do not use window Structures         */
 
68
#define TW_MACROS       0       /* Don't use Windows Macros */
 
69
#include <twset.h>
 
70
 
 
71
MID_EXTERN TERM *terms ;                
 
72
 
 
73
#if     DEBUG
 
74
#       define ENTER_DEBUG(x)   ENTER(x)
 
75
#       define EXIT_DEBUG(x)    EXIT(x)
 
76
#       define  TERMTEST        if(!terms->version) tv_gopen();\
 
77
                                tv_ed(terms)
 
78
#else
 
79
#       define  TERMTEST        if(!terms->version) tv_gopen()
 
80
#       define ENTER_DEBUG(x)   
 
81
#       define EXIT_DEBUG(x)    return(x)
 
82
#endif
 
83
 
 
84
#define FINISH          goto FIN
 
85
 
 
86
MID_STATIC unsigned int         f = 0;          /* Flags to communicate */
 
87
MID_STATIC unsigned int         f0= Echo|Stacking;/* Flags to communicate       */
 
88
static int      J;                      /* Column width         */
 
89
static int      init_pos;               /* Where is the cursor at beginning */
 
90
static char     *p_start;
 
91
MID_STATIC char         *stop_list = (char *)0;
 
92
MID_STATIC int  stop_len = 0;
 
93
 
 
94
#define Stop            0x0100
 
95
#define Stop1           0x0400
 
96
#define Special         0x0200
 
97
#define NoMore          0x1000
 
98
#define Raw             0x2000
 
99
 
 
100
/* Stored Commands as a static structure */
 
101
 
 
102
static unsigned char command_buffer[1600] = {0,0,0,0};
 
103
 
 
104
static COMMAND command = {
 
105
                MASK('\r'),     /* Which controls exit */
 
106
                0,              /* Which arrow keys exit */
 
107
                0,              /* Which special keys exit */
 
108
                0,              /* last_type    */
 
109
                0,              /* last_char    */
 
110
                sizeof(command_buffer), 
 
111
                2,              /* used         */
 
112
                0,              /* pointed      */
 
113
                0,              /* pointed_no   */
 
114
                1,              /* first_no     */
 
115
                0,              /* last_no      */
 
116
                command_buffer
 
117
        };
 
118
 
 
119
static COMMAND *c = &command;
 
120
static short command_number;
 
121
static int   command_len;
 
122
 
 
123
        MONITOR(TVGETS);
 
124
 
 
125
 
 
126
/*==========================================================================
 
127
 *                      o1
 
128
 *==========================================================================*/
 
129
static int o1(ch, len)
 
130
/*+++
 
131
.PURPOSE Optimized output of 1 character.
 
132
.RETURNS 0 / 1 (number of chars output on Screen)
 
133
.REMARKS Complete string rewritten if in InsertMode.
 
134
---*/
 
135
        char    *ch;                    /* IN: Character to output      */
 
136
        int      len;                   /* IN: Length of input          */
 
137
{
 
138
        char    *p;
 
139
        int     state_buffer;
 
140
 
 
141
  ENTER_DEBUG("+o1");
 
142
 
 
143
  if_not(f&Echo)        EXIT_DEBUG(0);
 
144
 
 
145
  p = ch;
 
146
 
 
147
  state_buffer = tv_buffer(1);          /* To output only at end */
 
148
  status = WriteBinary(p, 1);
 
149
  p++;
 
150
 
 
151
  if ( f & Imode)               /* Continuation to write */
 
152
  {     len--;
 
153
        WriteBinary(p, len);
 
154
        SetPosition(GetPosition() - len);
 
155
  }
 
156
 
 
157
  tv_buffer(state_buffer);              /* Output everything    */
 
158
 
 
159
        /* Check if the Screen scrolled; modify accordingly init_pos */
 
160
  init_pos = GetPosition() - (p - p_start);
 
161
 
 
162
  EXIT_DEBUG(status);
 
163
}
 
164
 
 
165
/*======================================================================
 
166
 *                      mv1
 
167
 *======================================================================*/
 
168
static int mv1(direction, max_move)
 
169
/*+++++
 
170
.PURPOSE Optimized cursor mouvement of 1 place in the specified
 
171
        direction: up, down, right, left or home.
 
172
.RETURNS The actual displacement in bytes.
 
173
.REMARKS Move is limited...
 
174
------*/
 
175
        int direction;  /* IN: The direction of the displacement        */
 
176
        int max_move;   /* IN: Maximal right / down displacement in bytes */
 
177
{
 
178
        int pos, new_pos;
 
179
        
 
180
  ENTER_DEBUG("+mv1");
 
181
 
 
182
  pos = GetPosition();
 
183
  new_pos = pos;
 
184
 
 
185
  switch(direction)
 
186
  { case _LEFT_:        new_pos -= 1;   break;
 
187
    case _RIGHT_:       new_pos += MIN(max_move, 1);    break;
 
188
    case _UP_:          new_pos -= J;   break;
 
189
    case _DOWN_:        new_pos += MIN(max_move, J);    break;
 
190
    default:            new_pos  = init_pos;
 
191
  }
 
192
 
 
193
  if (new_pos < init_pos)       new_pos = init_pos;
 
194
  SetPosition(new_pos);
 
195
 
 
196
  EXIT_DEBUG(new_pos - pos);
 
197
}
 
198
 
 
199
/*======================================================================
 
200
 *                      dc
 
201
 *======================================================================*/
 
202
static int dc(str, nd, len)
 
203
/*+++++
 
204
.PURPOSE Delete characters at left of cursor.
 
205
.RETURNS 0
 
206
.REMARKS 
 
207
------*/
 
208
        char *str;      /* IN: The new string */
 
209
        int  nd;        /* IN: Number of bytes to delete        */
 
210
        int  len;       /* IN: Length of text   */
 
211
{
 
212
        int     pos, nb, state_buffer;
 
213
        static char blanks[] = "        ";
 
214
        
 
215
        
 
216
  ENTER_DEBUG("dc");
 
217
 
 
218
  state_buffer = tv_buffer(1);          /* To output only at end */
 
219
  pos = GetPosition() - nd;
 
220
  SetPosition(pos);
 
221
  /* ClearDown(); */
 
222
  if (len)      WriteBinary(str, len);
 
223
  for (nb = nd; nb > 0; nb -= sizeof(blanks)-1) 
 
224
        WriteBinary(blanks, MIN(nb, sizeof(blanks)-1));
 
225
 
 
226
  SetPosition(pos);
 
227
  tv_buffer(state_buffer);              /* Output everything    */
 
228
 
 
229
  EXIT_DEBUG(0);
 
230
}
 
231
 
 
232
/*======================================================================
 
233
 *                      show
 
234
 *======================================================================*/
 
235
static int show(str, in, len)
 
236
/*+++++
 
237
.PURPOSE Redisplay the string (in, len) in place of the current command,
 
238
        and copy it to str.
 
239
.RETURNS Length of string
 
240
.REMARKS 
 
241
------*/
 
242
        char    *str;   /* OUT: copied string           */
 
243
        char    *in;    /* IN: string to display        */
 
244
        int     len;    /* IN: Length of in             */
 
245
{
 
246
        int     l;
 
247
 
 
248
  l = MIN (len, command_len);
 
249
  oscopy  (str, in, l);
 
250
  SetPosition(init_pos);
 
251
  ClearDown();
 
252
  WriteBinary(str, l);
 
253
        /* Check if the Screen scrolled; modify accordingly init_pos */
 
254
  init_pos = GetPosition() - l;
 
255
 
 
256
  return(l);
 
257
}
 
258
 
 
259
/*==========================================================================*/
 
260
static int zm(direction)
 
261
/*+++
 
262
.PURPOSE Move in the command stack according to the specified direction.
 
263
.RETURNS OK / NOK (at the top or bottom of the stack)
 
264
.REMARKS 
 
265
---*/
 
266
        int     direction;      /* IN: _UP_, _DOWN_ or _HOME_ (last command) */
 
267
{
 
268
 
 
269
  status = NOK;
 
270
 
 
271
  switch(direction)
 
272
  { case _UP_:          /* Towards the beginning of the stack   */
 
273
        if (c->pointed_no <= c->first_no)       
 
274
        {       c->pointed_no   = c->first_no - 1;
 
275
                c->pointed      = 0;
 
276
                FINISH;
 
277
        }
 
278
        (c->pointed_no)--;
 
279
        (c->pointed)--;         /* Index of suffix length       */
 
280
        (c->pointed) -= (1 + *(c->text + c->pointed));
 
281
        break;
 
282
    case _DOWN_:        /* Towards the bottom of the stack      */
 
283
        if (c->pointed_no >= c->last_no)        
 
284
        {       c->pointed_no   = c->last_no + 1;
 
285
                c->pointed      = c->used;
 
286
                FINISH;
 
287
        }
 
288
        (c->pointed_no)++;
 
289
        (c->pointed) += (2 + *(c->text + c->pointed));
 
290
        break;
 
291
    default:            /* The last issued command              */
 
292
        if (c->last_no < c->first_no)   
 
293
        {       c->pointed_no   = 0;
 
294
                c->pointed      = 0;
 
295
                FINISH;
 
296
        }
 
297
        c->pointed_no   = c->last_no;
 
298
        c->pointed      = (c->used) - 1;
 
299
        (c->pointed) -= (1 + *(c->text + c->pointed));
 
300
        break;
 
301
  }
 
302
 
 
303
  status = OK;
 
304
  FIN:
 
305
  return(status);
 
306
}
 
307
 
 
308
/*==========================================================================
 
309
 *                      zadd
 
310
 *==========================================================================*/
 
311
static int zadd(str, nbytes, opt)
 
312
/*+++
 
313
.PURPOSE Insert into the command stack the string str.
 
314
.RETURNS OK / NOK (not enough space)
 
315
.REMARKS 
 
316
---*/
 
317
        char    *str;   /* IN: The string to insert */
 
318
        int     nbytes;         /* IN: Length of the str string */
 
319
        int     opt;            /* IN: Option 1 to add effectively / 2 only if\
 
320
                                        differs from previous   */
 
321
{
 
322
        char    *p;
 
323
        int     i,u, l;
 
324
 
 
325
  TRACE_ED_STR2("Command = ",str,nbytes);
 
326
 
 
327
  status = NOK;
 
328
 
 
329
  if (nbytes < 0)               FINISH;
 
330
  if (c->size == 0)             FINISH;
 
331
 
 
332
        /* Check it it's the same command as previous one       */
 
333
        
 
334
  if ((opt == 2) && zm(_HOME_))         /* Get last command     */
 
335
  {     p = (char *)(c->text + c->pointed);
 
336
        if ((*(p++) == nbytes) && (oscomp(p, str, nbytes) == 0))
 
337
        {       status = OK;
 
338
                FINISH;
 
339
        }
 
340
  }
 
341
 
 
342
  u = c->used + nbytes + 2;     /* Used bytes after addition    */
 
343
  i = 2;
 
344
  
 
345
  while (u > c->size)           /* Look if stack must be compressed     */
 
346
  {     l = *(c->text + i) + 2; /* Length of command    */
 
347
        (c->first_no)++;
 
348
        u -= l, i += l;
 
349
  }
 
350
 
 
351
  if (u < 2)                            /* Not enough space ... */
 
352
  {     c->used = 2;
 
353
        FINISH;
 
354
  }
 
355
 
 
356
  if (i>2) 
 
357
  {     l = c->used - i;                /* Length to copy       */
 
358
        c->used = 2 + oscopy((char *)(c->text+2), (char *)(c->text + i), l);
 
359
  }
 
360
 
 
361
  c->pointed = c->used;
 
362
 
 
363
  p          = (char *)(c->text + c->used);
 
364
  *(p++) = nbytes;                      /* Prefix length        */
 
365
  p += oscopy((char *)p, (char *)str, nbytes);
 
366
                                        /* Copy text            */
 
367
  *(p++) = nbytes;                      /* Suffix length        */
 
368
 
 
369
  if (opt)                              /* Modify only if required */
 
370
  {     c->used = (unsigned char *)p - (c->text);
 
371
        (c->last_no)++;
 
372
        (c->pointed_no) = c->last_no;
 
373
  }
 
374
 
 
375
  status = OK;
 
376
 
 
377
  FIN:
 
378
  return(status);
 
379
}
 
380
 
 
381
/*==========================================================================
 
382
 *                      tv_stopin
 
383
 *==========================================================================*/
 
384
int     tv_stopin(type, list)
 
385
/*+++
 
386
.PURPOSE Define the list of Characters that stop the Input:
 
387
        Control Characters, Arrows, Keypad, Function Keys.
 
388
.RETURNS OK / NOK 
 
389
.REMARKS For type _STANDARD_ or _ARROW_, list gives the ASCII equivalence,
 
390
        e.g. A for Control A, U for the Up Key. 
 
391
        For a void string (""), all stopping characters are removed;
 
392
        a string starting with + means "add to existing list",
 
393
        with - "delete from existing list".
 
394
        The * acts as the wild character, e.g. "*-" means "delete all".
 
395
        By default, only the \r (Carriage-Return) stops the input.
 
396
---*/
 
397
        int     type;   /* IN: _STANDARD_ , _ARROW_, _KEYPAD_, _PF_ or _FK_ */
 
398
        char    *list;  /* IN: The characters that may be used to terminate; \
 
399
                                the * is used as a wild character \
 
400
                                (enable all)    */
 
401
{
 
402
        char *p;
 
403
        int wild;
 
404
        unsigned int i;
 
405
 
 
406
  ENTER("tv_stopin");
 
407
 
 
408
  if_not(list)          EXIT(NOK);
 
409
  p = list;
 
410
  wild = (*p == '+' ? 1 : (*p == '-' ? -1 : 0));
 
411
  
 
412
  switch(type)
 
413
  { case _ARROW_:
 
414
        if_not(wild)    c->exit_ar = 0;
 
415
        for ( ; *p; p++)
 
416
        {       switch(tolower(*p))
 
417
                { case 'u': i = MASK(_UP_);     break;
 
418
                  case 'd': i = MASK(_DOWN_);   break;
 
419
                  case 'l': case 'b': i = MASK(_LEFT_);         break;
 
420
                  case 'r': case 'f': i = MASK(_RIGHT_);        break;
 
421
                  default : i = MASK(_HOME_);   break;
 
422
                  case '*': i = 0xff;   break;;
 
423
                  case '+': wild = 1;           continue;
 
424
                  case '-': wild = -1;          continue;
 
425
                }
 
426
                if (wild<0)     c->exit_ar &= ~i;
 
427
                else            c->exit_ar |=  i;
 
428
        }
 
429
        break;
 
430
 
 
431
    case _KEYPAD_: case _PF_: case _FK_:
 
432
        i = MASK(type);
 
433
        if (*p == '*')  wild = 1;
 
434
        if (wild)       c->exit_pf &= ~i;
 
435
        if (wild > 0)   c->exit_pf |= i;
 
436
        break;
 
437
 
 
438
    default:            /* Control Characters */
 
439
        if_not(wild)    c->exit_cc = MASK('\r');
 
440
        for ( ; *p; p++)
 
441
        {       switch(*p)      
 
442
                { case '+':     wild = 1;       continue;
 
443
                  case '-':     wild = -1;      continue;
 
444
                  case '*':     i = (unsigned int)0xffffffff;   break;
 
445
                  default:      i = MASK(Control_(*p)); break;
 
446
                }
 
447
                if (wild<0)     c->exit_cc &= ~i;
 
448
                else            c->exit_cc |=  i;
 
449
        }
 
450
        break;
 
451
  }
 
452
 
 
453
  EXIT(OK);
 
454
}
 
455
 
 
456
/*==========================================================================
 
457
 *                      tv_get1
 
458
 *==========================================================================*/
 
459
int tv_get1(str, nbytes, stop1)
 
460
/*+++
 
461
.PURPOSE Get a command string from terminal, made of up to (nbytes-1)
 
462
        characters, but stop if one of the characters
 
463
        in stop1 was hit as the {\em first} input.
 
464
.RETURNS _EOF_ / 0 / _STANDARD_ / _ARROW_ / _KEYPAD_ / _FK_ / _PF_
 
465
        (see tv_mods)
 
466
---*/
 
467
        char    *str;           /* MOD: The buffer to get the input     */
 
468
        int     nbytes;         /* IN: Length of the input buffer       */
 
469
        char    *stop1;         /* IN: List of characters to stop       */
 
470
{
 
471
        int     status;
 
472
 
 
473
  ENTER("tv_get1");
 
474
 
 
475
  stop_list = stop1;
 
476
  stop_len  = strlen(stop1);
 
477
  status    = tv_mods(str, nbytes, 0);
 
478
  stop_len  = 0;
 
479
 
 
480
  EXIT(status);
 
481
}
 
482
  
 
483
/*==========================================================================
 
484
 *                      tv_getp
 
485
 *==========================================================================*/
 
486
int tv_getp(str, nbytes)
 
487
/*+++
 
488
.PURPOSE Get a password (no echo)
 
489
.RETURNS _EOF_ / 0 / _STANDARD_ / _ARROW_ / _KEYPAD_ / _FK_ / _PF_
 
490
        (see tv_mods)
 
491
---*/
 
492
        char    *str;           /* MOD: The buffer to get the input     */
 
493
        int     nbytes;         /* IN: Length of the input buffer       */
 
494
{
 
495
        int     status;
 
496
 
 
497
  ENTER("tv_getp");
 
498
 
 
499
  f0 = 0;
 
500
  status    = tv_mods(str, nbytes, 0);
 
501
  f0 = Echo | Stacking;
 
502
 
 
503
  EXIT(status);
 
504
}
 
505
  
 
506
/*==========================================================================
 
507
 *                      tv_mods
 
508
 *==========================================================================*/
 
509
int     tv_mods(str, nbytes, linput)
 
510
/*+++
 
511
.PURPOSE Display a template command, and get a command string 
 
512
        from terminal, made of up to (nbytes-1)
 
513
        characters, and echo. 
 
514
        The input stops when the one of the characters
 
515
        specified by tv_stopin is hit (the Carriage Return only by default).
 
516
\begin{TeX}
 
517
        {\em Note that} keypad characters are considered as normal chars,
 
518
        unless {\tt tv\_stopin(w, \_KEYPAD\_,"*")}  was called.
 
519
\end{TeX}
 
520
.RETURNS OK or _STANDARD_, EOF, NOK, _KEYPAD_, _PF_, _FK_ with the 
 
521
following meanings:
 
522
\begin{TeX}
 
523
\begin{itemize}
 
524
\item   OK or \_STANDARD\_: a $<$Carriage\_Return$>$ or $<$Enter$>$
 
525
        terminates the input;
 
526
        this last character is not reported to the string,
 
527
        but {\em is replaced by the EOS character.}
 
528
\item   NOK: either
 
529
        \begin{itemize}
 
530
        \item the size of the input string is 1 character or less
 
531
                (nbytes $<2$)
 
532
        \item a control / arrow / keypad / PK / Function character was typed 
 
533
                at the terminal, which is {\em not the 
 
534
                first} input char;
 
535
                the returned string contains the previous characters
 
536
                (\ie before the stopping char), and a next call to 
 
537
                the function will return the control character.
 
538
        \end{itemize}
 
539
\item   EOF: the EOF (Control\_Z or Control\_D, depending on initialization) 
 
540
        char was typed as the
 
541
        {\em first} input character; the output string contains only
 
542
        a zero (EOS).
 
543
        {\em Note that the EOF character not typed as the first char
 
544
        returns NOK.}
 
545
\item   \_KEYPAD\_: a keypad key is the 
 
546
        {\em first} input character and the Keypad is enabled
 
547
        via a previous call to {\tt tv\_stopin(w, \_KEYPAD\_, "*")}; 
 
548
        the output string contains the equivalence keypad.
 
549
        If the Keypad is enabled via {\em tv\_stopin}, and a Keypad
 
550
        was hit after normal ASCII characters, the function returns NOK.
 
551
        Note that keypad keys are translated if the keypad is not enabled.
 
552
\item   \_PF\_: a PF key is the 
 
553
        {\em first} input character if PF keys were previously enabled
 
554
        via {\tt tv\_stopin(w, \_PF\_, "*")}.
 
555
\item   \_FK\_: a Function is the 
 
556
        {\em first} input character if Function  keys were previously enabled
 
557
        via {\tt tv\_stopin(w, \_FK\_, "*")}.
 
558
\end{itemize}
 
559
\end{TeX}
 
560
.REMARKS 
 
561
---*/
 
562
        char    *str;           /* MOD: The buffer to get the input     */
 
563
        int     nbytes;         /* IN: Length of the input buffer       */
 
564
        int     linput;         /* IN: Length of template string        */
 
565
{
 
566
        register char   *p;     /* Current position in str      */
 
567
                 char   *pw, *p_end;    /* pw is last valid char in str */
 
568
                 int    type;
 
569
        static   char   ch;
 
570
                 int    i, l;
 
571
 
 
572
  ENTER("tv_mods");
 
573
 
 
574
  f = f0, f0 = Echo | Stacking;
 
575
 
 
576
  if (nbytes < 2)       EXIT(NOK);              /* Buffer too small     */
 
577
 
 
578
  TERMTEST;             /* Open Terminal if not yet done        */
 
579
  
 
580
  p_start = str;
 
581
  p = p_start, pw = p;
 
582
  command_len = nbytes - 1;
 
583
  p_end = p + command_len;
 
584
 
 
585
  init_pos = GetPosition();     /* Keep first initial data */
 
586
  J = terms->dim[1];            /* Column width            */
 
587
 
 
588
  if (linput)   TRACE_STR2(str, linput);
 
589
 
 
590
 
 
591
        /* Echo template string, and position cursor to End of Template */
 
592
 
 
593
  if (linput > 0) 
 
594
  {     i = MIN(linput, p_end - p_start);
 
595
        WriteBinary(p_start, i);
 
596
        p += i, pw = p;
 
597
  }     
 
598
 
 
599
        /* Initialize the Stack of Commands     */
 
600
 
 
601
  c->pointed = c->used;
 
602
  c->pointed_no = c->last_no + 1;
 
603
  command_number = c->pointed_no;
 
604
 
 
605
 
 
606
        /* ============ Loop on the input char ======== */
 
607
 
 
608
  while ( ! (f&Stop) )
 
609
  {     
 
610
        if (f & NoMore)         /* Too long string...   */
 
611
        {       Bell();         
 
612
                f &= ~NoMore;
 
613
        }
 
614
 
 
615
        type = GetChar(&ch);
 
616
 
 
617
#if DEBUG
 
618
        TRACE_ED_STR2("Total   string is: ",str, pw-str);
 
619
        TRACE_ED_STR2("Present string is: ",str, p-str);
 
620
        TRACE_ED_STR2("Just read        : ",&ch, 1);
 
621
        TRACE_ED_I   (" ... of type: ",type);
 
622
#endif
 
623
 
 
624
        if ( type == NOK)       /* Bad Escape Sequence...       */
 
625
        {       Bell();
 
626
                continue;
 
627
        }
 
628
 
 
629
        if (f & Raw)            type = _STANDARD_;
 
630
 
 
631
        switch(type)
 
632
        { case EOF:     f |= (Stop|Special);
 
633
                continue;
 
634
 
 
635
          case _PF_: case _FK_:
 
636
                if (c->exit_pf & MASK(type))
 
637
                        f |= (Stop|Special);
 
638
                else            Bell();
 
639
                continue;
 
640
 
 
641
          case _ARROW_: 
 
642
                if (c->exit_ar & MASK(ch))
 
643
                {       f |= (Stop|Special);
 
644
                        continue;
 
645
                }
 
646
                switch(ch)      /* Execute the Cursor Movements */
 
647
                { case _LEFT_:  
 
648
                  case _RIGHT_: 
 
649
                        p += mv1(ch, pw - p);   /* Maximal Displacement is pw-p */
 
650
                        continue;
 
651
                  default:
 
652
                        SetPosition(init_pos), p = p_start;
 
653
                        continue;
 
654
                  case _UP_:
 
655
                  case _DOWN_:
 
656
                        /* Copy retrieved command, and edit it  */
 
657
                        if_not(f&Echo)  continue;
 
658
                        if (c->pointed_no == command_number)
 
659
                                /* Save what has been typed */
 
660
                                zadd(str, pw-str, 0);
 
661
                        zm(ch);         /* Move in Stack */
 
662
                        i = c->pointed;
 
663
                        l = *(c->text + i);
 
664
                        l = show(p_start, (char *)(c->text + i + 1), l);
 
665
                        p = str + l, pw = p;
 
666
                }
 
667
                continue;
 
668
                
 
669
          case _KEYPAD_:
 
670
                if (c->exit_pf & MASK(_KEYPAD_))
 
671
                {       f |= (Stop|Special);
 
672
                        continue;
 
673
                }
 
674
                type = _STANDARD_;  /* Keypad chars are considered as normal */
 
675
                break;
 
676
        }               
 
677
 
 
678
        /* --- Here Only if it's an ASCII character ---- */
 
679
 
 
680
        if ((isprint(ch)) || (f&Raw))
 
681
        {       f &= ~Raw;
 
682
                if (f & Imode)
 
683
                {       if ( (pw) >= p_end)     f |= NoMore;
 
684
                        else oscopy ( p+1, p, pw++ - p);
 
685
                }
 
686
                else            /* Replace Mode */
 
687
                {       if (pw <= p)    pw = p+1;
 
688
                        if (pw > p_end) pw--, f |= NoMore;
 
689
                }
 
690
                if (f & NoMore)         /* Too long string...   */
 
691
                        continue;
 
692
                *p = ch;
 
693
                o1(p, pw-p);            /* Echo the character...*/
 
694
                p++;
 
695
                if (stop_len)           /* Check first byte     */
 
696
                {       if (oscloc(stop_list, stop_len, ch) < stop_len)
 
697
                                ch = '\r';
 
698
                        else    ch = EOS;
 
699
                        stop_len = 0;
 
700
                        if(ch == EOS)   continue;
 
701
                }
 
702
                else    continue;
 
703
        }
 
704
 
 
705
                /*==============================================*/
 
706
                /* ---     Here only if it's a Control Char     */
 
707
                /*==============================================*/
 
708
        
 
709
        if (ch == '\r')                         /* Normal End   */
 
710
        {       f |= Stop;
 
711
                continue;
 
712
        }
 
713
 
 
714
        i = *(unsigned char *)(&ch);
 
715
        if (i > 32)             /* Delete char  */
 
716
                i = 32;
 
717
 
 
718
        if (c->exit_cc & MASK(i))               /* Exit on Control      */
 
719
        {       f |= (Stop|Special);
 
720
                continue;
 
721
        }
 
722
 
 
723
        switch(terms->tc[i])
 
724
        { default:              Bell();         /* Just ignore...       */
 
725
                continue;
 
726
 
 
727
          case TW_cc_RAW:       f |= Raw;
 
728
                continue;
 
729
 
 
730
          case TW_cc_REFR:                      /* Refresh Screen       */
 
731
                SetPosition(init_pos);
 
732
                ClearDown();
 
733
                WriteBinary(p_start, pw-p_start);
 
734
                SetPosition(init_pos + (p-p_start));
 
735
                continue;
 
736
 
 
737
          case TW_cc_HELP:      /* Go first to end of text, show help,
 
738
                                 * and reissue text */
 
739
                SetPosition(init_pos + (pw - p_start));
 
740
                ShowHelp();     
 
741
                WriteBinary(p_start, pw-p_start);
 
742
                init_pos = GetPosition() - (pw - p_start);
 
743
                SetPosition(init_pos + (p - p_start));
 
744
                continue;
 
745
 
 
746
          case TW_cc_MODE:      f ^= Imode;     /* Change mode  */
 
747
                continue;       /* Imode flag done at loop top  */
 
748
 
 
749
          case TW_cc_NW:                        /* Move to next word    */
 
750
                p += oscscan(p, pw-p, _SPACE_, main_ascii);
 
751
                p += oscspan(p, pw-p, _SPACE_, main_ascii);
 
752
                SetPosition(init_pos + (p-p_start));
 
753
                continue;
 
754
 
 
755
          case TW_cc_EOL:                       /* Move cursor to end   */
 
756
                SetPosition(init_pos + (pw - p_start));
 
757
                p = pw;
 
758
                continue;
 
759
 
 
760
          case TW_cc_DELC:                      /* Delete Char  */
 
761
                if (p == p_start)       continue;
 
762
                p--, pw--;
 
763
                oscopy(p, p+1, pw-p);
 
764
                dc(p, 1, pw-p);
 
765
                continue;
 
766
 
 
767
          case TW_cc_DELL:                      /* Clear Line           */
 
768
                p = p_start, pw = p;
 
769
                SetPosition(init_pos);
 
770
                ClearDown();
 
771
                continue;
 
772
 
 
773
          case TW_cc_DELE:                      /* Delete to the right  */
 
774
                pw = p;
 
775
                ClearDown();
 
776
                continue;
 
777
 
 
778
          case TW_cc_DELW:                      /* Delete Previous Word */
 
779
                if (p == p_start)       continue;
 
780
                i = oscbspan(p_start, p-p_start, _SPACE_, main_ascii);
 
781
                i = oscbscan(p_start, i+1, _SPACE_, main_ascii);
 
782
                i = (p-p_start) - (i+1); /* Number of chars to delete   */
 
783
                oscopy(p-i, p, pw-p);
 
784
                p -= i, pw -= i;
 
785
                dc(p, i, pw-p);
 
786
                continue;
 
787
        }
 
788
  }
 
789
 
 
790
  p = pw, l = p - p_start;              /* Final Length of String       */
 
791
  SetPosition(init_pos + l);            /* Where the cursor must be     */
 
792
 
 
793
        /* Add the string to command stack      */
 
794
 
 
795
  if ( (type <= _STANDARD_)  && (l > 0) && (f&Stacking))
 
796
        zadd(str, l, 2);
 
797
 
 
798
  if (f & Special)
 
799
  {     if (pw == str)                  /* Was First Input Character */
 
800
                *(p++) = ch;
 
801
        else    tv_push(type, ch), type = NOK;
 
802
  }
 
803
  *p = EOS;
 
804
 
 
805
 
 
806
  TRACE(p_start);
 
807
 
 
808
  EXIT(type);
 
809
}
 
810
 
 
811
 
 
812
/*==========================================================================
 
813
 *                      tv_kmods
 
814
 *==========================================================================*/
 
815
int     tv_kmods(flag,str, nbytes, linput)
 
816
/*+++
 
817
.PURPOSE Display a template command, and get a command string 
 
818
        from terminal, made of up to (nbytes-1)
 
819
        characters, and echo. 
 
820
        The input stops when the one of the characters
 
821
        specified by tv_stopin is hit (the Carriage Return only by default).
 
822
\begin{TeX}
 
823
        {\em Note that} keypad characters are considered as normal chars,
 
824
        unless {\tt tv\_stopin(w, \_KEYPAD\_,"*")}  was called.
 
825
\end{TeX}
 
826
.RETURNS OK or _STANDARD_, EOF, NOK, _KEYPAD_, _PF_, _FK_ with the 
 
827
following meanings:
 
828
\begin{TeX}
 
829
\begin{itemize}
 
830
\item   OK or \_STANDARD\_: a $<$Carriage\_Return$>$ or $<$Enter$>$
 
831
        terminates the input;
 
832
        this last character is not reported to the string,
 
833
        but {\em is replaced by the EOS character.}
 
834
\item   NOK: either
 
835
        \begin{itemize}
 
836
        \item the size of the input string is 1 character or less
 
837
                (nbytes $<2$)
 
838
        \item a control / arrow / keypad / PK / Function character was typed 
 
839
                at the terminal, which is {\em not the 
 
840
                first} input char;
 
841
                the returned string contains the previous characters
 
842
                (\ie before the stopping char), and a next call to 
 
843
                the function will return the control character.
 
844
        \end{itemize}
 
845
\item   EOF: the EOF (Control\_Z or Control\_D, depending on initialization) 
 
846
        char was typed as the
 
847
        {\em first} input character; the output string contains only
 
848
        a zero (EOS).
 
849
        {\em Note that the EOF character not typed as the first char
 
850
        returns NOK.}
 
851
\item   \_KEYPAD\_: a keypad key is the 
 
852
        {\em first} input character and the Keypad is enabled
 
853
        via a previous call to {\tt tv\_stopin(w, \_KEYPAD\_, "*")}; 
 
854
        the output string contains the equivalence keypad.
 
855
        If the Keypad is enabled via {\em tv\_stopin}, and a Keypad
 
856
        was hit after normal ASCII characters, the function returns NOK.
 
857
        Note that keypad keys are translated if the keypad is not enabled.
 
858
\item   \_PF\_: a PF key is the 
 
859
        {\em first} input character if PF keys were previously enabled
 
860
        via {\tt tv\_stopin(w, \_PF\_, "*")}.
 
861
\item   \_FK\_: a Function is the 
 
862
        {\em first} input character if Function  keys were previously enabled
 
863
        via {\tt tv\_stopin(w, \_FK\_, "*")}.
 
864
\end{itemize}
 
865
\end{TeX}
 
866
.REMARKS 
 
867
---*/
 
868
        int     flag;           /* IN: 1 or 0 for Insert or Change mode */
 
869
        char    *str;           /* MOD: The buffer to get the input     */
 
870
        int     nbytes;         /* IN: Length of the input buffer       */
 
871
        int     linput;         /* IN: Length of template string        */
 
872
{
 
873
        register char   *p;     /* Current position in str      */
 
874
                 char   *pw, *p_end;    /* pw is last valid char in str */
 
875
                 int    type;
 
876
        static   char   ch;
 
877
                 int    i, l;
 
878
 
 
879
  ENTER("tv_mods");
 
880
 
 
881
  f = f0, f0 = Echo | Stacking;
 
882
 
 
883
  if (nbytes < 2)       EXIT(NOK);              /* Buffer too small     */
 
884
 
 
885
  TERMTEST;             /* Open Terminal if not yet done        */
 
886
  
 
887
  p_start = str;
 
888
  p = p_start, pw = p;
 
889
  command_len = nbytes - 1;
 
890
  p_end = p + command_len;
 
891
 
 
892
  init_pos = GetPosition();     /* Keep first initial data */
 
893
  J = terms->dim[1];            /* Column width            */
 
894
 
 
895
  if (linput)   TRACE_STR2(str, linput);
 
896
 
 
897
 
 
898
        /* Echo template string, and position cursor to End of Template */
 
899
 
 
900
  if (linput > 0) 
 
901
  {     i = MIN(linput, p_end - p_start);
 
902
        WriteBinary(p_start, i);
 
903
        p += i, pw = p;
 
904
  }     
 
905
 
 
906
        /* Initialize the Stack of Commands     */
 
907
 
 
908
  c->pointed = c->used;
 
909
  c->pointed_no = c->last_no + 1;
 
910
  command_number = c->pointed_no;
 
911
 
 
912
  if (flag == 1) f ^= Imode;     /* Change mode  */
 
913
 
 
914
        /* ============ Loop on the input char ======== */
 
915
 
 
916
  while ( ! (f&Stop) )
 
917
  {     
 
918
        if (f & NoMore)         /* Too long string...   */
 
919
        {       Bell();         
 
920
                f &= ~NoMore;
 
921
        }
 
922
 
 
923
        type = GetChar(&ch);
 
924
 
 
925
#if DEBUG
 
926
        TRACE_ED_STR2("Total   string is: ",str, pw-str);
 
927
        TRACE_ED_STR2("Present string is: ",str, p-str);
 
928
        TRACE_ED_STR2("Just read        : ",&ch, 1);
 
929
        TRACE_ED_I   (" ... of type: ",type);
 
930
#endif
 
931
 
 
932
        if ( type == NOK)       /* Bad Escape Sequence...       */
 
933
        {       Bell();
 
934
                continue;
 
935
        }
 
936
 
 
937
        if (f & Raw)            type = _STANDARD_;
 
938
 
 
939
        switch(type)
 
940
        { case EOF:     f |= (Stop|Special);
 
941
                continue;
 
942
 
 
943
          case _PF_: case _FK_:
 
944
                if (c->exit_pf & MASK(type))
 
945
                        f |= (Stop|Special);
 
946
                else            Bell();
 
947
                continue;
 
948
 
 
949
          case _ARROW_: 
 
950
                if (c->exit_ar & MASK(ch))
 
951
                {       f |= (Stop|Special);
 
952
                        continue;
 
953
                }
 
954
                switch(ch)      /* Execute the Cursor Movements */
 
955
                { case _LEFT_:  
 
956
                  case _RIGHT_: 
 
957
                        p += mv1(ch, pw - p);   /* Maximal Displacement is pw-p */
 
958
                        continue;
 
959
                  default:
 
960
                        SetPosition(init_pos), p = p_start;
 
961
                        continue;
 
962
                  case _UP_:
 
963
                  case _DOWN_:
 
964
                        /* Copy retrieved command, and edit it  */
 
965
                        if_not(f&Echo)  continue;
 
966
                        if (c->pointed_no == command_number)
 
967
                                /* Save what has been typed */
 
968
                                zadd(str, pw-str, 0);
 
969
                        zm(ch);         /* Move in Stack */
 
970
                        i = c->pointed;
 
971
                        l = *(c->text + i);
 
972
                        l = show(p_start, (char *)(c->text + i + 1), l);
 
973
                        p = str + l, pw = p;
 
974
                }
 
975
                continue;
 
976
                
 
977
          case _KEYPAD_:
 
978
                if (c->exit_pf & MASK(_KEYPAD_))
 
979
                {       f |= (Stop|Special);
 
980
                        continue;
 
981
                }
 
982
                type = _STANDARD_;  /* Keypad chars are considered as normal */
 
983
                break;
 
984
        }               
 
985
 
 
986
        /* --- Here Only if it's an ASCII character ---- */
 
987
 
 
988
        if ((isprint(ch)) || (f&Raw))
 
989
        {       f &= ~Raw;
 
990
                if (f & Imode)
 
991
                {       if ( (pw) >= p_end)     f |= NoMore;
 
992
                        else oscopy ( p+1, p, pw++ - p);
 
993
                }
 
994
                else            /* Replace Mode */
 
995
                {       if (pw <= p)    pw = p+1;
 
996
                        if (pw > p_end) pw--, f |= NoMore;
 
997
                }
 
998
                if (f & NoMore)         /* Too long string...   */
 
999
                        continue;
 
1000
                *p = ch;
 
1001
                o1(p, pw-p);            /* Echo the character...*/
 
1002
                p++;
 
1003
                if (stop_len)           /* Check first byte     */
 
1004
                {       if (oscloc(stop_list, stop_len, ch) < stop_len)
 
1005
                                ch = '\r';
 
1006
                        else    ch = EOS;
 
1007
                        stop_len = 0;
 
1008
                        if(ch == EOS)   continue;
 
1009
                }
 
1010
                else    continue;
 
1011
        }
 
1012
 
 
1013
                /*==============================================*/
 
1014
                /* ---     Here only if it's a Control Char     */
 
1015
                /*==============================================*/
 
1016
        
 
1017
        if (ch == '\r')                         /* Normal End   */
 
1018
        {       f |= Stop;
 
1019
                continue;
 
1020
        }
 
1021
 
 
1022
        i = *(unsigned char *)(&ch);
 
1023
        if (i > 32)             /* Delete char  */
 
1024
                i = 32;
 
1025
 
 
1026
        if (c->exit_cc & MASK(i))               /* Exit on Control      */
 
1027
        {       f |= (Stop|Special);
 
1028
                continue;
 
1029
        }
 
1030
 
 
1031
        switch(terms->tc[i])
 
1032
        { default:              Bell();         /* Just ignore...       */
 
1033
                continue;
 
1034
 
 
1035
          case TW_cc_RAW:       f |= Raw;
 
1036
                continue;
 
1037
 
 
1038
          case TW_cc_REFR:                      /* Refresh Screen       */
 
1039
                SetPosition(init_pos);
 
1040
                ClearDown();
 
1041
                WriteBinary(p_start, pw-p_start);
 
1042
                SetPosition(init_pos + (p-p_start));
 
1043
                continue;
 
1044
 
 
1045
          case TW_cc_HELP:      /* Go first to end of text, show help,
 
1046
                                 * and reissue text */
 
1047
                SetPosition(init_pos + (pw - p_start));
 
1048
                ShowHelp();     
 
1049
                WriteBinary(p_start, pw-p_start);
 
1050
                init_pos = GetPosition() - (pw - p_start);
 
1051
                SetPosition(init_pos + (p - p_start));
 
1052
                continue;
 
1053
 
 
1054
          case TW_cc_MODE:      f ^= Imode;     /* Change mode  */
 
1055
                continue;       /* Imode flag done at loop top  */
 
1056
 
 
1057
          case TW_cc_NW:                        /* Move to next word    */
 
1058
                p += oscscan(p, pw-p, _SPACE_, main_ascii);
 
1059
                p += oscspan(p, pw-p, _SPACE_, main_ascii);
 
1060
                SetPosition(init_pos + (p-p_start));
 
1061
                continue;
 
1062
 
 
1063
          case TW_cc_EOL:                       /* Move cursor to end   */
 
1064
                SetPosition(init_pos + (pw - p_start));
 
1065
                p = pw;
 
1066
                continue;
 
1067
 
 
1068
          case TW_cc_DELC:                      /* Delete Char  */
 
1069
                if (p == p_start)       continue;
 
1070
                p--, pw--;
 
1071
                oscopy(p, p+1, pw-p);
 
1072
                dc(p, 1, pw-p);
 
1073
                continue;
 
1074
 
 
1075
          case TW_cc_DELL:                      /* Clear Line           */
 
1076
                p = p_start, pw = p;
 
1077
                SetPosition(init_pos);
 
1078
                ClearDown();
 
1079
                continue;
 
1080
 
 
1081
          case TW_cc_DELE:                      /* Delete to the right  */
 
1082
                pw = p;
 
1083
                ClearDown();
 
1084
                continue;
 
1085
 
 
1086
          case TW_cc_DELW:                      /* Delete Previous Word */
 
1087
                if (p == p_start)       continue;
 
1088
                i = oscbspan(p_start, p-p_start, _SPACE_, main_ascii);
 
1089
                i = oscbscan(p_start, i+1, _SPACE_, main_ascii);
 
1090
                i = (p-p_start) - (i+1); /* Number of chars to delete   */
 
1091
                oscopy(p-i, p, pw-p);
 
1092
                p -= i, pw -= i;
 
1093
                dc(p, i, pw-p);
 
1094
                continue;
 
1095
        }
 
1096
  }
 
1097
 
 
1098
  p = pw, l = p - p_start;              /* Final Length of String       */
 
1099
  SetPosition(init_pos + l);            /* Where the cursor must be     */
 
1100
 
 
1101
        /* Add the string to command stack      */
 
1102
 
 
1103
  if ( (type <= _STANDARD_)  && (l > 0) && (f&Stacking))
 
1104
        zadd(str, l, 2);
 
1105
 
 
1106
  if (f & Special)
 
1107
  {     if (pw == str)                  /* Was First Input Character */
 
1108
                *(p++) = ch;
 
1109
        else    tv_push(type, ch), type = NOK;
 
1110
  }
 
1111
  *p = EOS;
 
1112
 
 
1113
 
 
1114
  TRACE(p_start);
 
1115
 
 
1116
  EXIT(type);
 
1117
}
 
1118
 
 
1119