home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Unix System Administration Handbook 1997 October
/
usah_oct97.iso
/
news
/
nn.tar
/
nn-6.5.1
/
variable.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-29
|
33KB
|
1,306 lines
/*
* (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
*
* Variable setting and display
*/
#include "config.h"
#include "keymap.h"
#include "regexp.h"
#include "chset.h"
/* variable.c */
static struct variable_defs *lookup_variable __APROTO((char *variable));
static char escaped_char __APROTO((int c));
static void adjust __APROTO((register char *str));
static char *var_value __APROTO((register struct variable_defs *var, char *tag));
static var_on_stack __APROTO((register struct variable_defs *var));
extern int prompt_length, prompt_line;
extern regexp *pg_regexp;
extern int pg_new_regexp;
/*
* Variable types and variants
*
* Boolean: type 'int'.
*
* BOOL 0 Ordinary boolean variable.
* BOOL 1 As 0 + redraw screen on return.
* BOOL 2 Special: reorder menu according to new value.
* BOOL 4 Inverse boolean varible ("set" clears internal var).
*
* Numeric: type 'int'.
*
* INT 0 Ordinary numeric variable ("unset" set var to 0).
* INT 1 As 0 + redraw screen on return.
* INT 2 As 0, but "unset" set var to -1.
* INT 3 As 2 + redraw screen on return.
*
* Strings: type 'char *'
*
* STR 0 Ordinary string ("unset" set var to NULL).
* STR 2 (home relative) file name or full path.
* Automatically expanded. ("unset" set var to NULL).
* STR 3 Ordinary string, but cannot be "unset".
* STR 4 (Expanded) file name - cannot be unset.
* STR 5 Ordinary string ("unset" set var to "").
*
* CODES n String initialized by list of key names.
* A maximum of 16 CODES variables (n = 0 - 15) exist.
*
* Strings: type 'char []'
*
* STR 1 Ordinary string saved in static array.
* "unset" set array to empty string.
* Warning: no bounds checking!
* Notice: Variable address is "(char **)var" (no &).
*
* Keys: type 'key_type'
*
* KEY 0 Ordinary key.
*
* Pseudo variables:
*
* SPEC n Treated by V_SPECIAL 'case n'.
*
* Modifiers:
*
* INIT Can only be set in init file.
* SAFE Cannot be changed if "shell-restrictions" is set.
*/
import in_init;
import char /* string variables */
*backup_folder_path,
*bak_suffix,
*bug_address,
*counter_delim_left,
*counter_delim_right,
*decode_header_file,
*default_distribution,
*default_save_file,
*distribution_follow,
*distribution_post,
*editor_program,
*extra_mail_headers,
*extra_news_headers,
*folder_save_file,
*header_lines,
*folder_directory,
included_mark[],
*inews_program,
*initial_newsrc_path,
*mail_alias_expander,
*mail_box,
*mail_record,
*mail_script,
*mailer_program,
attributes[],
*newsrc_file,
*news_record,
*news_script,
*pager,
patch_command[],
printer[],
*print_header_lines,
*response_dflt_answer,
*save_counter_format,
*save_header_lines,
*saved_header_escape,
*shade_on_attr,
*shade_off_attr,
*spell_checker,
*trusted_escapes,
unshar_command[],
*unshar_header_file,
*user_shell;
import int /* boolean variables */
also_cross_postings,
also_full_digest,
also_subgroups,
append_sig_mail,
append_sig_post,
auto_junk_seen,
auto_select_rw,
auto_select_subject,
auto_preview_mode,
body_search_header,
case_fold_search,
check_group_access,
compress_mode,
conf_append,
conf_auto_quit,
conf_create,
conf_dont_sleep,
conf_group_entry,
conf_junk_seen,
consolidated_manual,
consolidated_menu,
counter_padding,
delay_redraw,
dflt_kill_select,
do_kill_handling,
dont_sort_articles,
dont_sort_folders,
dont_split_digests,
echo_prefix_key,
edit_patch_command,
edit_print_command,
edit_unshar_command,
empty_answer_check,
enter_last_read_mode,
flow_control,
flush_typeahead,
fmt_rptsubj,
folder_format_check,
folder_rewrite_trace,
guard_double_slash,
ignore_formfeed,
ignore_xon_xoff,
ignore_re,
include_art_id,
include_full_header,
include_mark_blanks,
inews_pipe_input,
keep_backup_folder,
keep_rc_backup,
keep_unsubscribed,
keep_unsub_long,
long_menu,
macro_debug,
mailer_pipe_input,
mark_overlap,
mark_overlap_shading,
match_parts_equal,
match_parts_begin,
monitor_mode,
new_read_prompt,
novice,
prev_also_read,
preview_mark_read,
query_signature,
quick_save,
quick_unread_count,
read_ret_next_page,
repeat_group_query,
report_cost_on_exit,
retain_seen_status,
save_report,
scroll_clear_page,
select_leave_next,
select_on_sender,
seq_cross_filtering,
shell_restrictions,
show_article_date,
show_current_time,
show_motd_on_entry,
silent,
slow_mode,
suggest_save_file,
tidy_newsrc,
use_mail_folders,
use_mmdf_folders,
use_path_in_from,
use_selections,
use_visible_bell;
import int /* integer variables */
also_read_articles,
article_limit,
auto_read_limit,
auto_select_closed,
check_db_update,
conf_entry_limit,
collapse_subject,
Columns,
data_bits,
Debug,
decode_skip_prefix,
entry_message_limit,
expired_msg_delay,
first_page_lines,
fmt_linenum,
kill_debug,
kill_ref_count,
Lines,
match_skip_prefix,
mark_next_group,
mark_read_return,
mark_read_skip,
menu_spacing,
merge_report_rate,
message_history,
min_pv_window,
mouse_usage,
multi_key_guard_time,
new_group_action,
newsrc_update_freq,
orig_to_include_mask,
overlap,
preview_continuation,
preview_window,
print_header_type,
re_layout,
re_layout_more,
response_check_pause,
retry_on_error,
save_closed_mode,
save_counter_offset,
scroll_last_lines,
show_purpose_mode,
slow_speed,
strict_from_parse,
sort_mode,
subject_match_limit,
wrap_headers;
#ifdef NNTP
import char *nntp_cache_dir;
import int nntp_cache_size, nntp_debug;
#endif
import key_type /* key strokes */
comp1_key,
comp2_key,
help_key,
erase_key,
delword_key,
kill_key;
#undef STR
#undef BOOL
#undef INT
#undef KEY
#undef SPEC
#undef SAFE
#undef INIT
#undef CODES
#define V_STRING 0x1000
#define V_BOOLEAN 0x2000
#define V_INTEGER 0x3000
#define V_KEY 0x4000
#define V_SPECIAL 0x5000
#define V_CODES 0x6000
#define V_SAFE 0x0100
#define V_INIT 0x0200
#define V_LOCKED 0x0800
#define V_MODIFIED 0x8000
#define STR V_STRING |
#define BOOL V_BOOLEAN |
#define INT V_INTEGER |
#define KEY V_KEY |
#define SPEC V_SPECIAL |
#define CODES V_CODES |
#define SAFE V_SAFE |
#define INIT V_INIT |
static char *code_strings[16] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
static int var_on_stack();
struct variable_defs {
char *var_name;
int var_flags;
char **var_addr;
} variables[] = {
"also-full-digest", BOOL 0, (char **)&also_full_digest,
"also-subgroups", BOOL INIT 0, (char **)&also_subgroups,
"append-signature-mail", BOOL 0, (char **)&append_sig_mail,
"append-signature-post", BOOL 0, (char **)&append_sig_post,
"attributes", STR 1, (char **)attributes,
"auto-junk-seen", BOOL 0, (char **)&auto_junk_seen,
"auto-preview-mode", BOOL 0, (char **)&auto_preview_mode,
"auto-read-mode-limit", INT 0, (char **)&auto_read_limit,
"auto-select-closed", INT 0, (char **)&auto_select_closed,
"auto-select-rw", BOOL 0, (char **)&auto_select_rw,
"auto-select-subject", BOOL 0, (char **)&auto_select_subject,
"backup", BOOL 0, (char **)&keep_rc_backup,
"backup-folder-path", STR 4, (char **)&backup_folder_path,
"backup-suffix", STR 0, (char **)&bak_suffix,
"body-search-header", BOOL 0, (char **)&body_search_header,
"bug-report-address", STR 0, (char **)&bug_address,
"case-fold-search", BOOL 0, (char **)&case_fold_search,
"charset", SPEC 3, (char **)NULL,
"check-db-update-time", INT 0, (char **)&check_db_update,
"check-group-access", BOOL 0, (char **)&check_group_access,
"collapse-subject", INT 3, (char **)&collapse_subject,
"columns", INT 1, (char **)&Columns,
"comp1-key", KEY 0, (char **)&comp1_key,
"comp2-key", KEY 0, (char **)&comp2_key,
"compress", BOOL 0, (char **)&compress_mode,
"confirm-append", BOOL 0, (char **)&conf_append,
"confirm-auto-quit", BOOL 0, (char **)&conf_auto_quit,
"confirm-create", BOOL 0, (char **)&conf_create,
"confirm-entry", BOOL 0, (char **)&conf_group_entry,
"confirm-entry-limit", INT 0, (char **)&conf_entry_limit,
"confirm-junk-seen", BOOL 0, (char **)&conf_junk_seen,
"confirm-messages", BOOL 0, (char **)&conf_dont_sleep,
"consolidated-manual", BOOL 0, (char **)&consolidated_manual,
"consolidated-menu", BOOL 1, (char **)&consolidated_menu,
"counter-delim-left", STR 5, (char **)&counter_delim_left,
"counter-delim-right", STR 5, (char **)&counter_delim_right,
"counter-padding", INT 1, (char **)&counter_padding,
"cross-filter-seq", BOOL 0, (char **)&seq_cross_filtering,
"cross-post", BOOL 0, (char **)&also_cross_postings,
"data-bits", INT 0, (char **)&data_bits,
"date", BOOL 0, (char **)&show_article_date,
"debug", INT 0, (char **)&Debug,
"decode-header-file", STR 0, (char **)&decode_header_file,
"decode-skip-prefix", INT 0, (char **)&decode_skip_prefix,
"default-distribution", STR 0, (char **)&default_distribution,
"default-kill-select", INT 0, (char **)&dflt_kill_select,
"default-save-file", STR 3, (char **)&default_save_file,
"delay-redraw", BOOL 0, (char **)&delay_redraw,
"echo-prefix-key", BOOL 0, (char **)&echo_prefix_key,
"edit-patch-command", BOOL 0, (char **)&edit_patch_command,
"edit-print-command", BOOL 0, (char **)&edit_print_command,
"edit-response-check", BOOL 0, (char **)&empty_answer_check,
"edit-unshar-command", BOOL 0, (char **)&edit_unshar_command,
"editor", STR 0, (char **)&editor_program,
"embedded-header-escape", STR 0, (char **)&saved_header_escape,
"enter-last-read-mode", INT 0, (char **)&enter_last_read_mode,
"entry-report-limit", INT 0, (char **)&entry_message_limit,
"erase-key", KEY 0, (char **)&erase_key,
"expert", BOOL 4, (char **)&novice,
"expired-message-delay", INT 0, (char **)&expired_msg_delay,
"flow-control", BOOL 0, (char **)&flow_control,
"flush-typeahead", BOOL 0, (char **)&flush_typeahead,
"folder", STR 2, (char **)&folder_directory,
"folder-format-check", BOOL 0, (char **)&folder_format_check,
"folder-save-file", STR 3, (char **)&folder_save_file,
"follow-distribution", STR 0, (char **)&distribution_follow,
"from-line-parsing", INT 0, (char **)&strict_from_parse,
"fsort", BOOL 2, (char **)&dont_sort_folders,
"guard-double-slash", BOOL 0, (char **)&guard_double_slash,
"header-lines", STR 0, (char **)&header_lines,
"help-key", KEY 0, (char **)&help_key,
"ignore-formfeed", BOOL 0, (char **)&ignore_formfeed,
"ignore-re", BOOL 0, (char **)&ignore_re,
"ignore-xon-xoff", BOOL 0, (char **)&ignore_xon_xoff,
"include-art-id", BOOL 0, (char **)&include_art_id,
"include-full-header", BOOL 0, (char **)&include_full_header,
"include-mark-blank-lines", BOOL 0, (char **)&include_mark_blanks,
"included-mark", STR 1, (char **)included_mark,
"inews", STR 0, (char **)&inews_program,
"inews-pipe-input", BOOL 0, (char **)&inews_pipe_input,
"initial-newsrc-file", STR 0, (char **)&initial_newsrc_path,
"keep-backup-folder", BOOL 0, (char **)&keep_backup_folder,
"keep-unsubscribed", BOOL 0, (char **)&keep_unsubscribed,
"kill", BOOL 0, (char **)&do_kill_handling,
"kill-debug", BOOL 0, (char **)&kill_debug,
"kill-key", KEY 0, (char **)&kill_key,
"kill-reference-count", INT 0, (char **)&kill_ref_count,
"layout", INT 1, (char **)&fmt_linenum,
"limit", INT 2, (char **)&article_limit,
"lines", INT 1, (char **)&Lines,
"long-menu", BOOL 1, (char **)&long_menu,
"macro-debug", BOOL 0, (char **)¯o_debug,
"mail", STR 2, (char **)&mail_box,
"mail-alias-expander", STR 0, (char **)&mail_alias_expander,
"mail-format", BOOL 0, (char **)&use_mail_folders,
"mail-header", STR 0, (char **)&extra_mail_headers,
"mail-record", STR 2, (char **)&mail_record,
"mail-script", STR SAFE 2, (char **)&mail_script,
"mailer", STR 0, (char **)&mailer_program,
"mailer-pipe-input", BOOL 0, (char **)&mailer_pipe_input,
"mark-overlap", BOOL 0, (char **)&mark_overlap,
"mark-overlap-shading", BOOL 0, (char **)&mark_overlap_shading,
"marked-by-next-group", INT 0, (char **)&mark_next_group,
"marked-by-read-return", INT 0, (char **)&mark_read_return,
"marked-by-read-skip", INT 0, (char **)&mark_read_skip,
"menu-spacing", INT 1, (char **)&menu_spacing,
"merge-report-rate", INT 0, (char **)&merge_report_rate,
"message-history", INT 0, (char **)&message_history,
"min-window", INT 1, (char **)&min_pv_window,
"mmdf-format", BOOL 0, (char **)&use_mmdf_folders,
"monitor", BOOL 0, (char **)&monitor_mode,
"motd", BOOL 0, (char **)&show_motd_on_entry,
"mouse-usage", INT 0, (char **)&mouse_usage,
"multi-key-guard-time", INT 0, (char **)&multi_key_guard_time,
"new-group-action", INT 0, (char **)&new_group_action,
"new-style-read-prompt", BOOL 0, (char **)&new_read_prompt,
"news-header", STR 0, (char **)&extra_news_headers,
"news-record", STR 2, (char **)&news_record,
"news-script", STR SAFE 2, (char **)&news_script,
"newsrc", STR 2, (char **)&newsrc_file,
#ifdef NNTP
"nntp-cache-dir", STR INIT 0, (char **)&nntp_cache_dir,
"nntp-cache-size", INT INIT 0, (char **)&nntp_cache_size,
"nntp-debug", BOOL 0, (char **)&nntp_debug,
#endif
/* "no....." -- cannot have variable names starting with "no" */
"old", SPEC 2, (char **)NULL,
"orig-to-include-mask", INT 0, (char **)&orig_to_include_mask,
"overlap", INT 0, (char **)&overlap,
"pager", STR SAFE 3, (char **)&pager,
"patch-command", STR SAFE 1, (char **)patch_command,
"post-distribution", STR 0, (char **)&distribution_post,
"preview-continuation", INT 0, (char **)&preview_continuation,
"preview-mark-read", BOOL 0, (char **)&preview_mark_read,
"previous-also-read", BOOL 0, (char **)&prev_also_read,
"print-header-lines", STR 0, (char **)&print_header_lines,
"print-header-type", INT 0, (char **)&print_header_type,
"printer", STR SAFE 1, (char **)printer,
"query-signature", BOOL 0, (char **)&query_signature,
"quick-count", BOOL 0, (char **)&quick_unread_count,
"quick-save", BOOL 0, (char **)&quick_save,
"re-layout", INT 0, (char **)&re_layout,
"re-layout-read", INT 0, (char **)&re_layout_more,
"read-return-next-page", BOOL 0, (char **)&read_ret_next_page,
"record", SPEC 1, (char **)NULL,
"repeat", BOOL 0, (char **)&fmt_rptsubj,
"repeat-group-query", BOOL 0, (char **)&repeat_group_query,
"report-cost", BOOL 0, (char **)&report_cost_on_exit,
"response-check-pause", INT 0, (char **)&response_check_pause,
"response-default-answer", STR 0, (char **)&response_dflt_answer,
"retain-seen-status", BOOL 0, (char **)&retain_seen_status,
"retry-on-error", INT 0, (char **)&retry_on_error,
"save-closed-mode", INT 0, (char **)&save_closed_mode,
"save-counter", STR 3, (char **)&save_counter_format,
"save-counter-offset", INT 0, (char **)&save_counter_offset,
"save-header-lines", STR 0, (char **)&save_header_lines,
"save-report", BOOL 0, (char **)&save_report,
"scroll-clear-page", BOOL 0, (char **)&scroll_clear_page,
"scroll-last-lines", INT 0, (char **)&scroll_last_lines,
"select-leave-next", BOOL 0, (char **)&select_leave_next,
"select-on-sender", BOOL 0, (char **)&select_on_sender,
"shading-off", CODES 0, (char **)&shade_off_attr,
"shading-on", CODES 1, (char **)&shade_on_attr,
"shell", STR SAFE 0, (char **)&user_shell,
"shell-restrictions", BOOL INIT 0, (char **)&shell_restrictions,
"show-purpose-mode", INT 0, (char **)&show_purpose_mode,
"silent", BOOL 0, (char **)&silent,
"slow-mode", BOOL 0, (char **)&slow_mode,
"slow-speed", INT 0, (char **)&slow_speed,
"sort", BOOL 2, (char **)&dont_sort_articles,
"sort-mode", INT 0, (char **)&sort_mode,
"spell-checker", STR 0, (char **)&spell_checker,
"split", BOOL 4, (char **)&dont_split_digests,
"stop", INT 0, (char **)&first_page_lines,
"subject-match-limit", INT 0, (char **)&subject_match_limit,
"subject-match-minimum", INT 0, (char **)&match_parts_begin,
"subject-match-offset", INT 0, (char **)&match_skip_prefix,
"subject-match-parts", BOOL 0, (char **)&match_parts_equal,
"suggest-default-save", BOOL 0, (char **)&suggest_save_file,
"tidy-newsrc", BOOL 0, (char **)&tidy_newsrc,
"time", BOOL 0, (char **)&show_current_time,
"trace-folder-packing", BOOL 0, (char **)&folder_rewrite_trace,
"trusted-escape-codes", STR 0, (char **)&trusted_escapes,
"unshar-command", STR SAFE 1, (char **)unshar_command,
"unshar-header-file", STR 0, (char **)&unshar_header_file,
"unsubscribe-mark-read", BOOL 4, (char **)&keep_unsub_long,
"update-frequency", INT 0, (char **)&newsrc_update_freq,
"use-path-in-from", BOOL 0, (char **)&use_path_in_from,
"use-selections", BOOL 0, (char **)&use_selections,
"visible-bell", BOOL 0, (char **)&use_visible_bell,
"window", INT 1, (char **)&preview_window,
"word-key", KEY 0, (char **)&delword_key,
"wrap-header-margin", INT 2, (char **)&wrap_headers
};
#define TABLE_SIZE (sizeof(variables)/sizeof(struct variable_defs))
#define INT_VAR (*((int *)(var->var_addr)))
#define BOOL_VAR (*((int *)(var->var_addr)))
#define STR_VAR (*(var->var_addr))
#define CBUF_VAR ((char *)(var->var_addr))
#define KEY_VAR (*((key_type *)(var->var_addr)))
#define VAR_TYPE (var->var_flags & 0x7000)
#define VAR_OP (var->var_flags & 0x000f)
static struct variable_defs *lookup_variable(variable)
char *variable;
{
register struct variable_defs *var;
register i, j, k, t;
i = 0; j = TABLE_SIZE - 1;
while (i <= j) {
k = (i + j) / 2;
var = &variables[k];
if ( (t=strcmp(variable, var->var_name)) > 0)
i = k+1;
else
if (t < 0)
j = k-1;
else
return var;
}
init_message("unknown variable: %s", variable);
return NULL;
}
static char escaped_char(c)
char c;
{
switch (c) {
case 'a':
return 007;
case 'b':
return BS;
case 'e':
return 033;
case 'f':
return '\f';
case 'n':
return NL;
case 'r':
return CR;
case 't':
return TAB;
}
return c;
}
static void
adjust(str)
register char *str;
{
register char *s, *t;
if ((s = t = str) == NULL) return;
while (*s && *s != '#') {
if (*s == '\\' && s[1] != NUL) {
s++;
*str++ = escaped_char(*s++);
} else
if (str == s) {
str++;
if (isspace(*s++)) continue;
} else
if (isspace(*str++ = *s++)) continue;
t = str;
}
*t = NUL;
}
int
set_variable(variable, on, val_string)
char *variable;
int on;
char *val_string;
{
int value;
register struct variable_defs *var;
if (strncmp(variable, "no", 2) == 0) {
on = !on;
variable += 2;
if (variable[0] == '-') variable++;
}
if ((var = lookup_variable(variable)) == NULL)
return 0;
if (!in_init && (var->var_flags & (V_INIT | V_SAFE))) {
if (var->var_flags & V_INIT) {
msg("'%s' can only be set in the init file", variable);
return 0;
}
if (shell_restrictions) {
msg("Restricted operation - cannot change");
return 0;
}
}
if (var->var_flags & V_LOCKED) {
msg("Variable '%s' is locked", variable);
return 0;
}
if (!on || val_string == NULL)
value = 0;
else
value = atoi(val_string);
var->var_flags |= V_MODIFIED;
switch (VAR_TYPE) {
case V_STRING:
if (on) adjust(val_string);
switch (VAR_OP) {
case 0:
STR_VAR = (on && val_string) ? copy_str(val_string) : (char *)NULL;
break;
case 1:
strcpy(CBUF_VAR, (on && val_string) ? val_string : "");
break;
case 2:
if (on) {
char exp_buf[FILENAME];
if (val_string) {
if (expand_file_name(exp_buf, val_string, 1))
STR_VAR = home_relative(exp_buf);
}
} else
STR_VAR = (char *)NULL;
break;
case 3:
case 4:
if (!on || val_string == NULL) {
msg("Cannot unset string `%s'", variable);
break;
}
if (VAR_OP == 4) {
char exp_buf[FILENAME];
if (expand_file_name(exp_buf, val_string, 1)) {
STR_VAR = copy_str(exp_buf);
break;
}
}
STR_VAR = copy_str(val_string);
break;
case 5:
STR_VAR = (on && val_string) ? copy_str(val_string) : "";
break;
}
break;
case V_BOOLEAN:
adjust(val_string);
if (val_string && *val_string != NUL)
if (val_string[0] == 'o')
on = val_string[1] == 'n'; /* on */
else
on = val_string[0] == 't'; /* true */
switch (VAR_OP) {
case 0:
BOOL_VAR = on;
break;
case 1:
BOOL_VAR = on;
return 1;
case 2:
if (BOOL_VAR) { /* don't change if already ok */
if (!on) break;
} else
if (on) break;
BOOL_VAR = !on;
if (!in_init) {
sort_articles(BOOL_VAR ? 0 : -1);
return 1;
}
break;
case 4:
BOOL_VAR = !on;
break;
}
break;
case V_INTEGER:
switch (VAR_OP) {
case 0:
case 1:
INT_VAR = value;
break;
case 2:
case 3:
if (!on) value = -1;
INT_VAR = value;
break;
}
return (VAR_OP & 1);
case V_KEY:
switch (VAR_OP) {
case 0:
if (val_string) {
if (*val_string) adjust(val_string + 1); /* #N is valid */
KEY_VAR = parse_key(val_string);
}
break;
}
break;
case V_SPECIAL:
switch (VAR_OP) {
case 1:
if (val_string) {
adjust(val_string);
news_record = home_relative(val_string);
mail_record = news_record;
var->var_flags &= ~V_MODIFIED;
lookup_variable("mail-record")->var_flags |= V_MODIFIED;
lookup_variable("news-record")->var_flags |= V_MODIFIED;
}
break;
case 2:
also_read_articles = on;
article_limit = (on && value > 0) ? value : -1;
break;
case 3:
{
struct chset *csp;
struct variable_defs *dbvar;
dbvar = lookup_variable("data-bits");
if (on && val_string) {
if ((csp = getchset(val_string)) == NULL)
msg("Illegal value for `%s' variable", variable);
else {
curchset = csp;
data_bits = csp->cs_width ? csp->cs_width : 7;
dbvar->var_flags &= ~V_MODIFIED;
}
} else
msg("Cannot unset special `%s' variable", variable);
}
break;
}
break;
case V_CODES:
{
char codes[80], code[16], *sp, *cp, *vs;
if (val_string == NULL) on = 0;
if (on) {
adjust(val_string);
if (val_string[0] == NUL) on = 0;
}
if (on) {
sp = codes;
vs = val_string;
while (*vs) {
while (*vs && (!isascii(*vs) || isspace(*vs)))
vs++;
if (*vs == NUL) break;
cp = code;
while (*vs && isascii(*vs) && !isspace(*vs))
*cp++ = *vs++;
*cp = NUL;
*sp++ = parse_key(code);
}
*sp = NUL;
if (codes[0] == NUL) on = 0;
}
freeobj(code_strings[VAR_OP]);
code_strings[VAR_OP] = on ? copy_str(val_string) : NULL;
STR_VAR = on ? copy_str(codes) : (char *)NULL;
break;
}
break;
}
return 0;
}
void
toggle_variable(variable)
char *variable;
{
register struct variable_defs *var;
if ((var = lookup_variable(variable)) == NULL) return;
if (VAR_TYPE != V_BOOLEAN) {
init_message("variable %s is not boolean", variable);
return;
}
BOOL_VAR = !BOOL_VAR;
}
void
lock_variable(variable)
char *variable;
{
register struct variable_defs *var;
if ((var = lookup_variable(variable)) != NULL)
var->var_flags |= V_LOCKED;
}
static char *var_value(var, tag)
register struct variable_defs *var;
char *tag;
{
static char ival[16];
register char *str = NULL;
register int b;
if (tag != NULL)
*tag = var_on_stack(var) ? '>' :
(var->var_flags & V_LOCKED) ? '!' :
(var->var_flags & V_MODIFIED) ? '*' : ' ';
switch (VAR_TYPE) {
case V_STRING:
str = (VAR_OP == 1) ? CBUF_VAR : STR_VAR;
break;
case V_BOOLEAN:
b = BOOL_VAR;
if (VAR_OP == 2 || VAR_OP == 4) b = !b;
str = b ? "on" : "off";
break;
case V_INTEGER:
sprintf(ival, "%d", INT_VAR);
str = ival;
break;
case V_KEY:
str = key_name(KEY_VAR);
break;
case V_SPECIAL:
str = "UNDEF";
switch (VAR_OP) {
case 2:
if (!also_read_articles) break;
sprintf(ival, "%d", article_limit);
str = ival;
break;
case 3:
str = curchset->cs_name;
break;
}
break;
case V_CODES:
str = code_strings[VAR_OP];
break;
}
if (str == NULL) str = "NULL";
return str;
}
int
test_variable(expr)
char *expr;
{
char *variable;
register struct variable_defs *var;
int res = -1;
variable = expr;
if ((expr = strchr(variable, '=')) == NULL)
goto err;
*expr++ = NUL;
if ((var = lookup_variable(variable)) == NULL) {
msg("testing unknown variable %s=%s", variable, expr);
goto out;
}
switch (VAR_TYPE) {
case V_BOOLEAN:
res = BOOL_VAR;
if (strcmp(expr, "on") == 0 || strcmp(expr, "true") == 0) break;
if (strcmp(expr, "off") == 0 || strcmp(expr, "false") == 0) {
res = !res;
break;
}
msg("boolean variables must be tested =on or =off");
break;
case V_INTEGER:
res = (INT_VAR == atoi(expr)) ? 1 : 0;
break;
default:
msg("%s: cannot only test boolean and integer variables", variable);
break;
}
out:
*--expr = '=';
err:
return res;
}
static int vc_column;
void
var_compl_opts(col)
int col;
{
vc_column = col;
}
int
var_completion(path, index)
char *path;
int index;
{
static char *head, *tail = NULL;
static int len;
static struct variable_defs *var, *help_var;
if (index < 0) {
clrmsg(-(index + 1));
return 1;
}
if (path) {
head = path;
tail = path + index;
while (*head && isspace(*head)) head++;
if (strncmp(head, "no", 2) == 0) {
head += 2;
if (*head == '-') head++;
}
help_var = var = variables;
len = tail - head;
return 1;
}
if (index) {
list_completion((char *)NULL);
for (;; help_var++) {
if (help_var >= &variables[TABLE_SIZE]) {
help_var = variables;
break;
}
index = strncmp(help_var->var_name, head, len);
if (index < 0) continue;
if (index > 0) {
help_var = variables;
break;
}
if (list_completion(help_var->var_name) == 0) break;
}
fl;
return 1;
}
for (; var < &variables[TABLE_SIZE]; var++) {
if (len == 0)
index = 0;
else
index = strncmp(var->var_name, head, len);
if (index < 0) continue;
if (index > 0) break;
sprintf(tail, "%s ", var->var_name + len);
msg("%.70s", var_value(var, (char *)NULL));
gotoxy(prompt_length + vc_column, prompt_line);
var++;
return 1;
}
clrmsg(vc_column);
return 0;
}
static struct var_stack {
struct var_stack *next;
struct variable_defs *v;
int mod_flag;
union {
int ivar;
int bool;
char key;
char *str;
} value;
} *var_stack = NULL, *vs_pool = NULL;
void
mark_var_stack()
{
register struct var_stack *vs;
if (vs_pool) {
vs = vs_pool;
vs_pool = vs->next;
} else
vs = newobj(struct var_stack, 1);
vs->next = var_stack;
var_stack = vs;
vs->v = NULL;
}
int
push_variable(variable)
char *variable;
{
register struct variable_defs *var;
register struct var_stack *vs;
if (strncmp(variable, "no", 2) == 0) {
variable += 2;
if (variable[0] == '-') variable++;
}
if ((var = lookup_variable(variable)) == NULL) {
msg("pushing unknown variable %s", variable);
return 0;
}
mark_var_stack();
vs = var_stack;
vs->v = var;
vs->mod_flag = var->var_flags & V_MODIFIED;
switch (VAR_TYPE) {
case V_STRING:
switch (VAR_OP) {
case 0: /* if we update one of these variables, */
case 2: /* new storage will be allocated for it */
case 3: /* so it is ok just to save the pointer */
case 4:
vs->value.str = STR_VAR;
break;
case 1: /* we free this memory when restored */
vs->value.str = copy_str(CBUF_VAR);
break;
}
break;
case V_BOOLEAN:
vs->value.bool = BOOL_VAR;
break;
case V_INTEGER:
vs->value.ivar = INT_VAR;
break;
case V_KEY:
vs->value.key = KEY_VAR;
break;
case V_SPECIAL:
msg("Cannot push pseudo variable %s", var->var_name);
break;
case V_CODES:
msg("Cannot push code string variable %s", var->var_name);
break;
}
return 1;
}
void
restore_variables()
{
register struct variable_defs *var;
register struct var_stack *vs, *vs1;
vs = var_stack;
while (vs != NULL) {
if ((var = vs->v) == NULL) {
var_stack = vs->next;
vs->next = vs_pool;
vs_pool = vs;
return;
}
var->var_flags &= ~V_MODIFIED;
var->var_flags |= vs->mod_flag;
switch (VAR_TYPE) {
case V_STRING:
switch (VAR_OP) {
case 0: /* only restore the string if changed; then we */
case 2: /* can also free the memory occupied by the */
case 3: /* 'new' value (if not NULL) */
case 4:
if (STR_VAR != vs->value.str) {
if (STR_VAR != NULL) freeobj(STR_VAR);
STR_VAR = vs->value.str;
}
break;
case 1: /* it fitted before, so it will fit againg */
strcpy(CBUF_VAR, vs->value.str);
freeobj(vs->value.str);
break;
}
break;
case V_BOOLEAN:
BOOL_VAR = vs->value.bool;
break;
case V_INTEGER:
INT_VAR = vs->value.ivar;
break;
case V_KEY:
KEY_VAR = vs->value.key;
break;
case V_SPECIAL: /* these are not saved, so... */
break;
case V_CODES:
break;
}
vs1 = vs->next;
vs->next = vs_pool;
vs_pool = vs;
vs = vs1;
}
var_stack = NULL;
}
static int
var_on_stack(var)
register struct variable_defs *var;
{
register struct var_stack *vs;
for (vs = var_stack; vs; vs = vs->next)
if (vs->v == var) return 1;
return 0;
}
void
disp_variables(all, rexp)
int all;
char *rexp;
{
char *str, pushed;
register struct variable_defs *var;
if (in_init) return;
clrdisp();
if (novice && !all && rexp == NULL) {
msg("Use `:set all' to see all variable settings");
home();
}
so_printxy(0, 0, "Variable settings");
pg_init(1, 1);
if (rexp) {
pg_regexp = regcomp(rexp + 1);
all = 1;
}
for (var = variables; var < &variables[TABLE_SIZE]; var++) {
if (pg_regexp != NULL && regexec(pg_regexp, var->var_name) == 0)
continue;
str = var_value(var, &pushed);
if (!all && pushed == ' ') continue;
if (pg_next() < 0) break;
if (pg_new_regexp) {
pg_new_regexp = 0;
var = variables;
var--;
continue;
}
if (VAR_TYPE == V_STRING)
tprintf("%c %-25.25s = \"%s\"\n", pushed, var->var_name, str);
else
tprintf("%c %-25.25s = %s\n", pushed, var->var_name, str);
}
pg_end();
}
void
print_variable_config(f, all)
FILE *f;
int all;
{
register struct variable_defs *var;
char *str, tag[2];
tag[1] = NUL;
for (var = variables; var < &variables[TABLE_SIZE]; var++) {
if (!all && (var->var_flags & V_MODIFIED) == 0) continue;
str = var_value(var, tag);
fprintf(f, "%s%s='%s'\n", all ? tag : "", var->var_name, str);
}
}
/*
* var_options(string_var *, options, result *)
*
* test whether "string_var" contains any of the options
* listed in "options" (NUL-separated list of names ended with
* double NUL). On return, string_var is advanced over all
* recognized options and the result will have the bits corresponding
* to the recognized options set.
*/
void
var_options(str, options, res)
char **str;
register char *options;
flag_type *res;
{
char word[128];
char *optab[32];
register char **op, *wp, c;
register int n;
for (op = optab; *options != NUL; op++, options++) {
*op = options;
while (*options) options++;
}
*op = NULL;
*res = 0;
options = *str;
while (*options) {
for (wp = word; (c = *options) != NUL; *wp++ = c, options++)
if (isascii(c) && isspace(c)) break;
while ((c = *options) && isascii(c) && isspace(c)) options++;
*wp = NUL;
for (op = optab, n = 1; *op != NULL; op++, n++) {
if (strcmp(word, *op)) continue;
*res |= FLAG(n);
*str = options;
break;
}
if (*op == NULL) break;
}
}