Subject:  v22i041:  NN Newsreader, release 6.4, Part06/21
Newsgroups: comp.sources.unix
Approved: rsalz@uunet.UU.NET
X-Checksum-Snefru: 424bcc2d 36950156 9e5dda93 f728ae0b

Submitted-by: "Kim F. Storm" <storm@texas.dk>
Posting-number: Volume 22, Issue 41
Archive-name: nn6.4/part06

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents:  conf/s-hpux.h keymap.c menu.c
# Wrapped by storm@texas.dk on Sun May  6 18:19:28 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 6 (of 22)."'
if test -f 'conf/s-hpux.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'conf/s-hpux.h'\"
else
  echo shar: Extracting \"'conf/s-hpux.h'\" \(510 characters\)
  sed "s/^X//" >'conf/s-hpux.h' <<'END_OF_FILE'
X/*
X *	This version is for Hewlett-Packard HP-UX
X */
X
X#define NO_DIRENT_H
X#include "s-sys5.h"
X
X#undef	SIGNAL_HANDLERS_ARE_VOID	/* */
X
X/*
X *	Define if your system provides the "directory(3X)" access routines
X *
X *	If true, include the header file(s) required by the package below
X *	(remember that <sys/types.h> or equivalent is included above)
X *	Also typedef Direntry to the proper struct type.
X */
X
X#define	HAVE_DIRECTORY			/* */
X
X#include <ndir.h>			/* HP-UX */
X
Xtypedef struct direct Direntry;		/* HP-UX */
END_OF_FILE
  if test 510 -ne `wc -c <'conf/s-hpux.h'`; then
    echo shar: \"'conf/s-hpux.h'\" unpacked with wrong size!
  fi
  # end of 'conf/s-hpux.h'
fi
if test -f 'keymap.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'keymap.c'\"
else
  echo shar: Extracting \"'keymap.c'\" \(17311 characters\)
  sed "s/^X//" >'keymap.c' <<'END_OF_FILE'
