/*======================================================================*\ |* Editor mined *| |* dialog prompt functions *| \*======================================================================*/ #include "mined.h" #include "io.h" #include "termprop.h" FLAG char_on_status_line = False; /* is output active on status line ? */ FLAG input_active = False; /*======================================================================*\ |* Status and prompt buffer *| \*======================================================================*/ static char * lastinbuf; static FLAG lastattrib; static char status_buf [maxLINE_LEN]; static char * mnemo = NIL_PTR; /*======================================================================*\ |* Output functions for status line and prompt *| \*======================================================================*/ /* current position on status line */ int lpos = 0; /* extern only for keyboard mapping menu */ /* Did output on the bottom line wrap and scroll? */ static FLAG pagewrapped = False; static int bottom_lines = 0; /** Print line-end mark. */ static void print_mark () { reverse_off (); dim_on (); if (cjk_term) { put_cjkchar (encodedchar (0x300A)); /* 《 */ if (cjk_lineend_width == 2) { lpos ++; } } else { put_unichar ((character) RET_marker); } lpos ++; dim_off (); reverse_on (); } /** Print a byte to status line. Account for column position and possible line-wrap. */ static void print_byte (c) character c; { char_on_status_line = True; if (lpos > XBREAK_bottom - 1) { putstring ("\r\n"); lpos = 0; pagewrapped = True; bottom_lines ++; } if (c == '\n') { print_mark (); } else if (iscontrol (c)) { putchar ('^'); lpos ++; put_unichar (controlchar (c)); lpos ++; } else { putcharacter (c); lpos ++; } char_on_status_line = False; } /** Print a mapped character to status line. Account for column position and possible line-wrap. Only called if (mapped_text && ! combining_mode && encoding_has_combining ()) */ static void print_mapped (c, char_begin, line_begin) character c; char * char_begin; char * line_begin; { int width; unsigned long unichar = lookup_encodedchar (c); char_on_status_line = True; /* This would be generic; for combining_mode == False it's just width = 1; ... if (iscombined (unichar, char_begin, line_begin)) { width = 0; } else { width = 1; } */ width = 1; if (lpos > XBREAK_bottom - 2 + width) { putstring ("\r\n"); lpos = 0; pagewrapped = True; bottom_lines ++; } if (c == '\n') { print_mark (); } else if (iscontrol (c)) { putchar ('^'); lpos ++; put_unichar (controlchar (c)); lpos ++; } else { if (! combining_mode && combining_screen && iscombined (unichar, char_begin, line_begin)) { /* enforce separated display */ putcharacter (' '); putcharacter (c); } else { putcharacter (c); } lpos ++; } char_on_status_line = False; } /** Print a CJK character to status line. Line position and wrapping, as well as status line flag, are handled in input_cjk. */ static void print_cjk (c, width, char_begin, line_begin) unsigned long c; int width; char * char_begin; char * line_begin; { unsigned long unichar = lookup_encodedchar (c); if (encoding_has_combining () && iscombined (unichar, char_begin, line_begin)) { if (! combining_mode && combining_screen) { /* enforce separated display */ /* disp_separate_combining = True; */ /* combiningdisp_on (); */ if (width == 2) { put_cjkchar (encodedchar (0x3000)); put_cjkchar (c); } else { if (isjoined (unichar, char_begin, line_begin)) { /* prevent terminal ligature by substituting joining character with its ISOLATED FORM */ unichar = isolated_alef (unichar); c = encodedchar (unichar); if (no_char (c)) { put_cjkchar (encodedchar (0x2135)); } else { put_cjkchar (c); } } else { put_cjkchar (' '); put_cjkchar (c); } } } else if (! combining_screen) { /* disp_separate_combining = True; */ /* combiningdisp_on (); */ put_cjkchar (c); } else { put_cjkchar (c); } } else { put_cjkchar (c); } } /** Print a Unicode character to status line. Handle line position and wrapping, as well as status line flag. */ static void print_unichar (unichar, width, char_begin, line_begin) unsigned long unichar; int width; char * char_begin; char * line_begin; { char_on_status_line = True; if (width < 0) { width = uniscrwidth (unichar, char_begin, line_begin); } if (lpos > XBREAK_bottom - 2 + width) { putstring ("\r\n"); lpos = 0; pagewrapped = True; bottom_lines ++; } lpos += width; if (iscombined (unichar, char_begin, line_begin)) { if (! combining_mode && combining_screen) { /* enforce separated display */ /* disp_separate_combining = True; */ /* combiningdisp_on (); */ if (iswide (unichar)) { put_unichar (0x3000); put_unichar (unichar); } else { if (isjoined (unichar, char_begin, line_begin)) { /* prevent terminal ligature by substituting joining character with its ISOLATED FORM */ put_unichar (isolated_alef (unichar)); } else { put_unichar (' '); put_unichar (unichar); } } } else if (! combining_screen) { /* disp_separate_combining = True; */ /* combiningdisp_on (); */ put_unichar (unichar); } else { put_unichar (unichar); } } else { put_unichar (unichar); } char_on_status_line = False; } /** Print a string to status line, limited by screen width if limit > 0. */ static void printlim_string (text, limit, attributes) char * text; int limit; FLAG attributes; { int utfcount; unsigned long unichar; unsigned long cjkchar; int charwidth; char * start = text; char_on_status_line = True; while (* text != '\0') { if (text == mnemo) { diagdisp_off (); } if (utf8_text) { utf8_info (text, & utfcount, & unichar); charwidth = uniscrwidth (unichar, text, start); } else if (iscontrol ((character) * text)) { if (attributes && * text != '\n') { charwidth = 0; } else { charwidth = 2; } } else if (cjk_text) { cjkchar = charvalue (text); charwidth = cjkscrwidth (cjkchar, text, start); } else { charwidth = 1; } if (limit > 0 && lpos > limit - charwidth) { putmark (SHIFT_marker, UTF_SHIFT_marker); break; } if (lpos > XBREAK_bottom - 1) { putstring ("\r\n"); lpos = 0; pagewrapped = True; bottom_lines ++; } if (* text == '\n') { print_mark (); text ++; } else if (iscontrol ((character) * text)) { if (attributes) { switch (* text) { case '': unidisp_on (); break; case '': dim_on (); menuheader_on (); break; case '': disp_normal (); break; case '': diagdisp_on (); break; } text ++; } else { lpos += 2; putchar ('^'); put_unichar (controlchar (* text ++)); } } else if (utf8_text) { print_unichar (unichar, charwidth, text, start); text += utfcount; } else if (cjk_text) { /*int prev_lpos = lpos;*/ advance_char_scr (& text, & lpos, start); /*put_cjkchar (cjkchar, lpos - prev_lpos);*/ put_cjkchar (cjkchar); } else { lpos ++; putcharacter (* text ++); } } char_on_status_line = False; } /** Print a string to status line. */ static void print_string (text) register char * text; { printlim_string (text, 0, False); } /*======================================================================*\ |* Terminal dialog *| \*======================================================================*/ /* * promptyn reads in a 'y' or 'n' character. */ character promptyn () { register character c; while ((c = readcharacter ()) != 'y' && c != 'n' && c != '\033' && ! quit) { ring_bell (); flush (); } if (c == '\033') { quit = True; } return c; } #ifdef UNUSED /* * In case of a QUIT signal, swallow the dummy char generated by catchquit () * called by re_search () and change () */ void swallow_dummy_quit_char () { (void) readcharacter (); /* Swallow away a quit character delivered by QUIT */ /* Not needed because this character is ignored by being the CANCEL command */ } #endif /*======================================================================*\ |* Status line dialog and input *| \*======================================================================*/ /* Read numeric character value within prompt line. */ static unsigned long get_num_char (result, maxvalue) unsigned long * result; unsigned long maxvalue; { unsigned long c; unsigned long unichar = 0; int base = 16; int i = 0; unsigned long maxfill = 0; FLAG uniinput = False; diagdisp_off (); while (maxfill < maxvalue && ! quit) { flush (); c = readcharacter (); if (i == 0 && c == '#') { base = 8; } else if (i == 0 && c == '=') { base = 10; } else if (i == 0 && (c == 'u' || c == 'U' || c == '+')) { uniinput = True; maxvalue = 0x10FFFF; } else if ((c == '\b' || c == '\177') && i > 0) { i --; unichar /= base; maxfill /= base; putstring ("\b \b"); } else if (c >= '0' && c <= '9' && (base > 8 || c <= '7')) { i ++; unichar *= base; unichar += c - '0'; maxfill = maxfill * base + base - 1; print_byte (c); } else if (base == 16 && c >= 'A' && c <= 'F') { i ++; unichar *= base; unichar += c - 'A' + 10; maxfill = maxfill * base + base - 1; print_byte (c); } else if (base == 16 && c >= 'a' && c <= 'f') { i ++; unichar *= base; unichar += c - 'a' + 10; maxfill = maxfill * base + base - 1; print_byte (c); } else if (c == ' ' || c == '\n' || c == '\r') { break; } else { quit = True; break; } } if (quit) { ring_bell (); } while (i > 0) { putstring ("\b \b"); i --; } diagdisp_on (); if (uniinput && (cjk_text || mapped_text)) { * result = encodedchar (unichar); } else { * result = unichar; } return c; } /** Various auxiliary functions for input (). */ static char * input_byte (inbuf, ptr, c) char * inbuf; char * ptr; character c; { if (c > '\0' && (ptr - inbuf) < maxLINE_LEN) { if (mapped_text && ! combining_mode && encoding_has_combining ()) { print_mapped (c, ptr, inbuf); } else { print_byte (c); } putstring (" \b"); * ptr ++ = c; * ptr = '\0'; } else { ring_bell (); } if (mapped_text && combining_mode && encoding_has_combining ()) { if (iscombining (lookup_encodedchar (c))) { /* refresh display from base char, needed on xterm */ unsigned long uc; char * refreshptr = ptr; do { precede_char (& refreshptr, inbuf); c = charvalue (refreshptr); uc = lookup_encodedchar (c); } while (refreshptr != inbuf && iscombining (uc)); if (! iscombining (uc)) { putstring ("\b"); } /* Now refresh the whole combined character */ while (refreshptr < ptr) { c = charvalue (refreshptr ++); put_unichar (lookup_encodedchar (c)); } } } return ptr; } static char * input_cjk (inbuf, ptr, c) char * inbuf; char * ptr; unsigned long c; { character cjkbytes [5]; int len; int scrlen; character * cp; len = cjkencode (c, cjkbytes); if (len > 0 && (ptr - inbuf - 1 + len) < maxLINE_LEN) { scrlen = cjkscrwidth (c, ptr, inbuf); char_on_status_line = True; if (lpos > XBREAK_bottom - scrlen) { putstring ("\r\n"); lpos = 0; pagewrapped = True; bottom_lines ++; } print_cjk (c, scrlen, ptr, inbuf); cp = cjkbytes; while (* cp != '\0') { * ptr ++ = * cp; cp ++; } * ptr = '\0'; lpos += scrlen; char_on_status_line = False; putstring (" \b"); } else { ring_bell (); } if (combining_mode && encoding_has_combining ()) { if (iscombining (lookup_encodedchar (c))) { /* refresh display from base char, needed on xterm */ unsigned long uc; char * refreshptr = ptr; do { precede_char (& refreshptr, inbuf); c = charvalue (refreshptr); uc = lookup_encodedchar (c); } while (refreshptr != inbuf && iscombining (uc)); if (! iscombining (uc)) { if (cjkscrwidth (c, refreshptr, inbuf) == 2) { putstring ("\b\b"); } else { putstring ("\b"); } } /* Now refresh the whole combined character */ while (refreshptr < ptr) { c = charvalue (refreshptr); put_cjkchar (c); advance_char (& refreshptr); } } } return ptr; } static char * add_input_buf (ptr, c) char * ptr; character c; { * ptr ++ = c; return ptr; } static char * input_unicode (inbuf, ptr, unichar) char * inbuf; char * ptr; unsigned long unichar; { int utfcount; char * inputptr = ptr; if (unichar < 0x80) { return input_byte (inbuf, ptr, unichar); } else if (unichar < 0x800) { if ((ptr - inbuf) + 2 > maxLINE_LEN) { ring_bell (); } else { print_unichar (unichar, -1, inputptr, inbuf); ptr = add_input_buf (ptr, 0xC0 | (unichar >> 6)); ptr = add_input_buf (ptr, 0x80 | (unichar & 0x3F)); * ptr = '\0'; } } else if (unichar < 0x10000) { if ((ptr - inbuf) + 3 > maxLINE_LEN) { ring_bell (); } else { print_unichar (unichar, -1, inputptr, inbuf); ptr = add_input_buf (ptr, 0xE0 | (unichar >> 12)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 6) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | (unichar & 0x3F)); * ptr = '\0'; } } else if (unichar < 0x200000) { if ((ptr - inbuf) + 4 > maxLINE_LEN) { ring_bell (); } else { print_unichar (unichar, -1, inputptr, inbuf); ptr = add_input_buf (ptr, 0xF0 | (unichar >> 18)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 12) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 6) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | (unichar & 0x3F)); * ptr = '\0'; } } else if (unichar < 0x4000000) { if ((ptr - inbuf) + 5 > maxLINE_LEN) { ring_bell (); } else { print_unichar (unichar, -1, inputptr, inbuf); ptr = add_input_buf (ptr, 0xF8 | (unichar >> 24)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 18) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 12) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 6) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | (unichar & 0x3F)); * ptr = '\0'; } } else if (unichar < 0x80000000) { if ((ptr - inbuf) + 6 > maxLINE_LEN) { ring_bell (); } else { print_unichar (unichar, -1, inputptr, inbuf); ptr = add_input_buf (ptr, 0xFC | (unichar >> 30)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 24) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 18) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 12) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | ((unichar >> 6) & 0x3F)); ptr = add_input_buf (ptr, 0x80 | (unichar & 0x3F)); * ptr = '\0'; } } else { ring_bell (); } if (combining_mode) { if (iscombining (unichar)) { /* refresh display from base char, needed on xterm */ do { precede_char (& inputptr, inbuf); utf8_info (inputptr, & utfcount, & unichar); } while (inputptr != inbuf && iscombining (unichar)); if (! iscombining (unichar)) { if (iswide (unichar)) { putstring ("\b\b"); } else { putstring ("\b"); } } /* This also assumes utf8_screen == True because otherwise combining_mode would be False */ putstring (inputptr); } } putstring (" \b"); return ptr; } static char * input_character (inbuf, ptr, c) char * inbuf; char * ptr; unsigned long c; { if (no_char (c)) { ring_bell (); return ptr; } else if (c < 0x80) { return input_byte (inbuf, ptr, c); } else if (utf8_text) { return input_unicode (inbuf, ptr, c); } else if (cjk_text) { return input_cjk (inbuf, ptr, c); } else if (c < 0x100) { return input_byte (inbuf, ptr, c); } else { ring_bell (); return ptr; } } void redraw_prompt () { set_cursor (0, - MENU); while (bottom_lines > 0) { scroll_reverse (); bottom_lines --; } if (MENU && ! can_add_line) { displaymenuline (); } rd_bottom_line (); if (can_clear_eol) { clear_eol (); } } static char * erase1 (inbuf, ptr, all_combined) char * inbuf; char * ptr; FLAG all_combined; { FLAG need_refresh = False; diagdisp_off (); precede_char (& ptr, inbuf); if (iscontrol ((character) * ptr)) { if (* ptr == '\n' && (cjk_lineend_width == 1 || ! cjk_term)) { /* single-width newline indication */ putstring (" \b\b \b"); lpos = lpos - 1; } else { putstring (" \b\b\b \b\b"); lpos = lpos - 2; } } else { unsigned long charval = charvalue (ptr); int charwidth; if (combining_mode && encoding_has_combining ()) { if (all_combined) { while (ptr != inbuf && iscombined (unicode (charval), ptr, inbuf)) { precede_char (& ptr, inbuf); charval = charvalue (ptr); } } else if (iscombined (unicode (charval), ptr, inbuf)) { /* work-around for refresh of base character without or with fewer combining accents */ need_refresh = True; } } if (utf8_text) { charwidth = uniscrwidth (charval, ptr, inbuf); } else if (cjk_text) { charwidth = cjkscrwidth (charval, ptr, inbuf); } else if (mapped_text && combining_mode && encoding_has_combining () && iscombined (lookup_encodedchar (charval), ptr, inbuf)) { charwidth = 0; } else { charwidth = 1; } if (charwidth == 2) { putstring (" \b\b\b \b\b"); lpos = lpos - 2; } else if (charwidth == 1) { putstring (" \b\b \b"); lpos = lpos - 1; } } diagdisp_on (); putstring (" \b"); * ptr = '\0'; if (need_refresh) { redraw_prompt (); } return ptr; } static char * input_prefix (inbuf, ptr, ps) char * inbuf; char * ptr; struct prefixspec * ps; { unsigned long c = readcharacter_unicode_mapped (); if (command (c) == DPC) { if (mnemo == NIL_PTR ? ptr > inbuf : (char *) ptr > mnemo) { return erase1 (inbuf, ptr, False); } else { ring_bell (); return ptr; } } else if ((command (c) == CTRLINS && (c = readcharacter_unicode_mapped ()) == FUNcmd && (keyshift |= ctrl_mask)) || c == FUNcmd) { struct prefixspec * ps2 = lookup_prefix (keyproc, keyshift); if (ps2) { c = readcharacter_unicode_mapped (); if ((command (c) == CTRLINS && (c = readcharacter_unicode_mapped ()) == FUNcmd && (keyshift |= ctrl_mask)) || c == FUNcmd) { struct prefixspec * ps3 = lookup_prefix (keyproc, keyshift); if (ps3) { c = readcharacter_unicode_mapped (); c = compose_patterns (c, ps, ps2, ps3); return input_character (inbuf, ptr, c); } else { ring_bell (); return ptr; } } else { c = compose_patterns (c, ps, ps2, 0); return input_character (inbuf, ptr, c); } } else { ring_bell (); return ptr; } } else { c = compose_patterns (c, ps, 0, 0); return input_character (inbuf, ptr, c); } } static voidfunc command1 (c) unsigned long c; { voidfunc c0 = command (c); if (c0 == F12 && (keyshift & altshift_mask) == alt_mask) { return toggleKEYMAP; } else if (c0 == F12 && (keyshift & ctrlshift_mask) == ctrl_mask) { return setupKEYMAP; } else { return c0; } } /** Read prompt input. * Input () reads a string and echoes it on the prompt line. * Return values: * when QUIT character typed => ERRORS * when empty input and clearfl == True: NO_INPUT * otherwise: FINE */ static int input (inbuf, clearfl, term_input) char * inbuf; FLAG clearfl; char * term_input; { char * ptr; unsigned long c; unsigned long mnemoc; char * term_chars; ptr = inbuf; * ptr = '\0'; bottom_lines = 0; while (! quit) { if (lpos >= XBREAK_bottom) { pagewrapped = True; } if (lpos < 0) { redraw_prompt (); } while (True) { if (mnemo != NIL_PTR) { diagdisp_off (); putstring (" \b"); flush (); c = readcharacter (); } else { flush (); c = readcharacter_mapped (); } if (no_char (c)) { ring_bell (); } else { break; } } if (command (c) == SNL || command (c) == Popmark) { c = '\r'; } for (term_chars = term_input; * term_chars != '\0'; term_chars ++) { if (c == * term_chars) { c = '\n'; } } if (mnemo != NIL_PTR && (c == ' ' || c == '\n' || c == '\r' || c == quit_char || c == '\033')) { mnemoc = compose_mnemonic (mnemo); diagdisp_on (); /* restore prompt display, remove mnemonic */ while ((char *) ptr > mnemo) { ptr = erase1 (inbuf, ptr, True); } mnemo = NIL_PTR; if (c != quit_char && c != '\033') { ptr = input_character (inbuf, ptr, mnemoc); } } else if (c == quit_char) { ring_bell (); quit = True; } else if (allow_keymap && command1 (c) == toggleKEYMAP) { reverse_off (); toggleKEYMAP (); if (flags_changed) { displayflags (); } redraw_prompt (); } else if (allow_keymap && command1 (c) == setupKEYMAP) { reverse_off (); setupKEYMAP (); if (flags_changed) { displayflags (); } redraw_prompt (); } else if (command (c) == DPC) { if (mnemo == NIL_PTR ? ptr > inbuf : (char *) ptr > mnemo) { ptr = erase1 (inbuf, ptr, ! (keyshift & ctrl_mask)); } else { ring_bell (); } } else if (command (c) == CTRLINS) { c = readcharacter_unicode (); if (c == FUNcmd) { struct prefixspec * ps; keyshift |= ctrl_mask; ps = lookup_prefix (keyproc, keyshift); if (ps) { ptr = input_prefix (inbuf, ptr, ps); } else { ring_bell (); } } else if (c == '#') { unsigned long cx; do { cx = get_num_char (& c, max_char_value ()); if (quit) { quit = False; } else { ptr = input_character (inbuf, ptr, c); } } while (cx == ' '); } else if (c == ' ') { /* mark mnemonic start position in input buffer */ mnemo = (char *) ptr; diagdisp_off (); } else if (c > ' ' && c != 0x7F) { c = compose (c, readcharacter_unicode ()); if (no_char (c)) { ring_bell (); } else { ptr = input_character (inbuf, ptr, c); } } else { ptr = input_character (inbuf, ptr, c); } } else if (c == '\033') { quit = True; } else if (c == '\n' || c == '\r') { /* if inbuf is empty clear status line */ return (ptr == inbuf && clearfl) ? NO_INPUT : FINE; } else if (c == FUNcmd) { struct prefixspec * ps = lookup_prefix (keyproc, keyshift); if (ps) { ptr = input_prefix (inbuf, ptr, ps); } else { ring_bell (); } } else { ptr = input_character (inbuf, ptr, c); } } quit = False; return ERRORS; } /* * Show concatenation of s1 and s2 on the status line (bottom of screen) Set stat_visible only if bottom_line is visible. The return value is FINE except for get_string, where it is taken from the call to input (). status_line (str1, str2) is (void) bottom_line (True, (str1), (str2), NIL_PTR, False, "") status_msg (str) is status_line (str, NIL_PTR) status_beg (str) is (void) bottom_line (True, (str), NIL_PTR, NIL_PTR, True, "") error (str1) is (void) bottom_line (True, (str1), NIL_PTR, NIL_PTR, False, "") error2 (str1, str2) is (void) bottom_line (True, (str1), (str2), NIL_PTR, False, "") clear_status () is (void) bottom_line (False, NIL_PTR, NIL_PTR, NIL_PTR, False, "") get_string (str1, str2, fl, term_chars) is bottom_line (True, (str1), NIL_PTR, (str2), fl, term_chars) */ void status_uni (msg) char * msg; { FLAG save_utf8_text = utf8_text; utf8_text = True; /* don't need to save and set utf16_file = False; */ bottom_line (VALID, msg, NIL_PTR, NIL_PTR, False, ""); utf8_text = save_utf8_text; } /** get_string_uni prompts a string like get_string_nokeymap but uses Unicode input BEWARE: conflicts with RDwin! */ int get_string_uni (prompt, inbuf, statfl, term_input) char * prompt; char * inbuf; FLAG statfl; char * term_input; { int ret; /* push text encoding, temp. set to utf8 */ FLAG save_utf8_text = utf8_text; FLAG save_cjk_text = cjk_text; FLAG save_mapped_text = mapped_text; utf8_text = True; cjk_text = False; mapped_text = False; ret = get_string_nokeymap (prompt, inbuf, statfl, term_input); /* pop text encoding */ utf8_text = save_utf8_text; cjk_text = save_cjk_text; mapped_text = save_mapped_text; return ret; } void rd_bottom_line () { set_cursor (0, YMAX); diagdisp_on (); if (lastinbuf == NIL_PTR) { lpos = 0; if (lastattrib == VALID) { FLAG save_utf8_text = utf8_text; utf8_text = True; printlim_string (status_buf, XBREAK_bottom, True); utf8_text = save_utf8_text; } else { printlim_string (status_buf, XBREAK_bottom, False); } } else { lpos = 0; print_string (status_buf); print_string (lastinbuf); } if (! input_active) { diagdisp_off (); set_cursor_xy (); /* Set cursor back to old position */ } flush (); /* Perform the actual screen output */ } /** Clear or display status line, read prompt if desired. s1, s2: strings to display inbuf: buffer for prompt to read attrib: True: turn on reverse video on both strings False: don't (clear_status) VALID: interpret control chars in string for attributes */ int bottom_line (attrib, s1, s2, inbuf, statfl, term_input) FLAG attrib; char * s1; char * s2; char * inbuf; FLAG statfl; char * term_input; { int ret = FINE; if (inbuf != NIL_PTR) { * inbuf = '\0'; } lastinbuf = inbuf; lastattrib = attrib; if (pagewrapped) { status_buf [0] = '\0'; RD (); pagewrapped = False; } if (attrib == VALID && s1 && * s1 == '') { build_string (status_buf, "%s%s", unnull (s1), unnull (s2)); } else { build_string (status_buf, " %s%s ", unnull (s1), unnull (s2)); } if (attrib != False && stat_visible) { set_cursor (0, YMAX); clear_lastline (); } set_cursor (0, YMAX); if (attrib != False) { /* Print rev. start sequence */ diagdisp_on (); stat_visible = True; } else { /* Used as clear_status () */ diagdisp_off (); stat_visible = False; } if (inbuf == NIL_PTR) { lpos = 0; printlim_string (status_buf, XBREAK_bottom, attrib == VALID); } else { lpos = 0; print_string (status_buf); input_active = True; ret = input (inbuf, statfl, term_input); input_active = False; } /* Print normal video */ diagdisp_off (); /* set_cursor (lpos, YMAX); not needed; wouldn't work proportional */ if (can_clear_eol) { clear_eol (); } else { put_blanks (XMAX - 1 - lpos); if (proportional) { set_cursor (0, YMAX); diagdisp_on (); if (lastinbuf == NIL_PTR) { lpos = 0; printlim_string (status_buf, XBREAK_bottom, attrib == VALID); } else { lpos = 0; print_string (status_buf); print_string (lastinbuf); } /* pagewrapped ? diagdisp_off ()? */ } else { set_cursor (lpos, YMAX); } } if (inbuf != NIL_PTR) { set_cursor (0, YMAX); } else if (statfl) { diagdisp_on (); } else { set_cursor_xy (); /* Set cursor back to old position */ } flush (); /* Perform the actual screen output */ if (ret != FINE) { clear_status (); } return ret; } /* * Get_file () reads a filename from the terminal. */ int get_filename (message, file) char * message; char * file; { int ret = get_string (message, file, True, ""); #ifndef msdos char * filei; char file1 [maxLINE_LEN]; if (file [0] == '~' && (file [1] == '/' || file [1] == '\0')) { filei = file; filei ++; build_string (file1, "%s%s", envvar ("HOME"), filei); build_string (file, file1); } #endif return ret; } /*======================================================================*\ |* Number input *| \*======================================================================*/ /* * get_number () reads a number from the terminal. * prompt_num_char () prompts for a numeric character from the terminal. * If the parameter firstdigit is a valid digit, empty input (return) * will yield a valid number; if it is '\0', it won't. * The last character typed in is returned. * ERRORS is returned on a bad number or on interrupted input. * The resulting number is put into the integer the argument points to. */ long get_number (message, firstdigit, result) char * message; char firstdigit; int * result; { long ch; int value; int i = 0; status_beg (message); if (firstdigit > '\0') { ch = firstdigit; } else { ch = readcharacter_mapped (); } if (ch == quit_char || ch == '\033') { quit = True; } if (! quit && (ch < '0' || ch > '9')) { error ("Bad number"); return ERRORS; } /* Convert input to a decimal number */ value = 0; while (! quit && ((ch >= '0' && ch <= '9') || ch == '\b' || ch == '\177')) { if (ch == '\b' || ch == '\177') { if (i > 0) { i --; value /= 10; putstring ("\b \b"); flush (); if (lpos >= XBREAK_bottom) { pagewrapped = True; } lpos --; } } else { i ++; print_byte (ch); flush (); if (lpos >= XBREAK_bottom) { pagewrapped = True; } value *= 10; value += ch - '0'; } ch = readcharacter_mapped (); if (ch == quit_char || ch == '\033') { quit = True; } } clear_status (); if (quit) { clear_status (); return ERRORS; } * result = value; return ch; } /* Prompt for hex or octal character value. */ int prompt_num_char (result, maxvalue) unsigned long * result; unsigned long maxvalue; { unsigned long ch; int value = 0; int i; FLAG ok = False; FLAG uniinput = False; int base = 16; unsigned long maxfill = 0; if (cjk_text || mapped_text) { status_beg ("Enter character code value (hex / # oct / = dec / u unicode) ..."); } else { status_beg ("Enter character code value (hex / # oct / = dec) ..."); } i = 0; while (maxfill < maxvalue && ! ok) { ch = readcharacter (); if (i == 0) { if (ch == '#') { base = 8; print_string ("(oct) "); flush (); continue; } else if (ch == '=') { base = 10; print_string ("(dec) "); flush (); continue; } else if (ch == 'u' || ch == 'U' || ch == '+') { uniinput = True; maxvalue = 0x10FFFF; print_string ("(uni) "); flush (); continue; } } if (ch >= '0' && ch <= '9' && (ch <= '7' || base > 8)) { i ++; value *= base; value += ch - '0'; maxfill = maxfill * base + base - 1; print_byte (ch); flush (); } else if (base == 16 && ch >= 'A' && ch <= 'F') { i ++; value *= base; value += ch - 'A' + 10; maxfill = maxfill * base + base - 1; print_byte (ch); flush (); } else if (base == 16 && ch >= 'a' && ch <= 'f') { i ++; value *= base; value += ch - 'a' + 10; maxfill = maxfill * base + base - 1; ch = ch - 'a' + 'A'; print_byte (ch); flush (); } else if (ch == '\b' || ch == '\177') { if (i > 0) { i --; value /= base; maxfill /= base; putstring ("\b \b"); flush (); if (lpos >= XBREAK_bottom) { pagewrapped = True; } lpos --; } } else if (ch == '\033' || ch == quit_char) { clear_status (); return ERRORS; } else if (ch == ' ' || ch == '\n' || ch == '\r') { if (i == 0) { clear_status (); return ERRORS; } ok = True; } else { quit = True; ok = True; } if (lpos >= XBREAK_bottom) { pagewrapped = True; } } clear_status (); if (quit) { if (base == 16) { error ("Bad hex value"); } else if (base == 8) { error ("Bad octal value"); } else { error ("Bad decimal value"); } quit = False; return ERRORS; } if (uniinput && (cjk_text || mapped_text)) { * result = encodedchar (value); } else { * result = value; } return ch; } /*======================================================================*\ |* End *| \*======================================================================*/