void my_regex_init(CHARSET_INFO *cs, my_regex_stack_check_t func) { char buff[CCLASS_LAST][256]; int count[CCLASS_LAST]; uint i; if (!regex_inited) { regex_inited=1; my_regex_enough_mem_in_stack= func; bzero((uchar*) &count,sizeof(count)); for (i=1 ; i<= 255; i++) { if (my_isalnum(cs,i)) buff[CCLASS_ALNUM][count[CCLASS_ALNUM]++]=(char) i; if (my_isalpha(cs,i)) buff[CCLASS_ALPHA][count[CCLASS_ALPHA]++]=(char) i; if (my_iscntrl(cs,i)) buff[CCLASS_CNTRL][count[CCLASS_CNTRL]++]=(char) i; if (my_isdigit(cs,i)) buff[CCLASS_DIGIT][count[CCLASS_DIGIT]++]=(char) i; if (my_isgraph(cs,i)) buff[CCLASS_GRAPH][count[CCLASS_GRAPH]++]=(char) i; if (my_islower(cs,i)) buff[CCLASS_LOWER][count[CCLASS_LOWER]++]=(char) i; if (my_isprint(cs,i)) buff[CCLASS_PRINT][count[CCLASS_PRINT]++]=(char) i; if (my_ispunct(cs,i)) buff[CCLASS_PUNCT][count[CCLASS_PUNCT]++]=(char) i; if (my_isspace(cs,i)) buff[CCLASS_SPACE][count[CCLASS_SPACE]++]=(char) i; if (my_isupper(cs,i)) buff[CCLASS_UPPER][count[CCLASS_UPPER]++]=(char) i; if (my_isxdigit(cs,i)) buff[CCLASS_XDIGIT][count[CCLASS_XDIGIT]++]=(char) i; } buff[CCLASS_BLANK][0]=' '; buff[CCLASS_BLANK][1]='\t'; count[CCLASS_BLANK]=2; for (i=0; i < CCLASS_LAST ; i++) { char *tmp=(char*) malloc(count[i]+1); if (!tmp) { /* This is very unlikely to happen as this function is called once at program startup */ fprintf(stderr, "Fatal error: Can't allocate memory in regex_init\n"); exit(1); } memcpy(tmp,buff[i],count[i]*sizeof(char)); tmp[count[i]]=0; cclasses[i].chars=tmp; } } return; }
/* * Write text to the given file and apply line-wrapping. * * Hook function for text_out(). Make sure that text_out_file points * to an open text-file. * * Long lines will be wrapped at text_out_wrap, or at column 75 if that * is not set; or at a newline character. Note that punctuation can * sometimes be placed one column beyond the wrap limit. * * You must be careful to end all file output with a newline character * to "flush" the stored line position. */ void text_out_to_file(byte a, const char *str) { const char *s; char buf[1024]; /* Current position on the line */ static int pos = 0; /* Wrap width */ int wrap = (text_out_wrap ? text_out_wrap : 75); /* We use either ascii or system-specific encoding */ int encoding = OPT(xchars_to_file) ? SYSTEM_SPECIFIC : ASCII; /* Unused parameter */ (void)a; /* Copy to a rewriteable string */ my_strcpy(buf, str, 1024); /* Translate it to 7-bit ASCII or system-specific format */ xstr_trans(buf, encoding); /* Current location within "buf" */ s = buf; /* Process the string */ while (*s) { char ch; int n = 0; int len = wrap - pos; int l_space = -1; /* If we are at the start of the line... */ if (pos == 0) { int i; /* Output the indent */ for (i = 0; i < text_out_indent; i++) { file_writec(text_out_file, ' '); pos++; } } /* Find length of line up to next newline or end-of-string */ while ((n < len) && !((s[n] == '\n') || (s[n] == '\0'))) { /* Mark the most recent space in the string */ if (s[n] == ' ') l_space = n; /* Increment */ n++; } /* If we have encountered no spaces */ if ((l_space == -1) && (n == len)) { /* If we are at the start of a new line */ if (pos == text_out_indent) { len = n; } /* HACK - Output punctuation at the end of the line */ else if ((s[0] == ' ') || (s[0] == ',') || (s[0] == '.')) { len = 1; } else { /* Begin a new line */ file_writec(text_out_file, '\n'); /* Reset */ pos = 0; continue; } } else { /* Wrap at the newline */ if ((s[n] == '\n') || (s[n] == '\0')) len = n; /* Wrap at the last space */ else len = l_space; } /* Write that line to file */ for (n = 0; n < len; n++) { /* Ensure the character is printable */ ch = (my_isprint((unsigned char) s[n]) ? s[n] : ' '); /* Write out the character */ file_writec(text_out_file, ch); /* Increment */ pos++; } /* Move 's' past the stuff we've written */ s += len; /* If we are at the end of the string, end */ if (*s == '\0') return; /* Skip newlines */ if (*s == '\n') s++; /* Begin a new line */ file_writec(text_out_file, '\n'); /* Reset */ pos = 0; /* Skip whitespace */ while (*s == ' ') s++; } /* We are done */ return; }
/* * Print some (colored) text to the screen at the current cursor position, * automatically "wrapping" existing text (at spaces) when necessary to * avoid placing any text into the last column, and clearing every line * before placing any text in that line. Also, allow "newline" to force * a "wrap" to the next line. Advance the cursor as needed so sequential * calls to this function will work correctly. * * Once this function has been called, the cursor should not be moved * until all the related "text_out()" calls to the window are complete. * * This function will correctly handle any width up to the maximum legal * value of 256, though it works best for a standard 80 character width. */ void text_out_to_screen(byte a, const char *str) { int x, y; int wid, h; int wrap; const char *s; char buf[1024]; /* We use either ascii or system-specific encoding */ int encoding = (OPT(xchars_to_file)) ? SYSTEM_SPECIFIC : ASCII; /* Obtain the size */ (void)Term_get_size(&wid, &h); /* Obtain the cursor */ (void)Term_locate(&x, &y); /* Copy to a rewriteable string */ my_strcpy(buf, str, 1024); /* Translate it to 7-bit ASCII or system-specific format */ xstr_trans(buf, encoding); /* Use special wrapping boundary? */ if ((text_out_wrap > 0) && (text_out_wrap < wid)) wrap = text_out_wrap; else wrap = wid; /* Process the string */ for (s = buf; *s; s++) { char ch; /* Force wrap */ if (*s == '\n') { /* Wrap */ x = text_out_indent; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); x += text_out_pad; Term_gotoxy(x, y); continue; } /* Clean up the char */ ch = (my_isprint((unsigned char)*s) ? *s : ' '); /* Wrap words as needed */ if ((x >= wrap - 1) && (ch != ' ')) { int i, n = 0; byte av[256]; char cv[256]; /* Wrap word */ if (x < wrap) { /* Scan existing text */ for (i = wrap - 2; i >= 0; i--) { /* Grab existing attr/char */ Term_what(i, y, &av[i], &cv[i]); /* Break on space */ if (cv[i] == ' ') break; /* Track current word */ n = i; } } /* Special case */ if (n == 0) n = wrap; /* Clear line */ Term_erase(n, y, 255); /* Wrap */ x = text_out_indent; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); x += text_out_pad; Term_gotoxy(x, y); /* Wrap the word (if any) */ for (i = n; i < wrap - 1; i++) { /* Dump */ Term_addch(av[i], cv[i]); /* Advance (no wrap) */ if (++x > wrap) x = wrap; } } /* Dump */ Term_addch(a, ch); /* Advance */ if (++x > wrap) x = wrap; } }
/* * The default "keypress handling function" for askfor_aux, this takes the * given keypress, input buffer, length, etc, and does the appropriate action * for each keypress, such as moving the cursor left or inserting a character. * * It should return TRUE when editing of the buffer is "complete" (e.g. on * the press of RETURN). */ bool askfor_aux_keypress(char *buf, size_t buflen, size_t *curs, size_t *len, struct keypress keypress, bool firsttime) { switch (keypress.code) { case ESCAPE: { *curs = 0; return TRUE; break; } case '\n': case '\r': { *curs = *len; return TRUE; break; } case ARROW_LEFT: { if (firsttime) *curs = 0; if (*curs > 0) (*curs)--; break; } case ARROW_RIGHT: { if (firsttime) *curs = *len - 1; if (*curs < *len) (*curs)++; break; } case 0x7F: case '\010': { /* If this is the first time round, backspace means "delete all" */ if (firsttime) { buf[0] = '\0'; *curs = 0; *len = 0; break; } /* Refuse to backspace into oblivion */ if (*curs == 0) break; /* Move the string from k to nul along to the left by 1 */ memmove(&buf[*curs - 1], &buf[*curs], *len - *curs); /* Decrement */ (*curs)--; (*len)--; /* Terminate */ buf[*len] = '\0'; break; } default: { bool atnull = (buf[*curs] == 0); if (!my_isprint((unsigned char)keypress.code)) { bell("Illegal edit key!"); break; } /* Clear the buffer if this is the first time round */ if (firsttime) { buf[0] = '\0'; *curs = 0; *len = 0; atnull = 1; } if (atnull) { /* Make sure we have enough room for a new character */ if ((*curs + 1) >= buflen) break; } else { /* Make sure we have enough room to add a new character */ if ((*len + 1) >= buflen) break; /* Move the rest of the buffer along to make room */ memmove(&buf[*curs+1], &buf[*curs], *len - *curs); } /* Insert the character */ buf[(*curs)++] = (char)keypress.code; (*len)++; /* Terminate */ buf[*len] = '\0'; break; } } /* By default, we aren't done. */ return FALSE; }
/* * Write text to the given file and apply line-wrapping. * * Hook function for text_out(). Make sure that text_out_file points * to an open text-file. * * Long lines will be wrapped at text_out_wrap, or at column 75 if that * is not set; or at a newline character. Note that punctuation can * sometimes be placed one column beyond the wrap limit. * * You must be careful to end all file output with a newline character * to "flush" the stored line position. */ void text_out_dump(byte a, char *str, char_attr_line **line, int *current_line, int indent, int wrap) { const char *s; char buf[1024]; /* Current position on the line */ int pos = 0; /* We use either ascii or system-specific encoding */ int encoding = OPT(xchars_to_file) ? SYSTEM_SPECIFIC : ASCII; char_attr_line *lline = *line; /* Copy to a rewriteable string */ my_strcpy(buf, str, 1024); /* Translate it to 7-bit ASCII or system-specific format */ xstr_trans(buf, encoding); /* Current location within "buf" */ s = buf; /* Process the string */ while (*s) { char ch; int n = 0; int len = wrap - pos; int l_space = -1; /* If we are at the start of the line... */ if (pos == 0) { int i; /* Output the indent */ for (i = 0; i < indent; i++) { dump_put_str(TERM_WHITE, " ", pos); pos++; } } /* Find length of line up to next newline or end-of-string */ while ((n < len) && !((s[n] == '\n') || (s[n] == '\0'))) { /* Mark the most recent space in the string */ if (s[n] == ' ') l_space = n; /* Increment */ n++; } /* If we have encountered no spaces */ if ((l_space == -1) && (n == len)) { /* If we are at the start of a new line */ if (pos == indent) { len = n; } /* HACK - Output punctuation at the end of the line */ else if ((s[0] == ' ') || (s[0] == ',') || (s[0] == '.')) { len = 1; } else { /* Begin a new line */ (*current_line)++; dump_ptr = (char_attr *) &lline[*current_line]; /* Reset */ pos = 0; continue; } } else { /* Wrap at the newline */ if ((s[n] == '\n') || (s[n] == '\0')) len = n; /* Wrap at the last space */ else len = l_space; } /* Write that line to dump */ for (n = 0; n < len; n++) { /* Ensure the character is printable */ ch = (my_isprint((unsigned char) s[n]) ? s[n] : ' '); /* Write out the character */ dump_put_str(a, format("%c",ch), pos); /* Increment */ pos++; } /* Move 's' past the stuff we've written */ s += len; /* Begin a new line */ (*current_line)++; dump_ptr = (char_attr *) &lline[*current_line]; /* If we are at the end of the string, end */ if (*s == '\0') return; /* Begin a new line */ if (*s == '\n') { (*current_line)++; dump_ptr = (char_attr *) &lline[*current_line]; } /* Reset */ pos = 0; /* Skip whitespace */ while (*s == ' ') s++; } /* We are done */ return; }
bool file_getl(ang_file *f, char *buf, size_t len) { bool seen_cr = FALSE; byte b; size_t i = 0; bool check_encodes = FALSE; /* Leave a byte for the terminating 0 */ size_t max_len = len - 1; while (i < max_len) { char c; if (!file_readc(f, &b)) { buf[i] = '\0'; return (i == 0) ? FALSE : TRUE; } c = (char) b; if (c == '\r') { seen_cr = TRUE; continue; } if (seen_cr && c != '\n') { fseek(f->fh, -1, SEEK_CUR); buf[i] = '\0'; return TRUE; } if (c == '\n') { buf[i] = '\0'; return TRUE; } /* Expand tabs */ if (c == '\t') { /* Next tab stop */ size_t tabstop = ((i + TAB_COLUMNS) / TAB_COLUMNS) * TAB_COLUMNS; if (tabstop >= len) break; /* Convert to spaces */ while (i < tabstop) buf[i++] = ' '; continue; } /* Ignore non-printables */ else if (my_isprint((unsigned char)c)) { buf[i++] = c; /* Notice possible encode */ if (c == '[') check_encodes = TRUE; continue; } else { buf[i++] = '?'; continue; } } /* Translate encodes if necessary */ if (check_encodes) xstr_trans(buf, LATIN1); buf[i] = '\0'; return TRUE; }
char * tin_getline( const char *prompt, int number_only, /* 1=positive numbers only, 2=negative too */ const char *str, int max_chars, t_bool passwd, int which_hist) { int c, i, loc, tmp, gl_max; #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) wint_t wc; #else char *buf = gl_buf; #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ is_passwd = passwd; set_xclick_off(); if (prompt == NULL) prompt = ""; gl_buf[0] = 0; /* used as end of input indicator */ gl_fixup(-1, 0); /* this resets gl_fixup */ gl_width = cCOLS - strlen(prompt); gl_prompt = prompt; gl_pos = gl_cnt = 0; if (max_chars == 0) { if (number_only) gl_max = 6; else gl_max = BUF_SIZE; } else gl_max = max_chars; my_fputs(prompt, stdout); cursoron(); my_flush(); if (gl_in_hook) { loc = gl_in_hook(gl_buf); if (loc >= 0) gl_fixup(0, BUF_SIZE); } if (!cmd_line && gl_max == BUF_SIZE) CleartoEOLN(); #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) if (str != NULL) { wchar_t wbuf[LEN]; if (mbstowcs(wbuf, str, ARRAY_SIZE(wbuf) - 1) != (size_t) -1) { wbuf[ARRAY_SIZE(wbuf) - 1] = (wchar_t) '\0'; for (i = 0; wbuf[i]; i++) gl_addwchar(wbuf[i]); } } while ((wc = ReadWch()) != WEOF) { if ((gl_cnt < gl_max) && iswprint(wc)) { if (number_only) { if (iswdigit(wc)) { gl_addwchar(wc); /* Minus */ } else if (number_only == 2 && gl_pos == 0 && wc == (wint_t) '-') { gl_addwchar(wc); } else { ring_bell(); } } else gl_addwchar(wc); } else { c = (int) wc; switch (wc) { #else if (str != NULL) { for (i = 0; str[i]; i++) gl_addchar(str[i]); } while ((c = ReadCh()) != EOF) { c &= 0xff; if ((gl_cnt < gl_max) && my_isprint(c)) { if (number_only) { if (isdigit(c)) { gl_addchar(c); /* Minus */ } else if (number_only == 2 && gl_pos == 0 && c == '-') { gl_addchar(c); } else { ring_bell(); } } else gl_addchar(c); } else { switch (c) { #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ case ESC: /* abort */ #ifdef HAVE_KEY_PREFIX case KEY_PREFIX: #endif /* HAVE_KEY_PREFIX */ switch (get_arrow_key(c)) { case KEYMAP_UP: case KEYMAP_PAGE_UP: hist_prev(which_hist); break; case KEYMAP_PAGE_DOWN: case KEYMAP_DOWN: hist_next(which_hist); break; case KEYMAP_RIGHT: gl_fixup(-1, gl_pos + 1); break; case KEYMAP_LEFT: gl_fixup(-1, gl_pos - 1); break; case KEYMAP_HOME: gl_fixup(-1, 0); break; case KEYMAP_END: gl_fixup(-1, gl_cnt); break; case KEYMAP_DEL: gl_del(0); break; case KEYMAP_INS: #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) gl_addwchar((wint_t) ' '); #else gl_addchar(' '); #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ break; default: return (char *) 0; } break; case '\n': /* newline */ case '\r': gl_newline(which_hist); #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) wcstombs(buf, gl_buf, BUF_SIZE - 1); #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ return buf; case CTRL_A: gl_fixup(-1, 0); break; case CTRL_B: gl_fixup(-1, gl_pos - 1); break; case CTRL_D: if (gl_cnt == 0) { gl_buf[0] = 0; my_fputc('\n', stdout); #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) wcstombs(buf, gl_buf, BUF_SIZE - 1); #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ return buf; } else gl_del(0); break; case CTRL_E: gl_fixup(-1, gl_cnt); break; case CTRL_F: gl_fixup(-1, gl_pos + 1); break; case CTRL_H: case DEL: gl_del(-1); break; case TAB: if (gl_tab_hook) { tmp = gl_pos; loc = gl_tab_hook(gl_buf, strlen(gl_prompt), &tmp); if (loc >= 0 || tmp != gl_pos) gl_fixup(loc, tmp); } break; case CTRL_W: gl_kill_back_word(); break; case CTRL_U: gl_fixup(-1, 0); /* FALLTHROUGH */ case CTRL_K: gl_kill(); break; case CTRL_L: case CTRL_R: gl_redraw(); break; case CTRL_N: hist_next(which_hist); break; case CTRL_P: hist_prev(which_hist); break; default: ring_bell(); break; } } } #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) wcstombs(buf, gl_buf, BUF_SIZE - 1); #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ return buf; } /* * adds the character c to the input buffer at current location if * the character is in the allowed template of characters */ static void #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) gl_addwchar( wint_t wc) #else gl_addchar( int c) #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ { int i; /* * Crashing is always the worst solution IMHO. So as a quick hack, * ignore characters silently, if buffer is full. To allow a final * newline, leave space for one more character. Just a hack too. * This was the original code: * if (gl_cnt >= BUF_SIZE - 1) { error_message("tin_getline: input buffer overflow"); giveup(); } */ if (gl_cnt >= BUF_SIZE - 2) return; for (i = gl_cnt; i >= gl_pos; i--) gl_buf[i + 1] = gl_buf[i]; #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) gl_buf[gl_pos] = (wchar_t) wc; #else gl_buf[gl_pos] = c; #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ gl_fixup(gl_pos, gl_pos + 1); } /* * Cleans up entire line before returning to caller. A \n is appended. * If line longer than screen, we redraw starting at beginning */ static void gl_newline( int w) { int change = gl_cnt; int len = gl_cnt; int loc = gl_width - 5; /* shifts line back to start position */ if (gl_cnt >= BUF_SIZE - 1) { /* * Like above: avoid crashing if possible. gl_addchar() now * leaves one space left for the newline, so this part of the * code should never be reached. A proper implementation is * desirable though. */ error_message("tin_getline: input buffer overflow"); giveup(); } hist_add(w); /* only adds if nonblank */ if (gl_out_hook) { change = gl_out_hook(gl_buf); #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) len = wcslen(gl_buf); #else len = strlen(gl_buf); #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ } if (loc > len) loc = len; gl_fixup(change, loc); /* must do this before appending \n */ #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) gl_buf[len] = (wchar_t) '\0'; #else gl_buf[len] = '\0'; #endif /* MULTIBYTE_ABLE && !NO_LOCALE */ } /* * Delete a character. The loc variable can be: * -1 : delete character to left of cursor * 0 : delete character under cursor */ static void gl_del( int loc) { int i; if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) { for (i = gl_pos + loc; i < gl_cnt; i++) gl_buf[i] = gl_buf[i + 1]; gl_fixup(gl_pos + loc, gl_pos + loc); } else ring_bell(); }