Bug Summary

File:os_tty.c
Location:line 7722, column 19
Description:Value stored to 'orig_byte_buf_avail' during its initialization is never read

Annotated Source Code

1/* File: "os_tty.c" */
2
3/* Copyright (c) 1994-2013 by Marc Feeley, All Rights Reserved. */
4
5/*
6 * This module implements the operating system specific routines
7 * related to ttys.
8 */
9
10#define ___INCLUDED_FROM_OS_TTY
11#define ___VERSION407000 407000
12#include "gambit.h"
13
14#include "os_base.h"
15#include "os_tty.h"
16#include "os_shell.h"
17#include "os_io.h"
18#include "setup.h"
19#include "c_intf.h"
20
21
22/*---------------------------------------------------------------------------*/
23
24/* Extensible string routines */
25
26
27___HIDDENstatic ___SCMOBJlong extensible_string_setup
28 ___P((extensible_string *str,(extensible_string *str, int n)
29 int n),(extensible_string *str, int n)
30 (str,(extensible_string *str, int n)
31 n)(extensible_string *str, int n)
32extensible_string *str;(extensible_string *str, int n)
33int n;)(extensible_string *str, int n)
34{
35#define EXTENSIBLE_STRING_INITIAL_BUFFER_SIZE32 32
36
37 if (n < EXTENSIBLE_STRING_INITIAL_BUFFER_SIZE32)
38 n = EXTENSIBLE_STRING_INITIAL_BUFFER_SIZE32;
39
40 str->buffer = ___CAST(extensible_string_char*,((extensible_string_char*)(___alloc_mem (n * sizeof (extensible_string_char
))))
41 ___alloc_mem (n * sizeof (extensible_string_char)))((extensible_string_char*)(___alloc_mem (n * sizeof (extensible_string_char
))))
;
42
43 if (str->buffer == NULL((void*)0))
44 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
45
46 str->length = 0;
47 str->max_length = n;
48
49 return ___FIX(___NO_ERR)(((long)(0))<<2);
50}
51
52
53___HIDDENstatic void extensible_string_cleanup
54 ___P((extensible_string *str),(extensible_string *str)
55 (str)(extensible_string *str)
56extensible_string *str;)(extensible_string *str)
57{
58 ___free_mem (str->buffer);
59}
60
61
62___HIDDENstatic ___SCMOBJlong extensible_string_copy
63 ___P((extensible_string_char *src,(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
64 int len,(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
65 extensible_string *dst,(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
66 int fudge),(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
67 (src,(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
68 len,(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
69 dst,(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
70 fudge)(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
71extensible_string_char *src;(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
72int len;(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
73extensible_string *dst;(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
74int fudge;)(extensible_string_char *src, int len, extensible_string *dst
, int fudge)
75{
76 extensible_string_char *buf;
77
78 buf = ___CAST(extensible_string_char*,((extensible_string_char*)(___alloc_mem ((len+fudge) * sizeof
(extensible_string_char))))
79 ___alloc_mem ((len+fudge) * sizeof (extensible_string_char)))((extensible_string_char*)(___alloc_mem ((len+fudge) * sizeof
(extensible_string_char))))
;
80
81 if (buf == NULL((void*)0))
82 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
83
84 dst->buffer = buf;
85 dst->length = len;
86 dst->max_length = len+fudge;
87
88 while (len-- > 0)
89 buf[len] = src[len];
90
91 return ___FIX(___NO_ERR)(((long)(0))<<2);
92}
93
94
95___HIDDENstatic ___SCMOBJlong extensible_string_set_length
96 ___P((extensible_string *str,(extensible_string *str, int len, int fudge)
97 int len,(extensible_string *str, int len, int fudge)
98 int fudge),(extensible_string *str, int len, int fudge)
99 (str,(extensible_string *str, int len, int fudge)
100 len,(extensible_string *str, int len, int fudge)
101 fudge)(extensible_string *str, int len, int fudge)
102extensible_string *str;(extensible_string *str, int len, int fudge)
103int len;(extensible_string *str, int len, int fudge)
104int fudge;)(extensible_string *str, int len, int fudge)
105{
106 if (len > str->max_length || 2*len+1 < str->max_length)
107 {
108 int i;
109 int new_max_length = (fudge<0) ? 3*len/2+1 : len+fudge;
110 extensible_string_char *old_buffer = str->buffer;
111 extensible_string_char *new_buffer =
112 ___CAST(extensible_string_char*,((extensible_string_char*)(___alloc_mem (new_max_length * sizeof
(extensible_string_char))))
113 ___alloc_mem (new_max_length *((extensible_string_char*)(___alloc_mem (new_max_length * sizeof
(extensible_string_char))))
114 sizeof (extensible_string_char)))((extensible_string_char*)(___alloc_mem (new_max_length * sizeof
(extensible_string_char))))
;
115
116 if (new_buffer == NULL((void*)0))
117 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
118
119 i = str->length;
120 if (i > len)
121 i = len;
122
123 while (i-- > 0)
124 new_buffer[i] = old_buffer[i];
125
126 ___free_mem (old_buffer);
127 str->buffer = new_buffer;
128 str->max_length = new_max_length;
129 }
130
131 str->length = len;
132
133 return ___FIX(___NO_ERR)(((long)(0))<<2);
134}
135
136
137___HIDDENstatic void extensible_string_delete
138 ___P((extensible_string *str,(extensible_string *str, int pos, int len)
139 int pos,(extensible_string *str, int pos, int len)
140 int len),(extensible_string *str, int pos, int len)
141 (str,(extensible_string *str, int pos, int len)
142 pos,(extensible_string *str, int pos, int len)
143 len)(extensible_string *str, int pos, int len)
144extensible_string *str;(extensible_string *str, int pos, int len)
145int pos;(extensible_string *str, int pos, int len)
146int len;)(extensible_string *str, int pos, int len)
147{
148 int i;
149
150 if (pos < 0)
151 pos = 0;
152 else if (pos > str->length)
153 pos = str->length;
154
155 i = str->length - pos;
156 if (len < 0)
157 len = 0;
158 else if (len > i)
159 len = i;
160
161 for (i=pos; i<str->length-len; i++)
162 str->buffer[i] = str->buffer[i+len];
163
164 str->length -= len;
165}
166
167
168___HIDDENstatic ___SCMOBJlong extensible_string_insert
169 ___P((extensible_string *str,(extensible_string *str, int pos, int len, extensible_string_char
*chars)
170 int pos,(extensible_string *str, int pos, int len, extensible_string_char
*chars)
171 int len,(extensible_string *str, int pos, int len, extensible_string_char
*chars)
172 extensible_string_char *chars),(extensible_string *str, int pos, int len, extensible_string_char
*chars)
173 (str,(extensible_string *str, int pos, int len, extensible_string_char
*chars)
174 pos,(extensible_string *str, int pos, int len, extensible_string_char
*chars)
175 len,(extensible_string *str, int pos, int len, extensible_string_char
*chars)
176 chars)(extensible_string *str, int pos, int len, extensible_string_char
*chars)
177extensible_string *str;(extensible_string *str, int pos, int len, extensible_string_char
*chars)
178int pos;(extensible_string *str, int pos, int len, extensible_string_char
*chars)
179int len;(extensible_string *str, int pos, int len, extensible_string_char
*chars)
180extensible_string_char *chars;)(extensible_string *str, int pos, int len, extensible_string_char
*chars)
181{
182 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
183 int i;
184
185 if (len > 0)
186 {
187 if (pos < 0)
188 pos = 0;
189 else if (pos > str->length)
190 pos = str->length;
191
192 if ((e = extensible_string_set_length (str, str->length+len, -1))
193 == ___FIX(___NO_ERR)(((long)(0))<<2))
194 {
195 for (i=str->length-len-1; i>=pos; i--)
196 str->buffer[i+len] = str->buffer[i];
197
198 for (i=len-1; i>=0; i--)
199 str->buffer[i+pos] = chars[i];
200 }
201 }
202
203 return e;
204}
205
206
207___HIDDENstatic ___SCMOBJlong extensible_string_insert_at_end
208 ___P((extensible_string *str,(extensible_string *str, int len, extensible_string_char *chars
)
209 int len,(extensible_string *str, int len, extensible_string_char *chars
)
210 extensible_string_char *chars),(extensible_string *str, int len, extensible_string_char *chars
)
211 (str,(extensible_string *str, int len, extensible_string_char *chars
)
212 len,(extensible_string *str, int len, extensible_string_char *chars
)
213 chars)(extensible_string *str, int len, extensible_string_char *chars
)
214extensible_string *str;(extensible_string *str, int len, extensible_string_char *chars
)
215int len;(extensible_string *str, int len, extensible_string_char *chars
)
216extensible_string_char *chars;)(extensible_string *str, int len, extensible_string_char *chars
)
217{
218 return extensible_string_insert (str, str->length, len, chars);
219}
220
221
222/*---------------------------------------------------------------------------*/
223
224/* TTY mode setting */
225
226
227___HIDDENstatic ___SCMOBJlong ___device_tty_mode_get
228 ___P((___device_tty *self),(___device_tty *self)
229 (self)(___device_tty *self)
230___device_tty *self;)(___device_tty *self)
231{
232 ___device_tty *d = self;
233
234#ifdef USE_tcgetsetattr
235#ifdef USE_fcntl
236
237#ifdef ___DEBUG_TTY
238
239 ___printf ("tcgetattr d->fd = %d\n", d->fd);
240
241#endif
242
243 if (tcgetattr (d->fd, &d->initial_termios) < 0 ||
244 (d->initial_flags = fcntl (d->fd, F_GETFL3, 0)) < 0)
245 return err_code_from_errno ()___err_code_from_errno();
246
247#ifdef ___DEBUG_TTY
248
249 ___printf ("___device_tty_mode_get d->fd = %d\n", d->fd);
250 ___printf (" d->initial_termios.c_iflag = 0x%08x\n", d->initial_termios.c_iflag);
251 ___printf (" d->initial_termios.c_oflag = 0x%08x\n", d->initial_termios.c_oflag);
252 ___printf (" d->initial_termios.c_lflag = 0x%08x\n", d->initial_termios.c_lflag);
253
254#endif
255#endif
256
257#endif
258
259#ifdef USE_WIN32
260
261 if (!GetConsoleMode (d->hin, &d->hin_initial_mode) ||
262 !GetConsoleMode (d->hout, &d->hout_initial_mode))
263 return err_code_from_GetLastError ()___err_code_from_GetLastError();
264
265#endif
266
267 return ___FIX(___NO_ERR)(((long)(0))<<2);
268}
269
270
271___HIDDENstatic ___SCMOBJlong ___device_tty_mode_save
272 ___P((___device_tty *self),(___device_tty *self)
273 (self)(___device_tty *self)
274___device_tty *self;)(___device_tty *self)
275{
276 ___device_tty *d = self;
277 ___SCMOBJlong e;
278
279 if ((e = ___device_tty_mode_get (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
280 return e;
281
282 d->mode_save_stack_next = ___tty_mod.mode_save_stack;
283 ___tty_mod.mode_save_stack = d;
284
285 d->stage = TTY_STAGE_MODE_NOT_SET2;
286
287 return ___FIX(___NO_ERR)(((long)(0))<<2);
288}
289
290
291___HIDDENstatic ___SCMOBJlong ___device_tty_mode_update
292 ___P((___device_tty *self,(___device_tty *self, int current)
293 ___BOOL current),(___device_tty *self, int current)
294 (self,(___device_tty *self, int current)
295 current)(___device_tty *self, int current)
296___device_tty *self;(___device_tty *self, int current)
297___BOOL current;)(___device_tty *self, int current)
298{
299 ___device_tty *d = self;
300 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
301
302#ifdef USE_tcgetsetattr
303#ifdef USE_fcntl
304
305 {
306 struct termios new_termios = d->initial_termios;
307 int new_flags = d->initial_flags;
308
309#ifdef ___DEBUG_TTY
310
311 ___printf ("tcsetattr d->fd = %d\n", d->fd);
312 ___printf (" d->lineeditor_mode = %d\n", d->lineeditor_mode);
313 ___printf (" d->input_allow_special = %d\n", d->input_allow_special);
314 ___printf (" d->input_echo = %d\n", d->input_echo);
315 ___printf (" d->input_raw = %d\n", d->input_raw);
316 ___printf (" d->output_raw = %d\n", d->output_raw);
317 ___printf (" new_termios.c_iflag = 0x%08x\n", new_termios.c_iflag);
318 ___printf (" new_termios.c_oflag = 0x%08x\n", new_termios.c_oflag);
319 ___printf (" new_termios.c_lflag = 0x%08x\n", new_termios.c_lflag);
320
321#endif
322
323 if (current)
324 {
325 if (d->input_allow_special)
326 {
327 new_termios.c_iflag |= (IXON0002000);
328 new_termios.c_lflag |= (IEXTEN0100000 | ISIG0000001);
329 }
330 else
331 {
332 new_termios.c_iflag &= ~(IXON0002000);
333 new_termios.c_lflag &= ~(IEXTEN0100000 | ISIG0000001);
334 }
335
336 if (d->input_raw
337#ifdef USE_LINEEDITOR
338 || d->lineeditor_mode != LINEEDITOR_MODE_DISABLE0
339#endif
340 )
341 {
342 new_termios.c_iflag &= ~(IMAXBEL0020000
343 | ISTRIP0000040
344 | ICRNL0000400
345 | INLCR0000100
346 | IGNCR0000200
347 | ICRNL0000400
348 | IXON0002000
349 | IXOFF0010000
350#ifdef IUCLC0001000
351 | IUCLC0001000
352#endif
353 );
354 new_termios.c_iflag &= ~(ICRNL0000400);
355 new_termios.c_lflag &= ~(ICANON0000002 | ECHO0000010 | ECHOCTL0001000);
356
357#ifndef _POSIX_VDISABLE'\0'
358#define _POSIX_VDISABLE'\0' 0xff
359#endif
360
361#if 0
362 new_termios.c_cc[VEOF4] = _POSIX_VDISABLE'\0';
363 new_termios.c_cc[VEOL11] = _POSIX_VDISABLE'\0';
364 new_termios.c_cc[VEOL216] = _POSIX_VDISABLE'\0';
365 new_termios.c_cc[VERASE2] = _POSIX_VDISABLE'\0';
366 new_termios.c_cc[VWERASE14] = _POSIX_VDISABLE'\0';
367 new_termios.c_cc[VKILL3] = _POSIX_VDISABLE'\0';
368 new_termios.c_cc[VREPRINT12] = _POSIX_VDISABLE'\0';
369 new_termios.c_cc[VINTR0] = _POSIX_VDISABLE'\0';
370 new_termios.c_cc[VQUIT1] = _POSIX_VDISABLE'\0';
371 new_termios.c_cc[VSUSP10] = _POSIX_VDISABLE'\0';
372#endif
373#ifdef VDSUSP
374 new_termios.c_cc[VDSUSP] = _POSIX_VDISABLE'\0';
375#endif
376#if 0
377 new_termios.c_cc[VSTART8] = _POSIX_VDISABLE'\0';
378 new_termios.c_cc[VSTOP9] = _POSIX_VDISABLE'\0';
379#endif
380#ifdef VLNEXT15
381 new_termios.c_cc[VLNEXT15] = _POSIX_VDISABLE'\0';
382#endif
383#if 0
384 new_termios.c_cc[VDISCARD13] = _POSIX_VDISABLE'\0';
385 new_termios.c_cc[VMIN6] = _POSIX_VDISABLE'\0';
386 new_termios.c_cc[VTIME5] = _POSIX_VDISABLE'\0';
387 new_termios.c_cc[VSTATUS] = _POSIX_VDISABLE'\0';
388#endif
389
390 new_termios.c_cc[VMIN6] = 1;
391 new_termios.c_cc[VTIME5] = 0;
392 }
393 else
394 {
395 new_termios.c_iflag |= (ICRNL0000400);
396 new_termios.c_lflag |= (ICANON0000002 | ECHO0000010 | ECHOCTL0001000);
397 }
398
399 if (!d->input_echo)
400 new_termios.c_lflag &= ~(ECHO0000010 | ECHOCTL0001000);
401
402 if (d->output_raw)
403 new_termios.c_oflag &= ~(OPOST0000001 | ONLCR0000004);
404 else
405 new_termios.c_oflag |= (OPOST0000001);
406
407 new_termios.c_iflag |= (IGNBRK0000001 | IGNPAR0000004);
408
409 new_termios.c_cflag &= ~(CSIZE0000060 | PARENB0000400);
410
411 new_termios.c_cflag |= (CS80000060 | CLOCAL0004000 | CREAD0000200);
412
413 if (d->speed != 0)
414 {
415 int speed_code = -1;
416
417 switch (d->speed)
418 {
419#ifdef B500000001
420 case 50: speed_code = B500000001; break;
421#endif
422#ifdef B750000002
423 case 75: speed_code = B750000002; break;
424#endif
425#ifdef B1100000003
426 case 110: speed_code = B1100000003; break;
427#endif
428#ifdef B1340000004
429 case 134: speed_code = B1340000004; break;
430#endif
431#ifdef B1500000005
432 case 150: speed_code = B1500000005; break;
433#endif
434#ifdef B2000000006
435 case 200: speed_code = B2000000006; break;
436#endif
437#ifdef B3000000007
438 case 300: speed_code = B3000000007; break;
439#endif
440#ifdef B6000000010
441 case 600: speed_code = B6000000010; break;
442#endif
443#ifdef B12000000011
444 case 1200: speed_code = B12000000011; break;
445#endif
446#ifdef B18000000012
447 case 1800: speed_code = B18000000012; break;
448#endif
449#ifdef B24000000013
450 case 2400: speed_code = B24000000013; break;
451#endif
452#ifdef B48000000014
453 case 4800: speed_code = B48000000014; break;
454#endif
455#ifdef B96000000015
456 case 9600: speed_code = B96000000015; break;
457#endif
458#ifdef B192000000016
459 case 19200: speed_code = B192000000016; break;
460#endif
461#ifdef B384000000017
462 case 38400: speed_code = B384000000017; break;
463#endif
464#ifdef B576000010001
465 case 57600: speed_code = B576000010001; break;
466#endif
467#ifdef B1152000010002
468 case 115200: speed_code = B1152000010002; break;
469#endif
470#ifdef B2304000010003
471 case 230400: speed_code = B2304000010003; break;
472#endif
473#ifdef B4608000010004
474 case 460800: speed_code = B4608000010004; break;
475#endif
476#ifdef B5000000010005
477 case 500000: speed_code = B5000000010005; break;
478#endif
479#ifdef B5760000010006
480 case 576000: speed_code = B5760000010006; break;
481#endif
482#ifdef B9216000010007
483 case 921600: speed_code = B9216000010007; break;
484#endif
485#ifdef B10000000010010
486 case 1000000: speed_code = B10000000010010; break;
487#endif
488#ifdef B11520000010011
489 case 1152000: speed_code = B11520000010011; break;
490#endif
491#ifdef B15000000010012
492 case 1500000: speed_code = B15000000010012; break;
493#endif
494#ifdef B20000000010013
495 case 2000000: speed_code = B20000000010013; break;
496#endif
497#ifdef B25000000010014
498 case 2500000: speed_code = B25000000010014; break;
499#endif
500#ifdef B30000000010015
501 case 3000000: speed_code = B30000000010015; break;
502#endif
503#ifdef B35000000010016
504 case 3500000: speed_code = B35000000010016; break;
505#endif
506#ifdef B40000000010017
507 case 4000000: speed_code = B40000000010017; break;
508#endif
509 }
510
511 if (speed_code != -1)
512 {
513 cfsetispeed (&new_termios, speed_code);
514 cfsetospeed (&new_termios, speed_code);
515 }
516 }
517
518 new_flags = new_flags | O_NONBLOCK04000;
519 }
520
521#ifdef ___DEBUG_TTY
522
523 ___printf (" new_termios.c_iflag = 0x%08x\n", new_termios.c_iflag);
524 ___printf (" new_termios.c_oflag = 0x%08x\n", new_termios.c_oflag);
525 ___printf (" new_termios.c_lflag = 0x%08x\n", new_termios.c_lflag);
526
527#endif
528
529 if (tcsetattr (d->fd, TCSANOW0, &new_termios) < 0 ||
530 fcntl (d->fd, F_SETFL4, new_flags) < 0)
531 e = err_code_from_errno ()___err_code_from_errno();
532 }
533
534#endif
535#endif
536
537#ifdef USE_WIN32
538
539 {
540 DWORD hin_mode = d->hin_initial_mode;
541 DWORD hout_mode = d->hout_initial_mode;
542
543 if (current)
544 {
545 if (d->input_allow_special)
546 hin_mode |= (ENABLE_PROCESSED_INPUT);
547 else
548 hin_mode &= ~(ENABLE_PROCESSED_INPUT);
549
550#ifndef USE_LINEEDITOR
551 if (!d->input_raw)
552 hin_mode |= (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
553 else
554#endif
555 hin_mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
556
557#if 0
558#ifndef USE_LINEEDITOR
559 if (!d->output_raw)
560 hout_mode |= (ENABLE_PROCESSED_OUTPUT);
561 else
562#endif
563 hout_mode &= ~(ENABLE_PROCESSED_OUTPUT);
564#endif
565
566 hout_mode |= (ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_PROCESSED_OUTPUT);
567
568 hin_mode |= (ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
569 }
570
571 if (!SetConsoleMode (d->hin, hin_mode) ||
572 !SetConsoleMode (d->hout, hout_mode))
573 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
574 }
575
576#endif
577
578 return e;
579}
580
581
582___HIDDENstatic ___SCMOBJlong ___device_tty_mode_restore
583 ___P((___device_tty *self,(___device_tty *self, int remove)
584 ___BOOL remove),(___device_tty *self, int remove)
585 (self,(___device_tty *self, int remove)
586 remove)(___device_tty *self, int remove)
587___device_tty *self;(___device_tty *self, int remove)
588___BOOL remove;)(___device_tty *self, int remove)
589{
590 ___device_tty *d = self;
591 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
592 ___device_tty *curr = ___tty_mod.mode_save_stack;
593 ___device_tty *prev = NULL((void*)0);
594 ___device_tty *next;
595
596 while (curr != d)
597 {
598 if ((e = ___device_tty_mode_update (curr, 0)) != ___FIX(___NO_ERR)(((long)(0))<<2))
599 break;
600 next = curr->mode_save_stack_next;
601 curr->mode_save_stack_next = prev;
602 prev = curr;
603 curr = next;
604 }
605
606 if (e == ___FIX(___NO_ERR)(((long)(0))<<2) &&
607 curr != NULL((void*)0) &&
608 (e = ___device_tty_mode_update (curr, !remove)) == ___FIX(___NO_ERR)(((long)(0))<<2) &&
609 remove)
610 {
611 d->stage = TTY_STAGE_MODE_NOT_SAVED1;
612 curr = curr->mode_save_stack_next; /* remove d from mode save stack */
613 }
614
615 while (prev != NULL((void*)0))
616 {
617 ___SCMOBJlong e2;
618 next = curr;
619 curr = prev;
620 prev = prev->mode_save_stack_next;
621 curr->mode_save_stack_next = next;
622 if ((e2 = ___device_tty_mode_get (curr)) != ___FIX(___NO_ERR)(((long)(0))<<2) ||
623 (e2 = ___device_tty_mode_update (curr, 1)) != ___FIX(___NO_ERR)(((long)(0))<<2))
624 {
625 if (e == ___FIX(___NO_ERR)(((long)(0))<<2))
626 e = e2;
627 }
628 }
629
630 ___tty_mod.mode_save_stack = curr;
631
632 return e;
633}
634
635
636___HIDDENstatic ___SCMOBJlong ___device_tty_mode_set
637 ___P((___device_tty *self,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
638 ___BOOL input_allow_special,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
639 ___BOOL input_echo,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
640 ___BOOL input_raw,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
641 ___BOOL output_raw,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
642 int speed),(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
643 (self,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
644 input_allow_special,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
645 input_echo,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
646 input_raw,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
647 output_raw,(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
648 speed)(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
649___device_tty *self;(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
650___BOOL input_allow_special;(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
651___BOOL input_echo;(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
652___BOOL input_raw;(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
653___BOOL output_raw;(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
654int speed;)(___device_tty *self, int input_allow_special, int input_echo
, int input_raw, int output_raw, int speed)
655{
656 ___device_tty *d = self;
657
658 /**************** TODO: begin critical section (must block SIGCONT) */
659 d->input_allow_special = input_allow_special;
660 d->input_echo = input_echo;
661 d->input_raw = input_raw;
662 d->output_raw = output_raw;
663 d->speed = speed;
664 /**************** TODO: end critical section (must block SIGCONT) */
665
666 return ___device_tty_mode_restore (d, 0);
667}
668
669
670___HIDDENstatic ___SCMOBJlong ___device_tty_update_size
671 ___P((___device_tty *self),(___device_tty *self)
672 (self)(___device_tty *self)
673___device_tty *self;)(___device_tty *self)
674{
675 ___device_tty *d = self;
676
677 if (d->size_needs_update)
678 {
679 int prev_line_start_col = d->current.line_start % d->terminal_nb_cols;
680 int prev_line_start_row = d->current.line_start / d->terminal_nb_cols;
681
682#ifdef USE_POSIX
683
684#ifdef USE_ioctl
685#ifdef TIOCGWINSZ0x5413
686
687 struct winsize size;
688
689 if (ioctl (d->fd, TIOCGWINSZ0x5413, &size) < 0)
690 return err_code_from_errno ()___err_code_from_errno();
691
692 if (size.ws_col > 0)
693 d->terminal_nb_cols = size.ws_col;
694
695 if (size.ws_row > 0)
696 d->terminal_nb_rows = size.ws_row;
697
698#endif
699#endif
700
701#endif
702
703#ifdef USE_WIN32
704
705 CONSOLE_SCREEN_BUFFER_INFO info;
706
707 if (!GetConsoleScreenBufferInfo (self->hout, &info))
708 return err_code_from_GetLastError ()___err_code_from_GetLastError();
709
710 d->terminal_nb_cols = info.dwSize.X;
711 d->terminal_nb_rows = info.dwSize.Y;
712
713#endif
714
715 d->terminal_size =
716 d->terminal_nb_rows * d->terminal_nb_cols;
717
718 d->terminal_cursor =
719 d->terminal_row * d->terminal_nb_cols + d->terminal_col;
720
721 d->current.line_start =
722 prev_line_start_row * d->terminal_nb_cols + prev_line_start_col;
723
724 d->terminal_delayed_wrap = 0;
725
726 d->size_needs_update = 0;
727 }
728
729 return ___FIX(___NO_ERR)(((long)(0))<<2);
730}
731
732
733___HIDDENstatic ___BOOLint lineeditor_under_emacs ___PVOID(void)
734{
735 static ___UCS_2unsigned short emacs_env_name[] = { 'E', 'M', 'A', 'C', 'S', '\0' };
736 ___UCS_2STRINGunsigned short* cvalue;
737
738 if (___getenv_UCS_2 (emacs_env_name, &cvalue) == ___FIX(___NO_ERR)(((long)(0))<<2))
739 {
740 if (cvalue != 0)
741 {
742 ___free_mem (cvalue);
743 return 1;
744 }
745 }
746
747 return 0;
748}
749
750
751#ifdef USE_WIN32
752
753#if 0
754#ifdef USE_GetConsoleWindow
755
756___BEGIN_C_LINKAGE
757HWND WINAPI GetConsoleWindow (void);
758___END_C_LINKAGE
759
760#endif
761#endif
762
763___HIDDENstatic BOOL WINAPI console_event_handler
764 ___P((DWORD dwCtrlType),(DWORD dwCtrlType)
765 ())(DWORD dwCtrlType);
766
767#endif
768
769
770/* forward declaration */
771
772___HIDDENstatic ___SCMOBJlong lineeditor_redraw
773 ___P((___device_tty *self),(___device_tty *self)
774 ())(___device_tty *self);
775
776
777___HIDDENstatic ___SCMOBJlong ___device_tty_force_open
778 ___P((___device_tty *self),(___device_tty *self)
779 (self)(___device_tty *self)
780___device_tty *self;)(___device_tty *self)
781{
782 ___device_tty *d = self;
783
784 switch (d->stage)
785 {
786 case TTY_STAGE_NOT_OPENED0:
787 {
788#ifdef USE_POSIX
789
790 int fd;
791
792#ifndef HAVE_ctermid
793 char* term_name = "/dev/tty";
794#else
795 char term_name[L_ctermid9];
796 ctermid (term_name); /* get controlling terminal's name */
797#endif
798
799 if ((fd = open (term_name,
800#ifdef LINEEDITOR_WITH_NONBLOCKING_IO
801 O_NONBLOCK04000 |
802#endif
803#ifdef O_BINARY
804 O_BINARY |
805#endif
806 O_RDWR02,
807 0))
808 < 0)
809 {
810#ifdef ENXIO6
811 if (errno(*__errno_location ()) == ENXIO6)
812 {
813 /*
814 * There is no controlling terminal! This is a fatal
815 * error, because trying to display an error message
816 * will just cause the open to be tried again to
817 * report the problem, and this will lead to an
818 * infinite loop.
819 */
820
821 static char *msgs[] =
822 { "No controlling terminal (try using the -:d- runtime option)",
823 NULL((void*)0)
824 };
825
826 ___fatal_error (msgs);
827 }
828#endif
829 return fnf_or_err_code_from_errno ()___err_code_from_errno();
830 }
831
832 d->fd = fd;
833
834#endif
835
836#ifdef USE_WIN32
837
838 DWORD m;
839 HANDLE in;
840 HANDLE out;
841 HANDLE sin = GetStdHandle (STD_INPUT_HANDLE); /* ignore error */
842 HANDLE sout = GetStdHandle (STD_OUTPUT_HANDLE); /* ignore error */
843 HANDLE serr = GetStdHandle (STD_ERROR_HANDLE); /* ignore error */
844
845#ifdef USE_GetConsoleWindow
846
847 HWND cons_wind = GetConsoleWindow ();
848 if (cons_wind == NULL((void*)0) || !IsWindowVisible (cons_wind))
849 FreeConsole ();
850
851#endif
852
853 if (AllocConsole ())
854 {
855 /* restore initial standard handles */
856
857 SetConsoleCtrlHandler (console_event_handler, TRUE); /* ignore error */
858 SetStdHandle (STD_INPUT_HANDLE, sin); /* ignore error */
859 SetStdHandle (STD_OUTPUT_HANDLE, sout); /* ignore error */
860 SetStdHandle (STD_ERROR_HANDLE, serr); /* ignore error */
861 }
862
863 in = CreateFile
864 (_T("CONIN$"),
865 GENERIC_READ | GENERIC_WRITE,
866 FILE_SHARE_READ | FILE_SHARE_WRITE,
867 NULL((void*)0),
868 OPEN_EXISTING,
869 0,
870 NULL((void*)0));
871
872 if (in == INVALID_HANDLE_VALUE)
873 return fnf_or_err_code_from_GetLastError ()___fnf_or_err_code_from_GetLastError();
874
875 out = CreateFile
876 (_T("CONOUT$"),
877 GENERIC_READ | GENERIC_WRITE,
878 FILE_SHARE_READ | FILE_SHARE_WRITE,
879 NULL((void*)0),
880 OPEN_EXISTING,
881 0,
882 NULL((void*)0));
883
884 if (out == INVALID_HANDLE_VALUE)
885 {
886 ___SCMOBJlong e = fnf_or_err_code_from_GetLastError ()___fnf_or_err_code_from_GetLastError();
887 CloseHandle (in); /* ignore error */
888 return e;
889 }
890
891 d->hin = in;
892 d->hout = out;
893
894#endif
895
896 d->stage = TTY_STAGE_MODE_NOT_SAVED1;
897
898 /* fall through */
899 }
900
901 case TTY_STAGE_MODE_NOT_SAVED1:
902 {
903 ___SCMOBJlong e;
904
905 if ((e = ___device_tty_mode_save (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
906 return e;
907
908 /* fall through */
909 }
910
911 case TTY_STAGE_MODE_NOT_SET2:
912 {
913 ___SCMOBJlong e;
914
915 if ((e = ___device_tty_mode_restore (d, 0))
916 != ___FIX(___NO_ERR)(((long)(0))<<2))
917 return e;
918
919 d->stage = TTY_STAGE_INIT_DONE3;
920 }
921 }
922
923 if (d->size_needs_update)
924 {
925 ___SCMOBJlong e;
926 int prev_nb_cols = d->terminal_nb_cols;
927
928 if ((e = ___device_tty_update_size (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
929 return e;
930
931 if (d->editing_line && prev_nb_cols != d->terminal_nb_cols)
932 if ((e = lineeditor_redraw (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
933 return e;
934 }
935
936 return ___FIX(___NO_ERR)(((long)(0))<<2);
937}
938
939
940#ifdef USE_WIN32
941
942___HIDDENstatic void show_cursor
943 ___P((___device_tty *self),(___device_tty *self)
944 (self)(___device_tty *self)
945___device_tty *self;)(___device_tty *self)
946{
947 ___device_tty *d = self;
948 CONSOLE_SCREEN_BUFFER_INFO info;
949
950 if (GetConsoleScreenBufferInfo (d->hout, &info))
951 SetConsoleCursorPosition
952 (d->hout,
953 info.dwCursorPosition); /* ignore error */
954}
955
956#endif
957
958
959___HIDDENstatic ___SCMOBJlong ___device_tty_write
960 ___P((___device_tty *self,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
961 ___U8 *buf,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
962 ___stream_index len,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
963 ___stream_index *len_done),(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
964 (self,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
965 buf,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
966 len,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
967 len_done)(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
968___device_tty *self;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
969___U8 *buf;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
970___stream_index len;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
971___stream_index *len_done;)(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
972{
973 ___device_tty *d = self;
974
975#ifdef USE_POSIX
976
977 {
978 int n;
979
980 if ((n = write (d->fd, buf, len)) < 0)
981 return err_code_from_errno ()___err_code_from_errno();
982
983 *len_done = n;
984 }
985
986#endif
987
988#ifdef USE_WIN32
989
990 {
991 DWORD n;
992 int len_in_chars = TTY_CHAR_SELECT(len,len>>1)len; /* convert bytes to chars */
993
994 if (len_in_chars < 1)
995 return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+3)))<<2)
;
996
997 if (!TTY_CHAR_SELECT(WriteConsoleA (d->hout, buf, len_in_chars, &n, NULL),WriteConsoleA (d->hout, buf, len_in_chars, &n, ((void*
)0))
998 WriteConsoleW (d->hout, buf, len_in_chars, &n, NULL))WriteConsoleA (d->hout, buf, len_in_chars, &n, ((void*
)0))
)
999 return err_code_from_GetLastError ()___err_code_from_GetLastError();
1000
1001 show_cursor (d);
1002
1003 *len_done = TTY_CHAR_SELECT(n,n<<1)n; /* convert chars to bytes */
1004 }
1005
1006#endif
1007
1008 return ___FIX(___NO_ERR)(((long)(0))<<2);
1009}
1010
1011
1012___HIDDENstatic ___SCMOBJlong ___device_tty_write_raw_no_lineeditor
1013 ___P((___device_tty *self,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1014 ___U8 *buf,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1015 ___stream_index len,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1016 ___stream_index *len_done),(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1017 (self,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1018 buf,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1019 len,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1020 len_done)(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1021___device_tty *self;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1022___U8 *buf;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1023___stream_index len;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1024___stream_index *len_done;)(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1025{
1026 ___device_tty *d = self;
1027
1028 if (d->base.base.write_stage != ___STAGE_OPEN0)
1029 return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+6)))<<2)
;
1030
1031 return ___device_tty_write (d, buf, len, len_done);
1032}
1033
1034___HIDDENstatic ___SCMOBJlong ___device_tty_read_raw_no_lineeditor
1035 ___P((___device_tty *self,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1036 ___U8 *buf,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1037 ___stream_index len,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1038 ___stream_index *len_done),(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1039 (self,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1040 buf,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1041 len,(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1042 len_done)(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1043___device_tty *self;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1044___U8 *buf;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1045___stream_index len;(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1046___stream_index *len_done;)(___device_tty *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
1047{
1048 ___device_tty *d = self;
1049
1050 if (d->base.base.read_stage != ___STAGE_OPEN0)
1051 return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+6)))<<2)
;
1052
1053#ifdef USE_POSIX
1054
1055 {
1056 int n;
1057
1058#ifdef ___DEBUG
1059 ___printf ("read len=%d\n", len);
1060#endif
1061
1062 if ((n = read (d->fd, buf, len)) < 0)
1063 return err_code_from_errno ()___err_code_from_errno();
1064
1065#ifdef ___DEBUG
1066 ___printf ("read n=%d\n", n);
1067#endif
1068
1069 *len_done = n;
1070 }
1071
1072#endif
1073
1074#ifdef USE_WIN32
1075
1076 {
1077 char *seq;
1078 int len_in_chars = TTY_CHAR_SELECT(len,len>>1)len; /* convert bytes to chars */
1079
1080 if (len_in_chars < 1)
1081 return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+3)))<<2)
;
1082
1083 next_chars:
1084
1085 seq = d->key_seq;
1086
1087 if (seq != NULL((void*)0))
1088 {
1089 TTY_CHARunsigned char *tty_char_buf = ___CAST(TTY_CHAR*,buf)((unsigned char*)(buf));
1090 int i = 0;
1091
1092 while (i < len_in_chars && *seq != '\0')
1093 {
1094 *tty_char_buf++ = *seq++;
1095 i++;
1096 }
1097
1098 if (*seq == '\0')
1099 d->key_seq = NULL((void*)0);
1100 else
1101 d->key_seq = seq;
1102
1103 if (i > 0)
1104 {
1105 *len_done = TTY_CHAR_SELECT(i,i<<1)i; /* convert chars to bytes */
1106 return ___FIX(___NO_ERR)(((long)(0))<<2);
1107 }
1108 }
1109
1110 next_event:
1111
1112 if (d->ir.EventType != KEY_EVENT ||
1113 d->ir.Event.KeyEvent.wRepeatCount <= 0)
1114 {
1115 DWORD avail;
1116
1117 if (!GetNumberOfConsoleInputEvents (d->hin, &avail))
1118 return err_code_from_GetLastError ()___err_code_from_GetLastError();
1119
1120 if (avail <= 0)
1121 return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<<
16)+(11)))))<<2)
;
1122
1123 if (!TTY_CHAR_SELECT(ReadConsoleInputA (d->hin, &d->ir, 1, &avail),ReadConsoleInputA (d->hin, &d->ir, 1, &avail)
1124 ReadConsoleInputW (d->hin, &d->ir, 1, &avail))ReadConsoleInputA (d->hin, &d->ir, 1, &avail))
1125 return err_code_from_GetLastError ()___err_code_from_GetLastError();
1126
1127 if (avail <= 0)
1128 return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<<
16)+(11)))))<<2)
;
1129 }
1130
1131 switch (d->ir.EventType)
1132 {
1133 case KEY_EVENT:
1134 {
1135 DWORD ctrl_keys;
1136 ___BOOLint ctrl;
1137 ___BOOLint alt;
1138 ___BOOLint shift;
1139 char *seq;
1140 TTY_CHARunsigned char c;
1141
1142 if (!(d->ir.Event.KeyEvent.bKeyDown &&
1143 d->ir.Event.KeyEvent.wRepeatCount > 0))
1144 {
1145 d->ir.EventType = MOUSE_EVENT; /* anything but KEY_EVENT */
1146 goto next_event;
1147 }
1148
1149 ctrl_keys = d->ir.Event.KeyEvent.dwControlKeyState;
1150 ctrl = ctrl_keys & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED);
1151 alt = ctrl_keys & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED);
1152 shift = ctrl_keys & SHIFT_PRESSED;
1153
1154 c = TTY_CHAR_SELECT(d->ir.Event.KeyEvent.uChar.AsciiChar,d->ir.Event.KeyEvent.uChar.AsciiChar
1155 d->ir.Event.KeyEvent.uChar.UnicodeChar)d->ir.Event.KeyEvent.uChar.AsciiChar;
1156
1157 seq = NULL((void*)0);
1158
1159 if (!ctrl && alt && !shift && c>='a' && c<='z')
1160 {
1161 static char alt_seq[3];
1162 alt_seq[0] = ___UNICODE_ESCAPE27;
1163 alt_seq[1] = c;
1164 alt_seq[2] = '\0';
1165 seq = alt_seq;
1166 }
1167 else if (!ctrl && !alt && !shift && c == 0)
1168 switch (d->ir.Event.KeyEvent.wVirtualKeyCode)
1169 {
1170 case VK_BACK: seq = "\010"; break;
1171 case VK_UP: seq = "\033[A"; break;
1172 case VK_DOWN: seq = "\033[B"; break;
1173 case VK_RIGHT: seq = "\033[C"; break;
1174 case VK_LEFT: seq = "\033[D"; break;
1175 case VK_HOME: seq = "\033[H"; break;
1176 case VK_INSERT: seq = "\033[2~"; break;
1177 case VK_DELETE: seq = "\177"; break;
1178 case VK_END: seq = "\033[F"; break;
1179 case VK_PRIOR: seq = "\033[5~"; break;
1180 case VK_NEXT: seq = "\033[6~"; break;
1181 case VK_F1: seq = "\033OP"; break;
1182 case VK_F2: seq = "\033OQ"; break;
1183 case VK_F3: seq = "\033OR"; break;
1184 case VK_F4: seq = "\033OS"; break;
1185 case VK_F5: seq = "\033[15~"; break;
1186 case VK_F6: seq = "\033[17~"; break;
1187 case VK_F7: seq = "\033[18~"; break;
1188 case VK_F8: seq = "\033[19~"; break;
1189 case VK_F9: seq = "\033[20~"; break;
1190 case VK_F10: seq = "\033[21~"; break;
1191 case VK_F11: seq = "\033[23~"; break;
1192 case VK_F12: seq = "\033[24~"; break;
1193 }
1194
1195 if (seq == NULL((void*)0))
1196 {
1197 if (c == 0)
1198 {
1199 d->ir.EventType = MOUSE_EVENT; /* anything but KEY_EVENT */
1200 goto next_event;
1201 }
1202
1203 if (ctrl && c == ' ') /* ctrl-space => NUL character */
1204 c = '\0';
1205
1206 TTY_CHAR_SELECT(buf[0] = c & 0xff; *len_done = 1;
1207 buf[0] = c & 0xff;buf[0] = c & 0xff; *len_done = 1;
1208 *len_done = 1;buf[0] = c & 0xff; *len_done = 1;
1209 ,buf[0] = c & 0xff; *len_done = 1;
1210 buf[0] = c & 0xff;buf[0] = c & 0xff; *len_done = 1;
1211 buf[1] = c >> 8;buf[0] = c & 0xff; *len_done = 1;
1212 *len_done = 2;buf[0] = c & 0xff; *len_done = 1;
1213 )buf[0] = c & 0xff; *len_done = 1;
1214
1215 d->ir.Event.KeyEvent.wRepeatCount--;
1216
1217 return ___FIX(___NO_ERR)(((long)(0))<<2);
1218 }
1219 else
1220 {
1221 d->key_seq = seq;
1222 d->ir.Event.KeyEvent.wRepeatCount--;
1223 goto next_chars;
1224 }
1225
1226 break;
1227 }
1228
1229 case MOUSE_EVENT:
1230 {
1231#if 0
1232 /*************************/
1233 COORD c = d->ir.Event.MouseEvent.dwMousePosition;
1234 CONSOLE_SCREEN_BUFFER_INFO info;
1235 COORD pos;
1236
1237 printf ("m.X=%d m.Y=%d\n",c.X,c.Y);
1238 if (GetConsoleScreenBufferInfo (d->hout, &info))
1239 {
1240 printf (" dwSize.X=%d dwSize.Y=%d\n",info.dwSize.X,info.dwSize.Y);
1241 printf (" dwCursorPosition.X=%d dwCursorPosition.Y=%d\n",info.dwCursorPosition.X,info.dwCursorPosition.Y);
1242 printf (" dwMaximumWindowSize.X=%d dwMaximumWindowSize.Y=%d\n",info.dwMaximumWindowSize.X,info.dwMaximumWindowSize.Y);
1243 printf (" srWindow.Left=%d srWindow.Top=%d\n",info.srWindow.Left,info.srWindow.Top);
1244 printf (" srWindow.Right=%d srWindow.Bottom=%d\n",info.srWindow.Right,info.srWindow.Bottom);
1245 fflush(stdoutstdout);
1246 }
1247
1248 ___WORDlong e;
1249
1250 if (i > 0)
1251 goto done; /* in case paste returns an error */
1252
1253 state->input_rlo++;
1254
1255 if (d->ir.Event.MouseEvent.dwEventFlags == 0 &&
1256 (d->ir.Event.MouseEvent.dwButtonState ==
1257 (FROM_LEFT_1ST_BUTTON_PRESSED | RIGHTMOST_BUTTON_PRESSED) ||
1258 d->ir.Event.MouseEvent.dwButtonState ==
1259 FROM_LEFT_2ND_BUTTON_PRESSED))
1260 if ((e = lineeditor_paste_from_clipboard (state->les))
1261 != ___FIX(___NO_ERR)(((long)(0))<<2))
1262 return e;
1263
1264 goto done; /* pasted text is available to be read */
1265#endif
1266 goto next_event;
1267 }
1268
1269 case WINDOW_BUFFER_SIZE_EVENT:
1270 {
1271 d->size_needs_update = 1;
1272#if 0
1273 COORD c = d->ir.Event.WindowBufferSizeEvent.dwSize;
1274 printf ("c.X=%d c.Y=%d\n", c.X, c.Y);fflush(stdoutstdout);/********************/
1275#endif
1276 goto next_event;
1277 }
1278
1279 default:
1280 goto next_event;
1281 }
1282 }
1283
1284#endif
1285
1286 return ___FIX(___NO_ERR)(((long)(0))<<2);
1287}
1288
1289
1290/*****************************************************************************/
1291
1292/* Line editing subsystem */
1293
1294
1295#ifdef USE_LINEEDITOR
1296
1297
1298/*---------------------------------------------------------------------------*/
1299
1300/* Line editing input decoder routines */
1301
1302
1303___HIDDENstatic ___SCMOBJlong lineeditor_input_decoder_setup
1304 ___P((lineeditor_input_decoder *decoder),(lineeditor_input_decoder *decoder)
1305 (decoder)(lineeditor_input_decoder *decoder)
1306lineeditor_input_decoder *decoder;)(lineeditor_input_decoder *decoder)
1307{
1308#define LINEEDITOR_INPUT_DECODER_INITIAL_BUFFER_SIZE150 150
1309
1310 int n = LINEEDITOR_INPUT_DECODER_INITIAL_BUFFER_SIZE150;
1311
1312 decoder->buffer = ___CAST(lineeditor_input_test*,((lineeditor_input_test*)(___alloc_mem (n * sizeof (lineeditor_input_test
))))
1313 ___alloc_mem (n * sizeof (lineeditor_input_test)))((lineeditor_input_test*)(___alloc_mem (n * sizeof (lineeditor_input_test
))))
;
1314
1315 if (decoder->buffer == NULL((void*)0))
1316 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
1317
1318 decoder->length = 0;
1319 decoder->max_length = n;
1320
1321 return ___FIX(___NO_ERR)(((long)(0))<<2);
1322}
1323
1324
1325___HIDDENstatic void lineeditor_input_decoder_cleanup
1326 ___P((lineeditor_input_decoder *decoder),(lineeditor_input_decoder *decoder)
1327 (decoder)(lineeditor_input_decoder *decoder)
1328lineeditor_input_decoder *decoder;)(lineeditor_input_decoder *decoder)
1329{
1330 ___free_mem (decoder->buffer);
1331}
1332
1333
1334___HIDDENstatic ___SCMOBJlong lineeditor_input_decoder_set_length
1335 ___P((lineeditor_input_decoder *decoder,(lineeditor_input_decoder *decoder, int len, int fudge)
1336 int len,(lineeditor_input_decoder *decoder, int len, int fudge)
1337 int fudge),(lineeditor_input_decoder *decoder, int len, int fudge)
1338 (decoder,(lineeditor_input_decoder *decoder, int len, int fudge)
1339 len,(lineeditor_input_decoder *decoder, int len, int fudge)
1340 fudge)(lineeditor_input_decoder *decoder, int len, int fudge)
1341lineeditor_input_decoder *decoder;(lineeditor_input_decoder *decoder, int len, int fudge)
1342int len;(lineeditor_input_decoder *decoder, int len, int fudge)
1343int fudge;)(lineeditor_input_decoder *decoder, int len, int fudge)
1344{
1345 if (len > LINEEDITOR_INPUT_DECODER_MAX_LENGTH(255 -55 -1))
1346 return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+3)))<<2)
;
1347
1348 if (len > decoder->max_length)
1349 {
1350 int i;
1351 int new_max_length = (fudge<0) ? 3*len/2+1 : len+fudge;
1352 lineeditor_input_test *old_buffer = decoder->buffer;
1353 lineeditor_input_test *new_buffer =
1354 ___CAST(lineeditor_input_test*,((lineeditor_input_test*)(___alloc_mem (new_max_length * sizeof
(lineeditor_input_test))))
1355 ___alloc_mem (new_max_length *((lineeditor_input_test*)(___alloc_mem (new_max_length * sizeof
(lineeditor_input_test))))
1356 sizeof (lineeditor_input_test)))((lineeditor_input_test*)(___alloc_mem (new_max_length * sizeof
(lineeditor_input_test))))
;
1357
1358 if (new_buffer == NULL((void*)0))
1359 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
1360
1361 i = decoder->length;
1362 if (i > len)
1363 i = len;
1364
1365 while (i-- > 0)
1366 new_buffer[i] = old_buffer[i];
1367
1368 ___free_mem (old_buffer);
1369 decoder->buffer = new_buffer;
1370 decoder->max_length = new_max_length;
1371 }
1372
1373 decoder->length = len;
1374
1375 return ___FIX(___NO_ERR)(((long)(0))<<2);
1376}
1377
1378
1379___HIDDENstatic ___SCMOBJlong lineeditor_input_decoder_add
1380 ___P((lineeditor_input_decoder *decoder,(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1381 char *seq,(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1382 ___U8 event),(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1383 (decoder,(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1384 seq,(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1385 event)(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1386lineeditor_input_decoder *decoder;(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1387char *seq;(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1388___U8 event;)(lineeditor_input_decoder *decoder, char *seq, unsigned char event
)
1389{
1390 ___SCMOBJlong e;
1391 ___U8unsigned char b;
1392 int i = 0;
1393 char *p = seq;
1394
1395 if (event & WITH_ESC_PREFIX(unsigned char)(1<<7))
1396 b = ___UNICODE_ESCAPE27;
1397 else
1398 b = ___CAST_U8(*p++)(unsigned char)(*p++);
1399
1400 if (decoder->length > 0)
1401 {
1402 while (b != ___CAST_U8('\0')(unsigned char)('\0') || p == seq+1)
1403 {
1404 if (decoder->buffer[i].trigger == b)
1405 {
1406 int a = decoder->buffer[i].action;
1407 if (a >= decoder->length)
1408 return ___FIX(___NO_ERR)(((long)(0))<<2); /* prefix of sequence exists */
1409 i = a;
1410 b = ___CAST_U8(*p++)(unsigned char)(*p++);
1411 }
1412 else
1413 {
1414 int n = decoder->buffer[i].next;
1415 if (n >= decoder->length)
1416 {
1417 decoder->buffer[i].next = decoder->length;
1418 break;
1419 }
1420 i = n;
1421 }
1422 }
1423 }
1424
1425 if (b != ___CAST_U8('\0')(unsigned char)('\0') || p == seq+1)
1426 {
1427 /* sequence is not a prefix of a preexisting sequence */
1428
1429 while (b != ___CAST_U8('\0')(unsigned char)('\0') || p == seq+1)
1430 {
1431 i = decoder->length;
1432
1433 if ((e = lineeditor_input_decoder_set_length (decoder, i+1, -1))
1434 != ___FIX(___NO_ERR)(((long)(0))<<2))
1435 return e;
1436
1437 decoder->buffer[i].trigger = b;
1438 decoder->buffer[i].action = i+1;
1439 decoder->buffer[i].next = LINEEDITOR_INPUT_DECODER_STATE_MAX255;
1440
1441 b = ___CAST_U8(*p++)(unsigned char)(*p++);
1442 }
1443 decoder->buffer[i].action =
1444 LINEEDITOR_INPUT_DECODER_STATE_MAX255-(event&~WITH_ESC_PREFIX(unsigned char)(1<<7));
1445 }
1446
1447 return ___FIX(___NO_ERR)(((long)(0))<<2);
1448}
1449
1450
1451typedef struct lineeditor_defseq_struct
1452 {
1453 char *seq;
1454 ___U8unsigned char event;
1455 } lineeditor_defseq;
1456
1457
1458___HIDDENstatic lineeditor_defseq lineeditor_defseq_common[] =
1459{
1460 /* sequences that all terminals support */
1461
1462 { "\012", LINEEDITOR_EV_RETURN2 }
1463 ,{ "\015", LINEEDITOR_EV_RETURN2 }
1464 ,{ "\010", LINEEDITOR_EV_BACK3 }
1465 ,{ "\010", LINEEDITOR_EV_BACK_SEXPR5 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1466 ,{ "\011", LINEEDITOR_EV_TAB6 }
1467};
1468
1469
1470___HIDDENstatic lineeditor_defseq lineeditor_defseq_map_rubout_to_backspace[] =
1471{
1472 /* sequences that map the rubout key to backspace */
1473
1474 { "\177", LINEEDITOR_EV_BACK3 }
1475 ,{ "\177", LINEEDITOR_EV_BACK_WORD4 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1476};
1477
1478
1479___HIDDENstatic lineeditor_defseq lineeditor_defseq_emacs[] =
1480{
1481 /* sequences specific to emacs mode */
1482
1483 { "\0", LINEEDITOR_EV_MARK7 }
1484 ,{ "\031", LINEEDITOR_EV_PASTE8 }
1485 ,{ "\027", LINEEDITOR_EV_CUT9 }
1486 ,{ "\013", LINEEDITOR_EV_CUT_RIGHT10 }
1487 ,{ "\025", LINEEDITOR_EV_CUT_LEFT11 }
1488 ,{ "\014", LINEEDITOR_EV_REFRESH12 }
1489 ,{ "\024", LINEEDITOR_EV_TRANSPOSE13 }
1490 ,{ "\024", LINEEDITOR_EV_TRANSPOSE_SEXPR15 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1491 ,{ "t", LINEEDITOR_EV_TRANSPOSE_WORD14 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1492 ,{ "T", LINEEDITOR_EV_TRANSPOSE_WORD14 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1493 ,{ "p", LINEEDITOR_EV_UP16 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1494 ,{ "P", LINEEDITOR_EV_UP16 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1495 ,{ "n", LINEEDITOR_EV_DOWN17 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1496 ,{ "N", LINEEDITOR_EV_DOWN17 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1497
1498 ,{ "\020", LINEEDITOR_EV_UP16 }
1499 ,{ "\016", LINEEDITOR_EV_DOWN17 }
1500 ,{ "\006", LINEEDITOR_EV_RIGHT18 }
1501 ,{ "\002", LINEEDITOR_EV_LEFT21 }
1502 ,{ "\006", LINEEDITOR_EV_RIGHT_SEXPR20 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1503 ,{ "f", LINEEDITOR_EV_RIGHT_WORD19 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1504 ,{ "F", LINEEDITOR_EV_RIGHT_WORD19 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1505 ,{ "\002", LINEEDITOR_EV_LEFT_SEXPR23 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1506 ,{ "b", LINEEDITOR_EV_LEFT_WORD22 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1507 ,{ "B", LINEEDITOR_EV_LEFT_WORD22 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1508
1509 ,{ "\001", LINEEDITOR_EV_HOME24 }
1510 ,{ "\004", LINEEDITOR_EV_DELETE27 }
1511 ,{ "\005", LINEEDITOR_EV_END30 }
1512 ,{ "\004", LINEEDITOR_EV_DELETE_SEXPR29 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1513 ,{ "d", LINEEDITOR_EV_DELETE_WORD28 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1514 ,{ "D", LINEEDITOR_EV_DELETE_WORD28 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1515};
1516
1517
1518___HIDDENstatic lineeditor_defseq lineeditor_defseq_widespread[] =
1519{
1520 /* sequences that many types of terminals support */
1521
1522 { "[A", LINEEDITOR_EV_UP16 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1523 ,{ "[B", LINEEDITOR_EV_DOWN17 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1524 ,{ "[C", LINEEDITOR_EV_RIGHT18 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1525 ,{ "[D", LINEEDITOR_EV_LEFT21 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1526
1527 ,{ "\033[A", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1528 ,{ "\033[B", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1529 ,{ "\033[C", LINEEDITOR_EV_RIGHT_SEXPR20 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1530 ,{ "\033[D", LINEEDITOR_EV_LEFT_SEXPR23 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1531
1532 ,{ "OA", LINEEDITOR_EV_UP16 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1533 ,{ "OB", LINEEDITOR_EV_DOWN17 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1534 ,{ "OC", LINEEDITOR_EV_RIGHT18 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1535 ,{ "OD", LINEEDITOR_EV_LEFT21 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1536
1537 ,{ "\033OA", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1538 ,{ "\033OB", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1539 ,{ "\033OC", LINEEDITOR_EV_RIGHT_SEXPR20 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1540 ,{ "\033OD", LINEEDITOR_EV_LEFT_SEXPR23 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1541
1542 ,{ "A", LINEEDITOR_EV_UP16 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1543 ,{ "B", LINEEDITOR_EV_DOWN17 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1544 ,{ "C", LINEEDITOR_EV_RIGHT18 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1545 ,{ "D", LINEEDITOR_EV_LEFT21 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1546
1547 ,{ "\033A", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1548 ,{ "\033B", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1549 ,{ "\033C", LINEEDITOR_EV_RIGHT_SEXPR20 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1550 ,{ "\033D", LINEEDITOR_EV_LEFT_SEXPR23 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1551
1552#ifdef USE_XTERM_CTRL_COMBINATIONS
1553 ,{ "[5A", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1554 ,{ "[5B", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1555 ,{ "[5C", LINEEDITOR_EV_RIGHT_SEXPR20 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1556 ,{ "[5D", LINEEDITOR_EV_LEFT_SEXPR23 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1557#endif
1558
1559 ,{ "[1~", LINEEDITOR_EV_HOME24 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1560 ,{ "[2~", LINEEDITOR_EV_INSERT26 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1561 ,{ "[3~", LINEEDITOR_EV_DELETE27 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1562 ,{ "[4~", LINEEDITOR_EV_END30 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1563 ,{ "[5~", LINEEDITOR_EV_HOME_DOC25 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1564 ,{ "[6~", LINEEDITOR_EV_END_DOC31 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1565
1566 ,{ "\033[1~", LINEEDITOR_EV_HOME_DOC25 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1567 ,{ "\033[2~", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1568 ,{ "\033[3~", LINEEDITOR_EV_DELETE_SEXPR29 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1569 ,{ "\033[4~", LINEEDITOR_EV_END_DOC31 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1570 ,{ "\033[5~", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1571 ,{ "\033[6~", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1572
1573 ,{ "[H", LINEEDITOR_EV_HOME24 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1574 ,{ "[L", LINEEDITOR_EV_INSERT26 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1575 ,{ "[F", LINEEDITOR_EV_END30 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1576 ,{ "\177", LINEEDITOR_EV_DELETE27 }
1577 ,{ "\033[H", LINEEDITOR_EV_HOME_DOC25 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1578 ,{ "\177", LINEEDITOR_EV_DELETE_SEXPR29 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1579 ,{ "\033[F", LINEEDITOR_EV_END_DOC31 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1580
1581#ifdef USE_XTERM_CTRL_COMBINATIONS
1582 ,{ "[1;5~", LINEEDITOR_EV_HOME_DOC25 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1583 ,{ "[2;5~", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1584 ,{ "[3;5~", LINEEDITOR_EV_DELETE_SEXPR29 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1585 ,{ "[4;5~", LINEEDITOR_EV_END_DOC31 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1586 ,{ "[5;5~", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1587 ,{ "[6;5~", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1588
1589 ,{ "[5H", LINEEDITOR_EV_HOME_DOC25 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1590 ,{ "[5L", LINEEDITOR_EV_NONE0 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1591 ,{ "[5F", LINEEDITOR_EV_END_DOC31 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1592#endif
1593
1594 ,{ "OP", LINEEDITOR_EV_F132 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1595 ,{ "OQ", LINEEDITOR_EV_F234 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1596 ,{ "OR", LINEEDITOR_EV_F336 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1597 ,{ "OS", LINEEDITOR_EV_F438 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1598
1599 ,{ "\033OP", LINEEDITOR_EV_META_F133 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1600 ,{ "\033OQ", LINEEDITOR_EV_META_F235 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1601 ,{ "\033OR", LINEEDITOR_EV_META_F337 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1602 ,{ "\033OS", LINEEDITOR_EV_META_F439 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1603
1604#ifdef USE_XTERM_CTRL_COMBINATIONS
1605 ,{ "O5P", LINEEDITOR_EV_META_F133 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1606 ,{ "O5Q", LINEEDITOR_EV_META_F235 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1607 ,{ "O5R", LINEEDITOR_EV_META_F337 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1608 ,{ "O5S", LINEEDITOR_EV_META_F439 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1609#endif
1610
1611 ,{ "[11~", LINEEDITOR_EV_F132 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1612 ,{ "[12~", LINEEDITOR_EV_F234 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1613 ,{ "[13~", LINEEDITOR_EV_F336 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1614 ,{ "[14~", LINEEDITOR_EV_F438 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1615
1616 ,{ "\033[11~", LINEEDITOR_EV_META_F133 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1617 ,{ "\033[12~", LINEEDITOR_EV_META_F235 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1618 ,{ "\033[13~", LINEEDITOR_EV_META_F337 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1619 ,{ "\033[14~", LINEEDITOR_EV_META_F439 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1620
1621#ifdef USE_XTERM_CTRL_COMBINATIONS
1622 ,{ "[11;5~", LINEEDITOR_EV_META_F133 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1623 ,{ "[12;5~", LINEEDITOR_EV_META_F235 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1624 ,{ "[13;5~", LINEEDITOR_EV_META_F337 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1625 ,{ "[14;5~", LINEEDITOR_EV_META_F439 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1626#endif
1627
1628#ifdef LINEEDITOR_SUPPORT_F5_TO_F12
1629
1630 ,{ "[15~", LINEEDITOR_EV_F540 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1631 ,{ "[17~", LINEEDITOR_EV_F642 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1632 ,{ "[18~", LINEEDITOR_EV_F744 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1633 ,{ "[19~", LINEEDITOR_EV_F846 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1634 ,{ "[20~", LINEEDITOR_EV_F948 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1635 ,{ "[21~", LINEEDITOR_EV_F1050 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1636 ,{ "[23~", LINEEDITOR_EV_F1152 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1637 ,{ "[24~", LINEEDITOR_EV_F1254 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1638
1639 ,{ "\033[15~", LINEEDITOR_EV_META_F541 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1640 ,{ "\033[17~", LINEEDITOR_EV_META_F643 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1641 ,{ "\033[18~", LINEEDITOR_EV_META_F745 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1642 ,{ "\033[19~", LINEEDITOR_EV_META_F847 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1643 ,{ "\033[20~", LINEEDITOR_EV_META_F949 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1644 ,{ "\033[21~", LINEEDITOR_EV_META_F1051 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1645 ,{ "\033[23~", LINEEDITOR_EV_META_F1153 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1646 ,{ "\033[24~", LINEEDITOR_EV_META_F1255 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1647
1648#ifdef USE_XTERM_CTRL_COMBINATIONS
1649 ,{ "[15;5~", LINEEDITOR_EV_META_F541 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1650 ,{ "[17;5~", LINEEDITOR_EV_META_F643 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1651 ,{ "[18;5~", LINEEDITOR_EV_META_F745 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1652 ,{ "[19;5~", LINEEDITOR_EV_META_F847 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1653 ,{ "[20;5~", LINEEDITOR_EV_META_F949 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1654 ,{ "[21;5~", LINEEDITOR_EV_META_F1051 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1655 ,{ "[23;5~", LINEEDITOR_EV_META_F1153 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1656 ,{ "[24;5~", LINEEDITOR_EV_META_F1255 | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1657#endif
1658
1659#endif
1660};
1661
1662
1663___HIDDENstatic ___SCMOBJlong lineeditor_defseq_install_table
1664 ___P((lineeditor_input_decoder *decoder,(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1665 lineeditor_defseq *table,(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1666 int len),(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1667 (decoder,(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1668 table,(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1669 len)(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1670lineeditor_input_decoder *decoder;(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1671lineeditor_defseq *table;(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1672int len;)(lineeditor_input_decoder *decoder, lineeditor_defseq *table,
int len)
1673{
1674 ___SCMOBJlong e;
1675 int i;
1676
1677 for (i=0; i<len; i++)
1678 if ((e = lineeditor_input_decoder_add
1679 (decoder,
1680 table[i].seq,
1681 table[i].event))
1682 != ___FIX(___NO_ERR)(((long)(0))<<2))
1683 return e;
1684
1685 return ___FIX(___NO_ERR)(((long)(0))<<2);
1686}
1687
1688
1689/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1690
1691
1692#ifdef USE_CURSES
1693
1694
1695typedef struct lineeditor_dkey_struct
1696 {
1697 char *cap;
1698 ___U8unsigned char event_no_escape;
1699 ___U8unsigned char event_with_escape;
1700 } lineeditor_dkey;
1701
1702
1703#ifdef USE_TERMCAP
1704
1705#define DKEY(tcap_name,tinfo_name,xterm_def,event_no_esc,event_with_esc){ xterm_def, event_no_esc, event_with_esc | (unsigned char)(1
<<7) }
\
1706{ tcap_name, event_no_esc, event_with_esc | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1707
1708#else
1709
1710#ifdef USE_TERMINFO
1711
1712#define DKEY(tcap_name,tinfo_name,xterm_def,event_no_esc,event_with_esc){ xterm_def, event_no_esc, event_with_esc | (unsigned char)(1
<<7) }
\
1713{ tinfo_name, event_no_esc, event_with_esc | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1714
1715#else
1716
1717#define DKEY(tcap_name,tinfo_name,xterm_def,event_no_esc,event_with_esc){ xterm_def, event_no_esc, event_with_esc | (unsigned char)(1
<<7) }
\
1718{ xterm_def, event_no_esc, event_with_esc | WITH_ESC_PREFIX(unsigned char)(1<<7) }
1719
1720#endif
1721
1722#endif
1723
1724
1725typedef struct lineeditor_dcap_struct
1726 {
1727 char *cap;
1728#ifdef USE_TERMCAP_OR_TERMINFO
1729 char *xterm_cap;
1730#endif
1731 } lineeditor_dcap;
1732
1733
1734#ifdef USE_TERMCAP
1735
1736#define DCAP(tcap_name,tinfo_name,xterm_def){ xterm_def } { tcap_name, xterm_def }
1737
1738#else
1739
1740#ifdef USE_TERMINFO
1741
1742#define DCAP(tcap_name,tinfo_name,xterm_def){ xterm_def } { tinfo_name, xterm_def }
1743
1744#else
1745
1746#define DCAP(tcap_name,tinfo_name,xterm_def){ xterm_def } { xterm_def }
1747
1748#endif
1749
1750#endif
1751
1752
1753___HIDDENstatic lineeditor_dcap lineeditor_dcap_table[LINEEDITOR_CAP_LAST21+1] =
1754{
1755 /* order must match LINEEDITOR_CAP_XXX */
1756
1757 DCAP("ho","home", "\033[H" ){ "\033[H" } /* home cursor */
1758,DCAP("cl","clear","\033[H\033[J" ){ "\033[H\033[J" } /* home cursor and clear screen */
1759,DCAP("up","cuu1", "\033[A" ){ "\033[A" } /* move up one line */
1760,DCAP("do","cud1", "\033[B" ){ "\033[B" } /* move down one line */
1761,DCAP("UP","cuu", "\033[%p1%dA" ){ "\033[%p1%dA" } /* move up N lines */
1762,DCAP("DO","cud", "\033[%p1%dB" ){ "\033[%p1%dB" } /* move down N lines */
1763,DCAP("RI","cuf", "\033[%p1%dC" ){ "\033[%p1%dC" } /* move right N columns */
1764,DCAP("LE","cub", "\033[%p1%dD" ){ "\033[%p1%dD" } /* move left N columns */
1765,DCAP("cm","cup", "\033[%i%p1%d;%p2%dH"){ "\033[%i%p1%d;%p2%dH" } /* move cursor to (ROW,COL) */
1766,DCAP("me","sgr0", "\033[m" ){ "\033[m" } /* turn off all attributes */
1767,DCAP("md","bold", "\033[1m" ){ "\033[1m" } /* turn on bold attribute */
1768,DCAP("us","smul", "\033[4m" ){ "\033[4m" } /* turn on underline attribute */
1769,DCAP("mr","rev", "\033[7m" ){ "\033[7m" } /* turn on reverse attribute */
1770,DCAP("AF","setaf","\033[3%p1%dm" ){ "\033[3%p1%dm" } /* ANSI set foreground color */
1771,DCAP("AB","setab","\033[4%p1%dm" ){ "\033[4%p1%dm" } /* ANSI set background color */
1772,DCAP("cd","ed", "\033[J" ){ "\033[J" } /* erase to end of screen */
1773,DCAP("ce","el", "\033[K" ){ "\033[K" } /* erase to end of line */
1774,DCAP("cb","el1", "\033[1K" ){ "\033[1K" } /* erase to beginning of line */
1775,DCAP(" 0"," 0", "\033[%p1%dt" ){ "\033[%p1%dt" } /* window operation with no arg */
1776,DCAP(" 1"," 1", "\033[%p1%d;%p2%dt" ){ "\033[%p1%d;%p2%dt" } /* window operation with 1 arg */
1777,DCAP(" 2"," 2", "\033[%p1%d;%p2%d;%p3%dt"){ "\033[%p1%d;%p2%d;%p3%dt" } /* window operation with 2 args */
1778,DCAP(" 3"," 3", "\033]%p1%d;" ){ "\033]%p1%d;" } /* window operation with text arg */
1779};
1780
1781
1782___HIDDENstatic lineeditor_dkey lineeditor_dkey_table[] =
1783{
1784 DKEY("ku","kcuu1","\033OA", LINEEDITOR_EV_UP, LINEEDITOR_EV_NONE ){ "\033OA", 16, 0 | (unsigned char)(1<<7) }
1785,DKEY("kd","kcud1","\033OB", LINEEDITOR_EV_DOWN, LINEEDITOR_EV_NONE ){ "\033OB", 17, 0 | (unsigned char)(1<<7) }
1786,DKEY("kr","kcuf1","\033OC", LINEEDITOR_EV_RIGHT, LINEEDITOR_EV_RIGHT_SEXPR ){ "\033OC", 18, 20 | (unsigned char)(1<<7) }
1787,DKEY("kl","kcub1","\033OD", LINEEDITOR_EV_LEFT, LINEEDITOR_EV_LEFT_SEXPR ){ "\033OD", 21, 23 | (unsigned char)(1<<7) }
1788,DKEY("kh","khome","\033[1~", LINEEDITOR_EV_HOME, LINEEDITOR_EV_HOME_DOC ){ "\033[1~", 24, 25 | (unsigned char)(1<<7) }
1789,DKEY("kI","kich1","\033[2~", LINEEDITOR_EV_INSERT, LINEEDITOR_EV_NONE ){ "\033[2~", 26, 0 | (unsigned char)(1<<7) }
1790,DKEY("kD","kdch1","\033[3~", LINEEDITOR_EV_DELETE, LINEEDITOR_EV_DELETE_SEXPR){ "\033[3~", 27, 29 | (unsigned char)(1<<7) }
1791,DKEY("@7","kend", "\033[4~", LINEEDITOR_EV_END, LINEEDITOR_EV_END_DOC ){ "\033[4~", 30, 31 | (unsigned char)(1<<7) }
1792,DKEY("kP","kpp", "\033[5~", LINEEDITOR_EV_HOME_DOC,LINEEDITOR_EV_NONE ){ "\033[5~", 25, 0 | (unsigned char)(1<<7) }
1793,DKEY("kN","knp", "\033[6~", LINEEDITOR_EV_END_DOC, LINEEDITOR_EV_NONE ){ "\033[6~", 31, 0 | (unsigned char)(1<<7) }
1794,DKEY("k1","kf1", "\033OP", LINEEDITOR_EV_F1, LINEEDITOR_EV_META_F1 ){ "\033OP", 32, 33 | (unsigned char)(1<<7) }
1795,DKEY("k2","kf2", "\033OQ", LINEEDITOR_EV_F2, LINEEDITOR_EV_META_F2 ){ "\033OQ", 34, 35 | (unsigned char)(1<<7) }
1796,DKEY("k3","kf3", "\033OR", LINEEDITOR_EV_F3, LINEEDITOR_EV_META_F3 ){ "\033OR", 36, 37 | (unsigned char)(1<<7) }
1797,DKEY("k4","kf4", "\033OS", LINEEDITOR_EV_F4, LINEEDITOR_EV_META_F4 ){ "\033OS", 38, 39 | (unsigned char)(1<<7) }
1798#ifdef LINEEDITOR_SUPPORT_ALTERNATE_ESCAPES
1799,DKEY("kh","khome","\033OH", LINEEDITOR_EV_HOME, LINEEDITOR_EV_HOME_DOC ){ "\033OH", 24, 25 | (unsigned char)(1<<7) }
1800,DKEY("@7","kend", "\033OF", LINEEDITOR_EV_END, LINEEDITOR_EV_END_DOC ){ "\033OF", 30, 31 | (unsigned char)(1<<7) }
1801,DKEY("k1","kf1", "\033[11~",LINEEDITOR_EV_F1, LINEEDITOR_EV_META_F1 ){ "\033[11~", 32, 33 | (unsigned char)(1<<7) }
1802,DKEY("k2","kf2", "\033[12~",LINEEDITOR_EV_F2, LINEEDITOR_EV_META_F2 ){ "\033[12~", 34, 35 | (unsigned char)(1<<7) }
1803,DKEY("k3","kf3", "\033[13~",LINEEDITOR_EV_F3, LINEEDITOR_EV_META_F3 ){ "\033[13~", 36, 37 | (unsigned char)(1<<7) }
1804,DKEY("k4","kf4", "\033[14~",LINEEDITOR_EV_F4, LINEEDITOR_EV_META_F4 ){ "\033[14~", 38, 39 | (unsigned char)(1<<7) }
1805#endif
1806#ifdef LINEEDITOR_SUPPORT_F5_TO_F12
1807,DKEY("k5","kf5", "\033[15~",LINEEDITOR_EV_F5, LINEEDITOR_EV_META_F5 ){ "\033[15~", 40, 41 | (unsigned char)(1<<7) }
1808,DKEY("k6","kf6", "\033[17~",LINEEDITOR_EV_F6, LINEEDITOR_EV_META_F6 ){ "\033[17~", 42, 43 | (unsigned char)(1<<7) }
1809,DKEY("k7","kf7", "\033[18~",LINEEDITOR_EV_F7, LINEEDITOR_EV_META_F7 ){ "\033[18~", 44, 45 | (unsigned char)(1<<7) }
1810,DKEY("k8","kf8", "\033[19~",LINEEDITOR_EV_F8, LINEEDITOR_EV_META_F8 ){ "\033[19~", 46, 47 | (unsigned char)(1<<7) }
1811,DKEY("k9","kf9", "\033[20~",LINEEDITOR_EV_F9, LINEEDITOR_EV_META_F9 ){ "\033[20~", 48, 49 | (unsigned char)(1<<7) }
1812,DKEY("k;","kf10", "\033[21~",LINEEDITOR_EV_F10, LINEEDITOR_EV_META_F10 ){ "\033[21~", 50, 51 | (unsigned char)(1<<7) }
1813,DKEY("F1","kf11", "\033[23~",LINEEDITOR_EV_F11, LINEEDITOR_EV_META_F11 ){ "\033[23~", 52, 53 | (unsigned char)(1<<7) }
1814,DKEY("F2","kf12", "\033[24~",LINEEDITOR_EV_F12, LINEEDITOR_EV_META_F12 ){ "\033[24~", 54, 55 | (unsigned char)(1<<7) }
1815#endif
1816};
1817
1818
1819___HIDDENstatic ___SCMOBJlong lineeditor_dkey_install
1820 ___P((lineeditor_input_decoder *decoder,(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1821 char *cap,(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1822 ___U8 event_no_escape,(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1823 ___U8 event_with_escape,(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1824 ___BOOL force_xterm),(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1825 (decoder,(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1826 cap,(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1827 event_no_escape,(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1828 event_with_escape,(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1829 force_xterm)(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1830lineeditor_input_decoder *decoder;(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1831char *cap;(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1832___U8 event_no_escape;(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1833___U8 event_with_escape;(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1834___BOOL force_xterm;)(lineeditor_input_decoder *decoder, char *cap, unsigned char event_no_escape
, unsigned char event_with_escape, int force_xterm)
1835{
1836 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
1837 char *seq;
1838
1839#ifdef USE_TERMCAP_OR_TERMINFO
1840
1841 if (!force_xterm)
1842 {
1843#ifdef USE_TERMCAP
1844
1845 seq = tgetstr (cap, NULL((void*)0));
1846
1847#else
1848
1849 seq = tigetstr (cap);
1850
1851#endif
1852 }
1853 else
1854
1855#endif
1856
1857 seq = cap;
1858
1859 if (seq != ___CAST(char*,-1)((char*)(-1)) && seq != NULL((void*)0))
1860 if ((e = lineeditor_input_decoder_add (decoder, seq, event_no_escape))
1861 != ___FIX(___NO_ERR)(((long)(0))<<2) &&
1862 event_with_escape != (LINEEDITOR_EV_NONE0|WITH_ESC_PREFIX(unsigned char)(1<<7)))
1863 e = lineeditor_input_decoder_add (decoder, seq, event_with_escape);
1864
1865 return e;
1866}
1867
1868
1869___HIDDENstatic ___SCMOBJlong lineeditor_dkey_install_table
1870 ___P((lineeditor_input_decoder *decoder,(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1871 lineeditor_dkey *table,(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1872 int len,(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1873 ___BOOL force_xterm),(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1874 (decoder,(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1875 table,(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1876 len,(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1877 force_xterm)(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1878lineeditor_input_decoder *decoder;(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1879lineeditor_dkey *table;(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1880int len;(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1881___BOOL force_xterm;)(lineeditor_input_decoder *decoder, lineeditor_dkey *table, int
len, int force_xterm)
1882{
1883 ___SCMOBJlong e;
1884 int i;
1885
1886 for (i=0; i<len; i++)
1887 if ((e = lineeditor_dkey_install
1888 (decoder,
1889 table[i].cap,
1890 table[i].event_no_escape,
1891 table[i].event_with_escape,
1892 force_xterm))
1893 != ___FIX(___NO_ERR)(((long)(0))<<2))
1894 return e;
1895
1896 return ___FIX(___NO_ERR)(((long)(0))<<2);
1897}
1898
1899
1900#endif
1901
1902
1903/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1904
1905
1906___HIDDENstatic ___SCMOBJlong lineeditor_input_decoder_init
1907 ___P((lineeditor_input_decoder *decoder,(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1908 ___BOOL map_rubout_to_backspace,(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1909 ___BOOL emacs_bindings,(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1910 ___BOOL force_xterm),(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1911 (decoder,(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1912 map_rubout_to_backspace,(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1913 emacs_bindings,(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1914 force_xterm)(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1915lineeditor_input_decoder *decoder;(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1916___BOOL map_rubout_to_backspace;(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1917___BOOL emacs_bindings;(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1918___BOOL force_xterm;)(lineeditor_input_decoder *decoder, int map_rubout_to_backspace
, int emacs_bindings, int force_xterm)
1919{
1920 ___SCMOBJlong e;
1921
1922 decoder->length = 0;
1923
1924 if ((e = lineeditor_defseq_install_table
1925 (decoder,
1926 lineeditor_defseq_common,
1927 ___NBELEMS(lineeditor_defseq_common)(sizeof (lineeditor_defseq_common) / sizeof ((lineeditor_defseq_common
)[0]))
))
1928 != ___FIX(___NO_ERR)(((long)(0))<<2))
1929 return e;
1930
1931 if (map_rubout_to_backspace)
1932 if ((e = lineeditor_defseq_install_table
1933 (decoder,
1934 lineeditor_defseq_map_rubout_to_backspace,
1935 ___NBELEMS(lineeditor_defseq_map_rubout_to_backspace)(sizeof (lineeditor_defseq_map_rubout_to_backspace) / sizeof (
(lineeditor_defseq_map_rubout_to_backspace)[0]))
))
1936 != ___FIX(___NO_ERR)(((long)(0))<<2))
1937 return e;
1938
1939 if (emacs_bindings)
1940 if ((e = lineeditor_defseq_install_table
1941 (decoder,
1942 lineeditor_defseq_emacs,
1943 ___NBELEMS(lineeditor_defseq_emacs)(sizeof (lineeditor_defseq_emacs) / sizeof ((lineeditor_defseq_emacs
)[0]))
))
1944 != ___FIX(___NO_ERR)(((long)(0))<<2))
1945 return e;
1946
1947#ifdef USE_CURSES
1948
1949 if ((e = lineeditor_dkey_install_table
1950 (decoder,
1951 lineeditor_dkey_table,
1952 ___NBELEMS(lineeditor_dkey_table)(sizeof (lineeditor_dkey_table) / sizeof ((lineeditor_dkey_table
)[0]))
,
1953 force_xterm))
1954 != ___FIX(___NO_ERR)(((long)(0))<<2))
1955 return e;
1956
1957#endif
1958
1959 if ((e = lineeditor_defseq_install_table
1960 (decoder,
1961 lineeditor_defseq_widespread,
1962 ___NBELEMS(lineeditor_defseq_widespread)(sizeof (lineeditor_defseq_widespread) / sizeof ((lineeditor_defseq_widespread
)[0]))
))
1963 != ___FIX(___NO_ERR)(((long)(0))<<2))
1964 return e;
1965
1966 return ___FIX(___NO_ERR)(((long)(0))<<2);
1967}
1968
1969
1970/*---------------------------------------------------------------------------*/
1971
1972/* Line editing history routines */
1973
1974
1975___HIDDENstatic ___SCMOBJlong lineeditor_history_begin_edit
1976 ___P((___device_tty *self,(___device_tty *self, lineeditor_history *h)
1977 lineeditor_history *h),(___device_tty *self, lineeditor_history *h)
1978 (self,(___device_tty *self, lineeditor_history *h)
1979 h)(___device_tty *self, lineeditor_history *h)
1980___device_tty *self;(___device_tty *self, lineeditor_history *h)
1981lineeditor_history *h;)(___device_tty *self, lineeditor_history *h)
1982{
1983#define LINEEDITOR_FUDGE80 80
1984
1985 ___device_tty *d = self;
1986 ___SCMOBJlong e;
1987
1988 if (h->edited.buffer == NULL((void*)0))
1989 {
1990 if ((e = extensible_string_copy
1991 (h->actual.buffer,
1992 h->actual.length,
1993 &h->edited,
1994 LINEEDITOR_FUDGE80))
1995 != ___FIX(___NO_ERR)(((long)(0))<<2))
1996 return e;
1997 }
1998
1999 return ___FIX(___NO_ERR)(((long)(0))<<2);
2000}
2001
2002
2003___HIDDENstatic void lineeditor_history_end_edit
2004 ___P((___device_tty *self,(___device_tty *self, lineeditor_history *h)
2005 lineeditor_history *h),(___device_tty *self, lineeditor_history *h)
2006 (self,(___device_tty *self, lineeditor_history *h)
2007 h)(___device_tty *self, lineeditor_history *h)
2008___device_tty *self;(___device_tty *self, lineeditor_history *h)
2009lineeditor_history *h;)(___device_tty *self, lineeditor_history *h)
2010{
2011 ___device_tty *d = self;
2012
2013 if (h->edited.buffer != NULL((void*)0))
2014 {
2015 extensible_string_cleanup (&h->edited);
2016 h->edited.buffer = NULL((void*)0);
2017 }
2018}
2019
2020
2021___HIDDENstatic ___SCMOBJlong lineeditor_history_setup
2022 ___P((___device_tty *self,(___device_tty *self, lineeditor_history **hist)
2023 lineeditor_history **hist),(___device_tty *self, lineeditor_history **hist)
2024 (self,(___device_tty *self, lineeditor_history **hist)
2025 hist)(___device_tty *self, lineeditor_history **hist)
2026___device_tty *self;(___device_tty *self, lineeditor_history **hist)
2027lineeditor_history **hist;)(___device_tty *self, lineeditor_history **hist)
2028{
2029 ___device_tty *d = self;
2030 ___SCMOBJlong e;
2031 lineeditor_history *h;
2032
2033 h = ___CAST(lineeditor_history*,((lineeditor_history*)(___alloc_mem (sizeof (lineeditor_history
))))
2034 ___alloc_mem (sizeof (lineeditor_history)))((lineeditor_history*)(___alloc_mem (sizeof (lineeditor_history
))))
;
2035
2036 if (h == NULL((void*)0))
2037 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
2038
2039 if ((e = extensible_string_setup (&h->actual, 0)) != ___FIX(___NO_ERR)(((long)(0))<<2))
2040 {
2041 ___free_mem (h);
2042 return e;
2043 }
2044
2045 h->edited.buffer = NULL((void*)0);
2046
2047 h->prev = h; /* create a circular list */
2048 h->next = h;
2049
2050 *hist = h;
2051
2052 return ___FIX(___NO_ERR)(((long)(0))<<2);
2053}
2054
2055
2056___HIDDENstatic ___SCMOBJlong lineeditor_history_cleanup
2057 ___P((___device_tty *self,(___device_tty *self, lineeditor_history *h)
2058 lineeditor_history *h),(___device_tty *self, lineeditor_history *h)
2059 (self,(___device_tty *self, lineeditor_history *h)
2060 h)(___device_tty *self, lineeditor_history *h)
2061___device_tty *self;(___device_tty *self, lineeditor_history *h)
2062lineeditor_history *h;)(___device_tty *self, lineeditor_history *h)
2063{
2064 ___device_tty *d = self;
2065
2066 lineeditor_history_end_edit (d, h);
2067
2068 extensible_string_cleanup (&h->actual);
2069
2070 ___free_mem (h);
2071
2072 return ___FIX(___NO_ERR)(((long)(0))<<2);
2073}
2074
2075
2076___HIDDENstatic void lineeditor_history_remove
2077 ___P((___device_tty *self,(___device_tty *self, lineeditor_history *item)
2078 lineeditor_history *item),(___device_tty *self, lineeditor_history *item)
2079 (self,(___device_tty *self, lineeditor_history *item)
2080 item)(___device_tty *self, lineeditor_history *item)
2081___device_tty *self;(___device_tty *self, lineeditor_history *item)
2082lineeditor_history *item;)(___device_tty *self, lineeditor_history *item)
2083{
2084 ___device_tty *d = self;
2085
2086 lineeditor_history *prev = item->prev;
2087 lineeditor_history *next = item->next;
2088
2089 if (prev == item)
2090 d->hist_last = NULL((void*)0);
2091 else
2092 {
2093 next->prev = prev;
2094 prev->next = next;
2095 item->prev = item;
2096 item->next = item;
2097 if (d->hist_last == item)
2098 d->hist_last = prev;
2099 }
2100}
2101
2102
2103___HIDDENstatic void lineeditor_history_trim_to
2104 ___P((___device_tty *self,(___device_tty *self, int max_length)
2105 int max_length),(___device_tty *self, int max_length)
2106 (self,(___device_tty *self, int max_length)
2107 max_length)(___device_tty *self, int max_length)
2108___device_tty *self;(___device_tty *self, int max_length)
2109int max_length;)(___device_tty *self, int max_length)
2110{
2111 ___device_tty *d = self;
2112
2113 while (d->history_length > max_length)
2114 {
2115 lineeditor_history *first = d->hist_last->next;
2116 lineeditor_history_remove (d, first);
2117 lineeditor_history_cleanup (d, first); /* ignore error */
2118 d->history_length--;
2119 }
2120}
2121
2122
2123___HIDDENstatic void lineeditor_history_trim
2124 ___P((___device_tty *self),(___device_tty *self)
2125 (self)(___device_tty *self)
2126___device_tty *self;)(___device_tty *self)
2127{
2128 ___device_tty *d = self;
2129
2130 lineeditor_history_trim_to (d, d->history_max_length);
2131}
2132
2133
2134___HIDDENstatic void lineeditor_set_history_max_length
2135 ___P((___device_tty *self,(___device_tty *self, int history_max_length)
2136 int history_max_length),(___device_tty *self, int history_max_length)
2137 (self,(___device_tty *self, int history_max_length)
2138 history_max_length)(___device_tty *self, int history_max_length)
2139___device_tty *self;(___device_tty *self, int history_max_length)
2140int history_max_length;)(___device_tty *self, int history_max_length)
2141{
2142 ___device_tty *d = self;
2143
2144 if (history_max_length >= 0)
2145 {
2146 d->history_max_length = history_max_length;
2147 lineeditor_history_trim (d);
2148 }
2149}
2150
2151
2152___HIDDENstatic void lineeditor_history_add_after
2153 ___P((___device_tty *self,(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2154 lineeditor_history *item,(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2155 lineeditor_history *dest),(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2156 (self,(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2157 item,(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2158 dest)(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2159___device_tty *self;(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2160lineeditor_history *item;(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2161lineeditor_history *dest;)(___device_tty *self, lineeditor_history *item, lineeditor_history
*dest)
2162{
2163 ___device_tty *d = self;
2164
2165 if (dest == NULL((void*)0))
2166 {
2167 item->prev = item;
2168 item->next = item;
2169 }
2170 else
2171 {
2172 lineeditor_history *after_dest = dest->next;
2173 item->next = after_dest;
2174 item->prev = dest;
2175 dest->next = item;
2176 after_dest->prev = item;
2177 }
2178
2179 d->history_length++;
2180}
2181
2182
2183___HIDDENstatic void lineeditor_history_add_last
2184 ___P((___device_tty *self,(___device_tty *self, lineeditor_history *item)
2185 lineeditor_history *item),(___device_tty *self, lineeditor_history *item)
2186 (self,(___device_tty *self, lineeditor_history *item)
2187 item)(___device_tty *self, lineeditor_history *item)
2188___device_tty *self;(___device_tty *self, lineeditor_history *item)
2189lineeditor_history *item;)(___device_tty *self, lineeditor_history *item)
2190{
2191 ___device_tty *d = self;
2192
2193 lineeditor_history_add_after (d, item, d->hist_last);
2194 d->hist_last = item;
2195}
2196
2197
2198___HIDDENstatic ___SCMOBJlong lineeditor_history_add_line_before_last
2199 ___P((___device_tty *self,(___device_tty *self, int len, extensible_string_char *chars)
2200 int len,(___device_tty *self, int len, extensible_string_char *chars)
2201 extensible_string_char *chars),(___device_tty *self, int len, extensible_string_char *chars)
2202 (self,(___device_tty *self, int len, extensible_string_char *chars)
2203 len,(___device_tty *self, int len, extensible_string_char *chars)
2204 chars)(___device_tty *self, int len, extensible_string_char *chars)
2205___device_tty *self;(___device_tty *self, int len, extensible_string_char *chars)
2206int len;(___device_tty *self, int len, extensible_string_char *chars)
2207extensible_string_char *chars;)(___device_tty *self, int len, extensible_string_char *chars)
2208{
2209 ___SCMOBJlong e;
2210 lineeditor_history *line;
2211
2212 if ((e = lineeditor_history_setup (self, &line))
2213 == ___FIX(___NO_ERR)(((long)(0))<<2))
2214 {
2215 if ((e = extensible_string_insert_at_end (&line->actual, len, chars))
2216 == ___FIX(___NO_ERR)(((long)(0))<<2))
2217 lineeditor_history_add_after (self, line, self->hist_last->prev);
2218 else
2219 lineeditor_history_cleanup (self, line); /* ignore error */
2220 }
2221
2222 return e;
2223}
2224
2225
2226/*---------------------------------------------------------------------------*/
2227
2228/* Line editing routines */
2229
2230
2231___HIDDENstatic ___SCMOBJlong lineeditor_output_drain
2232 ___P((___device_tty *self),(___device_tty *self)
2233 (self)(___device_tty *self)
2234___device_tty *self;)(___device_tty *self)
2235{
2236 /*
2237 * This routine drains the output buffers. The return value is
2238 * ___FIX(___NO_ERR) if and only if the output buffers were
2239 * completely drained. The return value is different from
2240 * ___FIX(___NO_ERR) only when ___device_tty_write
2241 * returned an error.
2242 */
2243
2244 ___device_tty *d = self;
2245 ___SCMOBJlong e;
2246
2247 for (;;)
2248 {
2249 int byte_avail;
2250 int len = d->output_byte_hi - d->output_byte_lo;
2251
2252 while (len > 0)
2253 {
2254 ___stream_index len_done;
2255 ___U8unsigned char *byte_buf = d->output_byte + d->output_byte_lo;
2256
2257 if ((e = ___device_tty_write
2258 (d,
2259 byte_buf,
2260 len,
2261 &len_done)) != ___FIX(___NO_ERR)(((long)(0))<<2))
2262 return e;
2263
2264 len = d->output_byte_hi - (d->output_byte_lo += len_done);
2265 }
2266
2267 d->output_byte_lo = 0;
2268 d->output_byte_hi = 0;
2269
2270 len = d->output_char.length - d->output_char_lo;
2271
2272 if (len <= 0)
2273 break;
2274
2275 do
2276 {
2277 ___Cunsigned int *char_buf = d->output_char.buffer + d->output_char_lo;
2278 ___U8unsigned char *byte_buf = d->output_byte + d->output_byte_hi;
2279
2280 byte_avail = ___NBELEMS(d->output_byte)(sizeof (d->output_byte) / sizeof ((d->output_byte)[0])
)
- d->output_byte_hi;
2281
2282 if (chars_to_bytes (char_buf,
2283 &len,
2284 byte_buf,
2285 &byte_avail,
2286 &d->output_encoding_state)
2287 == ___ILLEGAL_CHAR2)
2288 len--; /* skip over the illegal character */
2289
2290#ifdef ___DEBUG_TTY
2291
2292 {
2293 int i;
2294 int n = (___NBELEMS(d->output_byte)(sizeof (d->output_byte) / sizeof ((d->output_byte)[0])
)
- d->output_byte_hi) - byte_avail;
2295
2296 ___printf ("lineeditor_output_drain nb_bytes: %d ", n);
2297
2298 for (i=0; i<n; i++)
2299 ___printf (" %02x", d->output_byte[i]);
2300
2301 ___printf ("\n");
2302 }
2303
2304#endif
2305
2306 d->output_char_lo = d->output_char.length - len;
2307
2308 d->output_byte_hi = ___NBELEMS(d->output_byte)(sizeof (d->output_byte) / sizeof ((d->output_byte)[0])
)
- byte_avail;
2309 } while (byte_avail > 0 && len > 0);
2310
2311 if (len <= 0)
2312 {
2313 extensible_string_set_length
2314 (&d->output_char, 0, 1); /* ignore error */
2315 d->output_char.length = 0; /* in case set_length failed */
2316 d->output_char_lo = 0;
2317 }
2318 }
2319
2320 return ___FIX(___NO_ERR)(((long)(0))<<2);
2321}
2322
2323
2324/* forward declaration needed because lineeditor_output is recursive */
2325
2326___HIDDENstatic ___SCMOBJlong lineeditor_output_terminal_emulate
2327 ___P((___device_tty *self,(___device_tty *self, unsigned int *buf, int len)
2328 ___C *buf,(___device_tty *self, unsigned int *buf, int len)
2329 int len),(___device_tty *self, unsigned int *buf, int len)
2330 ())(___device_tty *self, unsigned int *buf, int len);
2331
2332
2333___HIDDENstatic ___SCMOBJlong lineeditor_output
2334 ___P((___device_tty *self,(___device_tty *self, unsigned int *buf, int len)
2335 ___C *buf,(___device_tty *self, unsigned int *buf, int len)
2336 int len),(___device_tty *self, unsigned int *buf, int len)
2337 (self,(___device_tty *self, unsigned int *buf, int len)
2338 buf,(___device_tty *self, unsigned int *buf, int len)
2339 len)(___device_tty *self, unsigned int *buf, int len)
2340___device_tty *self;(___device_tty *self, unsigned int *buf, int len)
2341___C *buf;(___device_tty *self, unsigned int *buf, int len)
2342int len;)(___device_tty *self, unsigned int *buf, int len)
2343{
2344 /*
2345 * This routine outputs the string of characters "buf" of length
2346 * "len" to the terminal.
2347 */
2348
2349 ___device_tty *d = self;
2350 ___SCMOBJlong e;
2351
2352#ifdef ___DEBUG_TTY
2353
2354 {
2355 int i;
2356
2357 ___printf ("et:%d row:%2d col:%2d cursor:%2d dw:%d len:%3d ",
2358 d->emulate_terminal,
2359 d->terminal_row,
2360 d->terminal_col,
2361 d->terminal_cursor,
2362 d->terminal_delayed_wrap,
2363 len);
2364
2365 ___printf ("\"");
2366
2367 for (i=0; i<len; i++)
2368 if (buf[i] < 32 || buf[i] >= 127)
2369 ___printf ("\\x%02x", buf[i]);
2370 else
2371 ___printf ("%c", buf[i]);
2372
2373 ___printf ("\"\n");
2374 }
2375
2376#endif
2377
2378 if (d->emulate_terminal)
2379 {
2380 d->emulate_terminal = 0;
2381 e = lineeditor_output_terminal_emulate (d, buf, len);
2382 d->emulate_terminal = 1;
2383 }
2384 else
2385 e = extensible_string_insert
2386 (&d->output_char,
2387 d->output_char.length,
2388 len,
2389 buf);
2390
2391#ifdef USE_WIN32
2392 e = lineeditor_output_drain (d);/******************************/
2393#endif
2394
2395 return e;
2396}
2397
2398
2399___HIDDENstatic ___SCMOBJlong lineeditor_output_curses_drain
2400 ___P((int len),(int len)
2401 (len)(int len)
2402int len;)(int len)
2403{
2404 /*
2405 * This routine drains the curses output buffer. The parameters it
2406 * uses are stored in the TTY module structure "___tty_mod" (because
2407 * C does not have closures...).
2408 */
2409
2410 struct ___curses_struct *cs = &CURRENT_CURSES_STRUCT___tty_mod.curses[___tty_mod.curses_tty->emulate_terminal];
2411
2412 return lineeditor_output (___tty_mod.curses_tty, cs->output, len);
2413}
2414
2415
2416___HIDDENstatic int lineeditor_output_curses
2417 ___P((int c),(int c)
2418 (c)(int c)
2419int c;)(int c)
2420{
2421 /*
2422 * This routine outputs a C character. It is passed as an argument
2423 * to the termcap/terminfo "tputs" routine for outputing individual
2424 * characters. The parameters it uses are stored in the TTY module
2425 * structure "___tty_mod" (because C does not have closures...).
2426 */
2427
2428 struct ___curses_struct *cs = &CURRENT_CURSES_STRUCT___tty_mod.curses[___tty_mod.curses_tty->emulate_terminal];
2429
2430 if (cs->last_err == ___FIX(___NO_ERR)(((long)(0))<<2))
2431 {
2432 cs->output[cs->output_lo++] = c;
2433
2434 if (cs->output_lo >= ___CAST(int,___NBELEMS(cs->output))((int)((sizeof (cs->output) / sizeof ((cs->output)[0]))
))
)
2435 {
2436 cs->last_err = lineeditor_output_curses_drain
2437 (___NBELEMS(cs->output)(sizeof (cs->output) / sizeof ((cs->output)[0])));
2438 cs->output_lo = 0;
2439 }
2440 }
2441
2442 return c;
2443}
2444
2445
2446___HIDDENstatic char *lineeditor_cap
2447 ___P((___device_tty *self,(___device_tty *self, int cap)
2448 int cap),(___device_tty *self, int cap)
2449 (self,(___device_tty *self, int cap)
2450 cap)(___device_tty *self, int cap)
2451___device_tty *self;(___device_tty *self, int cap)
2452int cap;)(___device_tty *self, int cap)
2453{
2454 /*
2455 * This routine returns the curses string for the terminal
2456 * capability "cap".
2457 */
2458
2459 ___device_tty *d = self;
2460
2461#ifdef TERMINAL_EMULATION_USES_CURSES
2462
2463 if (!d->emulate_terminal)
2464 return d->capability[cap];
2465
2466#endif
2467
2468#ifdef USE_TERMCAP_OR_TERMINFO
2469
2470 return lineeditor_dcap_table[cap].xterm_cap;
2471
2472#else
2473
2474 return lineeditor_dcap_table[cap].cap;
2475
2476#endif
2477}
2478
2479
2480___HIDDENstatic ___SCMOBJlong lineeditor_output_cap3
2481 ___P((___device_tty *self,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2482 int cap,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2483 int arg1,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2484 int arg2,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2485 int arg3,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2486 int rep),(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2487 (self,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2488 cap,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2489 arg1,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2490 arg2,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2491 arg3,(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2492 rep)(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2493___device_tty *self;(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2494int cap;(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2495int arg1;(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2496int arg2;(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2497int arg3;(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2498int rep;)(___device_tty *self, int cap, int arg1, int arg2, int arg3, int
rep)
2499{
2500 /*
2501 * This routine outputs the character sequence for the terminal
2502 * capability "cap" with integer parameters "arg1", "arg2" and "arg3"
2503 * (-1 means no parameter). This is repeated "rep" times.
2504 */
2505
2506 ___device_tty *d = self;
2507 struct ___curses_struct *cs;
2508 char *str = lineeditor_cap (d, cap);
2509
2510 if (str == NULL((void*)0))
2511 return ___FIX(___NO_ERR)(((long)(0))<<2);
2512
2513 ___tty_mod.curses_tty = d;
2514
2515 cs = &CURRENT_CURSES_STRUCT___tty_mod.curses[___tty_mod.curses_tty->emulate_terminal];
2516 cs->output_lo = 0;
2517 cs->last_err = ___FIX(___NO_ERR)(((long)(0))<<2);
2518
2519 while (rep > 0)
2520 {
2521 char *p;
2522
2523 if (cap < LINEEDITOR_CAP_SGR09) /******** TODO: this belongs elsewhere */
2524 d->terminal_delayed_wrap = 0; /* cursor cmds cancel delayed wrap */
2525
2526#ifdef TERMINAL_EMULATION_USES_CURSES
2527#ifdef USE_TERMCAP_OR_TERMINFO
2528
2529 if (!d->emulate_terminal)
2530 {
2531 p = str;
2532
2533 if (arg1 >= 0 && arg3 < 0)
2534 {
2535#ifdef USE_TERMCAP
2536 p = tgoto (p, arg2, arg1);
2537#else
2538 if (arg2 >= 0)
2539 p = tparm (p, arg1, arg2);
2540 else
2541 p = tparm (p, arg1);
2542#endif
2543 }
2544
2545 if (tputs (p, 1, lineeditor_output_curses) == ERR &&
2546 cs->last_err == ___FIX(___NO_ERR)(((long)(0))<<2))
2547 cs->last_err = ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+3)))<<2)
;
2548 }
2549 else
2550
2551#endif
2552#endif
2553
2554 {
2555 int params[3];
2556 int stack[10];
2557 int sp = 0;
2558
2559 params[0] = arg1;
2560 params[1] = arg2;
2561 params[2] = arg3;
2562
2563 p = str;
2564
2565 while (*p != '\0')
2566 {
2567 ___Cunsigned int c = *p++;
2568
2569 if (c == '%') /* start of a formatting command? */
2570 {
2571 switch (*p++)
2572 {
2573 case 'i':
2574 params[0]++;
2575 params[1]++;
2576 break;
2577
2578 case 'p':
2579 if (sp < ___CAST(int,___NBELEMS(stack))((int)((sizeof (stack) / sizeof ((stack)[0])))))
2580 stack[sp++] = params[*p++ - '1'];
2581 break;
2582
2583 case 'd':
2584 {
2585 int d = 1;
2586 int n;
2587
2588 if (sp > 0)
2589 n = stack[--sp];
2590 else
2591 n = 0;
2592
2593 while (d*10 <= n)
2594 d *= 10;
2595
2596 while (d > 0)
2597 {
2598 lineeditor_output_curses ('0' + (n / d) % 10);
2599 d /= 10;
2600 }
2601
2602 break;
2603 }
2604 }
2605 }
2606 else
2607 lineeditor_output_curses (c);
2608 }
2609 }
2610
2611 if (cs->last_err != ___FIX(___NO_ERR)(((long)(0))<<2))
2612 return cs->last_err;
2613
2614 rep--;
2615 }
2616
2617 return lineeditor_output_curses_drain (cs->output_lo);
2618}
2619
2620___HIDDENstatic ___SCMOBJlong lineeditor_output_cap0
2621 ___P((___device_tty *self,(___device_tty *self, int cap, int rep)
2622 int cap,(___device_tty *self, int cap, int rep)
2623 int rep),(___device_tty *self, int cap, int rep)
2624 (self,(___device_tty *self, int cap, int rep)
2625 cap,(___device_tty *self, int cap, int rep)
2626 rep)(___device_tty *self, int cap, int rep)
2627___device_tty *self;(___device_tty *self, int cap, int rep)
2628int cap;(___device_tty *self, int cap, int rep)
2629int rep;)(___device_tty *self, int cap, int rep)
2630{
2631 return lineeditor_output_cap3 (self, cap, -1, -1, -1, rep);
2632}
2633
2634___HIDDENstatic ___SCMOBJlong lineeditor_output_cap1
2635 ___P((___device_tty *self,(___device_tty *self, int cap, int arg1, int rep)
2636 int cap,(___device_tty *self, int cap, int arg1, int rep)
2637 int arg1,(___device_tty *self, int cap, int arg1, int rep)
2638 int rep),(___device_tty *self, int cap, int arg1, int rep)
2639 (self,(___device_tty *self, int cap, int arg1, int rep)
2640 cap,(___device_tty *self, int cap, int arg1, int rep)
2641 arg1,(___device_tty *self, int cap, int arg1, int rep)
2642 rep)(___device_tty *self, int cap, int arg1, int rep)
2643___device_tty *self;(___device_tty *self, int cap, int arg1, int rep)
2644int cap;(___device_tty *self, int cap, int arg1, int rep)
2645int arg1;(___device_tty *self, int cap, int arg1, int rep)
2646int rep;)(___device_tty *self, int cap, int arg1, int rep)
2647{
2648 return lineeditor_output_cap3 (self, cap, arg1, -1, -1, rep);
2649}
2650
2651___HIDDENstatic ___SCMOBJlong lineeditor_output_cap2
2652 ___P((___device_tty *self,(___device_tty *self, int cap, int arg1, int arg2, int rep)
2653 int cap,(___device_tty *self, int cap, int arg1, int arg2, int rep)
2654 int arg1,(___device_tty *self, int cap, int arg1, int arg2, int rep)
2655 int arg2,(___device_tty *self, int cap, int arg1, int arg2, int rep)
2656 int rep),(___device_tty *self, int cap, int arg1, int arg2, int rep)
2657 (self,(___device_tty *self, int cap, int arg1, int arg2, int rep)
2658 cap,(___device_tty *self, int cap, int arg1, int arg2, int rep)
2659 arg1,(___device_tty *self, int cap, int arg1, int arg2, int rep)
2660 arg2,(___device_tty *self, int cap, int arg1, int arg2, int rep)
2661 rep)(___device_tty *self, int cap, int arg1, int arg2, int rep)
2662___device_tty *self;(___device_tty *self, int cap, int arg1, int arg2, int rep)
2663int cap;(___device_tty *self, int cap, int arg1, int arg2, int rep)
2664int arg1;(___device_tty *self, int cap, int arg1, int arg2, int rep)
2665int arg2;(___device_tty *self, int cap, int arg1, int arg2, int rep)
2666int rep;)(___device_tty *self, int cap, int arg1, int arg2, int rep)
2667{
2668 return lineeditor_output_cap3 (self, cap, arg1, arg2, -1, rep);
2669}
2670
2671___HIDDENstatic ___SCMOBJlong lineeditor_output_set_attrs
2672 ___P((___device_tty *self,(___device_tty *self, tty_text_attrs attrs)
2673 tty_text_attrs attrs),(___device_tty *self, tty_text_attrs attrs)
2674 (self,(___device_tty *self, tty_text_attrs attrs)
2675 attrs)(___device_tty *self, tty_text_attrs attrs)
2676___device_tty *self;(___device_tty *self, tty_text_attrs attrs)
2677tty_text_attrs attrs;)(___device_tty *self, tty_text_attrs attrs)
2678{
2679 /*
2680 * This routine outputs the character sequence that sets the text
2681 * attributes of the next characters sent to the terminal.
2682 */
2683
2684 ___device_tty *d = self;
2685 ___SCMOBJlong e;
2686 int turn_on;
2687 tty_text_attrs current_attrs;
2688
2689#ifdef TERMINAL_EMULATION_USES_CURSES
2690
2691 if (!d->emulate_terminal)
2692 {
2693 current_attrs = d->terminal_attrs;
2694 d->terminal_attrs = attrs;
2695 }
2696 else
2697
2698#endif
2699
2700 {
2701 current_attrs = d->current.attrs;
2702 d->current.attrs = attrs;
2703 }
2704
2705 if (current_attrs == attrs)
2706 return ___FIX(___NO_ERR)(((long)(0))<<2);
2707
2708 turn_on = GET_STYLE(attrs)(((attrs)>>8)&3);
2709
2710 if ((GET_STYLE(current_attrs)(((current_attrs)>>8)&3) & ~turn_on) != 0 ||
2711 (GET_FOREGROUND_COLOR(attrs)((attrs)&15) >= DEFAULT_TEXT_COLOR8 &&
2712 GET_FOREGROUND_COLOR(current_attrs)((current_attrs)&15) < DEFAULT_TEXT_COLOR8) ||
2713 (GET_BACKGROUND_COLOR(attrs)(((attrs)>>4)&15) >= DEFAULT_TEXT_COLOR8 &&
2714 GET_BACKGROUND_COLOR(current_attrs)(((current_attrs)>>4)&15) < DEFAULT_TEXT_COLOR8))
2715 {
2716 if ((e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_SGR09, 1))
2717 != ___FIX(___NO_ERR)(((long)(0))<<2))
2718 return e;
2719 current_attrs = MAKE_TEXT_ATTRS(0,DEFAULT_TEXT_COLOR,DEFAULT_TEXT_COLOR)(((0)<<8)+(8)+((8)<<4));
2720 }
2721 else
2722 turn_on = (~GET_STYLE(current_attrs)(((current_attrs)>>8)&3) & turn_on);
2723
2724 if (turn_on & TEXT_STYLE_BOLD1)
2725 if ((e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_BOLD10, 1))
2726 != ___FIX(___NO_ERR)(((long)(0))<<2))
2727 return e;
2728
2729 if (turn_on & TEXT_STYLE_UNDERLINE2)
2730 if ((e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_SMUL11, 1))
2731 != ___FIX(___NO_ERR)(((long)(0))<<2))
2732 return e;
2733
2734 if (turn_on & TEXT_STYLE_REVERSE4)
2735 if ((e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_REV12, 1))
2736 != ___FIX(___NO_ERR)(((long)(0))<<2))
2737 return e;
2738
2739 if (GET_FOREGROUND_COLOR(attrs)((attrs)&15) < DEFAULT_TEXT_COLOR8 &&
2740 GET_FOREGROUND_COLOR(attrs)((attrs)&15) != GET_FOREGROUND_COLOR(current_attrs)((current_attrs)&15))
2741 if ((e = lineeditor_output_cap1
2742 (d,
2743 LINEEDITOR_CAP_SETAF13,
2744 GET_FOREGROUND_COLOR(attrs)((attrs)&15),
2745 1))
2746 != ___FIX(___NO_ERR)(((long)(0))<<2))
2747 return e;
2748
2749 if (GET_BACKGROUND_COLOR(attrs)(((attrs)>>4)&15) < DEFAULT_TEXT_COLOR8 &&
2750 GET_BACKGROUND_COLOR(attrs)(((attrs)>>4)&15) != GET_BACKGROUND_COLOR(current_attrs)(((current_attrs)>>4)&15))
2751 if ((e = lineeditor_output_cap1
2752 (d,
2753 LINEEDITOR_CAP_SETAB14,
2754 GET_BACKGROUND_COLOR(attrs)(((attrs)>>4)&15),
2755 1))
2756 != ___FIX(___NO_ERR)(((long)(0))<<2))
2757 return e;
2758
2759 return ___FIX(___NO_ERR)(((long)(0))<<2);
2760}
2761
2762
2763___HIDDENstatic ___SCMOBJlong lineeditor_output_terminal_plain_chars
2764 ___P((___device_tty *self,(___device_tty *self, unsigned int *buf, int len)
2765 ___C *buf,(___device_tty *self, unsigned int *buf, int len)
2766 int len),(___device_tty *self, unsigned int *buf, int len)
2767 (self,(___device_tty *self, unsigned int *buf, int len)
2768 buf,(___device_tty *self, unsigned int *buf, int len)
2769 len)(___device_tty *self, unsigned int *buf, int len)
2770___device_tty *self;(___device_tty *self, unsigned int *buf, int len)
2771___C *buf;(___device_tty *self, unsigned int *buf, int len)
2772int len;)(___device_tty *self, unsigned int *buf, int len)
2773{
2774 /*
2775 * This routine processes a string of plain characters (with no
2776 * control characters) that the emulated terminal received. It also
2777 * tracks the movement of the emulated terminal's cursor.
2778 */
2779
2780 ___device_tty *d = self;
2781 int col = d->terminal_col + d->terminal_delayed_wrap + len;
2782
2783 if (col >= d->terminal_nb_cols)
2784 {
2785 if (d->has_auto_right_margin)
2786 {
2787 int row = d->terminal_row + col / d->terminal_nb_cols;
2788
2789 col = col % d->terminal_nb_cols;
2790
2791 if (col == 0 && d->has_eat_newline_glitch)
2792 {
2793 col = d->terminal_nb_cols - 1;
2794 row--;
2795 d->terminal_delayed_wrap = 1; /* delay wrap */
2796 }
2797 else
2798 d->terminal_delayed_wrap = 0;
2799
2800 if (row >= d->terminal_nb_rows)
2801 {
2802 d->current.line_start -= d->terminal_nb_cols *
2803 (row - d->terminal_nb_rows + 1);
2804 row = d->terminal_nb_rows - 1;
2805 }
2806
2807 d->terminal_row = row;
2808 }
2809 else
2810 col = d->terminal_nb_cols - 1;
2811 }
2812 else
2813 d->terminal_delayed_wrap = 0;
2814
2815 d->terminal_col = col;
2816
2817 d->terminal_cursor = d->terminal_row * d->terminal_nb_cols + col;
2818
2819 return lineeditor_output (d, buf, len);
2820}
2821
2822
2823#ifdef USE_WIN32
2824
2825___HIDDENstatic ___SCMOBJlong lineeditor_output_terminal_op_move_abs
2826 ___P((___device_tty *self,(___device_tty *self, int dest_col, int dest_row)
2827 int dest_col,(___device_tty *self, int dest_col, int dest_row)
2828 int dest_row),(___device_tty *self, int dest_col, int dest_row)
2829 ())(___device_tty *self, int dest_col, int dest_row);
2830
2831#endif
2832
2833
2834___HIDDENstatic ___SCMOBJlong lineeditor_output_terminal_op_move_col
2835 ___P((___device_tty *self,(___device_tty *self, int dist)
2836 int dist),(___device_tty *self, int dist)
2837 (self,(___device_tty *self, int dist)
2838 dist)(___device_tty *self, int dist)
2839___device_tty *self;(___device_tty *self, int dist)
2840int dist;)(___device_tty *self, int dist)
2841{
2842 /*
2843 * This routine performs a relative cursor positioning operation
2844 * that changes the column of the cursor. It also tracks the
2845 * movement of the emulated terminal's cursor.
2846 */
2847
2848 ___device_tty *d = self;
2849 int col = d->terminal_col;
2850 int dest_col = col + dist;
2851
2852 if (dest_col < 0)
2853 dest_col = 0;
2854 else if (dest_col >= d->terminal_nb_cols)
2855 dest_col = d->terminal_nb_cols - 1;
2856
2857#ifdef USE_WIN32
2858
2859 return lineeditor_output_terminal_op_move_abs
2860 (d,
2861 dest_col,
2862 d->terminal_row);
2863
2864#else
2865
2866 dist = dest_col - col;
2867
2868 if (dist != 0)
2869 {
2870 d->terminal_col = dest_col;
2871 d->terminal_cursor = d->terminal_row * d->terminal_nb_cols + dest_col;
2872 d->terminal_delayed_wrap = 0;
2873
2874 if (dist > 0)
2875 return lineeditor_output_cap1 (d, LINEEDITOR_CAP_CUF6, dist, 1);
2876 else
2877 return lineeditor_output_cap1 (d, LINEEDITOR_CAP_CUB7, -dist, 1);
2878 }
2879
2880 return ___FIX(___NO_ERR)(((long)(0))<<2);
2881
2882#endif
2883}
2884
2885
2886___HIDDENstatic ___SCMOBJlong lineeditor_output_terminal_op_move_row
2887 ___P((___device_tty *self,(___device_tty *self, int dist)
2888 int dist),(___device_tty *self, int dist)
2889 (self,(___device_tty *self, int dist)
2890 dist)(___device_tty *self, int dist)
2891___device_tty *self;(___device_tty *self, int dist)
2892int dist;)(___device_tty *self, int dist)
2893{
2894 /*
2895 * This routine performs a relative cursor positioning operation
2896 * that changes the row of the cursor. It also tracks the movement
2897 * of the emulated terminal's cursor.
2898 */
2899
2900 ___device_tty *d = self;
2901 int row = d->terminal_row;
2902 int dest_row = row + dist;
2903
2904 if (dest_row < 0)
2905 dest_row = 0;
2906 else if (dest_row >= d->terminal_nb_rows)
2907 dest_row = d->terminal_nb_rows - 1;
2908
2909#ifdef USE_WIN32
2910
2911 return lineeditor_output_terminal_op_move_abs
2912 (d,
2913 d->terminal_col,
2914 dest_row);
2915
2916#else
2917
2918 dist = dest_row - row;
2919
2920 if (dist != 0)
2921 {
2922 d->terminal_row = dest_row;
2923 d->terminal_cursor = dest_row * d->terminal_nb_cols + d->terminal_col;
2924 d->terminal_delayed_wrap = 0;
2925
2926 if (dist > 0)
2927 {
2928 if ((dist == 1 || lineeditor_cap (d, LINEEDITOR_CAP_CUD5) == NULL((void*)0)) &&
2929 lineeditor_cap (d, LINEEDITOR_CAP_CUD13) != NULL((void*)0))
2930 return lineeditor_output_cap0 (d, LINEEDITOR_CAP_CUD13, dist);
2931 else
2932 return lineeditor_output_cap1 (d, LINEEDITOR_CAP_CUD5, dist, 1);
2933 }
2934 else
2935 {
2936 if ((dist == -1 || lineeditor_cap (d, LINEEDITOR_CAP_CUU4) == NULL((void*)0)) &&
2937 lineeditor_cap (d, LINEEDITOR_CAP_CUU12) != NULL((void*)0))
2938 return lineeditor_output_cap0 (d, LINEEDITOR_CAP_CUU12, -dist);
2939 else
2940 return lineeditor_output_cap1 (d, LINEEDITOR_CAP_CUU4, -dist, 1);
2941 }
2942 }
2943
2944 return ___FIX(___NO_ERR)(((long)(0))<<2);
2945
2946#endif
2947}
2948
2949
2950___HIDDENstatic ___SCMOBJlong lineeditor_output_terminal_op_move_abs
2951 ___P((___device_tty *self,(___device_tty *self, int dest_col, int dest_row)
2952 int dest_col,(___device_tty *self, int dest_col, int dest_row)
2953 int dest_row),(___device_tty *self, int dest_col, int dest_row)
2954 (self,(___device_tty *self, int dest_col, int dest_row)
2955 dest_col,(___device_tty *self, int dest_col, int dest_row)
2956 dest_row)(___device_tty *self, int dest_col, int dest_row)
2957___device_tty *self;(___device_tty *self, int dest_col, int dest_row)
2958int dest_col;(___device_tty *self, int dest_col, int dest_row)
2959int dest_row;)(___device_tty *self, int dest_col, int dest_row)
2960{
2961 /*
2962 * This routine performs an absolute cursor positioning operation.
2963 * It also tracks the movement of the emulated terminal's cursor.
2964 */
2965
2966 ___device_tty *d = self;
2967 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
2968
2969#ifdef USE_WIN32
2970
2971 {
2972 CONSOLE_SCREEN_BUFFER_INFO info;
2973
2974 if (!GetConsoleScreenBufferInfo (d->hout, &info))
2975 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
2976 else
2977 {
2978 COORD pos = info.dwCursorPosition;
2979
2980 pos.X += dest_col - d->terminal_col;
2981 pos.Y += dest_row - d->terminal_row;
2982
2983 d->terminal_col = dest_col;
2984 d->terminal_row = dest_row;
2985 d->terminal_cursor = dest_row * d->terminal_nb_cols + dest_col;
2986 d->terminal_delayed_wrap = 0;
2987
2988 if (!SetConsoleCursorPosition (d->hout, pos))
2989 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
2990 }
2991 }
2992
2993#else
2994
2995 if (dest_col == 0 &&
2996 dest_row == 0 &&
2997 lineeditor_cap (d, LINEEDITOR_CAP_HOME0) != NULL((void*)0))
2998 {
2999 d->terminal_col = 0;
3000 d->terminal_row = 0;
3001 d->terminal_cursor = 0;
3002 d->terminal_delayed_wrap = 0;
3003
3004 return lineeditor_output_cap0 (d, LINEEDITOR_CAP_HOME0, 1);
3005 }
3006
3007 if (lineeditor_cap (d, LINEEDITOR_CAP_CUP8) != NULL((void*)0))
3008 {
3009 d->terminal_col = dest_col;
3010 d->terminal_row = dest_row;
3011 d->terminal_cursor = dest_row * d->terminal_nb_cols + dest_col;
3012 d->terminal_delayed_wrap = 0;
3013
3014 return lineeditor_output_cap2
3015 (d,
3016 LINEEDITOR_CAP_CUP8,
3017 dest_row,
3018 dest_col,
3019 1);
3020 }
3021
3022 if ((e = lineeditor_output_terminal_op_move_col
3023 (d,
3024 dest_col - d->terminal_col)) == ___FIX(___NO_ERR)(((long)(0))<<2))
3025 e = lineeditor_output_terminal_op_move_row
3026 (d,
3027 dest_row - d->terminal_row);
3028
3029#endif
3030
3031 return e;
3032}
3033
3034
3035#define TERMINAL_MOVE_ABS1 1
3036#define TERMINAL_MOVE_ROW0 0
3037#define TERMINAL_MOVE_COL-1 -1
3038#define TERMINAL_ERASE_DISP-2 -2
3039#define TERMINAL_ERASE_LINE-3 -3
3040#define TERMINAL_SET_ATTRS-4 -4
3041#define TERMINAL_NOOP-5 -5
3042#define TERMINAL_CTRL-6 -6
3043#define TERMINAL_WINDOW_OP-7 -7
3044
3045___HIDDENstatic ___SCMOBJlong lineeditor_output_terminal_op
3046 ___P((___device_tty *self,(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3047 int op,(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3048 int arg,(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3049 ___U8 *text_arg),(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3050 (self,(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3051 op,(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3052 arg,(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3053 text_arg)(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3054___device_tty *self;(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3055int op;(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3056int arg;(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3057___U8 *text_arg;)(___device_tty *self, int op, int arg, unsigned char *text_arg
)
3058{
3059 /*
3060 * This routine performs an operation of the emulated terminal and
3061 * tracks the movement of the cursor.
3062 */
3063
3064 ___device_tty *d = self;
3065 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
3066
3067 switch (op)
3068 {
3069 case TERMINAL_NOOP-5:
3070 break;
3071
3072 case TERMINAL_CTRL-6 - ___UNICODE_BELL7:
3073 {
3074#ifdef USE_POSIX
3075
3076 {
3077 ___Cunsigned int c = ___UNICODE_BELL7;
3078 e = lineeditor_output (d, &c, 1);
3079 }
3080
3081#endif
3082
3083#ifdef USE_WIN32
3084
3085 if (!MessageBeep (MB_OK))
3086 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3087
3088#endif
3089
3090 break;
3091 }
3092
3093 case TERMINAL_CTRL-6 - ___UNICODE_BACKSPACE8:
3094 {
3095 if (d->terminal_col > 0)
3096 d->terminal_col--;
3097 else if (d->terminal_row > 0 && d->has_auto_left_margin)
3098 {
3099 d->terminal_row--;
3100 d->terminal_col = d->terminal_nb_cols - 1;
3101 }
3102
3103 d->terminal_cursor = d->terminal_row * d->terminal_nb_cols +
3104 d->terminal_col;
3105
3106 d->terminal_delayed_wrap = 0;
3107
3108#ifdef USE_POSIX
3109
3110 {
3111 ___Cunsigned int c = ___UNICODE_BACKSPACE8;
3112 e = lineeditor_output (d, &c, 1);
3113 }
3114
3115#endif
3116
3117#ifdef USE_WIN32
3118
3119 {
3120 CONSOLE_SCREEN_BUFFER_INFO info;
3121
3122 if (!GetConsoleScreenBufferInfo (d->hout, &info))
3123 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3124 else
3125 {
3126 COORD pos = info.dwCursorPosition;
3127
3128 if (pos.X > 0)
3129 pos.X--;
3130 else if (pos.Y > info.srWindow.Top && d->has_auto_left_margin)
3131 {
3132 pos.X = info.dwSize.X - 1;
3133 pos.Y--;
3134 }
3135
3136 if (!SetConsoleCursorPosition (d->hout, pos))
3137 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3138 }
3139 }
3140
3141#endif
3142
3143 break;
3144 }
3145
3146 case TERMINAL_CTRL-6 - ___UNICODE_TAB9:
3147 {
3148 e = lineeditor_output_terminal_op_move_col
3149 (d,
3150 8 - d->terminal_col % 8);
3151 break;
3152 }
3153
3154 case TERMINAL_CTRL-6 - ___UNICODE_LINEFEED10:
3155 {
3156 if (d->terminal_row < d->terminal_nb_rows-1)
3157 d->terminal_row++;
3158 else
3159 d->current.line_start -= d->terminal_nb_cols;
3160
3161 if (d->linefeed_moves_to_left_margin || !d->output_raw)
3162 d->terminal_col = 0;
3163
3164 d->terminal_cursor = d->terminal_row * d->terminal_nb_cols +
3165 d->terminal_col;
3166
3167 d->terminal_delayed_wrap = 0;
3168
3169#ifdef USE_POSIX
3170
3171 {
3172 ___Cunsigned int c = ___UNICODE_LINEFEED10;
3173 e = lineeditor_output (d, &c, 1);
3174 }
3175
3176#endif
3177
3178#ifdef USE_WIN32
3179
3180 {
3181 CONSOLE_SCREEN_BUFFER_INFO info;
3182
3183 if (!GetConsoleScreenBufferInfo (d->hout, &info))
3184 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3185 else
3186 {
3187 COORD pos = info.dwCursorPosition;
3188
3189 if (pos.Y >= info.dwSize.Y - 1)
3190 {
3191 SMALL_RECT rect;
3192 CHAR_INFO fill;
3193 COORD dest;
3194
3195 rect.Top = 0;
3196 rect.Bottom = info.dwSize.Y - 1;
3197 rect.Left = 0;
3198 rect.Right = info.dwSize.X - 1;
3199
3200 dest.X = 0;
3201 dest.Y = -1;
3202
3203 fill.Attributes = info.wAttributes;
3204 TTY_CHAR_SELECT(fill.Char.AsciiChar = ' ',fill.Char.AsciiChar = ' '
3205 fill.Char.UnicodeChar = ' ')fill.Char.AsciiChar = ' ';
3206
3207 if (!ScrollConsoleScreenBuffer (d->hout,
3208 &rect,
3209 &rect,
3210 dest,
3211 &fill))
3212 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3213
3214 pos.Y = info.dwSize.Y - 1;
3215 }
3216 else
3217 pos.Y++;
3218
3219 if (e == ___FIX(___NO_ERR)(((long)(0))<<2))
3220 {
3221 if (d->linefeed_moves_to_left_margin || !d->output_raw)
3222 pos.X = 0;
3223
3224 if (!SetConsoleCursorPosition (d->hout, pos))
3225 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3226 }
3227 }
3228 }
3229
3230#endif
3231
3232 break;
3233 }
3234
3235 case TERMINAL_CTRL-6 - ___UNICODE_RETURN13:
3236 {
3237 d->terminal_col = 0;
3238 d->terminal_cursor = d->terminal_row * d->terminal_nb_cols;
3239 d->terminal_delayed_wrap = 0;
3240
3241#ifdef USE_POSIX
3242
3243 {
3244 ___Cunsigned int c = ___UNICODE_RETURN13;
3245 e = lineeditor_output (d, &c, 1);
3246 }
3247
3248#endif
3249
3250#ifdef USE_WIN32
3251
3252 {
3253 CONSOLE_SCREEN_BUFFER_INFO info;
3254
3255 if (!GetConsoleScreenBufferInfo (d->hout, &info))
3256 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3257 else
3258 {
3259 COORD pos = info.dwCursorPosition;
3260
3261 pos.X = 0;
3262
3263 if (!SetConsoleCursorPosition (d->hout, pos))
3264 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3265 }
3266 }
3267
3268#endif
3269
3270 break;
3271 }
3272
3273 case TERMINAL_SET_ATTRS-4:
3274 {
3275#ifdef USE_POSIX
3276
3277 e = lineeditor_output_set_attrs (d, arg);
3278
3279#endif
3280
3281#ifdef USE_WIN32
3282
3283 {
3284 int style = GET_STYLE(arg)(((arg)>>8)&3);
3285 int fg = GET_FOREGROUND_COLOR(arg)((arg)&15);
3286 int bg = GET_BACKGROUND_COLOR(arg)(((arg)>>4)&15);
3287 WORD attr = 0;
3288
3289 if (fg == DEFAULT_TEXT_COLOR8)
3290 fg = NORMAL_FOREGROUND0;
3291
3292 if (bg == DEFAULT_TEXT_COLOR8)
3293 bg = NORMAL_BACKGROUND7;
3294
3295 if (style & TEXT_STYLE_BOLD1)
3296 attr |= FOREGROUND_INTENSITY;
3297
3298 if (style & TEXT_STYLE_UNDERLINE2)
3299 attr |= BACKGROUND_INTENSITY;
3300
3301 if (style & TEXT_STYLE_REVERSE4)
3302 {
3303 int temp = fg;
3304 fg = bg;
3305 bg = temp;
3306 }
3307
3308 if (fg & 4) attr |= FOREGROUND_BLUE;
3309 if (fg & 2) attr |= FOREGROUND_GREEN;
3310 if (fg & 1) attr |= FOREGROUND_RED;
3311 if (bg & 4) attr |= BACKGROUND_BLUE;
3312 if (bg & 2) attr |= BACKGROUND_GREEN;
3313 if (bg & 1) attr |= BACKGROUND_RED;
3314
3315 if (!SetConsoleTextAttribute (d->hout, attr))
3316 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3317 }
3318
3319#endif
3320
3321 break;
3322 }
3323
3324#ifdef USE_WIN32
3325
3326 case TERMINAL_ERASE_DISP-2:
3327 case TERMINAL_ERASE_LINE-3:
3328 {
3329 if (arg <= 2) /* argument valid? */
3330 {
3331 COORD pos;
3332 CONSOLE_SCREEN_BUFFER_INFO info;
3333 DWORD n;
3334 DWORD written;
3335
3336 if (!GetConsoleScreenBufferInfo (d->hout, &info))
3337 return err_code_from_GetLastError ()___err_code_from_GetLastError();
3338
3339 if (d->terminal_col == 0 &&
3340 d->terminal_row == 0)
3341 {
3342 pos.X = 0;
3343 pos.Y = 0;
3344
3345 if (!SetConsoleCursorPosition (d->hout, pos))
3346 return err_code_from_GetLastError ()___err_code_from_GetLastError();
3347 }
3348 else
3349 pos = info.dwCursorPosition;
3350
3351 if (arg == 0)
3352 n = info.dwSize.X - pos.X;
3353 else
3354 {
3355 if (arg == 1)
3356 n = pos.X;
3357 else
3358 n = info.dwSize.X;
3359 pos.X = 0;
3360 }
3361
3362 if (op == TERMINAL_ERASE_DISP-2)
3363 {
3364 if (arg == 0)
3365 n += info.dwSize.X * (info.dwSize.Y - pos.Y - 1);
3366 else
3367 {
3368 if (arg == 1)
3369 n += info.dwSize.X * pos.Y;
3370 else
3371 n = info.dwSize.X * info.dwSize.Y;
3372 pos.Y = 0;
3373 }
3374 }
3375
3376 if (!FillConsoleOutputAttribute
3377 (d->hout,
3378 info.wAttributes,
3379 n,
3380 pos,
3381 &written) ||
3382 !FillConsoleOutputCharacter
3383 (d->hout,
3384 ' ',
3385 n,
3386 pos,
3387 &written))
3388 e = err_code_from_GetLastError ()___err_code_from_GetLastError();
3389 }
3390
3391 break;
3392 }
3393
3394 case TERMINAL_WINDOW_OP-7:
3395 {
3396 int window_op = arg & ((1<<8)-1);
3397 int arg1 = (arg >> 8) & ((1<<12)-1);
3398 int arg2 = (arg >> 20) & ((1<<12)-1);
3399 HWND cons_wind = GetConsoleWindow ();
3400
3401 if (cons_wind != NULL((void*)0))
3402 {
3403 if (text_arg != NULL((void*)0))
3404 {
3405 SetWindowTextA (cons_wind,
3406 ___CAST(LPCSTR,text_arg)((LPCSTR)(text_arg))); /* ignore error */
3407 }
3408 else
3409 {
3410 switch (window_op)
3411 {
3412 case 1: /* De-iconify window */
3413 case 2: /* Iconify window */
3414 ShowWindow (cons_wind,
3415 (window_op == 1) ? SW_RESTORE : SW_MINIMIZE);
3416 break;
3417
3418 case 3: /* Move window to [arg1, arg2] */
3419 SetWindowPos (cons_wind,
3420 cons_wind,
3421 arg1,
3422 arg2,
3423 0,
3424 0,
3425 SWP_NOZORDER | SWP_NOSIZE);
3426 break;
3427
3428 case 4: /* Resize window to height=arg1 and width=arg2 in pixels */
3429 SetWindowPos (cons_wind,
3430 cons_wind,
3431 0,
3432 0,
3433 arg2,
3434 arg1,
3435 SWP_NOZORDER | SWP_NOMOVE);
3436 break;
3437
3438 case 5: /* Raise the window to the front of the stacking order */
3439 case 6: /* Lower the window to the bottom of the stacking order */
3440 SetWindowPos (cons_wind,
3441 (window_op == 5) ? HWND_TOP : HWND_BOTTOM,
3442 0,
3443 0,
3444 0,
3445 0,
3446 SWP_NOSIZE | SWP_NOMOVE);
3447 break;
3448
3449 case 7: /* Refresh the window */
3450 break;
3451
3452 case 8: /* Resize window to height=arg1 and width=arg2 in chars */
3453 break;
3454
3455 case 9: /* Maximize or un-maximize window (arg1=0 or arg1=1) */
3456 ShowWindow (cons_wind,
3457 (arg1 == 0) ? SW_MAXIMIZE : SW_RESTORE);
3458 break;
3459 }
3460 }
3461 }
3462
3463 break;
3464 }
3465
3466#else
3467
3468 case TERMINAL_ERASE_DISP-2:
3469 {
3470 switch (arg)
3471 {
3472 case 1: /* erase from beginning of screen */
3473 break;
3474 case 2: /* erase all screen */
3475 if (d->terminal_col != 0 || d->terminal_row != 0)
3476 break;
3477 case 0: /* erase to end of screen */
3478 e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_ED15, 1);
3479 break;
3480 }
3481 break;
3482 }
3483
3484 case TERMINAL_ERASE_LINE-3:
3485 {
3486 switch (arg)
3487 {
3488 case 1: /* erase from beginning of line */
3489 e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_EL117, 1);
3490 break;
3491 case 2: /* erase all line */
3492 if (d->terminal_col != 0)
3493 break;
3494 case 0: /* erase to end of line */
3495 e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_EL16, 1);
3496 break;
3497 }
3498 break;
3499 }
3500
3501 case TERMINAL_WINDOW_OP-7:
3502 {
3503 int window_op = arg & ((1<<8)-1);
3504 int arg1 = (arg >> 8) & ((1<<12)-1);
3505 int arg2 = (arg >> 20) & ((1<<12)-1);
3506
3507 if (text_arg != NULL((void*)0))
3508 {
3509 ___Cunsigned int c;
3510
3511 e = lineeditor_output_cap1
3512 (d,
3513 LINEEDITOR_CAP_WINDOW_OP321,
3514 window_op,
3515 1);
3516
3517 while (e == ___FIX(___NO_ERR)(((long)(0))<<2) &&
3518 *text_arg != ___UNICODE_NUL0)
3519 {
3520 c = *text_arg++;
3521 e = lineeditor_output (d, &c, 1);
3522 }
3523
3524 if (e == ___FIX(___NO_ERR)(((long)(0))<<2))
3525 {
3526 c = ___UNICODE_BELL7;
3527 e = lineeditor_output (d, &c, 1);
3528 }
3529 }
3530 else
3531 {
3532 switch (window_op)
3533 {
3534 case 1: /* De-iconify window */
3535 case 2: /* Iconify window */
3536 case 5: /* Raise the window to the front of the stacking order */
3537 case 6: /* Lower the window to the bottom of the stacking order */
3538 case 7: /* Refresh the window */
3539 e = lineeditor_output_cap1
3540 (d,
3541 LINEEDITOR_CAP_WINDOW_OP018,
3542 window_op,
3543 1);
3544 break;
3545
3546 case 9: /* Maximize or un-maximize window (arg1=0 or arg1=1) */
3547 e = lineeditor_output_cap2
3548 (d,
3549 LINEEDITOR_CAP_WINDOW_OP119,
3550 window_op,
3551 arg1,
3552 1);
3553 break;
3554
3555 case 3: /* Move window to [arg1, arg2] */
3556 case 4: /* Resize window to height=arg1 and width=arg2 in pixels */
3557 case 8: /* Resize window to height=arg1 and width=arg2 in chars */
3558 e = lineeditor_output_cap3
3559 (d,
3560 LINEEDITOR_CAP_WINDOW_OP220,
3561 window_op,
3562 arg1,
3563 arg2,
3564 1);
3565 break;
3566 }
3567 }
3568
3569 break;
3570 }
3571
3572#endif
3573
3574 case TERMINAL_MOVE_COL-1:
3575 {
3576 e = lineeditor_output_terminal_op_move_col (d, arg);
3577 break;
3578 }
3579
3580 case TERMINAL_MOVE_ROW0:
3581 {
3582 e = lineeditor_output_terminal_op_move_row (d, arg);
3583 break;
3584 }
3585
3586 default:
3587 {
3588 if (op >= TERMINAL_MOVE_ABS1)
3589 e = lineeditor_output_terminal_op_move_abs
3590 (d,
3591 arg,
3592 op - TERMINAL_MOVE_ABS1);
3593 break;
3594 }
3595 }
3596
3597 return e;
3598}
3599
3600
3601___HIDDENstatic ___SCMOBJlong lineeditor_output_terminal_emulate
3602 ___P((___device_tty *self,(___device_tty *self, unsigned int *buf, int len)
3603 ___C *buf,(___device_tty *self, unsigned int *buf, int len)
3604 int len),(___device_tty *self, unsigned int *buf, int len)
3605 (self,(___device_tty *self, unsigned int *buf, int len)
3606 buf,(___device_tty *self, unsigned int *buf, int len)
3607 len)(___device_tty *self, unsigned int *buf, int len)
3608___device_tty *self;(___device_tty *self, unsigned int *buf, int len)
3609___C *buf;(___device_tty *self, unsigned int *buf, int len)
3610int len;)(___device_tty *self, unsigned int *buf, int len)
3611{
3612 /*
3613 * This routine processes a string of characters (possibly
3614 * containing control characters and escape sequences) that the
3615 * emulated terminal received. It also tracks the movement of the
3616 * emulated terminal's cursor.
3617 */
3618
3619 ___device_tty *d = self;
3620 ___SCMOBJlong e;
3621 int pn;
3622 ___Cunsigned int c;
3623
3624#ifdef ___DEBUG_TTY
3625
3626 {
3627 int i;
3628
3629 ___printf ("lineeditor_output_terminal_emulate len: %d ", len);
3630
3631 ___printf ("\"");
3632
3633 for (i=0; i<len; i++)
3634 if (buf[i] < 32 || buf[i] >= 127)
3635 ___printf ("\\x%02x", buf[i]);
3636 else
3637 ___printf ("%c", buf[i]);
3638
3639 ___printf ("\"\n");
3640 }
3641
3642#endif
3643
3644 pn = d->terminal_param_num;
3645
3646 while (len > 0)
3647 {
3648 ___Cunsigned int c = *buf++;
3649
3650 len--;
3651
3652 if (!d->editing_line)
3653 {
3654 /* accumulate prompt */
3655
3656 int i = d->prompt_length;
3657 if (i < ___CAST(int,___NBELEMS(d->prompt))((int)((sizeof (d->prompt) / sizeof ((d->prompt)[0])))))
3658 {
3659 d->prompt[i] = c;
3660 d->prompt_length = i+1;
3661 }
3662 }
3663
3664 switch (pn)
3665 {
3666 case -2:
3667 {
3668 /* outside of an escape sequence */
3669
3670 if (c >= ___UNICODE_SPACE32)
3671 {
3672 int n = 0;
3673
3674 while (n < len && *buf >= ___UNICODE_SPACE32)
3675 {
3676 n++;
3677 buf++;
3678 }
3679
3680 if (!d->editing_line)
3681 {
3682 /* accumulate prompt */
3683
3684 ___Cunsigned int *p = buf - n;
3685 int i = d->prompt_length;
3686 while (i < ___CAST(int,___NBELEMS(d->prompt))((int)((sizeof (d->prompt) / sizeof ((d->prompt)[0])))) && p < buf)
3687 d->prompt[i++] = *p++;
3688 d->prompt_length = i;
3689 }
3690
3691 len -= n;
3692 n++;
3693
3694 if ((e = lineeditor_output_terminal_plain_chars (d, buf-n, n))
3695 != ___FIX(___NO_ERR)(((long)(0))<<2))
3696 {
3697 d->terminal_param_num = pn;
3698 return e;
3699 }
3700 }
3701 else if (c != ___UNICODE_ESCAPE27) /* non ESC control character? */
3702 {
3703 if (c == ___UNICODE_LINEFEED10)
3704 {
3705 if (!d->editing_line)
3706 d->prompt_length = 0; /* reset prompt */
3707
3708 /******** TODO: should check if cr-lf, etc is needed */
3709
3710 if ((e = lineeditor_output_terminal_op
3711 (d,
3712 TERMINAL_CTRL-6 - c,
3713 0,
3714 NULL((void*)0)))
3715 != ___FIX(___NO_ERR)(((long)(0))<<2))
3716 {
3717 d->terminal_param_num = pn;
3718 return e;
3719 }
3720 }
3721 else
3722 {
3723 if ((e = lineeditor_output_terminal_op
3724 (d,
3725 TERMINAL_CTRL-6 - c,
3726 0,
3727 NULL((void*)0)))
3728 != ___FIX(___NO_ERR)(((long)(0))<<2))
3729 {
3730 d->terminal_param_num = pn;
3731 return e;
3732 }
3733 }
3734 }
3735 else
3736 pn = -1; /* start of an escape sequence */
3737
3738 break;
3739 }
3740
3741 case -1:
3742 {
3743 /* after an ESC */
3744
3745 if (c == '[')
3746 {
3747 d->terminal_op_type = 0;
3748 pn = 0;
3749 d->terminal_param[0] = 0;
3750 }
3751 else if (c == ']')
3752 {
3753 d->terminal_op_type = 1;
3754 pn = 0;
3755 d->terminal_param[0] = 0;
3756 }
3757 else
3758 pn = -2;
3759
3760 break;
3761 }
3762
3763 default:
3764 {
3765 /* accumulating parameters after an ESC '[' */
3766
3767 if (d->terminal_op_type == 1 && pn == 1)
3768 {
3769 if (c == ___UNICODE_BELL7)
3770 {
3771 pn = -2;
3772
3773 if ((e = lineeditor_output_terminal_op
3774 (d,
3775 TERMINAL_WINDOW_OP-7,
3776 d->terminal_param[0],
3777 d->terminal_param_text))
3778 != ___FIX(___NO_ERR)(((long)(0))<<2))
3779 {
3780 d->terminal_param_num = pn;
3781 return e;
3782 }
3783 }
3784 else
3785 {
3786 if (d->terminal_param[1] <
3787 ___CAST(int,___NBELEMS(d->terminal_param_text))((int)((sizeof (d->terminal_param_text) / sizeof ((d->terminal_param_text
)[0]))))
-1)
3788 d->terminal_param_text[d->terminal_param[1]++] = c;
3789 }
3790 }
3791 else if (c >= '0' && c <= '9')
3792 {
3793 int x = c - '0';
3794 int p = d->terminal_param[pn];
3795 if (p < 1000)
3796 d->terminal_param[pn] = p*10 + x;
3797 }
3798 else if (c == ';')
3799 {
3800 if (pn < ___CAST(int,___NBELEMS(d->terminal_param))((int)((sizeof (d->terminal_param) / sizeof ((d->terminal_param
)[0]))))
-1)
3801 pn++;
3802 d->terminal_param[pn] = 0;
3803 }
3804 else
3805 {
3806 int op = TERMINAL_NOOP-5;
3807 int arg = 0;
3808
3809 if (c == 'A')
3810 {
3811 op = TERMINAL_MOVE_ROW0;
3812 arg = -d->terminal_param[0];
3813 if (arg >= 0) arg = -1;
3814 }
3815 else if (c == 'B')
3816 {
3817 op = TERMINAL_MOVE_ROW0;
3818 arg = d->terminal_param[0];
3819 if (arg <= 0) arg = 1;
3820 }
3821 else if (c == 'C')
3822 {
3823 op = TERMINAL_MOVE_COL-1;
3824 arg = d->terminal_param[0];
3825 if (arg <= 0) arg = 1;
3826 }
3827 else if (c == 'D')
3828 {
3829 op = TERMINAL_MOVE_COL-1;
3830 arg = -d->terminal_param[0];
3831 if (arg >= 0) arg = -1;
3832 }
3833 else if (c == 'H' || c == 'f')
3834 {
3835 op = d->terminal_param[0];
3836 if (op <= 0) op = 1;
3837 op += TERMINAL_MOVE_ABS1 - 1;
3838 arg = d->terminal_param[1];
3839 if (pn < 1 || arg <= 0) arg = 1;
3840 arg--;
3841 }
3842 else if (c == 'J')
3843 {
3844 op = TERMINAL_ERASE_DISP-2;
3845 arg = d->terminal_param[0];
3846 if (arg <= 0) arg = 0;
3847 }
3848 else if (c == 'K')
3849 {
3850 op = TERMINAL_ERASE_LINE-3;
3851 arg = d->terminal_param[0];
3852 if (arg <= 0) arg = 0;
3853 }
3854 else if (c == 'm')
3855 {
3856 int j;
3857 int style;
3858 int fg;
3859 int bg;
3860
3861 op = TERMINAL_SET_ATTRS-4;
3862 arg = d->terminal_attrs;
3863 style = GET_STYLE(arg)(((arg)>>8)&3);
3864 fg = GET_FOREGROUND_COLOR(arg)((arg)&15);
3865 bg = GET_BACKGROUND_COLOR(arg)(((arg)>>4)&15);
3866
3867 for (j=0; j<=pn; j++)
3868 {
3869 int x = d->terminal_param[j];
3870 if (x <= 0)
3871 {
3872 style = TEXT_STYLE_NORMAL0;
3873 fg = DEFAULT_TEXT_COLOR8;
3874 bg = DEFAULT_TEXT_COLOR8;
3875 }
3876 else if (x == 1)
3877 style |= TEXT_STYLE_BOLD1;
3878 else if (x == 4)
3879 style |= TEXT_STYLE_UNDERLINE2;
3880 else if (x == 7)
3881 style |= TEXT_STYLE_REVERSE4;
3882 else if (x >= 30 && x <= 37)
3883 fg = x-30;
3884 else if (x >= 40 && x <= 47)
3885 bg = x-40;
3886 }
3887 arg = MAKE_TEXT_ATTRS(style,fg,bg)(((style)<<8)+(fg)+((bg)<<4));
3888 }
3889 else if (c == 't')
3890 {
3891 switch (d->terminal_param[0])
3892 {
3893 case 3:
3894 case 4:
3895 case 8:
3896 if (pn == 2 &&
3897 d->terminal_param[1] <= 4095 &&
3898 d->terminal_param[2] <= 4095)
3899 {
3900 arg = (d->terminal_param[2] << 20) +
3901 (d->terminal_param[1] << 8) +
3902 d->terminal_param[0];
3903 op = TERMINAL_WINDOW_OP-7;
3904 }
3905 break;
3906
3907 case 9:
3908 if (pn == 1 &&
3909 d->terminal_param[1] <= 4095)
3910 {
3911 arg = (d->terminal_param[1] << 8) +
3912 d->terminal_param[0];
3913 op = TERMINAL_WINDOW_OP-7;
3914 }
3915 break;
3916
3917 default:
3918 if (pn == 0 &&
3919 d->terminal_param[0] >= 1 &&
3920 d->terminal_param[0] <= 9)
3921 {
3922 arg = d->terminal_param[0];
3923 op = TERMINAL_WINDOW_OP-7;
3924 }
3925 break;
3926 }
3927 }
3928
3929 pn = -2;
3930
3931 if ((e = lineeditor_output_terminal_op (d, op, arg, NULL((void*)0)))
3932 != ___FIX(___NO_ERR)(((long)(0))<<2))
3933 {
3934 d->terminal_param_num = pn;
3935 return e;
3936 }
3937 }
3938
3939 break;
3940 }
3941 }
3942 }
3943
3944 d->terminal_param_num = pn;
3945
3946 return ___FIX(___NO_ERR)(((long)(0))<<2);
3947}
3948
3949
3950___HIDDENstatic ___SCMOBJlong lineeditor_output_chars
3951 ___P((___device_tty *self,(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3952 ___C *buf,(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3953 ___stream_index len,(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3954 tty_text_attrs attrs),(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3955 (self,(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3956 buf,(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3957 len,(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3958 attrs)(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3959___device_tty *self;(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3960___C *buf;(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3961___stream_index len;(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3962tty_text_attrs attrs;)(___device_tty *self, unsigned int *buf, ___stream_index len,
tty_text_attrs attrs)
3963{
3964 /*
3965 * This routine outputs "len" characters from the buffer "buf" using
3966 * the text attributes "attrs".
3967 */
3968
3969 ___device_tty *d = self;
3970 ___SCMOBJlong e;
3971
3972 if ((e = lineeditor_output_set_attrs (d, attrs))
3973 == ___FIX(___NO_ERR)(((long)(0))<<2))
3974 e = lineeditor_output (d, buf, len);
3975
3976 return e;
3977}
3978
3979
3980___HIDDENstatic ___SCMOBJlong lineeditor_output_char_repetition
3981 ___P((___device_tty *self,(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3982 ___C c,(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3983 int rep,(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3984 tty_text_attrs attrs),(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3985 (self,(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3986 c,(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3987 rep,(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3988 attrs)(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3989___device_tty *self;(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3990___C c;(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3991int rep;(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3992tty_text_attrs attrs;)(___device_tty *self, unsigned int c, int rep, tty_text_attrs
attrs)
3993{
3994 /*
3995 * This routine outputs the character "c" a total of "rep" times
3996 * using the text attributes "attrs".
3997 */
3998
3999#define CHAR_BUFFER_SIZE(80*50) (80*50)
4000
4001 ___device_tty *d = self;
4002 ___SCMOBJlong e;
4003 ___Cunsigned int char_buffer[CHAR_BUFFER_SIZE(80*50)];
4004 int n;
4005
4006 n = rep;
4007 if (n > CHAR_BUFFER_SIZE(80*50))
4008 n = CHAR_BUFFER_SIZE(80*50);
4009
4010 while (n > 0)
4011 char_buffer[--n] = c;
4012
4013 while (rep > 0)
4014 {
4015 n = rep;
4016 if (n > CHAR_BUFFER_SIZE(80*50))
4017 n = CHAR_BUFFER_SIZE(80*50);
4018 if ((e = lineeditor_output_chars (d, char_buffer, n, attrs))
4019 != ___FIX(___NO_ERR)(((long)(0))<<2))
4020 return e;
4021 rep -= n;
4022 }
4023
4024 return ___FIX(___NO_ERR)(((long)(0))<<2);
4025}
4026
4027
4028___HIDDENstatic tty_text_attrs lineeditor_erase_attrs
4029 ___P((___device_tty *self),(___device_tty *self)
4030 (self)(___device_tty *self)
4031___device_tty *self;)(___device_tty *self)
4032{
4033 /*
4034 * This routine returns the text attributes that should be used to
4035 * erase portions of the screen.
4036 */
4037
4038 ___device_tty *d = self;
4039 tty_text_attrs output_attrs = d->output_attrs;
4040 int output_style = GET_STYLE(output_attrs)(((output_attrs)>>8)&3);
4041 int current_style = GET_STYLE(d->current.attrs)(((d->current.attrs)>>8)&3);
4042
4043 return MAKE_TEXT_ATTRS(output_style & TEXT_STYLE_REVERSE,(((output_style & 4)<<8)+(((output_attrs)&15))+
(((((output_attrs)>>4)&15))<<4))
4044 GET_FOREGROUND_COLOR(output_attrs),(((output_style & 4)<<8)+(((output_attrs)&15))+
(((((output_attrs)>>4)&15))<<4))
4045 GET_BACKGROUND_COLOR(output_attrs))(((output_style & 4)<<8)+(((output_attrs)&15))+
(((((output_attrs)>>4)&15))<<4))
;
4046}
4047
4048
4049___HIDDENstatic ___SCMOBJlong lineeditor_output_current_hist
4050 ___P((___device_tty *self,(___device_tty *self, int start, int len)
4051 int start,(___device_tty *self, int start, int len)
4052 int len),(___device_tty *self, int start, int len)
4053 (self,(___device_tty *self, int start, int len)
4054 start,(___device_tty *self, int start, int len)
4055 len)(___device_tty *self, int start, int len)
4056___device_tty *self;(___device_tty *self, int start, int len)
4057int start;(___device_tty *self, int start, int len)
4058int len;)(___device_tty *self, int start, int len)
4059{
4060 /*
4061 * This routine sends to the terminal "len" characters of the line
4062 * being edited starting at position "start". The line is logically
4063 * padded with spaces at both ends (so that a negative "start"
4064 * outputs spaces first and if "start+len" is beyond the end of the
4065 * line some spaces will be output at the end).
4066 */
4067
4068 ___device_tty *d = self;
4069 ___SCMOBJlong e;
4070 extensible_string *edited = &d->current.hist->edited;
4071 int spaces_at_head;
4072 int chars_from_line;
4073
4074 spaces_at_head = -start;
4075
4076 if (spaces_at_head < 0)
4077 spaces_at_head = 0;
4078 else
4079 {
4080 if (spaces_at_head > len)
4081 spaces_at_head = len;
4082 start += spaces_at_head;
4083 len -= spaces_at_head;
4084 }
4085
4086 chars_from_line = edited->length - start;
4087
4088 if (chars_from_line < 0)
4089 chars_from_line = 0;
4090 else
4091 {
4092 if (chars_from_line > len)
4093 chars_from_line = len;
4094 len -= chars_from_line;
4095 }
4096
4097 if (spaces_at_head > 0)
4098 if ((e = lineeditor_output_char_repetition
4099 (d,
4100 ___UNICODE_SPACE32,
4101 spaces_at_head,
4102 lineeditor_erase_attrs (d)))
4103 != ___FIX(___NO_ERR)(((long)(0))<<2))
4104 return e;
4105
4106 if (chars_from_line > 0)
4107 if ((e = lineeditor_output_chars
4108 (d,
4109 &edited->buffer[start],
4110 chars_from_line,
4111 d->input_attrs))
4112 != ___FIX(___NO_ERR)(((long)(0))<<2))
4113 return e;
4114
4115 if (len > 0)
4116 if ((e = lineeditor_output_char_repetition
4117 (d,
4118 ___UNICODE_SPACE32,
4119 len,
4120 lineeditor_erase_attrs (d)))
4121 != ___FIX(___NO_ERR)(((long)(0))<<2))
4122 return e;
4123
4124 return ___FIX(___NO_ERR)(((long)(0))<<2);
4125}
4126
4127
4128___HIDDENstatic ___SCMOBJlong lineeditor_output_force_delayed_wrap
4129 ___P((___device_tty *self),(___device_tty *self)
4130 (self)(___device_tty *self)
4131___device_tty *self;)(___device_tty *self)
4132{
4133 /*
4134 * This routine forces the cursor to wrap to the next line if the
4135 * wrap was delayed.
4136 */
4137
4138 ___device_tty *d = self;
4139
4140 if (d->terminal_delayed_wrap)
4141 return lineeditor_output_current_hist
4142 (d,
4143 d->terminal_cursor + 1 - d->current.line_start,
4144 1);
4145
4146 return ___FIX(___NO_ERR)(((long)(0))<<2);
4147}
4148
4149
4150___HIDDENstatic ___SCMOBJlong lineeditor_move_cursor_plain
4151 ___P((___device_tty *self,(___device_tty *self, int dist)
4152 int dist),(___device_tty *self, int dist)
4153 (self,(___device_tty *self, int dist)
4154 dist)(___device_tty *self, int dist)
4155___device_tty *self;(___device_tty *self, int dist)
4156int dist;)(___device_tty *self, int dist)
4157{
4158 /*
4159 * This routine sends the appropriate commands to the terminal to
4160 * move the cursor "dist" positions forward/backward by writing
4161 * plain characters or backspace characters. We assume that the
4162 * terminal has auto left/right margins if the cursor needs to
4163 * change row.
4164 */
4165
4166 ___device_tty *d = self;
4167 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
4168
4169 if (dist != 0)
4170 {
4171 if (dist < 0)
4172 e = lineeditor_output_char_repetition
4173 (d,
4174 ___UNICODE_BACKSPACE8,
4175 -dist,
4176 d->current.attrs);
4177 else
4178 {
4179 ___BOOLint need_backspace = ((d->terminal_cursor + dist
4180 % d->terminal_nb_cols == 0)
4181 && d->has_eat_newline_glitch);
4182
4183 if ((e = lineeditor_output_current_hist
4184 (d,
4185 d->terminal_cursor + d->terminal_delayed_wrap
4186 - d->current.line_start,
4187 dist - d->terminal_delayed_wrap + need_backspace))
4188 == ___FIX(___NO_ERR)(((long)(0))<<2))
4189 {
4190 if (need_backspace)
4191 e = lineeditor_output_char_repetition
4192 (d,
4193 ___UNICODE_BACKSPACE8,
4194 1,
4195 d->current.attrs);
4196 }
4197 }
4198 }
4199
4200 return e;
4201}
4202
4203
4204___HIDDENstatic ___SCMOBJlong lineeditor_move_cursor
4205 ___P((___device_tty *self,(___device_tty *self, int screen_pos)
4206 int screen_pos),(___device_tty *self, int screen_pos)
4207 (self,(___device_tty *self, int screen_pos)
4208 screen_pos)(___device_tty *self, int screen_pos)
4209___device_tty *self;(___device_tty *self, int screen_pos)
4210int screen_pos;)(___device_tty *self, int screen_pos)
4211{
4212 /*
4213 * This routine sends the appropriate commands to the terminal to
4214 * move the cursor to position "screen_pos".
4215 */
4216
4217 ___device_tty *d = self;
4218 ___SCMOBJlong e;
4219 int cursor = d->terminal_cursor;
4220
4221#ifdef USE_CURSES
4222
4223 int col = screen_pos % d->terminal_nb_cols;
4224 int col_dist = col - d->terminal_col;
4225 int row_dist = screen_pos / d->terminal_nb_cols - d->terminal_row;
4226
4227 if (screen_pos <= cursor)
4228 {
4229 /*
4230 * Check if the cursor can be moved backward by writing no more
4231 * than 4 backspace characters (if on the same row or column) or
4232 * 8 backspace characters (otherwise). This is probably no more
4233 * than is required by cursor movement commands.
4234 */
4235
4236 if ((row_dist == 0 || d->has_auto_left_margin) &&
4237 cursor - screen_pos <= ((row_dist == 0 || col_dist == 0) ? 4 : 8))
4238 return lineeditor_move_cursor_plain (self, screen_pos - cursor);
4239 }
4240 else
4241 {
4242 /*
4243 * Check if the cursor can be moved forward by writing no more
4244 * than 4 plain characters (if on the same row or column) or 8
4245 * plain characters (otherwise). This is probably no more than
4246 * is required by cursor movement commands.
4247 */
4248
4249 if ((row_dist == 0 || d->has_auto_right_margin) &&
4250 screen_pos - (cursor + d->terminal_delayed_wrap)
4251 + ((col == 0 && d->has_eat_newline_glitch) ? 2 : 0)
4252 <= ((row_dist == 0 || col_dist == 0) ? 4 : 8))
4253 return lineeditor_move_cursor_plain (self, screen_pos - cursor);
4254 }
4255
4256 /*
4257 * Move the cursor to the target column.
4258 */
4259
4260 if ((col_dist >= -4) && (col_dist <= 4))
4261 {
4262 /* Use plain characters if not too far. */
4263
4264 if ((e = lineeditor_move_cursor_plain (self, col_dist))
4265 != ___FIX(___NO_ERR)(((long)(0))<<2))
4266 return e;
4267
4268 cursor += col_dist;
4269 col_dist = 0;
4270 }
4271 else
4272 {
4273 /* Use cursor commands if the terminal supports this. */
4274
4275 if (lineeditor_cap (d,
4276 (col_dist > 0)
4277 ? LINEEDITOR_CAP_CUF6
4278 : LINEEDITOR_CAP_CUB7)
4279 != NULL((void*)0))
4280 {
4281 if ((e = lineeditor_output_cap1
4282 (d,
4283 (col_dist > 0) ? LINEEDITOR_CAP_CUF6 : LINEEDITOR_CAP_CUB7,
4284 (col_dist > 0) ? col_dist : -col_dist,
4285 1))
4286 != ___FIX(___NO_ERR)(((long)(0))<<2))
4287 return e;
4288
4289 cursor += col_dist;
4290 col_dist = 0;
4291 }
4292 }
4293
4294 /*
4295 * Move the cursor to the target row using cursor movement commands,
4296 * if the terminal supports this.
4297 */
4298
4299 if (row_dist != 0 &&
4300 ((row_dist > 0)
4301 ? (lineeditor_cap (d, LINEEDITOR_CAP_CUD5) != NULL((void*)0) ||
4302 lineeditor_cap (d, LINEEDITOR_CAP_CUD13) != NULL((void*)0))
4303 : (lineeditor_cap (d, LINEEDITOR_CAP_CUU4) != NULL((void*)0) ||
4304 lineeditor_cap (d, LINEEDITOR_CAP_CUU12) != NULL((void*)0))))
4305 {
4306 if ((row_dist > 0)
4307 ? (lineeditor_cap (d, LINEEDITOR_CAP_CUD5) == NULL((void*)0) ||
4308 (lineeditor_cap (d, LINEEDITOR_CAP_CUD13) != NULL((void*)0) &&
4309 row_dist == 1))
4310 : (lineeditor_cap (d, LINEEDITOR_CAP_CUU4) == NULL((void*)0) ||
4311 (lineeditor_cap (d, LINEEDITOR_CAP_CUU12) != NULL((void*)0) &&
4312 row_dist == -1)))
4313 e = lineeditor_output_cap0
4314 (d,
4315 (row_dist > 0) ? LINEEDITOR_CAP_CUD13 : LINEEDITOR_CAP_CUU12,
4316 (row_dist > 0) ? row_dist : -row_dist);
4317 else
4318 e = lineeditor_output_cap1
4319 (d,
4320 (row_dist > 0) ? LINEEDITOR_CAP_CUD5 : LINEEDITOR_CAP_CUU4,
4321 (row_dist > 0) ? row_dist : -row_dist,
4322 1);
4323
4324 if (e != ___FIX(___NO_ERR)(((long)(0))<<2))
4325 return e;
4326
4327 /* Cursor commands to change row were successful. */
4328
4329 cursor += row_dist * d->terminal_nb_cols;
4330 }
4331
4332#endif
4333
4334 /*
4335 * If the cursor is still not at the target position, move the
4336 * cursor by writing plain characters or backspace characters.
4337 */
4338
4339 return lineeditor_move_cursor_plain (self, screen_pos - cursor);
4340}
4341
4342
4343___HIDDENstatic ___SCMOBJlong lineeditor_left_margin_of_next_row
4344 ___P((___device_tty *self),(___device_tty *self)
4345 (self)(___device_tty *self)
4346___device_tty *self;)(___device_tty *self)
4347{
4348 ___device_tty *d = self;
4349 ___SCMOBJlong e;
4350
4351 if (!(d->linefeed_moves_to_left_margin || !d->output_raw))
4352 if ((e = lineeditor_output_char_repetition
4353 (d,
4354 ___UNICODE_RETURN13,
4355 1,
4356 d->output_attrs))
4357 != ___FIX(___NO_ERR)(((long)(0))<<2))
4358 return e;
4359
4360 return lineeditor_output_char_repetition
4361 (d,
4362 ___UNICODE_LINEFEED10,
4363 1,
4364 d->output_attrs);
4365}
4366
4367
4368___HIDDENstatic ___SCMOBJlong lineeditor_prepare_to_write_at
4369 ___P((___device_tty *self,(___device_tty *self, int screen_pos)
4370 int screen_pos),(___device_tty *self, int screen_pos)
4371 (self,(___device_tty *self, int screen_pos)
4372 screen_pos)(___device_tty *self, int screen_pos)
4373___device_tty *self;(___device_tty *self, int screen_pos)
4374int screen_pos;)(___device_tty *self, int screen_pos)
4375{
4376 /*
4377 * This routine sends commands to the terminal such that the next
4378 * character sent to the terminal will show up at screen position
4379 * "screen_pos". The position can be equal to the size of the
4380 * screen, in which case either the screen is scrolled right away or
4381 * the next character sent to the terminal will cause the screen to
4382 * scroll.
4383 */
4384
4385 ___device_tty *d = self;
4386 ___SCMOBJlong e;
4387 int screen_size = d->terminal_size;
4388 int cursor = d->terminal_cursor;
4389
4390 if (screen_pos > screen_size)
4391 screen_pos = screen_size;
4392
4393 if (cursor + d->terminal_delayed_wrap == screen_pos)
4394 e = ___FIX(___NO_ERR)(((long)(0))<<2); /* next character will be at the right place */
4395 else if (screen_pos == screen_size)
4396 {
4397 if ((e = lineeditor_move_cursor (d, screen_pos-1))
4398 == ___FIX(___NO_ERR)(((long)(0))<<2))
4399 e = lineeditor_output_current_hist
4400 (d,
4401 screen_pos - 1 - d->current.line_start,
4402 1);
4403 }
4404 else
4405 {
4406 if ((e = lineeditor_move_cursor (d, screen_pos))
4407 == ___FIX(___NO_ERR)(((long)(0))<<2))
4408 {
4409 if (d->terminal_delayed_wrap)
4410 {
4411 /*
4412 * Output a backspace and a character. Note that this
4413 * assumes the screen is at least 2 columns wide.
4414 */
4415
4416 if ((e = lineeditor_output_char_repetition
4417 (d,
4418 ___UNICODE_BACKSPACE8,
4419 1,
4420 d->current.attrs))
4421 == ___FIX(___NO_ERR)(((long)(0))<<2))
4422 e = lineeditor_output_current_hist
4423 (d,
4424 screen_pos - 1 - d->current.line_start,
4425 1);
4426 }
4427 }
4428 }
4429
4430 return e;
4431}
4432
4433
4434___HIDDENstatic ___SCMOBJlong lineeditor_newline
4435 ___P((___device_tty *self),(___device_tty *self)
4436 (self)(___device_tty *self)
4437___device_tty *self;)(___device_tty *self)
4438{
4439 /*
4440 * This routine moves the cursor to the left margin of the row
4441 * following the last visible part of the line being edited.
4442 */
4443
4444 ___device_tty *d = self;
4445 ___SCMOBJlong e;
4446 extensible_string *edited = &d->current.hist->edited;
4447 int screen_size = d->terminal_size;
4448 int screen_end_of_line = d->current.line_start + edited->length;
4449
4450 if (screen_end_of_line < 0)
4451 screen_end_of_line = 0;
4452 else if (screen_end_of_line >= screen_size)
4453 screen_end_of_line = screen_size - 1;
4454
4455 if ((e = lineeditor_prepare_to_write_at (d, screen_end_of_line))
4456 != ___FIX(___NO_ERR)(((long)(0))<<2))
4457 return e;
4458
4459 return lineeditor_left_margin_of_next_row (d);
4460}
4461
4462
4463___HIDDENstatic ___SCMOBJlong lineeditor_copy_to_clipboard
4464 ___P((___device_tty *self,(___device_tty *self, unsigned int *buf, int len)
4465 ___C *buf,(___device_tty *self, unsigned int *buf, int len)
4466 int len),(___device_tty *self, unsigned int *buf, int len)
4467 (self,(___device_tty *self, unsigned int *buf, int len)
4468 buf,(___device_tty *self, unsigned int *buf, int len)
4469 len)(___device_tty *self, unsigned int *buf, int len)
4470___device_tty *self;(___device_tty *self, unsigned int *buf, int len)
4471___C *buf;(___device_tty *self, unsigned int *buf, int len)
4472int len;)(___device_tty *self, unsigned int *buf, int len)
4473{
4474 /*
4475 * Copies "len" characters from the buffer "buf" to the clipboard.
4476 */
4477
4478 ___device_tty *d = self;
4479 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
4480
4481#ifdef LINEEDITOR_WITH_LOCAL_CLIPBOARD
4482
4483 extensible_string str;
4484
4485 if ((e = extensible_string_copy (buf, len, &str, 0)) == ___FIX(___NO_ERR)(((long)(0))<<2))
4486 {
4487 extensible_string_cleanup (&d->clipboard);
4488 d->clipboard = str;
4489 }
4490
4491#else
4492
4493#ifdef USE_WIN32
4494
4495 HWND cons_wind = GetConsoleWindow ();
4496
4497 if (cons_wind != NULL((void*)0))
4498 {
4499 if (OpenClipboard (cons_wind))
4500 {
4501 HGLOBAL global_copy = GlobalAlloc (GMEM_MOVEABLE,
4502 (len+1) * sizeof(___U16unsigned short));
4503
4504 if (global_copy != NULL((void*)0))
4505 {
4506 ___U16unsigned short *locked_copy = ___CAST(___U16*,GlobalLock (global_copy))((unsigned short*)(GlobalLock (global_copy)));
4507
4508 if (locked_copy == NULL((void*)0))
4509 GlobalFree (global_copy);
4510 else
4511 {
4512 int i;
4513
4514 for (i=0; i<len; i++)
4515 locked_copy[i] = buf[i];
4516 locked_copy[len] = 0;
4517
4518 GlobalUnlock (global_copy);
4519
4520 EmptyClipboard ();
4521
4522 if (!SetClipboardData (CF_UNICODETEXT, global_copy))
4523 GlobalFree (global_copy);
4524 }
4525 }
4526
4527 CloseClipboard ();
4528 }
4529 }
4530
4531#endif
4532
4533#endif
4534
4535 return e;
4536}
4537
4538
4539___HIDDENstatic ___SCMOBJlong lineeditor_paste_from_clipboard
4540 ___P((___device_tty *self),(___device_tty *self)
4541 (self)(___device_tty *self)
4542___device_tty *self;)(___device_tty *self)
4543{
4544 /*
4545 * Paste the content of the clipboard to the input stream (the next
4546 * characters read from the terminal will in fact come from the
4547 * pasted text).
4548 */
4549
4550 ___device_tty *d = self;
4551 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
4552
4553#ifdef LINEEDITOR_WITH_LOCAL_CLIPBOARD
4554
4555 int len = d->clipboard.length;
4556 ___Cunsigned int *str;
4557
4558 str = ___CAST(___C*,((unsigned int*)(___alloc_mem ((len+1) * sizeof (unsigned int
))))
4559 ___alloc_mem ((len+1) * sizeof (___C)))((unsigned int*)(___alloc_mem ((len+1) * sizeof (unsigned int
))))
;
4560
4561 if (str == NULL((void*)0))
4562 e = ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
4563 else
4564 {
4565 str[len] = 0;
4566 while (len-- > 0)
4567 str[len] = d->clipboard.buffer[len];
4568
4569 if (d->paste_text != NULL((void*)0))
4570 ___free_mem (d->paste_text);
4571
4572 d->paste_index = 0;
4573 d->paste_text = str;
4574 }
4575
4576#else
4577
4578#ifdef USE_WIN32
4579
4580 HWND cons_wind = GetConsoleWindow ();
4581
4582 if (cons_wind != NULL((void*)0))
4583 {
4584 if (IsClipboardFormatAvailable (CF_UNICODETEXT) &&
4585 OpenClipboard (cons_wind))
4586 {
4587 HGLOBAL global_copy = GetClipboardData (CF_UNICODETEXT);
4588
4589 if (global_copy != NULL((void*)0))
4590 {
4591 ___U16unsigned short *locked_copy = ___CAST(___U16*,GlobalLock (global_copy))((unsigned short*)(GlobalLock (global_copy)));
4592
4593 if (locked_copy != NULL((void*)0))
4594 {
4595 int i;
4596 ___Cunsigned int *str;
4597 int len = 0;
4598
4599 while (locked_copy[len] != 0)
4600 len++;
4601
4602 str = ___CAST(___C*,((unsigned int*)(___alloc_mem ((len+1) * sizeof (unsigned int
))))
4603 ___alloc_mem ((len+1) * sizeof (___C)))((unsigned int*)(___alloc_mem ((len+1) * sizeof (unsigned int
))))
;
4604
4605 if (str == NULL((void*)0))
4606 e = ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
4607 else
4608 {
4609 str[len] = 0;
4610 while (len-- > 0)
4611 str[len] = locked_copy[len];
4612
4613 if (d->paste_text != NULL((void*)0))
4614 ___free_mem (d->paste_text);
4615
4616 d->paste_index = 0;
4617 d->paste_text = str;
4618 }
4619
4620 GlobalUnlock (locked_copy);
4621 }
4622 }
4623
4624 CloseClipboard ();
4625 }
4626 }
4627
4628#endif
4629
4630#endif
4631
4632 return e;
4633}
4634
4635
4636___HIDDENstatic ___BOOLint lineeditor_read_ready
4637 ___P((___device_tty *self),(___device_tty *self)
4638 (self)(___device_tty *self)
4639___device_tty *self;)(___device_tty *self)
4640{
4641 ___device_tty *d = self;
4642
4643 return (d->input_char_hi - d->input_char_lo > 0)
4644 || (d->paste_text != NULL((void*)0));
4645}
4646
4647
4648___HIDDENstatic ___SCMOBJlong lineeditor_input_read
4649 ___P((___device_tty *self,(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4650 ___C *buf,(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4651 ___stream_index len,(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4652 ___stream_index *len_done),(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4653 (self,(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4654 buf,(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4655 len,(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4656 len_done)(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4657___device_tty *self;(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4658___C *buf;(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4659___stream_index len;(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4660___stream_index *len_done;)(___device_tty *self, unsigned int *buf, ___stream_index len,
___stream_index *len_done)
4661{
4662 ___device_tty *d = self;
4663 int char_avail = d->input_char_hi - d->input_char_lo;
4664
4665 if (char_avail <= 0)
4666 {
4667 /*
4668 * There are no characters in the character input buffer so we
4669 * must fill the buffer by reading the device. If possible,
4670 * characters will be extracted from the byte input buffer
4671 * without reading new bytes from the device, otherwise the
4672 * device will be read. If a read error occurs (including
4673 * EAGAIN) an error code is returned, otherwise ___NO_ERR is
4674 * returned. ___NO_ERR is returned if and only if at least one
4675 * character was added to the character buffer.
4676 */
4677
4678 ___SCMOBJlong e;
4679 ___stream_index len;
4680 ___stream_index len_done;
4681 ___U8unsigned char *byte_buf;
4682 int byte_buf_avail;
4683 int char_buf_avail;
4684 int lo;
4685 int code;
4686
4687 /*
4688 * Make space at end of byte buffer by shifting remaining bytes to
4689 * the head of the buffer.
4690 */
4691
4692 lo = d->input_byte_lo;
4693
4694 if (lo > 0)
4695 {
4696 int hi = d->input_byte_hi;
4697 int i = 0;
4698
4699 while (lo < hi)
4700 d->input_byte[i++] = d->input_byte[lo++];
4701
4702 d->input_byte_lo = 0;
4703 d->input_byte_hi = i;
4704 }
4705
4706 do
4707 {
4708 /*
4709 * Read as many bytes as possible into the byte buffer.
4710 */
4711
4712 if ((e = ___device_tty_read_raw_no_lineeditor
4713 (d,
4714 d->input_byte + d->input_byte_hi,
4715 ___NBELEMS(d->input_byte)(sizeof (d->input_byte) / sizeof ((d->input_byte)[0])) - d->input_byte_hi,
4716 &len_done))
4717 != ___FIX(___NO_ERR)(((long)(0))<<2))
4718 return e;
4719
4720 byte_buf_avail = (d->input_byte_hi += len_done) - d->input_byte_lo;
4721
4722 /*
4723 * Extract as many characters as possible from byte buffer to
4724 * character buffer.
4725 */
4726
4727 if (byte_buf_avail > 0)
4728 {
4729 char_buf_avail = ___NBELEMS(d->input_char)(sizeof (d->input_char) / sizeof ((d->input_char)[0]));
4730
4731 code = chars_from_bytes (d->input_char,
4732 &char_buf_avail,
4733 d->input_byte + d->input_byte_lo,
4734 &byte_buf_avail,
4735 &d->input_decoding_state);
4736
4737 d->input_char_lo = 0;
4738 d->input_char_hi = ___NBELEMS(d->input_char)(sizeof (d->input_char) / sizeof ((d->input_char)[0])) - char_buf_avail;
4739
4740 if (byte_buf_avail <= 0)
4741 {
4742 d->input_byte_lo = 0;
4743 d->input_byte_hi = 0;
4744 }
4745 else
4746 d->input_byte_lo = d->input_byte_hi - byte_buf_avail;
4747
4748 if (code == ___ILLEGAL_CHAR2)
4749 return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+3)))<<2)
;
4750 }
4751 else
4752 code = ___INCOMPLETE_CHAR1;
4753
4754 } while (code != ___CONVERSION_DONE0);
4755
4756 /*
4757 * This point is reached if and only if there is at least one
4758 * character in the character buffer.
4759 */
4760
4761 char_avail = d->input_char_hi - d->input_char_lo;
4762 }
4763
4764 if (char_avail > len)
4765 char_avail = len;
4766
4767 *len_done = char_avail;
4768
4769 while (char_avail > 0)
4770 {
4771 *buf++ = d->input_char[d->input_char_lo++];
4772 char_avail--;
4773 }
4774
4775 return ___FIX(___NO_ERR)(((long)(0))<<2);
4776}
4777
4778
4779___HIDDENstatic ___SCMOBJlong lineeditor_get_event
4780 ___P((___device_tty *self,(___device_tty *self, lineeditor_event *ev)
4781 lineeditor_event *ev),(___device_tty *self, lineeditor_event *ev)
4782 (self,(___device_tty *self, lineeditor_event *ev)
4783 ev)(___device_tty *self, lineeditor_event *ev)
4784___device_tty *self;(___device_tty *self, lineeditor_event *ev)
4785lineeditor_event *ev;)(___device_tty *self, lineeditor_event *ev)
4786{
4787 /*
4788 * This routine obtains the next line editing event from the
4789 * terminal. An event can be a key press or some editing operation
4790 * (like "delete next word").
4791 */
4792
4793 ___device_tty *d = self;
4794 lineeditor_input_decoder_state s = d->input_decoder_state;
4795 ___Cunsigned int c;
4796 ___BOOLint first_char;
4797 ___stream_index len_done;
4798 ___SCMOBJlong e;
4799
4800 first_char = (s == 0);
4801
4802 if (d->paste_text != NULL((void*)0))
4803 {
4804 if (d->paste_cancel ||
4805 (c = d->paste_text[d->paste_index++]) == 0)
4806 {
4807 ___free_mem (d->paste_text);
4808 d->paste_text = NULL((void*)0);
4809 }
4810 else
4811 {
4812 ev->event_kind = LINEEDITOR_EV_KEY1;
4813 ev->event_char = c;
4814 return ___FIX(___NO_ERR)(((long)(0))<<2);
4815 }
4816 }
4817
4818 next_char:
4819
4820 if ((e = lineeditor_input_read (d, &c, 1, &len_done))
4821 == ___FIX(___NO_ERR)(((long)(0))<<2) &&
4822 len_done == 1)
4823 {
4824 while (s < d->input_decoder.length)
4825 {
4826 if (d->input_decoder.buffer[s].trigger == c)
4827 {
4828 int a = d->input_decoder.buffer[s].action;
4829 if (a < LINEEDITOR_INPUT_DECODER_MAX_LENGTH(255 -55 -1))
4830 {
4831 s = a;
4832 first_char = 0;
4833 goto next_char;
4834 }
4835 d->input_decoder_state = 0;
4836 ev->event_kind = LINEEDITOR_INPUT_DECODER_STATE_MAX255-a;
4837 return ___FIX(___NO_ERR)(((long)(0))<<2);
4838 }
4839 else
4840 s = d->input_decoder.buffer[s].next;
4841 }
4842 if (first_char)
4843 {
4844 ev->event_kind = LINEEDITOR_EV_KEY1;
4845 ev->event_char = c;
4846 return ___FIX(___NO_ERR)(((long)(0))<<2);
4847 }
4848 s = 0; /* ignore the sequence including last character read */
4849 }
4850
4851 d->input_decoder_state = s;
4852 ev->event_kind = LINEEDITOR_EV_NONE0;
4853
4854 if (e != ___FIX(___NO_ERR)(((long)(0))<<2) && e != ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<<
16)+(11)))))<<2)
)
4855 return e;
4856
4857 return ___FIX(___NO_ERR)(((long)(0))<<2);
4858}
4859
4860
4861___HIDDENstatic ___SCMOBJlong lineeditor_set_terminal_type
4862 ___P((___device_tty *self,(___device_tty *self, char *terminal_type, int emacs_bindings
)
4863 char *terminal_type,(___device_tty *self, char *terminal_type, int emacs_bindings
)
4864 ___BOOL emacs_bindings),(___device_tty *self, char *terminal_type, int emacs_bindings
)
4865 (self,(___device_tty *self, char *terminal_type, int emacs_bindings
)
4866 terminal_type,(___device_tty *self, char *terminal_type, int emacs_bindings
)
4867 emacs_bindings)(___device_tty *self, char *terminal_type, int emacs_bindings
)
4868___device_tty *self;(___device_tty *self, char *terminal_type, int emacs_bindings
)
4869char *terminal_type;(___device_tty *self, char *terminal_type, int emacs_bindings
)
4870___BOOL emacs_bindings;)(___device_tty *self, char *terminal_type, int emacs_bindings
)
4871{
4872 ___device_tty *d = self;
4873 ___SCMOBJlong e;
4874
4875 /* default values appropriate for "xterm": */
4876
4877 int rows = 24;
4878 int cols = 80;
4879 ___BOOLint has_auto_left_margin = 0;
4880 ___BOOLint has_auto_right_margin = 1;
4881 ___BOOLint has_eat_newline_glitch = 1;
4882
4883#ifdef USE_CURSES
4884
4885 int i;
4886
4887#ifdef USE_TERMCAP_OR_TERMINFO
4888
4889 if (terminal_type != NULL((void*)0))
4890 {
4891#ifdef USE_TERMCAP
4892
4893 char termcap_buffer[4080]; /* the value 4080 is used by GNU's readline */
4894
4895 if (tgetent (termcap_buffer, terminal_type) != 1)
4896 return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+3)))<<2)
;
4897
4898 rows = tgetnum ("li");
4899 cols = tgetnum ("co");
4900 has_auto_left_margin = (tgetflag ("bw") != 0);
4901 has_auto_right_margin = (tgetflag ("am") != 0);
4902 has_eat_newline_glitch = (tgetflag ("xn") != 0);
4903
4904#else
4905
4906 int errret;
4907
4908 if (setupterm (terminal_type, 1, &errret) == ERR)
4909 return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+3)))<<2)
;
4910
4911 rows = tigetnum ("lines");
4912 cols = tigetnum ("cols");
4913 has_auto_left_margin = (tigetflag ("bw") != 0);
4914 has_auto_right_margin = (tigetflag ("am") != 0);
4915 has_eat_newline_glitch = (tigetflag ("xenl") != 0);
4916
4917#endif
4918 }
4919
4920#endif
4921
4922 /*
4923 * Setup the capability table.
4924 */
4925
4926 for (i=0; i<LINEEDITOR_CAP_LAST21+1; i++)
4927 {
4928 char *seq = d->capability[i];
4929
4930 if (seq != NULL((void*)0))
4931 {
4932 ___free_mem (seq);
4933 d->capability[i] = NULL((void*)0);
4934 }
4935 }
4936
4937 for (i=0; i<LINEEDITOR_CAP_LAST21+1; i++)
4938 {
4939 char *seq;
4940
4941#ifdef USE_TERMCAP_OR_TERMINFO
4942
4943 if (terminal_type != NULL((void*)0))
4944 {
4945#ifdef USE_TERMCAP
4946
4947 seq = tgetstr (lineeditor_dcap_table[i].cap, NULL((void*)0));
4948
4949#else
4950
4951 seq = tigetstr (lineeditor_dcap_table[i].cap);
4952
4953#endif
4954 }
4955 else
4956 seq = lineeditor_dcap_table[i].xterm_cap;
4957
4958#else
4959
4960 seq = lineeditor_dcap_table[i].cap;
4961
4962#endif
4963
4964 if (seq != (char*)-1 && seq != NULL((void*)0))
4965 {
4966#ifdef ___DEBUG_TTY
4967
4968 int j = -1;
4969
4970 ___printf ("cap %d = ", i);
4971
4972 while (seq[++j] != '\0')
4973 if (seq[j] < ' ')
4974 ___printf ("\\%03o", seq[j]);
4975 else
4976 ___printf ("%c", seq[j]);
4977
4978 ___printf ("\n");
4979
4980#endif
4981
4982 /*
4983 * Reject any sequence that includes a linefeed if the
4984 * terminal driver automatically adds a carriage return.
4985 */
4986
4987 if (d->linefeed_moves_to_left_margin)
4988 {
4989 char *p = seq;
4990 while (*p != '\0')
4991 if (*p != ___UNICODE_LINEFEED10)
4992 p++;
4993 else
4994 break;
4995 if (*p != '\0')
4996 seq = NULL((void*)0);
4997 }
4998
4999 /*
5000 * Keep a copy of the sequence.
5001 */
5002
5003 if (seq != NULL((void*)0))
5004 {
5005 char *p;
5006 int len = 0;
5007 while (seq[len] != '\0')
5008 len++;
5009 p = ___CAST(char*,___alloc_mem (len+1))((char*)(___alloc_mem (len+1)));
5010 if (p != NULL((void*)0))
5011 {
5012 p[len] = '\0';
5013 while (len-- > 0)
5014 p[len] = seq[len];
5015 }
5016 d->capability[i] = p;
5017 }
5018 else
5019 d->capability[i] = NULL((void*)0);
5020 }
5021 else
5022 d->capability[i] = NULL((void*)0);
5023 }
5024
5025#endif
5026
5027 /*
5028 * Initialize input decoder so that it recognizes special keys. Map
5029 * rubout key to backspace if not on WIN32.
5030 */
5031
5032 d->input_decoder_state = 0;
5033
5034 if ((e = lineeditor_input_decoder_init
5035 (&d->input_decoder,
5036#ifdef USE_WIN32
5037 0,
5038#else
5039 1,
5040#endif
5041 emacs_bindings,
5042 terminal_type == NULL((void*)0)))
5043 != ___FIX(___NO_ERR)(((long)(0))<<2))
5044 return e;
5045
5046 if (rows <= 0)
5047 rows = 24;
5048 if (cols <= 0)
5049 cols = 80;
5050
5051 d->terminal_nb_cols = cols;
5052 d->terminal_nb_rows = rows;
5053 d->terminal_size = rows * cols;
5054 d->has_auto_left_margin = has_auto_left_margin;
5055 d->has_auto_right_margin = has_auto_right_margin;
5056 d->has_eat_newline_glitch = has_eat_newline_glitch;
5057 d->size_needs_update = 1;
5058
5059#ifdef ___DEBUG_TTY
5060
5061 ___printf ("terminal_type=%s rows=%d cols=%d alm=%d arm=%d eng=%d\n",
5062 terminal_type,
5063 rows,
5064 cols,
5065 has_auto_left_margin,
5066 has_auto_right_margin,
5067 has_eat_newline_glitch);
5068
5069#endif
5070
5071 return ___FIX(___NO_ERR)(((long)(0))<<2);
5072}
5073
5074
5075___HIDDENstatic ___SCMOBJlong ___device_tty_default_options_virt
5076 ___P((___device_stream *self),(___device_stream *self)
5077 ())(___device_stream *self);
5078
5079
5080___HIDDENstatic ___SCMOBJlong lineeditor_setup
5081 ___P((___device_tty *self,(___device_tty *self, int plain)
5082 int plain),(___device_tty *self, int plain)
5083 (self,(___device_tty *self, int plain)
5084 plain)(___device_tty *self, int plain)
5085___device_tty *self;(___device_tty *self, int plain)
5086int plain;)(___device_tty *self, int plain)
5087{
5088 ___device_tty *d = self;
5089 ___SCMOBJlong e;
5090 lineeditor_history *h;
5091 ___SCMOBJlong default_options =
5092 ___INT(___device_tty_default_options_virt (&d->base))((___device_tty_default_options_virt (&d->base))>>
2)
;
5093
5094 if (plain || d->stage == TTY_STAGE_NOT_OPENED0)
5095 {
5096 /* Console */
5097
5098 d->input_allow_special = 1;
5099 d->input_echo = 1;
5100 d->input_raw = 0;
5101 d->output_raw = 0;
5102 d->speed = 0;
5103 }
5104 else
5105 {
5106 /* TTY other than console */
5107
5108 d->input_allow_special = 0;
5109 d->input_echo = 0;
5110 d->input_raw = 1;
5111 d->output_raw = 1;
5112 d->speed = 0;
5113 }
5114
5115 d->lineeditor_mode = LINEEDITOR_MODE_DISABLE0;
5116
5117 if (lineeditor_under_emacs ())
5118 d->input_echo = 0;
5119 else
5120 {
5121 if (___TERMINAL_LINE_EDITING(___setup_params.terminal_settings)((___setup_params.terminal_settings)&(3<<16)) !=
5122 ___TERMINAL_LINE_EDITING_OFF(2<<16))
5123 d->lineeditor_mode = LINEEDITOR_MODE_SCHEME1;
5124 }
5125
5126 /* for terminal emulation */
5127
5128 d->emulate_terminal = 1;
5129
5130 d->terminal_nb_cols = 80;
5131 d->terminal_nb_rows = 24;
5132 d->terminal_size = d->terminal_nb_rows * d->terminal_nb_cols;
5133 d->has_auto_left_margin = 0;
5134 d->has_auto_right_margin = 1;
5135 d->has_eat_newline_glitch = 1;
5136 d->linefeed_moves_to_left_margin = 0;
5137
5138 d->terminal_col = 0;
5139 d->terminal_row = 0;
5140 d->terminal_cursor = 0;
5141 d->terminal_delayed_wrap = 0;
5142
5143 d->terminal_param_num = -2;
5144
5145 d->terminal_attrs = MAKE_TEXT_ATTRS(TEXT_STYLE_NORMAL,(((0)<<8)+(8)+((8)<<4))
5146 DEFAULT_TEXT_COLOR,(((0)<<8)+(8)+((8)<<4))
5147 DEFAULT_TEXT_COLOR)(((0)<<8)+(8)+((8)<<4));
5148
5149 /* input and output buffers */
5150
5151 d->input_byte_lo = 0;
5152 d->input_byte_hi = 0;
5153 d->input_char_lo = 0;
5154 d->input_char_hi = 0;
5155
5156 d->input_decoding_state = ___STREAM_OPTIONS_INPUT(default_options)((default_options)&((1<<15)-1));
5157 d->input_encoding_state = ___STREAM_OPTIONS_INPUT(default_options)((default_options)&((1<<15)-1));
5158
5159 d->input_line_lo = 0;
5160 d->input_line.buffer = NULL((void*)0);
5161 d->input_line.length = 0;
5162
5163 d->output_byte_lo = 0;
5164 d->output_byte_hi = 0;
5165
5166 d->output_char_incomplete = 0;
5167 d->input_char_incomplete = 0;
5168
5169 d->output_decoding_state = ___STREAM_OPTIONS_OUTPUT(default_options)(((default_options)>>15)&((1<<15)-1));
5170 d->output_encoding_state = ___STREAM_OPTIONS_OUTPUT(default_options)(((default_options)>>15)&((1<<15)-1));
5171
5172 d->output_char_lo = 0;
5173
5174 /* line editing */
5175
5176 d->editing_line = 0;
5177
5178 d->prompt_length = 0;
5179
5180 d->lineeditor_input_byte_lo = 0;
5181 d->lineeditor_input_byte_hi = 0;
5182
5183 d->paste_cancel = 0;
5184 d->paste_index = 0;
5185 d->paste_text = NULL((void*)0);
5186
5187 d->history_max_length = 1000000000; /* set a very high limit */
5188 d->history_length = -1;
5189 d->hist_last = NULL((void*)0);
5190
5191 d->current.edit_point = 0;
5192 d->current.completion_point = 0;
5193 d->current.mark_point = 0;
5194 d->current.line_start = 0;
5195 d->current.paren_balance_trigger = 0;
5196 d->current.paren_balance_in_progress = 0;
5197 d->current.attrs = INITIAL_TEXT_ATTRS(((0)<<8)+(8)+((8)<<4));
5198
5199 d->paren_balance_duration_nsecs = DEFAULT_PAREN_BALANCE_DURATION_NSECS500000000;
5200
5201 d->input_attrs = DEFAULT_INPUT_TEXT_ATTRS(((1)<<8)+(8)+((8)<<4));
5202 d->output_attrs = DEFAULT_OUTPUT_TEXT_ATTRS(((0)<<8)+(8)+((8)<<4));
5203
5204#ifdef USE_CURSES
5205
5206 {
5207 int i;
5208 for (i=0; i<LINEEDITOR_CAP_LAST21+1; i++)
5209 d->capability[i] = NULL((void*)0);
5210 }
5211
5212#endif
5213
5214#ifdef USE_WIN32
5215
5216 d->key_seq = NULL((void*)0);
5217
5218#endif
5219
5220#ifdef LINEEDITOR_WITH_LOCAL_CLIPBOARD
5221 if ((e = extensible_string_setup (&d->clipboard, 0))
5222 == ___FIX(___NO_ERR)(((long)(0))<<2))
5223 {
5224#endif
5225 if ((e = extensible_string_setup (&d->output_char, 0))
5226 == ___FIX(___NO_ERR)(((long)(0))<<2))
5227 {
5228 if ((e = lineeditor_input_decoder_setup (&d->input_decoder))
5229 == ___FIX(___NO_ERR)(((long)(0))<<2))
5230 {
5231 if ((e = lineeditor_history_setup (d, &h))
5232 == ___FIX(___NO_ERR)(((long)(0))<<2))
5233 {
5234 lineeditor_history_add_last (d, h);
5235 d->current.hist = h;
5236 if ((e = lineeditor_history_begin_edit (d, h))
5237 == ___FIX(___NO_ERR)(((long)(0))<<2))
5238 {
5239 if ((e = lineeditor_set_terminal_type
5240 (d,
5241 NULL((void*)0),
5242 DEFAULT_EMACS_BINDINGS1))
5243 == ___FIX(___NO_ERR)(((long)(0))<<2))
5244 {
5245 return ___FIX(___NO_ERR)(((long)(0))<<2);
5246 }
5247 }
5248 d->history_max_length = -1;
5249 lineeditor_history_trim (d);
5250 }
5251 lineeditor_input_decoder_cleanup (&d->input_decoder);
5252 }
5253 extensible_string_cleanup (&d->output_char);
5254 }
5255#ifdef LINEEDITOR_WITH_LOCAL_CLIPBOARD
5256 extensible_string_cleanup (&d->clipboard);
5257 }
5258#endif
5259
5260 return e;
5261}
5262
5263
5264___HIDDENstatic void lineeditor_cleanup
5265 ___P((___device_tty *self),(___device_tty *self)
5266 (self)(___device_tty *self)
5267___device_tty *self;)(___device_tty *self)
5268{
5269 ___device_tty *d = self;
5270
5271#ifdef USE_CURSES
5272 {
5273 int i;
5274
5275 for (i=0; i<LINEEDITOR_CAP_LAST21+1; i++)
5276 {
5277 char *seq = d->capability[i];
5278 if (seq != NULL((void*)0))
5279 ___free_mem (seq);
5280 }
5281 }
5282#endif
5283
5284 d->history_max_length = -1;
5285 lineeditor_history_trim (d);
5286
5287 lineeditor_input_decoder_cleanup (&d->input_decoder);
5288
5289 extensible_string_cleanup (&d->output_char);
5290
5291#ifdef LINEEDITOR_WITH_LOCAL_CLIPBOARD
5292 extensible_string_cleanup (&d->clipboard);
5293#endif
5294
5295 if (d->input_line.buffer != NULL((void*)0))
5296 extensible_string_cleanup (&d->input_line);
5297
5298 lineeditor_output_set_attrs
5299 (d,
5300 INITIAL_TEXT_ATTRS(((0)<<8)+(8)+((8)<<4))); /* ignore error */
5301
5302 lineeditor_output_drain (d); /* ignore error */
5303
5304 if (d->paste_text != NULL((void*)0))
5305 ___free_mem (d->paste_text); /* discard paste text */
5306
5307#if 0
5308 /******************** device should be freed elsewhere */
5309 ___free_mem (d);
5310#endif
5311}
5312
5313
5314/*
5315 * Each character position of the screen is identified by an integer
5316 * from 0 to nb_rows * nb_cols - 1. Screen position 0 is at the top
5317 * left. This numbering is logically extended beyond the actual
5318 * screen limits. If we assume that the screen is 10 columns by 4
5319 * rows we have this layout:
5320 *
5321 *
5322 * ... -8 -7 -6 -5 -4 -3 -2 -1
5323 * OFF SCREEN
5324 * +---+---+---+---+---+---+---+---+---+---+^^^^^^^^^^^^
5325 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | \
5326 * +---+---+---+---+---+---+---+---+---+---+ |
5327 * |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 | |
5328 * +---+---+---+---+---+---+---+---+---+---+ > SCREEN
5329 * |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 | |
5330 * +---+---+---+---+---+---+---+---+---+---+ |
5331 * |30 |31 |32 |33 |34 |35 |36 |37 |38 |39 | /
5332 * +---+---+---+---+---+---+---+---+---+---+vvvvvvvvvvvv
5333 * OFF SCREEN
5334 * 40 41 42 43 44 45 46 47 ...
5335 *
5336 * The "cursor" position is the screen position where the cursor is
5337 * currently located. The field terminal_cursor contains this
5338 * screen position (the fields terminal_col and terminal_row
5339 * indicate the column and row of the cursor).
5340 *
5341 * The line that is being edited usually fits completely on the screen
5342 * but if the line is very long some parts may not be visible. When
5343 * an editing operation causes the cursor to move the edited line is
5344 * redisplayed so that the cursor stays visible.
5345 *
5346 * The editing "point" is the character position in the line being
5347 * edited where editing operations occur (inserting characters, etc).
5348 * The cursor is usually over the character at the editing point.
5349 * Some operations, notably parenthesis balancing and program output,
5350 * move the cursor over some other character than the editing point.
5351 *
5352 * The field "line_start" contains the (logical) screen position where
5353 * the edited line starts. Here is an example where the edited line
5354 * starts at screen position 18 and is 15 characters long.
5355 *
5356 * +---+---+---+---+---+---+---+---+---+---+
5357 * | H | e | l | l | o | . | | | | |
5358 * +---+---+---+---+---+---+---+---+---+---+
5359 * | P | R | O | M | P | T | > | | 0 | 1 |
5360 * +---+---+---+---+---+---+---+---+---+---+
5361 * | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 |
5362 * +---+---+---+---+---+---+---+---+---+---+
5363 * |12 |13 |14 | | | | | | | |
5364 * +---+---+---+---+---+---+---+---+---+---+
5365 *
5366 * Here is an example where the edited line is larger than the
5367 * screen (the edited line starts at screen position -22 and
5368 * it contains 65 characters).
5369 *
5370 *
5371 * P R O M P T > 0 1
5372 *
5373 * 2 3 4 5 6 7 8 9 10 11
5374 *
5375 * 12 13 14 15 16 17 18 19 20 21
5376 * OFF SCREEN
5377 * +---+---+---+---+---+---+---+---+---+---+^^^^^^^^^^^^
5378 * |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 | \
5379 * +---+---+---+---+---+---+---+---+---+---+ |
5380 * |32 | . | . | . | . | . | . | . | . |41 | |
5381 * +---+---+---+---+---+---+---+---+---+---+ > SCREEN
5382 * |42 | . | . | . | . | . | . | . | . |51 | |
5383 * +---+---+---+---+---+---+---+---+---+---+ |
5384 * |52 |53 |54 |55 |56 |57 |58 |59 |60 |61 | /
5385 * +---+---+---+---+---+---+---+---+---+---+vvvvvvvvvvvv
5386 * OFF SCREEN
5387 * 62 63 64
5388 */
5389
5390
5391___HIDDENstatic ___SCMOBJlong lineeditor_update_region
5392 ___P((___device_tty *self,(___device_tty *self, int start, int end)
5393 int start,(___device_tty *self, int start, int end)
5394 int end),(___device_tty *self, int start, int end)
5395 (self,(___device_tty *self, int start, int end)
5396 start,(___device_tty *self, int start, int end)
5397 end)(___device_tty *self, int start, int end)
5398___device_tty *self;(___device_tty *self, int start, int end)
5399int start;(___device_tty *self, int start, int end)
5400int end;)(___device_tty *self, int start, int end)
5401{
5402 /*
5403 * This routine is called when a change in the line being edited
5404 * must be shown on the screen. Characters between positions
5405 * "start" (inclusive) and "end" (exclusive) have changed. Only the
5406 * changes that are visible cause the screen to be updated.
5407 */
5408
5409 ___device_tty *d = self;
5410 ___SCMOBJlong e;
5411 int screen_size = d->terminal_size;
5412 int screen_start = d->current.line_start + start;
5413 int screen_end = d->current.line_start + end;
5414
5415 if (!d->has_eat_newline_glitch)
5416 screen_size--; /* the last character on the screen can't be shown! */
5417
5418 if (screen_start >= screen_size ||
5419 screen_end <= 0)
5420 e = ___FIX(___NO_ERR)(((long)(0))<<2); /* the change is not visible */
5421 else
5422 {
5423 if (screen_start < 0)
5424 screen_start = 0;
5425
5426 if (screen_end > screen_size)
5427 screen_end = screen_size;
5428
5429 if ((e = lineeditor_prepare_to_write_at (d, screen_start))
5430 == ___FIX(___NO_ERR)(((long)(0))<<2))
5431 e = lineeditor_output_current_hist
5432 (d,
5433 screen_start - d->current.line_start,
5434 screen_end - screen_start);
5435 }
5436
5437 return e;
5438}
5439
5440
5441___HIDDENstatic ___SCMOBJlong lineeditor_output_prompt
5442 ___P((___device_tty *self),(___device_tty *self)
5443 (self)(___device_tty *self)
5444___device_tty *self;)(___device_tty *self)
5445{
5446 /*
5447 * This routine outputs the prompt that was output by the program
5448 * before line editing started.
5449 */
5450
5451 ___device_tty *d = self;
5452
5453 if (d->prompt_length < ___CAST(int,___NBELEMS(d->prompt))((int)((sizeof (d->prompt) / sizeof ((d->prompt)[0])))))
5454 return lineeditor_output (d, d->prompt, d->prompt_length);
5455
5456 return ___FIX(___NO_ERR)(((long)(0))<<2);
5457}
5458
5459
5460___HIDDENstatic ___SCMOBJlong lineeditor_move_edit_point
5461 ___P((___device_tty *self,(___device_tty *self, int pos)
5462 int pos),(___device_tty *self, int pos)
5463 (self,(___device_tty *self, int pos)
5464 pos)(___device_tty *self, int pos)
5465___device_tty *self;(___device_tty *self, int pos)
5466int pos;)(___device_tty *self, int pos)
5467{
5468 /*
5469 * Moves the editing point of the line being edited. The screen
5470 * may get scrolled in order to keep the editing point visible.
5471 */
5472
5473 ___device_tty *d = self;
5474 ___SCMOBJlong e;
5475 extensible_string *edited = &d->current.hist->edited;
5476 int cursor;
5477 int screen_nb_cols;
5478 int screen_nb_rows;
5479 int screen_size;
5480 int cursor_row;
5481 int first_row;
5482 int last_row;
5483 int scroll_rows;
5484 int all_fits;
5485 int n;
5486 int start;
5487
5488 if (pos < 0 ||
5489 pos > edited->length)
5490 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
5491
5492 screen_nb_cols = d->terminal_nb_cols;
5493 screen_nb_rows = d->terminal_nb_rows;
5494 screen_size = d->terminal_size;
5495 cursor = d->current.line_start + pos; /* new cursor position in screen */
5496
5497 cursor_row = cursor;
5498 if (cursor_row < 0)
5499 cursor_row -= screen_nb_cols - 1;
5500 cursor_row /= screen_nb_cols;
5501
5502 first_row = d->current.line_start;
5503 if (first_row < 0)
5504 first_row -= screen_nb_cols - 1;
5505 first_row /= screen_nb_cols;
5506
5507 last_row = d->current.line_start + edited->length;
5508 if (last_row < 0)
5509 last_row -= screen_nb_cols - 1;
5510 last_row /= screen_nb_cols;
5511
5512 /*
5513 * Here is an example where the edited line contains 25 characters,
5514 * the edited line starts at position 18, and pos = 11:
5515 *
5516 * +---+---+---+---+---+---+---+---+---+---+
5517 * | H | e | l | l | o | . | | | | |
5518 * +---+---+---+---+---+---+---+---+---+---+
5519 * | P | R | O | M | P | T | > | | 0 | 1 | first_row = 1
5520 * +---+---+---+---+---+---+---+---+---+---+
5521 * | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 | cursor_row = 2
5522 * +---+---+---+---+---+---+---+---+---+---+
5523 * |12 |13 |14 |15 |16 |17 |18 |19 |20 |21 |
5524 * +---+---+---+---+---+---+---+---+---+---+
5525 *
5526 * 22 23 24 last_row = 4
5527 */
5528
5529 /*
5530 * Check if the text from the cursor to the position just after end
5531 * of the edited line can all fit on the screen (while maintaining
5532 * column alignment).
5533 */
5534
5535 all_fits = (last_row - cursor_row < screen_nb_rows);
5536
5537 /*
5538 * Determine how many rows to scroll and in which direction
5539 * (scroll_rows is positive when scrolling forward and negative when
5540 * scrolling backward).
5541 */
5542
5543 if (all_fits)
5544 {
5545 /*
5546 * The region of the edited line between the cursor and end can
5547 * fit on the screen at the same time.
5548 */
5549
5550 if (cursor_row >= 0 &&
5551 last_row < screen_nb_rows)
5552 /* Don't scroll if text from cursor to end is visible right now. */
5553 scroll_rows = 0;
5554 else
5555 /* Scroll so that last row of edited line is at bottom of screen. */
5556 scroll_rows = last_row - (screen_nb_rows - 1);
5557 }
5558 else
5559 {
5560 /*
5561 * The region of the edited line between the cursor and end cannot
5562 * fit on the screen at the same time.
5563 */
5564
5565 if (cursor_row >= 0 &&
5566 cursor_row < screen_nb_rows)
5567 /* Don't scroll if cursor is visible right now. */
5568 scroll_rows = 0;
5569 else
5570 {
5571 /*
5572 * Scroll cursor row to bottom of screen unless this would
5573 * make a line before the line start visible, in which case
5574 * align the line start to the top of the screen.
5575 */
5576
5577 scroll_rows = cursor_row - (screen_nb_rows - 1);
5578
5579 if (scroll_rows < first_row)
5580 scroll_rows = first_row;
5581 }
5582 }
5583
5584 /*
5585 * Perform scrolling of screen.
5586 */
5587
5588 if (scroll_rows != 0)
5589 {
5590 cursor -= screen_nb_cols * scroll_rows;
5591
5592 if (scroll_rows < 0)
5593 {
5594 /* scroll screen backward by whole rows */
5595
5596 start = pos - cursor;
5597
5598 n = screen_size; /* write to the whole screen */
5599
5600 if ((e = lineeditor_prepare_to_write_at (d, 0))
5601 != ___FIX(___NO_ERR)(((long)(0))<<2))
5602 return e;
5603
5604 if ((e = lineeditor_output_prompt (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
5605 return e;
5606 }
5607 else
5608 {
5609 /* scroll screen forward by whole rows */
5610
5611 start = screen_size - d->current.line_start;
5612
5613 n = screen_nb_cols * scroll_rows; /* write characters that scroll in */
5614
5615 if ((e = lineeditor_prepare_to_write_at (d, screen_size))
5616 != ___FIX(___NO_ERR)(((long)(0))<<2))
5617 return e;
5618 }
5619
5620 if (!d->has_eat_newline_glitch)
5621 n--; /* to avoid wraparound at end of screen */
5622
5623 if (n > edited->length - start)
5624 n = edited->length - start;
5625
5626 if ((e = lineeditor_output_current_hist (d, start, n))
5627 != ___FIX(___NO_ERR)(((long)(0))<<2))
5628 return e;
5629 }
5630
5631 if (all_fits)
5632 if ((e = lineeditor_output_force_delayed_wrap (d))
5633 != ___FIX(___NO_ERR)(((long)(0))<<2))
5634 return e;
5635
5636 if ((e = lineeditor_move_cursor (d, cursor))
5637 != ___FIX(___NO_ERR)(((long)(0))<<2))
5638 return e;
5639
5640 d->current.edit_point = pos;
5641 d->current.completion_point = pos;
5642
5643 return ___FIX(___NO_ERR)(((long)(0))<<2);
5644}
5645
5646
5647___HIDDENstatic ___SCMOBJlong lineeditor_refresh
5648 ___P((___device_tty *self),(___device_tty *self)
5649 (self)(___device_tty *self)
5650___device_tty *self;)(___device_tty *self)
5651{
5652 ___device_tty *d = self;
5653 ___SCMOBJlong e;
5654 extensible_string *edited = &d->current.hist->edited;
5655
5656 if ((e = lineeditor_output_set_attrs
5657 (d,
5658 lineeditor_erase_attrs (d)))
5659 == ___FIX(___NO_ERR)(((long)(0))<<2))
5660 {
5661#ifdef USE_CURSES
5662
5663 if (lineeditor_cap (d, LINEEDITOR_CAP_CLEAR1) != NULL((void*)0))
5664 e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_CLEAR1, 1);
5665 else
5666
5667#endif
5668
5669 e = lineeditor_left_margin_of_next_row (d);
5670
5671 if (e == ___FIX(___NO_ERR)(((long)(0))<<2))
5672 {
5673 lineeditor_output_prompt (d); /* ignore error */
5674
5675 d->current.line_start = d->terminal_cursor;
5676
5677 if ((e = lineeditor_update_region (d, 0, edited->length))
5678 == ___FIX(___NO_ERR)(((long)(0))<<2))
5679 e = lineeditor_move_edit_point (d, d->current.edit_point);
5680 }
5681 }
5682
5683 return e;
5684}
5685
5686
5687___HIDDENstatic ___SCMOBJlong lineeditor_redraw
5688 ___P((___device_tty *self),(___device_tty *self)
5689 (self)(___device_tty *self)
5690___device_tty *self;)(___device_tty *self)
5691{
5692 ___device_tty *d = self;
5693 ___SCMOBJlong e;
5694 extensible_string *edited = &d->current.hist->edited;
5695 int prompt_start = d->current.line_start - d->prompt_length;
5696
5697 if (prompt_start < 0)
5698 prompt_start = 0;
5699
5700 if ((e = lineeditor_output_set_attrs
5701 (d,
5702 lineeditor_erase_attrs (d)))
5703 == ___FIX(___NO_ERR)(((long)(0))<<2))
5704 {
5705 if ((e = lineeditor_move_cursor (d, prompt_start)) != ___FIX(___NO_ERR)(((long)(0))<<2))
5706 return e;
5707
5708#ifdef USE_CURSES
5709
5710 if (lineeditor_cap (d, LINEEDITOR_CAP_ED15) != NULL((void*)0))
5711 e = lineeditor_output_cap0 (d, LINEEDITOR_CAP_ED15, 1);
5712
5713#endif
5714
5715 if ((e = lineeditor_output_prompt (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
5716 return e;
5717
5718 d->current.line_start = d->terminal_cursor;
5719
5720 if ((e = lineeditor_update_region (d, 0, edited->length))
5721 == ___FIX(___NO_ERR)(((long)(0))<<2))
5722 e = lineeditor_move_edit_point (d, d->current.edit_point);
5723 }
5724
5725 return e;
5726}
5727
5728
5729#define FORW_WORD0 0
5730#define BACK_WORD1 1
5731#define FORW_SEXPR2 2
5732#define BACK_SEXPR3 3
5733#define BACK_SEXPR_PAREN4 4
5734
5735___HIDDENstatic ___BOOLint lineeditor_word_boundary
5736 ___P((___device_tty *self,(___device_tty *self, int dir, int pos, int *final_pos)
5737 int dir,(___device_tty *self, int dir, int pos, int *final_pos)
5738 int pos,(___device_tty *self, int dir, int pos, int *final_pos)
5739 int *final_pos),(___device_tty *self, int dir, int pos, int *final_pos)
5740 (self,(___device_tty *self, int dir, int pos, int *final_pos)
5741 dir,(___device_tty *self, int dir, int pos, int *final_pos)
5742 pos,(___device_tty *self, int dir, int pos, int *final_pos)
5743 final_pos)(___device_tty *self, int dir, int pos, int *final_pos)
5744___device_tty *self;(___device_tty *self, int dir, int pos, int *final_pos)
5745int dir;(___device_tty *self, int dir, int pos, int *final_pos)
5746int pos;(___device_tty *self, int dir, int pos, int *final_pos)
5747int *final_pos;)(___device_tty *self, int dir, int pos, int *final_pos)
5748{
5749 ___device_tty *d = self;
5750 extensible_string *edited = &d->current.hist->edited;
5751 ___Cunsigned int *buf = edited->buffer;
5752 int len = edited->length;
5753 int depth = 0;
5754 ___Cunsigned int in_string = ___UNICODE_NUL0; /* assume not inside a string */
5755 ___Cunsigned int c;
5756
5757#define WORD_CHAR(x)((((x) >= 48) && ((x) <= 57)) || (((x) >= 97
) && ((x) <= 122)) || (((x) >= 65) && (
(x) <= 90)) || ((x) > 127))
\
5758((((x) >= ___UNICODE_048) && ((x) <= ___UNICODE_957)) || \
5759 (((x) >= ___UNICODE_LOWER_A97) && ((x) <= ___UNICODE_LOWER_Z122)) || \
5760 (((x) >= ___UNICODE_UPPER_A65) && ((x) <= ___UNICODE_UPPER_Z90)) || \
5761 ((x) > ___UNICODE_RUBOUT127))
5762
5763#define OPEN_PAREN(x)((x) == 40 || (x) == 91 || (x) == 123) \
5764((x) == ___UNICODE_LPAREN40 || \
5765 (x) == ___UNICODE_LBRACKET91 || \
5766 (x) == ___UNICODE_LBRACE123)
5767
5768#define CLOSE_PAREN(x)((x) == 41 || (x) == 93 || (x) == 125) \
5769((x) == ___UNICODE_RPAREN41 || \
5770 (x) == ___UNICODE_RBRACKET93 || \
5771 (x) == ___UNICODE_RBRACE125)
5772
5773#define STRING_DELIM(x)((x) == 34 || (x) == 124) \
5774((x) == ___UNICODE_DOUBLEQUOTE34 || (x) == ___UNICODE_VBAR124)
5775
5776#define INT_VECTOR(x)((x) == 115 || (x) == 83 || (x) == 117 || (x) == 85) \
5777((x) == ___UNICODE_LOWER_S115 || (x) == ___UNICODE_UPPER_S83 || \
5778 (x) == ___UNICODE_LOWER_U117 || (x) == ___UNICODE_UPPER_U85)
5779
5780#define FLOAT_VECTOR(x)((x) == 102 || (x) == 70) \
5781((x) == ___UNICODE_LOWER_F102 || (x) == ___UNICODE_UPPER_F70)
5782
5783 if (dir == FORW_WORD0)
5784 {
5785 while (pos < len)
5786 {
5787 c = buf[pos];
5788 if (!WORD_CHAR(c)((((c) >= 48) && ((c) <= 57)) || (((c) >= 97
) && ((c) <= 122)) || (((c) >= 65) && (
(c) <= 90)) || ((c) > 127))
)
5789 pos++;
5790 else
5791 break;
5792 }
5793
5794 while (pos < len)
5795 {
5796 c = buf[pos];
5797 if (WORD_CHAR(c)((((c) >= 48) && ((c) <= 57)) || (((c) >= 97
) && ((c) <= 122)) || (((c) >= 65) && (
(c) <= 90)) || ((c) > 127))
)
5798 pos++;
5799 else
5800 break;
5801 }
5802 }
5803 else if (dir == BACK_WORD1)
5804 {
5805 while (pos > 0)
5806 {
5807 c = buf[pos-1];
5808 if (!WORD_CHAR(c)((((c) >= 48) && ((c) <= 57)) || (((c) >= 97
) && ((c) <= 122)) || (((c) >= 65) && (
(c) <= 90)) || ((c) > 127))
)
5809 pos--;
5810 else
5811 break;
5812 }
5813
5814 while (pos > 0)
5815 {
5816 c = buf[pos-1];
5817 if (WORD_CHAR(c)((((c) >= 48) && ((c) <= 57)) || (((c) >= 97
) && ((c) <= 122)) || (((c) >= 65) && (
(c) <= 90)) || ((c) > 127))
)
5818 pos--;
5819 else
5820 break;
5821 }
5822 }
5823 else if (dir == FORW_SEXPR2)
5824 {
5825 /* skip whitespace */
5826
5827 while (pos < len)
5828 {
5829 c = buf[pos];
5830 if (c <= ___UNICODE_SPACE32)
5831 pos++;
5832 else
5833 break;
5834 }
5835
5836 /* skip standard read-macros */
5837
5838 while (pos < len)
5839 {
5840 c = buf[pos];
5841 if (c == ___UNICODE_QUOTE39)
5842 pos++;
5843 else if (c == ___UNICODE_COMMA44)
5844 {
5845 pos++;
5846 if (pos < len && buf[pos] == ___UNICODE_AT64)
5847 pos++;
5848 }
5849 else
5850 break;
5851 }
5852
5853 if (pos == len)
5854 {
5855 depth = -1; /* force error */
5856 goto done_forward;
5857 }
5858
5859 /* handle head specially */
5860
5861 c = buf[pos++];
5862
5863 if (pos < len && c == ___UNICODE_SHARP35)
5864 {
5865 /* handle #\xxx, #(...), #f32(...), etc */
5866
5867 c = buf[pos++];
5868 if (c == ___UNICODE_BACKSLASH92)
5869 {
5870 if (pos < len)
5871 pos++;
5872 }
5873 else if (OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123))
5874 depth++;
5875 else
5876 {
5877 ___BOOLint f = FLOAT_VECTOR(c)((c) == 102 || (c) == 70);
5878 if (pos < len && (f || INT_VECTOR(c)((c) == 115 || (c) == 83 || (c) == 117 || (c) == 85)))
5879 {
5880 c = buf[pos++];
5881 if ((!f && pos < len && c == ___UNICODE_856) ||
5882 (pos+1 < len &&
5883 ((!f && c == ___UNICODE_149 && buf[pos] == ___UNICODE_654) ||
5884 (c == ___UNICODE_351 && buf[pos] == ___UNICODE_250) ||
5885 (c == ___UNICODE_654 && buf[pos] == ___UNICODE_452)) &&
5886 (pos++, 1)))
5887 {
5888 c = buf[pos++];
5889 if (OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123))
5890 depth++;
5891 else
5892 pos--;
5893 }
5894 }
5895 }
5896 }
5897 else if (OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123))
5898 depth++;
5899 else if (CLOSE_PAREN(c)((c) == 41 || (c) == 93 || (c) == 125))
5900 {
5901 depth = -1; /* force error */
5902 goto done_forward;
5903 }
5904 else if (STRING_DELIM(c)((c) == 34 || (c) == 124))
5905 in_string = c;
5906
5907 while (pos < len)
5908 if (in_string == ___UNICODE_NUL0)
5909 {
5910 c = buf[pos];
5911
5912 if (c == ___UNICODE_SHARP35)
5913 {
5914 if (pos+2 < len && buf[pos+1] == ___UNICODE_BACKSLASH92)
5915 pos += 2;
5916 }
5917 else if (c <= ___UNICODE_SPACE32 ||
5918 c == ___UNICODE_SEMICOLON59 ||
5919 c == ___UNICODE_QUOTE39 ||
5920 c == ___UNICODE_COMMA44)
5921 {
5922 if (depth == 0)
5923 break;
5924 }
5925 else if (OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123))
5926 {
5927 if (depth == 0)
5928 break;
5929 depth++;
5930 }
5931 else if (CLOSE_PAREN(c)((c) == 41 || (c) == 93 || (c) == 125))
5932 {
5933 if (depth == 0)
5934 break;
5935 depth--;
5936 if (depth == 0)
5937 {
5938 pos++;
5939 break;
5940 }
5941 }
5942 else if (STRING_DELIM(c)((c) == 34 || (c) == 124))
5943 {
5944 if (depth == 0)
5945 break;
5946 in_string = c;
5947 }
5948
5949 pos++;
5950 }
5951 else
5952 {
5953 c = buf[pos++];
5954
5955 if (c == ___UNICODE_BACKSLASH92) /* character is escaped */
5956 {
5957 if (pos < len)
5958 pos++;
5959 }
5960 else if (c == in_string) /* end of string reached */
5961 {
5962 if (depth == 0)
5963 break;
5964 in_string = ___UNICODE_NUL0;
5965 }
5966 }
5967
5968 done_forward:;
5969 }
5970 else
5971 {
5972 /* skip whitespace */
5973
5974 while (pos > 0)
5975 {
5976 c = buf[pos-1];
5977 if (c <= ___UNICODE_SPACE32)
5978 pos--;
5979 else
5980 break;
5981 }
5982
5983 if (pos == 0)
5984 {
5985 depth = -1; /* force error */
5986 goto done_backward;
5987 }
5988
5989 /* handle tail specially */
5990
5991 c = buf[--pos];
5992
5993 if (pos >= 2 &&
5994 buf[pos-2] == ___UNICODE_SHARP35 &&
5995 buf[pos-1] == ___UNICODE_BACKSLASH92)
5996 pos -= 2;
5997 else if (OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123))
5998 {
5999 depth = -1; /* force error */
6000 goto done_backward;
6001 }
6002 else if (CLOSE_PAREN(c)((c) == 41 || (c) == 93 || (c) == 125))
6003 depth++;
6004 else if (STRING_DELIM(c)((c) == 34 || (c) == 124))
6005 in_string = c;
6006 else if (c == ___UNICODE_QUOTE39 ||
6007 c == ___UNICODE_COMMA44 ||
6008 (pos >= 1 && c == ___UNICODE_AT64 && buf[pos-1] == ___UNICODE_COMMA44))
6009 {
6010 pos++;
6011 goto skip_read_macros;
6012 }
6013
6014 while (pos > 0)
6015 if (in_string == ___UNICODE_NUL0)
6016 {
6017 c = buf[pos-1];
6018
6019 if (pos >= 3 &&
6020 buf[pos-3] == ___UNICODE_SHARP35 &&
6021 buf[pos-2] == ___UNICODE_BACKSLASH92)
6022 pos -= 2;
6023 else if (c <= ___UNICODE_SPACE32 ||
6024 c == ___UNICODE_SEMICOLON59 ||
6025 c == ___UNICODE_QUOTE39 ||
6026 c == ___UNICODE_COMMA44)
6027 {
6028 if (depth == 0)
6029 break;
6030 }
6031 else if (pos >= 2 &&
6032 c == ___UNICODE_AT64 &&
6033 buf[pos-2] == ___UNICODE_COMMA44)
6034 {
6035 if (depth == 0)
6036 break;
6037 pos--;
6038 }
6039 else if (OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123))
6040 {
6041 if (depth == 0)
6042 break;
6043 depth--;
6044 if (depth == 0)
6045 {
6046 pos--;
6047 break;
6048 }
6049 }
6050 else if (CLOSE_PAREN(c)((c) == 41 || (c) == 93 || (c) == 125))
6051 {
6052 if (depth == 0)
6053 break;
6054 depth++;
6055 }
6056 else if (STRING_DELIM(c)((c) == 34 || (c) == 124))
6057 {
6058 if (depth == 0)
6059 break;
6060 in_string = c;
6061 }
6062
6063 pos--;
6064 }
6065 else
6066 {
6067 int i;
6068
6069 i = --pos;
6070
6071 while (i > 0 &&
6072 buf[i-1] == ___UNICODE_BACKSLASH92) /* find nb of backslashes */
6073 i--;
6074
6075 if ((pos-i) & 1) /* character is escaped */
6076 pos = i;
6077 else if (buf[pos] == in_string) /* beginning of string reached */
6078 {
6079 if (depth == 0)
6080 break;
6081 in_string = ___UNICODE_NUL0;
6082 }
6083 }
6084
6085 done_backward:;
6086
6087 if (dir == BACK_SEXPR3)
6088 {
6089 /* handle #(...), #f32(...), etc */
6090
6091 if (pos < len)
6092 {
6093 c = buf[pos];
6094 if (OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123))
6095 {
6096 if (pos >= 1 && buf[pos-1] == ___UNICODE_SHARP35)
6097 pos--;
6098 else if (pos >= 3 && buf[pos-3] == ___UNICODE_SHARP35)
6099 {
6100 c = buf[pos-2];
6101 if (INT_VECTOR(c)((c) == 115 || (c) == 83 || (c) == 117 || (c) == 85) && buf[pos-1] == ___UNICODE_856)
6102 pos -= 3;
6103 }
6104 else if (pos >= 4 && buf[pos-4] == ___UNICODE_SHARP35)
6105 {
6106 ___BOOLint f;
6107 c = buf[pos-3];
6108 f = FLOAT_VECTOR(c)((c) == 102 || (c) == 70);
6109 if (f || INT_VECTOR(c)((c) == 115 || (c) == 83 || (c) == 117 || (c) == 85))
6110 {
6111 c = buf[pos-2];
6112 if ((!f &&
6113 c == ___UNICODE_149 &&
6114 buf[pos-1] == ___UNICODE_654) ||
6115 (c == ___UNICODE_351 && buf[pos-1] == ___UNICODE_250) ||
6116 (c == ___UNICODE_654 && buf[pos-1] == ___UNICODE_452))
6117 pos -= 4;
6118 }
6119 }
6120 }
6121 }
6122
6123 /* skip standard read-macros */
6124
6125 skip_read_macros:
6126
6127 while (pos > 0)
6128 {
6129 c = buf[pos-1];
6130 if (c == ___UNICODE_QUOTE39 || c == ___UNICODE_COMMA44)
6131 pos--;
6132 else if (pos >= 2 &&
6133 c == ___UNICODE_AT64 &&
6134 buf[pos-2] == ___UNICODE_COMMA44)
6135 pos -= 2;
6136 else
6137 break;
6138 }
6139 }
6140 }
6141
6142 *final_pos = pos;
6143
6144 return (depth == 0 && in_string == ___UNICODE_NUL0);
6145}
6146
6147
6148___HIDDENstatic ___SCMOBJlong lineeditor_delete_then_insert_chars
6149 ___P((___device_tty *self,(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6150 int pos,(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6151 ___BOOL copy_to_clipboard,(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6152 ___C *buf,(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6153 int len),(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6154 (self,(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6155 pos,(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6156 copy_to_clipboard,(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6157 buf,(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6158 len)(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6159___device_tty *self;(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6160int pos;(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6161___BOOL copy_to_clipboard;(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6162___C *buf;(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6163int len;)(___device_tty *self, int pos, int copy_to_clipboard, unsigned
int *buf, int len)
6164{
6165 ___device_tty *d = self;
6166 ___SCMOBJlong e;
6167 extensible_string *edited = &d->current.hist->edited;
6168 int edit_point;
6169 int end;
6170 int n;
6171 int open_paren_point;
6172 ___Cunsigned int c;
6173
6174 if (pos < 0 ||
6175 pos > edited->length ||
6176 len < 0)
6177 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
6178
6179 if (pos < d->current.edit_point)
6180 {
6181 edit_point = pos;
6182 end = d->current.edit_point;
6183 }
6184 else
6185 {
6186 edit_point = d->current.edit_point;
6187 end = pos;
6188 }
6189
6190 n = end - edit_point; /* number of characters to delete */
6191
6192 if (n > 0)
6193 {
6194 if (copy_to_clipboard &&
6195 ((e = lineeditor_copy_to_clipboard
6196 (d,
6197 &edited->buffer[edit_point],
6198 n))
6199 != ___FIX(___NO_ERR)(((long)(0))<<2)))
6200 return e;
6201
6202 extensible_string_delete (edited, edit_point, n);
6203 }
6204
6205 if ((e = extensible_string_insert (edited, edit_point, len, buf))
6206 != ___FIX(___NO_ERR)(((long)(0))<<2))
6207 return e;
6208
6209 if (d->current.mark_point >= end)
6210 d->current.mark_point += len - n;
6211 else if (d->current.mark_point >= edit_point+len)
6212 d->current.mark_point = edit_point+len;
6213
6214 if ((e = lineeditor_update_region
6215 (d,
6216 edit_point,
6217 (len > n) ? edited->length : edited->length - len + n))
6218 != ___FIX(___NO_ERR)(((long)(0))<<2))
6219 return e;
6220
6221 edit_point += len;
6222
6223 if (len > 0 &&
6224 d->paren_balance_duration_nsecs > 0 &&
6225 !lineeditor_read_ready (d) &&
6226 (c = buf[len-1], CLOSE_PAREN(c)((c) == 41 || (c) == 93 || (c) == 125)) &&
6227 lineeditor_word_boundary (d, BACK_SEXPR_PAREN4, edit_point, &open_paren_point) &&
6228 (c = edited->buffer[open_paren_point], OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123)))
6229 {
6230 if ((e = lineeditor_move_edit_point (d, open_paren_point))
6231 == ___FIX(___NO_ERR)(((long)(0))<<2))
6232 {
6233 lineeditor_output_drain (d); /* ignore error */
6234
6235 d->current.edit_point = edit_point;
6236 d->current.completion_point = edit_point;
6237 d->current.paren_balance_trigger = 1;
6238 }
6239 }
6240 else
6241 e = lineeditor_move_edit_point (d, edit_point);
6242
6243 return e;
6244}
6245
6246
6247___HIDDENstatic ___SCMOBJlong lineeditor_insert_chars
6248 ___P((___device_tty *self,(___device_tty *self, unsigned int *buf, int len)
6249 ___C *buf,(___device_tty *self, unsigned int *buf, int len)
6250 int len),(___device_tty *self, unsigned int *buf, int len)
6251 (self,(___device_tty *self, unsigned int *buf, int len)
6252 buf,(___device_tty *self, unsigned int *buf, int len)
6253 len)(___device_tty *self, unsigned int *buf, int len)
6254___device_tty *self;(___device_tty *self, unsigned int *buf, int len)
6255___C *buf;(___device_tty *self, unsigned int *buf, int len)
6256int len;)(___device_tty *self, unsigned int *buf, int len)
6257{
6258 ___device_tty *d = self;
6259
6260#if 1
6261
6262 if (len > 0)
6263 return lineeditor_delete_then_insert_chars
6264 (d,
6265 d->current.edit_point,
6266 0,
6267 buf,
6268 len);
6269
6270 return ___FIX(___NO_ERR)(((long)(0))<<2);
6271
6272#else
6273
6274 ___SCMOBJlong e;
6275 extensible_string *edited = &d->current.hist->edited;
6276 int edit_point = d->current.edit_point;
6277 int open_paren_point;
6278 ___Cunsigned int c;
6279
6280 if (len <= 0)
6281 return ___FIX(___NO_ERR)(((long)(0))<<2);
6282
6283 if ((e = extensible_string_insert (edited, edit_point, len, buf))
6284 != ___FIX(___NO_ERR)(((long)(0))<<2))
6285 return e;
6286
6287 if (d->current.mark_point > edit_point)
6288 d->current.mark_point += len;
6289
6290 if ((e = lineeditor_update_region (d, edit_point, edited->length))
6291 != ___FIX(___NO_ERR)(((long)(0))<<2))
6292 return e;
6293
6294 edit_point += len;
6295
6296 if (d->paren_balance_duration_nsecs > 0 &&
6297 !lineeditor_read_ready (d) &&
6298 (c = buf[len-1], CLOSE_PAREN(c)((c) == 41 || (c) == 93 || (c) == 125)) &&
6299 lineeditor_word_boundary (d, BACK_SEXPR_PAREN4, edit_point, &open_paren_point) &&
6300 (c = edited->buffer[open_paren_point], OPEN_PAREN(c)((c) == 40 || (c) == 91 || (c) == 123)))
6301 {
6302 if ((e = lineeditor_move_edit_point (d, open_paren_point))
6303 != ___FIX(___NO_ERR)(((long)(0))<<2))
6304 return e;
6305
6306 lineeditor_output_drain (d); /* ignore error */
6307
6308 d->current.edit_point = edit_point;
6309 d->current.completion_point = edit_point;
6310 d->current.paren_balance_trigger = 1;
6311
6312 return ___FIX(___NO_ERR)(((long)(0))<<2);
6313 }
6314
6315 return lineeditor_move_edit_point (d, edit_point);
6316#endif
6317}
6318
6319
6320___HIDDENstatic ___SCMOBJlong lineeditor_delete_chars
6321 ___P((___device_tty *self,(___device_tty *self, int pos, int copy_to_clipboard)
6322 int pos,(___device_tty *self, int pos, int copy_to_clipboard)
6323 ___BOOL copy_to_clipboard),(___device_tty *self, int pos, int copy_to_clipboard)
6324 (self,(___device_tty *self, int pos, int copy_to_clipboard)
6325 pos,(___device_tty *self, int pos, int copy_to_clipboard)
6326 copy_to_clipboard)(___device_tty *self, int pos, int copy_to_clipboard)
6327___device_tty *self;(___device_tty *self, int pos, int copy_to_clipboard)
6328int pos;(___device_tty *self, int pos, int copy_to_clipboard)
6329___BOOL copy_to_clipboard;)(___device_tty *self, int pos, int copy_to_clipboard)
6330{
6331 ___device_tty *d = self;
6332
6333#if 1
6334
6335 return lineeditor_delete_then_insert_chars
6336 (d,
6337 pos,
6338 copy_to_clipboard,
6339 NULL((void*)0),
6340 0);
6341
6342#else
6343
6344 ___SCMOBJlong e;
6345 extensible_string *edited = &d->current.hist->edited;
6346 int start;
6347 int end;
6348 int n;
6349
6350 if (pos < 0 ||
6351 pos > edited->length)
6352 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
6353
6354 if (pos < d->current.edit_point)
6355 {
6356 start = pos;
6357 end = d->current.edit_point;
6358 }
6359 else
6360 {
6361 start = d->current.edit_point;
6362 end = pos;
6363 }
6364
6365 n = end - start;
6366
6367 if (n == 0)
6368 return ___FIX(___NO_ERR)(((long)(0))<<2);
6369
6370 if (copy_to_clipboard &&
6371 ((e = lineeditor_copy_to_clipboard (d, &edited->buffer[start], n))
6372 != ___FIX(___NO_ERR)(((long)(0))<<2)))
6373 return e;
6374
6375 extensible_string_delete (edited, start, n);
6376
6377 if (d->current.mark_point >= start)
6378 {
6379 if (d->current.mark_point >= end)
6380 d->current.mark_point -= n;
6381 else
6382 d->current.mark_point = start;
6383 }
6384
6385 if ((e = lineeditor_update_region (d, start, edited->length + n))
6386 != ___FIX(___NO_ERR)(((long)(0))<<2))
6387 return e;
6388
6389 return lineeditor_move_edit_point (d, start);
6390#endif
6391}
6392
6393
6394___HIDDENstatic void lineeditor_rotate_left_chars
6395 ___P((___device_tty *self,(___device_tty *self, int start, int end, int n)
6396 int start,(___device_tty *self, int start, int end, int n)
6397 int end,(___device_tty *self, int start, int end, int n)
6398 int n),(___device_tty *self, int start, int end, int n)
6399 (self,(___device_tty *self, int start, int end, int n)
6400 start,(___device_tty *self, int start, int end, int n)
6401 end,(___device_tty *self, int start, int end, int n)
6402 n)(___device_tty *self, int start, int end, int n)
6403___device_tty *self;(___device_tty *self, int start, int end, int n)
6404int start;(___device_tty *self, int start, int end, int n)
6405int end;(___device_tty *self, int start, int end, int n)
6406int n;)(___device_tty *self, int start, int end, int n)
6407{
6408 ___device_tty *d = self;
6409 extensible_string *edited = &d->current.hist->edited;
6410 ___Cunsigned int *p = &edited->buffer[start];
6411 ___Cunsigned int temp;
6412 int len = end-start;
6413 int left = len;
6414 int i;
6415 int j;
6416 int k;
6417
6418 i = 0;
6419 while (left > 0)
6420 {
6421 temp = p[i];
6422 j = i;
6423 k = (j+n) % len;
6424 left--;
6425 while (k != i)
6426 {
6427 p[j] = p[k];
6428 j = k;
6429 k = (j+n) % len;
6430 left--;
6431 }
6432 p[j] = temp;
6433 i++;
6434 }
6435}
6436
6437
6438___HIDDENstatic ___SCMOBJlong lineeditor_transpose_chars
6439 ___P((___device_tty *self,(___device_tty *self, int start1, int end1, int start2, int end2
)
6440 int start1,(___device_tty *self, int start1, int end1, int start2, int end2
)
6441 int end1,(___device_tty *self, int start1, int end1, int start2, int end2
)
6442 int start2,(___device_tty *self, int start1, int end1, int start2, int end2
)
6443 int end2),(___device_tty *self, int start1, int end1, int start2, int end2
)
6444 (self,(___device_tty *self, int start1, int end1, int start2, int end2
)
6445 start1,(___device_tty *self, int start1, int end1, int start2, int end2
)
6446 end1,(___device_tty *self, int start1, int end1, int start2, int end2
)
6447 start2,(___device_tty *self, int start1, int end1, int start2, int end2
)
6448 end2)(___device_tty *self, int start1, int end1, int start2, int end2
)
6449___device_tty *self;(___device_tty *self, int start1, int end1, int start2, int end2
)
6450int start1;(___device_tty *self, int start1, int end1, int start2, int end2
)
6451int end1;(___device_tty *self, int start1, int end1, int start2, int end2
)
6452int start2;(___device_tty *self, int start1, int end1, int start2, int end2
)
6453int end2;)(___device_tty *self, int start1, int end1, int start2, int end2
)
6454{
6455 ___device_tty *d = self;
6456 ___SCMOBJlong e;
6457
6458 if (start1 > end1 ||
6459 end1 > start2 ||
6460 start2 > end2)
6461 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
6462
6463 lineeditor_rotate_left_chars
6464 (d,
6465 start1,
6466 end2,
6467 end1-start1);
6468
6469 lineeditor_rotate_left_chars
6470 (d,
6471 start1,
6472 end2-(end1-start1),
6473 start2-end1);
6474
6475 if ((e = lineeditor_update_region (d, start1, end2))
6476 != ___FIX(___NO_ERR)(((long)(0))<<2))
6477 return e;
6478
6479 return lineeditor_move_edit_point (d, end2);
6480}
6481
6482
6483typedef struct
6484 {
6485 extensible_string *buf;
6486 int word_start;
6487 int completion_point;
6488 int word_end;
6489 ___SCMOBJlong next;
6490 int common_length;
6491 } visit_symbol_data;
6492
6493
6494___HIDDENstatic void visit_symbol
6495 ___P((___SCMOBJ sym,(long sym, void *data)
6496 void *data),(long sym, void *data)
6497 (sym,(long sym, void *data)
6498 data)(long sym, void *data)
6499___SCMOBJ sym;(long sym, void *data)
6500void *data;)(long sym, void *data)
6501{
6502 visit_symbol_data *dat = ___CAST(visit_symbol_data*,data)((visit_symbol_data*)(data));
6503 ___SCMOBJlong name = ___FIELD(sym,___SYMKEY_NAME)(*((((long*)((sym)-(1)))+1)+0));
6504 int n = ___INT(___STRINGLENGTH(name))(((((long)(((((unsigned long)((*((long*)((name)-(1))))))>>
(3 +5))>>2)))<<2))>>2)
;
6505 int word_start = dat->word_start;
6506 int prefix = dat->completion_point - word_start;
6507 int len = dat->word_end - word_start;
6508 int i = 0;
6509
6510 if (n <= prefix)
6511 return;
6512
6513 for (i=0; i<prefix; i++)
6514 {
6515 ___Cunsigned int c1 = ___INT(___STRINGREF(name,___FIX(i)))((((((long)(((unsigned int)(*(((unsigned int*)((((long*)((name
)-(1)))+1)))+(((((long)(i))<<2))>>2))))))<<
2)+2))>>2)
;
6516 ___Cunsigned int c2 = dat->buf->buffer[word_start+i];
6517 if (c1 != c2)
6518 return;
6519 }
6520
6521 while (i < n)
6522 {
6523 if (i < len)
6524 {
6525 ___Cunsigned int c1 = ___INT(___STRINGREF(name,___FIX(i)))((((((long)(((unsigned int)(*(((unsigned int*)((((long*)((name
)-(1)))+1)))+(((((long)(i))<<2))>>2))))))<<
2)+2))>>2)
;
6526 ___Cunsigned int c2 = dat->buf->buffer[word_start+i];
6527 if (c1 < c2)
6528 return;
6529 if (c1 > c2)
6530 goto found;
6531 }
6532 else
6533 goto found;
6534 i++;
6535 }
6536
6537 return;
6538
6539 found:
6540
6541 if (dat->next == ___FAL((((long)(-1))<<2)+2))
6542 {
6543 dat->next = sym;
6544 dat->common_length = n;
6545 }
6546 else
6547 {
6548 ___SCMOBJlong name2 = ___FIELD(dat->next,___SYMKEY_NAME)(*((((long*)((dat->next)-(1)))+1)+0));
6549 int n2 = ___INT(___STRINGLENGTH(name2))(((((long)(((((unsigned long)((*((long*)((name2)-(1))))))>>
(3 +5))>>2)))<<2))>>2)
;
6550 i = 0;
6551 while (i < n)
6552 {
6553 if (i < n2)
6554 {
6555 ___Cunsigned int c1 = ___INT(___STRINGREF(name,___FIX(i)))((((((long)(((unsigned int)(*(((unsigned int*)((((long*)((name
)-(1)))+1)))+(((((long)(i))<<2))>>2))))))<<
2)+2))>>2)
;
6556 ___Cunsigned int c2 = ___INT(___STRINGREF(name2,___FIX(i)))((((((long)(((unsigned int)(*(((unsigned int*)((((long*)((name2
)-(1)))+1)))+(((((long)(i))<<2))>>2))))))<<
2)+2))>>2)
;
6557 if (c1 < c2)
6558 goto found2;
6559 if (c1 > c2)
6560 goto done;
6561 }
6562 else
6563 goto done;
6564 i++;
6565 }
6566 found2:
6567 dat->next = sym;
6568 done:
6569 dat->common_length = i;
6570 }
6571}
6572
6573
6574___HIDDENstatic int complete_word
6575 ___P((extensible_string *buf,(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6576 int word_start,(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6577 int completion_point,(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6578 int word_end,(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6579 extensible_string *completion),(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6580 (buf,(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6581 word_start,(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6582 completion_point,(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6583 word_end,(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6584 completion)(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6585extensible_string *buf;(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6586int word_start;(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6587int completion_point;(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6588int word_end;(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6589extensible_string *completion;)(extensible_string *buf, int word_start, int completion_point
, int word_end, extensible_string *completion)
6590{
6591#define FOUND_COMPLETION0 0
6592#define NO_COMPLETION1 1
6593#define CANNOT_COMPLETE2 2
6594
6595 visit_symbol_data dat;
6596
6597 if (completion_point <= word_start)
6598 return NO_COMPLETION1;
6599
6600 dat.buf = buf;
6601 dat.word_start = word_start;
6602 dat.completion_point = completion_point;
6603 dat.word_end = word_end;
6604 dat.next = ___FAL((((long)(-1))<<2)+2);
6605 dat.common_length = 0;
6606
6607 ___for_each_symkey (___sSYMBOL8, visit_symbol, ___CAST(void*,&dat)((void*)(&dat)));
6608
6609 if (dat.next != ___FAL((((long)(-1))<<2)+2))
6610 {
6611 ___SCMOBJlong name = ___FIELD(dat.next,___SYMKEY_NAME)(*((((long*)((dat.next)-(1)))+1)+0));
6612 int n = ___INT(___STRINGLENGTH(name))(((((long)(((((unsigned long)((*((long*)((name)-(1))))))>>
(3 +5))>>2)))<<2))>>2)
;
6613 int i;
6614
6615#define USE_EMACS_COMPLETION
6616
6617#ifdef USE_EMACS_COMPLETION
6618 if (dat.common_length > word_end - word_start)
6619 n = dat.common_length;
6620#endif
6621
6622 if (extensible_string_setup (completion, n) != ___FIX(___NO_ERR)(((long)(0))<<2))
6623 return CANNOT_COMPLETE2;
6624
6625 for (i=0; i<n; i++)
6626 {
6627 ___Cunsigned int c = ___INT(___STRINGREF(name,___FIX(i)))((((((long)(((unsigned int)(*(((unsigned int*)((((long*)((name
)-(1)))+1)))+(((((long)(i))<<2))>>2))))))<<
2)+2))>>2)
;
6628 if (extensible_string_insert_at_end (completion, 1, &c)
6629 != ___FIX(___NO_ERR)(((long)(0))<<2))
6630 {
6631 extensible_string_cleanup (completion);
6632 return CANNOT_COMPLETE2;
6633 }
6634 }
6635 return FOUND_COMPLETION0;
6636 }
6637
6638 return NO_COMPLETION1;
6639}
6640
6641
6642___HIDDENstatic ___SCMOBJlong lineeditor_word_completion
6643 ___P((___device_tty *self),(___device_tty *self)
6644 (self)(___device_tty *self)
6645___device_tty *self;)(___device_tty *self)
6646{
6647 /*
6648 * Complete current word.
6649 */
6650
6651 ___device_tty *d = self;
6652 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
6653 int word_start;
6654 int completion_point;
6655 extensible_string completion;
6656
6657 completion_point = d->current.completion_point;
6658
6659 if (!lineeditor_word_boundary (d, BACK_SEXPR_PAREN4, completion_point, &word_start))
6660 word_start = completion_point;
6661
6662 switch (complete_word (&d->current.hist->edited,
6663 word_start,
6664 completion_point,
6665 d->current.edit_point,
6666 &completion))
6667 {
6668 case FOUND_COMPLETION0:
6669 e = lineeditor_delete_then_insert_chars
6670 (d,
6671 word_start,
6672 0,
6673 completion.buffer,
6674 completion.length);
6675 extensible_string_cleanup (&completion);
6676 break;
6677
6678 case NO_COMPLETION1:
6679 if ((e = lineeditor_delete_then_insert_chars
6680 (d,
6681 completion_point,
6682 0,
6683 NULL((void*)0),
6684 0))
6685 == ___FIX(___NO_ERR)(((long)(0))<<2))
6686 e = lineeditor_output_char_repetition
6687 (d,
6688 ___UNICODE_BELL7,
6689 1,
6690 d->output_attrs);
6691 break;
6692
6693 case CANNOT_COMPLETE2:
6694 default:
6695 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
6696 }
6697
6698 d->current.completion_point = completion_point;
6699
6700 return e;
6701}
6702
6703
6704___HIDDENstatic ___SCMOBJlong lineeditor_move_history
6705 ___P((___device_tty *self,(___device_tty *self, lineeditor_history *h)
6706 lineeditor_history *h),(___device_tty *self, lineeditor_history *h)
6707 (self,(___device_tty *self, lineeditor_history *h)
6708 h)(___device_tty *self, lineeditor_history *h)
6709___device_tty *self;(___device_tty *self, lineeditor_history *h)
6710lineeditor_history *h;)(___device_tty *self, lineeditor_history *h)
6711{
6712 ___device_tty *d = self;
6713 ___SCMOBJlong e;
6714 int old_length;
6715 int new_length;
6716
6717 if ((e = lineeditor_history_begin_edit (d, h))
6718 != ___FIX(___NO_ERR)(((long)(0))<<2))
6719 return e;
6720
6721 if ((e = lineeditor_move_edit_point (d, 0))
6722 != ___FIX(___NO_ERR)(((long)(0))<<2))
6723 return e;
6724
6725 old_length = d->current.hist->edited.length;
6726 new_length = h->edited.length;
6727
6728 d->current.mark_point = 0;
6729 d->current.hist = h;
6730
6731 if ((e = lineeditor_update_region
6732 (d,
6733 0,
6734 (new_length > old_length) ? new_length : old_length))
6735 != ___FIX(___NO_ERR)(((long)(0))<<2))
6736 return e;
6737
6738 return lineeditor_move_edit_point (d, new_length);
6739}
6740
6741
6742___HIDDENstatic ___SCMOBJlong lineeditor_move_history_relative
6743 ___P((___device_tty *self,(___device_tty *self, int back)
6744 ___BOOL back),(___device_tty *self, int back)
6745 (self,(___device_tty *self, int back)
6746 back)(___device_tty *self, int back)
6747___device_tty *self;(___device_tty *self, int back)
6748___BOOL back;)(___device_tty *self, int back)
6749{
6750 ___device_tty *d = self;
6751 lineeditor_history *h;
6752 lineeditor_history *limit;
6753
6754 if (back)
6755 {
6756 h = d->current.hist->prev;
6757 limit = d->hist_last;
6758 }
6759 else
6760 {
6761 h = d->current.hist->next;
6762 limit = d->hist_last->next;
6763 }
6764
6765 if (h == limit)
6766 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
6767
6768 return lineeditor_move_history (d, h);
6769}
6770
6771
6772___HIDDENstatic ___SCMOBJlong lineeditor_line_done
6773 ___P((___device_tty *self,(___device_tty *self, int end_of_file)
6774 ___BOOL end_of_file),(___device_tty *self, int end_of_file)
6775 (self,(___device_tty *self, int end_of_file)
6776 end_of_file)(___device_tty *self, int end_of_file)
6777___device_tty *self;(___device_tty *self, int end_of_file)
6778___BOOL end_of_file;)(___device_tty *self, int end_of_file)
6779{
6780 ___device_tty *d = self;
6781 ___SCMOBJlong e;
6782 extensible_string *edited = &d->current.hist->edited;
6783 extensible_string *input_line = &d->input_line;
6784
6785 /*
6786 * Transfer the current edited line to the input.
6787 */
6788
6789 if (input_line->buffer == NULL((void*)0))
6790 {
6791 d->input_line_lo = 0;
6792
6793 if ((e = extensible_string_copy
6794 (edited->buffer,
6795 edited->length,
6796 input_line,
6797 1))
6798 != ___FIX(___NO_ERR)(((long)(0))<<2))
6799 return e;
6800
6801 if (!end_of_file)
6802 {
6803 int old_length = input_line->length;
6804 if ((e = extensible_string_set_length (input_line, old_length+1, 0))
6805 != ___FIX(___NO_ERR)(((long)(0))<<2))
6806 {
6807 extensible_string_cleanup (input_line);
6808 d->input_line.buffer = NULL((void*)0);
6809 return e;
6810 }
6811 input_line->buffer[old_length] = char_EOL10;
6812 }
6813 }
6814
6815 /*
6816 * Update history (empty lines are not added).
6817 */
6818
6819 if (edited->length == 0)
6820 {
6821 if ((e = lineeditor_move_edit_point (d, edited->length))
6822 == ___FIX(___NO_ERR)(((long)(0))<<2) &&
6823 (end_of_file ||
6824 (e = lineeditor_newline (d))
6825 == ___FIX(___NO_ERR)(((long)(0))<<2)))
6826 extensible_string_set_length
6827 (&d->hist_last->edited,
6828 0,
6829 1); /* ignore error */
6830 }
6831 else
6832 {
6833 /*
6834 * Make a copy of the current edited line for the history.
6835 */
6836
6837 extensible_string actual;
6838
6839 if ((e = extensible_string_copy
6840 (edited->buffer,
6841 edited->length,
6842 &actual,
6843 0))
6844 == ___FIX(___NO_ERR)(((long)(0))<<2))
6845 {
6846 /*
6847 * Add the current edited line to the history.
6848 */
6849
6850 lineeditor_history *next_line;
6851
6852 if ((e = lineeditor_history_setup (d, &next_line))
6853 == ___FIX(___NO_ERR)(((long)(0))<<2))
6854 {
6855 if ((e = lineeditor_history_begin_edit (d, next_line))
6856 == ___FIX(___NO_ERR)(((long)(0))<<2) &&
6857 (e = lineeditor_move_edit_point (d, edited->length))
6858 == ___FIX(___NO_ERR)(((long)(0))<<2) &&
6859 (e = lineeditor_newline (d))
6860 == ___FIX(___NO_ERR)(((long)(0))<<2))
6861 {
6862 extensible_string_cleanup (&d->hist_last->actual);
6863 d->hist_last->actual = actual;
6864 lineeditor_history_add_last (d, next_line);
6865 lineeditor_history_trim (d);
6866 }
6867 else
6868 lineeditor_history_cleanup (d, next_line); /* ignore error */
6869 }
6870
6871 if (e != ___FIX(___NO_ERR)(((long)(0))<<2))
6872 extensible_string_cleanup (&actual);
6873 }
6874 }
6875
6876 if (e == ___FIX(___NO_ERR)(((long)(0))<<2))
6877 {
6878 /*
6879 * Revert history lines to their nonedited state.
6880 */
6881
6882 lineeditor_history *h = d->hist_last;
6883
6884 for (;;)
6885 {
6886 h = h->prev;
6887 if (h == d->hist_last)
6888 break;
6889 lineeditor_history_end_edit (d, h);
6890 }
6891
6892 /*
6893 * Prepare editing of next line.
6894 */
6895
6896 d->editing_line = 0;
6897 d->prompt_length = 0;
6898 }
6899
6900 return e;
6901}
6902
6903
6904___HIDDENstatic ___SCMOBJlong lineeditor_end_paren_balance
6905 ___P((___device_tty *self),(___device_tty *self)
6906 (self)(___device_tty *self)
6907___device_tty *self;)(___device_tty *self)
6908{
6909 ___device_tty *d = self;
6910
6911 if (d->current.paren_balance_in_progress)
6912 {
6913 d->current.paren_balance_in_progress = 0;
6914 if (d->editing_line)
6915 return lineeditor_move_edit_point
6916 (d,
6917 d->current.edit_point);
6918 }
6919
6920 return ___FIX(___NO_ERR)(((long)(0))<<2);
6921}
6922
6923
6924___HIDDENstatic ___SCMOBJlong lineeditor_process_single_event
6925 ___P((___device_tty *self,(___device_tty *self, lineeditor_event *ev)
6926 lineeditor_event *ev),(___device_tty *self, lineeditor_event *ev)
6927 (self,(___device_tty *self, lineeditor_event *ev)
6928 ev)(___device_tty *self, lineeditor_event *ev)
6929___device_tty *self;(___device_tty *self, lineeditor_event *ev)
6930lineeditor_event *ev;)(___device_tty *self, lineeditor_event *ev)
6931{
6932 ___device_tty *d = self;
6933 extensible_string *edited = &d->current.hist->edited;
6934
6935 switch (ev->event_kind)
6936 {
6937 case LINEEDITOR_EV_NONE0:
6938 return ___FIX(___NO_ERR)(((long)(0))<<2);
6939
6940 case LINEEDITOR_EV_KEY1:
6941 if (ev->event_char < ___UNICODE_SPACE32 || /* discard control characters */
6942 ev->event_char == ___UNICODE_RUBOUT127)
6943 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
6944 return lineeditor_insert_chars (d, &ev->event_char, 1);
6945
6946 case LINEEDITOR_EV_RETURN2:
6947 return lineeditor_line_done (d, 0);
6948
6949 case LINEEDITOR_EV_BACK3:
6950 return lineeditor_delete_chars (d, d->current.edit_point-1, 0);
6951
6952 case LINEEDITOR_EV_BACK_WORD4:
6953 case LINEEDITOR_EV_BACK_SEXPR5:
6954 {
6955 int i;
6956 int dir = (ev->event_kind == LINEEDITOR_EV_BACK_WORD4)
6957 ? BACK_WORD1
6958 : BACK_SEXPR3;
6959 if (!lineeditor_word_boundary (d, dir, d->current.edit_point, &i))
6960 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
6961 return lineeditor_delete_chars (d, i, 1);
6962 }
6963
6964 case LINEEDITOR_EV_TAB6:
6965 return lineeditor_word_completion (d);
6966
6967 case LINEEDITOR_EV_MARK7:
6968 d->current.mark_point = d->current.edit_point;
6969 return ___FIX(___NO_ERR)(((long)(0))<<2);
6970
6971 case LINEEDITOR_EV_PASTE8:
6972 return lineeditor_paste_from_clipboard (d);
6973
6974 case LINEEDITOR_EV_CUT9:
6975 return lineeditor_delete_chars (d, d->current.mark_point, 1);
6976
6977 case LINEEDITOR_EV_CUT_RIGHT10:
6978 return lineeditor_delete_chars (d, edited->length, 1);
6979
6980 case LINEEDITOR_EV_CUT_LEFT11:
6981 return lineeditor_delete_chars (d, 0, 1);
6982
6983 case LINEEDITOR_EV_REFRESH12:
6984 return lineeditor_refresh (d);
6985
6986 case LINEEDITOR_EV_TRANSPOSE13:
6987 {
6988 int i = d->current.edit_point;
6989 if (i <= 0 ||
6990 edited->length < 2)
6991 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
6992 if (i == edited->length)
6993 return lineeditor_transpose_chars (d, i-2, i-1, i-1, i);
6994 else
6995 return lineeditor_transpose_chars (d, i-1, i, i, i+1);
6996 }
6997
6998 case LINEEDITOR_EV_TRANSPOSE_WORD14:
6999 case LINEEDITOR_EV_TRANSPOSE_SEXPR15:
7000 {
7001 int start1;
7002 int end1;
7003 int start2;
7004 int end2;
7005 int dir = (ev->event_kind == LINEEDITOR_EV_TRANSPOSE_WORD14)
7006 ? FORW_WORD0
7007 : FORW_SEXPR2;
7008 if (!lineeditor_word_boundary (d, dir, d->current.edit_point, &end2) ||
7009 !lineeditor_word_boundary (d, dir+1, end2, &start2) ||
7010 !lineeditor_word_boundary (d, dir+1, start2, &start1) ||
7011 !lineeditor_word_boundary (d, dir, start1, &end1))
7012 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
7013 return lineeditor_transpose_chars (d, start1, end1, start2, end2);
7014 }
7015
7016 case LINEEDITOR_EV_UP16:
7017 return lineeditor_move_history_relative (d, 1);
7018
7019 case LINEEDITOR_EV_DOWN17:
7020 return lineeditor_move_history_relative (d, 0);
7021
7022 case LINEEDITOR_EV_RIGHT18:
7023 return lineeditor_move_edit_point (d, d->current.edit_point+1);
7024
7025 case LINEEDITOR_EV_RIGHT_WORD19:
7026 case LINEEDITOR_EV_RIGHT_SEXPR20:
7027 {
7028 int i;
7029 int dir = (ev->event_kind == LINEEDITOR_EV_RIGHT_WORD19)
7030 ? FORW_WORD0
7031 : FORW_SEXPR2;
7032 lineeditor_word_boundary (d, dir, d->current.edit_point, &i);
7033 return lineeditor_move_edit_point (d, i);
7034 }
7035
7036 case LINEEDITOR_EV_LEFT21:
7037 return lineeditor_move_edit_point (d, d->current.edit_point-1);
7038
7039 case LINEEDITOR_EV_LEFT_WORD22:
7040 case LINEEDITOR_EV_LEFT_SEXPR23:
7041 {
7042 int i;
7043 int dir = (ev->event_kind == LINEEDITOR_EV_LEFT_WORD22)
7044 ? BACK_WORD1
7045 : BACK_SEXPR3;
7046 lineeditor_word_boundary (d, dir, d->current.edit_point, &i);
7047 return lineeditor_move_edit_point (d, i);
7048 }
7049
7050 case LINEEDITOR_EV_HOME24:
7051 return lineeditor_move_edit_point (d, 0);
7052
7053 case LINEEDITOR_EV_HOME_DOC25:
7054 return lineeditor_move_history (d, d->hist_last->next);
7055
7056 case LINEEDITOR_EV_INSERT26:
7057 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
7058
7059 case LINEEDITOR_EV_DELETE27:
7060 if (edited->length == 0)
7061 return lineeditor_line_done (d, 1);
7062 else
7063 return lineeditor_delete_chars (d, d->current.edit_point+1, 0);
7064
7065 case LINEEDITOR_EV_DELETE_WORD28:
7066 case LINEEDITOR_EV_DELETE_SEXPR29:
7067 {
7068 int i;
7069 int dir = (ev->event_kind == LINEEDITOR_EV_DELETE_WORD28)
7070 ? FORW_WORD0
7071 : FORW_SEXPR2;
7072 if (!lineeditor_word_boundary (d, dir, d->current.edit_point, &i))
7073 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
7074 return lineeditor_delete_chars (d, i, 1);
7075 }
7076
7077 case LINEEDITOR_EV_END30:
7078 return lineeditor_move_edit_point (d, edited->length);
7079
7080 case LINEEDITOR_EV_END_DOC31:
7081 return lineeditor_move_history (d, d->hist_last);
7082
7083 case LINEEDITOR_EV_F132:
7084 case LINEEDITOR_EV_META_F133:
7085 case LINEEDITOR_EV_F234:
7086 case LINEEDITOR_EV_META_F235:
7087 case LINEEDITOR_EV_F336:
7088 case LINEEDITOR_EV_META_F337:
7089 case LINEEDITOR_EV_F438:
7090 case LINEEDITOR_EV_META_F439:
7091#ifdef LINEEDITOR_SUPPORT_F5_TO_F12
7092 case LINEEDITOR_EV_F540:
7093 case LINEEDITOR_EV_META_F541:
7094 case LINEEDITOR_EV_F642:
7095 case LINEEDITOR_EV_META_F643:
7096 case LINEEDITOR_EV_F744:
7097 case LINEEDITOR_EV_META_F745:
7098 case LINEEDITOR_EV_F846:
7099 case LINEEDITOR_EV_META_F847:
7100 case LINEEDITOR_EV_F948:
7101 case LINEEDITOR_EV_META_F949:
7102 case LINEEDITOR_EV_F1050:
7103 case LINEEDITOR_EV_META_F1051:
7104 case LINEEDITOR_EV_F1152:
7105 case LINEEDITOR_EV_META_F1153:
7106 case LINEEDITOR_EV_F1254:
7107 case LINEEDITOR_EV_META_F1255:
7108#endif
7109 {
7110 ___Cunsigned int command[7];
7111 command[0] = ___UNICODE_SHARP35;
7112 command[1] = ___UNICODE_VBAR124;
7113 command[2] = ___UNICODE_VBAR124;
7114 command[3] = ___UNICODE_SHARP35;
7115 command[4] = ___UNICODE_COMMA44;
7116 switch (ev->event_kind)
7117 {
7118#ifdef LINEEDITOR_SUPPORT_F5_TO_F12
7119 case LINEEDITOR_EV_F846:
7120 command[5] = ___UNICODE_LOWER_C99;
7121 break;
7122 case LINEEDITOR_EV_F948:
7123 command[5] = ___UNICODE_MINUS45;
7124 break;
7125 case LINEEDITOR_EV_F1050:
7126 command[5] = ___UNICODE_PLUS43;
7127 break;
7128 case LINEEDITOR_EV_F1152:
7129 command[5] = ___UNICODE_LOWER_S115;
7130 break;
7131 case LINEEDITOR_EV_F1254:
7132 command[5] = ___UNICODE_LOWER_L108;
7133 break;
7134#endif
7135 default:
7136 command[5] = ___UNICODE_LOWER_T116;
7137 break;
7138 }
7139 command[6] = ___UNICODE_SEMICOLON59;
7140 if (lineeditor_move_edit_point (d, 0)
7141 == ___FIX(___NO_ERR)(((long)(0))<<2) &&
7142 lineeditor_delete_chars (d, edited->length, 0)
7143 == ___FIX(___NO_ERR)(((long)(0))<<2) &&
7144 lineeditor_insert_chars (d, command, 7)
7145 == ___FIX(___NO_ERR)(((long)(0))<<2))
7146 return lineeditor_line_done (d, 0);
7147 break;
7148 }
7149 }
7150
7151 return ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
;
7152}
7153
7154
7155___HIDDENstatic ___SCMOBJlong lineeditor_process_events
7156 ___P((___device_tty *self),(___device_tty *self)
7157 (self)(___device_tty *self)
7158___device_tty *self;)(___device_tty *self)
7159{
7160#define AGGREGATION_BUFFER_SIZE(80*50) (80*50)
7161
7162 ___device_tty *d = self;
7163 ___SCMOBJlong e1;
7164 ___SCMOBJlong e2;
7165 ___Cunsigned int aggregation_buffer[AGGREGATION_BUFFER_SIZE(80*50)];
7166 lineeditor_event ev;
7167 int i;
7168 struct lineeditor_state_undo_struct previous;
7169
7170 /*
7171 * Process events only if no input line is currently available.
7172 */
7173
7174 if (d->input_line.buffer != NULL((void*)0))
7175 return ___FIX(0)(((long)(0))<<2);
7176
7177 /*
7178 * Process events only if no line editing output is pending.
7179 */
7180
7181 if ((e1 = lineeditor_output_drain (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
7182 return e1;
7183
7184 /*
7185 * Save state so that we can undo if there is an error.
7186 */
7187
7188 d->current.paren_balance_trigger = 0;
7189
7190 previous = d->current;
7191
7192 i = 0;
7193
7194 ev.event_kind = LINEEDITOR_EV_NONE0;
7195
7196 for (;;)
7197 {
7198 if ((e1 = lineeditor_get_event (d, &ev)) != ___FIX(___NO_ERR)(((long)(0))<<2) ||
7199 ev.event_kind == LINEEDITOR_EV_NONE0)
7200 break;
7201
7202 if (ev.event_kind != LINEEDITOR_EV_KEY1 ||
7203 ev.event_char < ___UNICODE_SPACE32 ||
7204 ev.event_char == ___UNICODE_RUBOUT127)
7205 break;
7206
7207 aggregation_buffer[i++] = ev.event_char;
7208
7209 ev.event_kind = LINEEDITOR_EV_NONE0;
7210
7211 if (i == AGGREGATION_BUFFER_SIZE(80*50))
7212 break;
7213 }
7214
7215 e2 = lineeditor_insert_chars (d, aggregation_buffer, i);
7216 if (e1 == ___FIX(___NO_ERR)(((long)(0))<<2))
7217 e1 = e2;
7218
7219 e2 = lineeditor_process_single_event (d, &ev);
7220 if (e1 == ___FIX(___NO_ERR)(((long)(0))<<2))
7221 {
7222 if (ev.event_kind == LINEEDITOR_EV_NONE0)
7223 e1 = ___FIX(i)(((long)(i))<<2);
7224 else
7225 e1 = ___FIX(i+1)(((long)(i+1))<<2);
7226 }
7227
7228 if (e1 == ___FIX(___INVALID_OP_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+7)))<<2)
)
7229 {
7230 /*
7231 * Undo line editing operation.
7232 */
7233
7234 ___Cunsigned int c = ___UNICODE_BELL7;
7235
7236 extensible_string_set_length
7237 (&d->output_char,
7238 0,
7239 1); /* ignore error */
7240
7241 d->output_char.length = 0; /* in case set_length failed */
7242 d->output_char_lo = 0;
7243
7244 d->current = previous;
7245
7246 e1 = lineeditor_output (d, &c, 1);
7247 }
7248
7249 if (d->current.paren_balance_trigger)
7250 {
7251 /*
7252 * Parenthesis balancing started in this round of event
7253 * processing.
7254 */
7255
7256 ___time duration;
7257
7258 ___time_get_current_time (&d->current.paren_balance_end);
7259 ___time_from_nsecs (&duration, 0, d->paren_balance_duration_nsecs);
7260 ___time_add (&d->current.paren_balance_end, duration);
7261
7262 d->current.paren_balance_in_progress = 1;
7263 }
7264 else if (d->current.paren_balance_in_progress)
7265 {
7266 /*
7267 * Parenthesis balancing did not start in this round of event
7268 * processing and parenthesis balancing is in progress, check if
7269 * parenthesis balancing should end.
7270 */
7271
7272 if (i > 0 || ev.event_kind != LINEEDITOR_EV_NONE0)
7273 lineeditor_end_paren_balance (d); /* ignore error */
7274 else
7275 {
7276 ___time now;
7277 ___time_get_current_time (&now);
7278 if (!___time_less (now, d->current.paren_balance_end))
7279 lineeditor_end_paren_balance (d); /* ignore error */
7280 }
7281 }
7282
7283 e2 = lineeditor_output_drain (d);
7284 if (e2 != ___FIX(___NO_ERR)(((long)(0))<<2))
7285 e1 = e2;
7286
7287 return e1;
7288}
7289
7290
7291___HIDDENstatic ___SCMOBJlong lineeditor_read_line
7292 ___P((___device_tty *self),(___device_tty *self)
7293 (self)(___device_tty *self)
7294___device_tty *self;)(___device_tty *self)
7295{
7296 ___device_tty *d = self;
7297
7298 if (!d->editing_line)
7299 {
7300 d->editing_line = 1;
7301 d->current.edit_point = 0;
7302 d->current.completion_point = 0;
7303 d->current.mark_point = 0;
7304 d->current.hist = d->hist_last;
7305 d->current.line_start = d->terminal_row * d->terminal_nb_cols + d->terminal_col;
7306 if (lineeditor_process_events (d) <= ___FIX(0)(((long)(0))<<2))
7307 d->editing_line = 0;
7308 }
7309 else
7310 lineeditor_process_events (d); /* ignore error */
7311
7312 if (d->input_line.buffer == NULL((void*)0))
7313 return ___ERR_CODE_EAGAIN(((long)(((11)==0?0:((((int)(-1))<<29)+(((int)(320))<<
16)+(11)))))<<2)
;
7314
7315 return ___FIX(___NO_ERR)(((long)(0))<<2);
7316}
7317
7318
7319#endif
7320
7321
7322/*****************************************************************************/
7323
7324
7325___HIDDENstatic int ___device_tty_kind
7326 ___P((___device *self),(___device *self)
7327 (self)(___device *self)
7328___device *self;)(___device *self)
7329{
7330 return ___TTY_DEVICE_KIND(15 +64);
7331}
7332
7333
7334___HIDDENstatic ___SCMOBJlong ___device_tty_cleanup
7335 ___P((___device_tty *self),(___device_tty *self)
7336 ())(___device_tty *self);
7337
7338
7339___HIDDENstatic ___SCMOBJlong ___device_tty_close_raw_virt
7340 ___P((___device_stream *self,(___device_stream *self, int direction)
7341 int direction),(___device_stream *self, int direction)
7342 (self,(___device_stream *self, int direction)
7343 direction)(___device_stream *self, int direction)
7344___device_stream *self;(___device_stream *self, int direction)
7345int direction;)(___device_stream *self, int direction)
7346{
7347 ___device_tty *d = ___CAST(___device_tty*,self)((___device_tty*)(self));
7348 int is_not_closed = 0;
7349
7350 if (d->base.base.read_stage != ___STAGE_CLOSED3)
7351 is_not_closed |= ___DIRECTION_RD1;
7352
7353 if (d->base.base.write_stage != ___STAGE_CLOSED3)
7354 is_not_closed |= ___DIRECTION_WR2;
7355
7356 if (is_not_closed == 0)
7357 return ___FIX(___NO_ERR)(((long)(0))<<2);
7358
7359 if ((is_not_closed & ~direction) == 0)
7360 {
7361 /* Close tty when both sides are closed. */
7362
7363 ___SCMOBJlong e;
7364
7365 d->base.base.read_stage = ___STAGE_CLOSED3; /* avoid multiple closes */
7366 d->base.base.write_stage = ___STAGE_CLOSED3;
7367
7368 if ((e = ___device_tty_cleanup (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
7369 return e;
7370 }
7371 else if (direction & ___DIRECTION_RD1)
7372 d->base.base.read_stage = ___STAGE_CLOSED3;
7373 else if (direction & ___DIRECTION_WR2)
7374 d->base.base.write_stage = ___STAGE_CLOSED3;
7375
7376 return ___FIX(___NO_ERR)(((long)(0))<<2);
7377}
7378
7379
7380___HIDDENstatic ___SCMOBJlong ___device_tty_select_raw_virt
7381 ___P((___device_stream *self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7382 ___BOOL for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7383 int i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7384 int pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7385 ___device_select_state *state),(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7386 (self,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7387 for_writing,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7388 i,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7389 pass,(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7390 state)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7391___device_stream *self;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7392___BOOL for_writing;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7393int i;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7394int pass;(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7395___device_select_state *state;)(___device_stream *self, int for_writing, int i, int pass, ___device_select_state
*state)
7396{
7397 ___device_tty *d = ___CAST(___device_tty*,self)((___device_tty*)(self));
7398 ___SCMOBJlong e;
7399
7400 if ((e = ___device_tty_force_open (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
7401 return e;
7402
7403 if ((for_writing ? d->base.base.write_stage : d->base.base.read_stage)
7404 != ___STAGE_OPEN0)
7405 return ___FIX(___CLOSED_DEVICE_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+6)))<<2)
;
7406
7407 if (pass == ___SELECT_PASS_11)
7408 {
7409#ifdef USE_POSIX
7410
7411 ___device_select_add_fd (state, d->fd, for_writing);
7412
7413#endif
7414
7415#ifdef USE_WIN32
7416
7417 HANDLE wait_obj;
7418
7419 if (for_writing)
7420 wait_obj = d->hin;
7421 else
7422 wait_obj = d->hout;
7423
7424 ___device_select_add_wait_obj (state, i, wait_obj);
7425
7426#endif
7427
7428#ifdef USE_LINEEDITOR
7429
7430 if (!for_writing)
7431 {
7432 if (lineeditor_read_ready (d))
7433 ___device_select_add_timeout
7434 (state,
7435 i,
7436 ___time_mod.time_neg_infinity);
7437 else if (d->current.paren_balance_in_progress)
7438 ___device_select_add_timeout
7439 (state,
7440 i,
7441 d->current.paren_balance_end);
7442 }
7443
7444#endif
7445
7446 return ___FIX(___SELECT_SETUP_DONE)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+14)))<<2)
;
7447 }
7448
7449 /* pass == ___SELECT_PASS_CHECK */
7450
7451 if (for_writing)
7452 {
7453#ifdef USE_POSIX
7454
7455 if (___FD_ISSET(d->fd, &state->writefds)((((&state->writefds)->__fds_bits)[((d->fd) / (8
* (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << (
(d->fd) % (8 * (int) sizeof (__fd_mask))))) != 0)
)
7456 state->devs[i] = NULL((void*)0);
7457
7458#endif
7459
7460#ifdef USE_WIN32
7461
7462 if (state->devs_next[i] != -1)
7463 state->devs[i] = NULL((void*)0);
7464
7465#endif
7466 }
7467 else
7468 {
7469#ifdef USE_POSIX
7470
7471 if (___FD_ISSET(d->fd, &state->readfds)((((&state->readfds)->__fds_bits)[((d->fd) / (8 *
(int) sizeof (__fd_mask)))] & ((__fd_mask) 1 << ((
d->fd) % (8 * (int) sizeof (__fd_mask))))) != 0)
)
7472 state->devs[i] = NULL((void*)0);
7473
7474#endif
7475
7476#ifdef USE_WIN32
7477
7478 if (state->devs_next[i] != -1)
7479 state->devs[i] = NULL((void*)0);
7480
7481#endif
7482
7483#ifdef USE_LINEEDITOR
7484
7485 if (lineeditor_read_ready (d) ||
7486 (d->current.paren_balance_in_progress &&
7487 state->timeout_reached &&
7488 !___time_less (state->timeout, d->current.paren_balance_end)))
7489 state->devs[i] = NULL((void*)0);
7490
7491#endif
7492 }
7493
7494 return ___FIX(___NO_ERR)(((long)(0))<<2);
7495}
7496
7497
7498___HIDDENstatic ___SCMOBJlong ___device_tty_release_raw_virt
7499 ___P((___device_stream *self),(___device_stream *self)
7500 (self)(___device_stream *self)
7501___device_stream *self;)(___device_stream *self)
7502{
7503 return ___FIX(___NO_ERR)(((long)(0))<<2);
7504}
7505
7506
7507___HIDDENstatic ___SCMOBJlong ___device_tty_force_output_raw_virt
7508 ___P((___device_stream *self,(___device_stream *self, int level)
7509 int level),(___device_stream *self, int level)
7510 (self,(___device_stream *self, int level)
7511 level)(___device_stream *self, int level)
7512___device_stream *self;(___device_stream *self, int level)
7513int level;)(___device_stream *self, int level)
7514{
7515 ___device_tty *d = ___CAST(___device_tty*,self)((___device_tty*)(self));
7516
7517#ifdef USE_LINEEDITOR
7518
7519 if (d->stage >= TTY_STAGE_INIT_DONE3)
7520 return lineeditor_output_drain (d);
7521
7522#endif
7523
7524 return ___FIX(___NO_ERR)(((long)(0))<<2);
7525}
7526
7527
7528___HIDDENstatic ___SCMOBJlong ___device_tty_seek_raw_virt
7529 ___P((___device_stream *self,(___device_stream *self, ___stream_index *pos, int whence)
7530 ___stream_index *pos,(___device_stream *self, ___stream_index *pos, int whence)
7531 int whence),(___device_stream *self, ___stream_index *pos, int whence)
7532 (self,(___device_stream *self, ___stream_index *pos, int whence)
7533 pos,(___device_stream *self, ___stream_index *pos, int whence)
7534 whence)(___device_stream *self, ___stream_index *pos, int whence)
7535___device_stream *self;(___device_stream *self, ___stream_index *pos, int whence)
7536___stream_index *pos;(___device_stream *self, ___stream_index *pos, int whence)
7537int whence;)(___device_stream *self, ___stream_index *pos, int whence)
7538{
7539 ___device_tty *d = ___CAST(___device_tty*,self)((___device_tty*)(self));
7540
7541 return ___FIX(___UNKNOWN_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+3)))<<2)
;
7542}
7543
7544
7545___HIDDENstatic ___SCMOBJlong ___device_tty_read_raw_virt
7546 ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7547 ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7548 ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7549 ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7550 (self,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7551 buf,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7552 len,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7553 len_done)(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7554___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7555___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7556___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7557___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7558{
7559 ___device_tty *d = ___CAST(___device_tty*,self)((___device_tty*)(self));
7560 ___SCMOBJlong e;
7561
7562 if ((e = ___device_tty_force_open (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
7563 return e;
7564
7565 len = TTY_CHAR_SELECT(1,2)1;
7566
7567#ifdef USE_LINEEDITOR
7568
7569 {
7570 int lo = d->lineeditor_input_byte_lo;
7571 int hi = d->lineeditor_input_byte_hi;
7572 int n = hi - lo;
7573 int limit;
7574
7575 if (n > len)
7576 n = len;
7577
7578 if (n <= 0)
7579 {
7580 int char_avail;
7581 ___Cunsigned int *char_buf_end;
7582 int byte_avail;
7583 ___U8unsigned char *byte_buf_end;
7584
7585 char_avail = d->input_line.length - d->input_line_lo;
7586
7587 if (char_avail <= 0)
7588 {
7589 if (d->lineeditor_mode == LINEEDITOR_MODE_DISABLE0 || d->input_raw)
7590 goto read_raw;
7591
7592 if ((e = lineeditor_read_line (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
7593 return e;
7594
7595 char_avail = d->input_line.length - d->input_line_lo;
7596
7597 /*
7598 * It is possible that char_avail == 0. This happens when
7599 * the end-of-file character is typed (e.g. ctrl-d).
7600 */
7601 }
7602
7603 char_buf_end = d->input_line.buffer + d->input_line.length;
7604
7605 byte_avail = ___NBELEMS(d->lineeditor_input_byte)(sizeof (d->lineeditor_input_byte) / sizeof ((d->lineeditor_input_byte
)[0]))
;
7606 byte_buf_end = d->lineeditor_input_byte + byte_avail;
7607
7608 while (chars_to_bytes (char_buf_end - char_avail,
7609 &char_avail,
7610 byte_buf_end - byte_avail,
7611 &byte_avail,
7612 &d->input_encoding_state)
7613 == ___ILLEGAL_CHAR2)
7614 char_avail--; /* skip over the illegal characters */
7615
7616 d->input_line_lo = d->input_line.length - char_avail;
7617
7618 if (char_avail <= 0)
7619 {
7620 extensible_string_cleanup (&d->input_line);
7621 d->input_line.buffer = NULL((void*)0);
7622 }
7623
7624 n = ___NBELEMS(d->lineeditor_input_byte)(sizeof (d->lineeditor_input_byte) / sizeof ((d->lineeditor_input_byte
)[0]))
- byte_avail;
7625 lo = 0;
7626 hi = n;
7627 d->lineeditor_input_byte_hi = hi;
7628 }
7629
7630 limit = lo + n;
7631
7632 while (lo < limit)
7633 *buf++ = d->lineeditor_input_byte[lo++];
7634
7635 if (lo < hi)
7636 d->lineeditor_input_byte_lo = lo;
7637 else
7638 {
7639 d->lineeditor_input_byte_lo = 0;
7640 d->lineeditor_input_byte_hi = 0;
7641 }
7642
7643 *len_done = n;
7644
7645#ifdef ___DEBUG_TTY
7646
7647 {
7648 int i;
7649
7650 ___printf ("___device_tty_read_raw_virt nb_bytes: %d ", *len_done);
7651
7652 for (i=0; i<*len_done; i++)
7653 ___printf (" %02x", buf[i]);
7654
7655 ___printf ("\n");
7656 }
7657
7658#endif
7659
7660 return ___FIX(___NO_ERR)(((long)(0))<<2);
7661 }
7662
7663 read_raw:;
7664
7665#endif
7666
7667 return ___device_tty_read_raw_no_lineeditor
7668 (d,
7669 buf,
7670 len,
7671 len_done);
7672}
7673
7674
7675___HIDDENstatic ___SCMOBJlong ___device_tty_write_raw_virt
7676 ___P((___device_stream *self,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7677 ___U8 *buf,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7678 ___stream_index len,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7679 ___stream_index *len_done),(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7680 (self,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7681 buf,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7682 len,(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7683 len_done)(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7684___device_stream *self;(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7685___U8 *buf;(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7686___stream_index len;(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7687___stream_index *len_done;)(___device_stream *self, unsigned char *buf, ___stream_index len
, ___stream_index *len_done)
7688{
7689 ___device_tty *d = ___CAST(___device_tty*,self)((___device_tty*)(self));
7690 ___SCMOBJlong e;
7691
7692 if ((e = ___device_tty_force_open (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
7693 return e;
7694
7695#ifdef USE_LINEEDITOR
7696
7697 if (d->lineeditor_mode != LINEEDITOR_MODE_DISABLE0)
7698 {
7699 if (!d->output_raw)
7700 {
7701 ___SCMOBJlong e;
7702 ___U8unsigned char *byte_buf_end;
7703 int byte_buf_avail;
7704
7705 if ((e = lineeditor_end_paren_balance (d))
7706 != ___FIX(___NO_ERR)(((long)(0))<<2) ||
7707 (e = lineeditor_output_set_attrs (d, d->output_attrs))
7708 != ___FIX(___NO_ERR)(((long)(0))<<2) ||
7709 (e = lineeditor_output_drain (d))
7710 != ___FIX(___NO_ERR)(((long)(0))<<2))
7711 return e;
7712
7713 byte_buf_end = buf + len;
7714 byte_buf_avail = len + d->output_char_incomplete;
7715
7716 /* convert the bytes to characters */
7717
7718 while (byte_buf_avail > 0)
7719 {
7720 ___Cunsigned int char_buf[128];
7721 int char_buf_avail = ___NBELEMS(char_buf)(sizeof (char_buf) / sizeof ((char_buf)[0]));
7722 int orig_byte_buf_avail = byte_buf_avail;
Value stored to 'orig_byte_buf_avail' during its initialization is never read
7723 int code;
7724
7725 code = chars_from_bytes (char_buf,
7726 &char_buf_avail,
7727 byte_buf_end - byte_buf_avail,
7728 &byte_buf_avail,
7729 &d->output_decoding_state);
7730
7731 switch (code)
7732 {
7733 case ___CONVERSION_DONE0:
7734 if ((e = lineeditor_output
7735 (d,
7736 char_buf,
7737 ___NBELEMS(char_buf)(sizeof (char_buf) / sizeof ((char_buf)[0])) - char_buf_avail))
7738 != ___FIX(___NO_ERR)(((long)(0))<<2))
7739 {
7740 /*******************************/
7741 return e;
7742 }
7743 lineeditor_output_drain (d); /* ignore error */
7744 break;
7745
7746 case ___INCOMPLETE_CHAR1:
7747 *len_done = byte_buf_avail - d->output_char_incomplete;
7748 d->output_char_incomplete = byte_buf_avail;
7749 return ___FIX(___NO_ERR)(((long)(0))<<2);
7750
7751 case ___ILLEGAL_CHAR2:
7752 /* ignore illegal characters */
7753 break;
7754 }
7755 }
7756
7757 *len_done = len;
7758 d->output_char_incomplete = 0;
7759 return ___FIX(___NO_ERR)(((long)(0))<<2);
7760 }
7761 }
7762
7763#endif
7764
7765 return ___device_tty_write_raw_no_lineeditor (d, buf, len, len_done);
7766}
7767
7768
7769___HIDDENstatic ___SCMOBJlong ___device_tty_width_virt
7770 ___P((___device_stream *self),(___device_stream *self)
7771 (self)(___device_stream *self)
7772___device_stream *self;)(___device_stream *self)
7773{
7774 ___device_tty *d = ___CAST(___device_tty*,self)((___device_tty*)(self));
7775 ___SCMOBJlong e;
7776
7777 if ((e = ___device_tty_force_open (d)) != ___FIX(___NO_ERR)(((long)(0))<<2))
7778 return e;
7779
7780 if ((e = ___device_tty_update_size (d)) == ___FIX(___NO_ERR)(((long)(0))<<2))
7781 return ___FIX(d->terminal_nb_cols)(((long)(d->terminal_nb_cols))<<2);
7782
7783 return e;
7784}
7785
7786
7787___HIDDENstatic ___SCMOBJlong ___device_tty_default_options_virt
7788 ___P((___device_stream *self),(___device_stream *self)
7789 (self)(___device_stream *self)
7790___device_stream *self;)(___device_stream *self)
7791{
7792 int settings = ___setup_params.terminal_settings;
7793 int char_encoding_errors = ___CHAR_ENCODING_ERRORS(settings)((settings)&(3<<5));
7794 int char_encoding = ___CHAR_ENCODING(settings)((settings)&(31<<0));
7795 int eol_encoding = ___EOL_ENCODING(settings)((settings)&(3<<7));
7796 int buffering = ___BUFFERING(settings)((settings)&(3<<9));
7797
7798 if (char_encoding_errors == 0)
7799 char_encoding_errors = ___CHAR_ENCODING_ERRORS_ON(1<<5);
7800
7801 switch (char_encoding)
7802 {
7803 case ___CHAR_ENCODING_UCS_2(13<<0):
7804#ifdef ___BIG_ENDIAN
7805 char_encoding = ___CHAR_ENCODING_UCS_2BE(14<<0);
7806#else
7807 char_encoding = ___CHAR_ENCODING_UCS_2LE(15<<0);
7808#endif
7809 break;
7810
7811 case ___CHAR_ENCODING_UCS_4(16<<0):
7812#ifdef ___BIG_ENDIAN
7813 char_encoding = ___CHAR_ENCODING_UCS_4BE(17<<0);
7814#else
7815 char_encoding = ___CHAR_ENCODING_UCS_4LE(18<<0);
7816#endif
7817 break;
7818
7819 case 0:
7820#ifdef USE_WIN32
7821 char_encoding =
7822 TTY_CHAR_SELECT(___CHAR_ENCODING_ISO_8859_1,___CHAR_ENCODING_UCS_2LE)(2<<0);
7823#else
7824 char_encoding = ___CHAR_ENCODING_ISO_8859_1(2<<0);
7825#endif
7826 break;
7827 }
7828
7829 if (eol_encoding == 0)
7830 {
7831#ifdef USE_WIN32
7832 eol_encoding = ___EOL_ENCODING_CRLF(3<<7);
7833#else
7834 eol_encoding = ___EOL_ENCODING_LF(1<<7);
7835#endif
7836 }
7837
7838 if (buffering == 0)
7839 buffering = ___NO_BUFFERING(1<<9);
7840
7841#ifdef ___DEBUG_TTY
7842
7843 ___printf ("terminal char_encoding=%d eol_encoding=%d buffering=%d\n",
7844 char_encoding,
7845 eol_encoding,
7846 buffering);
7847
7848#endif
7849
7850 return ___FIX(___STREAM_OPTIONS(char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering
)+((char_encoding_errors+char_encoding+eol_encoding+buffering
)<<15)))<<2)
7851 char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering
)+((char_encoding_errors+char_encoding+eol_encoding+buffering
)<<15)))<<2)
7852 eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering
)+((char_encoding_errors+char_encoding+eol_encoding+buffering
)<<15)))<<2)
7853 buffering,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering
)+((char_encoding_errors+char_encoding+eol_encoding+buffering
)<<15)))<<2)
7854 char_encoding_errors,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering
)+((char_encoding_errors+char_encoding+eol_encoding+buffering
)<<15)))<<2)
7855 char_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering
)+((char_encoding_errors+char_encoding+eol_encoding+buffering
)<<15)))<<2)
7856 eol_encoding,(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering
)+((char_encoding_errors+char_encoding+eol_encoding+buffering
)<<15)))<<2)
7857 buffering))(((long)((char_encoding_errors+char_encoding+eol_encoding+buffering
)+((char_encoding_errors+char_encoding+eol_encoding+buffering
)<<15)))<<2)
;
7858}
7859
7860
7861___HIDDENstatic ___SCMOBJlong ___device_tty_options_set_virt
7862 ___P((___device_stream *self,(___device_stream *self, long options)
7863 ___SCMOBJ options),(___device_stream *self, long options)
7864 (self,(___device_stream *self, long options)
7865 options)(___device_stream *self, long options)
7866___device_stream *self;(___device_stream *self, long options)
7867___SCMOBJ options;)(___device_stream *self, long options)
7868{
7869 ___device_tty *d = ___CAST(___device_tty*,self)((___device_tty*)(self));
7870 int opts = ___INT(options)((options)>>2);
7871 int input_opts = ___STREAM_OPTIONS_INPUT(opts)((opts)&((1<<15)-1));
7872 int output_opts = ___STREAM_OPTIONS_OUTPUT(opts)(((opts)>>15)&((1<<15)-1));
7873
7874 d->input_decoding_state = input_opts;
7875 d->input_encoding_state = input_opts;
7876 d->output_decoding_state = output_opts;
7877 d->output_encoding_state = output_opts;
7878
7879#ifdef ___DEBUG_TTY
7880 ___printf ("input_opts=%d output_opts=%d\n", input_opts, output_opts);
7881#endif
7882
7883 return ___FIX(___NO_ERR)(((long)(0))<<2);
7884}
7885
7886
7887___HIDDENstatic ___device_tty_vtbl ___device_tty_table =
7888{
7889 {
7890 {
7891 ___device_tty_kind,
7892 ___device_stream_select_virt,
7893 ___device_stream_release_virt,
7894 ___device_stream_force_output_virt,
7895 ___device_stream_close_virt
7896 },
7897 ___device_tty_select_raw_virt,
7898 ___device_tty_release_raw_virt,
7899 ___device_tty_force_output_raw_virt,
7900 ___device_tty_close_raw_virt,
7901 ___device_tty_seek_raw_virt,
7902 ___device_tty_read_raw_virt,
7903 ___device_tty_write_raw_virt,
7904 ___device_tty_width_virt,
7905 ___device_tty_default_options_virt,
7906 ___device_tty_options_set_virt
7907 }
7908};
7909
7910
7911___HIDDENstatic ___SCMOBJlong ___device_tty_setup
7912 ___P((___device_tty *self,(___device_tty *self, int plain)
7913 int plain),(___device_tty *self, int plain)
7914 (self,(___device_tty *self, int plain)
7915 plain)(___device_tty *self, int plain)
7916___device_tty *self;(___device_tty *self, int plain)
7917int plain;)(___device_tty *self, int plain)
7918{
7919 ___device_tty *d = self;
7920 ___SCMOBJlong e = ___FIX(___NO_ERR)(((long)(0))<<2);
7921
7922#ifdef USE_LINEEDITOR
7923
7924 e = lineeditor_setup (d, plain);
7925
7926#endif
7927
7928 return e;
7929}
7930
7931
7932___HIDDENstatic ___SCMOBJlong ___device_tty_cleanup
7933 ___P((___device_tty *self),(___device_tty *self)
7934 (self)(___device_tty *self)
7935___device_tty *self;)(___device_tty *self)
7936{
7937 ___device_tty *d = self;
7938 ___SCMOBJlong e;
7939
7940#ifdef USE_LINEEDITOR
7941
7942 lineeditor_cleanup (d);
7943
7944#endif
7945
7946 if (d->stage >= TTY_STAGE_MODE_NOT_SAVED1)
7947 {
7948 if (d->stage >= TTY_STAGE_MODE_NOT_SET2)
7949 {
7950 if ((e = ___device_tty_mode_restore (d, 1)) != ___FIX(___NO_ERR)(((long)(0))<<2))
7951 return e;
7952 }
7953
7954 if ((d->base.base.close_direction & d->base.base.direction)
7955 == d->base.base.direction)
7956 {
7957#ifdef USE_POSIX
7958 if (close_no_EINTR (d->fd) < 0)
7959 return err_code_from_errno ()___err_code_from_errno();
7960#endif
7961
7962#ifdef USE_WIN32
7963 if (!CloseHandle (d->hin))
7964 return err_code_from_GetLastError ()___err_code_from_GetLastError();
7965 if (!CloseHandle (d->hout))
7966 return err_code_from_GetLastError ()___err_code_from_GetLastError();
7967#endif
7968 }
7969 }
7970
7971 return ___FIX(___NO_ERR)(((long)(0))<<2);
7972}
7973
7974
7975#ifndef USE_POSIX
7976#ifndef USE_WIN32
7977
7978
7979___SCMOBJlong ___device_tty_setup_from_stdio
7980 ___P((___device_tty **dev,(___device_tty **dev, ___device_group *dgroup, int direction)
7981 ___device_group *dgroup,(___device_tty **dev, ___device_group *dgroup, int direction)
7982 int direction),(___device_tty **dev, ___device_group *dgroup, int direction)
7983 (dev,(___device_tty **dev, ___device_group *dgroup, int direction)
7984 dgroup,(___device_tty **dev, ___device_group *dgroup, int direction)
7985 direction)(___device_tty **dev, ___device_group *dgroup, int direction)
7986___device_tty **dev;(___device_tty **dev, ___device_group *dgroup, int direction)
7987___device_group *dgroup;(___device_tty **dev, ___device_group *dgroup, int direction)
7988int direction;)(___device_tty **dev, ___device_group *dgroup, int direction)
7989{
7990 ___device_tty *d;
7991 ___SCMOBJlong e;
7992
7993 d = ___CAST(___device_tty*,((___device_tty*)(___alloc_mem (sizeof (___device_tty))))
7994 ___alloc_mem (sizeof (___device_tty)))((___device_tty*)(___alloc_mem (sizeof (___device_tty))));
7995
7996 if (d == NULL((void*)0))
7997 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
7998
7999 d->base.base.vtbl = &___device_tty_table;
8000
8001 d->stage = TTY_STAGE_NOT_OPENED0;
8002
8003 *dev = d;
8004
8005 if ((e = ___device_tty_setup (d, 1)) != ___FIX(___NO_ERR)(((long)(0))<<2))
8006 {
8007 ___free_mem (d);
8008 return e;
8009 }
8010
8011 return ___device_stream_setup
8012 (&d->base,
8013 dgroup,
8014 direction,
8015 0);
8016}
8017
8018
8019#endif
8020#endif
8021
8022
8023#ifdef USE_POSIX
8024
8025
8026___SCMOBJlong ___device_tty_setup_from_fd
8027 ___P((___device_tty **dev,(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8028 ___device_group *dgroup,(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8029 int fd,(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8030 int direction),(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8031 (dev,(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8032 dgroup,(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8033 fd,(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8034 direction)(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8035___device_tty **dev;(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8036___device_group *dgroup;(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8037int fd;(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8038int direction;(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8039int close_direction;)(___device_tty **dev, ___device_group *dgroup, int fd, int direction
)
8040{
8041 ___device_tty *d;
8042 ___SCMOBJlong e;
8043 int plain = (fd == STDIN_FILENO0) ||
8044 (fd == STDOUT_FILENO1) ||
8045 (fd == STDERR_FILENO2);
8046
8047 d = ___CAST(___device_tty*,((___device_tty*)(___alloc_mem (sizeof (___device_tty))))
8048 ___alloc_mem (sizeof (___device_tty)))((___device_tty*)(___alloc_mem (sizeof (___device_tty))));
8049
8050 if (d == NULL((void*)0))
8051 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
8052
8053 d->base.base.vtbl = &___device_tty_table;
8054
8055 d->stage = (fd < 0) ? TTY_STAGE_NOT_OPENED0 : TTY_STAGE_MODE_NOT_SAVED1;
8056 d->fd = fd;
8057
8058 *dev = d;
8059
8060 if ((e = ___device_tty_setup (d, plain)) != ___FIX(___NO_ERR)(((long)(0))<<2))
8061 {
8062 ___free_mem (d);
8063 return e;
8064 }
8065
8066 return ___device_stream_setup
8067 (&d->base,
8068 dgroup,
8069 direction,
8070 0);
8071}
8072
8073
8074#endif
8075
8076
8077#ifdef USE_WIN32
8078
8079
8080___SCMOBJlong ___device_tty_setup_from_console
8081 ___P((___device_tty **dev,(___device_tty **dev, ___device_group *dgroup, int direction)
8082 ___device_group *dgroup,(___device_tty **dev, ___device_group *dgroup, int direction)
8083 int direction),(___device_tty **dev, ___device_group *dgroup, int direction)
8084 (dev,(___device_tty **dev, ___device_group *dgroup, int direction)
8085 dgroup,(___device_tty **dev, ___device_group *dgroup, int direction)
8086 direction)(___device_tty **dev, ___device_group *dgroup, int direction)
8087___device_tty **dev;(___device_tty **dev, ___device_group *dgroup, int direction)
8088___device_group *dgroup;(___device_tty **dev, ___device_group *dgroup, int direction)
8089int direction;)(___device_tty **dev, ___device_group *dgroup, int direction)
8090{
8091 ___device_tty *d;
8092 ___SCMOBJlong e;
8093
8094 d = ___CAST(___device_tty*,((___device_tty*)(___alloc_mem (sizeof (___device_tty))))
8095 ___alloc_mem (sizeof (___device_tty)))((___device_tty*)(___alloc_mem (sizeof (___device_tty))));
8096
8097 if (d == NULL((void*)0))
8098 return ___FIX(___HEAP_OVERFLOW_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+5)))<<2)
;
8099
8100 d->base.base.vtbl = &___device_tty_table;
8101
8102 d->stage = TTY_STAGE_NOT_OPENED0;
8103
8104 *dev = d;
8105
8106 if ((e = ___device_tty_setup (d, 0)) != ___FIX(___NO_ERR)(((long)(0))<<2))
8107 {
8108 ___free_mem (d);
8109 return e;
8110 }
8111
8112 return ___device_stream_setup
8113 (&d->base,
8114 dgroup,
8115 direction,
8116 0);
8117}
8118
8119
8120#endif
8121
8122
8123___SCMOBJlong ___device_tty_setup_console
8124 ___P((___device_tty **dev,(___device_tty **dev, ___device_group *dgroup, int direction)
8125 ___device_group *dgroup,(___device_tty **dev, ___device_group *dgroup, int direction)
8126 int direction),(___device_tty **dev, ___device_group *dgroup, int direction)
8127 (dev,(___device_tty **dev, ___device_group *dgroup, int direction)
8128 dgroup,(___device_tty **dev, ___device_group *dgroup, int direction)
8129 direction)(___device_tty **dev, ___device_group *dgroup, int direction)
8130___device_tty **dev;(___device_tty **dev, ___device_group *dgroup, int direction)
8131___device_group *dgroup;(___device_tty **dev, ___device_group *dgroup, int direction)
8132int direction;)(___device_tty **dev, ___device_group *dgroup, int direction)
8133{
8134#ifndef USE_POSIX
8135#ifndef USE_WIN32
8136
8137 return ___device_tty_setup_from_stdio (dev,
8138 dgroup,
8139 direction);
8140
8141#endif
8142#endif
8143
8144#ifdef USE_POSIX
8145
8146 return ___device_tty_setup_from_fd (dev,
8147 dgroup,
8148 -1,
8149 direction);
8150
8151#endif
8152
8153#ifdef USE_WIN32
8154
8155 return ___device_tty_setup_from_console (dev,
8156 dgroup,
8157 direction);
8158
8159#endif
8160}
8161
8162
8163___tty_module ___tty_mod =
8164{
8165 0,
8166 NULL((void*)0),
8167 NULL((void*)0),
8168 NULL((void*)0),
8169 NULL((void*)0),
8170 {
8171#ifdef TERMINAL_EMULATION_USES_CURSES
8172 {
8173 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
8174 0,
8175 ___FIX(___NO_ERR)(((long)(0))<<2)
8176 },
8177#endif
8178 {
8179 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
8180 0,
8181 ___FIX(___NO_ERR)(((long)(0))<<2)
8182 }
8183 }
8184
8185#ifdef IO_MODULE_INIT
8186 ___TTY_MODULE_INIT
8187#endif
8188};
8189
8190
8191/*---------------------------------------------------------------------------*/
8192
8193/* Tty device operations. */
8194
8195
8196___SCMOBJlong ___os_device_tty_type_set
8197 ___P((___SCMOBJ dev,(long dev, long term_type, long emacs_bindings)
8198 ___SCMOBJ term_type,(long dev, long term_type, long emacs_bindings)
8199 ___SCMOBJ emacs_bindings),(long dev, long term_type, long emacs_bindings)
8200 (dev,(long dev, long term_type, long emacs_bindings)
8201 term_type,(long dev, long term_type, long emacs_bindings)
8202 emacs_bindings)(long dev, long term_type, long emacs_bindings)
8203___SCMOBJ dev;(long dev, long term_type, long emacs_bindings)
8204___SCMOBJ term_type;(long dev, long term_type, long emacs_bindings)
8205___SCMOBJ emacs_bindings;)(long dev, long term_type, long emacs_bindings)
8206{
8207 return ___FIX(___UNIMPL_ERR)(((long)((((((int)(-1))<<29)+(((int)(448))<<16)+(
0))+4)))<<2)
;
8208}
8209
8210
8211___SCMOBJlong ___os_device_tty_text_attributes_set
8212 ___P((___SCMOBJ dev,(long dev, long input, long output)
8213 ___SCMOBJ input,(long dev, long input, long output)
8214 ___SCMOBJ output),(long dev, long input, long output)
8215 (dev,(long dev, long input, long output)
8216 input,(long dev, long input, long output)
8217 output)(long dev, long input, long output)
8218___SCMOBJ dev;(long dev, long input, long output)
8219___SCMOBJ input;(long dev, long input, long output)
8220___SCMOBJ output;)(long dev, long input, long output)
8221{
8222 ___device_tty *d =
8223 ___CAST(___device_tty*,___FIELD(dev,___FOREIGN_PTR))((___device_tty*)((*((((long*)((dev)-(1)))+1)+2))));
8224
8225 d->input_attrs = ___INT(input)((input)>>2);
8226 d->output_attrs = ___INT(output)((output)>>2);
8227
8228 return ___VOID((((long)(-5))<<2)+2);
8229}
8230
8231
8232___SCMOBJlong ___os_device_tty_history
8233 ___P((___SCMOBJ dev),(long dev)
8234 (dev)(long dev)
8235___SCMOBJ dev;)(long dev)
8236{
8237 ___device_tty *d =
8238 ___CAST(___device_tty*,___FIELD(dev,___FOREIGN_PTR))((___device_tty*)((*((((long*)((dev)-(1)))+1)+2))));
8239 ___SCMOBJlong e;
8240 ___SCMOBJlong result;
8241 extensible_string hist;
8242
8243 if ((e = extensible_string_setup (&hist, 0))
8244 != ___FIX(___NO_ERR)(((long)(0))<<2))
8245 result = e;
8246 else
8247 {
8248 ___Cunsigned int nul = ___UNICODE_NUL0;
8249 ___Cunsigned int lf = ___UNICODE_LINEFEED10;
8250 lineeditor_history *probe = d->hist_last->next;
8251
8252 while (probe != d->hist_last)
8253 {
8254 if ((e = extensible_string_insert_at_end
8255 (&hist,
8256 probe->actual.length,
8257 probe->actual.buffer))
8258 != ___FIX(___NO_ERR)(((long)(0))<<2) ||
8259 (e = extensible_string_insert_at_end
8260 (&hist,
8261 1,
8262 &lf))
8263 != ___FIX(___NO_ERR)(((long)(0))<<2))
8264 break;
8265
8266 probe = probe->next;
8267 }
8268
8269 if (e != ___FIX(___NO_ERR)(((long)(0))<<2) ||
8270 (e = extensible_string_insert_at_end
8271 (&hist,
8272 1,
8273 &nul))
8274 != ___FIX(___NO_ERR)(((long)(0))<<2) ||
8275 (e = ___NONNULLSTRING_to_SCMOBJ
8276 (hist.buffer,
8277 &result,
8278 ___RETURN_POS127,
8279 ___CE(___C_CE_SELECT)(16<<0)))
8280 != ___FIX(___NO_ERR)(((long)(0))<<2))
8281 result = e;
8282
8283 extensible_string_cleanup (&hist);
8284 }
8285
8286 return result;
8287}
8288
8289
8290___SCMOBJlong ___os_device_tty_history_set
8291 ___P((___SCMOBJ dev,(long dev, long history)
8292 ___SCMOBJ history),(long dev, long history)
8293 (dev,(long dev, long history)
8294 history)(long dev, long history)
8295___SCMOBJ dev;(long dev, long history)
8296___SCMOBJ history;)(long dev, long history)
8297{
8298 ___device_tty *d =
8299 ___CAST(___device_tty*,___FIELD(dev,___FOREIGN_PTR))((___device_tty*)((*((((long*)((dev)-(1)))+1)+2))));
8300 ___SCMOBJlong e;
8301 void *hist;
8302
8303 if ((e = ___SCMOBJ_to_NONNULLSTRING
8304 (history,
8305 &hist,
8306 1,
8307 ___CE(___C_CE_SELECT)(16<<0),
8308 0))
8309 == ___FIX(___NO_ERR)(((long)(0))<<2))
8310 {
8311 ___Cunsigned int *h = ___CAST(___C*,hist)((unsigned int*)(hist));
8312
8313 lineeditor_history_trim_to (d, 0);
8314
8315 while (*h != ___UNICODE_NUL0)
8316 {
8317 ___Cunsigned int *start = h;
8318
8319 while (*h != ___UNICODE_NUL0 && *h != ___UNICODE_LINEFEED10)
8320 h++;
8321
8322 if (h != start)
8323 if ((e = lineeditor_history_add_line_before_last
8324 (d,
8325 h-start,
8326 start))
8327 != ___FIX(___NO_ERR)(((long)(0))<<2))
8328 break;
8329
8330 if (*h == ___UNICODE_LINEFEED10)
8331 h++;
8332 }
8333
8334 lineeditor_history_trim (d);
8335
8336 ___release_string (hist);
8337 }
8338
8339 return e;
8340}
8341
8342
8343___SCMOBJlong ___os_device_tty_history_max_length_set
8344 ___P((___SCMOBJ dev,(long dev, long max_length)
8345 ___SCMOBJ max_length),(long dev, long max_length)
8346 (dev,(long dev, long max_length)
8347 max_length)(long dev, long max_length)
8348___SCMOBJ dev;(long dev, long max_length)
8349___SCMOBJ max_length;)(long dev, long max_length)
8350{
8351 ___device_tty *d =
8352 ___CAST(___device_tty*,___FIELD(dev,___FOREIGN_PTR))((___device_tty*)((*((((long*)((dev)-(1)))+1)+2))));
8353
8354 lineeditor_set_history_max_length (d, ___INT(max_length)((max_length)>>2));
8355
8356 return ___VOID((((long)(-5))<<2)+2);
8357}
8358
8359
8360___SCMOBJlong ___os_device_tty_paren_balance_duration_set
8361 ___P((___SCMOBJ dev,(long dev, long duration)
8362 ___SCMOBJ duration),(long dev, long duration)
8363 (dev,(long dev, long duration)
8364 duration)(long dev, long duration)
8365___SCMOBJ dev;(long dev, long duration)
8366___SCMOBJ duration;)(long dev, long duration)
8367{
8368 ___device_tty *d =
8369 ___CAST(___device_tty*,___FIELD(dev,___FOREIGN_PTR))((___device_tty*)((*((((long*)((dev)-(1)))+1)+2))));
8370 int duration_nsecs = ___CAST(int,___FLONUM_VAL(duration) * 1e9)((int)(*((double*)((((long*)((duration)-(1)))+1))) * 1e9));
8371
8372 if (duration_nsecs < 0)
8373 duration_nsecs = 0;
8374
8375 d->paren_balance_duration_nsecs = duration_nsecs;
8376
8377 return ___VOID((((long)(-5))<<2)+2);
8378}
8379
8380
8381___SCMOBJlong ___os_device_tty_mode_set
8382 ___P((___SCMOBJ dev,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8383 ___SCMOBJ input_allow_special,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8384 ___SCMOBJ input_echo,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8385 ___SCMOBJ input_raw,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8386 ___SCMOBJ output_raw,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8387 ___SCMOBJ speed),(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8388 (dev,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8389 input_allow_special,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8390 input_echo,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8391 input_raw,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8392 output_raw,(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8393 speed)(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8394___SCMOBJ dev;(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8395___SCMOBJ input_allow_special;(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8396___SCMOBJ input_echo;(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8397___SCMOBJ input_raw;(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8398___SCMOBJ output_raw;(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8399___SCMOBJ speed;)(long dev, long input_allow_special, long input_echo, long input_raw
, long output_raw, long speed)
8400{
8401 ___device_tty *d =
8402 ___CAST(___device_tty*,___FIELD(dev,___FOREIGN_PTR))((___device_tty*)((*((((long*)((dev)-(1)))+1)+2))));
8403 ___SCMOBJlong e;
8404
8405 if ((e = ___device_tty_force_open (d)) == ___FIX(___NO_ERR)(((long)(0))<<2))
8406 e = ___device_tty_mode_set
8407 (d,
8408 !___FALSEP(input_allow_special)((input_allow_special)==((((long)(-1))<<2)+2)),
8409 !___FALSEP(input_echo)((input_echo)==((((long)(-1))<<2)+2)),
8410 !___FALSEP(input_raw)((input_raw)==((((long)(-1))<<2)+2)),
8411 !___FALSEP(output_raw)((output_raw)==((((long)(-1))<<2)+2)),
8412 ___INT(speed)((speed)>>2));
8413
8414 return e;
8415}
8416
8417
8418#ifdef USE_POSIX
8419
8420
8421void tty_signal_handler (int sig)
8422{
8423#ifdef USE_signal
8424 ___set_signal_handler (sig, tty_signal_handler);
8425#endif
8426
8427 switch (sig)
8428 {
8429 case SIGINT2:
8430 ___tty_mod.user_interrupt_handler ();
8431 break;
8432
8433 case SIGTERM15:
8434 ___tty_mod.terminate_interrupt_handler ();
8435 break;
8436
8437 case SIGWINCH28:
8438 {
8439 ___device_tty *probe = ___tty_mod.mode_save_stack;
8440
8441 while (probe != NULL((void*)0))
8442 {
8443 probe->size_needs_update = 1;
8444 probe = probe->mode_save_stack_next;
8445 }
8446
8447 break;
8448 }
8449
8450 case SIGCONT18:
8451 ___device_tty_mode_restore (0, 0); /***************/
8452 break;
8453 }
8454}
8455
8456
8457#endif
8458
8459
8460#ifdef USE_WIN32
8461
8462
8463___HIDDENstatic BOOL WINAPI console_event_handler
8464 ___P((DWORD dwCtrlType),(DWORD dwCtrlType)
8465 (dwCtrlType)(DWORD dwCtrlType)
8466DWORD dwCtrlType;)(DWORD dwCtrlType)
8467{
8468 switch (dwCtrlType)
8469 {
8470 case CTRL_CLOSE_EVENT:
8471 case CTRL_LOGOFF_EVENT:
8472 case CTRL_SHUTDOWN_EVENT:
8473 ___tty_mod.terminate_interrupt_handler ();
8474 break;
8475 case CTRL_C_EVENT:
8476 case CTRL_BREAK_EVENT:
8477 ___tty_mod.user_interrupt_handler ();
8478 break;
8479 }
8480
8481 SetEvent (___io_mod.abort_select); /* ignore error */
8482
8483 return TRUE;
8484
8485#if 0
8486#if 0
8487 /**********************************/
8488 switch (dwCtrlType)
8489 {
8490 case CTRL_C_EVENT:
8491 io_mod.got_event = 1;
8492 break;
8493 case CTRL_BREAK_EVENT:
8494 io_mod.got_event = 2;
8495 break;
8496 case CTRL_CLOSE_EVENT:
8497 io_mod.got_event = 3;
8498 break;
8499 case CTRL_LOGOFF_EVENT:
8500 io_mod.got_event = 4;
8501 break;
8502 case CTRL_SHUTDOWN_EVENT:
8503 io_mod.got_event = 5;
8504 break;
8505 default:
8506 io_mod.got_event = 999;
8507 }
8508
8509 SetEvent (io_mod.abort_select); /* ignore error */
8510
8511 return TRUE;
8512#else
8513 return FALSE;
8514#endif
8515#endif
8516}
8517
8518
8519#endif
8520
8521
8522___SCMOBJlong ___setup_user_interrupt_handling ___PVOID(void)
8523{
8524#ifdef USE_POSIX
8525
8526 ___set_signal_handler (SIGINT2, tty_signal_handler);
8527 ___set_signal_handler (SIGTERM15, tty_signal_handler);
8528 ___set_signal_handler (SIGWINCH28, tty_signal_handler);
8529 ___set_signal_handler (SIGCONT18, tty_signal_handler);
8530
8531#endif
8532
8533#ifdef USE_WIN32
8534
8535 SetConsoleCtrlHandler (console_event_handler, TRUE); /* ignore error */
8536
8537#endif
8538
8539 return ___FIX(___NO_ERR)(((long)(0))<<2);
8540}
8541
8542
8543void ___cleanup_user_interrupt_handling ___PVOID(void)
8544{
8545#ifdef USE_POSIX
8546
8547 ___set_signal_handler (SIGINT2, SIG_DFL((__sighandler_t) 0));
8548 ___set_signal_handler (SIGTERM15, SIG_DFL((__sighandler_t) 0));
8549 ___set_signal_handler (SIGWINCH28, SIG_DFL((__sighandler_t) 0));
8550 ___set_signal_handler (SIGCONT18, SIG_DFL((__sighandler_t) 0));
8551
8552#endif
8553
8554#ifdef USE_WIN32
8555
8556 SetConsoleCtrlHandler (console_event_handler, FALSE); /* ignore error */
8557
8558#endif
8559}
8560
8561
8562void ___disable_user_interrupts ___PVOID(void)
8563{
8564#ifdef USE_POSIX
8565#ifdef HAVE_SIGPROCMASK1
8566
8567 sigset_t sigs;
8568
8569 sigemptyset (&sigs);
8570 sigaddset (&sigs, SIGINT2);
8571 sigaddset (&sigs, SIGTERM15);
8572 sigaddset (&sigs, SIGWINCH28);
8573 sigaddset (&sigs, SIGCONT18);
8574
8575 sigprocmask (SIG_BLOCK0, &sigs, NULL((void*)0));
8576
8577#endif
8578#endif
8579}
8580
8581void ___enable_user_interrupts ___PVOID(void)
8582{
8583#ifdef USE_POSIX
8584#ifdef HAVE_SIGPROCMASK1
8585
8586 sigset_t sigs;
8587
8588 sigemptyset (&sigs);
8589 sigaddset (&sigs, SIGINT2);
8590 sigaddset (&sigs, SIGTERM15);
8591 sigaddset (&sigs, SIGWINCH28);
8592 sigaddset (&sigs, SIGCONT18);
8593
8594 sigprocmask (SIG_UNBLOCK1, &sigs, NULL((void*)0));
8595
8596#endif
8597#endif
8598}
8599
8600
8601___SCMOBJlong ___setup_tty_module
8602 ___P((void (*user_interrupt_handler) ___PVOID,(void (*user_interrupt_handler) (void), void (*terminate_interrupt_handler
) (void))
8603 void (*terminate_interrupt_handler) ___PVOID),(void (*user_interrupt_handler) (void), void (*terminate_interrupt_handler
) (void))
8604 (user_interrupt_handler,(void (*user_interrupt_handler) (void), void (*terminate_interrupt_handler
) (void))
8605 terminate_interrupt_handler)(void (*user_interrupt_handler) (void), void (*terminate_interrupt_handler
) (void))
8606void (*user_interrupt_handler) ___PVOID;(void (*user_interrupt_handler) (void), void (*terminate_interrupt_handler
) (void))
8607void (*terminate_interrupt_handler) ___PVOID;)(void (*user_interrupt_handler) (void), void (*terminate_interrupt_handler
) (void))
8608{
8609 if (___tty_mod.refcount == 0)
8610 {
8611 ___SCMOBJlong e;
8612
8613 ___tty_mod.mode_save_stack = NULL((void*)0);
8614
8615 ___tty_mod.user_interrupt_handler = user_interrupt_handler;
8616
8617 ___tty_mod.terminate_interrupt_handler = terminate_interrupt_handler;
8618
8619 if ((e = ___setup_user_interrupt_handling ()) != ___FIX(___NO_ERR)(((long)(0))<<2))
8620 return e;
8621 }
8622
8623 ___tty_mod.refcount++;
8624
8625 return ___FIX(___NO_ERR)(((long)(0))<<2);
8626}
8627
8628
8629void ___cleanup_tty_module ___PVOID(void)
8630{
8631 /********************* on Win32 this should be an InterlockedDecrement */
8632 if (--___tty_mod.refcount == 0)
8633 {
8634 ___cleanup_user_interrupt_handling ();
8635 }
8636}