sigar 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -1,1849 +0,0 @@
1
- /*
2
- * Copyright (C) 1991, 1992 by Chris Thewalt (thewalt@ce.berkeley.edu)
3
- *
4
- * Permission to use, copy, modify, and distribute this software
5
- * for any purpose and without fee is hereby granted, provided
6
- * that the above copyright notices appear in all copies and that both the
7
- * copyright notice and this permission notice appear in supporting
8
- * documentation. This software is provided "as is" without express or
9
- * implied warranty.
10
- */
11
- /*
12
- *************************** Motivation **********************************
13
-
14
- Many interactive programs read input line by line, but would like to
15
- provide line editing and history functionality to the end-user that
16
- runs the program.
17
-
18
- The input-edit package provides that functionality. As far as the
19
- programmer is concerned, the program only asks for the next line
20
- of input. However, until the user presses the RETURN key they can use
21
- emacs-style line editing commands and can traverse the history of lines
22
- previously typed.
23
-
24
- Other packages, such as GNU's readline, have greater capability but are
25
- also substantially larger. Input-edit is small, since it uses neither
26
- stdio nor any termcap features, and is also quite portable. It only uses
27
- \b to backspace and \007 to ring the bell on errors. Since it cannot
28
- edit multiple lines it scrolls long lines left and right on the same line.
29
-
30
- Input edit uses classic (not ANSI) C, and should run on any Unix
31
- system (BSD or SYSV), PC's with the MSC compiler, or Vax/VMS (untested by me).
32
- Porting the package to new systems basicaly requires code to read a
33
- character when it is typed without echoing it, everything else should be OK.
34
-
35
- I have run the package on:
36
-
37
- DECstation 5000, Ultrix 4.2 with cc and gcc
38
- Sun Sparc 2, SunOS 4.1.1, with cc
39
- SGI Iris, IRIX System V.3, with cc
40
- PC, DRDOS 5.0, with MSC 6.0
41
-
42
- The description below is broken into two parts, the end-user (editing)
43
- interface and the programmer interface. Send bug reports, fixes and
44
- enhancements to:
45
-
46
- Chris Thewalt (thewalt@ce.berkeley.edu)
47
- 2/4/92
48
-
49
- PS: I don't have, and don't want to add, a vi mode, sorry.
50
-
51
- ************************** End-User Interface ***************************
52
-
53
- Entering printable keys generally inserts new text into the buffer (unless
54
- in overwrite mode, see below). Other special keys can be used to modify
55
- the text in the buffer. In the description of the keys below, ^n means
56
- Control-n, or holding the CONTROL key down while pressing "n". M-B means
57
- Meta-B (or Alt-B). Errors will ring the terminal bell.
58
-
59
- ^A/^E : Move cursor to beginning/end of the line.
60
- ^F/^B : Move cursor forward/backward one character.
61
- ^D : Delete the character under the cursor.
62
- ^H, DEL : Delete the character to the left of the cursor.
63
- ^K : Kill from the cursor to the end of line.
64
- ^L : Redraw current line.
65
- ^O : Toggle overwrite/insert mode. Initially in insert mode. Text
66
- added in overwrite mode (including yanks) overwrite
67
- existing text, while insert mode does not overwrite.
68
- ^P/^N : Move to previous/next item on history list.
69
- ^R/^S : Perform incremental reverse/forward search for string on
70
- the history list. Typing normal characters adds to the current
71
- search string and searches for a match. Typing ^R/^S marks
72
- the start of a new search, and moves on to the next match.
73
- Typing ^H or DEL deletes the last character from the search
74
- string, and searches from the starting location of the last search.
75
- Therefore, repeated DEL's appear to unwind to the match nearest
76
- the point at which the last ^R or ^S was typed. If DEL is
77
- repeated until the search string is empty the search location
78
- begins from the start of the history list. Typing ESC or
79
- any other editing character accepts the current match and
80
- loads it into the buffer, terminating the search.
81
- ^T : Toggle the characters under and to the left of the cursor.
82
- ^U : Kill from beginning to the end of the line.
83
- ^Y : Yank previously killed text back at current location. Note that
84
- this will overwrite or insert, depending on the current mode.
85
- M-F/M-B : Move cursor forward/backward one word.
86
- M-D : Delete the word under the cursor.
87
- ^SPC : Set mark.
88
- ^W : Kill from mark to point.
89
- ^X : Exchange mark and point.
90
- TAB : By default adds spaces to buffer to get to next TAB stop
91
- (just after every 8th column), although this may be rebound by the
92
- programmer, as described below.
93
- NL, CR : returns current buffer to the program.
94
-
95
- DOS and ANSI terminal arrow key sequences are recognized, and act like:
96
-
97
- up : same as ^P
98
- down : same as ^N
99
- left : same as ^B
100
- right : same as ^F
101
-
102
- ************************** Programmer Interface ***************************
103
-
104
- The programmer accesses input-edit through five functions, and optionally
105
- through three additional function pointer hooks. The five functions are:
106
-
107
- char *Getline(char *prompt)
108
-
109
- Prints the prompt and allows the user to edit the current line. A
110
- pointer to the line is returned when the user finishes by
111
- typing a newline or a return. Unlike GNU readline, the returned
112
- pointer points to a static buffer, so it should not be free'd, and
113
- the buffer contains the newline character. The user enters an
114
- end-of-file by typing ^D on an empty line, in which case the
115
- first character of the returned buffer is '\0'. Getline never
116
- returns a NULL pointer. The getline function sets terminal modes
117
- needed to make it work, and resets them before returning to the
118
- caller. The getline function also looks for characters that would
119
- generate a signal, and resets the terminal modes before raising the
120
- signal condition. If the signal handler returns to getline,
121
- the screen is automatically redrawn and editing can continue.
122
- Getline now requires both the input and output stream be connected
123
- to the terminal (not redirected) so the main program should check
124
- to make sure this is true. If input or output have been redirected
125
- the main program should use buffered IO (stdio) rather than
126
- the slow 1 character read()s that getline uses (note: this limitation
127
- has been removed).
128
-
129
- char *Getlinem(int mode, char *prompt)
130
-
131
- mode: -1 = init, 0 = line mode, 1 = one char at a time mode, 2 = cleanup
132
-
133
- More specialized version of the previous function. Depending on
134
- the mode, it behaves differently. Its main use is to allow
135
- character by character input from the input stream (useful when
136
- in an X eventloop). It will return NULL as long as no newline
137
- has been received. Its use is typically as follows:
138
- 1) In the program initialization part one calls: Getlinem(-1,"prompt>")
139
- 2) In the X inputhandler: if ((line = Getlinem(1,NULL))) {
140
- 3) In the termination routine: Getlinem(2,NULL)
141
- With mode=0 the function behaves exactly like the previous function.
142
-
143
- void Gl_config(const char *which, int value)
144
-
145
- Set some config options. Which can be:
146
- "noecho": do not echo characters (used for passwd input)
147
- "erase": do erase line after return (used for text scrollers)
148
-
149
- void Gl_setwidth(int width)
150
-
151
- Set the width of the terminal to the specified width. The default
152
- width is 80 characters, so this function need only be called if the
153
- width of the terminal is not 80. Since horizontal scrolling is
154
- controlled by this parameter it is important to get it right.
155
-
156
- void Gl_histinit(char *file)
157
-
158
- This function reads a history list from file. So lines from a
159
- previous session can be used again.
160
-
161
- void Gl_histadd(char *buf)
162
-
163
- The Gl_histadd function checks to see if the buf is not empty or
164
- whitespace, and also checks to make sure it is different than
165
- the last saved buffer to avoid repeats on the history list.
166
- If the buf is a new non-blank string a copy is made and saved on
167
- the history list, so the caller can re-use the specified buf.
168
-
169
- The main loop in testgl.c, included in this directory, shows how the
170
- input-edit package can be used:
171
-
172
- extern char *Getline();
173
- extern void Gl_histadd();
174
- main()
175
- {
176
- char *p;
177
- Gl_histinit(".hist");
178
- do {
179
- p = Getline("PROMPT>>>> ");
180
- Gl_histadd(p);
181
- fputs(p, stdout);
182
- } while (*p != 0);
183
- }
184
-
185
- In order to allow the main program to have additional access to the buffer,
186
- to implement things such as completion or auto-indent modes, three
187
- function pointers can be bound to user functions to modify the buffer as
188
- described below. By default gl_in_hook and gl_out_hook are set to NULL,
189
- and gl_tab_hook is bound to a function that inserts spaces until the next
190
- logical tab stop is reached. The user can reassign any of these pointers
191
- to other functions. Each of the functions bound to these hooks receives
192
- the current buffer as the first argument, and must return the location of
193
- the leftmost change made in the buffer. If the buffer isn't modified the
194
- functions should return -1. When the hook function returns the screen is
195
- updated to reflect any changes made by the user function.
196
-
197
- int (*gl_in_hook)(char *buf)
198
-
199
- If gl_in_hook is non-NULL the function is called each time a new
200
- buffer is loaded. It is called when getline is entered, with an
201
- empty buffer, it is called each time a new buffer is loaded from
202
- the history with ^P or ^N, and it is called when an incremental
203
- search string is accepted (when the search is terminated). The
204
- buffer can be modified and will be redrawn upon return to Getline().
205
-
206
- int (*gl_out_hook)(char *buf)
207
-
208
- If gl_out_hook is non-NULL it is called when a line has been
209
- completed by the user entering a newline or return. The buffer
210
- handed to the hook does not yet have the newline appended. If the
211
- buffer is modified the screen is redrawn before getline returns the
212
- buffer to the caller.
213
-
214
- int (*gl_tab_hook)(char *buf, int prompt_width, int *cursor_loc)
215
-
216
- If gl_tab_hook is non-NULL, it is called whenever a tab is typed.
217
- In addition to receiving the buffer, the current prompt width is
218
- given (needed to do tabbing right) and a pointer to the cursor
219
- offset is given, where a 0 offset means the first character in the
220
- line. Not only does the cursor_loc tell the programmer where the
221
- TAB was received, but it can be reset so that the cursor will end
222
- up at the specified location after the screen is redrawn.
223
- */
224
-
225
- /* forward reference needed for gl_tab_hook */
226
- static int gl_tab(char *buf, int offset, int *loc);
227
-
228
- /********************* exported interface ********************************/
229
-
230
- static int (*gl_in_hook)(char *buf) = 0;
231
- static int (*gl_out_hook)(char *buf) = 0;
232
- static int (*gl_tab_hook)(char *buf, int prompt_width, int *loc) = gl_tab;
233
-
234
- /******************** imported interface *********************************/
235
- #ifdef DMALLOC
236
- /* reports leaks, which is the history buffer. dont care */
237
- #undef DMALLOC
238
- #endif
239
- #include "sigar_getline.h"
240
- #include "sigar_private.h"
241
- #include "sigar_util.h"
242
- #include <string.h>
243
- #include <ctype.h>
244
- #include <errno.h>
245
- #include <signal.h>
246
- #include <stdlib.h>
247
- #include <stdio.h>
248
-
249
- /******************** internal interface *********************************/
250
-
251
- static char *sigar_getlinem(int mode, char *prompt); /* allows reading char by char */
252
-
253
- static void sigar_getline_config(const char *which, int value); /* set some options */
254
-
255
- static void sigar_getline_clear_screen(void);
256
-
257
- #define BUF_SIZE 8096
258
-
259
- static int gl_init_done = -1; /* terminal mode flag */
260
- static int gl_notty = 0; /* 1 when not a tty */
261
- static int gl_eof = 0; /* 1 when not a tty and read() == -1 */
262
- static int gl_termw = 80; /* actual terminal width */
263
- static int gl_scroll = 27; /* width of EOL scrolling region */
264
- static int gl_width = 0; /* net size available for input */
265
- static int gl_extent = 0; /* how far to redraw, 0 means all */
266
- static int gl_overwrite = 0; /* overwrite mode */
267
- static int gl_no_echo = 0; /* do not echo input characters */
268
- static int gl_passwd = 0; /* do not echo input characters */
269
- static int gl_erase_line = 0; /* erase line before returning */
270
- static int gl_pos, gl_cnt = 0; /* position and size of input */
271
- static char gl_buf[BUF_SIZE]; /* input buffer */
272
- static char gl_killbuf[BUF_SIZE]=""; /* killed text */
273
- static char *gl_prompt; /* to save the prompt string */
274
- static char gl_intrc = 0; /* keyboard SIGINT char */
275
- static char gl_quitc = 0; /* keyboard SIGQUIT char */
276
- static char gl_suspc = 0; /* keyboard SIGTSTP char */
277
- static char gl_dsuspc = 0; /* delayed SIGTSTP char */
278
- static int gl_search_mode = 0; /* search mode flag */
279
- static int gl_bell_enabled = 0; /* bell mode */
280
- static int gl_savehist = 0; /* # of lines to save in hist file */
281
- static char gl_histfile[256]; /* name of history file */
282
-
283
- static void gl_init(); /* prepare to edit a line */
284
- static void gl_bell(); /* ring bell */
285
- static void gl_cleanup(); /* to undo gl_init */
286
- static void gl_char_init(); /* get ready for no echo input */
287
- static void gl_char_cleanup(); /* undo gl_char_init */
288
-
289
- static void gl_addchar(int c); /* install specified char */
290
- static void gl_del(int loc); /* del, either left (-1) or cur (0) */
291
- static void gl_error(char *buf); /* write error msg and die */
292
- static void gl_fixup(char *p, int c, int cur); /* fixup state variables and screen */
293
- static int gl_getc(); /* read one char from terminal */
294
- static void gl_kill(); /* delete to EOL */
295
- static void gl_newline(); /* handle \n or \r */
296
- static void gl_putc(int c); /* write one char to terminal */
297
- static void gl_puts(char *buf); /* write a line to terminal */
298
- static void gl_transpose(); /* transpose two chars */
299
- static void gl_yank(); /* yank killed text */
300
-
301
- static int is_whitespace(char c); /* "whitespace" very loosely interpreted */
302
- static void gl_back_1_word(); /* move cursor back one word */
303
- static void gl_kill_1_word(); /* kill to end of word */
304
- static void gl_kill_region(int i, int j); /* kills from i to j */
305
- static void gl_fwd_1_word(); /* move cursor forward one word */
306
- static void gl_set_mark(); /* sets mark to be at point */
307
- static void gl_exch(); /* exchanges point and mark */
308
- static void gl_wipe(); /* kills from mark to point */
309
- static int gl_mark = -1; /* position of mark. gl_mark<0 if not set */
310
-
311
- static void hist_init(); /* initializes hist pointers */
312
- static char *hist_next(); /* return ptr to next item */
313
- static char *hist_prev(); /* return ptr to prev item */
314
- static char *hist_save(char *p); /* makes copy of a string, without NL */
315
-
316
- static void search_addchar(int c); /* increment search string */
317
- static void search_term(); /* reset with current contents */
318
- static void search_back(int s); /* look back for current string */
319
- static void search_forw(int s); /* look forw for current string */
320
-
321
- /************************ nonportable part *********************************/
322
-
323
- #ifdef MSDOS
324
- #include <bios.h>
325
- #endif
326
-
327
- #ifdef WIN32
328
- # define MSDOS
329
- # include <io.h>
330
- # include <windows.h>
331
- #endif /* WIN32 */
332
-
333
- #ifdef __MWERKS__
334
- #define R__MWERKS
335
- #endif
336
-
337
- #ifdef R__MWERKS
338
- # include <unistd.h>
339
- #endif
340
-
341
- #if defined(_AIX) || defined(__Lynx__) || defined(__APPLE__)
342
- #define unix
343
- #endif
344
-
345
- #if defined(__hpux) || defined(__osf__) /* W.Karig@gsi.de */
346
- #ifndef unix
347
- #define unix
348
- #endif
349
- #endif
350
-
351
- #ifdef unix
352
- #include <unistd.h>
353
- #if !defined(__osf__) && !defined(_AIX) /* W.Karig@gsi.de */
354
- #include <sys/ioctl.h>
355
- #endif
356
-
357
- #if defined(__linux__) && defined(__powerpc__)
358
- # define R__MKLINUX // = linux on PowerMac
359
- #endif
360
- #if defined(__linux__) && defined(__alpha__)
361
- # define R__ALPHALINUX // = linux on Alpha
362
- #endif
363
-
364
- #if defined(TIOCGETP) && !defined(__sgi) && !defined(R__MKLINUX) && \
365
- !defined(R__ALPHALINUX) /* use BSD interface if possible */
366
- #include <sgtty.h>
367
- static struct sgttyb new_tty, old_tty;
368
- static struct tchars tch;
369
- static struct ltchars ltch;
370
- #else
371
- #ifdef SIGTSTP /* need POSIX interface to handle SUSP */
372
- #include <termios.h>
373
- #if defined(__sun) || defined(__sgi) || defined(R__MKLINUX) || \
374
- defined(R__ALPHALINUX)
375
- #undef TIOCGETP /* Solaris and SGI define TIOCGETP in <termios.h> */
376
- #undef TIOCSETP
377
- #endif
378
- static struct termios new_termios, old_termios;
379
- #else /* use SYSV interface */
380
- #include <termio.h>
381
- static struct termio new_termio, old_termio;
382
- #endif
383
- #endif
384
- #endif /* unix */
385
-
386
- #ifdef VMS
387
- #include <descrip.h>
388
- #include <ttdef.h>
389
- #include <iodef.h>
390
- #include <starlet.h>
391
- #include <unistd.h>
392
- #include unixio
393
-
394
- static int setbuff[2]; /* buffer to set terminal attributes */
395
- static short chan = -1; /* channel to terminal */
396
- struct dsc$descriptor_s descrip; /* VMS descriptor */
397
- #endif
398
-
399
- static void
400
- sigar_getline_config(const char *which, int value)
401
- {
402
- if (strcmp(which, "noecho") == 0)
403
- gl_no_echo = value;
404
- else if (strcmp(which, "erase") == 0)
405
- gl_erase_line = value;
406
- else
407
- printf("gl_config: %s ?\n", which);
408
- }
409
-
410
- static void
411
- gl_char_init() /* turn off input echo */
412
- {
413
- if (gl_notty) return;
414
- #ifdef unix
415
- #ifdef TIOCGETP /* BSD */
416
- ioctl(0, TIOCGETC, &tch);
417
- ioctl(0, TIOCGLTC, &ltch);
418
- gl_intrc = tch.t_intrc;
419
- gl_quitc = tch.t_quitc;
420
- gl_suspc = ltch.t_suspc;
421
- gl_dsuspc = ltch.t_dsuspc;
422
- ioctl(0, TIOCGETP, &old_tty);
423
- new_tty = old_tty;
424
- new_tty.sg_flags |= RAW;
425
- new_tty.sg_flags &= ~ECHO;
426
- ioctl(0, TIOCSETP, &new_tty);
427
- #else
428
- #ifdef SIGTSTP /* POSIX */
429
- tcgetattr(0, &old_termios);
430
- gl_intrc = old_termios.c_cc[VINTR];
431
- gl_quitc = old_termios.c_cc[VQUIT];
432
- #ifdef VSUSP
433
- gl_suspc = old_termios.c_cc[VSUSP];
434
- #endif
435
- #ifdef VDSUSP
436
- gl_dsuspc = old_termios.c_cc[VDSUSP];
437
- #endif
438
- new_termios = old_termios;
439
- new_termios.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF);
440
- new_termios.c_iflag |= (IGNBRK|IGNPAR);
441
- new_termios.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO);
442
- new_termios.c_cc[VMIN] = 1;
443
- new_termios.c_cc[VTIME] = 0;
444
- tcsetattr(0, TCSANOW, &new_termios);
445
- #else /* SYSV */
446
- ioctl(0, TCGETA, &old_termio);
447
- gl_intrc = old_termio.c_cc[VINTR];
448
- gl_quitc = old_termio.c_cc[VQUIT];
449
- new_termio = old_termio;
450
- new_termio.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF);
451
- new_termio.c_iflag |= (IGNBRK|IGNPAR);
452
- new_termio.c_lflag &= ~(ICANON|ISIG|ECHO);
453
- new_termio.c_cc[VMIN] = 1;
454
- new_termio.c_cc[VTIME] = 0;
455
- ioctl(0, TCSETA, &new_termio);
456
- #endif
457
- #endif
458
- #endif /* unix */
459
-
460
- #ifdef MSDOS
461
- gl_intrc = 'C' - '@';
462
- gl_quitc = 'Q' - '@';
463
- // gl_suspc = ltch.t_suspc;
464
- #endif /* MSDOS */
465
-
466
- #ifdef R__MWERKS
467
- gl_intrc = 'C' - '@';
468
- gl_quitc = 'Q' - '@';
469
- #endif
470
-
471
- #ifdef vms
472
- descrip.dsc$w_length = strlen("tt:");
473
- descrip.dsc$b_dtype = DSC$K_DTYPE_T;
474
- descrip.dsc$b_class = DSC$K_CLASS_S;
475
- descrip.dsc$a_pointer = "tt:";
476
- (void)sys$assign(&descrip,&chan,0,0);
477
- (void)sys$qiow(0,chan,IO$_SENSEMODE,0,0,0,setbuff,8,0,0,0,0);
478
- setbuff[1] |= TT$M_NOECHO;
479
- (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
480
- #endif /* vms */
481
- }
482
-
483
- static void
484
- gl_char_cleanup() /* undo effects of gl_char_init */
485
- {
486
- if (gl_notty) return;
487
- #ifdef unix
488
- #ifdef TIOCSETP /* BSD */
489
- ioctl(0, TIOCSETP, &old_tty);
490
- #else
491
- #ifdef SIGTSTP /* POSIX */
492
- tcsetattr(0, TCSANOW, &old_termios);
493
- #else /* SYSV */
494
- ioctl(0, TCSETA, &old_termio);
495
- #endif
496
- #endif
497
- #endif /* unix */
498
-
499
- #ifdef vms
500
- setbuff[1] &= ~TT$M_NOECHO;
501
- (void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
502
- sys$dassgn(chan);
503
- chan = -1;
504
- #endif
505
- }
506
-
507
- #if defined(MSDOS) && !defined(WIN32)
508
- // +DECK, PAUSE, T=XCC, IF=WINNT. (from KERNDOS.CAR )
509
- # include <conio.h>
510
- int pause_()
511
- {
512
- int first_char;
513
- first_char = _getch();
514
- if (first_char == 0 || first_char == 0xE0) first_char = -_getch();
515
- return first_char;
516
- }
517
- #endif
518
-
519
- #if defined(MSDOS) && defined(WIN32)
520
- //______________________________________________________________________________
521
- int pause_()
522
- {
523
- static HANDLE hConsoleInput = NULL;
524
- static iCharCount = 0;
525
- static int chLastChar = 0;
526
-
527
- DWORD cRead;
528
-
529
- INPUT_RECORD pirBuffer;
530
- KEY_EVENT_RECORD *KeyEvent= (KEY_EVENT_RECORD *)&(pirBuffer.Event);
531
-
532
- if (!hConsoleInput) hConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
533
-
534
- if (iCharCount) iCharCount--; // Whether several symbols had been read
535
- else {
536
- chLastChar = 0;
537
- while (chLastChar == 0) {
538
- if (!ReadConsoleInput(hConsoleInput, // handle of a console input buffer
539
- &pirBuffer, // address of the buffer for read data
540
- 1, // number of records to read
541
- &cRead // address of number of records read
542
- )) return 0;
543
-
544
- if (pirBuffer.EventType == KEY_EVENT && KeyEvent->bKeyDown == TRUE){
545
- iCharCount = KeyEvent->wRepeatCount - 1;
546
- chLastChar = ((int) (KeyEvent->uChar).AsciiChar & 0xffff);
547
- if (chLastChar)
548
- OemToCharBuff((char const *)&chLastChar,(char *)&chLastChar,1);
549
- else
550
- chLastChar = - (KeyEvent->wVirtualScanCode);
551
- // chLastChar = - (KeyEvent->wVirtualKeyCode);
552
- }
553
- }
554
- }
555
- return chLastChar;
556
-
557
- }
558
- #endif
559
-
560
- static int
561
- gl_getc()
562
- /* get a character without echoing it to screen */
563
- {
564
- #ifdef MSDOS
565
- # define k_ctrl_C 3
566
- # define k_ctrl_Z 26
567
- # define k_ctrl_Q 17
568
- # define k_ctrl_K 11
569
- # define k_rt_arr -77
570
- # define k_lt_arr -75
571
- # define k_up_arr -72
572
- # define k_dn_arr -80
573
- # define k_PGUP -73
574
- # define k_PGDW -81
575
- # define k_HOME -71
576
- # define k_END -79
577
- # define k_INS -82
578
- # define k_DEL -83
579
- # define k_ENTER 13
580
- # define k_CR 13
581
- # define k_BS 8
582
- # define k_ESC 27
583
- # define k_alt_H -35
584
- # define k_beep 7
585
- # ifndef WIN32
586
- int get_cursor__(int *,int *);
587
- int display_off__(int *);
588
- int display_on__();
589
- int locate_(int *,int *);
590
- int ixc, iyc;
591
- # endif
592
- int pause_();
593
- #endif
594
-
595
- int c;
596
-
597
- #if defined(unix)
598
- unsigned char ch;
599
- while ((c = (read(0, &ch, 1) > 0) ? ch : -1) == -1 && errno == EINTR)
600
- errno = 0;
601
- #endif
602
-
603
- #if defined(R__MWERKS)
604
- c = getchar();
605
- #endif
606
-
607
- #ifdef MSDOS
608
- c = pause_();
609
- if (c < 0) {
610
- switch (c) {
611
- case k_up_arr: c = 'P' - '@'; /* up -> ^P = 16 */
612
- break;
613
- case k_dn_arr: c = 'N' - '@'; /* down -> ^N = 14 */
614
- break;
615
- case k_lt_arr: c = 'B' - '@'; /* left -> ^B =2 */
616
- break;
617
- case k_rt_arr: c = 'F' - '@'; /* right -> ^F = 6*/
618
- break;
619
- case k_INS: c = 'O' - '@'; /* right -> ^O = 15*/
620
- break;
621
- case k_DEL: c = 'D' - '@'; /* Delete character under cursor = 4*/
622
- break;
623
- case k_END: c = 'E' - '@'; /* Moves cursor to end of line * = 5 */
624
- break;
625
- case k_HOME: c = 'A' - '@'; /* Moves cursor to beginning of line = 1*/
626
- break;
627
- default: c = 0; /* make it garbage */
628
- }
629
- }
630
- else {
631
- switch(c) {
632
- case k_ESC: c = 'U' - '@'; /* Clear full line -> ^U */
633
- break;
634
- default:
635
- break;
636
- }
637
- }
638
- #endif
639
-
640
- #ifdef vms
641
- if(chan < 0) {
642
- c='\0';
643
- }
644
- (void)sys$qiow(0,chan,IO$_TTYREADALL,0,0,0,&c,1,0,0,0,0);
645
- c &= 0177; /* get a char */
646
- #endif
647
- return c;
648
- }
649
-
650
- static void
651
- gl_putc(int c)
652
- {
653
- char ch = c;
654
-
655
- if (gl_notty) return;
656
-
657
- if ( !gl_passwd || !isgraph(c))
658
- {
659
- #ifdef WIN32
660
- CharToOemBuff((char const *)&c,&ch,1);
661
- #endif
662
-
663
- sigar_write(1, &ch, 1);
664
- }
665
- #if defined(unix) || defined(MSDOS) || defined(WIN32) || defined(R__MWERKS)
666
- #ifdef TIOCSETP /* BSD in RAW mode, map NL to NL,CR */
667
- if (ch == '\n') {
668
- ch = '\r';
669
- sigar_write(1, &ch, 1);
670
- }
671
- #endif
672
- #endif
673
- }
674
-
675
- /******************** fairly portable part *********************************/
676
-
677
- static void
678
- gl_puts(char *buf)
679
- {
680
- int len = strlen(buf);
681
-
682
- if (gl_notty) return;
683
- #ifdef WIN32
684
- {
685
- char *OemBuf = (char *)malloc(2*len);
686
- CharToOemBuff(buf,OemBuf,len);
687
- sigar_write(1, OemBuf, len);
688
- free(OemBuf);
689
- }
690
- #else
691
- sigar_write(1, buf, len);
692
- #endif
693
- }
694
-
695
- static void
696
- gl_error(char *buf)
697
- {
698
- int len = strlen(buf);
699
-
700
- gl_cleanup();
701
- #ifdef WIN32
702
- {
703
- char *OemBuf = (char *)malloc(2*len);
704
- CharToOemBuff(buf,OemBuf,len);
705
- sigar_write(2, OemBuf, len);
706
- free(OemBuf);
707
- }
708
- #else
709
- sigar_write(2, buf, len);
710
- #endif
711
- exit(1);
712
- }
713
-
714
- static void
715
- gl_init()
716
- /* set up variables and terminal */
717
- {
718
- if (gl_init_done < 0) { /* -1 only on startup */
719
- hist_init();
720
- }
721
- if (sigar_isatty(0) == 0 || sigar_isatty(1) == 0)
722
- gl_notty = 1;
723
- gl_char_init();
724
- gl_init_done = 1;
725
- }
726
-
727
- static void
728
- gl_bell()
729
- {
730
- if (gl_bell_enabled) {
731
- gl_putc('\007');
732
- }
733
- }
734
-
735
- static void
736
- gl_cleanup()
737
- /* undo effects of gl_init, as necessary */
738
- {
739
- if (gl_init_done > 0)
740
- gl_char_cleanup();
741
- gl_init_done = 0;
742
- }
743
-
744
- SIGAR_DECLARE(void)
745
- sigar_getline_setwidth(int w)
746
- {
747
- if (w > 20) {
748
- gl_termw = w;
749
- gl_scroll = w / 3;
750
- } else {
751
- gl_error("\n*** Error: minimum screen width is 21\n");
752
- }
753
- }
754
-
755
- SIGAR_DECLARE(void)
756
- sigar_getline_windowchanged()
757
- {
758
- #ifdef TIOCGWINSZ
759
- if (sigar_isatty(0)) {
760
- static char lenv[32], cenv[32];
761
- struct winsize wins;
762
- ioctl(0, TIOCGWINSZ, &wins);
763
-
764
- if (wins.ws_col == 0) wins.ws_col = 80;
765
- if (wins.ws_row == 0) wins.ws_row = 24;
766
-
767
- sigar_getline_setwidth(wins.ws_col);
768
-
769
- sprintf(lenv, "LINES=%d", wins.ws_row);
770
- putenv(lenv);
771
- sprintf(cenv, "COLUMNS=%d", wins.ws_col);
772
- putenv(cenv);
773
- }
774
- #endif
775
- }
776
-
777
- /* -1 = init, 0 = line mode, 1 = one char at a time mode, 2 = cleanup */
778
-
779
- static char *
780
- sigar_getlinem(int mode, char *prompt)
781
- {
782
- int c, loc, tmp;
783
- int sig;
784
-
785
- if (mode == 2) {
786
- gl_cleanup();
787
- return NULL;
788
- }
789
-
790
- if (mode < 1) {
791
- if (mode == -1) {
792
- sigar_getline_config("noecho", 0);
793
- sigar_getline_config("erase", 0);
794
- }
795
- gl_init();
796
- gl_prompt = (prompt)? prompt : (char*)"";
797
- gl_buf[0] = 0;
798
- if (gl_in_hook)
799
- gl_in_hook(gl_buf);
800
- gl_fixup(gl_prompt, -2, BUF_SIZE);
801
- if (mode == -1) return NULL;
802
- }
803
- while ((c = gl_getc()) >= 0) {
804
- gl_extent = 0; /* reset to full extent */
805
- #ifndef WIN32
806
- if (isprint(c)) {
807
- #else
808
- if (c >= ' ') {
809
- #endif
810
- if (gl_search_mode)
811
- search_addchar(c);
812
- else
813
- gl_addchar(c);
814
- } else {
815
- if (gl_search_mode) {
816
- if (c == '\033' || c == '\016' || c == '\020') {
817
- search_term();
818
- c = 0; /* ignore the character */
819
- } else if (c == '\010' || c == '\177') {
820
- search_addchar(-1); /* unwind search string */
821
- c = 0;
822
- } else if (c != '\022' && c != '\023') {
823
- search_term(); /* terminate and handle char */
824
- }
825
- }
826
- /* NOTE:
827
- * sometimes M-x turns on bit 8 ( M-x --> 'x' + 128 )
828
- * sometimes M-x prepends an escape character ( M-x --> '\033','x' )
829
- * both cases are handled ...
830
- */
831
- switch (c)
832
- {
833
- case 'b'+128: /* M-b */
834
- case 'B'+128: /* M-B */
835
- gl_back_1_word();
836
- break;
837
- case 'd'+128: /* M-d */
838
- case 'D'+128: /* M-D */
839
- gl_kill_1_word();
840
- break;
841
- case 'f'+128: /* M-f */
842
- case 'F'+128: /* M-F */
843
- gl_fwd_1_word();
844
- break;
845
- case '\000': /* ^SPC */
846
- gl_set_mark();
847
- break;
848
- case '\027': /* ^W */
849
- gl_wipe();
850
- break;
851
- case '\030': /* ^X */
852
- gl_exch();
853
- break;
854
- case '\n': /* newline */
855
- case '\r':
856
- gl_newline();
857
- gl_cleanup();
858
- return gl_buf;
859
- /*NOTREACHED*/
860
- break;
861
- case '\001': gl_fixup(gl_prompt, -1, 0); /* ^A */
862
- break;
863
- case '\002': gl_fixup(gl_prompt, -1, gl_pos-1); /* ^B */
864
- break;
865
- case '\004': /* ^D */
866
- if (gl_cnt == 0) {
867
- gl_buf[0] = 0;
868
- gl_cleanup();
869
- gl_putc('\n');
870
- return gl_buf;
871
- } else {
872
- gl_del(0);
873
- }
874
- break;
875
- case '\005': gl_fixup(gl_prompt, -1, gl_cnt); /* ^E */
876
- break;
877
- case '\006': gl_fixup(gl_prompt, -1, gl_pos+1); /* ^F */
878
- break;
879
- case '\010': case '\177': gl_del(-1); /* ^H and DEL */
880
- break;
881
- case '\t': /* TAB */
882
- if (gl_tab_hook) {
883
- tmp = gl_pos;
884
- loc = gl_tab_hook(gl_buf, strlen(gl_prompt), &tmp);
885
- if (loc >= 0 || tmp != gl_pos || loc == -2)
886
- gl_fixup(gl_prompt, loc, tmp);
887
- }
888
- break;
889
- case '\013': gl_kill(); /* ^K */
890
- break;
891
- case '\014': sigar_getline_clear_screen(); /* ^L */
892
- break;
893
- case '\016': /* ^N */
894
- strcpy(gl_buf, hist_next());
895
- if (gl_in_hook)
896
- gl_in_hook(gl_buf);
897
- gl_fixup(gl_prompt, 0, BUF_SIZE);
898
- break;
899
- case '\017': gl_overwrite = !gl_overwrite; /* ^O */
900
- break;
901
- case '\020': /* ^P */
902
- strcpy(gl_buf, hist_prev());
903
- if (gl_in_hook)
904
- gl_in_hook(gl_buf);
905
- gl_fixup(gl_prompt, 0, BUF_SIZE);
906
- break;
907
- case '\022': search_back(1); /* ^R */
908
- break;
909
- case '\023': search_forw(1); /* ^S */
910
- break;
911
- case '\024': gl_transpose(); /* ^T */
912
- break;
913
- case '\025': gl_fixup(gl_prompt,-1,0); gl_kill(); /* ^U */
914
- break;
915
- case '\031': gl_yank(); /* ^Y */
916
- break;
917
- case '\033':
918
- switch(c = gl_getc())
919
- {
920
- case 'b': /* M-b */
921
- case 'B': /* M-B */
922
- gl_back_1_word();
923
- break;
924
- case 'd': /* M-d */
925
- case 'D': /* M-D */
926
- gl_kill_1_word();
927
- break;
928
- case 'f': /* M-f */
929
- case 'F': /* M-F */
930
- gl_fwd_1_word();
931
- break;
932
- case '[': /* ansi arrow keys */
933
- case 'O': /* xterm arrow keys */
934
- switch(c = gl_getc())
935
- {
936
- case 'A': /* up */
937
- strcpy(gl_buf, hist_prev());
938
- if (gl_in_hook)
939
- gl_in_hook(gl_buf);
940
- gl_fixup(gl_prompt, 0, BUF_SIZE);
941
- break;
942
- case 'B': /* down */
943
- strcpy(gl_buf, hist_next());
944
- if (gl_in_hook)
945
- gl_in_hook(gl_buf);
946
- gl_fixup(gl_prompt, 0, BUF_SIZE);
947
- break;
948
- case 'C': gl_fixup(gl_prompt, -1, gl_pos+1); /* right */
949
- break;
950
- case 'D': gl_fixup(gl_prompt, -1, gl_pos-1); /* left */
951
- break;
952
- default: /* who knows */
953
- gl_bell();
954
- break;
955
- }
956
- break;
957
- default:
958
- gl_bell();
959
- }
960
- break;
961
- default: /* check for a terminal signal */
962
-
963
- #if defined(unix) || defined(WIN32) || defined(R__MWERKS)
964
- if (c > 0) { /* ignore 0 (reset above) */
965
- sig = 0;
966
- #ifdef SIGINT
967
- if (c == gl_intrc)
968
- sig = SIGINT;
969
- #endif
970
- #ifdef SIGQUIT
971
- if (c == gl_quitc)
972
- sig = SIGQUIT;
973
- #endif
974
- #ifdef SIGTSTP
975
- if (c == gl_suspc || c == gl_dsuspc)
976
- sig = SIGTSTP;
977
- #endif
978
- if (sig != 0) {
979
- gl_cleanup();
980
- #if !defined(WIN32)
981
- raise(sig);
982
- #endif
983
- #ifdef WIN32
984
- if (sig == SIGINT) GenerateConsoleCtrlEvent(CTRL_C_EVENT,0);
985
- else raise(sig);
986
- #endif
987
- gl_init();
988
- sigar_getline_redraw();
989
- c = 0;
990
- }
991
- }
992
- #endif /* unix */
993
- if (c > 0)
994
- gl_bell();
995
- break;
996
- }
997
- }
998
- if (mode == 1) return NULL;
999
- }
1000
- if (c == -1 && gl_notty)
1001
- gl_eof = 1;
1002
- else
1003
- gl_eof = 0;
1004
-
1005
- gl_cleanup();
1006
- gl_buf[0] = 0;
1007
- return gl_buf;
1008
- }
1009
-
1010
- SIGAR_DECLARE(int)
1011
- sigar_getline_eof()
1012
- {
1013
- return gl_eof;
1014
- }
1015
-
1016
- SIGAR_DECLARE(char *)
1017
- sigar_getline(char *prompt)
1018
- {
1019
- return sigar_getlinem(0, prompt);
1020
- }
1021
-
1022
- static void
1023
- gl_addchar(int c)
1024
- /* adds the character c to the input buffer at current location */
1025
- {
1026
- int i;
1027
-
1028
- if (gl_cnt >= BUF_SIZE - 1)
1029
- gl_error("\n*** Error: sigar_getline(): input buffer overflow\n");
1030
- if (gl_overwrite == 0 || gl_pos == gl_cnt) {
1031
- for (i=gl_cnt; i >= gl_pos; i--)
1032
- gl_buf[i+1] = gl_buf[i];
1033
- gl_buf[gl_pos] = c;
1034
- gl_fixup(gl_prompt, gl_pos, gl_pos+1);
1035
- } else {
1036
- gl_buf[gl_pos] = c;
1037
- gl_extent = 1;
1038
- gl_fixup(gl_prompt, gl_pos, gl_pos+1);
1039
- }
1040
- }
1041
-
1042
- static void
1043
- gl_yank()
1044
- /* adds the kill buffer to the input buffer at current location */
1045
- {
1046
- int i, len;
1047
-
1048
- len = strlen(gl_killbuf);
1049
- if (len > 0) {
1050
- gl_mark = gl_pos;
1051
- if (gl_overwrite == 0) {
1052
- if (gl_cnt + len >= BUF_SIZE - 1)
1053
- gl_error("\n*** Error: sigar_getline(): input buffer overflow\n");
1054
- for (i=gl_cnt; i >= gl_pos; i--)
1055
- gl_buf[i+len] = gl_buf[i];
1056
- for (i=0; i < len; i++)
1057
- gl_buf[gl_pos+i] = gl_killbuf[i];
1058
- gl_fixup(gl_prompt, gl_pos, gl_pos+len);
1059
- } else {
1060
- if (gl_pos + len > gl_cnt) {
1061
- if (gl_pos + len >= BUF_SIZE - 1)
1062
- gl_error("\n*** Error: sigar_getline(): input buffer overflow\n");
1063
- gl_buf[gl_pos + len] = 0;
1064
- }
1065
- for (i=0; i < len; i++)
1066
- gl_buf[gl_pos+i] = gl_killbuf[i];
1067
- gl_extent = len;
1068
- gl_fixup(gl_prompt, gl_pos, gl_pos+len);
1069
- }
1070
- } else
1071
- gl_bell();
1072
- }
1073
-
1074
- static void
1075
- gl_transpose()
1076
- /* switch character under cursor and to left of cursor */
1077
- {
1078
- int c;
1079
-
1080
- if (gl_pos > 0 && gl_cnt > gl_pos) {
1081
- c = gl_buf[gl_pos-1];
1082
- gl_buf[gl_pos-1] = gl_buf[gl_pos];
1083
- gl_buf[gl_pos] = c;
1084
- gl_extent = 2;
1085
- gl_fixup(gl_prompt, gl_pos-1, gl_pos);
1086
- } else
1087
- gl_bell();
1088
- }
1089
-
1090
- static void
1091
- gl_newline()
1092
- /*
1093
- * Cleans up entire line before returning to caller. A \n is appended.
1094
- * If line longer than screen, we redraw starting at beginning
1095
- */
1096
- {
1097
- int change = gl_cnt;
1098
- int len = gl_cnt;
1099
- int loc = gl_width - 5; /* shifts line back to start position */
1100
-
1101
- if (gl_cnt >= BUF_SIZE - 1)
1102
- gl_error("\n*** Error: sigar_getline(): input buffer overflow\n");
1103
- if (gl_out_hook) {
1104
- change = gl_out_hook(gl_buf);
1105
- len = strlen(gl_buf);
1106
- }
1107
- if (gl_erase_line) {
1108
- char gl_buf0 = gl_buf[0];
1109
- gl_buf[0] = '\0';
1110
- gl_fixup("", 0, 0);
1111
- gl_buf[0] = gl_buf0;
1112
- }
1113
- else {
1114
- if (loc > len)
1115
- loc = len;
1116
- gl_fixup(gl_prompt, change, loc); /* must do this before appending \n */
1117
- gl_putc('\n');
1118
- }
1119
- #if 0
1120
- gl_buf[len] = '\n';
1121
- gl_buf[len+1] = '\0';
1122
- #endif
1123
- gl_mark = -1;
1124
- }
1125
-
1126
- static void
1127
- gl_del(int loc)
1128
- /*
1129
- * Delete a character. The loc variable can be:
1130
- * -1 : delete character to left of cursor
1131
- * 0 : delete character under cursor
1132
- */
1133
- {
1134
- int i;
1135
-
1136
- if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
1137
- for (i=gl_pos+loc; i < gl_cnt; i++)
1138
- gl_buf[i] = gl_buf[i+1];
1139
- gl_fixup(gl_prompt, gl_pos+loc, gl_pos+loc);
1140
- } else
1141
- gl_bell();
1142
- }
1143
-
1144
- static void
1145
- gl_kill()
1146
- /* delete from current position to the end of line */
1147
- {
1148
- if (gl_pos < gl_cnt) {
1149
- strcpy(gl_killbuf, gl_buf + gl_pos);
1150
- gl_buf[gl_pos] = '\0';
1151
- gl_fixup(gl_prompt, gl_pos, gl_pos);
1152
- } else
1153
- gl_bell();
1154
- }
1155
-
1156
- SIGAR_DECLARE(void) sigar_getline_redraw(void)
1157
- /* emit a newline, reset and redraw prompt and current input line */
1158
- {
1159
- if (gl_init_done > 0) {
1160
- gl_putc('\n');
1161
- gl_fixup(gl_prompt, -2, gl_pos);
1162
- }
1163
- }
1164
-
1165
- #define CLEAR_SCREEN "\033[2J"
1166
-
1167
- static void sigar_getline_clear_screen(void)
1168
- {
1169
- if (gl_init_done > 0) {
1170
- gl_putc('\n');
1171
- /* XXX what to do for non-ansi term? */
1172
- gl_puts(CLEAR_SCREEN);
1173
- gl_fixup(gl_prompt, -2, gl_pos);
1174
- }
1175
- }
1176
-
1177
- SIGAR_DECLARE(void) sigar_getline_reset(void)
1178
- {
1179
- gl_fixup(gl_prompt,-1,0);
1180
- gl_kill();
1181
- }
1182
-
1183
- static void
1184
- gl_fixup(char *prompt, int change, int cursor)
1185
- /*
1186
- * This function is used both for redrawing when input changes or for
1187
- * moving within the input line. The parameters are:
1188
- * prompt: compared to last_prompt[] for changes;
1189
- * change : the index of the start of changes in the input buffer,
1190
- * with -1 indicating no changes, -2 indicating we're on
1191
- * a new line, redraw everything.
1192
- * cursor : the desired location of the cursor after the call.
1193
- * A value of BUF_SIZE can be used to indicate the cursor should
1194
- * move just past the end of the input line.
1195
- */
1196
- {
1197
- static int gl_shift; /* index of first on screen character */
1198
- static int off_right; /* true if more text right of screen */
1199
- static int off_left; /* true if more text left of screen */
1200
- static char last_prompt[BUF_SIZE] = "";
1201
- int left = 0, right = -1; /* bounds for redraw */
1202
- int padl; /* how much to erase at end of line */
1203
- int backup; /* how far to backup before fixing */
1204
- int new_shift; /* value of shift based on cursor */
1205
- int extra; /* adjusts when shift (scroll) happens */
1206
- int i;
1207
- int new_right = -1; /* alternate right bound, using gl_extent */
1208
- int l1, l2;
1209
-
1210
- if (change == -2) { /* reset */
1211
- gl_pos = gl_cnt = gl_shift = off_right = off_left = 0;
1212
- gl_passwd = 0;
1213
- gl_puts(prompt);
1214
- gl_passwd = gl_no_echo;
1215
- strcpy(last_prompt, prompt);
1216
- change = 0;
1217
- gl_width = gl_termw - strlen(prompt);
1218
- } else if (strcmp(prompt, last_prompt) != 0) {
1219
- l1 = strlen(last_prompt);
1220
- l2 = strlen(prompt);
1221
- gl_cnt = gl_cnt + l1 - l2;
1222
- strcpy(last_prompt, prompt);
1223
- backup = gl_pos - gl_shift + l1;
1224
- for (i=0; i < backup; i++)
1225
- gl_putc('\b');
1226
- gl_passwd = 0;
1227
- gl_puts(prompt);
1228
- gl_passwd = gl_no_echo;
1229
- gl_pos = gl_shift;
1230
- gl_width = gl_termw - l2;
1231
- change = 0;
1232
- }
1233
- padl = (off_right)? gl_width - 1 : gl_cnt - gl_shift; /* old length */
1234
- backup = gl_pos - gl_shift;
1235
- if (change >= 0) {
1236
- gl_cnt = strlen(gl_buf);
1237
- if (change > gl_cnt)
1238
- change = gl_cnt;
1239
- }
1240
- if (cursor > gl_cnt) {
1241
- if (cursor != BUF_SIZE) /* BUF_SIZE means end of line */
1242
- gl_bell();
1243
- cursor = gl_cnt;
1244
- }
1245
- if (cursor < 0) {
1246
- gl_bell();
1247
- cursor = 0;
1248
- }
1249
- if (off_right || (off_left && cursor < gl_shift + gl_width - gl_scroll / 2))
1250
- extra = 2; /* shift the scrolling boundary */
1251
- else
1252
- extra = 0;
1253
- new_shift = cursor + extra + gl_scroll - gl_width;
1254
- if (new_shift > 0) {
1255
- new_shift /= gl_scroll;
1256
- new_shift *= gl_scroll;
1257
- } else
1258
- new_shift = 0;
1259
- if (new_shift != gl_shift) { /* scroll occurs */
1260
- gl_shift = new_shift;
1261
- off_left = (gl_shift)? 1 : 0;
1262
- off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
1263
- left = gl_shift;
1264
- new_right = right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
1265
- } else if (change >= 0) { /* no scroll, but text changed */
1266
- if (change < gl_shift + off_left) {
1267
- left = gl_shift;
1268
- } else {
1269
- left = change;
1270
- backup = gl_pos - change;
1271
- }
1272
- off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
1273
- right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
1274
- new_right = (gl_extent && (right > left + gl_extent))?
1275
- left + gl_extent : right;
1276
- }
1277
- padl -= (off_right)? gl_width - 1 : gl_cnt - gl_shift;
1278
- padl = (padl < 0)? 0 : padl;
1279
- if (left <= right) { /* clean up screen */
1280
- for (i=0; i < backup; i++)
1281
- gl_putc('\b');
1282
- if (left == gl_shift && off_left) {
1283
- gl_putc('$');
1284
- left++;
1285
- }
1286
- for (i=left; i < new_right; i++)
1287
- gl_putc(gl_buf[i]);
1288
- gl_pos = new_right;
1289
- if (off_right && new_right == right) {
1290
- gl_putc('$');
1291
- gl_pos++;
1292
- } else {
1293
- for (i=0; i < padl; i++) /* erase remains of prev line */
1294
- gl_putc(' ');
1295
- gl_pos += padl;
1296
- }
1297
- }
1298
- i = gl_pos - cursor; /* move to final cursor location */
1299
- if (i > 0) {
1300
- while (i--)
1301
- gl_putc('\b');
1302
- } else {
1303
- for (i=gl_pos; i < cursor; i++)
1304
- gl_putc(gl_buf[i]);
1305
- }
1306
- gl_pos = cursor;
1307
- }
1308
-
1309
- static int
1310
- gl_tab(char *buf, int offset, int *loc)
1311
- /* default tab handler, acts like tabstops every 8 cols */
1312
- {
1313
- int i, count, len;
1314
-
1315
- len = strlen(buf);
1316
- count = 8 - (offset + *loc) % 8;
1317
- for (i=len; i >= *loc; i--)
1318
- buf[i+count] = buf[i];
1319
- for (i=0; i < count; i++)
1320
- buf[*loc+i] = ' ';
1321
- i = *loc;
1322
- *loc = i + count;
1323
- return i;
1324
- }
1325
-
1326
- /******************* History stuff **************************************/
1327
-
1328
- #ifndef HIST_SIZE
1329
- #define HIST_SIZE 100
1330
- #endif
1331
-
1332
- static int hist_pos = 0, hist_last = 0;
1333
- static char *hist_buf[HIST_SIZE];
1334
-
1335
- static void
1336
- hist_init()
1337
- {
1338
- int i;
1339
-
1340
- if (gl_savehist) return;
1341
-
1342
- hist_buf[0] = "";
1343
- for (i=1; i < HIST_SIZE; i++)
1344
- hist_buf[i] = (char *)0;
1345
- }
1346
-
1347
- SIGAR_DECLARE(void) sigar_getline_completer_set(sigar_getline_completer_t func)
1348
- {
1349
- if (func) {
1350
- gl_tab_hook = func;
1351
- }
1352
- else {
1353
- gl_tab_hook = gl_tab;
1354
- }
1355
- }
1356
-
1357
- SIGAR_DECLARE(void)
1358
- sigar_getline_histinit(char *file)
1359
- {
1360
- char line[256];
1361
- FILE *fp;
1362
- int nline = 1; /* prevent from becoming 0 */
1363
-
1364
- gl_savehist = 0;
1365
-
1366
- hist_init();
1367
-
1368
- if (!strcmp(file, "-")) return;
1369
-
1370
- sprintf(gl_histfile, "%s", file);
1371
-
1372
- fp = fopen(gl_histfile, "r");
1373
- if (fp)
1374
- while (fgets(line, 256, fp)) {
1375
- nline++;
1376
- sigar_getline_histadd(line);
1377
- }
1378
- else
1379
- fp = fopen(gl_histfile, "w");
1380
-
1381
- if (fp) fclose(fp);
1382
-
1383
- gl_savehist = nline;
1384
- }
1385
-
1386
- SIGAR_DECLARE(void)
1387
- sigar_getline_histadd(char *buf)
1388
- {
1389
- static char *prev = 0;
1390
- char *p = buf;
1391
- int len;
1392
-
1393
- while (*p == ' ' || *p == '\t' || *p == '\n')
1394
- p++;
1395
- if (*p) {
1396
- len = strlen(buf);
1397
- if (strchr(p, '\n')) /* previously line already has NL stripped */
1398
- len--;
1399
- if (prev == 0 || strlen(prev) != len ||
1400
- strncmp(prev, buf, len) != 0) {
1401
- hist_buf[hist_last] = hist_save(buf);
1402
- prev = hist_buf[hist_last];
1403
- hist_last = (hist_last + 1) % HIST_SIZE;
1404
- if (hist_buf[hist_last] && *hist_buf[hist_last]) {
1405
- free(hist_buf[hist_last]);
1406
- }
1407
- hist_buf[hist_last] = "";
1408
-
1409
- /* append command to history file */
1410
- if (gl_savehist) {
1411
- FILE *fp;
1412
- fp = fopen(gl_histfile, "a+");
1413
- if (fp) {
1414
- fprintf(fp, "%s\n", prev);
1415
- gl_savehist++;
1416
- fclose(fp);
1417
- }
1418
-
1419
- /* if more than HIST_SIZE lines, safe last 60 command and delete rest */
1420
- if (gl_savehist > HIST_SIZE) {
1421
- FILE *ftmp;
1422
- char tname[L_tmpnam];
1423
- char line[BUFSIZ];
1424
-
1425
- fp = fopen(gl_histfile, "r");
1426
- tmpnam(tname);
1427
- ftmp = fopen(tname, "w");
1428
- if (fp && ftmp) {
1429
- int nline = 0;
1430
- while (fgets(line, BUFSIZ, fp)) {
1431
- nline++;
1432
- gl_savehist = 1; /* prevent from becoming 0 */
1433
- if (nline > HIST_SIZE-60) {
1434
- gl_savehist++;
1435
- fprintf(ftmp, "%s", line);
1436
- }
1437
- }
1438
- }
1439
- if (fp) fclose(fp);
1440
- if (ftmp) fclose(ftmp);
1441
-
1442
- /* copy back to history file */
1443
- fp = fopen(gl_histfile, "w");
1444
- ftmp = fopen(tname, "r");
1445
- if (fp && ftmp)
1446
- while (fgets(line, BUFSIZ, ftmp))
1447
- fprintf(fp, "%s", line);
1448
-
1449
- if (fp) fclose(fp);
1450
- if (ftmp) fclose(ftmp);
1451
- remove(tname);
1452
- }
1453
- }
1454
- }
1455
- }
1456
- hist_pos = hist_last;
1457
- }
1458
-
1459
- static char *
1460
- hist_prev()
1461
- /* loads previous hist entry into input buffer, sticks on first */
1462
- {
1463
- char *p = 0;
1464
- int next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE;
1465
-
1466
- if (hist_buf[hist_pos] != 0 && next != hist_last) {
1467
- hist_pos = next;
1468
- p = hist_buf[hist_pos];
1469
- }
1470
- if (p == 0) {
1471
- p = "";
1472
- gl_bell();
1473
- }
1474
- return p;
1475
- }
1476
-
1477
- static char *
1478
- hist_next()
1479
- /* loads next hist entry into input buffer, clears on last */
1480
- {
1481
- char *p = 0;
1482
-
1483
- if (hist_pos != hist_last) {
1484
- hist_pos = (hist_pos+1) % HIST_SIZE;
1485
- p = hist_buf[hist_pos];
1486
- }
1487
- if (p == 0) {
1488
- p = "";
1489
- gl_bell();
1490
- }
1491
- return p;
1492
- }
1493
-
1494
- static char *
1495
- hist_save(char *p)
1496
- /* makes a copy of the string */
1497
- {
1498
- char *s = 0;
1499
- int len = strlen(p);
1500
- char *nl = strchr(p, '\n');
1501
-
1502
- if (nl) {
1503
- if ((s = (char *)malloc(len)) != 0) {
1504
- strncpy(s, p, len-1);
1505
- s[len-1] = 0;
1506
- }
1507
- } else {
1508
- if ((s = (char *)malloc(len+1)) != 0) {
1509
- strcpy(s, p);
1510
- }
1511
- }
1512
- if (s == 0)
1513
- gl_error("\n*** Error: hist_save() failed on malloc\n");
1514
- return s;
1515
- }
1516
-
1517
- /******************* Search stuff **************************************/
1518
-
1519
- static char search_prompt[101]; /* prompt includes search string */
1520
- static char search_string[100];
1521
- static int search_pos = 0; /* current location in search_string */
1522
- static int search_forw_flg = 0; /* search direction flag */
1523
- static int search_last = 0; /* last match found */
1524
-
1525
- static void
1526
- search_update(int c)
1527
- {
1528
- if (c == 0) {
1529
- search_pos = 0;
1530
- search_string[0] = 0;
1531
- search_prompt[0] = '?';
1532
- search_prompt[1] = ' ';
1533
- search_prompt[2] = 0;
1534
- } else if (c > 0) {
1535
- search_string[search_pos] = c;
1536
- search_string[search_pos+1] = 0;
1537
- search_prompt[search_pos] = c;
1538
- search_prompt[search_pos+1] = '?';
1539
- search_prompt[search_pos+2] = ' ';
1540
- search_prompt[search_pos+3] = 0;
1541
- search_pos++;
1542
- } else {
1543
- if (search_pos > 0) {
1544
- search_pos--;
1545
- search_string[search_pos] = 0;
1546
- search_prompt[search_pos] = '?';
1547
- search_prompt[search_pos+1] = ' ';
1548
- search_prompt[search_pos+2] = 0;
1549
- } else {
1550
- gl_bell();
1551
- hist_pos = hist_last;
1552
- }
1553
- }
1554
- }
1555
-
1556
- static void
1557
- search_addchar(int c)
1558
- {
1559
- char *loc;
1560
-
1561
- search_update(c);
1562
- if (c < 0) {
1563
- if (search_pos > 0) {
1564
- hist_pos = search_last;
1565
- } else {
1566
- gl_buf[0] = 0;
1567
- hist_pos = hist_last;
1568
- }
1569
- strcpy(gl_buf, hist_buf[hist_pos]);
1570
- }
1571
- if ((loc = strstr(gl_buf, search_string)) != 0) {
1572
- gl_fixup(search_prompt, 0, loc - gl_buf);
1573
- } else if (search_pos > 0) {
1574
- if (search_forw_flg) {
1575
- search_forw(0);
1576
- } else {
1577
- search_back(0);
1578
- }
1579
- } else {
1580
- gl_fixup(search_prompt, 0, 0);
1581
- }
1582
- }
1583
-
1584
- static void
1585
- search_term()
1586
- {
1587
- gl_search_mode = 0;
1588
- if (gl_buf[0] == 0) /* not found, reset hist list */
1589
- hist_pos = hist_last;
1590
- if (gl_in_hook)
1591
- gl_in_hook(gl_buf);
1592
- gl_fixup(gl_prompt, 0, gl_pos);
1593
- }
1594
-
1595
- static void
1596
- search_back(int new_search)
1597
- {
1598
- int found = 0;
1599
- char *p, *loc;
1600
-
1601
- search_forw_flg = 0;
1602
- if (gl_search_mode == 0) {
1603
- search_last = hist_pos = hist_last;
1604
- search_update(0);
1605
- gl_search_mode = 1;
1606
- gl_buf[0] = 0;
1607
- gl_fixup(search_prompt, 0, 0);
1608
- } else if (search_pos > 0) {
1609
- while (!found) {
1610
- p = hist_prev();
1611
- if (*p == 0) { /* not found, done looking */
1612
- gl_buf[0] = 0;
1613
- gl_fixup(search_prompt, 0, 0);
1614
- found = 1;
1615
- } else if ((loc = strstr(p, search_string)) != 0) {
1616
- strcpy(gl_buf, p);
1617
- gl_fixup(search_prompt, 0, loc - p);
1618
- if (new_search)
1619
- search_last = hist_pos;
1620
- found = 1;
1621
- }
1622
- }
1623
- } else {
1624
- gl_bell();
1625
- }
1626
- }
1627
-
1628
- static void
1629
- search_forw(int new_search)
1630
- {
1631
- int found = 0;
1632
- char *p, *loc;
1633
-
1634
- search_forw_flg = 1;
1635
- if (gl_search_mode == 0) {
1636
- search_last = hist_pos = hist_last;
1637
- search_update(0);
1638
- gl_search_mode = 1;
1639
- gl_buf[0] = 0;
1640
- gl_fixup(search_prompt, 0, 0);
1641
- } else if (search_pos > 0) {
1642
- while (!found) {
1643
- p = hist_next();
1644
- if (*p == 0) { /* not found, done looking */
1645
- gl_buf[0] = 0;
1646
- gl_fixup(search_prompt, 0, 0);
1647
- found = 1;
1648
- } else if ((loc = strstr(p, search_string)) != 0) {
1649
- strcpy(gl_buf, p);
1650
- gl_fixup(search_prompt, 0, loc - p);
1651
- if (new_search)
1652
- search_last = hist_pos;
1653
- found = 1;
1654
- }
1655
- }
1656
- } else {
1657
- gl_bell();
1658
- }
1659
- }
1660
- #if 0
1661
- /***********************************************************************
1662
- * *
1663
- * Strip blanks from both sides of a string. Space for the new *
1664
- * string is allocated and a pointer to it is returned. *
1665
- * *
1666
- ***********************************************************************/
1667
- char *strip(char *s)
1668
- {
1669
- char *r, *t1, *t2;
1670
- int l;
1671
-
1672
- l = strlen(s);
1673
- r = (char *)calloc(l+1, 1);
1674
-
1675
- if (l == 0) {
1676
- *r = '\0';
1677
- return r;
1678
- }
1679
-
1680
- /* get rid of leading blanks */
1681
- t1 = s;
1682
- while (*t1 == ' ')
1683
- t1++;
1684
-
1685
- t2 = s + l - 1;
1686
- while (*t2 == ' ' && t2 > s)
1687
- t2--;
1688
-
1689
- if (t1 > t2) {
1690
- *r = '\0';
1691
- return r;
1692
- }
1693
- strncpy(r, t1, (size_t) (t2-t1+1));
1694
-
1695
- return r;
1696
- }
1697
- #endif
1698
- /*****************************************************************************/
1699
- /* Extra routine provided by Christian Lacunza <lacunza@cdfsg5.lbl.gov> */
1700
- /*****************************************************************************/
1701
-
1702
- /* move cursor back to beginning of _current_ word */
1703
- /* unless it's already at the beginning, */
1704
- /* in which case it moves back to the beginning */
1705
- /* of the _previous_ word. */
1706
- static void gl_back_1_word( void )
1707
- {
1708
- int i = gl_pos;
1709
-
1710
- /* if we're at the beginning of a word, */
1711
- /* slip back into the preceeding whitespace */
1712
- if( i>0 && is_whitespace(gl_buf[i-1]) ) {
1713
- i-=1;
1714
- }
1715
-
1716
- /* now move back over all consecutive whitespace */
1717
- while( i>0 && is_whitespace(gl_buf[i]) ) {
1718
- i-=1;
1719
- }
1720
-
1721
- /* now keep moving back over all consecutive non-whitespace */
1722
- /* until we find the beginning of this word. */
1723
- /* ie. stop just before more whitespace shows up. */
1724
- while( i>0 && !is_whitespace(gl_buf[i-1]) ) {
1725
- i-=1;
1726
- }
1727
-
1728
- /* move the cursor here */
1729
- gl_fixup(gl_prompt, -1, i);
1730
- }
1731
-
1732
- /* kills from current position to end of word */
1733
- static void gl_kill_1_word( void )
1734
- {
1735
- int i = gl_pos;
1736
- int j = gl_pos;
1737
-
1738
- /* delete this: */
1739
- #if 0
1740
- /* not sure what to do with "punctuation" */
1741
- if( is_whitespace(gl_buf[j]) && gl_buf[j]!=' ' ) {
1742
- return;
1743
- }
1744
- /* first find a word */
1745
- while( j<gl_cnt && gl_buf[j]==' ' ) {
1746
- j+=1;
1747
- }
1748
- #endif
1749
-
1750
- /* first find a word */
1751
- while( j<gl_cnt && is_whitespace(gl_buf[j]) ) {
1752
- j+=1;
1753
- }
1754
-
1755
- /* next, find the end of this word. */
1756
- while( j<gl_cnt && !is_whitespace(gl_buf[j+1]) ) {
1757
- j+=1;
1758
- }
1759
-
1760
- /* kill */
1761
- gl_kill_region( i, j );
1762
-
1763
- /* fixup */
1764
- gl_fixup(gl_prompt, gl_pos, gl_pos);
1765
- }
1766
-
1767
- static void gl_kill_region( int i, int j )
1768
- {
1769
- /* copy to kill buffer */
1770
- strncpy( gl_killbuf, gl_buf+i, j-i+1 );
1771
- gl_killbuf[j-i+1]='\0';
1772
-
1773
- /* remove from gl_buf */
1774
- while( j<gl_cnt ) {
1775
- gl_buf[i]=gl_buf[j+1];
1776
- i+=1;
1777
- j+=1;
1778
- }
1779
- gl_buf[i]='\0';
1780
- }
1781
-
1782
- /* move cursor forward to the beginning of the next word. */
1783
- static void gl_fwd_1_word( void )
1784
- {
1785
- int i = gl_pos;
1786
-
1787
- /* move past all non-whitespace into the whitespace between words. */
1788
- while( i<gl_cnt && !is_whitespace(gl_buf[i]) ) {
1789
- i+=1;
1790
- }
1791
-
1792
- /* move past this whitespace to the beginning of the next word. */
1793
- while( i<gl_cnt && is_whitespace(gl_buf[i]) ) {
1794
- i+=1;
1795
- }
1796
-
1797
- /* move the cursor here. */
1798
- gl_fixup(gl_prompt, -1, i);
1799
- }
1800
-
1801
- /* NOTE: "whitespace" is very loosely defined. */
1802
- static int is_whitespace( char c )
1803
- {
1804
- int decent_character;
1805
-
1806
- decent_character = sigar_isalpha(c) || sigar_isdigit(c) || c=='_';
1807
-
1808
- return !decent_character;
1809
- }
1810
-
1811
- /* sets mark to be at point */
1812
- static void gl_set_mark( void )
1813
- {
1814
- gl_mark = gl_pos;
1815
- }
1816
-
1817
- /* kills from mark to point */
1818
- static void gl_wipe( void )
1819
- {
1820
- int left, right;
1821
-
1822
- if( gl_mark < 0 ) return;
1823
- if( gl_mark == gl_pos ) return;
1824
-
1825
- if( gl_mark < gl_pos ) {
1826
- left = gl_mark;
1827
- right = gl_pos;
1828
- }
1829
- else {
1830
- left = gl_pos;
1831
- right = gl_mark;
1832
- }
1833
-
1834
- gl_kill_region( left, right-1 );
1835
- gl_fixup( gl_prompt, left, left );
1836
- }
1837
-
1838
- /* echanges point and mark */
1839
- static void gl_exch( void )
1840
- {
1841
- int tmp;
1842
-
1843
- /* make sure mark is set */
1844
- if( gl_mark < 0 ) return;
1845
-
1846
- tmp = gl_pos;
1847
- gl_fixup( gl_prompt, -1, gl_mark );
1848
- gl_mark = tmp;
1849
- }