sigar-test 0.7.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/NOTICE +117 -0
- data/README +2 -0
- data/Rakefile +105 -0
- data/bindings/SigarBuild.pm +301 -0
- data/bindings/SigarWrapper.pm +3025 -0
- data/bindings/ruby/extconf.rb +131 -0
- data/bindings/ruby/rbsigar.c +888 -0
- data/include/sigar.h +984 -0
- data/include/sigar_fileinfo.h +157 -0
- data/include/sigar_format.h +65 -0
- data/include/sigar_getline.h +18 -0
- data/include/sigar_log.h +80 -0
- data/include/sigar_private.h +429 -0
- data/include/sigar_ptql.h +53 -0
- data/include/sigar_util.h +197 -0
- data/src/os/aix/aix_sigar.c +2168 -0
- data/src/os/aix/sigar_os.h +73 -0
- data/src/os/darwin/Info.plist.in +27 -0
- data/src/os/darwin/darwin_sigar.c +3718 -0
- data/src/os/darwin/sigar_os.h +80 -0
- data/src/os/hpux/hpux_sigar.c +1361 -0
- data/src/os/hpux/sigar_os.h +49 -0
- data/src/os/linux/linux_sigar.c +2810 -0
- data/src/os/linux/sigar_os.h +82 -0
- data/src/os/solaris/get_mib2.c +321 -0
- data/src/os/solaris/get_mib2.h +127 -0
- data/src/os/solaris/kstats.c +181 -0
- data/src/os/solaris/procfs.c +97 -0
- data/src/os/solaris/sigar_os.h +224 -0
- data/src/os/solaris/solaris_sigar.c +2732 -0
- data/src/os/win32/peb.c +212 -0
- data/src/os/win32/sigar.rc.in +40 -0
- data/src/os/win32/sigar_os.h +685 -0
- data/src/os/win32/sigar_pdh.h +47 -0
- data/src/os/win32/win32_sigar.c +4109 -0
- data/src/sigar.c +2444 -0
- data/src/sigar_cache.c +253 -0
- data/src/sigar_fileinfo.c +815 -0
- data/src/sigar_format.c +696 -0
- data/src/sigar_getline.c +1849 -0
- data/src/sigar_ptql.c +1976 -0
- data/src/sigar_signal.c +216 -0
- data/src/sigar_util.c +1060 -0
- data/src/sigar_version.c.in +22 -0
- data/src/sigar_version_autoconf.c.in +22 -0
- data/version.properties +11 -0
- metadata +91 -0
data/src/sigar_getline.c
ADDED
@@ -0,0 +1,1849 @@
|
|
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, <ch);
|
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
|
+
}
|