1
/*===========================================================================
2
Copyright (C) 1986-2009 European Southern Observatory (ESO)
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License as
6
published by the Free Software Foundation; either version 2 of
7
the License, or (at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public
15
License along with this program; if not, write to the Free
16
Software Foundation, Inc., 675 Massachusetss Ave, Cambridge,
19
Corresponding concerning ESO-MIDAS should be addressed as follows:
20
Internet e-mail: midas@eso.org
21
Postal address: European Southern Observatory
22
Data Management Division
23
Karl-Schwarzschild-Strasse 2
24
D 85748 Garching bei Muenchen
26
===========================================================================*/
28
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
30
.IDENTIFICATION twget.c
31
.AUTHOR Francois Ochsenbein [ESO-IPG]
33
.KEYWORDS Window Management
34
.ENVIRONMENT TermWindows
35
.COMMENTS This module contains routines to perform command input,
36
and to manage the associated command stack.
39
The commands are stacked in a buffer (named {\tt text} in the
40
{\tt COMMAND} structure). Each command is preceded and followed
41
by the text length, in order to facilitate forward and backward
42
movements in the stack.\\[0.5ex]
43
{\bf Editing possibilities} when a command is typed at the terminal
44
are available, like cursor mouvements, moving in the stack,
45
refreshing the Screen.
47
The default actions of control characters are defined as TW\_cc\_default
48
in {\tt twparam.h}, with choices UNIX-like, VMS-like or a third
49
set. The action of each control character may be modified with the
50
tv\_setcc(control\_character, action) (DefineControl) function.
54
.VERSION 1.0 01-Sep-1986: Creation
55
.VERSION 2.0 03-Dec-1986 New terminal-independant graphic characters
56
with output buffering version.
57
.VERSION 3.0 20-May-1988: Version '3'
58
Functions tw_get1 and tw_getf added.
59
.VERSION 3.1 17-Feb-1989: Add ^ option in SetStopping, which specifies
60
that the arrow should stop if borders encountered.
61
Changed tw_getf to tw_modf.
62
.VERSION 3.2 31-Mar-1989: Removed bug in mv1...
63
.VERSION 3.3 05-Apr-1989: Possibility of NULL_WINDOW as input.
64
.VERSION 3.4 17-May-1989: No redisplay with ModsWithCheck if window
66
.VERSION 3.5 09-Jun-1989: Use negative string size for Stretchable Window.
67
Added tw_ms2. Added tw_gc2.
68
.VERSION 3.6 19-Jun-1989: tw_mods puts the cursor at the BEGINNING of
70
.VERSION 3.7 24-Jul-1989: Catched INTERRUPT
71
.VERSION 3.8 24-Aug-1989: Clear line if INTERRUPT
72
.VERSION 3.9 05-Dec-1990: Modified tw_get1: Return 0 if First Char found.
73
Added tw_gc1 (use a stopping list)
76
----------------------------------------------------------------------------*/
78
#define DEBUG 0 /* For debugging only */
80
#define PM_LEVEL LEVEL_TW
82
#include <midas_def.h>
85
#define TW_import 0 /* Do not use macro window definitions */
89
extern int tv_wa(), tv_agoto(), tv_getc();
90
extern int tv_bell(), tv_setsc(), tv_push();
92
extern int tw_write(), tw_uc(), tw_box(), tw_r(), tw_agoto(), tw_st();
93
extern int tw_wa(), tw_clear(), tw_tra(), tw_dc(), tw_mods();
94
extern int tw_helps(), tw_amark(), tw_occluded(), tw_nl(), tw_line();
96
extern int pm_enter(), pm_iexit(), pm_ed_tr2(), pm_trace();
98
extern int eh_ed_str2();
101
MID_EXTERN WINDOW *Screen;
102
MID_EXTERN TERM *terms;
103
typedef void (*FUNCTION)();
104
extern FUNCTION ostint();
108
#define TW_cc_level 3
109
#define ENTER_DEBUG(x) ENTER(x)
110
#define EXIT_DEBUG(x) EXIT(x)
111
#define DISPLAY(opt) zed(opt)
114
#define ENTER_DEBUG(x)
115
#define EXIT_DEBUG(x) return(x)
118
MID_STATIC WINDOW *W = NULL_PTR(WINDOW);
119
MID_STATIC COMMAND *c = NULL_PTR(COMMAND);
120
static short int command_number;
121
MID_STATIC unsigned int f = 0; /* Flags to communicate */
122
MID_STATIC char *stop_list = (char *)0;
123
MID_STATIC int stop_len = 0;
124
MID_STATIC int (*f_ed)() = NULL_FCT(int);
125
/* Control function for modf */
127
static ACHAR *saved_screen = NULL_PTR(ACHAR);
128
static int saved_screen_size = 0;
129
static int saved_screen_len = 0;
131
static char *input_start, *input_end, *input_valid; /* Input string */
134
#define Special 0x0200
136
#define NoMore 0x1000
138
#define Occluded 0x4000
139
#define Interrupted 0x8000
141
#define BYTE_MAX 0xff
142
#define ULONG_MAX 0xffffffff
147
/*==========================================================================*/
150
.PURPOSE Catch Interrupt
154
int s; /* IN: Signal */
156
f |= (Stop | Interrupted);
160
/*==========================================================================*/
161
static int OpenStretchableWindow(len)
163
.PURPOSE Special Window, saving what's presently on the Screen.
164
.RETURNS OK / NOK (It's a _DISPLAY_ window)
167
int len; /* IN: Length of Stretchable Window */
170
if (saved_screen_size < len)
171
saved_screen_size = len,
172
saved_screen = MEM_EXP(ACHAR,(char *) saved_screen, saved_screen_size);
174
saved_screen_len = len;
175
tw_tra(W, saved_screen, saved_screen_len);
177
return(saved_screen_len);
180
/*==========================================================================
182
*==========================================================================*/
185
.PURPOSE Check if window is Display Only
188
WINDOW *w; /* IN: The concerned Window */
194
W = (w ? w : Screen);
196
if_not(c = Command(W)) status = NOK,
197
ERR_ED_STR2("Window is Display-Only: ", W->id, 8);
202
/*==========================================================================
204
*==========================================================================*/
207
.PURPOSE Optimized output of 1 character, if Echo is on.
208
.RETURNS 0 / 1 (number of chars output on Screen)
209
.REMARKS Optimization only for an active window, not in Insert Mode.
211
char *ch; /* IN: Character to output */
214
int i, j, J, saved_marker;
219
saved_marker = W->marker[1];
220
if_not(f&Echo) FINISH; /* Nothing if no echo */
222
J = W->Nj, i = W->pos/J, j = W->pos%J;
224
if ( f & (Imode | Occluded) )
226
if (saved_screen_len)
227
W->marker[1] = W->marker[0] + input_valid - input_start;
228
status = tw_write(W, (char *)ch, 1, 0); /* Not optimized... */
232
/* Convert char to ACHAR, and update Cursor Position on Screen */
234
achar = (W->attr & ~HIGH) | ( iscntrl(*ch) ? RubbishAchar() : *ch);
237
/* Update Window's Cursor Position */
241
/* First, copy char to window */
245
/* ... and copy char to Screen */
249
J = Screen->Nj, i = Screen->pos/J, j = Screen->pos%J;
250
*Aij(Screen, i, j) = achar;
251
SetPosition(Screen->pos);
254
/* ... physically output char to Screen */
256
WriteAchars(&achar, 1);
258
/* ... And finally update Screen Cursor */
265
W->marker[1] = saved_marker;
269
/*======================================================================
271
*======================================================================*/
272
static int mv1(direction, bytes)
274
.PURPOSE Optimized cursor mouvement of 1 place in the specified
275
direction: up, down, right, left or home.
276
.RETURNS OK / NOK (attempt to move outside window, cursor does not move).
277
.REMARKS Move is limited within markers.
279
int direction; /* IN: The direction of the displacement */
280
int bytes; /* IN: The maximal displacement */
282
int displacement, saved_marker, status;
287
if_not(f&Echo) FINISH; /* Nothing if no echo */
290
saved_marker = W->marker[1], W->marker[1] = W->pos + bytes;
293
{ case _LEFT_: displacement = -1; break;
294
case _RIGHT_: displacement = 1; break;
295
case _UP_: displacement = -W->Nj; break;
296
case _DOWN_: displacement = W->Nj; break;
297
default: displacement = W->marker[0] - W->pos;
298
if (displacement == 0) displacement = -1; /* No mouvement,
302
displacement += W->pos; /* New position */
303
if ( (displacement >= W->marker[0]) && (displacement <= W->marker[1]))
304
tw_agoto(W, displacement);
306
W->marker[1] = saved_marker;
312
/*======================================================================
314
*======================================================================*/
315
static int move(out, in, len)
317
.PURPOSE Copy string to another.
318
.RETURNS Length of string
319
.REMARKS Move is limited within markers.
321
char *out; /* OUT: copied string */
322
char *in; /* IN: string to display */
323
int len; /* IN: Length of in */
327
l = MIN (len, W->marker[1] - W->marker[0]);
333
/*======================================================================
335
*======================================================================*/
336
static int show(str, len)
338
.PURPOSE Redisplay the string (in, len) on the W window.
339
.RETURNS Length of string
340
.REMARKS Move is limited within markers. Cursor positioned AFTER marker.
342
char *str; /* IN: string to display */
343
int len; /* IN: Length of in */
347
l = MIN (len, W->marker[1] - W->marker[0]);
348
if_not(f&Echo) FINISH; /* Nothing if no echo */
350
tw_st(W, Imode|Echo, 0);
351
tw_agoto(W, old_pos);
352
if (saved_screen_len) tw_wa(W, saved_screen, saved_screen_len);
353
else tw_clear(W, _DOWN_);
354
tw_write(W, str, l, 0);
355
if (f&Echo) tw_st(W, Echo, 1), tw_r(W,0, NULL_WINDOW);
361
/*======================================================================
363
*======================================================================*/
364
static int here_Delete(ndel)
366
.PURPOSE Delete char interface
367
.RETURNS Length of string
368
.REMARKS Move is limited within markers. Cursor positioned AFTER marker.
370
int ndel; /* IN: Number of bytes to delete */
372
int len; /* IN: Length of input */
375
len = input_valid - input_start;
377
if (saved_screen_len)
381
tw_st(W, Imode|Echo, 0);
383
tw_agoto(W, old_pos + len);
384
tw_wa(W, saved_screen + len, saved_screen_len - len);
386
tw_agoto(W, old_pos);
387
tw_write(W, input_start, len, 0);
389
if (ndel < 0) status += ndel;
391
if (f&Imode) W->flags |= Imode;
392
if (f&Echo) tw_st(W, Echo, 1), tw_r(W,0, NULL_WINDOW);
395
else status = tw_dc(W, ndel);
400
/*==========================================================================
402
*==========================================================================*/
403
static int zm(direction)
405
.PURPOSE Move in the command stack according to the specified direction.
406
.RETURNS OK / NOK (at the top or bottom of the stack)
409
int direction; /* IN: _UP_, _DOWN_ or _HOME_ (last command) */
415
if (c->size == 0) FINISH;
420
{ case _UP_: /* Towards the beginning of the stack */
421
if (c->pointed_no <= c->first_no)
422
{ c->pointed_no = c->first_no - 1;
427
(c->pointed)--; /* Index of suffix length */
428
(c->pointed) -= (1 + *(c->text + c->pointed));
430
case _DOWN_: /* Towards the bottom of the stack */
431
if (c->pointed_no >= c->last_no)
432
{ c->pointed_no = c->last_no + 1;
433
c->pointed = c->used;
437
(c->pointed) += (2 + *(c->text + c->pointed));
439
default: /* The last issued command */
440
if (c->last_no < c->first_no)
445
c->pointed_no = c->last_no;
446
c->pointed = (c->used) - 1;
447
(c->pointed) -= (1 + *(c->text + c->pointed));
461
/*==========================================================================
463
*==========================================================================*/
464
static int zadd(str, nbytes, opt)
466
.PURPOSE Insert into the command stack the string str.
467
.RETURNS OK / NOK (not enough space)
470
char *str; /* IN: The string to insert */
471
int nbytes; /* IN: Length of the str string */
472
int opt; /* IN: Option 1 to add effectively / 2 only if\
473
differs from previous */
479
TRACE_ED_STR2("Command = ",str,nbytes);
483
if (nbytes < 0) FINISH;
484
if (c->size == 0) FINISH;
488
/* Check it it's the same command as previous one */
490
if ((opt == 2) && zm(_HOME_)) /* Get last command */
491
{ p = (char *)(c->text + c->pointed);
492
if ((*(p++) == nbytes) && (oscomp(p, str, nbytes) == 0))
498
u = c->used + nbytes + 2; /* Used bytes after addition */
501
while (u > c->size) /* Look if stack must be compressed */
502
{ l = *(c->text + i) + 2; /* Length of command */
507
if (u < 2) /* Not enough space ... */
513
{ l = c->used - i; /* Length to copy */
515
TRACE("Compress Stack:");
518
c->used = 2 + oscopy((char *)(c->text+2), (char *)(c->text + i), l);
520
TRACE("Compressed Stack:");
525
c->pointed = c->used;
527
p = (char *)(c->text + c->used);
528
*(p++) = nbytes; /* Prefix length */
529
p += oscopy((char *)p, (char *)str, nbytes);
531
*(p++) = nbytes; /* Suffix length */
533
if (opt) /* Modify only if required */
534
{ c->used = (unsigned char *)p - (c->text);
536
(c->pointed_no) = c->last_no;
549
/*==========================================================================
551
*==========================================================================*/
552
int tw_stopin(w, type, list)
554
.PURPOSE Define the list of Characters that stop the Input:
555
Control Characters, Arrows, Keypad, Function Keys.
556
.RETURNS OK / NOK (It's a _DISPLAY_ window)
557
.REMARKS A void string ("") removes all stopping characters;
558
a string starting with + means "add to existing list",
559
with - "delete from existing list".
560
The * acts as the wild character, e.g. "-*" means "delete all".
561
By default, only the \r (Carriage-Return) stops the input.
564
For type \_STANDARD\_, {\em list} contains the ASCII equivalence,
565
e.g. A for Control A.
567
For type \_ARROW\_, individual keys are specified in {\em list}
568
by {\bf u}p, {\bf d}owm, {\bf l}eft, {\bf r}ight and {\bf h}ome.
569
The {\bf \^{ }} (carret) means {\em return if a border encountered}
571
Other keys cannot be individually specified.
575
WINDOW *w; /* MOD: Window concerned */
576
int type; /* IN: _NORMAL_ , _ARROW_, _KEYPAD_, _PF_ or _FK_ */
577
char *list; /* IN: The characters that may be used to terminate; \
578
the * is used as a wild character \
589
if_not(check(w)) EXIT(NOK);
590
if_not(list) EXIT(NOK);
592
wild = (*p == '+' ? 1 : (*p == '-' ? -1 : 0));
596
if_not(wild) c->exit_ar = 0;
598
{ switch(tolower(*p))
599
{ case 'u': i = MASK(_UP_); break;
600
case 'd': i = MASK(_DOWN_); break;
601
case 'l': i = MASK(_LEFT_); break;
602
case 'r': i = MASK(_RIGHT_); break;
603
case 'h': i = MASK(_HOME_); break;
604
case '*': i = 0x1f; break;
605
case '^': i = MASK(_TEE_); break;
606
case '+': wild = 1; continue;
607
case '-': wild = -1; continue;
609
if (wild<0) c->exit_ar &= ~i;
610
else c->exit_ar |= i;
614
case _KEYPAD_: case _PF_: case _FK_:
616
if (*p == '*') wild = 1;
617
if (wild) c->exit_pf &= ~i;
618
if (wild > 0) c->exit_pf |= i;
621
default: /* Control Characters */
622
if_not(wild) c->exit_cc = MASK('\r');
625
{ case '+': wild = 1; continue;
626
case '-': wild = -1; continue;
627
case '*': i = ULONG_MAX; break;
628
default: i = MASK(Control_(*p)); break;
630
if (wild<0) c->exit_cc &= ~i;
631
else c->exit_cc |= i;
639
/*==========================================================================
641
*==========================================================================*/
644
.PURPOSE Get a single character on the window.
645
.RETURNS _STANDARD_, NOK (unknown escape sequence) _INTERRUPT_ _EOF_, _PF_, _FK_ , _KEYPAD_
646
.REMARKS Help Window Removed if _EOF_ or \r.
648
WINDOW *w; /* MOD: Window concerned */
649
char *ch; /* OUT: The character typed */
656
f = Stop1; /* Stop after first byte */
657
type = tw_mods(w, buffer, sizeof(buffer), 0);
661
if( (type < 0) || ((type == _STANDARD_) && (buffer[0] == '\r')))
662
tw_helps(W,0); /* Remove Help Window */
668
int tw_gc1(w, ch, stop1)
670
.PURPOSE Similar to gc, but uses a list of characters that are NOT
672
.RETURNS _EOF_ / _INTERRUPT_ / 0(stopped after first input) /
673
_STANDARD_ / _ARROW_ / _KEYPAD_ / _FK_ / _PF_
676
WINDOW *w; /* MOD: Window to echo the input */
677
char *ch; /* OUT: The character typed */
678
char *stop1; /* IN: List of characters to stop */
685
stop_len = strlen(stop1);
686
status = tw_getc(w, ch);
687
if (stop_len < 0) status = 0; /* Stopped due to 1st char */
693
/*==========================================================================
695
*==========================================================================*/
696
int tw_get1(w, str, nbytes, stop1)
698
.PURPOSE Get a command string from terminal, made of up to (nbytes-1)
699
characters, but stop if one of the characters
700
in stop1 was hit as the {\em first} input.
701
.RETURNS _EOF_ / _INTERRUPT_ / 0(stopped after first input) /
702
_STANDARD_ / _ARROW_ / _KEYPAD_ / _FK_ / _PF_
705
WINDOW *w; /* MOD: Window to echo the input */
706
char *str; /* MOD: The buffer to get the input */
707
int nbytes; /* IN: Length of the input buffer */
708
char *stop1; /* IN: List of characters to stop */
715
stop_len = strlen(stop1);
716
status = tw_mods(w, str, nbytes, 0);
717
if (stop_len < 0) status = 0; /* Stopped due to 1st char */
723
/*==========================================================================
725
*==========================================================================*/
726
int tw_ms2(w, str, nbytes, linput, fct)
728
.PURPOSE Similar to tw_modf, but returns a composite status.
729
.RETURNS A composite code including the kind of key and the actual key
730
typed at the terminal. Codes are:
733
\item 0: the \b r terminated the input.
734
\item \_INTERRUPT\_: the {\em Interrupt} key was hit.
735
\item \_EOF\_: the {\em EOF} key was hit.
736
\item a control char: the returned character terminated the input.
737
\item \_ARROW({\em key}): one of the Arrows was hit, e.g.
738
{\tt \_ARROW(\_UP\_)}
739
\item \_KEYPAD({\em key}): one of the Kitpad Keys was hit,
740
e.g. {\tt \_KEYPAD('6')}
741
\item \_PF({\em key}): one of the PF Keys was hit,
743
\item \_FK({\em key}): one of the FK Keys was hit,
748
WINDOW *w; /* MOD: Window to echo the input */
749
char *str; /* MOD: The buffer to get the input */
750
int nbytes; /* IN: Length of the input buffer (<0 stretchable) */
751
int linput; /* IN: Length of the string to modify */
752
int (*fct)(); /* IN: The check function */
761
status = tw_mods(w, str, nbytes, linput);
762
if (status < 0) *str = EOS;
765
case _STANDARD_: /* Normal \r terminated string */
769
case 0: /* Special Character stopped the Input */
770
status = GetChar(&thechar); /* Get it... */
775
status = thechar; break;
777
status = (status << 8) | thechar;
783
status = (status << 8) | *str;
787
f_ed = NULL_FCT(int);
792
/*==========================================================================
794
*==========================================================================*/
797
.PURPOSE Similar to tw_getc, but returns a composite status.
798
.RETURNS A composite code including the kind of key and the actual key
799
typed at the terminal (see tw_ms2).
801
WINDOW *w; /* MOD: Window to echo the input */
808
f = Stop1; /* Stop after first byte */
810
type = tw_mods(w, buffer, sizeof(buffer), 0);
811
if (type < 0) buffer[0] = EOS;
814
case _STANDARD_: /* Normal \r terminated string */
815
type = (buffer[0] == '\r' ? 0 : buffer[0]);
819
type = (type << 8) | buffer[0];
824
if (type <= 0) tw_helps(W,0); /* Remove Help Window */
829
/*==========================================================================
831
*==========================================================================*/
832
int tw_modf(w, str, nbytes, linput, fct)
834
.PURPOSE Get a command string from terminal, made of up to (nbytes-1)
835
characters, but with check using the user--supplied
838
The supplied {\em fct} function is called before returning from
839
the general input function, \ie just after the \meta{Carriage Return}
840
or any other character that stops the input.
841
The fct function has three arguments:
843
\item The window used
844
\item the input string
845
\item the size of this string (for modifications)
847
ans should return OK (the input is good) or NOK (the input is bad).
849
.RETURNS _EOF_ / _INTERRUPT_ / 0 / _STANDARD_ / _ARROW_ / _KEYPAD_ / _FK_ / _PF_
852
WINDOW *w; /* MOD: Window to echo the input */
853
char *str; /* MOD: The buffer to get the input */
854
int nbytes; /* IN: Length of the input buffer (<0 stretchable) */
855
int linput; /* IN: Length of the string to modify */
856
int (*fct)(); /* IN: The check function */
863
status = tw_mods(w, str, nbytes, linput);
864
f_ed = NULL_FCT(int);
869
/*==========================================================================
871
*==========================================================================*/
872
int tw_mods(w, str, nbytes, linput)
874
.PURPOSE Display a template command, and get a command string
875
from terminal, made of up to (nbytes-1)
876
characters, and echo on specified window.
877
The input stops when the one of the characters
878
specified by tw_stopin is hit (the Carriage Return only by default).
880
{\em Note that keypad characters are considered as normal chars,
881
unless {\tt tw\_stopin(w, \_KEYPAD\_,"*")} was called.}
883
.RETURNS OK or _STANDARD_, EOF, NOK, _KEYPAD_, _PF_, _FK_ with the
887
\item OK or \_STANDARD\_: a $<$Carriage\_Return$>$ or $<$Enter$>$
888
terminates the input;
889
this last character is not reported to the string,
890
but {\em is replaced by the EOS character.}
893
\item the window is Display Only (no input available)
894
\item the size of the input string is 1 character or less
896
\item a control / arrow / keypad / PK / Function character was typed
897
at the terminal, which is {\em not the
899
the returned string contains the previous characters
900
(\ie before the stopping char), and a next call to
901
the function will return the control character.
903
\item \_INTERRUPT\_: the {\em Interrupt}(Control\_C)
904
char was typed. Output string is blanked.
905
\item \_EOF\_: the EOF (Control\_Z or Control\_D, depending on InitWindow)
906
char was typed as the
907
{\em first} input character; the output string contains only
909
{\em Note that the EOF character not typed as the first char
911
\item \_KEYPAD\_: a keypad key is the
912
{\em first} input character and the Keypad is enabled
913
via a previous call to {\tt tw\_stopin(w, \_KEYPAD\_, "*")};
914
the output string contains the equivalence keypad.
915
If the Keypad is enabled via {\em tw\_stopin}, and a Keypad
916
was hit after normal ASCII characters, the function returns NOK.
917
Note that keypad keys are translated if the keypad is not enabled.
918
\item \_PF\_: a PF key is the
919
{\em first} input character if PF keys were previously enabled
920
via {\tt tw\_stopin(w, \_PF\_, "*")}.
921
\item \_FK\_: a Function is the
922
{\em first} input character if Function keys were previously enabled
923
via {\tt tw\_stopin(w, \_FK\_, "*")}.
928
WINDOW *w; /* MOD: Window to echo the input */
929
char *str; /* MOD: The buffer to get the input */
930
int nbytes; /* IN: Length of the input buffer (<0 stretchable) */
931
int linput; /* IN: Length of template string */
933
char *p; /* Current position in str */
935
int i, l, k, old_stoplen;
938
unsigned char old_flags, old_control;
945
i = ABSOLUTE(nbytes);
946
if (i < 2) EXIT(NOK); /* Buffer too small */
948
saved_screen_len = 0;
952
{ *input_start = EOS;
956
if (nbytes < 0) /* Use Stretchable Window */
958
OpenStretchableWindow(nbytes-1);
961
old_pos = W->pos; /* Keep first initial data */
962
old_marker[0] = W->marker[0], old_marker[1] = W->marker[1];
963
old_flags = W->flags;
964
old_stoplen = stop_len;
966
if (old_pos >= W->marker[1]) EXIT(NOK);
968
p = input_start, input_valid = p;
969
f |= W->flags & (Imode|Echo|Stacking);
970
if ( (f&Echo) == 0) f &= ~Stacking; /* No stacking if no echo ... */
973
/* To be sure that wrapping allowed, install a Range on the
974
* Window. Anything will then be limited to the Range
977
l = tw_amark(W, W->pos, nbytes-1);
980
if(f&Echo) if (tw_occluded(W,0)) f |= Occluded;
981
/* Can't optimize output... */
983
if (f&Stacking) /* Set stack to (last+1) command */
984
{ c->pointed = c->used;
985
c->pointed_no = c->last_no + 1;
986
command_number = c->pointed_no;
988
else command_number = -1;
990
/* Echo template string, and position cursor to End of Template */
991
/**** Note: If No Echo, DON'T DISPLAY INPUT ....................*/
993
if ((linput > 0) && (f&Echo))
994
{ i = MIN(linput, input_end - input_start);
995
tw_write(W, input_start, i, 0);
996
/* p += i, input_valid = p; If Cursor at END of text */
997
input_valid = input_start + i; tw_agoto(W, old_pos);
998
/* Cursor at BEGINNING of text */
1000
tw_agoto(W, old_pos);
1002
old_int = OnInterrupt((void *)InInt); /* Install Interrupt Function */
1004
/* Loop on the input char */
1008
if (f&Stop) /* Check with the Function */
1010
if (f&Interrupted) /* Delete the Whole Line */
1011
{ tw_agoto(W, old_pos);
1012
i = input_valid - input_start; /* Number of chars to delete */
1013
p = input_start, input_valid = p;
1019
{ *input_valid = EOS;
1020
/* tw_agoto(W, old_pos + (input_valid - input_start));*/
1021
k = (*f_ed)(W, input_start, nbytes); /* Call... */
1022
l = strlen(input_start);/* Don't redisplay if stretch */
1023
if (saved_screen_len == 0)
1024
l = show(input_start, l);
1025
input_valid = input_start + l;
1026
if (p > input_valid) p = input_valid;
1027
tw_agoto(W, old_pos + (p - input_start));
1028
if (k) break; /* Anything OK */
1029
f &= ~Stop; /* Bad input... */
1035
if ((f & Stop1) && (p == input_end) ) break;
1037
if (f & NoMore) /* Too long string... */
1042
/* When there is a stopping list, install the terminal
1043
as NOMAP. This is done via SetControls
1045
if (stop_len > 0) old_control = SetControls(0);
1046
type = GetChar(&ch);
1047
if (stop_len > 0) SetControls(old_control);
1048
if(f&Interrupted) continue;
1051
TRACE_ED_STR2("Total string is: ",input_start,input_valid-input_start);
1052
TRACE_ED_STR2("Present string is: ",input_start,p-input_start);
1053
TRACE_ED_STR2("Just read : ",&ch, 1);
1054
TRACE_ED_I (" ... of type: ",type);
1057
if ( type == NOK) /* Bad Escape Sequence... */
1058
{ if (f & Stop1) f |= (Stop|Special);
1059
if (input_valid == input_start) /* Was First Input Character */
1060
f |= (Stop|Special);
1065
if (f & Raw) type = _STANDARD_;
1067
if (f&Imode) W->flags |= Imode;
1068
else W->flags &= ~Imode;
1071
{ case EOF: f |= (Stop|Special);
1074
case _PF_: case _FK_:
1075
if (c->exit_pf & MASK(type))
1076
f |= (Stop|Special);
1082
if (c->exit_ar & i) /* Possible Stop */
1083
{ if(c->exit_ar & MASK(_TEE_)); /* not Immediate */
1084
else { f |= (Stop|Special); continue; }
1086
if ((f&Stacking) && (i&(MASK(_UP_)|MASK(_DOWN_))))
1087
{ /* Copy retrieved command, and edit it */
1088
if (c->pointed_no == command_number)
1089
/* Save what has been typed */
1090
zadd(input_start, input_valid-input_start, 0);
1092
zm(ch); /* Move in Stack */
1095
l = move(input_start, (char *)(c->text + i + 1), l);
1096
show(input_start, l);
1097
p = input_start + l, input_valid = p;
1101
/* Reflect Cursor Displacement */
1102
if_not (mv1(ch, input_valid-p)) /* No possible move */
1103
if (c->exit_ar & i) /* Must Stop */
1104
f |= (Stop|Special);
1105
p = input_start + (W->pos - W->marker[0]); /* Pos in buf */
1109
if (c->exit_pf & MASK(_KEYPAD_))
1110
{ f |= (Stop|Special);
1113
type = _STANDARD_; /* Keypad chars are considered as normal */
1117
if (stop_len > 0) { /* Check first byte */
1118
if (oscloc(stop_list, stop_len, ch) < stop_len) {
1119
stop_len = -1; /* Found*/
1120
f |= (Stop|Special);
1126
/* --- Here Only if it's an ASCII character ---- */
1128
if ((isprint(ch)) || (f&Raw) || (terms->flags & TERM_NOMAP)) {
1131
{ if ( (input_valid) >= input_end) f |= NoMore;
1132
else oscopy ( p+1, p, input_valid++ - p);
1134
else /* Replace Mode */
1135
{ if (input_valid <= p) input_valid = p+1;
1136
if (input_valid > input_end) input_valid--, f |= NoMore;
1138
if (f & NoMore) /* Too long string... */
1141
o1(&ch); /* Echo the character...*/
1142
if (stop_len <= 0) continue;
1145
/*==============================================*/
1146
/* --- Here only if it's a Control Char */
1147
/*==============================================*/
1149
if (ch == '\r') /* Normal End */
1151
if (f&Stop1) f |= Special;
1155
i = *(unsigned char *)(&ch);
1156
if (i > 32) /* Delete char */
1158
if (f&Stop1) { f |= Stop|Special; continue; }
1161
if (c->exit_cc & MASK(i)) /* Exit on Control */
1162
{ f |= (Stop|Special);
1166
switch(terms->tc[i])
1167
{ default: Bell(); /* Just ignore... */
1170
case TW_cc_EOF: f |= (Stop|Special);
1174
case TW_cc_RAW: f |= Raw;
1177
case TW_cc_REFR: /* Refresh Screen */
1178
tw_r(NULL_WINDOW,1,NULL_WINDOW);
1181
case TW_cc_HELP: tw_helps(W,1); /* Switch the Help Wind */
1183
if(f&Echo) if (tw_occluded(W,0)) f |= Occluded;
1186
case TW_cc_MODE: f ^= Imode; /* Change mode */
1187
continue; /* Window Imode flag done at loop top */
1189
case TW_cc_NW: /* Move to next word */
1190
p += oscscan((unsigned char *)p, input_valid-p, _SPACE_, main_ascii);
1191
p += oscspan((unsigned char *)p, input_valid-p, _SPACE_, main_ascii);
1192
tw_agoto(W, old_pos + (p-input_start));
1195
case TW_cc_EOL: /* Move cursor to end */
1196
tw_agoto(W, old_pos + (input_valid - input_start));
1200
case TW_cc_DELC: /* Delete Char */
1201
if (p > input_start)
1202
{ p--, input_valid--;
1203
oscopy(p, p+1, input_valid-p);
1208
case TW_cc_DELL: /* Clear Line = delete all */
1209
tw_agoto(W, old_pos);
1210
i = input_valid - input_start; /* Number of chars to delete */
1211
p = input_start, input_valid = p;
1213
stop_len = old_stoplen;
1216
case TW_cc_DELE: /* Delete to the right */
1217
i = input_valid - p;
1222
case TW_cc_DELW: /* Delete Previous Word */
1223
i = oscbspan((unsigned char *)input_start, p-input_start, _SPACE_, main_ascii);
1224
i = oscbscan((unsigned char *)input_start, i+1, _SPACE_, main_ascii);
1225
i = (p-input_start) - (i+1); /* Number of chars to delete */
1226
oscopy(p-i, p, input_valid-p);
1227
p -= i, input_valid -= i;
1233
if (f&Interrupted) type = _INTERRUPT_, input_valid = input_start;
1234
p = input_valid, l = p - input_start; /* Final Length of String */
1237
/* Add the string to command stack */
1239
if ( (f&Stacking) && (type <= _STANDARD_) && (l > 0))
1240
zadd(input_start, l, 2);
1243
{ if (input_valid == input_start) /* Was First Input Character */
1245
else tv_push(type, ch), type = NOK;
1251
if_not(f&Stop1) tw_helps(W,0); /* Remove Help Window */
1252
W->marker[0] = old_marker[0], W->marker[1] = old_marker[1];
1253
W->flags = old_flags;
1255
if(saved_screen_len) /* Restore The Text */
1259
tw_agoto(W, old_pos);
1260
tw_wa(W, saved_screen, saved_screen_len);
1262
if (f&Echo) tw_st(W, Echo, 1), tw_r(W,0,NULL_WINDOW);
1265
OnInterrupt(old_int);
1273
/*==========================================================================
1275
*==========================================================================*/
1278
.PURPOSE Edit a stack (for debugging purposes)
1280
.REMARKS Option 1 to display the whole stack
1282
int opt; /* IN: Edition option */
1288
sprintf(msg,"!size=%d, used=%d, pointed=%d, no=%d, first=%d, last=%d",
1289
c->size, c->used, c->pointed, c->pointed_no, c->first_no,
1294
{ TRACE_ED_HEXA("Stack is:",c->text,c->used);
1295
for (p = (char *)(c->text)+2, i=c->first_no; i<= c->last_no; i++)
1296
{ sprintf(msg,"!No %4d=>",i);
1297
TRACE_ED_STR2(msg,p+1,*p);
1306
/*==========================================================================
1308
*==========================================================================*/
1309
int tw_zadd(w, str, nbytes)
1311
.PURPOSE Insert into the command stack the string str.
1312
.RETURNS OK / NOK (not enough space)
1313
.REMARKS The command IS NOT inserted if it's the same as the previoue one.
1315
WINDOW *w; /* IN: The concerned Window */
1316
char *str; /* IN: The string to insert */
1317
int nbytes; /* IN: Length of the str string */
1321
if(status) status = zadd(str, nbytes, 2);
1325
/*==========================================================================*/
1328
.PURPOSE Clear the command stack.
1336
if (c->size < 2) FINISH;
1359
/*==========================================================================
1361
*==========================================================================*/
1364
.PURPOSE Clear the command stack.
1368
WINDOW *w; /* IN: The concerned Window */
1372
if(status) status = zclear();
1376
/*==========================================================================
1378
*==========================================================================*/
1379
int tw_zm(w, direction)
1381
.PURPOSE Move in the command stack according to the specified direction.
1382
.RETURNS OK / NOK (at the top or bottom of the stack)
1385
WINDOW *w; /* IN: The concerned Window */
1386
int direction; /* IN: _UP_, _DOWN_ or _HOME_ (last command) */
1390
if(status) status = zm(direction);
1394
/*==========================================================================
1396
*==========================================================================*/
1397
static int zn(number)
1399
.PURPOSE Move in the stack to a specified numbered command
1400
.RETURNS OK / NOK (numbered command not in stack)
1403
int number; /* IN: Command number */
1409
TRACE_ED_I("Getting command #",number);
1414
if (c->size == 0) FINISH;
1419
if (n < c->first_no) FINISH;
1420
if (n > c->last_no) FINISH;
1422
if ( (n - c->first_no) < 3)
1424
c->pointed_no = c->first_no;
1427
while (c->pointed_no > n) zm(_UP_);
1428
while (c->pointed_no < n) zm(_DOWN_);
1440
/*==========================================================================*/
1441
int tw_zn(w, number)
1443
.PURPOSE Move in the stack to a specified numbered command
1444
.RETURNS OK / NOK (numbered command not in stack)
1447
WINDOW *w; /* IN: The concerned Window */
1448
int number; /* IN: Command number */
1452
if(status) status = zn(number);
1456
/*==========================================================================
1458
*==========================================================================*/
1459
static int zo1(w, option)
1461
.PURPOSE Edit on a specified window the current stacked command
1462
.RETURNS OK / NOK (no stacked command)
1463
.REMARKS The edition starts on a new line
1465
WINDOW *w; /* MOD: Window for output */
1466
int option; /* IN: 1 to edit with number */
1471
MID_STATIC char c_no[6] = {' ', ' ', ' ', ' ', ':', ' '};
1475
if (c->size == 0) FINISH;
1476
if (c->pointed_no < c->first_no) FINISH;
1477
if (c->pointed_no > c->last_no) FINISH;
1481
f = w->flags & Echo;
1484
if (w->pos % w->Nj) tw_nl(w);
1487
{ i = sizeof(c_no) - 2;
1488
for (n = c->pointed_no; --i >= 0; n /= 10)
1489
c_no[i] = (n ? n%10+'0' : ' ');
1490
tw_write(w, c_no, sizeof(c_no), 0);
1493
p = c->text + c->pointed;
1494
tw_line(w, p+1, *p, 0);
1497
{ w->flags |= Echo, f = 0;
1498
tw_rw(w, 0,NULL_WINDOW);
1509
/*==========================================================================*/
1510
int tw_zo1(w, win, option)
1512
.PURPOSE Edit on a specified window the current stacked command
1513
.RETURNS OK / NOK (no stacked command)
1514
.REMARKS The edition starts on a new line
1516
WINDOW *w; /* MOD: Window for output */
1517
WINDOW *win; /* IN: The concerned Window */
1518
int option; /* IN: 1 to edit with number */
1521
status = check(win);
1522
if(status) status = zo1(w, option);
1526
/*==========================================================================
1528
*==========================================================================*/
1529
static int zo(w, option)
1531
.PURPOSE Edit on a specified window the stack contents
1532
.RETURNS OK / NOK (no stacked command)
1533
.REMARKS The edition starts on a new line. The window is cleared before
1534
the edition. If the window is active with scrolling,
1535
ALL commands are listed.
1537
WINDOW *w; /* MOD: Window for output */
1538
int option; /* IN: 1 to edit with number */
1545
if (c->size == 0) FINISH;
1546
if (c->pointed_no == 0) FINISH;
1550
/* Computation of the number of commands that can be issued */
1551
n = c->last_no - c->first_no + 1;
1552
if ( n > w->Ni ) n = c->last_no - w->Ni + 1;
1553
else n = c->first_no;
1554
/* if ( (w->active) && (w->scroll) ) n = c->first_no; */
1557
tw_clear(w,_WHOLE_);
1561
if_not(zm(_DOWN_)) break;
1572
/*==========================================================================*/
1573
int tw_zo(w, win, option)
1575
.PURPOSE Edit on a specified window the stack contents
1576
.RETURNS OK / NOK (no stacked command)
1577
.REMARKS The edition starts on a new line. The window is cleared before
1578
the edition. If the window is active with scrolling,
1579
ALL commands are listed.
1581
WINDOW *w; /* MOD: Window for output */
1582
WINDOW *win; /* IN: The concerned Window */
1583
int option; /* IN: 1 to edit with number */
1586
status = check(win);
1587
if(status) status = zo(w, option);