X/*
X *	(c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
X *
X *	Keyboard (re)mapping
X */
X
X#include "config.h"
X#include "keymap.h"
X#include "term.h"
X
X
X/*
X * standard keyboard mapping for more()
X *
X *	redraw			^L, ^R
X *	continue		space
X *	repeat message		^P
X *	help			?
X *	shell escape		!
X *	version			V
X *	extended command	:
X *	quit			Q
X *
X *	save			S, O
X *	save, no header		W
X *	reply			R
X *	follow up		F
X *	mail (forward)		M
X *	cancel			C
X *	unsubscribe		U
X *	group overview		Y
X *	print article		P
X *	kill handling		K
X *
X *	update, goto next group	X
X *	no update, next group	q, Z
X *	return to menu		=
X *	prev article		p
X *	goto group		G
X *
X *	line forward		CR/NL
X *	half page forward	d/^D
X *	half page back		u/^U
X *	full page back		BS, DEL, (up arrow)
X *	goto line		g
X *	goto match		/
X *	next match		.
X *
X *	select subject		N, *
X *
X *	header			h
X *	digest header		H
X *	top			t
X *	last page		$
X *	leave article		l
X *	leave article to next	L
X *	next article		n
X *	kill subject		k
X *
X *	rot13			D
X *	compress		c
X */
X
Xexport int more_key_map[KEY_MAP_SIZE] = {
X
X/* NUL ^@ */	K_UNBOUND,
X/* SOH ^A */	K_UNBOUND,
X/* STX ^B */	K_UNBOUND,
X/* ETX ^C */	K_UNBOUND,
X/* EOT ^D */		K_NEXT_HALF_PAGE,
X/* ENQ ^E */	K_UNBOUND,
X/* ACK ^F */	K_UNBOUND,
X/* BEL ^G */		K_INVALID,
X/* BS  ^H */		K_PREV_PAGE,
X/* TAB ^I */		K_SKIP_LINES,
X/* NL  ^J */		K_NEXT_LINE,
X/* VT  ^K */	K_UNBOUND,
X/* FF  ^L */		K_REDRAW,
X/* CR  ^M */		K_NEXT_LINE,
X/* SO  ^N */	K_UNBOUND,
X/* SI  ^O */	K_UNBOUND,
X/* DLE ^P */		K_LAST_MESSAGE,
X/* DC1 ^Q */	K_UNBOUND,
X/* DC2 ^R */		K_REDRAW,
X/* DC3 ^S */	K_UNBOUND,
X/* DC4 ^T */	K_UNBOUND,
X/* NAK ^U */		K_PREV_HALF_PAGE,
X/* SYN ^V */		K_NEXT_PAGE,
X/* ETB ^W */	K_UNBOUND,
X/* CAN ^X */	K_UNBOUND,
X/* EM  ^Y */	K_UNBOUND,
X/* SUB ^Z */	K_UNBOUND,
X/* ESC ^[ */	K_UNBOUND,
X/* FS  ^\ */	K_UNBOUND,
X/* GS  ^] */	K_UNBOUND,
X/* RS  ^^ */	K_UNBOUND,
X/* US  ^_ */	K_UNBOUND,
X/* SP  */		K_CONTINUE,
X/* !   */		K_SHELL,
X/* "   */	K_UNBOUND,
X/* #   */	K_UNBOUND,
X/* $   */		K_LAST_PAGE,
X/* %   */		K_PREVIEW,
X/* &   */	K_UNBOUND,
X/* '   */	K_UNBOUND,
X/* (   */	K_UNBOUND,
X/* )   */	K_UNBOUND,
X/* *   */		K_SELECT_SUBJECT,
X/* +   */	K_UNBOUND,
X/* ,   */	K_UNBOUND,
X/* -   */	K_UNBOUND,
X/* .   */		K_NEXT_MATCH,
X/* /   */		K_GOTO_MATCH,
X/* 0   */	K_UNBOUND,
X/* 1   */	K_UNBOUND,
X/* 2   */	K_UNBOUND,
X/* 3   */	K_UNBOUND,
X/* 4   */	K_UNBOUND,
X/* 5   */	K_UNBOUND,
X/* 6   */	K_UNBOUND,
X/* 7   */	K_UNBOUND,
X/* 8   */	K_UNBOUND,
X/* 9   */	K_UNBOUND,
X/* :   */	 	K_EXTENDED_CMD,
X/* ;   */	K_UNBOUND,
X/* <   */	K_UNBOUND,
X/* =   */		K_BACK_TO_MENU,
X/* >   */	K_UNBOUND,
X/* ?   */		K_HELP,
X/* @   */	K_UNBOUND,
X/* A   */	K_UNBOUND,
X/* B   */	K_UNBOUND,
X/* C   */		K_CANCEL,
X/* D   */		K_ROT13,
X/* E   */	K_UNBOUND,
X/* F   */		K_FOLLOW_UP,
X/* G   */		K_GOTO_GROUP,
X/* H   */		K_FULL_DIGEST,
X/* I   */	K_UNBOUND,
X/* J   */	K_UNBOUND,
X/* K   */		K_KILL_HANDLING,
X/* L   */		K_LEAVE_NEXT,
X/* M   */		K_MAIL_OR_FORWARD,
X/* N   */		K_NEXT_GROUP_NO_UPDATE,
X/* O   */		K_SAVE_SHORT_HEADER,
X/* P   */		K_PRINT,
X/* Q   */	 	K_QUIT,
X/* R   */		K_REPLY,
X/* S   */		K_SAVE_FULL_HEADER,
X/* T   */	K_UNBOUND,
X/* U   */		K_UNSUBSCRIBE,
X/* V   */	 	K_VERSION,
X/* W   */		K_SAVE_NO_HEADER,
X/* X   */		K_READ_GROUP_UPDATE,
X/* Y   */		K_GROUP_OVERVIEW,
X/* Z   */		K_BACK_TO_MENU,
X/* [   */	K_UNBOUND,
X/* \   */	K_UNBOUND,
X/* ]   */	K_UNBOUND,
X/* ^   */		K_FIRST_PAGE,
X/* _   */	K_UNBOUND,
X/* `   */	K_UNBOUND,
X/* a   */		K_FORW_ARTICLE,
X/* b   */		K_BACK_ARTICLE,
X/* c   */		K_COMPRESS,
X/* d   */		K_NEXT_HALF_PAGE,
X/* e   */	K_UNBOUND,
X/* f   */		K_FOLLOW_UP,
X/* g   */		K_GOTO_LINE,
X/* h   */		K_HEADER_PAGE,
X/* i   */	K_UNBOUND,
X/* j   */	K_UNBOUND,
X/* k   */		K_NEXT_SUBJECT,
X/* l   */		K_LEAVE_ARTICLE,
X/* m   */		K_MAIL_OR_FORWARD,
X/* n   */		K_NEXT_ARTICLE,
X/* o   */		K_SAVE_SHORT_HEADER,
X/* p   */		K_PREVIOUS /* article */,
X/* q   */		K_NEXT_GROUP_NO_UPDATE,
X/* r   */		K_REPLY,
X/* s   */		K_SAVE_FULL_HEADER,
X/* t   */		K_FIRST_PAGE,
X/* u   */		K_PREV_HALF_PAGE,
X/* v   */	K_UNBOUND,
X/* w   */		K_SAVE_NO_HEADER,
X/* x   */	K_UNBOUND,
X/* y   */	K_UNBOUND,
X/* z   */	K_UNBOUND,
X/* {   */	K_UNBOUND,
X/* |   */	K_UNBOUND,
X/* }   */	K_UNBOUND,
X/* ~   */	K_UNBOUND,
X/* DEL */		K_PREV_PAGE,
X/* 200 */	K_UNBOUND,
X/* up  */		K_PREV_PAGE,
X/* down */		K_NEXT_PAGE,
X/* left */	K_UNBOUND,
X/* right */	K_UNBOUND,
X/* #0  */	K_UNBOUND,
X/* #1  */	K_UNBOUND,
X/* #2  */	K_UNBOUND,
X/* #3  */	K_UNBOUND,
X/* #4  */	K_UNBOUND,
X/* #5  */	K_UNBOUND,
X/* #6  */	K_UNBOUND,
X/* #7  */	K_UNBOUND,
X/* #8  */	K_UNBOUND,
X/* #9  */	K_UNBOUND
X};
X
X
X
X/*
X * standard keyboard mappings for menu()
X *
X *	illegal command
X *	redraw			^L, ^R
X *	continue		space
X *	continue no mark	return, newline
X *	repeat message		^P
X *	help			?
X *	shell escape		!
X *	version			V
X *	alternative commands	:
X *	quit			Q
X *
X *	save			S, O
X *	save, no header		W
X *	reply			R
X *	follow up		F
X *	mail (forward)		M
X *	cancel			C
X *	unsubscribe		U
X *	group overview		Y
X *	kill handling		K
X *	junk articles		J
X *
X *	read, then next		X
X *	read, then same		Z
X *	no update, next		N
X *	prev group		P
X *	goto group		G
X *	advance group		A
X *	back group		B
X *
X *	article identifier	a-z 0-9
X *	inverse			@
X *	select current, next	.
X *	next			, (down arrow)
X *	prev			/ (up arrow)
X *	select subject		*
X *	range			-
X *	auto select 		+
X *
X *	next page		>
X *	prev page		<
X *	first page		^
X *	last page		$
X *
X *	pre-view article	%
X *
X *	layout			L
X */
X
X
Xexport int menu_key_map[KEY_MAP_SIZE] = {
X
X/* NUL ^@ */	K_UNBOUND,
X/* SOH ^A */	K_UNBOUND,
X/* STX ^B */	K_UNBOUND,
X/* ETX ^C */	K_UNBOUND,
X/* EOT ^D */	K_UNBOUND,
X/* ENQ ^E */	K_UNBOUND,
X/* ACK ^F */	K_UNBOUND,
X/* BEL ^G */		K_INVALID,
X/* BS  ^H */		K_PREV_LINE,
X/* TAB ^I */	K_UNBOUND,
X/* NL  ^J */		K_CONTINUE_NO_MARK,
X/* VT  ^K */	K_UNBOUND,
X/* FF  ^L */		K_REDRAW,
X/* CR  ^M */		K_CONTINUE_NO_MARK,
X/* SO  ^N */	K_UNBOUND,
X/* SI  ^O */	K_UNBOUND,
X/* DLE ^P */		K_LAST_MESSAGE,
X/* DC1 ^Q */	K_UNBOUND,
X/* DC2 ^R */		K_REDRAW,
X/* DC3 ^S */	K_UNBOUND,
X/* DC4 ^T */	K_UNBOUND,
X/* NAK ^U */	K_UNBOUND,
X/* SYN ^V */		K_NEXT_PAGE,
X/* ETB ^W */	K_UNBOUND,
X/* CAN ^X */	K_UNBOUND,
X/* EM  ^Y */	K_UNBOUND,
X/* SUB ^Z */	K_UNBOUND,
X/* ESC ^[ */	K_UNBOUND,
X/* FS  ^\ */	K_UNBOUND,
X/* GS  ^] */	K_UNBOUND,
X/* RS  ^^ */	K_UNBOUND,
X/* US  ^_ */	K_UNBOUND,
X/* SP  */		K_CONTINUE,
X/* !   */		K_SHELL,
X/* "   */		K_LAYOUT,
X/* #   */	K_UNBOUND,
X/* $   */		K_LAST_PAGE,
X/* %   */		K_PREVIEW,
X/* &   */	K_UNBOUND,
X/* '   */	K_UNBOUND,
X/* (   */	K_UNBOUND,
X/* )   */	K_UNBOUND,
X/* *   */		K_SELECT_SUBJECT,
X/* +   */		K_AUTO_SELECT,
X/* ,   */		K_NEXT_LINE,
X/* -   */		K_SELECT_RANGE,
X/* .   */		K_SELECT,
X/* /   */		K_PREV_LINE,
X/* 0   */	K_ARTICLE_ID + 26,
X/* 1   */	K_ARTICLE_ID + 27,
X/* 2   */	K_ARTICLE_ID + 28,
X/* 3   */	K_ARTICLE_ID + 29,
X/* 4   */	K_ARTICLE_ID + 30,
X/* 5   */	K_ARTICLE_ID + 31,
X/* 6   */	K_ARTICLE_ID + 32,
X/* 7   */	K_ARTICLE_ID + 33,
X/* 8   */	K_ARTICLE_ID + 34,
X/* 9   */	K_ARTICLE_ID + 35,
X/* :   */		K_EXTENDED_CMD,
X/* ;   */	K_UNBOUND,
X/* <   */		K_PREV_PAGE,
X/* =   */		K_GOTO_MATCH,
X/* >   */		K_NEXT_PAGE,
X/* ?   */		K_HELP,
X/* @   */		K_SELECT_INVERT,
X/* A   */		K_ADVANCE_GROUP,
X/* B   */		K_BACK_GROUP,
X/* C   */		K_CANCEL,
X/* D   */	K_UNBOUND,
X/* E   */	K_UNBOUND,
X/* F   */		K_FOLLOW_UP,
X/* G   */		K_GOTO_GROUP,
X/* H   */	K_UNBOUND,
X/* I   */	K_UNBOUND,
X/* J   */		K_JUNK_ARTICLES,
X/* K   */		K_KILL_HANDLING,
X/* L   */		K_LEAVE_NEXT,
X/* M   */		K_MAIL_OR_FORWARD,
X/* N   */		K_NEXT_GROUP_NO_UPDATE,
X/* O   */		K_SAVE_SHORT_HEADER,
X/* P   */		K_PREVIOUS /* group */,
X/* Q   */		K_QUIT,
X/* R   */		K_REPLY,
X/* S   */		K_SAVE_FULL_HEADER,
X/* T   */	K_UNBOUND,
X/* U   */		K_UNSUBSCRIBE,
X/* V   */		K_VERSION,
X/* W   */		K_SAVE_NO_HEADER,
X/* X   */		K_READ_GROUP_UPDATE,
X/* Y   */		K_GROUP_OVERVIEW,
X/* Z   */		K_READ_GROUP_THEN_SAME,
X/* [   */	K_UNBOUND,
X/* \   */	K_UNBOUND,
X/* ]   */	K_UNBOUND,
X/* ^   */		K_FIRST_PAGE,
X/* _   */	K_UNBOUND,
X/* `   */	K_UNBOUND,
X/* a   */	K_ARTICLE_ID +  0,
X/* b   */	K_ARTICLE_ID +  1,
X/* c   */	K_ARTICLE_ID +  2,
X/* d   */	K_ARTICLE_ID +  3,
X/* e   */	K_ARTICLE_ID +  4,
X/* f   */	K_ARTICLE_ID +  5,
X/* g   */	K_ARTICLE_ID +  6,
X/* h   */	K_ARTICLE_ID +  7,
X/* i   */	K_ARTICLE_ID +  8,
X/* j   */	K_ARTICLE_ID +  9,
X/* k   */	K_ARTICLE_ID + 10,
X/* l   */	K_ARTICLE_ID + 11,
X/* m   */	K_ARTICLE_ID + 12,
X/* n   */	K_ARTICLE_ID + 13,
X/* o   */	K_ARTICLE_ID + 14,
X/* p   */	K_ARTICLE_ID + 15,
X/* q   */	K_ARTICLE_ID + 16,
X/* r   */	K_ARTICLE_ID + 17,
X/* s   */	K_ARTICLE_ID + 18,
X/* t   */	K_ARTICLE_ID + 19,
X/* u   */	K_ARTICLE_ID + 20,
X/* v   */	K_ARTICLE_ID + 21,
X/* w   */	K_ARTICLE_ID + 22,
X/* x   */	K_ARTICLE_ID + 23,
X/* y   */	K_ARTICLE_ID + 24,
X/* z   */	K_ARTICLE_ID + 25,
X/* {   */	K_UNBOUND,
X/* |   */	K_UNBOUND,
X/* }   */	K_UNBOUND,
X/* ~   */		K_UNSELECT_ALL,
X/* DEL */		K_PREV_LINE,
X/* 200 */	K_UNBOUND,
X/* up  */		K_PREV_LINE,
X/* down */		K_NEXT_LINE,
X/* left */	K_UNBOUND,
X/* right */	K_UNBOUND,
X/* #0  */	K_UNBOUND,
X/* #1  */	K_UNBOUND,
X/* #2  */	K_UNBOUND,
X/* #3  */	K_UNBOUND,
X/* #4  */	K_UNBOUND,
X/* #5  */	K_UNBOUND,
X/* #6  */	K_UNBOUND,
X/* #7  */	K_UNBOUND,
X/* #8  */	K_UNBOUND,
X/* #9  */	K_UNBOUND
X};
X
X
X
Xstatic struct command_name_map {
X    char *	cmd_name;
X    int   	cmd_code;
X    int	  	cmd_restriction;
X} command_name_map[] = {
X
X    "advance-article",		K_FORW_ARTICLE,		K_ONLY_MORE,
X    "advance-group",		K_ADVANCE_GROUP,	0,
X    "article",			K_ARTICLE_ID,		K_ONLY_MENU,
X    "as",			K_EQUAL_KEY,		0,
X
X    "back-article",		K_BACK_ARTICLE,		K_ONLY_MORE,
X    "back-group",		K_BACK_GROUP,		0,
X
X    "cancel",			K_CANCEL,		0,
X    "command",			K_EXTENDED_CMD,		0,
X    "compress",			K_COMPRESS,		K_ONLY_MORE,
X    "continue",			K_CONTINUE,		0,
X    "continue-no-mark",		K_CONTINUE_NO_MARK,	K_ONLY_MENU,
X
X    "decode",			K_UUDECODE,		0,
X
X    "find",			K_GOTO_MATCH,		0,
X    "find-next",		K_NEXT_MATCH,		K_ONLY_MORE,
X    "follow",			K_FOLLOW_UP,		0,
X    "full-digest",		K_FULL_DIGEST,		K_ONLY_MORE,
X
X    "goto-group",		K_GOTO_GROUP,		0,
X    "goto-menu",		K_BACK_TO_MENU,		K_ONLY_MORE,
X
X    "help",			K_HELP,			0,
X
X    "junk-articles",		K_JUNK_ARTICLES,	K_ONLY_MENU,
X
X    "kill-select",		K_KILL_HANDLING,	0,
X
X    "layout",			K_LAYOUT,		K_ONLY_MENU,
X    "leave-article",		K_LEAVE_ARTICLE,	K_ONLY_MORE,
X    "leave-next",		K_LEAVE_NEXT,		K_ONLY_MORE,
X    "line+1",			K_NEXT_LINE,		0,
X    "line-1",			K_PREV_LINE,		0,
X    "line=@",			K_GOTO_LINE,		K_ONLY_MORE,
X
X    "macro",			K_MACRO,		0,
X    "mail",			K_MAIL_OR_FORWARD,	0,
X    "message",			K_LAST_MESSAGE,		0,
X
X    "next-article",		K_NEXT_ARTICLE,		K_ONLY_MORE,
X    "next-group",		K_NEXT_GROUP_NO_UPDATE,	0,
X    "next-subject",		K_NEXT_SUBJECT,		K_ONLY_MORE,
X    "nil",			K_UNBOUND,		0,
X
X    "overview",			K_GROUP_OVERVIEW,	0,
X
X    "page+1",			K_NEXT_PAGE,		0,
X    "page+1/2",			K_NEXT_HALF_PAGE,	K_ONLY_MORE,
X    "page-1",			K_PREV_PAGE,		0,
X    "page-1/2",			K_PREV_HALF_PAGE,	K_ONLY_MORE,
X    "page=$",			K_LAST_PAGE,		0,
X    "page=0",			K_HEADER_PAGE,		0,
X    "page=1",			K_FIRST_PAGE,		0,
X    "page=@",			K_GOTO_PAGE,		K_ONLY_MORE,
X
X    "patch",			K_PATCH,		0,
X    "post",			K_POST,			0,
X    "preview",			K_PREVIEW,		0,
X    "previous",			K_PREVIOUS,		0,
X    "print",			K_PRINT,		0,
X
X    "quit",			K_QUIT,			0,
X
X    "read-return",		K_READ_GROUP_THEN_SAME,	K_ONLY_MENU,
X    "read-skip",		K_READ_GROUP_UPDATE,	0,
X    "redraw",			K_REDRAW,		0,
X    "reply",			K_REPLY,		0,
X    "rot13",			K_ROT13,		K_ONLY_MORE,
X
X    "save-body",		K_SAVE_NO_HEADER,	0,
X    "save-full",		K_SAVE_FULL_HEADER,	0,
X    "save-short",		K_SAVE_SHORT_HEADER,	0,
X    "select",			K_SELECT,		K_ONLY_MENU,
X    "select-auto",		K_AUTO_SELECT,		K_ONLY_MENU,
X    "select-invert",		K_SELECT_INVERT,	K_ONLY_MENU,
X    "select-range",		K_SELECT_RANGE,		K_ONLY_MENU,
X    "select-subject",		K_SELECT_SUBJECT,	0,
X    "shell",			K_SHELL,		0,
X    "skip-lines",		K_SKIP_LINES,		0,
X
X    "unselect-all",		K_UNSELECT_ALL,		K_ONLY_MENU,
X    "unshar",			K_UNSHAR,		0,
X    "unsub",			K_UNSUBSCRIBE,		0,
X
X    "version",			K_VERSION,		0,
X
X    (char *)NULL,		0,			0
X};
X
Xstatic int name_map_size;
Xstatic int max_cmd_name_length = 14;	/* recalculate if table is changed */
X
Xexport key_type global_key_map[KEY_MAP_SIZE];
X
X
Xinit_key_map()
X{
X    register int c;
X    register struct command_name_map *cnmp;
X
X    for (c = 0; c < KEY_MAP_SIZE; c++) global_key_map[c] = c;
X
X    for (cnmp = command_name_map; cnmp->cmd_name; cnmp++);
X    name_map_size = cnmp - command_name_map;
X}
X
X
Xlookup_command(command, restriction)
Xchar *command;
Xint restriction;
X{
X    register struct command_name_map *cnmp;
X    register i, j, k, t;
X
X    i = 0; j = name_map_size - 1;
X
X    while (i <= j) {
X	k = (i + j) / 2;
X	cnmp = &command_name_map[k];
X
X	if ( (t=strcmp(command, cnmp->cmd_name)) > 0)
X	    i = k+1;
X	else
X	if (t < 0)
X	    j = k-1;
X	else {
X	    if (cnmp->cmd_restriction == 0
X		|| (cnmp->cmd_restriction & restriction))
X		return cnmp->cmd_code;
X	    break;
X	}
X    }
X
X    return K_INVALID;
X}
X
X
Xcmd_completion(path, index)
Xchar *path;
Xint index;
X{
X    static char *head, *tail = NULL;
X    static int len;
X    static struct command_name_map *cmd, *help_cmd;
X
X    if (index < 0) return 0;
X
X    if (path) {
X	head = path;
X	tail = path + index;
X	while (*head && isspace(*head)) head++;
X	help_cmd = cmd = command_name_map;
X	len = tail - head;
X
X	return 1;
X    }
X
X    if (index) {
X	list_completion((char *)NULL);
X
X	if (help_cmd->cmd_name == NULL)
X	    help_cmd = command_name_map;
X
X	for (;help_cmd->cmd_name; help_cmd++) {
X	    index = strncmp(help_cmd->cmd_name, head, len);
X	    if (index < 0) continue;
X	    if (index > 0) {
X		help_cmd = command_name_map;
X		break;
X	    }
X	    if (list_completion(help_cmd->cmd_name) == 0) break;
X	}
X	fl;
X	return 1;
X    }
X
X    for (; cmd->cmd_name; cmd++) {
X	if (len == 0)
X	    index = 0;
X	else
X	    index = strncmp(cmd->cmd_name, head, len);
X	if (index < 0) continue;
X	if (index > 0) break;
X	if (cmd->cmd_code == K_MACRO ||
X	    cmd->cmd_code == K_ARTICLE_ID ||
X	    cmd->cmd_code == K_EQUAL_KEY)
X	    sprintf(tail, "%s ", cmd->cmd_name + len);
X	else
X	    strcpy(tail, cmd->cmd_name + len);
X	cmd++;
X	return 1;
X    }
X    return 0;
X}
X
X
Xchar *command_name(cmd)
Xint cmd;
X{
X    register struct command_name_map *cnmp;
X
X    cmd &= ~GETC_COMMAND;
X
X    for (cnmp = command_name_map; cnmp->cmd_name; cnmp++)
X	if (cnmp->cmd_code == cmd) return cnmp->cmd_name;
X
X    return "unknown";
X}
X
X
X/*
X * convert key name into ascii code
X *
X *	key names are:
X *		c	character c
X *		^C	control-C
X *		0xNN	hex value (0..0x7f)
X *		0NNN	octal value (0..0177)
X *		NNN	decimal value (0..127)
X *		up, down, left, rigth	arrow keys
X *		#0..#9			function keys (initially undefined)
X */
X
Xkey_type parse_key(str)
Xchar *str;
X{
X    int x;
X
X    if (str[1] == NUL)
X	return str[0] & 0177;
X
X    if (str[0] == '^')
X	if (str[1] == '?')
X	    return 0177;
X	else
X	    return CONTROL_(str[1]);
X
X    if (isdigit(str[0])) {
X	if (str[0] == '0')
X	    if (str[1] == 'x')
X		sscanf(str+2, "%x", &x);
X	    else
X		sscanf(str+1, "%o", &x);
X	else
X	    sscanf(str, "%d", &x);
X
X	return x & 0177;
X    }
X
X    if (str[0] == '#' && isdigit(str[1]))
X	return K_function(str[1] - '0');
X
X    if (strcmp(str, "up") == 0)
X	return K_up_arrow;
X
X    if (strcmp(str, "down") == 0)
X	return K_down_arrow;
X
X    if (strcmp(str, "left") == 0)
X	return K_left_arrow;
X
X    if (strcmp(str, "right") == 0)
X	return K_right_arrow;
X
X    init_message("unknown key: %s", str);
X
X    return 0200;
X}
X
Xchar *key_name(c)
Xkey_type c;
X{
X    static char buf[3];
X
X    if (c & 0200) {
X	switch (c) {
X	 case K_up_arrow:
X	    return "up";
X	 case K_down_arrow:
X	    return "down";
X	 case K_left_arrow:
X	    return "left";
X	 case K_right_arrow:
X	    return "right";
X	 default:
X	    buf[0] = '#';
X	    buf[1] = (c - K_function(0)) + '0';
X	    buf[2] = NUL;
X	    goto out;
X	}
X    }
X
X    if (c < SP) {
X	buf[0] = '^';
X	buf[1] = c + '@';
X	buf[2] = NUL;
X	goto out;
X    }
X
X    if (c == 0177) {
X	strcpy(buf, "^?");
X	goto out;
X    }
X
X    buf[0] = c;
X    buf[1] = NUL;
X
X out:
X    return buf;
X}
X
X
Xdump_global_map()
X{
X    register key_type c;
X
X    clrdisp();
X    so_printf("\1REMAPPED KEYS\1\n\n");
X    pg_init(2, 4);
X
X    for (c = 0; c < KEY_MAP_SIZE; c++)
X	if (c != global_key_map[c]) {
X	    if (pg_next() < 0) break;
X	    printf("%s", key_name(c));
X	    pg_indent(6);
X	    printf("-> %s", key_name(global_key_map[c]));
X	}
X
X    pg_end();
X}
X
X
Xdump_key_map(map, where, restriction)
Xint map[];
Xchar *where;
Xint restriction;
X{
X    register struct command_name_map *cnmp;
X    register key_type c;
X    register int code, first_prt;
X    
X    clrdisp();
X    so_printf("\1KEY BINDINGS (%s)\1\n\n", where);
X
X    if (restriction == K_ONLY_MENU) {
X	printf("\rarticle:  ");
X	for (c = 0; c < KEY_MAP_SIZE; c++)
X	    if (map[c] & K_ARTICLE_ID) printf("%s", key_name(c));
X    }
X
X    pg_init(4, 2);
X
X    for (cnmp = command_name_map; cnmp->cmd_name; cnmp++) {
X	if (cnmp->cmd_restriction && cnmp->cmd_restriction != restriction)
X	    continue;
X	if (cnmp->cmd_code == K_UNBOUND) continue;
X	if (cnmp->cmd_code == K_MACRO) continue;
X
X	code = cnmp->cmd_code;
X	first_prt = 1;
X
X	for (c = 0; c < KEY_MAP_SIZE; c++)
X	    if (map[c] == code) {
X		if (first_prt) {
X		    if (pg_next() < 0) goto out;
X		    fputs(cnmp->cmd_name, stdout);
X		    pg_indent(max_cmd_name_length);
X		    first_prt = 0;
X		}
X		printf(" %s", key_name(c));
X	    }
X    }
X
X    for (c = 0; c < KEY_MAP_SIZE; c++)
X	if (map[c] & K_MACRO) {
X	    if (pg_next() < 0) goto out;
X	    printf("macro %d: %s", (map[c] & ~K_MACRO), key_name(c));
X	}
X
X out:
X    pg_end();
X}
END_OF_FILE
  if test 17311 -ne `wc -c <'keymap.c'`; then
    echo shar: \"'keymap.c'\" unpacked with wrong size!
  fi
  # end of 'keymap.c'
