summaryrefslogtreecommitdiffstats
path: root/ncurses-5.3/tack/edit.c
diff options
context:
space:
mode:
Diffstat (limited to 'ncurses-5.3/tack/edit.c')
-rw-r--r--ncurses-5.3/tack/edit.c977
1 files changed, 977 insertions, 0 deletions
diff --git a/ncurses-5.3/tack/edit.c b/ncurses-5.3/tack/edit.c
new file mode 100644
index 0000000..28bdb69
--- /dev/null
+++ b/ncurses-5.3/tack/edit.c
@@ -0,0 +1,977 @@
+/*
+** Copyright (C) 1997 Free Software Foundation, Inc.
+**
+** This file is part of TACK.
+**
+** TACK is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2, or (at your option)
+** any later version.
+**
+** TACK is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with TACK; see the file COPYING. If not, write to
+** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+** Boston, MA 02111-1307, USA.
+*/
+
+#include <tack.h>
+#include <time.h>
+#include <tic.h>
+
+MODULE_ID("$Id$")
+
+/*
+ * Terminfo edit features
+ */
+static void show_info(struct test_list *, int *, int *);
+static void show_value(struct test_list *, int *, int *);
+static void show_untested(struct test_list *, int *, int *);
+static void show_changed(struct test_list *, int *, int *);
+
+#define SHOW_VALUE 1
+#define SHOW_EDIT 2
+#define SHOW_DELETE 3
+
+struct test_list edit_test_list[] = {
+ {MENU_CLEAR, 0, 0, 0, "i) display current terminfo", show_info, 0},
+ {0, 0, 0, 0, "w) write the current terminfo to a file", save_info, 0},
+ {SHOW_VALUE, 3, 0, 0, "v) show value of a selected cap", show_value, 0},
+ {SHOW_EDIT, 4, 0, 0, "e) edit value of a selected cap", show_value, 0},
+ {SHOW_DELETE, 3, 0, 0, "d) delete string", show_value, 0},
+ {0, 3, 0, 0, "m) show caps that have been modified", show_changed, 0},
+ {MENU_CLEAR + FLAG_CAN_TEST, 0, 0, 0, "c) show caps that can be tested", show_report, 0},
+ {MENU_CLEAR + FLAG_TESTED, 0, 0, 0, "t) show caps that have been tested", show_report, 0},
+ {MENU_CLEAR + FLAG_FUNCTION_KEY, 0, 0, 0, "f) show a list of function keys", show_report, 0},
+ {MENU_CLEAR, 0, 0, 0, "u) show caps defined that can not be tested", show_untested, 0},
+ {MENU_LAST, 0, 0, 0, 0, 0, 0}
+};
+
+static char change_pad_text[MAX_CHANGES][80];
+struct test_list change_pad_list[MAX_CHANGES] = {
+ {MENU_LAST, 0, 0, 0, 0, 0, 0}
+};
+
+static void build_change_menu(struct test_menu *);
+static void change_one_entry(struct test_list *, int *, int *);
+
+struct test_menu change_pad_menu = {
+ 0, 'q', 0,
+ "Select cap name", "change", 0,
+ build_change_menu, change_pad_list, 0, 0, 0
+};
+
+extern struct test_results *pads[STRCOUNT]; /* save pad results here */
+
+static TERMTYPE original_term; /* terminal type description */
+
+static char flag_boolean[BOOLCOUNT]; /* flags for booleans */
+static char flag_numerics[NUMCOUNT]; /* flags for numerics */
+static char flag_strings[STRCOUNT]; /* flags for strings */
+static int xon_index; /* Subscript for (xon) */
+int xon_shadow;
+
+static int start_display; /* the display has just started */
+static int display_lines; /* number of lines displayed */
+
+/*
+** send_info_string(str)
+**
+** Return the terminfo string prefixed by the correct separator
+*/
+static void
+send_info_string(
+ const char *str,
+ int *ch)
+{
+ int len;
+
+ if (display_lines == -1) {
+ return;
+ }
+ len = strlen(str);
+ if (len + char_count + 3 >= columns) {
+ if (start_display == 0) {
+ put_str(",");
+ }
+ put_crlf();
+ if (++display_lines > lines) {
+ ptext("-- more -- ");
+ *ch = wait_here();
+ if (*ch == 'q') {
+ display_lines = -1;
+ return;
+ }
+ display_lines = 0;
+ }
+ if (len >= columns) {
+ /* if the terminal does not (am) then this loses */
+ if (columns) {
+ display_lines += ((strlen(str) + 3) / columns) + 1;
+ }
+ put_str(" ");
+ put_str(str);
+ start_display = 0;
+ return;
+ }
+ ptext(" ");
+ } else
+ if (start_display == 0) {
+ ptext(", ");
+ } else {
+ ptext(" ");
+ }
+ ptext(str);
+ start_display = 0;
+}
+
+/*
+** show_info(test_list, status, ch)
+**
+** Display the current terminfo
+*/
+static void
+show_info(
+ struct test_list *t GCC_UNUSED,
+ int *state GCC_UNUSED,
+ int *ch)
+{
+ int i;
+ char buf[1024];
+
+ display_lines = 1;
+ start_display = 1;
+ for (i = 0; i < BOOLCOUNT; i++) {
+ if ((i == xon_index) ? xon_shadow : CUR Booleans[i]) {
+ send_info_string(boolnames[i], ch);
+ }
+ }
+ for (i = 0; i < NUMCOUNT; i++) {
+ if (CUR Numbers[i] >= 0) {
+ sprintf(buf, "%s#%d", numnames[i], CUR Numbers[i]);
+ send_info_string(buf, ch);
+ }
+ }
+ for (i = 0; i < STRCOUNT; i++) {
+ if (CUR Strings[i]) {
+ sprintf(buf, "%s=%s", strnames[i],
+ print_expand(CUR Strings[i]));
+ send_info_string(buf, ch);
+ }
+ }
+ put_newlines(2);
+ *ch = REQUEST_PROMPT;
+}
+
+/*
+** save_info_string(str, fp)
+**
+** Write the terminfo string prefixed by the correct separator
+*/
+static void
+save_info_string(
+ const char *str,
+ FILE *fp)
+{
+ int len;
+
+ len = strlen(str);
+ if (len + display_lines >= 77) {
+ if (display_lines > 0) {
+ (void) fprintf(fp, "\n\t");
+ }
+ display_lines = 8;
+ } else
+ if (display_lines > 0) {
+ (void) fprintf(fp, " ");
+ display_lines++;
+ } else {
+ (void) fprintf(fp, "\t");
+ display_lines = 8;
+ }
+ (void) fprintf(fp, "%s,", str);
+ display_lines += len + 1;
+}
+
+/*
+** save_info(test_list, status, ch)
+**
+** Write the current terminfo to a file
+*/
+void
+save_info(
+ struct test_list *t,
+ int *state,
+ int *ch)
+{
+ int i;
+ FILE *fp;
+ time_t now;
+ char buf[1024];
+
+ if ((fp = fopen(tty_basename, "w")) == (FILE *) NULL) {
+ (void) sprintf(temp, "can't open: %s", tty_basename);
+ ptextln(temp);
+ generic_done_message(t, state, ch);
+ return;
+ }
+ time(&now);
+ /* Note: ctime() returns a newline at the end of the string */
+ (void) fprintf(fp, "# Terminfo created by TACK for TERM=%s on %s",
+ tty_basename, ctime(&now));
+ (void) fprintf(fp, "%s|%s,\n", tty_basename, longname());
+
+ display_lines = 0;
+ for (i = 0; i < BOOLCOUNT; i++) {
+ if (i == xon_index ? xon_shadow : CUR Booleans[i]) {
+ save_info_string(boolnames[i], fp);
+ }
+ }
+ for (i = 0; i < NUMCOUNT; i++) {
+ if (CUR Numbers[i] >= 0) {
+ sprintf(buf, "%s#%d", numnames[i], CUR Numbers[i]);
+ save_info_string(buf, fp);
+ }
+ }
+ for (i = 0; i < STRCOUNT; i++) {
+ if (CUR Strings[i]) {
+ sprintf(buf, "%s=%s", strnames[i],
+ _nc_tic_expand(CUR Strings[i], TRUE, TRUE));
+ save_info_string(buf, fp);
+ }
+ }
+ (void) fprintf(fp, "\n");
+ (void) fclose(fp);
+ sprintf(temp, "Terminfo saved as file: %s", tty_basename);
+ ptextln(temp);
+}
+
+/*
+** show_value(test_list, status, ch)
+**
+** Display the value of a selected cap
+*/
+static void
+show_value(
+ struct test_list *t,
+ int *state GCC_UNUSED,
+ int *ch)
+{
+ struct name_table_entry const *nt;
+ char *s;
+ int n, op, b;
+ char buf[1024];
+ char tmp[1024];
+
+ ptext("enter name: ");
+ read_string(buf, 80);
+ if (buf[0] == '\0' || buf[1] == '\0') {
+ *ch = buf[0];
+ return;
+ }
+ if (line_count + 2 >= lines) {
+ put_clear();
+ }
+ op = t->flags & 255;
+ if ((nt = _nc_find_entry(buf, _nc_info_hash_table))) {
+ switch (nt->nte_type) {
+ case BOOLEAN:
+ if (op == SHOW_DELETE) {
+ if (nt->nte_index == xon_index) {
+ xon_shadow = 0;
+ } else {
+ CUR Booleans[nt->nte_index] = 0;
+ }
+ return;
+ }
+ b = nt->nte_index == xon_index ? xon_shadow :
+ CUR Booleans[nt->nte_index];
+ sprintf(temp, "boolean %s %s", buf,
+ b ? "True" : "False");
+ break;
+ case STRING:
+ if (op == SHOW_DELETE) {
+ CUR Strings[nt->nte_index] = (char *) 0;
+ return;
+ }
+ if (CUR Strings[nt->nte_index]) {
+ sprintf(temp, "string %s %s", buf,
+ expand(CUR Strings[nt->nte_index]));
+ } else {
+ sprintf(temp, "undefined string %s", buf);
+ }
+ break;
+ case NUMBER:
+ if (op == SHOW_DELETE) {
+ CUR Numbers[nt->nte_index] = -1;
+ return;
+ }
+ sprintf(temp, "numeric %s %d", buf,
+ CUR Numbers[nt->nte_index]);
+ break;
+ default:
+ sprintf(temp, "unknown");
+ break;
+ }
+ ptextln(temp);
+ } else {
+ sprintf(temp, "Cap not found: %s", buf);
+ ptextln(temp);
+ return;
+ }
+ if (op != SHOW_EDIT) {
+ return;
+ }
+ if (nt->nte_type == BOOLEAN) {
+ ptextln("Value flipped");
+ if (nt->nte_index == xon_index) {
+ xon_shadow = !xon_shadow;
+ } else {
+ CUR Booleans[nt->nte_index] = !CUR Booleans[nt->nte_index];
+ }
+ return;
+ }
+ ptextln("Enter new value");
+ read_string(buf, sizeof(buf));
+
+ switch (nt->nte_type) {
+ case STRING:
+ _nc_reset_input((FILE *) 0, buf);
+ _nc_trans_string(tmp, tmp + sizeof(tmp));
+ s = (char *)malloc(strlen(tmp) + 1);
+ strcpy(s, tmp);
+ CUR Strings[nt->nte_index] = s;
+ sprintf(temp, "new string value %s", nt->nte_name);
+ ptextln(temp);
+ ptextln(expand(CUR Strings[nt->nte_index]));
+ break;
+ case NUMBER:
+ if (sscanf(buf, "%d", &n) == 1) {
+ CUR Numbers[nt->nte_index] = n;
+ sprintf(temp, "new numeric value %s %d",
+ nt->nte_name, n);
+ ptextln(temp);
+ } else {
+ sprintf(temp, "Illegal number: %s", buf);
+ ptextln(temp);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+** get_string_cap_byname(name, long_name)
+**
+** Given a cap name, find the value
+** Errors are quietly ignored.
+*/
+char *
+get_string_cap_byname(
+ const char *name,
+ const char **long_name)
+{
+ struct name_table_entry const *nt;
+
+ if ((nt = _nc_find_entry(name, _nc_info_hash_table))) {
+ if (nt->nte_type == STRING) {
+ *long_name = strfnames[nt->nte_index];
+ return (CUR Strings[nt->nte_index]);
+ }
+ }
+ *long_name = "??";
+ return (char *) 0;
+}
+
+/*
+** get_string_cap_byvalue(value)
+**
+** Given a capability string, find its position in the data base.
+** Return the index or -1 if not found.
+*/
+int
+get_string_cap_byvalue(
+ const char *value)
+{
+ int i;
+
+ if (value) {
+ for (i = 0; i < STRCOUNT; i++) {
+ if (CUR Strings[i] == value) {
+ return i;
+ }
+ }
+ /* search for translated strings */
+ for (i = 0; i < TM_last; i++) {
+ if (TM_string[i].value == value) {
+ return TM_string[i].index;
+ }
+ }
+ }
+ return -1;
+}
+
+/*
+** show_changed(test_list, status, ch)
+**
+** Display a list of caps that have been changed.
+*/
+static void
+show_changed(
+ struct test_list *t GCC_UNUSED,
+ int *state GCC_UNUSED,
+ int *ch)
+{
+ int i, header = 1, v;
+ const char *a;
+ const char *b;
+ static char title[] = " old value cap new value";
+ char abuf[1024];
+
+ for (i = 0; i < BOOLCOUNT; i++) {
+ v = (i == xon_index) ? xon_shadow : CUR Booleans[i];
+ if (original_term.Booleans[i] != v) {
+ if (header) {
+ ptextln(title);
+ header = 0;
+ }
+ sprintf(temp, "%30d %6s %d",
+ original_term.Booleans[i], boolnames[i], v);
+ ptextln(temp);
+ }
+ }
+ for (i = 0; i < NUMCOUNT; i++) {
+ if (original_term.Numbers[i] != CUR Numbers[i]) {
+ if (header) {
+ ptextln(title);
+ header = 0;
+ }
+ sprintf(temp, "%30d %6s %d",
+ original_term.Numbers[i], numnames[i],
+ CUR Numbers[i]);
+ ptextln(temp);
+ }
+ }
+ for (i = 0; i < STRCOUNT; i++) {
+ a = original_term.Strings[i] ? original_term.Strings[i] : "";
+ b = CUR Strings[i] ? CUR Strings[i] : "";
+ if (strcmp(a, b)) {
+ if (header) {
+ ptextln(title);
+ header = 0;
+ }
+ strcpy(abuf, _nc_tic_expand(a, TRUE, TRUE));
+ sprintf(temp, "%30s %6s %s", abuf, strnames[i],
+ _nc_tic_expand(b, TRUE, TRUE));
+ putln(temp);
+ }
+ }
+ if (header) {
+ ptextln("No changes");
+ }
+ put_crlf();
+ *ch = REQUEST_PROMPT;
+}
+
+/*
+** user_modified()
+**
+** Return TRUE if the user has modified the terminfo
+*/
+int
+user_modified(void)
+{
+ const char *a, *b;
+ int i, v;
+
+ for (i = 0; i < BOOLCOUNT; i++) {
+ v = (i == xon_index) ? xon_shadow : CUR Booleans[i];
+ if (original_term.Booleans[i] != v) {
+ return TRUE;
+ }
+ }
+ for (i = 0; i < NUMCOUNT; i++) {
+ if (original_term.Numbers[i] != CUR Numbers[i]) {
+ return TRUE;
+ }
+ }
+ for (i = 0; i < STRCOUNT; i++) {
+ a = original_term.Strings[i] ? original_term.Strings[i] : "";
+ b = CUR Strings[i] ? CUR Strings[i] : "";
+ if (strcmp(a, b)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*****************************************************************************
+ *
+ * Maintain the list of capabilities that can be tested
+ *
+ *****************************************************************************/
+
+/*
+** mark_cap(name, flag)
+**
+** Mark the cap data base with the flag provided.
+*/
+static void
+mark_cap(
+ char *name,
+ int flag)
+{
+ struct name_table_entry const *nt;
+
+ if ((nt = _nc_find_entry(name, _nc_info_hash_table))) {
+ switch (nt->nte_type) {
+ case BOOLEAN:
+ flag_boolean[nt->nte_index] |= flag;
+ break;
+ case STRING:
+ flag_strings[nt->nte_index] |= flag;
+ break;
+ case NUMBER:
+ flag_numerics[nt->nte_index] |= flag;
+ break;
+ default:
+ sprintf(temp, "unknown cap type (%s)", name);
+ ptextln(temp);
+ break;
+ }
+ } else {
+ sprintf(temp, "Cap not found: %s", name);
+ ptextln(temp);
+ (void) wait_here();
+ }
+}
+
+/*
+** can_test(name-list, flags)
+**
+** Scan the name list and get the names.
+** Enter each name into the can-test data base.
+** <space> ( and ) may be used as separators.
+*/
+void
+can_test(
+ const char *s,
+ int flags)
+{
+ int ch, j;
+ char name[32];
+
+ if (s) {
+ for (j = 0; (name[j] = ch = *s); s++) {
+ if (ch == ' ' || ch == ')' || ch == '(') {
+ if (j) {
+ name[j] = '\0';
+ mark_cap(name, flags);
+ }
+ j = 0;
+ } else {
+ j++;
+ }
+ }
+ if (j) {
+ mark_cap(name, flags);
+ }
+ }
+}
+
+/*
+** cap_index(name-list, index-list)
+**
+** Scan the name list and return a list of indexes.
+** <space> ( and ) may be used as separators.
+** This list is terminated with -1.
+*/
+void
+cap_index(
+ const char *s,
+ int *inx)
+{
+ struct name_table_entry const *nt;
+ int ch, j;
+ char name[32];
+
+ if (s) {
+ for (j = 0; ; s++) {
+ name[j] = ch = *s;
+ if (ch == ' ' || ch == ')' || ch == '(' || ch == 0) {
+ if (j) {
+ name[j] = '\0';
+ if ((nt = _nc_find_entry(name,
+ _nc_info_hash_table)) &&
+ (nt->nte_type == STRING)) {
+ *inx++ = nt->nte_index;
+ }
+ }
+ if (ch == 0) {
+ break;
+ }
+ j = 0;
+ } else {
+ j++;
+ }
+ }
+ }
+ *inx = -1;
+}
+
+/*
+** cap_match(name-list, cap)
+**
+** Scan the name list and see if the cap is in the list.
+** Return TRUE if we find an exact match.
+** <space> ( and ) may be used as separators.
+*/
+int
+cap_match(
+ const char *names,
+ const char *cap)
+{
+ char *s;
+ int c, l, t;
+
+ if (names) {
+ l = strlen(cap);
+ while ((s = strstr(names, cap))) {
+ c = (names == s) ? 0 : *(s - 1);
+ t = s[l];
+ if ((c == 0 || c == ' ' || c == '(') &&
+ (t == 0 || t == ' ' || t == ')')) {
+ return TRUE;
+ }
+ if (t == 0) {
+ break;
+ }
+ names = s + l;
+ }
+ }
+ return FALSE;
+}
+
+/*
+** show_report(test_list, status, ch)
+**
+** Display a list of caps that can be tested
+*/
+void
+show_report(
+ struct test_list *t,
+ int *state GCC_UNUSED,
+ int *ch)
+{
+ int i, j, nc, flag;
+ const char *s;
+ const char *nx[BOOLCOUNT + NUMCOUNT + STRCOUNT];
+
+ flag = t->flags & 255;
+ nc = 0;
+ for (i = 0; i < BOOLCOUNT; i++) {
+ if (flag_boolean[i] & flag) {
+ nx[nc++] = boolnames[i];
+ }
+ }
+ for (i = 0; i < NUMCOUNT; i++) {
+ if (flag_numerics[i] & flag) {
+ nx[nc++] = numnames[i];
+ }
+ }
+ for (i = 0; i < STRCOUNT; i++) {
+ if (flag_strings[i] & flag) {
+ nx[nc++] = strnames[i];
+ }
+ }
+ /* sort */
+ for (i = 0; i < nc - 1; i++) {
+ for (j = i + 1; j < nc; j++) {
+ if (strcmp(nx[i], nx[j]) > 0) {
+ s = nx[i];
+ nx[i] = nx[j];
+ nx[j] = s;
+ }
+ }
+ }
+ if (flag & FLAG_FUNCTION_KEY) {
+ ptextln("The following function keys can be tested:");
+ } else
+ if (flag & FLAG_CAN_TEST) {
+ ptextln("The following capabilities can be tested:");
+ } else
+ if (flag & FLAG_TESTED) {
+ ptextln("The following capabilities have been tested:");
+ }
+ put_crlf();
+ for (i = 0; i < nc; i++) {
+ sprintf(temp, "%s ", nx[i]);
+ ptext(temp);
+ }
+ put_newlines(1);
+ *ch = REQUEST_PROMPT;
+}
+
+/*
+** show_untested(test_list, status, ch)
+**
+** Display a list of caps that are defined but cannot be tested.
+** Don't bother to sort this list.
+*/
+static void
+show_untested(
+ struct test_list *t GCC_UNUSED,
+ int *state GCC_UNUSED,
+ int *ch)
+{
+ int i;
+
+ ptextln("Caps that are defined but cannot be tested:");
+ for (i = 0; i < BOOLCOUNT; i++) {
+ if (flag_boolean[i] == 0 && CUR Booleans[i]) {
+ sprintf(temp, "%s ", boolnames[i]);
+ ptext(temp);
+ }
+ }
+ for (i = 0; i < NUMCOUNT; i++) {
+ if (flag_numerics[i] == 0 && CUR Numbers[i] >= 0) {
+ sprintf(temp, "%s ", numnames[i]);
+ ptext(temp);
+ }
+ }
+ for (i = 0; i < STRCOUNT; i++) {
+ if (flag_strings[i] == 0 && CUR Strings[i]) {
+ sprintf(temp, "%s ", strnames[i]);
+ ptext(temp);
+ }
+ }
+ put_newlines(1);
+ *ch = REQUEST_PROMPT;
+}
+
+/*
+** edit_init()
+**
+** Initialize the function key data base
+*/
+void
+edit_init(void)
+{
+ int i, j, lc;
+ char *lab;
+ struct name_table_entry const *nt;
+ int label_strings[STRCOUNT];
+
+ _nc_copy_termtype(&original_term, &cur_term->type);
+ for (i = 0; i < BOOLCOUNT; i++) {
+ original_term.Booleans[i] = CUR Booleans[i];
+ }
+ for (i = 0; i < NUMCOUNT; i++) {
+ original_term.Numbers[i] = CUR Numbers[i];
+ }
+ /* scan for labels */
+ for (i = lc = 0; i < STRCOUNT; i++) {
+ original_term.Strings[i] = CUR Strings[i];
+ if (strncmp(strnames[i], "lf", 2) == 0) {
+ flag_strings[i] |= FLAG_LABEL;
+ if (CUR Strings[i]) {
+ label_strings[lc++] = i;
+ }
+ }
+ }
+ /* scan for function keys */
+ for (i = 0; i < STRCOUNT; i++) {
+ if ((strnames[i][0] == 'k') && strcmp(strnames[i], "kmous")) {
+ flag_strings[i] |= FLAG_FUNCTION_KEY;
+ lab = (char *) 0;
+ for (j = 0; j < lc; j++) {
+ if (!strcmp(&strnames[i][1],
+ &strnames[label_strings[j]][1])) {
+ lab = CUR Strings[label_strings[j]];
+ break;
+ }
+ }
+ enter_key(strnames[i], CUR Strings[i], lab);
+ }
+ }
+ /* Lookup the translated strings */
+ for (i = 0; i < TM_last; i++) {
+ if ((nt = _nc_find_entry(TM_string[i].name,
+ _nc_info_hash_table)) && (nt->nte_type == STRING)) {
+ TM_string[i].index = nt->nte_index;
+ } else {
+ sprintf(temp, "TM_string lookup failed for: %s",
+ TM_string[i].name);
+ ptextln(temp);
+ }
+ }
+ if ((nt = _nc_find_entry("xon", _nc_info_hash_table)) != 0) {
+ xon_index = nt->nte_index;
+ }
+ xon_shadow = xon_xoff;
+}
+
+/*
+** change_one_entry(test_list, status, ch)
+**
+** Change the padding on the selected cap
+*/
+static void
+change_one_entry(
+ struct test_list *test,
+ int *state,
+ int *chp)
+{
+ struct name_table_entry const *nt;
+ int i, j, x, star, slash, v, dot, ch;
+ const char *s;
+ char *t, *p;
+ const char *current_string;
+ char buf[1024];
+ char pad[1024];
+
+ i = test->flags & 255;
+ if (i == 255) {
+ /* read the cap name from the user */
+ ptext("enter name: ");
+ read_string(pad, 32);
+ if (pad[0] == '\0' || pad[1] == '\0') {
+ *chp = pad[0];
+ return;
+ }
+ if ((nt = _nc_find_entry(pad, _nc_info_hash_table)) &&
+ (nt->nte_type == STRING)) {
+ x = nt->nte_index;
+ current_string = CUR Strings[x];
+ } else {
+ sprintf(temp, "%s is not a string capability", pad);
+ ptext(temp);
+ generic_done_message(test, state, chp);
+ return;
+ }
+ } else {
+ x = tx_index[i];
+ current_string = tx_cap[i];
+ strcpy(pad, strnames[x]);
+ }
+ if (!current_string) {
+ ptextln("That string is not currently defined. Please enter a new value, including the padding delay:");
+ read_string(buf, sizeof(buf));
+ _nc_reset_input((FILE *) 0, buf);
+ _nc_trans_string(pad, pad + sizeof(pad));
+ t = (char *)malloc(strlen(pad) + 1);
+ strcpy(t, pad);
+ CUR Strings[x] = t;
+ sprintf(temp, "new string value %s", strnames[x]);
+ ptextln(temp);
+ ptextln(expand(t));
+ return;
+ }
+ sprintf(buf, "Current value: (%s) %s", pad, _nc_tic_expand(current_string, TRUE, TRUE));
+ putln(buf);
+ ptextln("Enter new pad. 0 for no pad. CR for no change.");
+ read_string(buf, 32);
+ if (buf[0] == '\0' || (buf[1] == '\0' && isalpha(UChar(buf[0])))) {
+ *chp = buf[0];
+ return;
+ }
+ star = slash = FALSE;
+ for (j = v = dot = 0; (ch = buf[j]); j++) {
+ if (ch >= '0' && ch <= '9') {
+ v = ch - '0' + v * 10;
+ if (dot) {
+ dot++;
+ }
+ } else if (ch == '*') {
+ star = TRUE;
+ } else if (ch == '/') {
+ slash = TRUE;
+ } else if (ch == '.') {
+ dot = 1;
+ } else {
+ sprintf(temp, "Illegal character: %c", ch);
+ ptextln(temp);
+ ptext("General format: 99.9*/ ");
+ generic_done_message(test, state, chp);
+ return;
+ }
+ }
+ while (dot > 2) {
+ v /= 10;
+ dot--;
+ }
+ if (dot == 2) {
+ sprintf(pad, "%d.%d%s%s", v / 10, v % 10,
+ star ? "*" : "", slash ? "/" : "");
+ } else {
+ sprintf(pad, "%d%s%s",
+ v, star ? "*" : "", slash ? "/" : "");
+ }
+ s = current_string;
+ t = buf;
+ for (v = 0; (ch = *t = *s++); t++) {
+ if (v == '$' && ch == '<') {
+ while ((ch = *s++) && (ch != '>'));
+ for (p = pad; (*++t = *p++); );
+ *t++ = '>';
+ while ((*t++ = *s++));
+ pad[0] = '\0';
+ break;
+ }
+ v = ch;
+ }
+ if (pad[0]) {
+ sprintf(t, "$<%s>", pad);
+ }
+ if ((t = (char *)malloc(strlen(buf) + 1))) {
+ strcpy(t, buf);
+ CUR Strings[x] = t;
+ if (i != 255) {
+ tx_cap[i] = t;
+ }
+ }
+ generic_done_message(test, state, chp);
+}
+
+/*
+** build_change_menu(menu_list)
+**
+** Build the change pad menu list
+*/
+static void
+build_change_menu(
+ struct test_menu *m)
+{
+ int i, j, k;
+ char *s;
+
+ for (i = j = 0; i < txp; i++) {
+ if ((k = tx_index[i]) >= 0) {
+ s = _nc_tic_expand(tx_cap[i], TRUE, TRUE);
+ s[40] = '\0';
+ sprintf(change_pad_text[j], "%c) (%s) %s",
+ 'a' + j, strnames[k], s);
+ change_pad_list[j].flags = i;
+ change_pad_list[j].lines_needed = 4;
+ change_pad_list[j].menu_entry = change_pad_text[j];
+ change_pad_list[j].test_procedure = change_one_entry;
+ j++;
+ }
+ }
+ strcpy(change_pad_text[j], "z) enter name");
+ change_pad_list[j].flags = 255;
+ change_pad_list[j].lines_needed = 4;
+ change_pad_list[j].menu_entry = change_pad_text[j];
+ change_pad_list[j].test_procedure = change_one_entry;
+ j++;
+ change_pad_list[j].flags = MENU_LAST;
+ if (m->menu_title) {
+ put_crlf();
+ ptextln(m->menu_title);
+ }
+}