home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
unix
/
volume19
/
nn
/
part07
< prev
next >
Wrap
Text File
|
1989-06-22
|
50KB
|
2,291 lines
Subject: v19i068: NN, a Usenet news reader, Part07/15
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: storm@texas.dk (Kim F. Storm)
Posting-number: Volume 19, Issue 68
Archive-name: nn/part07
#!/bin/sh
# this is part 7 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file master.c continued
#
CurArch=7
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file master.c"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' >> master.c
X write_error();
X fflush(master_file);
X}
X
X
Xclean_group(gh)
Xregister group_header *gh;
X{
X if (trace)
X log_entry('T', "CLEAN %s", gh->group_name);
X
X gh->first_l_article = 0;
X gh->last_l_article = 0;
X
X gh->index_write_offset = (off_t)0;
X gh->data_write_offset = (off_t)0;
X
X gh->group_flag &= ~G_EXPIRE;
X gh->group_flag |= G_BLOCKED;
X
X save_group(gh);
X}
X
X/*
X * Build initial master file ; calls Initialize script and
X * reads info from its standard output
X */
X
Xbuild_master()
X{
X char command[512];
X char groupname[512];
X group_header group;
X FILE *group_file, *src;
X int lcount, use_group_file;
X
X
X printf("Confirm initialization by typing 'OK': ");
X fl;
X gets(command);
X if (strcmp(command, "OK")) {
X printf("No initialization\n");
X nn_exit(0);
X }
X
X printf("Initializing master data base...");
X fl;
X
X if (chdir(lib_directory) < 0) /* so we can use open_file */
X sys_error("lib");
X
X#ifdef NNTP
X if (use_nntp && nntp_get_active() < 0)
X sys_error("Can't get active file");
X#endif
X /* check active file for duplicates */
X
X sprintf(command, "awk 'NF>0{print $1}' %s | sort | uniq -d", news_active);
X
X src = popen(command, "r");
X
X for (lcount = 0; fgets(groupname, 512, src); lcount++) {
X if (lcount == 0)
X printf("\n%s contains duplicate entries for the following groups:",
X news_active);
X
X fputs(groupname, stdout);
X }
X
X pclose(src);
X
X if (lcount > 0) {
X printf("Do you want to repair this file before continuing ? (y)");
X gets(command);
X if (command[0] == NUL || command[0] == 'y' || command[0] == 'Y')
X nn_exit(0);
X }
X
X /* if a "GROUPS" file exist offer to use that, else */
X /* read group names from active file */
X
X use_group_file = 0;
X
X if (src = open_groups(OPEN_READ)) {
X printf("\nA GROUPS file already exist -- reuse it? (y)");
X fl;
X gets(command);
X if (command[0] == NUL || command[0] == 'y' || command[0] == 'Y') {
X use_group_file = 1;
X } else
X fclose(src);
X }
X
X if (!use_group_file) {
X strcpy(command, "awk 'NF>0{print $1}' ");
X strcat(command, news_active);
X strcat(command, " | sort -u");
X
X src = popen(command, "r");
X
X group_file = open_groups(OPEN_CREATE|MUST_EXIST);
X }
X
X open_master(OPEN_CREATE);
X
X fseek(master_file, sizeof(master), 0);
X
X master.number_of_groups = 0;
X
X while (fgets(groupname, 512, src)) {
X
X group.group_num = master.number_of_groups++;
X
X group.group_name_length = strlen(groupname) - 1; /* strip NL */
X groupname[group.group_name_length] = NUL;
X group.group_name = groupname;
X
X init_group(&group);
X
X clean_group(&group);
X
X group.group_flag = 0;
X
X /* moderation flag will be set by first visit_active_file call */
X
X if (strcmp(groupname, "control") == 0)
X group.group_flag |= G_CONTROL;
X
X save_group(&group);
X
X if (!use_group_file) {
X groupname[group.group_name_length] = NL;
X Fwrite(groupname, sizeof(char),
X group.group_name_length + 1, group_file);
X }
X }
X
X if (use_group_file) {
X master.next_group_write_offset = ftell(src);
X fclose(src);
X } else {
X master.next_group_write_offset = ftell(group_file);
X fclose(group_file);
X pclose(src);
X }
X
X master.last_scan = 0;
X
X save_master();
X
X close_master();
X
X printf("done\n");
X
X log_entry('M', "Master data base initialized");
X
X fl;
X}
X
X
X/*
X * receive commands from administrator
X */
X
Xreceive_admin()
X{
X FILE *gate;
X char buffer[128], *bp;
X char command, *user_date;
X long arg1, arg2;
X int must_collect;
X register group_header *gh;
X
X gate = open_file(relative(lib_directory, "GATE"), OPEN_READ | OPEN_UNLINK);
X if (gate == NULL) return 0;
X
X sleep(2); /* give administrator time to flush buffers */
X
X must_collect = 0;
X
X while (fgets(buffer, 128, gate)) {
X bp = buffer;
X command = *bp;
X if ((bp = strchr(bp, ';')) == NULL) continue;
X arg1 = atol(++bp);
X if ((bp = strchr(bp, ';')) == NULL) continue;
X arg2 = atol(++bp);
X if ((bp = strchr(bp, ';')) == NULL) continue;
X user_date = ++bp;
X if ((bp = strchr(bp, ';')) == NULL) continue;
X *bp++ = NUL;
X if (*bp != NL) continue;
X
X log_entry('A', "RECV %c %ld %ld (%s)",
X command, arg1, arg2, user_date);
X
X if (arg1 >= 0 && arg1 < master.number_of_groups)
X gh = &active_groups[arg1];
X else
X gh = NULL;
X
X switch (command) {
X
X case 'r':
X repeat_delay = arg1;
X continue;
X
X case 'e':
X expire_level = arg1;
X continue;
X
X case 'X': /* expire */
X if (gh) {
X gh->group_flag |= G_EXPIRE | G_BLOCKED;
X save_group(gh);
X break;
X }
X visit_active_file(); /* just in case */
X Loop_Groups_Header(gh) {
X if (gh->first_l_article + arg2 < gh->first_article) {
X gh->group_flag |= G_EXPIRE;
X save_group(gh); /* could block here */
X }
X }
X break;
X
X case 'S': /* set flag */
X gh->group_flag |= arg2;
X save_group(gh);
X continue;
X
X case 'C': /* clear flag */
X gh->group_flag |= arg2;
X save_group(gh);
X continue;
X
X case 'R': /* recollect */
X if (gh) {
X clean_group(gh);
X } else
X Loop_Groups_Header(gh)
X clean_group(gh);
X break;
X
X case 'U': /* unconditional pass */
X unconditional++;
X break;
X
X case 'T': /* toggle trace flag */
X trace = !trace;
X continue;
X
X default:
X continue;
X }
X must_collect++;
X }
X
X fclose(gate);
X
X return must_collect;
X}
X
X
X/*
X * disk write with check -- halt if no space on disk
X */
X
X
XFwrite(buf, size, nitems, stream)
Xchar *buf;
Xint size;
Xint nitems;
XFILE *stream;
X{
X if (fwrite(buf, size, nitems, stream) != nitems)
X write_error();
X}
X
Xwrite_error()
X{
X /*
X * should wait for problems to clear out rather than die...
X */
X sys_error("DISK WRITE ERROR");
X}
X
X/*
X * dummy routines - should never be called by master
X */
X
X/*VARARGS*/
Xuser_error()
X{
X dummy_error("user_error");
X}
X
Xdummy_error(name)
Xchar *name;
X{
X sys_error("Dummy routine called by master: %s", name);
X}
X
X
X#ifdef NNTP /* XXX */
Xmsg() {}
X#endif /* NNTP Bogus */
NO_NEWS_IS_GOOD_NEWS
echo "File master.c is complete"
chmod 0644 master.c || echo "restore of master.c fails"
set `wc -c master.c`;Sum=$1
if test "$Sum" != "15145"
then echo original size 15145, current size $Sum;fi
echo "x - extracting match.c (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > match.c &&
X#define NUL '\0'
X#define NULL ((char *)0)
X
X
X#ifdef notdef
X
X/* use this table for creating input to the match.h routines */
X
Xchar match_xxx[128] = {
X
X/* NUL SOH STX ETX EOT ENQ ACK BEL BS TAB NL VT FF CR SO SI */
X 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
X
X/* DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US */
X 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
X
X/* SP ! " # $ % & ' ( ) * + , - . / */
X 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
X
X/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
X 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
X
X/* @ A B C D E F G H I J K L M N O */
X 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
X
X/* P Q R S T U V W X Y Z [ \ ] ^ _ */
X 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
X
X/* ` a b c d e f g h i j k l m n o */
X 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
X
X/* p q r s t u v w x y z { | } ~ DEL */
X 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
X
X};
X#endif
X
X
X/*
X * the following routines only works for ASCII !!!!
X *
X * they are a quick hack to check for the occurrence of a word
X * (regardless of case) in a string
X */
X
X#define UNIFY 040
X
Xinit_quick_match(mask)
Xchar *mask;
X{
X register char *m;
X
X for (m = mask; *m; m++) *m |= UNIFY;
X}
X
Xchar *quick_match(subject, mask)
Xregister char *subject;
Xchar *mask;
X{
X register char *q, *m;
X register char m1 = *mask;
X
X for (; *subject; subject++) {
X if ((*subject | UNIFY) != m1) continue;
X
X q = subject; m = mask;
X do
X if (*++m == NUL) return subject;
X while ((*++q | UNIFY) == *m);
X }
X return NULL;
X}
NO_NEWS_IS_GOOD_NEWS
chmod 0644 match.c || echo "restore of match.c fails"
set `wc -c match.c`;Sum=$1
if test "$Sum" != "1884"
then echo original size 1884, current size $Sum;fi
echo "x - extracting match.h (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > match.h &&
X/* usage:
X * MATCH_DROP(t, a) and MATCH_DROP(t, b) must both be proven false
X * before MATCH_EQ(t, a, b) is used.
X */
X
X#define MATCH_DROP(table, c) ( c & 0200 || table[c] == 0 )
X
X#define MATCH_EQ(table, a, b) ( a == b || table[a] == table[b] )
X
X#define MATCH_LS_EQ(table, a, b) ( a <= b || table[a] <= table[b] )
X
X#define MATCH_LS(table, a, b) ( a < b || table[a] < table[b] )
X
X#define MATCH_CMP(table, a, b) (table[a] - table[b])
NO_NEWS_IS_GOOD_NEWS
chmod 0644 match.h || echo "restore of match.h fails"
set `wc -c match.h`;Sum=$1
if test "$Sum" != "439"
then echo original size 439, current size $Sum;fi
echo "x - extracting menu.c (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > menu.c &&
X/*
X * selection mode menu
X */
X
X#include "config.h"
X#include "articles.h"
X#include "term.h"
X#include "keymap.h"
X#include "menu.h"
X
X
Xexport int preview_window = 0; /* size of preview window */
Xexport int fmt_linenum = 1; /* menu line format */
Xexport int fmt_rptsubj = 0; /* repeat identical subjects if !0 */
Xexport int novice = 1; /* novice mode -- use extended prompts */
Xexport int long_menu = 0; /* don't put empty lines around menu lines */
Xexport int delay_redraw = 0; /* prompt again if :-command clears screen */
X
Xexport char *delayed_msg = NULL; /* give to msg() after redraw */
X
Ximport also_read_articles;
Ximport merged_menu;
X
Xextern group_completion();
X
Xstatic int firstl; /* first menu line */
X
Xstatic int firsta; /* first article on menu (0 based) */
Xstatic int cura; /* current article */
Xstatic int next_cura; /* article to become cura if >= 0 */
Xstatic int numa; /* no of articles on menu - 1 */
X
X#define INTERVAL1 ('z' - 'a' + 1)
X#define INTERVAL2 ('9' - '0' + 1)
X
Xchar ident[] = "abcdefghijklmnopqrstuvwxyz0123456789";
Xchar Ident[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ&&&&&&&&&&";
X
X/* mark commands */
X
X#define OFF 0
X#define ON 1
X#define TOGGLE 2
X#define INIT 3
X#define SAVED 4
X#define REMOVE 5
X#define CANCEL 6
X
Xstatic int how;
X
Xstatic mark()
X{
X register article_header *ah;
X int lno, curhow, must_print, lnum, lsubj, lname;
X
X ah = articles[firsta + cura];
X curhow = (ah->flag & A_SELECT) ? ON : OFF;
X if (how == curhow) return;
X
X lno = firstl + cura;
X must_print = STANDOUT;
X
X toggle:
X
X switch (how) {
X
X case TOGGLE:
X how = (curhow == ON) ? OFF : ON;
X goto toggle;
X
X case ON:
X if (ah->flag & A_CANCEL) {
X if (curhow == OFF) return;
X how = OFF;
X goto toggle;
X }
X ah->flag |= A_SELECT;
X break;
X
X case OFF:
X ah->flag &= ~A_SELECT;
X break;
X
X case INIT:
X gotoxy(0, lno);
X putchar(ident[cura]);
X how = curhow;
X must_print = 1;
X break;
X
X case SAVED:
X gotoxy(0, lno);
X putchar(Ident[cura]);
X return;
X
X case REMOVE:
X gotoxy(0, lno);
X clrline();
X return;
X
X case CANCEL:
X gotoxy(1, lno);
X if (ah->flag & A_SELECT) {
X ah->flag &= ~A_SELECT;
X break;
X }
X putchar((ah->flag & A_CANCEL) ? '#' : ' ');
X return;
X }
X
X if (cura < 0 || cura > numa) return;
X
X /* menu line formats:
X 1 3 8 10 20 22 xx
X : : : : : : :
X 0 id name subject +lines
X 1 id name lines subject
X 2 id lines subject
X 3 id subject
X 4 id name:8 subject
X */
X
X if (must_print) {
X
X if (fmt_linenum > 4) fmt_linenum = 1;
X
X if (ah->flag & A_CANCEL) {
X gotoxy(1, lno);
X putchar('#');
X } else
X if (how == ON) {
X if (so_gotoxy(1, lno, 1) == 0) putchar('*');
X } else {
X gotoxy(1, lno);
X putchar(' ');
X }
X
X if (fmt_linenum > 1) lnum = 0; else
X if (ah->lines < 10) lnum = 1; else
X if (ah->lines < 100) lnum = 2; else
X if (ah->lines < 1000) lnum = 3; else
X if (ah->lines < 10000) lnum = 4; else lnum = 5;
X
X lsubj = Columns - cookie_size - 2; /* ident char + space */
X
X switch (fmt_linenum) {
X
X case 0:
X lsubj -= NAME_LENGTH + 1 + 2 + lnum; /* name. .subj. +.lines */
X so_printf("%-*s ", NAME_LENGTH, ah->sender);
X break;
X
X case 1:
X lsubj -= NAME_LENGTH + 4;
X /* name.lines. .subj (name may be shortened) */
X lname = NAME_LENGTH + 2 - lnum;
X lsubj -= 4; /* 2 columns for the number + 2 spaces */
X so_printf("%-*.*s ", lname, lname, ah->sender);
X so_printf(ah->lines >= 0 ? "%d " : "? ", ah->lines);
X break;
X
X case 2:
X lsubj -= 6;
X so_printf("%5d ", ah->lines);
X break;
X
X case 3:
X break;
X
X case 4:
X lsubj -= 9;
X so_printf("%-8.8s ", ah->sender);
X break;
X }
X
X if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) {
X if (ah->replies == 0)
X so_printf("-");
X else
X prt_replies(ah->replies);
X } else {
X lsubj -= prt_replies(ah->replies);
X so_printf("%-.*s", lsubj, ah->subject);
X }
X
X if (fmt_linenum == 0)
X so_printf(ah->lines >= 0 ? " +%d" : " +?", ah->lines);
X
X so_end();
X } else
X putchar((how == OFF) ? ' ' : '*');
X
X fl;
X
X return;
X}
X
X
Xstatic prt_replies(level)
X{
X if (level == 0) return 0;
X
X if (level < 10) {
X so_printf("%-.*s", level, ">>>>>>>>>");
X return level;
X }
X
X so_printf(">>>%3d >>>>", level);
X return 11;
X}
X
X
Xstatic int article_id;
X
Xstatic int get_k_cmd()
X{
X register int c, map;
X
X loop:
X
X article_id = -1;
X
X if ((c = get_c()) & GETC_COMMAND)
X map = c & ~GETC_COMMAND;
X else
X map = menu_key_map[c];
X
X if (s_hangup) map = K_QUIT;
X
X if (map & K_MACRO) {
X m_invoke(map & ~K_MACRO);
X goto loop;
X }
X
X if (map & K_ARTICLE_ID) {
X article_id = map & ~K_ARTICLE_ID;
X map = K_ARTICLE_ID;
X
X if (article_id < 0 || article_id > numa) {
X ding();
X goto loop;
X }
X }
X
X return map;
X}
X
X
Xchar *pct(start, end, first, last)
Xlong start, end, first, last;
X{
X long n = end - start;
X static char buf[16];
X char *fmt;
X
X if (first <= start || n <= 0)
X if (last >= end)
X return "All";
X else
X fmt = "Top %d%%";
X else
X if (last >= end)
X return "Bot";
X else
X fmt = "%d%%";
X
X sprintf(buf, fmt, ((last - start) * 100)/n);
X return buf;
X}
X
Xmenu(print_header)
Xint (* print_header)();
X{
X register k_cmd, cur_k_cmd;
X register article_header *ah;
X int last_k_cmd, last_how, was_selected;
X int seen_all, menu_cmd, temp;
X int save_selected, last_save;
X int doing_unshar, did_unshar;
X char *fname, *savemode, *init_save();
X int nexta; /* first article on next menu */
X int maxa; /* max no of articles per menu page */
X int o_firsta, o_mode; /* for recursive calls */
X static menu_level = 0;
X char purpose[80], pr_fmt[60];
X extern int enable_stop, file_completion();
X extern int alt_cmd_key, in_menu_mode, slow_mode, any_message;
X
X#define menu_return(cmd) \
X { menu_cmd = (cmd); goto menu_exit; }
X
X o_firsta = firsta;
X o_mode = in_menu_mode;
X in_menu_mode = 1;
X
X menu_level++;
X
X sprintf(pr_fmt,
X menu_level == 1 ?
X "\1\2-- SELECT %s-----%%s-----\1" :
X "\1\2-- SELECT %s-----%%s-----<%s%d>--\1",
X novice ? "-- help:? " : "",
X novice ? "level " : "",
X menu_level);
X
X purpose[0] = NUL;
X if (!merged_menu && current_group->group_flag & G_NEW)
X get_purpose(purpose);
X
X seen_all = 0;
X firsta = 0;
X while (firsta < n_articles && articles[firsta]->flag & A_SEEN)
X firsta++;
X
X if (firsta == n_articles) {
X seen_all++;
X firsta = 0;
X }
X
X next_cura = -1;
X cur_k_cmd = K_UNBOUND;
X
X#ifdef HAVE_JOBCONTROL
X#define REDRAW_CHECK if (s_redraw) goto do_redraw
X
X do_redraw:
X /* safe to clear here, because we are going to redraw anyway */
X s_redraw = 0;
X#else
X#define REDRAW_CHECK
X#endif
X
X redraw:
X s_keyboard = 0;
X
X empty_menu_hack: /* do: "s_keyboard=1; goto empty_menu_hack;" */
X if (!slow_mode) s_keyboard = 0;
X
X nexta = firsta;
X
X clrdisp();
X
X firstl = (*print_header)();
X maxa = Lines - preview_window - firstl - 2;
X if (!long_menu) firstl++, maxa -= 2;
X
X if (maxa > (INTERVAL1 + INTERVAL2))
X maxa = INTERVAL1 + INTERVAL2;
X
X nextmenu:
X
X no_raw();
X gotoxy(0, firstl);
X clrpage(firstl);
X
X if (nexta > 0) {
X while (firsta < nexta)
X articles[firsta++]->flag |= A_SEEN;
X } else
X if (purpose[0]) {
X msg(purpose);
X }
X
X firsta = nexta;
X numa = Lines; /* for mark; is set correctly below */
X cura = 0;
X
X REDRAW_CHECK;
X
X if (!s_keyboard)
X while (nexta < n_articles && cura < maxa) {
X
X REDRAW_CHECK;
X
X how = INIT;
X mark(); fl;
X
X if (s_keyboard) { /* Signal may have corrupted output. */
X if (cura == 0)
X mark(); /* redraw first entry */
X else {
X how = REMOVE; /* We delete the last entry (the user */
X mark(); /* wanted to stop the output anyway) */
X cura--;
X nexta--;
X }
X break;
X }
X
X nexta++; cura++;
X }
X
X s_keyboard = 0;
X
X prompt_line = firstl + cura;
X if (!long_menu || cura < maxa) prompt_line++;
X
X numa = nexta - firsta - 1;
X if (numa < 0) prompt_line++;
X
X if (next_cura >= 0) {
X cura = next_cura;
X next_cura = -1;
X } else {
X cura = 0;
X for (article_id = firsta; cura < numa; article_id++, cura++)
X if ((articles[article_id]->flag & A_SELECT) == 0) break;
X }
X
X how = TOGGLE;
X
X build_prompt:
X
X raw();
X
X Prompt:
X
X prompt(pr_fmt,
X pct(0L, (long)(n_articles-1), (long)firsta, (long)(firsta+numa)));
X
X if (delayed_msg != NULL) {
X msg(delayed_msg);
X delayed_msg = NULL;
X }
X
X same_prompt:
X
X if (cura < 0 || cura > numa) cura = 0;
X
X if (numa >= 0) {
X gotoxy(0, firstl + cura);
X fl; /* place cursor at current article id */
X }
X
X last_k_cmd = cur_k_cmd;
X cur_k_cmd = k_cmd = get_k_cmd();
X if (any_message) clrmsg(-1);
X
X alt_key:
X
X switch (k_cmd) {
X
X case K_UNBOUND:
X ding();
X flush_input();
X goto same_prompt;
X
X case K_REDRAW:
X goto redraw;
X
X case K_LAST_MESSAGE:
X msg((char *)NULL);
X goto same_prompt;
X
X case K_HELP:
X if (numa < 0) goto nextmenu; /* give specific help here */
X display_help("menu");
X goto redraw;
X
X case K_SHELL:
X if (group_file_name) *group_file_name = NUL;
X if (shell_escape()) goto redraw;
X goto Prompt;
X
X case K_VERSION:
X prompt(P_VERSION);
X goto same_prompt;
X
X case K_EXTENDED_CMD:
X switch (alt_command()) {
X
X case AC_QUIT:
X menu_return( ME_QUIT );
X
X case AC_PROMPT:
X goto Prompt;
X
X case AC_REORDER:
X firsta = 0;
X /* fall thru */
X case AC_REDRAW:
X goto redraw;
X
X case AC_KEYCMD:
X k_cmd = alt_cmd_key;
X goto alt_key;
X
X case AC_HEADER:
X home();
X (*print_header)();
X goto Prompt;
X }
X
X case K_QUIT:
X menu_return(ME_QUIT);
X
X case K_SAVE_NO_HEADER:
X case K_SAVE_SHORT_HEADER:
X case K_SAVE_FULL_HEADER:
X case K_PRINT:
X case K_UNSHAR:
X case K_PATCH:
X
X if (numa < 0) goto nextmenu;
X
X fname = init_save(k_cmd, &savemode);
X if (fname == NULL) goto Prompt;
X
X enable_stop = 0;
X save_selected = 0;
X doing_unshar = k_cmd == K_UNSHAR || k_cmd == K_PATCH;
X did_unshar = 0;
X
X m_startinput();
X
X while (!save_selected && !did_unshar) {
X prompt("\1%s\1 %.*s Article (* +): ",
X savemode, Columns - 25, fname);
X
X k_cmd = get_k_cmd();
X
X if (k_cmd == K_SELECT_SUBJECT) {
X save_selected = 1;
X cura = 0;
X article_id = firsta;
X last_save = firsta + numa;
X } else
X if (k_cmd == K_AUTO_SELECT) {
X save_selected = 2;
X cura = -firsta;
X article_id = 0;
X last_save = n_articles - 1;
X } else
X if (k_cmd == K_ARTICLE_ID) {
X cura = article_id;
X article_id += firsta;
X last_save = article_id;
X } else
X break;
X
X for ( ; article_id <= last_save ; article_id++, cura++) {
X ah = articles[article_id];
X if (save_selected && (ah->flag & A_SELECT) == 0) continue;
X
X if (doing_unshar) {
X did_unshar++;
X } else
X if (cura >= 0 && cura <= numa)
X prompt("Processing %c...", ident[cura]);
X else
X prompt("Processing entry %d...", article_id);
X
X if (save(ah)) {
X if (doing_unshar) {
X if (save_selected)
X ah->flag &= ~A_SELECT;
X } else
X if (cura >= 0 && cura <= numa) {
X how = save_selected ? OFF : SAVED;
X mark();
X how = TOGGLE;
X } else
X if (save_selected)
X ah->flag &= ~A_SELECT;
X }
X }
X }
X
X if (save_selected) cura = 0;
X how = TOGGLE;
X
X m_endinput();
X
X enable_stop = 1;
X end_save();
X
X if (did_unshar) {
X any_key(0);
X goto redraw;
X }
X goto Prompt;
X
X case K_REPLY:
X case K_FOLLOW_UP:
X if (numa < 0) goto nextmenu;
X
X prompt(k_cmd == K_REPLY ?
X "\1Reply to author\1 of article: " :
X "\1Follow Up\1 to article: ");
X
X if (get_k_cmd() == K_ARTICLE_ID)
X if (answer(articles[firsta+article_id], k_cmd, -1))
X goto redraw;
X
X goto Prompt;
X
X case K_POST:
X if (post_menu()) goto redraw;
X goto Prompt;
X
X case K_MAIL_OR_FORWARD:
X if (numa < 0) goto nextmenu;
X
X prompt("\1Article to be forwarded\1 (SP if none): ");
X
X if ((k_cmd = get_k_cmd()) == K_ARTICLE_ID) {
X if (answer(articles[firsta+article_id], K_MAIL_OR_FORWARD, 1))
X goto redraw;
X } else
X if (k_cmd == K_CONTINUE)
X if (answer((article_header *)NULL, K_MAIL_OR_FORWARD, 0))
X goto redraw;
X
X goto Prompt;
X
X case K_CANCEL:
X if (numa < 0) goto nextmenu;
X
X if (current_group->group_flag & G_FOLDER) {
X prompt("\1Cancel Folder\1 Article: ");
X if (get_k_cmd() == K_ARTICLE_ID) {
X cura = article_id;
X fcancel(articles[firsta+article_id]);
X how = CANCEL;
X mark();
X }
X goto Prompt;
X }
X
X prompt("\1Cancel\1 Article: ");
X
X if (get_k_cmd() == K_ARTICLE_ID)
X if (cancel(articles[firsta+article_id]) & 1) goto redraw;
X goto Prompt;
X
X case K_UNSUBSCRIBE:
X if (unsubscribe(current_group)) {
X if (!(current_group->group_flag & G_SUBSCRIPTION))
X menu_return(ME_NEXT);
X home();
X (*print_header)();
X }
X goto Prompt;
X
X case K_GROUP_OVERVIEW:
X group_overview(0);
X goto redraw;
X
X case K_KILL_HANDLING:
X kill_menu((article_header *)NULL);
X goto Prompt;
X
X case K_CONTINUE: /* goto next menu page or show the articles */
X if (nexta < n_articles && !seen_all) goto nextmenu;
X /* fall thru */
X
X case K_READ_GROUP_UPDATE:
X case K_READ_GROUP_THEN_SAME:
X no_raw();
X clrdisp();
X
X switch (show_articles()) {
X
X case SH_MENU:
X goto redraw;
X
X case SH_QUIT:
X menu_return(ME_QUIT);
X
X case SH_NO_SELECT:
X break;
X
X case SH_NEXT:
X menu_return(ME_NEXT);
X
X case SH_READ:
X if (k_cmd == K_READ_GROUP_THEN_SAME || also_read_articles) goto redraw;
X break;
X
X default:
X user_error("show_articles returned improper value");
X }
X
X menu_return(ME_READ);
X
X case K_NEXT_GROUP_NO_UPDATE:
X menu_return(ME_NEXT);
X
X case K_PREVIOUS:
X menu_return(ME_PREV);
X
X case K_ADVANCE_GROUP:
X case K_BACK_GROUP:
X if (merged_menu) {
X msg("No possible on merged menu");
X goto same_prompt;
X }
X /* FALL THRU */
X
X case K_GOTO_GROUP:
X
X switch (goto_group(k_cmd, (article_header *)NULL)) {
X
X case ME_REDRAW:
X firsta = 0;
X goto redraw;
X
X case ME_NO_ARTICLES:
X msg("No selections made.");
X
X case ME_NO_REDRAW:
X goto Prompt;
X
X case ME_QUIT:
X menu_return( ME_QUIT );
X
X case ME_PREV:
X goto redraw;
X
X case ME_NEXT:
X case ME_READ:
X s_keyboard = 1;
X goto empty_menu_hack;
X }
X
X case K_ARTICLE_ID:
X if (numa < 0) goto nextmenu;
X
X cura = article_id;
X how = TOGGLE;
X mark();
X last_how = how;
X cura++;
X
X goto same_prompt;
X
X case K_SELECT_INVERT:
X if (numa < 0) goto nextmenu;
X
X temp = cura;
X
X no_raw(); /* for x-on/x-off */
X for (cura = 0; cura <= numa; cura++) {
X how = TOGGLE;
X mark();
X }
X fl;
X
X REDRAW_CHECK;
X raw();
X
X how = TOGGLE; cura = temp;
X goto same_prompt;
X
X
X case K_SELECT:
X if (numa < 0) goto nextmenu;
X
X how = TOGGLE;
X mark();
X last_how = how;
X cura++;
X goto same_prompt;
X
X case K_UNSELECT_ALL:
X for (cura = -firsta; cura < n_articles - firsta; cura++) {
X how = OFF;
X mark();
X }
X fl;
X cura = 0;
X goto same_prompt;
X
X case K_NEXT_LINE:
X if (numa < 0) goto nextmenu;
X
X cura++;
X how = TOGGLE;
X goto same_prompt;
X
X case K_PREV_LINE:
X if (numa < 0) goto nextmenu;
X
X if (--cura < 0) cura = numa;
X how = TOGGLE;
X goto same_prompt;
X
X case K_SELECT_SUBJECT:
X if (numa < 0) goto nextmenu;
X
X mark();
X
X while (firsta+cura > 0 && articles[firsta+cura]->flag & A_SAME)
X cura--;
X
X do {
X mark();
X cura++;
X if (firsta+cura >= n_articles) break;
X } while (articles[firsta+cura]->flag & A_SAME);
X
X how = TOGGLE;
X goto same_prompt;
X
X case K_SELECT_RANGE:
X if (numa < 0) goto nextmenu;
X
X if (last_k_cmd == K_ARTICLE_ID || last_k_cmd == K_SELECT) {
X how = last_how;
X cura--;
X if (cura < 0) cura = numa;
X } else
X how = articles[firsta+cura]->flag & A_SELECT ? OFF : ON;
X
X range_again:
X
X prompt("\1%select range\1 %c-", how == ON ? "S" : "Des", ident[cura]);
X
X k_cmd = get_k_cmd();
X if (k_cmd == K_SELECT_RANGE) {
X how = !how;
X goto range_again;
X }
X
X if (k_cmd != K_ARTICLE_ID) goto Prompt;
X
X if (last_k_cmd != K_ARTICLE_ID && last_k_cmd != K_SELECT)
X mark();
X
X if (article_id <= cura) {
X while (--cura >= article_id) mark();
X if (cura < 0) cura = 0;
X } else {
X while (++cura <= article_id) mark();
X if (cura > numa) cura = numa;
X }
X
X how = TOGGLE;
X goto Prompt;
X
X case K_AUTO_SELECT:
X do_auto_select();
X goto same_prompt;
X
X case K_NEXT_PAGE:
X if (nexta < n_articles) goto nextmenu;
X if (firsta == 0) goto same_prompt;
X
X seen_all++;
X nexta = 0;
X goto nextmenu;
X
X case K_PREV_PAGE:
X if (firsta == 0 && nexta == n_articles) goto same_prompt;
X
X nexta = (firsta > 0 ? firsta : n_articles) - maxa;
X if (nexta <= 1) nexta = 0;
X goto nextmenu;
X
X case K_FIRST_PAGE:
X if (firsta == 0) goto same_prompt;
X
X nexta = 0;
X goto nextmenu;
X
X case K_LAST_PAGE:
X if (nexta == n_articles) goto same_prompt;
X
X nexta = n_articles - maxa;
X if (nexta <= 1) nexta = 0;
X goto nextmenu;
X
X case K_PREVIEW:
X if (numa < 0) goto nextmenu;
X
X preview_other:
X
X prompt("\1Preview article\1");
X k_cmd = get_k_cmd();
X
X if (k_cmd != K_ARTICLE_ID) {
X if (k_cmd != K_PREVIEW)
X goto Prompt;
X article_id = cura;
X }
X
X temp = prompt_line;
X
X preview_next:
X ah = articles[firsta+article_id];
X cura = article_id + 1;
X was_selected = (ah->flag & A_SELECT);
X
X switch (more(ah, MM_PREVIEW, prompt_line)) {
X
X case MC_REDRAW:
X next_cura = cura;
X goto redraw;
X
X case MC_NO_REDRAW:
X break;
X
X case MC_QUIT:
X menu_return( ME_QUIT );
X
X case MC_NEXT: /* article not found -- preview next */
X if (prompt_line == temp)
X break; /* not redrawn -- return to menu instead */
X user_delay(1);
X /* FALL THRU */
X
X case MC_PREVIEW_NEXT:
X if (prompt_line < 0) { /* redrawn screen ! */
X if ((firsta + cura) >= n_articles) goto redraw;
X prompt_line = Lines;
X } else {
X if ((ah->flag & A_SELECT) && was_selected == 0) {
X cura--;
X ah->flag &= ~A_SELECT;
X how = ON;
X mark();
X cura++;
X }
X if (cura > numa) break;
X prompt_line = temp;
X }
X article_id = cura;
X goto preview_next;
X
X case MC_PREVIEW_OTHER:
X prompt_line = temp;
X raw();
X goto preview_other;
X
X default:
X break;
X }
X
X prompt_line = temp;
X goto build_prompt;
X
X case K_LAYOUT:
X if (++fmt_linenum > 3) fmt_linenum = 0;
X goto redraw;
X
X default:
X msg("Command %d not supported", k_cmd);
X goto same_prompt;
X }
X
X
X menu_exit:
X
X firsta = o_firsta;
X in_menu_mode = o_mode;
X menu_level--;
X
X no_raw();
X return menu_cmd;
X}
X
X
Xstatic show_articles()
X{
X register cur, next, mode;
X int cmd, prev = -1, again;
X
X do {
X again = 0;
X
X for (cur = 0; cur < n_articles; cur++) {
X if (articles[cur]->flag & A_SELECT) break;
X }
X
X while (cur < n_articles) {
X
X for (next = cur+1; next < n_articles; next++) {
X if (articles[next]->flag & A_SELECT) break;
X }
X
X articles[cur]->flag &= ~A_SELECT;
X
X show:
X mode = 0;
X if (prev >= 0) mode |= MM_PREVIOUS;
X if (next == n_articles) mode |= MM_LAST_ARTICLE;
X
X cmd = more(articles[cur], mode, 0);
X
X switch(cmd) {
X
X case MC_PREV:
X if (prev == next) break;
X
X next = cur; cur = prev; prev = next;
X goto show;
X
X case MC_NEXTSUBJ:
X for (next = cur+1; next < n_articles; next++) {
X if ((articles[next]->flag & A_SAME) == 0) break;
X articles[next]->flag &= ~A_SELECT;
X }
X for (; next < n_articles; next++) {
X if (articles[next]->flag & A_SELECT) break;
X }
X break;
X
X case MC_ALLSUBJ:
X for (next = cur+1; next < n_articles; next++) {
X if ((articles[next]->flag & A_SAME) == 0) break;
X articles[next]->flag |= A_SELECT;
X }
X for (next = cur+1; next < n_articles; next++)
X if (articles[next]->flag & A_SELECT) break;
X break;
X
X case MC_MENU:
X articles[cur]->flag |= A_SELECT;
X firsta = cur - 5;
X if (firsta < 0) firsta = 0;
X next_cura = cur - firsta;
X
X return SH_MENU;
X
X case MC_QUIT:
X return SH_QUIT;
X
X case MC_NEXT:
X if (articles[cur]->flag & A_SELECT) again++;
X break;
X
X case MC_NEXTGROUP:
X return SH_NEXT;
X
X case MC_READGROUP:
X return SH_READ;
X }
X
X prev = cur; cur = next;
X }
X
X if (again > 1)
X delayed_msg = "Showing this and the following articles again";
X else
X if (again == 1)
X delayed_msg = "Showing article again";
X
X } while (again);
X
X return prev < 0 ? SH_NO_SELECT : SH_READ;
X}
X
X/*
X * return article header for article on menu
X */
X
Xarticle_header *get_menu_article()
X{
X register article_header *ah;
X
X fputs(" from article: ", stdout); fl;
X
X if (get_k_cmd() == K_ARTICLE_ID) {
X ah = articles[firsta + article_id];
X if (ah->a_group) init_group(ah->a_group);
X return ah;
X }
X
X return NULL;
X}
X
X
Xstatic get_purpose(purpose)
Xchar *purpose;
X{
X#ifdef NNTP
X return; /* newsgroups file is not available */
X#else
X FILE *f;
X char line[256], group[80];
X register char *cp, *pp;
X register int len;
X extern char news_active[];
X
X strcpy(line, news_active);
X if ((cp = strrchr(line, '/')) == NULL) return;
X strcat(cp + 1, "newsgroups");
X
X if ((f = fopen(line, "r")) == NULL) return;
X
X sprintf(group, "%s\t", current_group->group_name);
X len = current_group->group_name_length + 1;
X
X while (fgets(line, 256, f) != NULL) {
X if (strncmp(line, group, len)) continue;
X cp = line + len;
X while (*cp && isspace(*cp)) cp++;
X for (pp = purpose, len = 76; --len >= 0 && *cp && *cp != NL; )
X *pp++ = *cp++;
X *pp = NUL;
X }
X
X fclose(f);
X#endif
X}
X
X/*
X * perform auto selections that are not already selected
X * if article is in range firsta..firsta+numa (incl) mark article
X */
X
Xstatic do_auto_select()
X{
X register int i;
X register article_header *ah, **ahp;
X int count = 0, o_cura;
X
X o_cura = cura;
X
X for (i = 0, ahp = articles; i < n_articles; i++, ahp++) {
X ah = *ahp;
X if (auto_select_article(ah)) {
X count++;
X if (ah->flag & A_SELECT) continue;
X if (firsta <= i && i <= (firsta+numa)) {
X cura = i - firsta;
X how = ON;
X mark();
X } else
X ah->flag |= A_SELECT;
X }
X }
X
X msg(count == 0 ? "No selections" : "Selected %d article%s",
X count, count > 1 ? "s" : "");
X cura = o_cura;
X}
X
X
X
X/*
X * read command from command line
X */
X
Xalt_command()
X{
X int ok_val, macro_cmd;
X char *cmd;
X extern char erase_key;
X extern int get_from_macro;
X extern int alt_completion();
X
X prompt(":");
X ok_val = AC_PROMPT;
X
X again:
X
X cmd = "?? ";
X cmd[1] = erase_key;
X
X cmd = get_s(NONE, NONE, cmd, alt_completion);
X if (cmd == NULL ||
X *cmd == NUL || *cmd == SP || *cmd == erase_key)
X return ok_val;
X
X macro_cmd = get_from_macro;
X
X if (*cmd == '?') {
X display_file("help.extended", CLEAR_DISPLAY);
X ok_val = AC_REDRAW;
X goto new_prompt;
X }
X
X ok_val = parse_command(cmd, ok_val, (FILE *)NULL);
X if (ok_val != AC_REDRAW || !delay_redraw) return ok_val;
X
X new_prompt:
X if (macro_cmd) return ok_val;
X
X prompt_line = -1;
X printf("\n\r:");
X fl;
X goto again;
X}
NO_NEWS_IS_GOOD_NEWS
chmod 0644 menu.c || echo "restore of menu.c fails"
set `wc -c menu.c`;Sum=$1
if test "$Sum" != "23564"
then echo original size 23564, current size $Sum;fi
echo "x - extracting menu.h (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > menu.h &&
X/* menu commands */
X
X#define ME_QUIT 0 /* quit nn */
X#define ME_NEXT 1 /* continue to next group */
X#define ME_READ 2 /* read this group, cont to next */
X#define ME_PREV 3 /* previous group */
X#define ME_NO_ARTICLES 4 /* no articles in group */
X#define ME_REDRAW 5 /* redraw screen after return */
X#define ME_NO_REDRAW 6 /* screen is not corrupted */
X
X/* show_articles commands */
X
X#define SH_QUIT 0 /* quit nn */
X#define SH_NEXT 1 /* goto next group, no read */
X#define SH_READ 2 /* articles has been read */
X#define SH_MENU 3 /* redraw menu */
X#define SH_NO_SELECT 4 /* no articles was selected */
X
X
X/* more commands */
X
X#define MC_QUIT 0 /* quit nn */
X#define MC_NEXT 1 /* next article */
X#define MC_MENU 2 /* return to menu */
X#define MC_PREV 3 /* previous article */
X#define MC_NEXTSUBJ 4 /* show next subject */
X#define MC_ALLSUBJ 5 /* show all with same subject */
X#define MC_NEXTGROUP 6 /* next group, no read */
X#define MC_READGROUP 7 /* next group, mark as read */
X#define MC_PREVIEW_NEXT 8 /* preview next article */
X#define MC_PREVIEW_OTHER 9 /* preview another article */
X#define MC_REDRAW 10 /* redraw screen after return */
X#define MC_NO_REDRAW 11 /* screen is not corrupted */
X
X/* more modes */
X
X#define MM_NORMAL 0 /* show article */
X#define MM_DIGEST 1 /* show full digest */
X#define MM_PREVIOUS 0x10 /* previous article exists */
X#define MM_LAST_ARTICLE 0x20 /* last article in group */
X#define MM_LAST_GROUP 0x40 /* last group */
X#define MM_PREVIEW 0x80 /* preview mode flag */
X
X/* alt_command return values */
X
X#define AC_QUIT 0 /* quit nn */
X#define AC_PROMPT 1 /* just redraw prompt line */
X#define AC_REDRAW 2 /* redraw screen */
X#define AC_REORDER 3 /* articles have been reordered */
X#define AC_HEADER 4 /* update header line + Prompt */
X#define AC_KEYCMD 5 /* alt_cmd_key contains command */
NO_NEWS_IS_GOOD_NEWS
chmod 0644 menu.h || echo "restore of menu.h fails"
set `wc -c menu.h`;Sum=$1
if test "$Sum" != "1853"
then echo original size 1853, current size $Sum;fi
echo "x - extracting mk_online_man (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > mk_online_man &&
X# convert a manual to a folder
X
Xsed -e 's/\\f[BPI]//g' \
X -e 's/\\-/-/g' \
X -e 's/\\&//' \
X -e '/^\.\\"/d' \
X -e '/^\.nf/d' \
X -e '/^\.fi/d' \
X -e 's/^\.[BI] //' "$@" |
Xawk '
XBEGIN {
X l=""
X o=""
X m=72
X a=0
X h=""
X}
X/^\.SH / {
X if (a) printf("%s\n\n", l)
X a++
X l=o=""
X z=u=0
X printf("From: %s\nSubject:", h);
X for (i = 2; i <= NF; i++) printf(" %s", $i);
X printf("\n\n");
X next
X}
X/^\.TH / {
X h=$2
X next
X}
X/^\.UC / {
X next
X}
X/^\.br/ {
X if (l != o) printf("%s\n", l)
X l=o
X z=u
X next
X}
X/^\.PP/ {
X if (l != o) printf("%s\n", l)
X printf("\n")
X l=" "
X z=3
X o=""
X u=0
X next
X}
X/^\.LP/ || /^\.sp/ {
X if (l != o) printf("%s\n", l)
X printf("\n")
X l=""
X o=""
X z=u=0
X next
X}
X/^\.TP/ {
X if (l != o) printf("%s\n", l)
X printf("\n")
X getline
X l=$0
X z=u=5
X o=" "
X if (length(l) >= 5) {
X printf("%s\n", l)
X l=o
X } else while (length(l) < 4) l=l " "
X next
X}
X{
X s=1
X p=" "
X q=1
X}
X/^[ ]/ {
X if (l != o) printf("%s\n",l)
X l=o " "
X z=u+5
X}
X/^\.[IB] / {
X s=2
X}
X/^\.[IB]R / {
X s=2
X p=""
X q=0
X}
X{
X r=" "
X while (s <= NF) {
X k=length($s)
X if ((z+k) > m) {
X printf("%s\n", l)
X l=o
X z=u
X }
X if (l != o)
X l=l r $s
X else
X l=l $s
X z=z + q + k
X r=p
X s++
X }
X}
XEND {
X if (l != o) printf("%s\n\n", l)
X}'
NO_NEWS_IS_GOOD_NEWS
chmod 0644 mk_online_man || echo "restore of mk_online_man fails"
set `wc -c mk_online_man`;Sum=$1
if test "$Sum" != "1198"
then echo original size 1198, current size $Sum;fi
echo "x - extracting more.c (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > more.c &&
X#include "config.h"
X#include "news.h"
X#include "term.h"
X#include "menu.h"
X#include "keymap.h"
X#include "regexp.h"
X
Xexport int monitor_mode = 0;
Xexport int show_article_date = 1;
Xexport int first_page_lines = 0;
Xexport int overlap = 2;
Xexport int mark_overlap = 0;
Xexport char *header_lines = NULL;
X
Ximport int preview_window;
Ximport int novice;
X
Ximport char *delayed_msg;
X
Xextern char *init_save();
X
Xstatic char rot13tab[128];
Xstatic int norot13 = 1, rot13;
Xstatic int compress_space;
X
Xstatic regexp *regular_expr = NULL;
X
X#define LINEMAX 5000 /* max no of lines backed up */
X
Xstatic struct header_def {
X char field;
X char *text;
X char **news;
X char **digest;
X} header_defs[] = {
X 'A', "Approved", &news.ng_appr, 0,
X 'B', "Distribution",&news.ng_dist, 0,
X 'D', "Date", &news.ng_date, &digest.dg_date,
X 'F', "From", &news.ng_from, &digest.dg_from,
X 'I', "Message-Id", &news.ng_ident, 0,
X 'K', "Keywords", &news.ng_keyw, 0,
X 'L', "Lines", &news.ng_xlines, 0,
X 'N', "Newsgroups", &news.ng_groups, 0,
X 'O', "Organization",&news.ng_org, 0,
X 'P', "Path", &news.ng_path, 0,
X 'R', "Reply-To", &news.ng_reply, 0,
X 'S', "Subject", &news.ng_subj, &digest.dg_subj,
X 'W', "Followup-To", &news.ng_follow, 0,
X 'X', "References", &news.ng_ref, 0,
X 0
X};
X
X
Xmore(ah, mode, screen_offset)
Xarticle_header *ah;
Xint mode, screen_offset;
X{
X register c, col, lno;
X register FILE *art;
X int more_cmd, eof, skip_spaces, has_space, window_lines;
X int form_feed, ignore_nl;
X off_t firstl, lastl;
X off_t linepos[LINEMAX];
X char linebuf[200], *lp;
X int linenum, maxline, topline, print_lines, lno1;
X int underline_line, fake_underline;
X int match_lines, match_redraw, match_topline, match_botline;
X int goto_line, prev_goto, stop_line, extra_lines;
X int in_digest = ah->flag & A_DIGEST;
X article_header digestah;
X char *fname, *hdrline;
X extern STANDOUT;
X char pr_fmt[60], send_date[40];
X int match_expr;
X char *match_start, *match_end;
X int open_modes, hdr_mode, o_mode;
X struct header_def *hdef;
X extern int alt_cmd_key, in_menu_mode, any_message;
X#ifdef RESIZING
X int entry_col = Columns;
X#endif
X extern char *pct();
X
X#define more_return(cmd) \
X { more_cmd = cmd; goto more_exit; }
X
X if (ah->a_group != NULL) init_group(ah->a_group);
X
X open_modes = SKIP_HEADER;
X if (show_article_date || header_lines) {
X open_modes |= FILL_NEWS_HEADER;
X if (header_lines == NULL)
X open_modes |= GET_DATE_ONLY;
X else
X open_modes |= GET_ALL_FIELDS;
X if (in_digest) open_modes |= FILL_DIGEST_HEADER;
X }
X
X /* temporary use of linepos array as header buffers... */
X
X art = open_news_article(ah, open_modes, (char *)&linepos[100], (char *)&linepos[LINEMAX/2]);
X
X if (art == NULL) {
X msg("Expired: \"%s: %-.50s\"", ah->sender, ah->subject);
X if ((mode & MM_PREVIEW) == 0) user_delay(1);
X return MC_NEXT;
X }
X
X o_mode = in_menu_mode;
X in_menu_mode = 0;
X
X if (screen_offset)
X if (preview_window < 1 && Lines - screen_offset < 6)
X screen_offset = 0;
X else {
X so_printxy(0, screen_offset++, "%s: %s ", ah->sender, ah->subject);
X if (!STANDOUT) screen_offset++;
X clrline();
X }
X
X if (show_article_date) {
X if (in_digest && digest.dg_date)
X strncpy(send_date, digest.dg_date, 40);
X else
X if (news.ng_date) {
X strncpy(send_date, news.ng_date, 40);
X } else
X send_date[0] = NUL;
X send_date[39] = NUL;
X if (lp = strrchr(send_date, ':')) *lp = NUL;
X }
X
X linepos[0] = ah->hpos;
X linepos[1] = firstl = ah->fpos;
X maxline = 1;
X topline = 1;
X hdrline = screen_offset == 0 ? header_lines : "";
X
X lastl = (ah->lpos - firstl + 99)/100;
X if (lastl == 0) lastl = 1; /* impossible ? */
X
X rot13 = 0;
X compress_space = 0;
X goto_line = -1, prev_goto = 1;
X match_lines = match_redraw = match_expr = 0;
X underline_line = -1;
X fake_underline = 0;
X
X stop_line = first_page_lines ? first_page_lines : -1;
X
X sprintf(pr_fmt,
X "\1\2-- %s%s %s-----%%s-----\1",
X (mode & MM_PREVIEW) ? "PREVIEW " : "",
X (mode & MM_DIGEST) ? "FULL DIGEST" :
X (mode & MM_LAST_ARTICLE) ? "LAST ARTICLE" : "ARTICLE",
X novice ? "-- help:? " : "");
X
X if (screen_offset) goto safe_redraw;
X
X redraw: /* redraw that will destroy whole screen */
X screen_offset = 0;
X
X safe_redraw: /* redraw of "more window" only */
X linenum = topline;
X
X next_page:
X no_raw();
X
X s_keyboard = 0;
X
X if (stop_line) {
X
X if (lno = screen_offset) {
X gotoxy(0, lno);
X clrpage(lno);
X } else
X clrdisp();
X
X print_header:
X if (hdrline == NULL || *hdrline == '*') {
X if (hdrline && *++hdrline == NUL) hdrline = NULL;
X
X if (linenum <= 1) {
X if (linenum == 0 || (mode & MM_DIGEST)) {
X if (screen_offset) {
X lno--;
X if (!STANDOUT) lno--;
X gotoxy(0, lno);
X clrpage(lno);
X }
X so_printxy(0, lno,
X "Newsgroup: %s, article: %ld%s",
X current_group->group_name,
X (long)(ah->a_number),
X ((mode & MM_DIGEST) || in_digest)
X ? " *DIGEST*" : "");
X/* fseek(art, linepos[0], 0); */
X
X lno++;
X if (!STANDOUT) lno++;
X } else {
X if (screen_offset == 0 && linenum == 1) {
X if (show_article_date) so_printxy(-1, 0, send_date);
X
X /* so_printxy will cut subject */
X so_printxy(0, lno, "%s: %s ", ah->sender, ah->subject);
X lno++;
X if (!STANDOUT) lno++;
X }
X }
X }
X }
X
X if (hdrline && screen_offset == 0) {
X
X hdr_mode = 0;
X while (*hdrline) {
X
X if (*hdrline == '*') goto print_header;
X
X if (*hdrline == '=') {
X hdr_mode = 1;
X hdrline++;
X continue;
X }
X if (*hdrline == '_') {
X hdr_mode = 2;
X hdrline++;
X continue;
X }
X for (hdef = header_defs; hdef->field; hdef++) {
X if (hdef->field != *hdrline) continue;
X if (in_digest) {
X if (hdef->digest == NULL) break;
X if ((lp = *(hdef->digest)) == NULL)
X break;
X } else
X if ((lp = *(hdef->news)) == NULL)
X break;
X gotoxy(0, lno++);
X c = strlen(hdef->text) + 2;
X col = c + strlen(lp);
X if (col > Columns) lp[Columns - c] = 0;
X printf("%s: ", hdef->text);
X switch (hdr_mode) {
X case 0:
X break;
X case 1:
X highlight(1);
X break;
X case 2:
X underline(1);
X break;
X }
X printf("%s", lp);
X switch (hdr_mode) {
X case 0:
X break;
X case 1:
X highlight(0);
X break;
X case 2:
X underline(0);
X break;
X }
X break;
X }
X hdr_mode = 0;
X hdrline++;
X }
X
X hdrline = NULL;
X putchar(NL);
X lno++;
X }
X
X lno1 = lno;
X topline = linenum;
X
X window_lines = Lines - lno - 2;
X print_lines = window_lines;
X
X ignore_nl = 1; /* ignore blank lines at top op screen */
X } else
X print_lines = extra_lines; /* LINT complaints here -- ignore */
X
X if (stop_line > 0) {
X if (print_lines > stop_line) {
X extra_lines = print_lines - stop_line;
X print_lines = stop_line;
X underline_line = -1;
X }
X stop_line = 0;
X } else
X stop_line = -1;
X
X next_line:
X
X if (linenum == LINEMAX) {
X /* THIS IS EXTREMELY DIRTY (like most quick hacks) */
X /* the following definitions assume that LINEMAX >> START+SIZE */
X#define HACK_START 1000 /* line numbers > START_POS are wrong */
X#define HACK_SIZE 1000 /* we simply delete HACK_SIZE lines */
X for (linenum = HACK_START; linenum < (LINEMAX-HACK_SIZE); linenum++)
X linepos[linenum] = linepos[linenum+HACK_SIZE];
X maxline = linenum - 1;
X if (goto_line > 0) goto_line -= HACK_SIZE;
X if (prev_goto > HACK_START)
X if (prev_goto > (HACK_START + HACK_SIZE))
X prev_goto -= HACK_SIZE;
X else
X prev_goto = HACK_START;
X }
X
X if (goto_line == linenum) {
X goto_line = -1;
X goto next_page;
X }
X
X eof = 0;
X
X if (linenum > maxline)
X linepos[++maxline] = ftell(art);
X else
X if (linenum > 0)
X fseek(art, linepos[linenum], 0);
X
X
X if (linepos[linenum] >= ah->lpos) {
X if (match_expr) {
X match_expr = 0;
X topline = match_topline; /* LINT complaints here -- ignore */
X linenum = match_botline; /* LINT complaints here -- ignore */
X fseek(art, linepos[linenum], 0);
X msg("Not found");
X goto Prompt;
X }
X eof++;
X if (goto_line > 0) {
X goto_line = -1;
X linenum -= window_lines/2;
X goto next_page;
X }
X goto Prompt;
X }
X
X if (linenum == 0) {
X if (ftell(art) >= linepos[1]) {
X linenum = 2; /* current line is 1st line ! */
X lno1 = lno;
X }
X } else
X linenum++;
X
X lp = linebuf;
X col = 0;
X form_feed = 0;
X
X next_char:
X
X c = getc(art);
X if (c == EOF) {
X eof++;
X if (lp == linebuf) goto Prompt;
X goto end_line;
X }
X
X if (c & 0200) {
X col += 4;
X if (col > Columns) { /* then there is no room for M-^X */
X ungetc(c, art);
X goto long_line;
X }
X c &= 0177;
X *lp++ = 'M';
X *lp++ = '-';
X if (c < SP) {
X *lp++ = '^';
X c += '@';
X } else
X col--;
X } else
X if (c < SP) {
X if (monitor_mode) {
X if (c == NL) {
X *lp++ = '$';
X goto end_line;
X }
X if (col + 2 > Columns) {
X *lp++ = '\\';
X ungetc(c, art);
X goto end_line;
X }
X *lp++ = '^';
X c += '@';
X col++;
X } else
X switch (c) {
X
X case '\f':
X if (lp == linebuf) {
X if (goto_line && lno == lno1) goto next_line;
X form_feed = 1;
X goto Prompt;
X }
X form_feed = 1;
X goto end_line;
X
X case CR:
X if (lp == linebuf || ignore_nl) goto next_char;
X ignore_nl = 1;
X goto end_line;
X
X case NL:
X if (ignore_nl) {
X ignore_nl = 0;
X if (lp == linebuf) {
X if (lno == lno1) {
X ignore_nl = 1;
X goto next_line;
X }
X goto next_char;
X }
X }
X goto end_line;
X
X case BS:
X if (col) {
X lp--;
X col--;
X }
X goto next_char;
X
X case TAB:
X if (col + 8 - (col & 07) >= Columns)
X goto long_line;
X
X do {
X *lp++ = SP;
X col++;
X } while (col & 07);
X goto next_char;
X
X default:
X if (col + 2 > Columns) {
X ungetc(c, art);
X goto long_line;
X }
X *lp++ = '^';
X c += '@';
X col++;
X break;
X }
X }
X
X *lp++ = c;
X col++;
X ignore_nl = 0;
X
X if (col < Columns) goto next_char;
X
Xlong_line:
X ignore_nl = 1;
X
X end_line:
X /* if we are seaching for a specific line, repeat until it is found */
X if (goto_line >= linenum) goto next_line;
X
X *lp++ = NUL;
X
X if (match_expr) {
X if (!regexec(regular_expr, linebuf))
X goto next_line;
X match_expr = 0;
NO_NEWS_IS_GOOD_NEWS
echo "End of part 7"
echo "File more.c is continued in part 8"
echo "8" > s2_seq_.tmp
exit 0
---
Kim F. Storm storm@texas.dk Tel +45 429 174 00
Texas Instruments, Marielundvej 46E, DK-2730 Herlev, Denmark
No news is good news, but nn is better!