fi
if test -f 'menu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'menu.c'\"
else
  echo shar: Extracting \"'menu.c'\" \(33007 characters\)
  sed "s/^X//" >'menu.c' <<'END_OF_FILE'
X/*
X *	(c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
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#include "regexp.h"
X
Ximport char *news_lib_directory;
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 */
Xexport int  slow_mode	   = 0;	/* mark selected articles with *s */
Xexport int  re_layout      = 0; /* Re: format presentation on menus */
Xexport int  collapse_subject = 25; /* collapse long subjects at position */
Xexport int  conf_group_entry = 0; /* ask whether group should be entered */
Xexport int  conf_entry_limit = 0; /* ask only if more than .. unread */
X
Xexport int  auto_preview_mode = 0; /* preview rather than select */
Xexport int  preview_continuation = 12; /* what to do after preview */
Xexport int  preview_mark_read = 1; /* previewed articles are A_READ */
Xexport int  select_on_sender = 0; /* + command selects on sender */
X
Xexport char delayed_msg[100] = "";	/* give to msg() after redraw */
X
Xexport int  flush_typeahead = 0;
X
Ximport int also_read_articles;
Ximport int merged_menu;
Ximport int case_fold_search;
X
Xextern group_completion();
X
Xstatic regexp *regular_expr = NULL;
X
Xstatic int firstl;	/* first menu line */
X
Xstatic article_number firsta;	/* first article on menu (0 based) */
Xstatic article_number nexta;	/* first article on next menu */
Xstatic int cura;	/* current article */
Xstatic int next_cura;	/* article to become cura if >= 0 */
Xstatic int numa;	/* no of articles on menu - 1 */
Xstatic attr_type last_attr;
X
X#define INTERVAL1	('z' - 'a' + 1)
X#define INTERVAL2	('9' - '0' + 1)
X
Xchar ident[] = "abcdefghijklmnopqrstuvwxyz0123456789";
X
Xchar attributes[30] = " .,+=#! **"; /* Corresponds to A_XXXX in data.h */
X
Xstatic prt_replies(level)
X{
X    int re;
X
X    if (level == 0) return 0;
X    re = level & 0x80;
X    level &= 0x7f;
X
X    switch (re_layout) {
X     case 1:
X	if (!re) return 0;
X	so_printf(">");
X	return 1;
X     case 2:
X	so_printf("%d>", level);
X	return level < 10 ? 2 : 3;
X     case 3:
X	so_printf("Re: ");
X	return 4;
X    }
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
Xstatic mark()
X{
X    register article_header *ah;
X    int lno, lnum, lsubj, lname;
X
X    ah = articles[firsta + cura];
X    last_attr = ah->attr;
X
X    if (last_attr == ah->disp_attr) return;
X    if (cura < 0 || cura > numa) return;
X
X    lno = firstl + cura;
X    if (ah->disp_attr == A_NOT_DISPLAYED) {
X	gotoxy(0, lno);
X	putchar(ident[cura]);
X	goto print_line;
X    }
X
X    /* A_AUTO_SELECT will not occur here! */
X
X    if (!slow_mode)
X	if (last_attr == A_SELECT) {
X	    if ((ah->disp_attr & A_SELECT) == 0) goto print_line;
X	} else {
X	    if (ah->disp_attr & A_SELECT) goto print_line;
X	}
X
X    gotoxy(1, lno);
X    putchar(attributes[ah->attr]);
X    goto out;
X
X print_line:
X    /* menu line formats:
X                1  3    8 10     20 22        xx
X		:  :    :  :      :  :        :
X       -1	id name:8 subject
X       0	id name           subject     +lines
X       1	id name       lines  subject
X       2	id  lines  subject
X       3	id subject
X       4	id   subject  (or as 1 if short subject)
X     */
X
X    if (fmt_linenum > 4) fmt_linenum = 1;
X
X    if (!slow_mode && (ah->attr & A_SELECT)) {
X	if (so_gotoxy(1, lno, 1) == 0)
X	    putchar(attributes[A_SELECT]);
X    } else {
X    	gotoxy(1, lno);
X	putchar(attributes[ah->attr]);
X    }
X
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 -1:
X	lsubj -= 9;
X	so_printf("%-8.8s ", ah->sender);
X	break;
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 4:
X	if (ah->subj_length > (lsubj - NAME_LENGTH - 5))
X	    if (fmt_rptsubj || lno == firstl || (ah->flag & A_SAME) == 0) {
X		so_printf("  ");
X		lsubj -= 2;
X		break;
X	    }
X	/* else use layout 1, so fall thru */
X
X     case 1:
X	lsubj -= NAME_LENGTH + 5;
X	/* name.lines.  .subj (name may be shortened) */
X	lname = NAME_LENGTH + 2 - lnum;
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
X    if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) {
X	if (ah->replies == 0 || prt_replies(ah->replies) == 0)
X	    so_printf("-");
X    } else {
X	lsubj -= prt_replies(ah->replies);
X	if (lsubj >= ah->subj_length)
X	    so_printf("%s", ah->subject);
X	else
X	if (collapse_subject < 0)
X	    so_printf("%-.*s", lsubj, ah->subject);
X	else {
X	    if (collapse_subject > 0)
X		so_printf("%-.*s", collapse_subject, ah->subject);
X	    lsubj -= 2 + collapse_subject;
X	    so_printf("<>%s", ah->subject + ah->subj_length - lsubj);
X	}
X    }
X
X    if (fmt_linenum == 0)
X	so_printf(ah->lines >= 0 ? " +%d" : " +?", ah->lines);
X
X    so_end();
X
X out:
X    ah->disp_attr = last_attr;
X    return;
X}
X
Xstatic new_mark(how)
Xattr_type how;
X{
X    articles[firsta + cura]->attr = how;
X    mark();
X}
X
Xstatic toggle()
X{
X    last_attr = articles[firsta + cura]->attr =
X	articles[firsta + cura]->attr & A_SELECT ? 0 : A_SELECT;
X}
X
Xstatic do_auto_kill()
X{
X    register article_number i;
X    register article_header *ah, **ahp;
X    int any = 0;
X
X    for (i = 0, ahp = articles; i < n_articles; i++, ahp++) {
X	ah = *ahp;
X	if (auto_select_article(ah, 0)) {
X	    ah->attr = A_KILL;
X	    any = 1;
X	}
X    }
X    return any;
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(re, mode)
Xregexp *re;
Xint mode;
X{
X    register article_number 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 (re != NULL) {
X	    if (!regexec_cf(re, select_on_sender ? ah->sender : ah->subject)) continue;
X	} else
X	    if (!auto_select_article(ah, mode)) continue;
X
X	count++;
X	if (ah->attr & A_SELECT) continue;
X	if (firsta <= i && i <= (firsta+numa)) {
X	    cura = i - firsta;
X	    new_mark(A_SELECT);
X	} else
X	    ah->attr = A_SELECT;
X    }
X
X    if (count)
X	msg("Selected %d article%s", count, plural((long)count));
X    else
X	msg("No selections");
X    
X    cura = o_cura;
X}
X
Xstatic quit_preview(cmd)
Xint cmd;
X{
X    int op;
X
X    if ((firsta + cura) >= n_articles) return 1;
X    op = preview_continuation;
X    if (cmd == MC_PREVIEW_NEXT)	op /= 10;
X    op %= 10;
X    switch (op) {
X     case 0:
X	return 1;
X     case 1:
X	return 0;
X     case 2:
X	return (articles[firsta+cura]->flag & (A_SAME | A_ALMOST_SAME)) == 0;
X    }
X    return 0;
X}
X
X
Xstatic show_articles()
X{
X    register article_number cur, next, temp;
X    register article_header *ah;
X    article_number elim_list[1];
X    register int mode;
X    int cmd, prev = -1, again;
X    attr_type o_attr;
X
X    do {
X	for (cur = 0; cur < n_articles; cur++) {
X	    if (articles[cur]->attr & A_SELECT) break;
X	}
X
X	while (cur < n_articles) {
X
X	    for (next = cur+1; next < n_articles; next++) {
X		if (articles[next]->attr & A_SELECT) break;
X	    }
X
X	 show:
X	    ah = articles[cur];
X	    o_attr = ah->attr;
X	    ah->attr = 0;
X
X	    mode = 0;
X	    if (prev >= 0) mode |= MM_PREVIOUS;
X	    if (next == n_articles) mode |= MM_LAST_SELECTED;
X	    if ((cur + 1) >= n_articles) mode |= MM_LAST_ARTICLE;
X	    if (cur == 0) mode |= MM_FIRST_ARTICLE;
X
X	    cmd = more(ah, mode, 0);
X
X	    switch (cmd) {
X
X	     case MC_DO_KILL:
X		if (do_auto_kill()) {
X		    elim_list[0] = next;
X		    elim_articles(elim_list, 1);
X		    cur = elim_list[0];
X		    /* if next was n_articles, cur will be 0 */
X		    if (cur >= n_articles || cur < 0
X			|| (articles[cur]->attr & A_SELECT) == 0)
X			cur = n_articles;
X		    continue;
X		}
X		break;
X
X	     case MC_DO_SELECT:
X		for (temp = cur+1; temp < n_articles; temp++) {
X		    if (auto_select_article(ah = articles[temp], 2)) {
X			ah->attr = A_SELECT;
X			if (temp < next) next = temp;
X		    }
X		}
X		break;
X
X	     case MC_PREV:
X		if (prev == next) break;
X
X		ah->attr = o_attr;
X		next = cur; cur = prev; prev = next;
X		goto show;
X
X	     case MC_NEXTSUBJ:
X		ah->attr = A_READ;
X		for (next = cur+1; next < n_articles; next++) {
X		    if (((ah = articles[next])->flag & (A_SAME | A_ALMOST_SAME)) == 0) break;
X		    ah->attr = A_READ;
X		}
X		for (; next < n_articles; next++) {
X		    if (articles[next]->attr & A_SELECT) break;
X		}
X		break;
X
X	     case MC_ALLSUBJ:
X		for (next = cur+1; next < n_articles; next++) {
X		    ah = articles[next];
X		    if ((ah->flag & (A_SAME | A_ALMOST_SAME)) == 0) break;
X		    ah->attr = A_SELECT;
X		}
X		for (next = cur+1; next < n_articles; next++)
X		    if (articles[next]->attr & A_SELECT) break;
X		break;
X
X	     case MC_MENU:
X		ah->attr = o_attr;
X		if (nexta - firsta < n_articles)
X		    if ((firsta = cur - 5) < 0) firsta = 0;
X		next_cura = cur - firsta;
X
X		return MC_MENU;
X
X	     case MC_NEXT:
X		if (ah->attr == 0)	/* Not set by more (sufficient ???) */
X		    ah->attr = A_READ;
X		break;
X
X	     case MC_BACK_ART:
X		ah->attr = o_attr ? o_attr : A_SEEN;
X		next = cur - 1;
X		break;
X
X	     case MC_FORW_ART:
X		ah->attr = o_attr ? o_attr : A_SEEN;
X		next = cur + 1;
X		break;
X
X	     case MC_NEXTGROUP:
X	     case MC_REENTER_GROUP:
X	     case MC_QUIT:
X		ah->attr = o_attr;
X		return cmd;
X
X	     case MC_READGROUP:
X		return cmd;
X	    }
X
X	    prev = cur; cur = next;
X	}
X
X	for (cur = 0; cur < n_articles; cur++)
X	    if (articles[cur]->attr & A_SELECT) break;
X	if (cur < n_articles) continue;
X
X	again = 0;
X	for (cur = 0; cur < n_articles; cur++) {
X	    ah = articles[cur];
X	    if (ah->attr == A_LEAVE) {
X		if (again == 0) {
X		    prompt("Show left over articles again now? ");
X		    if (yes(0) <= 0) break;
X		}
X		ah->attr = A_SELECT;
X		again++;
X	    }
X	}
X
X	if (again > 1)
X	    sprintf(delayed_msg, "Showing %ld articles again", again);
X    } while (again);
X
X    return MC_READGROUP;
X}
X
Xstatic int article_id;
Xstatic int cur_key;
X
Xstatic int get_k_cmd()
X{
X    extern int any_message;
X    register int c, map;
X
X    if (flush_typeahead) flush_input();
X
X loop:
X
X    article_id = -1;
X
X    if ((c = get_c()) & GETC_COMMAND) {
X	cur_key = K_interrupt;
X	map = c & ~GETC_COMMAND;
X    } else {
X	cur_key = c;
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    if (any_message) clrmsg(-1);
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 || n <= 0)
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
Xstatic repl_attr(first, last, old, new, update)
Xregister article_number first, last;
Xregister attr_type old, new;
Xint update;
X{
X    int any;
X
X    if (new == old) return 0;
X    if (new == A_KILL) update = 0;
X
X    any = 0;
X    while (first < last) {
X	if (old == A_KILL || articles[first]->attr == old) {
X	    articles[first]->attr = new;
X	    if (update) {
X		cura = first-firsta;
X		mark();
X	    }
X	    any = 1;
X	}
X
X	first++;
X    }
X    return any;
X}
X
X
Xstatic repl_attr_all(old, new, update)
Xattr_type old, new;
Xint update;
X{
X    return repl_attr((article_number)0, n_articles, old, new, update);
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
X    f = open_file(relative(news_lib_directory, "newsgroups"), OPEN_READ);
X    if (f == 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
Xmenu(print_header)
Xfct_type print_header;
X{
X    register 		k_cmd, cur_k_cmd;
X    register		article_header *ah;
X    int			last_k_cmd;
X    int 		menu_cmd, temp;
X    int 		save_selected;
X    article_number	last_save;
X    attr_type		orig_attr, junk_attr;
X    int			doing_unshar, did_unshar, junk_prompt;
X    char 		*fname, *savemode, *init_save();
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;
X    article_number	elim_list[3];
X    int			entry_check;
X
X#define	menu_return(cmd) \
X    { menu_cmd = (cmd); goto menu_exit; }
X
X    flush_input();
X
X    o_firsta = firsta;
X    o_mode = in_menu_mode;
X    in_menu_mode = 1;
X
X    menu_level++;
X
X    entry_check = menu_level == 1 && conf_group_entry &&
X	current_group->unread_count > conf_entry_limit;
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    firsta = 0;
X    while (firsta < n_articles && articles[firsta]->attr == A_SEEN)
X	firsta++;
X
X    if (firsta == n_articles) firsta = 0;
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 = CALL(print_header)();
X
X    if (entry_check && menu_level == 1) {
X	/* we do it here to avoid redrawing the group header */
X	entry_check = 0;
X	prompt_line = firstl;
X	prompt("\1Enter?\1 ");
X	if ((temp = yes(0)) <= 0) {
X	    if (temp < 0) {
X		prompt("\1Mark as read?\1 ");
X		if ((temp = yes(0)) < 0) menu_return(ME_QUIT);
X		if (temp > 0) repl_attr_all(A_KILL, A_READ, 0);
X	    }
X	    menu_return(ME_NEXT);
X	}
X
X	gotoxy(0, firstl);
X	clrline();
X    }
X
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	firsta = nexta;
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	    REDRAW_CHECK;
X
X	    articles[firsta+cura]->disp_attr = A_NOT_DISPLAYED;
X	    mark();
X	    nexta++; cura++;
X	}
X
X    fl;
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]->attr & A_SELECT) == 0) break;	/*???*/
X     }
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[0] != NUL) {
X	 msg(delayed_msg);
X	 delayed_msg[0] = NUL;
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	 save_xy();
X     }
X
X     last_k_cmd = cur_k_cmd;
X     k_cmd = get_k_cmd();
X
X  alt_key:
X
X     switch (cur_k_cmd = k_cmd) {
X
X      case K_UNBOUND:
X	 ding();
X	 flush_input();
X      case K_INVALID:
X	 goto same_prompt;
X
X      case K_REDRAW:
X	 next_cura = cura;
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_UNCHANGED:
X	     goto same_prompt;
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_REENTER_GROUP:
X	     menu_return(ME_REENTER_GROUP);
X	 }
X
X      case K_QUIT:
X	 menu_return(ME_QUIT);
X
X      case K_CANCEL:
X	 savemode = "Cancel";
X	 fname = "";
X	 goto cancel1;
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      case K_UUDECODE:
X
X	 if (numa < 0) goto nextmenu;
X
X	 fname = init_save(k_cmd, &savemode);
X	 if (fname == NULL) goto Prompt;
X
X      cancel1:
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	 if (novice)
X	     msg(" * selected articles on this page, + all selected articles");
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->attr & A_SELECT) == 0) continue;
X
X		 if (cur_k_cmd == K_CANCEL) {
X		     if (current_group->group_flag & G_FOLDER) {
X			 if (ah->attr != A_CANCEL) fcancel(ah);
X		     } else
X			 switch (cancel(ah)) {
X			  case -1:
X			     did_unshar = 1;
X			     continue;
X			  case 0:
X			     ah->attr = A_CANCEL;
X			     break;
X			  default:
X			     continue;
X			 }
X
X		     if (!did_unshar)
X			 mark();
X
X		     continue;
X		 }
X
X		 if (doing_unshar) {
X		     did_unshar++;
X		 } else
X		 if (ah->subject != NULL)
X		     prompt("Processing '%.50s'...", ah->subject);
X		 else 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		     ah->attr = A_READ;
X		     if (doing_unshar) continue;
X
X		     if (cura >= 0 && cura <= numa)
X			 mark();
X		 }
X	     }
X	 }
X
X	 if (save_selected) cura = 0;
X
X	 m_endinput();
X
X	 enable_stop = 1;
X	 if (cur_k_cmd != K_CANCEL)
X	     end_save();
X
X	 if (did_unshar) {
X	     printf("\r\n");
X	     any_key(0);
X	     goto redraw;
X	 }
X	 goto Prompt;
X
X      case K_FOLLOW_UP:
X#ifdef NNTP_POST
X	 if (use_nntp && nntp_no_post()) goto same_prompt;
X#endif
X      case K_REPLY:
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
X#ifdef NNTP_POST
X	 if (use_nntp && nntp_no_post())
X	     goto same_prompt;
X#endif
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		 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_UNSUBSCRIBED)
X		 menu_return(ME_NEXT);
X	     home();
X	     CALL(print_header)();
X	 }
X	 goto Prompt;
X
X      case K_GROUP_OVERVIEW:
X	 group_overview(-1);
X	 goto redraw;
X
X      case K_KILL_HANDLING:
X	 switch (kill_menu((article_header *)NULL)) {
X	  case 0:		/* select */
X	     do_auto_select((regexp *)NULL, 2);
X	     break;
X	  case 1:		/* kill */
X	     if (!do_auto_kill()) break;
X	     goto junk_killed_articles;
X	  default:
X	     break;
X	 }
X	 goto Prompt;
X
X      case K_CONTINUE:	/* goto next menu page or show the articles */
X	 repl_attr(firsta, nexta, 0, A_SEEN, 0);
X	 /* fall thru */
X      case K_CONTINUE_NO_MARK:	/* but don't mark unselected articles */
X	 if (nexta < n_articles) goto nextmenu;
X	 break;
X
X      case K_READ_GROUP_UPDATE:
X	 repl_attr_all(0, A_SEEN, 0);
X	 break;
X
X      case K_READ_GROUP_THEN_SAME:
X	 break;
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, (flag_type)0)) {
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	     s_keyboard = 1;
X	     goto empty_menu_hack;
X	 }
X
X      case K_LEAVE_NEXT:
X      case K_JUNK_ARTICLES:
X	 junk_prompt = cur_k_cmd == K_JUNK_ARTICLES ? 1 : 5;
X
X	 for (;;) {
X	     switch (junk_prompt) {
X	      case 1:
X		 if (novice) msg("Use J repeatedly to select other functions");
X		 prompt("\1Mark read\1 S)een U)nmarked A)ll *+)selected a-z . [LN]");
X		 junk_attr = A_READ;
X		 break;
X	      case 2:
X		 prompt("\1Unmark\1 S)een R)ead a-z [*+LAN.J] ");
X		 junk_attr = 0;
X		 break;
X	      case 3:
X		 prompt("\1Select\1 L)eft-over, N(leave-next) [USRa-z.J]");
X		 junk_attr = A_SELECT;
X		 break;
X	      case 4:
X		 prompt("\1Kill\1 R)ead S)een [LANU*+a-z.J]");
X		 junk_attr = A_KILL;
X		 break;
X	      case 5:
X		 prompt("\1Leave\1 a-z .,/ * + U)nmarked [LANRSJ]");
X		 junk_attr = A_LEAVE_NEXT;
X		 break;
X	      default:
X		 junk_prompt = 1;
X		 continue;
X	     }
X
X	  junk_another:
X	     if (cura < 0 || cura > numa) cura = 0;
X	     gotoxy(0, firstl + cura); fl;
X	     
X	     switch (get_k_cmd()) {
X	      case K_JUNK_ARTICLES:
X		 junk_prompt++;	/* can be 0 */
X		 continue;
X
X	      case K_ARTICLE_ID:
X		 cura = article_id;
X	      case K_SELECT:
X		 if (junk_attr == A_KILL) junk_attr = A_READ;
X		 articles[firsta + cura]->attr = junk_attr;
X		 mark();
X		 cura++;
X		 goto junk_another;
X
X	      case K_NEXT_LINE:
X		 cura++;
X		 goto junk_another;
X		 
X	      case K_PREV_LINE:
X		 --cura;
X		 goto junk_another;
X
X	      case K_SELECT_SUBJECT:
X		 if (junk_attr == A_KILL) junk_attr = A_READ;
X		 repl_attr(firsta, nexta, A_AUTO_SELECT, A_SELECT, 0);
X		 repl_attr(firsta, nexta, A_SELECT, junk_attr, 1);
X		 goto Prompt;
X
X	      case K_AUTO_SELECT:
X		 repl_attr_all(A_AUTO_SELECT, A_SELECT, 0);
X		 orig_attr = A_SELECT;
X		 break;
X
X	      default:
X		 switch (cur_key) {
X		  case 'S':
X		     orig_attr = A_SEEN;
X		     break;
X
X		  case 'U':
X		     orig_attr = 0;
X		     break;
X
X		  case 'L':
X		     if (junk_attr == A_KILL) junk_attr = A_READ;
X		     orig_attr = A_LEAVE;
X		     break;
X
X		  case 'A':
X		     orig_attr = A_KILL;
X		     break;
X
X		  case 'N':
X		     orig_attr = A_LEAVE_NEXT;
X		     break;
X
X		  case 'R':		/* kill read articles */
X		     orig_attr = A_READ;
X		     break;
X
X		  default:
X		     goto Prompt;
X		 }
X		 break;
X	     }
X	     break;
X	 }
X	 if (nexta - firsta < n_articles) {
X	     prompt("On all menu pages? ");
X	     switch (yes(1)) {
X	      case -1:
X		 goto Prompt;
X	      case 0:
X		 if (!repl_attr(firsta, nexta, orig_attr, junk_attr, 1))
X		     goto Prompt;
X		 break;
X	      case 1:
X		 if (!repl_attr_all(orig_attr, junk_attr, 1))
X		     goto Prompt;
X		 break;
X	     }
X	 } else
X	     if (!repl_attr(firsta, nexta, orig_attr, junk_attr, 1))
X		 goto Prompt;
X
X	 if (junk_attr != A_KILL) goto Prompt;
X
X      junk_killed_articles:
X	 elim_list[0] = firsta;
X	 elim_list[1] = firsta + cura;
X	 elim_list[2] = nexta;
X	 if (elim_articles(elim_list, 3)) {
X	     firsta = elim_list[0];
X	     goto redraw;
X	 }
X	 firsta = elim_list[0];
X	 cura   = elim_list[1] - firsta;
X	 nexta  = elim_list[2];
X	 goto Prompt;
X
X      case K_ARTICLE_ID:
X	 if (numa < 0) goto nextmenu;
X
X	 if (auto_preview_mode) goto auto_preview;
X
X	 cura = article_id;
X	 toggle();
X	 mark();
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	     toggle();
X	     mark();
X	 }
X	 fl;
X
X	 REDRAW_CHECK;
X	 raw();
X
X	 cura = temp;
X	 goto same_prompt;
X
X
X      case K_SELECT:
X	 if (numa < 0) goto nextmenu;
X
X	 toggle();
X	 mark();
X	 cura++;
X	 goto same_prompt;
X
X      case K_UNSELECT_ALL:
X	 if (last_k_cmd == K_UNSELECT_ALL)
X	     repl_attr_all(A_SELECT, 0, 1);
X	 else
X	     repl_attr_all(A_AUTO_SELECT, 0, 1);
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	 goto same_prompt;
X
X      case K_PREV_LINE:
X	 if (numa < 0) goto nextmenu;
X
X	 if (--cura < 0) cura = numa;
X	 goto same_prompt;
X
X      case K_SELECT_SUBJECT:
X	 if (numa < 0) goto nextmenu;
X
X	 if (last_k_cmd != K_ARTICLE_ID && last_k_cmd != K_SELECT)
X	     toggle();
X
X	 while (firsta+cura > 0 &&
X		(articles[firsta+cura]->flag & (A_SAME | A_ALMOST_SAME)))
X	     cura--;
X
X	 do {
X	     new_mark(last_attr);
X	     cura++;
X	     if (firsta+cura >= n_articles) break;
X	 } while (articles[firsta+cura]->flag & (A_SAME | A_ALMOST_SAME));
X
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	     cura--;
X	     if (cura < 0) cura = numa;
X	 } else
X	     last_attr = (articles[firsta+cura]->attr & A_SELECT) ? 0 : A_SELECT;
X
X      range_again:
X
X	 prompt("\1%select range\1 %c-", last_attr ? "S" : "Des", ident[cura]);
X
X	 k_cmd = get_k_cmd();
X	 if (k_cmd == K_SELECT_RANGE) {
X	     last_attr = last_attr ? 0 : A_SELECT;
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	     new_mark(last_attr);
X
X	 if (article_id <= cura) {
X	     while (cura >= article_id) {
X		 new_mark(last_attr);
X		 cura--;
X	     }
X	     if (cura < 0) cura = 0;
X	 } else {
X	     while (cura <= article_id) {
X		 new_mark(last_attr);
X		 cura++;
X	     }
X	     if (cura > numa) cura = numa;
X	 }
X	 goto Prompt;
X
X      case K_AUTO_SELECT:
X	 do_auto_select((regexp *)NULL, 1);
X	 goto same_prompt;
X
X     case K_GOTO_MATCH:
X	 prompt("\1Select regexp\1 ");
X	 if ((fname = get_s(NONE, NONE, NONE, NULL_FCT)) == NULL)
X	     goto Prompt;
X
X	 if (*fname != NUL) {
X	     if (regular_expr) freeobj(regular_expr);
X	     if (case_fold_search) fold_string(fname);
X	     regular_expr = regcomp(fname);
X	 }
X
X	 if (regular_expr == NULL)
X	     msg("No previous expression");
X	 else
X	     do_auto_select(regular_expr, 2);
X
X	 goto Prompt;
X
X      case K_NEXT_PAGE:
X	 if (nexta < n_articles) goto nextmenu;
X	 if (firsta == 0) goto same_prompt;
X
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      auto_preview:
X	 temp = prompt_line;
X
X      preview_next:
X	 cura = article_id;
X	 ah = articles[firsta+cura];
X
X	 no_raw();
X	 ah->attr = 0;
X	 menu_cmd = more(ah, MM_PREVIEW, prompt_line);
X	 if (menu_cmd == MC_MENU) {
X	     next_cura = cura;
X	     if (prompt_line < 0) goto redraw;
X	     mark();
X	     prompt_line = temp;
X	     goto build_prompt;
X	 }
X
X	 if (preview_mark_read && ah->attr == 0) ah->attr = A_READ;
X	 if (prompt_line >= 0)
X	     mark();
X	 next_cura = ++cura;
X
X	 switch (menu_cmd) {
X
X	  case MC_DO_KILL:
X	     if (!do_auto_kill()) break;
X	     elim_list[0] = firsta;
X	     elim_list[1] = firsta + cura;
X	     elim_articles(elim_list, 2);
X	     firsta = elim_list[0];
X	     next_cura = elim_list[1] - firsta;
X	     goto redraw;
X
X	  case MC_DO_SELECT:
X	     if (prompt_line >= 0) { /* not redrawn */
X		 do_auto_select((regexp *)NULL, 2);
X		 break;
X	     }
X	     numa = -1;
X	     do_auto_select((regexp *)NULL, 2);
X	     /* FALL THRU */
X
X	  case MC_QUIT:
X	     menu_return( ME_QUIT );
X
X	  case MC_REENTER_GROUP:
X	     menu_return( ME_REENTER_GROUP );
X
X	  case MC_NEXT:
X	  case MC_PREVIEW_NEXT:
X	     if (prompt_line < 0) {	/* redrawn screen ! */
X		 if (quit_preview(menu_cmd)) goto redraw;
X		 prompt_line = Lines;
X	     } else {
X/*		 if (ah->attr == A_LEAVE || ah->attr == A_LEAVE_NEXT) {
X		     cura--;
X		     mark();
X		     cura++;
X		 }
X*/		 if (quit_preview(menu_cmd)) 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	     if (prompt_line < 0) goto redraw;
X	     break;
X	 }
X
X	 prompt_line = temp;
X	 goto build_prompt;
X
X      case K_LAYOUT:
X	 if (++fmt_linenum > 4) fmt_linenum = 0;
X	 goto redraw;
X
X      default:
X	 msg("Command %d not supported", k_cmd);
X	 goto same_prompt;
X     }
X
X    no_raw();
X
X    switch (show_articles()) {
X
X     case MC_MENU:
X	goto redraw;
X
X     case MC_READGROUP:
X	if (k_cmd == K_READ_GROUP_THEN_SAME || also_read_articles) goto redraw;
X     case MC_NEXTGROUP:
X	menu_cmd = ME_NEXT;
X	break;
X
X     case MC_REENTER_GROUP:
X	menu_cmd = ME_REENTER_GROUP;
X	break;
X
X     case MC_QUIT:
X	menu_cmd = ME_QUIT;
X	break;
X
X     default:
X	sys_error("show_articles returned improper value");
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
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
X
X/*
X *	read command from command line
X */
X
Xalt_command()
X{
X    int ok_val, macro_cmd;
X    char *cmd, brkchars[10];
X    extern key_type erase_key;
X    extern int get_from_macro;
X    extern int alt_completion();
X
X    if (get_from_macro)
X	ok_val = AC_UNCHANGED;
X    else {
X	prompt(":");
X	ok_val = AC_PROMPT;
X    }
X
X again:
X
X    sprintf(brkchars, "?%c ", erase_key);
X
X    cmd = get_s(NONE, NONE, brkchars, 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}
END_OF_FILE
  if test 33007 -ne `wc -c <'menu.c'`; then
    echo shar: \"'menu.c'\" unpacked with wrong size!
  fi
  # end of 'menu.c'
fi
echo shar: End of archive 6 \(of 22\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 22 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0

exit 0 # Just in case...
