"Fossies" - the Fresh Open Source Software Archive 
Member "tin-2.6.2/src/getline.c" (9 Dec 2022, 18146 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "getline.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.4.5_vs_2.6.0.
1 /*
2 * Project : tin - a Usenet reader
3 * Module : getline.c
4 * Author : Chris Thewalt & Iain Lea
5 * Created : 1991-11-09
6 * Updated : 2021-02-23
7 * Notes : emacs style line editing input package.
8 * Copyright : (c) Copyright 1991-99 by Chris Thewalt & Iain Lea
9 * Permission to use, copy, modify, and distribute this
10 * software for any purpose and without fee is hereby
11 * granted, provided that the above copyright notices
12 * appear in all copies and that both the copyright
13 * notice and this permission notice appear in supporting
14 * documentation. This software is provided "as is" without
15 * express or implied warranty.
16 */
17
18 #ifndef TIN_H
19 # include "tin.h"
20 #endif /* !TIN_H */
21 #ifndef TCURSES_H
22 # include "tcurses.h"
23 #endif /* !TCURSES_H */
24
25 #define BUF_SIZE 1024
26 #define TAB_SIZE 4
27
28 #define CTRL_A '\001'
29 #define CTRL_B '\002'
30 #define CTRL_D '\004'
31 #define CTRL_E '\005'
32 #define CTRL_F '\006'
33 #define CTRL_H '\010'
34 #define CTRL_K '\013'
35 #define CTRL_L '\014'
36 #define CTRL_R '\022'
37 #define CTRL_N '\016'
38 #define CTRL_P '\020'
39 #define CTRL_U '\025'
40 #define CTRL_W '\027'
41 #define TAB '\t'
42 #define DEL '\177'
43
44 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
45 static wchar_t gl_buf[BUF_SIZE]; /* wide-character input buffer */
46 static char buf[BUF_SIZE];
47 #else
48 static char gl_buf[BUF_SIZE]; /* input buffer */
49 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
50 static const char *gl_prompt; /* to save the prompt string */
51 static int gl_width = 0; /* net size available for input */
52 static int gl_pos, gl_cnt = 0; /* position and size of input */
53 static t_bool is_passwd;
54
55 /*
56 * local prototypes
57 */
58 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
59 static void gl_addwchar(wint_t wc);
60 static int gl_tab(wchar_t *wbuf, int offset, int *loc);
61 #else
62 static void gl_addchar(int c);
63 static int gl_tab(char *buf, int offset, int *loc);
64 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
65 static void gl_del(int loc);
66 static void gl_fixup(int change, int cursor);
67 static void gl_newline(int w);
68 static void gl_kill(void);
69 static void gl_kill_back_word(void);
70 static void hist_add(int w);
71 static void hist_next(int w);
72 static void hist_prev(int w);
73
74 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
75 static int (*gl_in_hook) (wchar_t *) = 0;
76 static int (*gl_out_hook) (wchar_t *) = 0;
77 static int (*gl_tab_hook) (wchar_t *, int, int *) = gl_tab;
78 #else
79 static int (*gl_in_hook) (char *) = 0;
80 static int (*gl_out_hook) (char *) = 0;
81 static int (*gl_tab_hook) (char *, int, int *) = gl_tab;
82 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
83
84 char *
85 tin_getline(
86 const char *prompt,
87 int number_only, /* 1=positive numbers only, 2=negative too */
88 const char *str,
89 int max_chars,
90 t_bool passwd,
91 int which_hist)
92 {
93 int c, i, loc, tmp, gl_max;
94 char *tprompt;
95 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
96 wint_t wc;
97 #else
98 char *buf = gl_buf;
99 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
100
101 input_context = cGetline;
102
103 is_passwd = passwd;
104
105 set_xclick_off();
106 if (prompt == NULL)
107 prompt = "";
108
109 tprompt = strunc(prompt, cCOLS - 6);
110
111 gl_buf[0] = 0; /* used as end of input indicator */
112 gl_fixup(-1, 0); /* this resets gl_fixup */
113 gl_width = cCOLS - MIN(cCOLS - 6, strwidth(tprompt));
114 gl_prompt = tprompt;
115 gl_pos = gl_cnt = 0;
116
117 if (max_chars == 0) {
118 if (number_only)
119 gl_max = 10;
120 else
121 gl_max = BUF_SIZE;
122 } else
123 gl_max = max_chars;
124
125 my_fputs(tprompt, stdout);
126 cursoron();
127 my_flush();
128
129 if (gl_in_hook) {
130 loc = gl_in_hook(gl_buf);
131 if (loc >= 0)
132 gl_fixup(0, BUF_SIZE);
133 }
134
135 if (!cmd_line && gl_max == BUF_SIZE)
136 CleartoEOLN();
137
138 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
139 if (str != NULL) {
140 wchar_t *wbuf;
141
142 if ((wbuf = char2wchar_t(str)) != NULL) {
143 for (i = 0; wbuf[i]; i++)
144 gl_addwchar((wint_t) wbuf[i]);
145 free(wbuf);
146 }
147 }
148
149 while ((wc = ReadWch()) != WEOF) {
150 if ((gl_cnt < gl_max) && iswprint(wc)) {
151 if (number_only) {
152 if (iswdigit(wc)) {
153 gl_addwchar(wc);
154 /* Minus */
155 } else if (number_only == 2 && gl_pos == 0 && wc == (wint_t) '-') {
156 gl_addwchar(wc);
157 } else {
158 ring_bell();
159 }
160 } else
161 gl_addwchar(wc);
162 } else {
163 c = (int) wc;
164 switch (wc) {
165 #else
166 if (str != NULL) {
167 for (i = 0; str[i]; i++)
168 gl_addchar(str[i]);
169 }
170
171 while ((c = ReadCh()) != EOF) {
172 c &= 0xff;
173 if ((gl_cnt < gl_max) && my_isprint(c)) {
174 if (number_only) {
175 if (isdigit(c)) {
176 gl_addchar(c);
177 /* Minus */
178 } else if (number_only == 2 && gl_pos == 0 && c == '-') {
179 gl_addchar(c);
180 } else {
181 ring_bell();
182 }
183 } else
184 gl_addchar(c);
185 } else {
186 switch (c) {
187 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
188 case ESC: /* abort */
189 #ifdef HAVE_KEY_PREFIX
190 case KEY_PREFIX:
191 #endif /* HAVE_KEY_PREFIX */
192 switch (get_arrow_key(c)) {
193 case KEYMAP_UP:
194 case KEYMAP_PAGE_UP:
195 hist_prev(which_hist);
196 break;
197
198 case KEYMAP_PAGE_DOWN:
199 case KEYMAP_DOWN:
200 hist_next(which_hist);
201 break;
202
203 case KEYMAP_RIGHT:
204 gl_fixup(-1, gl_pos + 1);
205 break;
206
207 case KEYMAP_LEFT:
208 gl_fixup(-1, gl_pos - 1);
209 break;
210
211 case KEYMAP_HOME:
212 gl_fixup(-1, 0);
213 break;
214
215 case KEYMAP_END:
216 gl_fixup(-1, gl_cnt);
217 break;
218
219 case KEYMAP_DEL:
220 gl_del(0);
221 break;
222
223 case KEYMAP_INS:
224 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
225 gl_addwchar((wint_t) ' ');
226 #else
227 gl_addchar(' ');
228 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
229 break;
230
231 default:
232 input_context = cNone;
233 free(tprompt);
234 return NULL;
235 }
236 break;
237
238 case '\n': /* newline */
239 case '\r':
240 gl_newline(which_hist);
241 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
242 wcstombs(buf, gl_buf, BUF_SIZE - 1);
243 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
244 input_context = cNone;
245 free(tprompt);
246 return buf;
247
248 case CTRL_A:
249 gl_fixup(-1, 0);
250 break;
251
252 case CTRL_B:
253 gl_fixup(-1, gl_pos - 1);
254 break;
255
256 case CTRL_D:
257 if (gl_cnt == 0) {
258 gl_buf[0] = 0;
259 my_fputc('\n', stdout);
260 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
261 wcstombs(buf, gl_buf, BUF_SIZE - 1);
262 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
263 input_context = cNone;
264 free(tprompt);
265 return buf;
266 } else
267 gl_del(0);
268 break;
269
270 case CTRL_E:
271 gl_fixup(-1, gl_cnt);
272 break;
273
274 case CTRL_F:
275 gl_fixup(-1, gl_pos + 1);
276 break;
277
278 case CTRL_H:
279 case DEL:
280 gl_del(-1);
281 break;
282
283 case TAB:
284 if (gl_tab_hook) {
285 tmp = gl_pos;
286 loc = gl_tab_hook(gl_buf, (int) strlen(gl_prompt), &tmp);
287 if (loc >= 0 || tmp != gl_pos)
288 gl_fixup(loc, tmp);
289 }
290 break;
291
292 case CTRL_W:
293 gl_kill_back_word();
294 break;
295
296 case CTRL_U:
297 gl_fixup(-1, 0);
298 /* FALLTHROUGH */
299 case CTRL_K:
300 gl_kill();
301 break;
302
303 case CTRL_L:
304 case CTRL_R:
305 gl_redraw();
306 break;
307
308 case CTRL_N:
309 hist_next(which_hist);
310 break;
311
312 case CTRL_P:
313 hist_prev(which_hist);
314 break;
315
316 default:
317 ring_bell();
318 break;
319 }
320 }
321 }
322 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
323 wcstombs(buf, gl_buf, BUF_SIZE - 1);
324 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
325 input_context = cNone;
326 free(tprompt);
327 return buf;
328 }
329
330
331 /*
332 * adds the character c to the input buffer at current location if
333 * the character is in the allowed template of characters
334 */
335 static void
336 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
337 gl_addwchar(
338 wint_t wc)
339 #else
340 gl_addchar(
341 int c)
342 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
343 {
344 int i;
345
346 /*
347 * Crashing is always the worst solution IMHO. So as a quick hack,
348 * ignore characters silently, if buffer is full. To allow a final
349 * newline, leave space for one more character. Just a hack too.
350 * This was the original code:
351 *
352 if (gl_cnt >= BUF_SIZE - 1) {
353 error_message(2, "tin_getline: input buffer overflow");
354 giveup();
355 }
356 */
357 if (gl_cnt >= BUF_SIZE - 2)
358 return;
359
360 for (i = gl_cnt; i >= gl_pos; i--)
361 gl_buf[i + 1] = gl_buf[i];
362
363 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
364 gl_buf[gl_pos] = (wchar_t) wc;
365 #else
366 gl_buf[gl_pos] = c;
367 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
368 gl_fixup(gl_pos, gl_pos + 1);
369 }
370
371
372 /*
373 * Cleans up entire line before returning to caller. A \n is appended.
374 * If line longer than screen, we redraw starting at beginning
375 */
376 static void
377 gl_newline(
378 int w)
379 {
380 int change = gl_cnt;
381 int len = gl_cnt;
382 int loc = gl_width - 5; /* shifts line back to start position */
383
384 if (gl_cnt >= BUF_SIZE - 1) {
385 /*
386 * Like above: avoid crashing if possible. gl_addchar() now
387 * leaves one space left for the newline, so this part of the
388 * code should never be reached. A proper implementation is
389 * desirable though.
390 */
391 error_message(2, "tin_getline: input buffer overflow");
392 free(tin_progname);
393 giveup();
394 }
395 hist_add(w); /* only adds if nonblank */
396 if (gl_out_hook) {
397 change = gl_out_hook(gl_buf);
398 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
399 len = (int) wcslen(gl_buf);
400 #else
401 len = (int) strlen(gl_buf);
402 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
403 }
404 if (loc > len)
405 loc = len;
406 gl_fixup(change, loc); /* must do this before appending \n */
407 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
408 gl_buf[len] = (wchar_t) '\0';
409 #else
410 gl_buf[len] = '\0';
411 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
412 }
413
414
415 /*
416 * Delete a character. The loc variable can be:
417 * -1 : delete character to left of cursor
418 * 0 : delete character under cursor
419 */
420 static void
421 gl_del(
422 int loc)
423 {
424 int i;
425
426 if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
427 for (i = gl_pos + loc; i < gl_cnt; i++)
428 gl_buf[i] = gl_buf[i + 1];
429 gl_fixup(gl_pos + loc, gl_pos + loc);
430 } else
431 ring_bell();
432 }
433
434
435 /*
436 * delete from current position to the end of line
437 */
438 static void
439 gl_kill(
440 void)
441 {
442 if (gl_pos < gl_cnt) {
443 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
444 gl_buf[gl_pos] = (wchar_t) '\0';
445 #else
446 gl_buf[gl_pos] = '\0';
447 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
448 gl_fixup(gl_pos, gl_pos);
449 } else
450 ring_bell();
451 }
452
453
454 /*
455 * delete from the start of current or last word to current position
456 */
457 static void
458 gl_kill_back_word(
459 void)
460 {
461 int i, j, cur;
462
463 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
464 /* delete spaces */
465 for (i = gl_pos - 1; i >= 0 && iswspace((wint_t) gl_buf[i]); --i)
466 ;
467
468 /* delete not alnum characters but graph characters */
469 for (; i >= 0 && iswgraph((wint_t) gl_buf[i]) && !iswalnum((wint_t) gl_buf[i]); --i)
470 ;
471
472 /* delete all graph characters except '/' */
473 for (; i >= 0 && gl_buf[i] != (wchar_t) '/' && iswgraph((wint_t) gl_buf[i]); --i)
474 ;
475 #else
476 /* delete spaces */
477 for (i = gl_pos - 1; i >= 0 && isspace((int) gl_buf[i]); --i)
478 ;
479
480 /* delete not alnum characters but graph characters */
481 for (; i >= 0 && isgraph((int) gl_buf[i]) && !isalnum((int) gl_buf[i]); --i)
482 ;
483
484 /* delete all graph characters except '/' */
485 for (; i >= 0 && gl_buf[i] != '/' && isgraph((int) gl_buf[i]); --i)
486 ;
487 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
488
489 i++;
490 if (i != gl_pos) {
491 j = i;
492 cur = gl_pos;
493 gl_fixup(-1, i);
494
495 while (gl_buf[cur])
496 gl_buf[j++] = gl_buf[cur++];
497 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
498 gl_buf[j] = (wchar_t) '\0';
499 #else
500 gl_buf[j] = '\0';
501 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
502 gl_fixup(i, i);
503 } else
504 ring_bell();
505 }
506
507
508 /*
509 * emit a newline, reset and redraw prompt and current input line
510 */
511 void
512 gl_redraw(
513 void)
514 {
515 clear_message();
516 my_fputs(gl_prompt, stdout);
517 gl_pos = 0;
518 gl_fixup(0, BUF_SIZE);
519 cursoron();
520 }
521
522
523 /*
524 * This function is used both for redrawing when input changes or for
525 * moving within the input line. The parameters are:
526 * change : the index of the start of changes in the input buffer,
527 * with -1 indicating no changes.
528 * cursor : the desired location of the cursor after the call.
529 * A value of BUF_SIZE can be used to indicate the cursor
530 * should move just past the end of the input line.
531 */
532 static void
533 gl_fixup(
534 int change,
535 int cursor)
536 {
537 static int gl_shift; /* index of first on screen character */
538 static int off_right; /* true if more text right of screen */
539 static int off_left; /* true if more text left of screen */
540 int left = 0, right = -1; /* bounds for redraw */
541 int pad; /* how much to erase at end of line */
542 int backup; /* how far to backup before fixing */
543 int new_shift; /* value of shift based on cursor */
544 int extra; /* adjusts when shift (scroll) happens */
545 int i;
546 /* FIXME: there are some small problems if SCROLL >= gl_width - 2 */
547 int SCROLL = MIN(30, gl_width - 3);
548
549 if (change == -1 && cursor == 0 && gl_buf[0] == 0) { /* reset */
550 gl_shift = off_right = off_left = 0;
551 return;
552 }
553 pad = (off_right) ? gl_width - 1 : gl_cnt - gl_shift; /* old length */
554 backup = gl_pos - gl_shift;
555 if (change >= 0) {
556 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
557 gl_cnt = (int) wcslen(gl_buf);
558 #else
559 gl_cnt = (int) strlen(gl_buf);
560 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
561 if (change > gl_cnt)
562 change = gl_cnt;
563 }
564 if (cursor > gl_cnt) {
565 if (cursor != BUF_SIZE) /* BUF_SIZE means end of line */
566 ring_bell();
567 cursor = gl_cnt;
568 }
569 if (cursor < 0) {
570 ring_bell();
571 cursor = 0;
572 }
573 if (!is_passwd) {
574 if (off_right || (off_left && (cursor < gl_shift + gl_width - SCROLL / 2)))
575 extra = 2; /* shift the scrolling boundary */
576 else
577 extra = 0;
578 new_shift = cursor + extra + SCROLL - gl_width;
579 if (new_shift > 0) {
580 new_shift /= SCROLL;
581 new_shift *= SCROLL;
582 } else
583 new_shift = 0;
584 if (new_shift != gl_shift) { /* scroll occurs */
585 gl_shift = new_shift;
586 off_left = (gl_shift) ? 1 : 0;
587 off_right = (gl_cnt > gl_shift + gl_width - 1) ? 1 : 0;
588 left = gl_shift;
589 right = (off_right) ? gl_shift + gl_width - 2 : gl_cnt;
590 } else if (change >= 0) { /* no scroll, but text changed */
591 if (change < gl_shift + off_left)
592 left = gl_shift;
593 else {
594 left = change;
595 backup = gl_pos - change;
596 }
597 off_right = (gl_cnt > gl_shift + gl_width - 1) ? 1 : 0;
598 right = (off_right) ? gl_shift + gl_width - 2 : gl_cnt;
599 }
600 pad -= (off_right ? gl_width - 1 : gl_cnt - gl_shift);
601 pad = (pad < 0) ? 0 : pad;
602 if (left <= right) { /* clean up screen */
603 for (i = 0; i < backup; i++)
604 my_fputc('\b', stdout);
605 if (left == gl_shift && off_left) {
606 my_fputc('$', stdout);
607 left++;
608 }
609 for (i = left; i < right; i++) {
610 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
611 my_fputwc((wint_t) gl_buf[i], stdout);
612 #else
613 my_fputc(gl_buf[i], stdout);
614 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
615 }
616 if (off_right) {
617 my_fputc('$', stdout);
618 gl_pos = right + 1;
619 } else {
620 for (i = 0; i < pad; i++) /* erase remains of prev line */
621 my_fputc(' ', stdout);
622 gl_pos = right + pad;
623 }
624 }
625 i = gl_pos - cursor; /* move to final cursor location */
626 if (i > 0) {
627 while (i--)
628 my_fputc('\b', stdout);
629 } else {
630 for (i = gl_pos; i < cursor; i++) {
631 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
632 my_fputwc((wint_t) gl_buf[i], stdout);
633 #else
634 my_fputc(gl_buf[i], stdout);
635 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
636 }
637 }
638 my_flush();
639 }
640 gl_pos = cursor;
641 }
642
643
644 /*
645 * default tab handler, acts like tabstops every TAB_SIZE cols
646 */
647 static int
648 gl_tab(
649 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
650 wchar_t *wbuf,
651 #else
652 char *buf,
653 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
654 int offset,
655 int *loc)
656 {
657 int i, count, len;
658
659 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
660 len = (int) wcslen(wbuf);
661 count = TAB_SIZE - (offset + *loc) % TAB_SIZE;
662 for (i = len; i >= *loc; i--)
663 wbuf[i + count] = wbuf[i];
664 for (i = 0; i < count; i++)
665 wbuf[*loc + i] = (wchar_t) ' ';
666 #else
667 len = (int) strlen(buf);
668 count = TAB_SIZE - (offset + *loc) % TAB_SIZE;
669 for (i = len; i >= *loc; i--)
670 buf[i + count] = buf[i];
671 for (i = 0; i < count; i++)
672 buf[*loc + i] = ' ';
673 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
674 i = *loc;
675 *loc = i + count;
676 return i;
677 }
678
679
680 static void
681 hist_add(
682 int w)
683 {
684 char *p;
685 char *tmp;
686
687 if (w == HIST_NONE)
688 return;
689
690 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
691 if ((tmp = wchar_t2char(gl_buf)) == NULL)
692 return;
693 #else
694 tmp = my_strdup(gl_buf);
695 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
696
697 p = tmp;
698 while (*p == ' ' || *p == '\t') /* only save nonblank line */
699 p++;
700
701 if (*p) {
702 input_history[w][hist_last[w]] = tmp;
703 hist_last[w] = (hist_last[w] + 1) % HIST_SIZE;
704 FreeAndNull(input_history[w][hist_last[w]]); /* erase next location */
705 } else /* we didn't need tmp, so free it */
706 free(tmp);
707
708 hist_pos[w] = hist_last[w];
709 }
710
711
712 /*
713 * loads previous hist entry into input buffer, sticks on first
714 */
715 static void
716 hist_prev(
717 int w)
718 {
719 int next;
720 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
721 size_t size;
722 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
723
724 if (w == HIST_NONE)
725 return;
726
727 next = (hist_pos[w] - 1 + HIST_SIZE) % HIST_SIZE;
728 if (next != hist_last[w]) {
729 if (input_history[w][next]) {
730 hist_pos[w] = next;
731 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
732 if ((size = mbstowcs(gl_buf, input_history[w][hist_pos[w]], BUF_SIZE - 1)) == (size_t) -1)
733 size = 0;
734 gl_buf[size] = (wchar_t) '\0';
735 #else
736 strcpy(gl_buf, input_history[w][hist_pos[w]]);
737 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
738 } else
739 ring_bell();
740 } else
741 ring_bell();
742
743 if (gl_in_hook)
744 gl_in_hook(gl_buf);
745 gl_fixup(0, BUF_SIZE);
746 }
747
748
749 /*
750 * loads next hist entry into input buffer, clears on last
751 */
752 static void
753 hist_next(
754 int w)
755 {
756 if (w == HIST_NONE)
757 return;
758
759 if (hist_pos[w] != hist_last[w]) {
760 hist_pos[w] = (hist_pos[w] + 1) % HIST_SIZE;
761 if (input_history[w][hist_pos[w]]) {
762 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
763 size_t size;
764
765 if ((size = mbstowcs(gl_buf, input_history[w][hist_pos[w]], BUF_SIZE - 1)) == (size_t) -1)
766 size = 0;
767 gl_buf[size] = (wchar_t) '\0';
768 #else
769 strcpy(gl_buf, input_history[w][hist_pos[w]]);
770 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
771 } else
772 gl_buf[0] = 0;
773 } else
774 ring_bell();
775
776 if (gl_in_hook)
777 gl_in_hook(gl_buf);
778 gl_fixup(0, BUF_SIZE);
779 }