hyperic-sigar 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. data/COPYING +339 -0
  2. data/EXCEPTIONS +104 -0
  3. data/README +2 -0
  4. data/Rakefile +87 -0
  5. data/bindings/SigarWrapper.pm +2934 -0
  6. data/bindings/ruby/examples/cpu_info.rb +16 -0
  7. data/bindings/ruby/examples/df.rb +32 -0
  8. data/bindings/ruby/examples/free.rb +19 -0
  9. data/bindings/ruby/examples/ifconfig.rb +67 -0
  10. data/bindings/ruby/examples/netstat.rb +54 -0
  11. data/bindings/ruby/examples/pargs.rb +18 -0
  12. data/bindings/ruby/examples/penv.rb +14 -0
  13. data/bindings/ruby/examples/route.rb +31 -0
  14. data/bindings/ruby/examples/who.rb +13 -0
  15. data/bindings/ruby/extconf.rb +110 -0
  16. data/bindings/ruby/rbsigar.c +628 -0
  17. data/include/sigar.h +901 -0
  18. data/include/sigar_fileinfo.h +141 -0
  19. data/include/sigar_format.h +65 -0
  20. data/include/sigar_getline.h +18 -0
  21. data/include/sigar_log.h +82 -0
  22. data/include/sigar_private.h +365 -0
  23. data/include/sigar_ptql.h +55 -0
  24. data/include/sigar_util.h +192 -0
  25. data/src/os/aix/aix_sigar.c +1927 -0
  26. data/src/os/aix/sigar_os.h +71 -0
  27. data/src/os/darwin/darwin_sigar.c +3450 -0
  28. data/src/os/darwin/sigar_os.h +82 -0
  29. data/src/os/hpux/dlpi.c +284 -0
  30. data/src/os/hpux/hpux_sigar.c +1205 -0
  31. data/src/os/hpux/sigar_os.h +51 -0
  32. data/src/os/linux/linux_sigar.c +2595 -0
  33. data/src/os/linux/sigar_os.h +84 -0
  34. data/src/os/netware/netware_sigar.c +719 -0
  35. data/src/os/netware/sigar_os.h +26 -0
  36. data/src/os/osf1/osf1_sigar.c +593 -0
  37. data/src/os/osf1/sigar_os.h +42 -0
  38. data/src/os/solaris/get_mib2.c +321 -0
  39. data/src/os/solaris/get_mib2.h +127 -0
  40. data/src/os/solaris/hmekstat.h +77 -0
  41. data/src/os/solaris/kstats.c +182 -0
  42. data/src/os/solaris/procfs.c +99 -0
  43. data/src/os/solaris/sigar_os.h +225 -0
  44. data/src/os/solaris/solaris_sigar.c +2561 -0
  45. data/src/os/stub/sigar_os.h +8 -0
  46. data/src/os/stub/stub_sigar.c +303 -0
  47. data/src/os/win32/peb.c +213 -0
  48. data/src/os/win32/sigar_os.h +623 -0
  49. data/src/os/win32/sigar_pdh.h +49 -0
  50. data/src/os/win32/win32_sigar.c +3718 -0
  51. data/src/sigar.c +2292 -0
  52. data/src/sigar_cache.c +181 -0
  53. data/src/sigar_fileinfo.c +792 -0
  54. data/src/sigar_format.c +649 -0
  55. data/src/sigar_getline.c +1849 -0
  56. data/src/sigar_ptql.c +1966 -0
  57. data/src/sigar_signal.c +218 -0
  58. data/src/sigar_util.c +1061 -0
  59. data/version.properties +11 -0
  60. metadata +112 -0
@@ -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, &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
+ }