This is menu.c in view mode; [Download] [Up]
/* * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved. * * selection mode menu */ #include "config.h" #include "articles.h" #include "term.h" #include "keymap.h" #include "menu.h" #include "regexp.h" import char *news_lib_directory; export int echo_prefix_key = 1; /* echo prefix keys */ export int preview_window = 0; /* size of preview window */ export int fmt_linenum = 1; /* menu line format */ export int fmt_rptsubj = 0; /* repeat identical subjects if !0 */ export int novice = 1; /* novice mode -- use extended prompts */ export int long_menu = 0; /* don't put empty lines around menu lines */ export int delay_redraw = 0; /* prompt again if :-command clears screen */ export int slow_mode = 0; /* mark selected articles with *s */ export int re_layout = 0; /* Re: format presentation on menus */ export int collapse_subject = 25; /* collapse long subjects at position */ export int conf_group_entry = 0; /* ask whether group should be entered */ export int conf_entry_limit = 0; /* ask only if more than .. unread */ export int mark_read_skip = 4; /* effect of X command */ export int mark_read_return = 0; /* effect of Z command */ export int mark_next_group = 0; /* effect of N command */ export int show_purpose_mode = 1; /* 0: never, 1: new, 2: always */ export int read_ret_next_page = 0; /* Z returns to next page */ export int consolidated_menu = 0; /* show only root articles */ export int save_closed_mode = 13; /* ask how to save closed subj, dflt all */ export int auto_select_closed = 1; /* select all in closed subject */ export int menu_spacing = 0; /* number of screen lines per menu line */ export char *counter_delim_left = "["; export char *counter_delim_right = "] "; export int counter_padding = 5; /* counters are padded to align subjects */ export int auto_preview_mode = 0; /* preview rather than select */ export int preview_continuation = 12; /* what to do after preview */ export int preview_mark_read = 1; /* previewed articles are A_READ */ export int select_on_sender = 0; /* find command selects on sender */ export int auto_select_subject = 0; /* auto select articles with same subj. */ export int auto_read_limit = 0; /* ignore auto_read_mode if less articles */ export char delayed_msg[100] = ""; /* give to msg() after redraw */ export int flush_typeahead = 0; import int also_read_articles; import int merged_menu; import int case_fold_search; extern group_completion(); static regexp *regular_expr = NULL; static int firstl; /* first menu line */ static article_number firsta; /* first article on menu (0 based) */ static article_number nexta; /* first article on next menu */ static int cura; /* current article */ static int next_cura; /* article to become cura if >= 0 */ static int numa; /* no of articles on menu - 1 */ static attr_type last_attr; #define INTERVAL1 ('z' - 'a' + 1) #define INTERVAL2 ('9' - '0' + 1) char ident[] = "abcdefghijklmnopqrstuvwxyz0123456789"; char attributes[30] = " .,+=#! **"; /* Corresponds to A_XXXX in data.h */ static int menu_length; /* current no of line on menu */ static int menu_articles; /* current no of articles on menu */ static struct menu_info { /* info for each menu line */ int mi_cura; /* cura corresponding to this menu line */ int mi_total; /* total number of articles with this subject */ int mi_unread; /* no of unread articles with this subject */ int mi_selected; /* no of selected articles with this subject */ int mi_art_id; /* article id (for mark()) */ } menu_info[INTERVAL1+INTERVAL2]; static struct menu_info *art_id_to_mi[INTERVAL1+INTERVAL2]; #define IS_VISIBLE(ah) (((ah)->flag & (A_CLOSED | A_ROOT_ART)) != A_CLOSED) prt_replies(level) { int re; if (level == 0) return 0; re = level & 0x80; level &= 0x7f; switch (re_layout) { case 1: if (!re) return 0; so_printf(">"); return 1; case 2: switch (level) { case 0: return 0; case 1: so_printf(">"); return 1; default: so_printf("%d>", level); return level < 10 ? 2 : 3; } case 3: so_printf("Re: "); return 4; case 4: if (level == 0 && re) level++; break; } if (level < 10) { so_printf("%-.*s", level, ">>>>>>>>>"); return level; } so_printf(">>>%3d >>>>", level); return 11; } static article_number root_article(root) register article_number root; { register article_header *ah = articles[root]; if (ah->flag & A_ROOT_ART) return root; if (ah->flag & A_CLOSED) /* only root article is shown on menu */ return firsta + menu_info[ah->menu_line].mi_cura; while (root > 0) { if (articles[root]->flag & A_ROOT_ART) break; root--; } return root; } static article_number next_root_article(root) register article_number root; { while (++root < n_articles) if (articles[root]->flag & A_ROOT_ART) break; return root; } static set_root_if_closed() { if (articles[firsta + cura]->flag & A_CLOSED) cura = root_article(firsta + cura) - firsta; } /* * count info for thread containing article #art (must be on menu!) * returns article number for next root article */ static article_number thread_counters(art) article_number art; { register struct menu_info *mi; register article_number n; int total, unread, selected, invisible; if (!(articles[art]->flag & A_CLOSED)) return art + 1; total = unread = selected = 0; n = art = root_article(art); while (n < n_articles) { if (articles[n]->attr == 0) unread++; else if (articles[n]->attr & A_SELECT) selected++; total++; if (++n == n_articles) break; if (articles[n]->flag & A_ROOT_ART) break; } unread += selected; mi = menu_info + articles[art]->menu_line; mi->mi_total = total; mi->mi_unread = unread; mi->mi_selected = selected; return n; } static cursor_at_id() { gotoxy(0, firstl + articles[firsta + cura]->menu_line); fl; /* place cursor at current article id */ save_xy(); } static attr_type closed_attr(mi, cbuf) register struct menu_info *mi; char *cbuf; { char sel[10], unr[10]; attr_type cattr; if (mi->mi_unread == 0) cattr = A_READ; else if (mi->mi_total == mi->mi_selected) cattr = A_SELECT; else if (auto_select_closed == 1 && mi->mi_unread == mi->mi_selected) cattr = A_SELECT; else if (mi->mi_selected) cattr = A_KILL; /* pseudo flag -> highlight cbuf */ else cattr = 0; sel[0] = unr[0] = NUL; if (mi->mi_selected && mi->mi_selected < mi->mi_unread) sprintf(sel, "%d/", mi->mi_selected); if (mi->mi_unread && mi->mi_unread < mi->mi_total) sprintf(unr, "%d:", mi->mi_unread); sprintf(cbuf, "%s%s%d", sel, unr, mi->mi_total); return cattr; } static int subj_indent; static mark() { register article_header *ah; register struct menu_info *mi; int lno, lnum, lsubj, lname; int pad; char cbuf[80]; attr_type cattr; ah = articles[firsta + cura]; if (!IS_VISIBLE(ah)) return; last_attr = ah->attr; if (ah->disp_attr == A_NOT_DISPLAYED) { mi = &menu_info[ah->menu_line]; lno = firstl + ah->menu_line; gotoxy(0, lno); putchar(ident[mi->mi_art_id]); cattr = closed_attr(mi, cbuf); goto print_line; } if (cura < 0 || cura > numa) return; lno = firstl + ah->menu_line; if (ah->flag & A_CLOSED) { struct menu_info old; char oldctr[80]; attr_type oldattr; mi = &menu_info[ah->menu_line]; old = *mi; thread_counters(firsta + cura); if (old.mi_total == mi->mi_total && old.mi_selected == mi->mi_selected && old.mi_unread == mi->mi_unread) return; cattr = closed_attr(mi, cbuf); if (!slow_mode) goto print_line; oldattr = closed_attr(&old, oldctr); if (strcmp(cbuf, oldctr)) goto print_line; last_attr = cattr; } if (last_attr == ah->disp_attr) return; /* A_AUTO_SELECT will not occur here! */ if (!slow_mode) if (last_attr == A_SELECT) { if ((ah->disp_attr & A_SELECT) == 0) goto print_line; } else { if (ah->disp_attr & A_SELECT) goto print_line; } gotoxy(1, lno); putchar(attributes[ah->attr]); goto out; print_line: /* menu line formats: 1 3 8 10 20 22 xx : : : : : : : -1 id name:8 subject 0 id name subject +lines 1 id name lines subject 2 id lines subject 3 id subject 4 id subject (or as 1 if short subject) */ if ((ah->flag & A_CLOSED) == 0) { cattr = ah->attr; cbuf[0] = NUL; } if (fmt_linenum > 4) fmt_linenum = 1; if (!slow_mode && (cattr & A_SELECT)) { if (so_gotoxy(1, lno, 1) == 0) putchar(attributes[A_SELECT]); } else { gotoxy(1, lno); putchar(cattr == A_KILL ? ' ' : attributes[cattr]); } if (ah->lines < 10) lnum = 1; else if (ah->lines < 100) lnum = 2; else if (ah->lines < 1000) lnum = 3; else if (ah->lines < 10000) lnum = 4; else lnum = 5; lsubj = Columns - cookie_size - 2; /* ident char + space */ switch (fmt_linenum) { case -1: lsubj -= 9; so_printf("%-8.8s ", ah->sender); goto no_counters; case 0: lsubj -= NAME_LENGTH + 1 + 2 + lnum; /* name. .subj. +.lines */ so_printf("%-*s ", NAME_LENGTH, ah->sender); break; case 4: if (ah->subj_length > (lsubj - NAME_LENGTH - 5)) if (fmt_rptsubj || lno == firstl || (ah->flag & A_SAME) == 0) { so_printf(" "); lsubj -= 2; break; } /* else use layout 1, so fall thru */ case 1: lsubj -= NAME_LENGTH + 5; /* name.lines. .subj (name may be shortened) */ lname = NAME_LENGTH + 2 - lnum; so_printf("%-*.*s ", lname, lname, ah->sender); so_printf(ah->lines >= 0 ? "%d " : "? ", ah->lines); break; case 2: lsubj -= 6; so_printf("%5d ", ah->lines); break; case 3: break; } print_subj: if (cbuf[0]) { so_printf("%s", counter_delim_left); if (cattr == A_KILL) so_gotoxy(-1, -1, 0); so_printf("%s", cbuf); if (cattr == A_KILL) so_end(); so_printf("%s", counter_delim_right); pad = strlen(cbuf) + strlen(counter_delim_left) + strlen(counter_delim_right); if (cattr == A_KILL) pad += cookie_size * 2; lsubj -= pad > subj_indent ? pad : subj_indent; pad = subj_indent - pad; } else { lsubj -= subj_indent; pad = subj_indent; } if (pad > 0) { if (pad > 20) pad = 20; so_printf(" "+20-pad); } no_counters: if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) { if (ah->replies == 0 || prt_replies(ah->replies) == 0) so_printf("-"); } else { lsubj -= prt_replies(ah->replies); if (lsubj >= ah->subj_length) so_printf("%s", ah->subject); else if (collapse_subject < 0) so_printf("%-.*s", lsubj, ah->subject); else { if (collapse_subject > 0) so_printf("%-.*s", collapse_subject, ah->subject); lsubj -= 2 + collapse_subject; so_printf("<>%s", ah->subject + ah->subj_length - lsubj); } } if (fmt_linenum == 0) so_printf(ah->lines >= 0 ? " +%d" : " +?", ah->lines); so_end(); if (ah->flag & A_CLOSED) clrline_noflush(); out: ah->disp_attr = last_attr; return; } static new_mark(how) attr_type how; { articles[firsta + cura]->attr = how; mark(); } static toggle() { last_attr = articles[firsta + cura]->attr = articles[firsta + cura]->attr & A_SELECT ? 0 : A_SELECT; } static do_auto_kill() { register article_number i; register article_header *ah, **ahp; int any = 0; for (i = 0, ahp = articles; i < n_articles; i++, ahp++) { ah = *ahp; if (auto_select_article(ah, 0)) { ah->attr = A_KILL; any = 1; } } return any; } /* * perform auto selections that are not already selected * if article is in range firsta..firsta+numa (incl) mark article */ static do_auto_select(re, mode) regexp *re; int mode; { register article_number i; register article_header *ah, **ahp; int count = 0, o_cura; extern int kill_file_loaded; if (mode == 1 && re == NULL) if (!kill_file_loaded && !init_kill()) return 0; o_cura = cura; cura = -1; for (i = 0, ahp = articles; i < n_articles; i++, ahp++) { ah = *ahp; if (cura >= 0 && (ah->flag & A_ROOT_ART)) { mark(); cura = -1; } if (re != NULL) { if (!regexec_cf(re, select_on_sender ? ah->sender : ah->subject)) continue; } else if (!auto_select_article(ah, mode)) continue; count++; if (ah->attr & A_SELECT) continue; ah->attr = A_SELECT; if (firsta <= i && i <= (firsta+numa)) { cura = i - firsta; if ((ah->flag & A_CLOSED) == 0) { mark(); cura = -1; } } } if (cura >= 0) mark(); if (count) msg("Selected %d article%s", count, plural((long)count)); else msg("No selections"); cura = o_cura; } static quit_preview(cmd) int cmd; { int op; if ((firsta + cura) >= n_articles) return 1; op = preview_continuation; if (cmd == MC_PREVIEW_NEXT) op /= 10; op %= 10; switch (op) { case 0: return 1; case 1: return 0; case 2: return articles[firsta+cura]->flag & A_ROOT_ART; } return 0; } export long n_selected; export int show_art_next_invalid; static count_selected_articles() { register article_number cur; n_selected = 0; for (cur = 0; cur < n_articles; cur++) { if (articles[cur]->attr & A_SELECT) n_selected++; } } static show_articles() { register article_number cur, next, temp; register article_header *ah; article_number elim_list[1]; register int mode; int cmd, prev = -1, again; attr_type o_attr; import int new_read_prompt; do { for (cur = 0; cur < n_articles; cur++) { if (articles[cur]->attr & A_SELECT) break; } while (cur < n_articles) { for (next = cur+1; next < n_articles; next++) { if (articles[next]->attr & A_SELECT) break; } show_art_next_invalid = 0; show: ah = articles[cur]; o_attr = ah->attr; ah->attr = 0; if (new_read_prompt) count_selected_articles(); mode = 0; if (prev >= 0) mode |= MM_PREVIOUS; if (next == n_articles) mode |= MM_LAST_SELECTED; if ((cur + 1) >= n_articles) mode |= MM_LAST_ARTICLE; if (cur == 0) mode |= MM_FIRST_ARTICLE; cmd = more(ah, mode, 0); switch (cmd) { case MC_DO_KILL: if (do_auto_kill()) { elim_list[0] = next; elim_articles(elim_list, 1); cur = elim_list[0]; /* if next was n_articles, cur will be 0 */ if (cur >= n_articles || cur < 0 || (articles[cur]->attr & A_SELECT) == 0) cur = n_articles; continue; } break; case MC_DO_SELECT: break; case MC_PREV: ah->attr = o_attr; if (prev == next) break; next = cur; cur = prev; prev = next; goto show; case MC_NEXTSUBJ: ah->attr = A_READ; for (next = cur+1; next < n_articles; next++) { if ((ah = articles[next])->flag & A_ROOT_ART) break; ah->attr = A_READ; } for (; next < n_articles; next++) { if (articles[next]->attr & A_SELECT) break; } break; case MC_ALLSUBJ: ah->attr = A_READ; for (next = cur+1; next < n_articles; next++) { ah = articles[next]; if (ah->flag & A_ROOT_ART) break; ah->attr = A_SELECT; } for (next = cur+1; next < n_articles; next++) if (articles[next]->attr & A_SELECT) break; break; case MC_MENU: ah->attr = o_attr; if (nexta - firsta < n_articles) if ((firsta = cur - 5) < 0) firsta = 0; next_cura = cur - firsta; return MC_MENU; case MC_NEXT: if (ah->attr == 0) /* Not set by more (sufficient ???) */ ah->attr = A_READ; break; case MC_BACK_ART: ah->attr = o_attr ? o_attr : A_SEEN; next = cur - 1; break; case MC_FORW_ART: ah->attr = o_attr ? o_attr : A_SEEN; next = cur + 1; break; case MC_NEXTGROUP: case MC_REENTER_GROUP: case MC_QUIT: ah->attr = o_attr; return cmd; case MC_READGROUP: for (cur = 0; cur < n_articles; cur++) { ah = articles[cur]; if (ah->attr == 0 || (ah->attr & A_SELECT)) ah->attr = A_READ; } return MC_NEXTGROUP; } if (show_art_next_invalid) for (next = cur+1; next < n_articles; next++) { if (articles[next]->attr & A_SELECT) break; } prev = cur; cur = next; } for (cur = 0; cur < n_articles; cur++) if (articles[cur]->attr & A_SELECT) break; if (cur < n_articles) continue; again = 0; for (cur = 0; cur < n_articles; cur++) { ah = articles[cur]; if (ah->attr == A_LEAVE) { if (again == 0) { prompt("Show left over articles again now? "); if (yes(0) <= 0) break; } ah->attr = A_SELECT; again++; } } if (again > 1) sprintf(delayed_msg, "Showing %ld articles again", again); } while (again); return MC_READGROUP; } static int article_id; static int cur_key; static int is_k_select; /* set when K_ARTICLE_ID was really K_SELECT */ static int get_k_cmd_1() { extern int any_message; register int c, map; int *key_map = menu_key_map; if (flush_typeahead) flush_input(); loop: article_id = -1; if ((c = get_c()) & GETC_COMMAND) { cur_key = K_interrupt; map = c & ~GETC_COMMAND; } else { cur_key = c; map = key_map[c]; } if (s_hangup) map = K_QUIT; if (map & K_PREFIX_KEY) { key_map = keymaps[map & ~K_PREFIX_KEY].km_map; if (echo_prefix_key) msg("%s", key_name(cur_key)); goto loop; } is_k_select = 0; if (map == K_SELECT) { map = K_ARTICLE_ID; article_id = cura; is_k_select = 1; } else if (map & K_ARTICLE_ID) { article_id = map & ~K_ARTICLE_ID; map = K_ARTICLE_ID; if (article_id < 0 || article_id > menu_articles) { ding(); goto loop; } article_id = art_id_to_mi[article_id]->mi_cura; } if (any_message && map != K_LAST_MESSAGE) clrmsg(-1); return map; } static int get_k_cmd() { register int map; map = get_k_cmd_1(); if (map & K_MACRO) map = orig_menu_map[cur_key]; return map; } char *pct(start, end, first, last) long start, end, first, last; { long n = end - start; static char buf[16]; char *fmt; if (first <= start || n <= 0) if (last >= end || n <= 0) return "All"; else fmt = "Top %d%%"; else if (last >= end) return "Bot"; else fmt = "%d%%"; sprintf(buf, fmt, ((last - start) * 100)/n); return buf; } static repl_attr(first, last, old, new, update) register article_number first, last; register attr_type old, new; int update; { int any; register article_header *ah; article_number ocura = cura; if (new == old) return 0; if (new == A_KILL) update = 0; any = 0; cura = -1; while (first < last) { ah = articles[first]; if (cura >= 0 && ah->flag & A_ROOT_ART) { set_root_if_closed(); mark(); cura = -1; } if (old == A_KILL || ah->attr == old) { ah->attr = new; if (update && first >= firsta && first < nexta) { cura = first - firsta; if ((ah->flag & A_CLOSED) == 0) { mark(); cura = -1; } } any = 1; } first++; } if (cura >= 0) { set_root_if_closed(); mark(); } cura = update ? last - firsta : ocura; return any; } static repl_attr_subject(old, new, update) attr_type old, new; int update; { return repl_attr(root_article(firsta+cura), next_root_article(firsta+cura), old, new, update); } static repl_attr_all(old, new, update) attr_type old, new; int update; { return repl_attr((article_number)0, n_articles, old, new, update); } static get_purpose(purpose) char *purpose; { FILE *f, *open_purpose_file(); char line[256], *group; register char *cp, *pp; register int len; if (current_group == NULL) return; if ((current_group->master_flag & M_VALID) == 0) return; if (current_group->group_flag & G_FAKED) return; if ((f = open_purpose_file()) == NULL) return; group = current_group->group_name; len = current_group->group_name_length; while (fgets(line, 256, f) != NULL) { if (!isascii(line[len]) || !isspace(line[len])) continue; if (strncmp(line, group, len)) continue; cp = line + len; while (*cp && isspace(*cp)) cp++; for (pp = purpose, len = 76; --len >= 0 && *cp && *cp != NL; ) *pp++ = *cp++; *pp = NUL; } } /* * bypass_consolidation may be set to temporarily overrule the global * consolidated_menu variable: * 1: don't consolidate (e.g. for G=... ) * 2: do consolidate * 3: use consolidated_mode */ export int bypass_consolidation = 0; static int cur_bypass = 0; /* current bypass status (see below) */ static do_consolidation() { int consolidate; switch (bypass_consolidation) { case 0: break; case 1: cur_bypass = -1; /* no consolidation */ break; case 2: cur_bypass = 1; /* force consolidation */ break; case 3: cur_bypass = 0; /* reset bypass to use consolidated_menu */ break; } bypass_consolidation = 0; if (cur_bypass) consolidate = cur_bypass > 0; else consolidate = consolidated_menu; if (consolidate) for (nexta = 0; nexta < n_articles; nexta++) articles[nexta]->flag |= A_CLOSED; else for (nexta = 0; nexta < n_articles; nexta++) articles[nexta]->flag &= ~A_CLOSED; return consolidate; } menu(print_header) fct_type print_header; { register k_cmd, cur_k_cmd; register article_header *ah; register struct menu_info *mi; int consolidate, o_bypass; int last_k_cmd; int menu_cmd, temp; int save_selected; article_number last_save; attr_type orig_attr, junk_attr; int doing_unshar, did_unshar, junk_prompt; char *fname, *savemode, *init_save(); int maxa; /* max no of articles per menu page */ article_number o_firsta, temp1, temp2; int o_mode; /* for recursive calls */ static menu_level = 0; char purpose[80], pr_fmt[60]; extern int enable_stop, file_completion(); extern int alt_cmd_key, in_menu_mode; article_number elim_list[3]; int entry_check; int auto_read; long o_selected; #define menu_return(cmd) \ { menu_cmd = (cmd); goto menu_exit; } flush_input(); o_firsta = firsta; o_mode = in_menu_mode; o_selected = n_selected; in_menu_mode = 1; menu_level++; if (menu_level == 1) { if ((current_group->group_flag & G_COUNTED) && n_articles != current_group->unread_count) { add_unread(current_group, -1); current_group->unread_count = n_articles; add_unread(current_group, 0); } entry_check = conf_group_entry && n_articles > conf_entry_limit; auto_read = auto_read_limit < 0 || n_articles <= auto_read_limit; } else { entry_check = 0; auto_read = 0; } sprintf(pr_fmt, menu_level == 1 ? "\1\2-- SELECT %s-----%%s-----\1" : "\1\2-- SELECT %s-----%%s-----<%s%d>--\1", novice ? "-- help:? " : "", novice ? "level " : "", menu_level); purpose[0] = NUL; if (!merged_menu) switch (show_purpose_mode) { case 0: break; case 1: if ((current_group->group_flag & G_NEW) == 0) break; case 2: get_purpose(purpose); if (purpose[0]) strcpy(delayed_msg, purpose); } o_bypass = cur_bypass; cur_bypass = 0; consolidate = do_consolidation(); firsta = 0; while (firsta < n_articles && articles[firsta]->attr == A_SEEN) firsta++; if (firsta == n_articles) firsta = 0; next_cura = -1; cur_k_cmd = K_UNBOUND; #ifdef HAVE_JOBCONTROL #define REDRAW_CHECK if (s_redraw) goto do_redraw do_redraw: /* safe to clear here, because we are going to redraw anyway */ s_redraw = 0; #else #define REDRAW_CHECK #endif redraw: s_keyboard = 0; empty_menu_hack: /* do: "s_keyboard=1; goto empty_menu_hack;" */ if (!slow_mode) s_keyboard = 0; nexta = firsta; clrdisp(); if (entry_check) { prompt_line = firstl = CALL(print_header)(); prompt("\1Enter?\1 "); if ((temp = yes(0)) <= 0) { if (temp < 0) { prompt("\1Mark as read?\1 "); if ((temp = yes(0)) < 0) menu_return(ME_QUIT); if (temp > 0) repl_attr_all(A_KILL, A_READ, 0); } menu_return(ME_NEXT); } gotoxy(0, firstl); clrline(); } if (auto_read) { auto_read = entry_check = 0; if (repl_attr_all(0, A_AUTO_SELECT, 0)) { k_cmd = K_READ_GROUP_UPDATE; if (purpose[0]) strcpy(delayed_msg, purpose); else sprintf(delayed_msg, "Entering %s, %ld articles", current_group->group_name, (long)n_articles); goto do_auto_read; } } if (!entry_check) firstl = CALL(print_header)(); entry_check = 0; maxa = Lines - preview_window - firstl - 2; if (!long_menu) firstl++, maxa -= 2; if (maxa > (INTERVAL1 + INTERVAL2)) maxa = INTERVAL1 + INTERVAL2; nextmenu: no_raw(); gotoxy(0, firstl); clrpage(firstl); if (articles[nexta]->flag & A_CLOSED) nexta = root_article(nexta); firsta = nexta; cura = 0; REDRAW_CHECK; menu_length = 0; menu_articles = 0; goto draw_menu; partial_redraw: next_cura = cura; partial_redraw_nc: nexta = firsta + cura; menu_length = articles[nexta]->menu_line; menu_articles = menu_info[menu_length].mi_art_id; gotoxy(0, firstl + menu_length); clrpage(firstl + menu_length); draw_menu: subj_indent = consolidate ? counter_padding : 0; if (!s_keyboard) { int first_menu_line = menu_length; mi = menu_info + menu_length; while (nexta < n_articles) { REDRAW_CHECK; ah = articles[nexta]; if (ah->flag & A_HIDE) { ah->menu_line = menu_length; /* just in case.... */ continue; } if (menu_length > first_menu_line) { switch (menu_spacing) { case 0: break; case 1: if ((ah->flag & A_ROOT_ART) == 0) break; case 2: menu_length++; mi++; break; } if (menu_length >= maxa) break; } ah->menu_line = menu_length; art_id_to_mi[menu_articles] = mi; mi->mi_art_id = menu_articles++; mi->mi_cura = cura = nexta - firsta; if (ah->flag & A_CLOSED) { /* skip rest of thread */ nexta = thread_counters(nexta); if (nexta == firsta + cura + 1) ah->flag &= ~A_CLOSED; else { article_number tmpa = firsta + cura; while (++tmpa < nexta) articles[tmpa]->menu_line = menu_length; } } else nexta++; ah->disp_attr = A_NOT_DISPLAYED; mark(); if (++menu_length >= maxa) break; mi++; } } if (menu_length > maxa) menu_length = maxa; fl; s_keyboard = 0; prompt_line = firstl + menu_length; if (!long_menu || menu_length < maxa) prompt_line++; numa = nexta - firsta - 1; if (numa < 0) prompt_line++; if (next_cura >= 0) { cura = next_cura; set_root_if_closed(); next_cura = -1; } else { cura = 0; for (article_id = firsta; cura < numa; article_id++, cura++) { if ((articles[article_id]->attr & A_SELECT) == 0) break; /*???*/ if (!IS_VISIBLE(articles[article_id])) continue; } if (!IS_VISIBLE(articles[article_id])) cura = root_article(article_id) - firsta; } build_prompt: raw(); Prompt: prompt(pr_fmt, pct(0L, (long)(n_articles-1), (long)firsta, (long)(firsta+numa))); if (delayed_msg[0] != NUL) { msg(delayed_msg); delayed_msg[0] = NUL; } same_prompt: if (cura < 0 || cura > numa) cura = 0; if (!IS_VISIBLE(articles[firsta+cura])) { cura = next_root_article(firsta + cura) - firsta; if (cura > numa) cura = 0; } if (numa >= 0) { cursor_at_id(); } last_k_cmd = cur_k_cmd; get_next_k_cmd: k_cmd = get_k_cmd_1(); alt_key: if (k_cmd & K_MACRO) { m_invoke(k_cmd & ~K_MACRO); goto get_next_k_cmd; } switch (cur_k_cmd = k_cmd) { case K_UNBOUND: ding(); flush_input(); case K_INVALID: goto same_prompt; case K_REDRAW: next_cura = cura; goto redraw; case K_LAST_MESSAGE: msg((char *)NULL); goto same_prompt; case K_HELP: if (numa < 0) goto nextmenu; /* give specific help here */ display_help("menu"); goto redraw; case K_SHELL: if (group_file_name) *group_file_name = NUL; if (shell_escape()) goto redraw; goto Prompt; case K_VERSION: prompt(P_VERSION); goto same_prompt; case K_EXTENDED_CMD: temp = consolidated_menu; switch (alt_command()) { case AC_UNCHANGED: goto same_prompt; case AC_QUIT: menu_return( ME_QUIT ); case AC_PROMPT: goto Prompt; case AC_REORDER: firsta = 0; consolidate = do_consolidation(); goto redraw; case AC_REDRAW: if (temp != consolidated_menu) consolidate = do_consolidation(); goto redraw; case AC_KEYCMD: k_cmd = alt_cmd_key; goto alt_key; case AC_REENTER_GROUP: menu_return(ME_REENTER_GROUP); } case K_QUIT: menu_return(ME_QUIT); case K_CANCEL: savemode = "Cancel"; fname = ""; goto cancel1; case K_SAVE_NO_HEADER: case K_SAVE_SHORT_HEADER: case K_SAVE_FULL_HEADER: case K_PRINT: case K_UNSHAR: case K_PATCH: case K_UUDECODE: if (numa < 0) goto nextmenu; fname = init_save(k_cmd, &savemode); if (fname == NULL) goto Prompt; cancel1: enable_stop = 0; save_selected = 0; doing_unshar = k_cmd == K_UNSHAR || k_cmd == K_PATCH; did_unshar = 0; m_startinput(); if (novice) msg(" * selected articles on this page, + all selected articles"); while (!save_selected && !did_unshar) { prompt("\1%s\1 %.*s Article (* +): ", savemode, Columns - 25, fname); k_cmd = get_k_cmd(); if (k_cmd == K_SELECT_SUBJECT) { save_selected = 1; cura = 0; article_id = firsta; last_save = firsta + numa; } else if (k_cmd == K_AUTO_SELECT) { save_selected = 1; cura = -firsta; article_id = 0; last_save = n_articles - 1; } else if (k_cmd == K_ARTICLE_ID) { cura = article_id; article_id += firsta; last_save = article_id; if (articles[article_id]->flag & A_CLOSED) { int n = save_closed_mode % 10; int c; if (article_id == n_articles - 1) goto save_it; if (articles[article_id + 1]->flag & A_ROOT_ART) goto save_it; if (save_closed_mode >= 10) { prompt("\1%s thread\1 (r)oot (s)elected (u)nread (b)oth (a)ll (%c)", savemode, "rsuba"[n]); switch (get_c()) { case 'r': n = 0; break; case 's': n = 1; break; case 'u': n = 2; break; case 'b': n = 3; break; case 'a': n = 4; break; case SP: case CR: case NL: break; default: ding(); goto Prompt; } } switch (n) { case 0: /* save root only */ break; case 1: /* save all selected */ save_selected = 1; break; case 2: /* save all unread */ save_selected = 2; break; case 3: /* save all selected + unread */ save_selected = 3; break; case 4: /* save all articles */ break; } if (n) last_save = next_root_article(article_id) - 1; save_selected |= 8; /* closed subject */ temp1 = cura; } } else break; save_it: for ( ; article_id <= last_save ; article_id++, cura++) { ah = articles[article_id]; switch (save_selected & 0x3) { case 0: break; case 3: if (ah->attr == 0) break; case 1: if ((ah->attr & A_SELECT) == 0) continue; break; case 2: if (ah->attr == 0) break; continue; } if (cur_k_cmd == K_CANCEL) { if (current_group->group_flag & G_FOLDER) { fcancel(ah); } else switch (cancel(ah)) { case -1: did_unshar = 1; continue; case 0: ah->attr = A_CANCEL; break; default: continue; } if (!did_unshar) mark(); continue; } if (doing_unshar) { did_unshar++; } else if (ah->subject != NULL) prompt("Processing '%.50s'...", ah->subject); else if (cura >= 0 && cura <= numa) prompt("Processing %c...", ident[cura]); else prompt("Processing entry %d...", article_id); if (save(ah)) { ah->attr = A_READ; if (doing_unshar) continue; if (cura >= 0 && cura <= numa) mark(); } } if (save_selected & 8) { save_selected = 0; /* select closed */ cura = temp1; mark(); } } if (save_selected) cura = 0; m_endinput(); enable_stop = 1; if (cur_k_cmd != K_CANCEL) end_save(); if (did_unshar) { printf("\r\n"); any_key(0); goto redraw; } goto Prompt; case K_FOLLOW_UP: #ifdef NNTP_POST if (use_nntp && nntp_no_post()) goto same_prompt; #endif case K_REPLY: if (numa < 0) goto nextmenu; prompt(k_cmd == K_REPLY ? "\1Reply to author\1 of article: " : "\1Follow Up\1 to article: "); if (get_k_cmd() == K_ARTICLE_ID) if (answer(articles[firsta+article_id], k_cmd, -1)) goto redraw; goto Prompt; case K_POST: #ifdef NNTP_POST if (use_nntp && nntp_no_post()) goto same_prompt; #endif if (post_menu()) goto redraw; goto Prompt; case K_MAIL_OR_FORWARD: if (numa < 0) goto nextmenu; prompt("\1Article to be forwarded\1 (SP if none): "); if ((k_cmd = get_k_cmd()) == K_ARTICLE_ID) { if (answer(articles[firsta+article_id], K_MAIL_OR_FORWARD, 1)) goto redraw; } else if (k_cmd == K_CONTINUE) if (answer((article_header *)NULL, K_MAIL_OR_FORWARD, 0)) goto redraw; goto Prompt; /* case K_CANCEL: if (numa < 0) goto nextmenu; if (current_group->group_flag & G_FOLDER) { prompt("\1Cancel Folder\1 Article: "); if (get_k_cmd() == K_ARTICLE_ID) { cura = article_id; fcancel(articles[firsta+article_id]); mark(); } goto Prompt; } prompt("\1Cancel\1 Article: "); if (get_k_cmd() == K_ARTICLE_ID) if (cancel(articles[firsta+article_id]) & 1) goto redraw; goto Prompt; */ case K_UNSUBSCRIBE: if (unsubscribe(current_group)) { if (current_group->group_flag & G_UNSUBSCRIBED) menu_return(ME_NEXT); home(); CALL(print_header)(); } goto Prompt; case K_GROUP_OVERVIEW: group_overview(-1); goto redraw; case K_KILL_HANDLING: switch (kill_menu((article_header *)NULL)) { case 0: /* select */ do_auto_select((regexp *)NULL, 2); break; case 1: /* kill */ if (!do_auto_kill()) break; goto junk_killed_articles; default: break; } goto Prompt; case K_CONTINUE: /* goto next menu page or show the articles */ repl_attr(firsta, nexta, 0, A_SEEN, 0); /* fall thru */ case K_CONTINUE_NO_MARK: /* but don't mark unselected articles */ if (nexta < n_articles) goto nextmenu; break; case K_READ_GROUP_THEN_SAME: if (temp = mark_read_return) goto do_marked_by; break; case K_NEXT_GROUP_NO_UPDATE: if (temp = mark_next_group) goto do_marked_by; menu_return(ME_NEXT); case K_READ_GROUP_UPDATE: if ((temp = mark_read_skip) == 0) break; do_marked_by: temp1 = 0; temp2 = n_articles; switch (temp) { case 1: temp1 = firsta; case 3: temp2 = nexta; break; case 2: temp2 = firsta - 1; break; case 4: break; } repl_attr(temp1, temp2, 0, A_SEEN, 0); if (k_cmd != K_NEXT_GROUP_NO_UPDATE) break; menu_return(ME_NEXT); case K_PREVIOUS: menu_return(ME_PREV); case K_ADVANCE_GROUP: case K_BACK_GROUP: if (merged_menu) { msg("No possible on merged menu"); goto same_prompt; } /* FALL THRU */ case K_GOTO_GROUP: temp1 = n_articles; switch (goto_group(k_cmd, (article_header *)NULL, (flag_type)0)) { case ME_REDRAW: firsta = 0; if (temp1 != n_articles && consolidate) consolidate = do_consolidation(); goto redraw; case ME_NO_ARTICLES: msg("No selections made."); case ME_NO_REDRAW: goto Prompt; case ME_QUIT: menu_return( ME_QUIT ); case ME_PREV: goto redraw; case ME_NEXT: s_keyboard = 1; goto empty_menu_hack; } case K_OPEN_SUBJECT: if (numa < 0) goto nextmenu; prompt("\1Open subject\1"); k_cmd = get_k_cmd(); if (k_cmd != K_ARTICLE_ID) { if (k_cmd != cur_k_cmd) goto Prompt; article_id = cura; } open_subject: ah = articles[firsta+article_id]; if (!(ah->flag & A_CLOSED) || (ah->flag & (A_ROOT_ART | A_NEXT_SAME)) == A_ROOT_ART) goto Prompt; cura = article_id = root_article(firsta + article_id) - firsta; while (cura + firsta < n_articles) { ah = articles[firsta+cura]; if (cura > article_id && ah->flag & A_ROOT_ART) break; ah->flag &= ~A_CLOSED; cura++; } cura = article_id; goto partial_redraw; case K_CLOSE_SUBJECT: if (numa < 0) goto nextmenu; prompt("\1Close subject\1"); k_cmd = get_k_cmd(); if (k_cmd != K_ARTICLE_ID) { if (k_cmd != cur_k_cmd) goto Prompt; article_id = cura; } ah = articles[firsta+article_id]; if ((ah->flag & A_CLOSED) || (ah->flag & (A_ROOT_ART | A_NEXT_SAME)) == A_ROOT_ART) { cura = next_root_article(firsta + cura) - firsta; goto Prompt; } cura = article_id = root_article(firsta + article_id) - firsta; while (cura + firsta < n_articles) { ah = articles[firsta+cura]; if (cura > article_id && ah->flag & A_ROOT_ART) break; ah->flag |= A_CLOSED; cura++; } cura = article_id; next_cura = next_root_article(firsta + cura) - firsta; if (cura >= 0) goto partial_redraw_nc; articles[cura + firsta]->menu_line = articles[firsta]->menu_line; firsta += cura; goto redraw; case K_LEAVE_NEXT: case K_JUNK_ARTICLES: junk_prompt = cur_k_cmd == K_JUNK_ARTICLES ? 1 : 5; for (;;) { switch (junk_prompt) { case 1: if (novice) msg("Use J repeatedly to select other functions"); prompt("\1Mark read\1 S)een U)nmarked A)ll *+)selected a-z . [LN]"); junk_attr = A_READ; break; case 2: prompt("\1Unmark\1 S)een R)ead a-z [*+LAN.J] "); junk_attr = 0; break; case 3: prompt("\1Select\1 L)eft-over, N(leave-next) [USRa-z.J]"); junk_attr = A_SELECT; break; case 4: prompt("\1Kill\1 R)ead S)een [LANU*+a-z.J]"); junk_attr = A_KILL; break; case 5: prompt("\1Leave\1 a-z .,/ * + U)nmarked [LANRSJ]"); junk_attr = A_LEAVE_NEXT; break; default: junk_prompt = 1; continue; } junk_another: if (cura < 0 || cura > numa) cura = 0; cursor_at_id(); switch (get_k_cmd()) { case K_JUNK_ARTICLES: junk_prompt++; /* can be 0 */ continue; case K_ARTICLE_ID: cura = article_id; if (junk_attr == A_KILL) junk_attr = A_READ; if (auto_select_closed > 0 && articles[firsta + cura]->flag & A_CLOSED) repl_attr_subject(A_KILL, junk_attr, 1); else { articles[firsta + cura]->attr = junk_attr; mark(); cura++; } goto junk_another; case K_NEXT_LINE: cura++; goto junk_another; case K_PREV_LINE: --cura; goto junk_another; case K_SELECT_SUBJECT: if (junk_attr == A_KILL) junk_attr = A_READ; repl_attr(firsta, nexta, A_AUTO_SELECT, A_SELECT, 0); repl_attr(firsta, nexta, A_SELECT, junk_attr, 1); goto Prompt; case K_AUTO_SELECT: repl_attr_all(A_AUTO_SELECT, A_SELECT, 0); orig_attr = A_SELECT; break; default: switch (cur_key) { case 'S': orig_attr = A_SEEN; break; case 'U': orig_attr = 0; break; case 'L': if (junk_attr == A_KILL) junk_attr = A_READ; orig_attr = A_LEAVE; break; case 'A': orig_attr = A_KILL; break; case 'N': orig_attr = A_LEAVE_NEXT; break; case 'R': /* kill read articles */ orig_attr = A_READ; break; default: goto Prompt; } break; } break; } if (nexta - firsta < n_articles) { prompt("On all menu pages? "); switch (yes(1)) { case -1: goto Prompt; case 0: if (!repl_attr(firsta, nexta, orig_attr, junk_attr, 1)) goto Prompt; break; case 1: if (!repl_attr_all(orig_attr, junk_attr, 1)) goto Prompt; break; } } else if (!repl_attr(firsta, nexta, orig_attr, junk_attr, 1)) goto Prompt; if (junk_attr != A_KILL) goto Prompt; junk_killed_articles: elim_list[0] = firsta; elim_list[1] = firsta + cura; elim_list[2] = nexta; if (elim_articles(elim_list, 3)) { firsta = elim_list[0]; goto redraw; } firsta = elim_list[0]; cura = elim_list[1] - firsta; nexta = elim_list[2]; goto Prompt; case K_ARTICLE_ID: if (numa < 0) goto nextmenu; if (!is_k_select && auto_preview_mode) goto auto_preview; cura = article_id; if (!auto_select_closed || !(articles[firsta+cura]->flag & A_CLOSED)) { toggle(); if (!is_k_select && auto_select_subject) goto select_subject; mark(); cura++; goto same_prompt; } if (auto_select_closed < 0) { article_id = cura; goto open_subject; } mi = menu_info + articles[firsta+cura]->menu_line; if (mi->mi_unread == 0) repl_attr_subject(A_KILL, A_SELECT, 1); else if (mi->mi_selected == mi->mi_unread) repl_attr_subject(auto_select_closed == 2 ? A_KILL : A_SELECT, 0, 1); else repl_attr_subject(auto_select_closed == 2 ? A_KILL : 0, A_SELECT, 1); goto same_prompt; case K_SELECT_INVERT: if (numa < 0) goto nextmenu; temp = cura; no_raw(); /* for x-on/x-off */ for (cura = 0; cura <= numa; cura++) { toggle(); } for (cura = 0; cura <= numa; cura++) { if (IS_VISIBLE(articles[firsta+cura])) mark(); } fl; REDRAW_CHECK; raw(); cura = temp; goto same_prompt; case K_UNSELECT_ALL: if (last_k_cmd == K_UNSELECT_ALL) repl_attr_all(A_SELECT, 0, 1); else repl_attr_all(A_AUTO_SELECT, 0, 1); fl; cura = 0; goto same_prompt; case K_NEXT_LINE: if (numa < 0) goto nextmenu; cura++; goto same_prompt; case K_PREV_LINE: if (numa < 0) goto nextmenu; if (--cura < 0) cura = numa; set_root_if_closed(); goto same_prompt; case K_SELECT_SUBJECT: if (numa < 0) goto nextmenu; if (last_k_cmd != K_ARTICLE_ID) toggle(); select_subject: repl_attr_subject(A_KILL, last_attr, 1); goto same_prompt; case K_SELECT_RANGE: if (numa < 0) goto nextmenu; if (last_k_cmd == K_ARTICLE_ID) { cura--; if (cura < 0) cura = numa; } else last_attr = (articles[firsta+cura]->attr & A_SELECT) ? 0 : A_SELECT; range_again: prompt("\1%select range\1 %c-", last_attr ? "S" : "Des", ident[cura]); k_cmd = get_k_cmd(); if (k_cmd == K_SELECT_RANGE) { last_attr = last_attr ? 0 : A_SELECT; goto range_again; } if (k_cmd != K_ARTICLE_ID) goto Prompt; if (article_id > cura) { article_number tmp = cura; cura = article_id; article_id = tmp; } repl_attr(firsta+article_id, firsta+cura+1, A_KILL, last_attr, 1); goto Prompt; case K_AUTO_SELECT: do_auto_select((regexp *)NULL, 1); goto same_prompt; case K_GOTO_MATCH: prompt("\1Select regexp\1 "); if ((fname = get_s(NONE, NONE, NONE, NULL_FCT)) == NULL) goto Prompt; if (*fname != NUL) { if (regular_expr) freeobj(regular_expr); if (case_fold_search) fold_string(fname); regular_expr = regcomp(fname); } if (regular_expr == NULL) msg("No previous expression"); else do_auto_select(regular_expr, 2); goto Prompt; case K_NEXT_PAGE: if (nexta < n_articles) goto nextmenu; if (firsta == 0) goto same_prompt; nexta = 0; goto nextmenu; case K_PREV_PAGE: if (firsta == 0 && nexta == n_articles) goto same_prompt; prevmenu: nexta = (firsta > 0 ? firsta : n_articles); for (menu_length = maxa; menu_length > 0 && --nexta >= 0; ) { if (!IS_VISIBLE(articles[nexta])) continue; if (--menu_length > 0) { switch (menu_spacing) { case 0: break; case 1: if ((articles[nexta]->flag & A_ROOT_ART) == 0) break; case 2: --menu_length; break; } } } if (nexta < 0) nexta = 0; goto nextmenu; case K_FIRST_PAGE: if (firsta == 0) goto same_prompt; nexta = 0; goto nextmenu; case K_LAST_PAGE: if (nexta == n_articles) goto same_prompt; firsta = 0; goto prevmenu; case K_PREVIEW: if (numa < 0) goto nextmenu; preview_other: prompt("\1Preview article\1"); k_cmd = get_k_cmd(); if (k_cmd != K_ARTICLE_ID) { if (k_cmd != K_PREVIEW) goto Prompt; article_id = cura; } auto_preview: temp = prompt_line; preview_next: cura = article_id; ah = articles[firsta+cura]; no_raw(); orig_attr = ah->attr; ah->attr = 0; menu_cmd = more(ah, MM_PREVIEW, prompt_line); if (menu_cmd == MC_MENU) { next_cura = cura; if (ah->attr == 0) ah->attr = orig_attr; if (prompt_line < 0) goto redraw; mark(); prompt_line = temp; goto build_prompt; } if (ah->attr == 0) ah->attr = preview_mark_read ? A_READ : orig_attr; if (prompt_line >= 0) mark(); next_cura = ++cura; switch (menu_cmd) { case MC_DO_KILL: if (!do_auto_kill()) break; elim_list[0] = firsta; elim_list[1] = firsta + cura; elim_articles(elim_list, 2); firsta = elim_list[0]; next_cura = elim_list[1] - firsta; goto redraw; case MC_DO_SELECT: if (prompt_line >= 0) { /* not redrawn */ do_auto_select((regexp *)NULL, 2); break; } numa = -1; do_auto_select((regexp *)NULL, 2); /* FALL THRU */ case MC_QUIT: menu_return( ME_QUIT ); case MC_REENTER_GROUP: menu_return( ME_REENTER_GROUP ); case MC_NEXT: case MC_PREVIEW_NEXT: if (prompt_line < 0) { /* redrawn screen ! */ if (quit_preview(menu_cmd)) goto redraw; prompt_line = Lines; } else { /* if (ah->attr == A_LEAVE || ah->attr == A_LEAVE_NEXT) { cura--; mark(); cura++; } */ if (quit_preview(menu_cmd)) break; prompt_line = temp; } article_id = cura; goto preview_next; case MC_PREVIEW_OTHER: prompt_line = temp; raw(); goto preview_other; default: if (prompt_line < 0) goto redraw; break; } prompt_line = temp; goto build_prompt; case K_LAYOUT: if (++fmt_linenum > 4) fmt_linenum = 0; goto redraw; default: msg("Command %d not supported", k_cmd); goto same_prompt; } no_raw(); do_auto_read: switch (show_articles()) { case MC_MENU: goto redraw; case MC_READGROUP: if (k_cmd == K_READ_GROUP_THEN_SAME) { if (read_ret_next_page && nexta < n_articles) firsta = nexta; goto redraw; } case MC_NEXTGROUP: menu_cmd = ME_NEXT; break; case MC_REENTER_GROUP: menu_cmd = ME_REENTER_GROUP; break; case MC_QUIT: menu_cmd = ME_QUIT; break; default: sys_error("show_articles returned improper value"); } menu_exit: cur_bypass = o_bypass; n_selected = o_selected; firsta = o_firsta; in_menu_mode = o_mode; menu_level--; no_raw(); return menu_cmd; } /* * return article header for article on menu */ article_header *get_menu_article() { register article_header *ah; fputs(" from article: ", stdout); fl; if (get_k_cmd() == K_ARTICLE_ID) { ah = articles[firsta + article_id]; if (ah->a_group) init_group(ah->a_group); return ah; } return NULL; } /* * read command from command line */ alt_command() { int ok_val, macro_cmd; char *cmd, brkchars[10]; extern key_type erase_key; extern int get_from_macro; extern int alt_completion(); if (get_from_macro) ok_val = AC_UNCHANGED; else { prompt(":"); ok_val = AC_PROMPT; } again: sprintf(brkchars, "?%c ", erase_key); cmd = get_s(NONE, NONE, brkchars, alt_completion); if (cmd == NULL || *cmd == NUL || *cmd == SP || *cmd == erase_key) return ok_val; macro_cmd = get_from_macro; if (*cmd == '?') { display_file("help.extended", CLEAR_DISPLAY); ok_val = AC_REDRAW; goto new_prompt; } ok_val = parse_command(cmd, ok_val, (FILE *)NULL); if (ok_val != AC_REDRAW || !delay_redraw) return ok_val; new_prompt: if (macro_cmd) return ok_val; prompt_line = -1; printf("\n\r:"); fl; goto again; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.