[comp.sources.unix] v19i066: NN, a Usenet news reader, Part05/15

rsalz@uunet.uu.net (Rich Salz) (06/23/89)

Submitted-by: storm@texas.dk (Kim F. Storm)
Posting-number: Volume 19, Issue 66
Archive-name: nn/part05

#!/bin/sh
# this is part 5 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file help.help continued
#
CurArch=5
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 help.help"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' >> help.help
Xshow		displaying various tables
Xvariables	variables
NO_NEWS_IS_GOOD_NEWS
echo "File help.help is complete"
chmod 0644 help.help || echo "restore of help.help fails"
set `wc -c help.help`;Sum=$1
if test "$Sum" != "269"
then echo original size 269, current size $Sum;fi
echo "x - extracting help.map (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > help.map &&
X;:AMAP COMMAND;:A
X
Xmap TABLE		show contents of mapping table		
X
Xmap menu KEY COMMAND	map KEY into COMMAND in menu mode
Xmap show KEY COMMAND	map KEY into COMMAND in article presentation mode
Xmap key  KEY1 KEY2	map KEY1 into KEY2 (unconditionally)
Xmap #N   CH1 CH2 ...	define the input sequence CH1 CH2 ... as special key N
X
X;:AKEYS;:A
X
X	0xNN: the ascii character NN
X	C: the character C
X	^C: control-C (^? = DEL)
X	#N: special key number N
X	up, down, left, rigth: the arrow keys
X
X;:Chelp.commands
NO_NEWS_IS_GOOD_NEWS
chmod 0644 help.map || echo "restore of help.map fails"
set `wc -c help.map`;Sum=$1
if test "$Sum" != "494"
then echo original size 494, current size $Sum;fi
echo "x - extracting help.menu (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > help.menu &&
X;:ASELECT (toggle);:A				;:AMOVE;:A
Xa-z0-9	specified article		,	Next menu line
Xx-y	range x to y			/	Previous menu line
Xx*	same subject as x		SPACE	Next menu page (if any)
X.	current article			< >	Prev/Next menu page
X@	Reverse all selections		^ $	First/Last menu page
X
X;:ASHOW SELECTED ARTICLES;:A
XSPACE	Show selected articles (only when on last menu page)
XZ 	Show selected articles NOW, and return to this group afterwards
XX	Show selected articles NOW, and continue with next group
X
X;:AGOTO OTHER GROUPS;:A
XX	If no articles are selected then skip to next group.
XN P 	Goto next/previous group WITHOUT reading current group
XG	Goto named group or open a folder.
XB A	Go back/forward in groups already read
X
X;:AMISCELLANEOUS;:A
XU	(Un)subscribe			L	Change menu layout
XS O W	Save articles			!	Shell escape
XF R M	Follow-up/Reply/Mail		C	Cancel an article of your own
NO_NEWS_IS_GOOD_NEWS
chmod 0644 help.menu || echo "restore of help.menu fails"
set `wc -c help.menu`;Sum=$1
if test "$Sum" != "858"
then echo original size 858, current size $Sum;fi
echo "x - extracting help.more (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > help.more &&
X;:ASCROLLING;:A		  ;:AABSOLUTE LINE;:A		;:ASEARCHING;:A
XSP	  1 page forw	  ^	top		/RE	find regular expr.
Xd	1/2 page forw	  gNUM	line NUM	. //	repeat last search
XCR	  1 line forw	  $	last line
XDEL       1 page back	  h	header		;:ATEXT CONVERSIONS;:A
Xu       1/2 page back	  H	full digest	D       decrypt article (rot13)
X						c       compress spaces
X;:AGOTO ANOTHER ARTICLE;:A
XSP      next (at end of current article)	;:ACANCEL, SUBSCRIBE, KILL;:A
Xn       next                            	C       cancel article
Xp       previous article                	U       (un)subscribe to group
Xk       kill subject (not permanently)  	K       kill/select handling
X*       select subject                  
X      	                                  	;:AQUIT / ESCAPE;:A
X;:ASAVE;:A			                   	=       back to menu
Xs, o, w   save with full/short/no header     	N       goto next group
X:unshar	  unshar article			X       as N, mark as read
X					     	!, ^Z   Shell escape, suspend
X;:AREPLY, POST;:A					Q       quit nn
Xr       mail reply to author of article                  	
Xm       mail (or forward article)       	;:AREDRAW;:A
Xf       post follow-up to article       	^P      Repeat last message
X:post   post new article                	^L, ^R  Redraw screen
NO_NEWS_IS_GOOD_NEWS
chmod 0644 help.more || echo "restore of help.more fails"
set `wc -c help.more`;Sum=$1
if test "$Sum" != "1258"
then echo original size 1258, current size $Sum;fi
echo "x - extracting help.read (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > help.read &&
X;:Chelp.more
NO_NEWS_IS_GOOD_NEWS
chmod 0644 help.read || echo "restore of help.read fails"
set `wc -c help.read`;Sum=$1
if test "$Sum" != "13"
then echo original size 13, current size $Sum;fi
echo "x - extracting help.set (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > help.set &&
X;:ASET COMMAND;:A
X
X:set			show current variables
X
X:set VARIABLE VALUE	set variable
X:unset VARIABLE		reset variable 
X:toggle VARIABLE
X
X;:Chelp.variables
NO_NEWS_IS_GOOD_NEWS
chmod 0644 help.set || echo "restore of help.set fails"
set `wc -c help.set`;Sum=$1
if test "$Sum" != "152"
then echo original size 152, current size $Sum;fi
echo "x - extracting help.show (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > help.show &&
X;:ASHOW COMMAND;:A
X
Xshow kill		show auto kill/select entries for current
X			groups and all groups.
X
Xshow groups		show groups with unread articles (= Y command)
X
Xshow groups all		show all subscribed groups
X
Xshow groups total	show all available groups
X
Xshow map key/menu/show	show key bindings
NO_NEWS_IS_GOOD_NEWS
chmod 0644 help.show || echo "restore of help.show fails"
set `wc -c help.show`;Sum=$1
if test "$Sum" != "292"
then echo original size 292, current size $Sum;fi
echo "x - extracting help.variables (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > help.variables &&
X;:AVARIABLES;:A
X
Xbackup			Keep backup of rc file + delay update until quit (= -B)
Xcomp1-key KEY		Completion key 1 (space)
Xcomp2-key KEY		Completion key 2 (tab)
Xconfirm			User must confirm all messages with return (= -W)
Xdate	  		Show article dates (date = -D)
Xdefault-save-file FILE	Default save file (for + abbreviation)		
Xdelay-redraw		Do not redraw screen immediately after : commands
Xerase-key KEY		Erase last input character or completion
Xexpert			Use shorter prompts
Xfolder DIR 		Folder directory
Xfsort			Sort folders in subject order (nofsort = -f)
Xheader-lines LIST	Customized article header format
Xhelp-key KEY		Completion help key (?)
Xincluded-mark STR  	Prefix on included lines in replies (>) 
Xkill			Enable/disable auto kill/select (nokill = -k)
Xkill-key KEY		Delete input line key
Xlayout N		Menu layout N (-LN)
Xlimit N	  		Limit number of presented articles to N (-aN)
Xlong-menu		Use all lines on the menu screen
Xmacro-debug		Trace the execution of all macros
Xmail-format		Folders are created in mail compatible format
Xmail-record FILE  	Save all replies in FILE
Xmonitor			Print all characters when reading article
Xnews-record FILE  	Save all posted articles in FILE
Xold   N	  		Show read articles also (-xN, or -x if N is omitted)
Xoverlap N		Display last N lines on next page when reading
Xpager CMD	  	Screen pager used in administration mode (e.g. pg -n)
Xprinter CMD	 	Default print command (e.g. lp -s)
Xquick-save		Save in default save file without asking
Xrecord FILE	  	Set both news-record and mail-record to FILE
Xrepeat			Do not truncate repeated subject lines
Xretry-on-error N	Retry N times if open of article fails
Xsave-counter FMT  	Format of the save counter (e.g. .%02d)
Xsave-report		Display number of lines saved
Xsilent			Do not print "No news" etc.
Xsort	  		Sort articles on menu (nosort = -q)
Xsplit	  		Split digests (nosplit = -d)
Xstop N			Stop printing of articles after N lines (= -lN)
Xtime	  		Show current time on prompt line (notime = -T)
Xwindow N		Preview window size is N lines (= -wN)
X
NO_NEWS_IS_GOOD_NEWS
chmod 0644 help.variables || echo "restore of help.variables fails"
set `wc -c help.variables`;Sum=$1
if test "$Sum" != "2023"
then echo original size 2023, current size $Sum;fi
echo "x - extracting help.welcome (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > help.welcome &&
X;:AWelcome to the nn news reader;:A
X
XUnlike the other news readers you might be familiar with, the ultimate
Xgoal of nn is "not to read news"; actually, "nn" is an acronym for "No
XNews", and the parole for nn is:
X
X	No news is good news, but nn is better.
X
XI hope that you will enjoy using nn.
X
XIf you have problems, try the '?' command which will provide a quick
Xreference guide for the present environment.  Otherwise, consult the
Xmanuals or ask a local guru.  
X
X
XHave fun,
X
XKim Fabricius Storm
XTexas Instruments A/S
XDenmark
NO_NEWS_IS_GOOD_NEWS
chmod 0644 help.welcome || echo "restore of help.welcome fails"
set `wc -c help.welcome`;Sum=$1
if test "$Sum" != "525"
then echo original size 525, current size $Sum;fi
echo "x - extracting init.c (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > init.c &&
X/*
X *	.nn/init file handling
X */
X
X
X#include "config.h"
X#include "articles.h"
X#include "term.h"
X#include "keymap.h"
X#include "menu.h"
X
Xexport int in_init = 0;		/* true when parsing init file */
Xexport int alt_cmd_key;		/* K_ when parse_command returns AC_KEYCMD */
X
Xstatic int init_err = 0;	/* errors in init file */
X
X
X/*VARARGS*/
Xinit_message(va_alist)
Xva_dcl
X{
X    char *fmt;
X    va_list ap;
X    
X    va_start(ap);
X    
X    if (in_init) {
X	fmt = va_arg1(char *);
X
X	printf("init error: ");
X	vprintf(fmt, va_args2toN);
X	putchar(NL);
X	init_err++;
X    } else
X	vmsg(va_args1toN);
X
X    va_end(ap);
X}
X
X    
Xvisit_init_file()
X{
X    extern FILE *loc_seq_hook, *glob_seq_hook;
X    in_init = 1;
X    load_init_file(relative(lib_directory, "init"), &glob_seq_hook);
X    load_init_file("init", &loc_seq_hook);
X    if (init_err) nn_exit(1);
X    in_init = 0;
X}
X
X
X#define START_SEQUENCE 555
X
X
Xstatic load_init_file(name, seq_hook_ptr)
Xchar *name;
XFILE **seq_hook_ptr;
X{
X    FILE *init;
X    char cmdbuf[512], *cmd, *term;
X    extern char *term_name;
X
X    /* use cmdbuf temporarily (to handle @ expansion) */
X    for (cmd = cmdbuf; *name; name++)
X	if (*name == '@') {
X	    term = term_name;
X	    while (term && *term) *cmd++ = *term++;
X	} else
X	    *cmd++ = *name;
X    *cmd = NUL;
X    name = cmdbuf;
X
X    if (*name != '/')
X	name = relative(nn_directory, name);
X    
X    init = open_file(name, OPEN_READ);
X    if (init == NULL) return;
X
X    while (fgets(cmdbuf, 512, init)) {
X	/* we use AC_REDRAW to avoid !-commands clear the screen */
X	if (parse_command(cmdbuf, AC_REDRAW, init) == START_SEQUENCE) {
X	    if (seq_hook_ptr) {
X		*seq_hook_ptr = init;
X		return;	/* no close !! */
X	    } else {
X		init_message("load file contains 'sequence'");
X		fclose(init);
X		return;
X	    }
X	}
X    }
X    
X    fclose(init);
X}
X
X
X#define MAXARG 10
X
Xstatic char *argvec[MAXARG + 2];
Xstatic int argc;
X
Xstatic char *strip_str(cmd)
Xregister char *cmd;
X{
X    if (cmd == NULL) return cmd;
X
X    while (*cmd && isspace(*cmd)) cmd++;
X    if (*cmd == NUL || *cmd == NL) return NULL;
X    
X    return cmd;
X}
X
X    
Xstatic split_command(cmd)
Xregister char *cmd;
X{
X    /* split command string */
X
X    for (argc = 0; argc < MAXARG + 2; argc++) argvec[argc] = NULL;
X    if ((cmd = strip_str(cmd)) == NULL || *cmd == '#') return 0;
X    
X    argc = 0;
X    argvec[0] = cmd;
X
X    if (in_init)
X	while (*cmd) {
X	    if (*cmd == NL) {
X		*cmd = NUL;
X		break;
X	    }
X	    cmd++;
X	}
X
X    return 1;
X}
X
Xstatic char *argv(i)
Xint i;
X{
X    register char *cmd;
X    
X    if (i > MAXARG) return NULL;
X    
X    if (argc <= i)
X	if (cmd = argvec[argc])
X	    while (argc <= i) {
X		while (*cmd && !isspace(*cmd)) cmd++;
X		if (*cmd == NUL) {
X		    argc = MAXARG;
X		    break;
X		}
X		
X		*cmd++ = NUL;
X		if ((cmd = strip_str(cmd)) == NULL) {
X		    argc = MAXARG;
X		    break;
X		}
X		argvec[++argc] = cmd;
X	    }
X	else
X	    argc = MAXARG;
X
X    return argvec[i];
X}
X
X    
X/*
X * parse a command (also :-commands)
X */
X
Xstatic char *sw_string;
X
X#define	SWITCH(str)	\
X    for (sw_string = str; sw_string; sw_string = NULL) 
X
X#define CASE(str)	\
X    if (strcmp(sw_string, str) == 0)
X    
X
X#define ARG(i, str)	(argv(i) && strcmp(argv(i), str) == 0)
X#define ARGVAL(i)	atol(argv(i))
X#define ARGTAIL		argvec[argc]
X
Xstruct alt_commands {
X    char *alt_name;
X    int	 alt_len;
X    int  alt_type;
X} alt_commands[] = {
X    "admin",			5,	0,
X    "cd",			2,	1,
X    "compile",			7,	0,
X    "coredump",			8,	0,
X    "define",			6,	0,
X    "help",			4,	2,
X    "man",			3,	0,
X    "map",			3,	-1,
X    "map both",			8,	4,
X    "map key",			7,	0,
X    "map menu",			8,	4,
X    "map show",			8,	4,
X    "mkdir",			5,	1,
X    "print",			5,	0, /* QUICK HACK */
X    "pwd",			3,	0,
X    "rmail",			5,	0,
X    "set",			3,	3,
X    "show",			4,	-1,
X    "show groups",		11,	-1,
X    "show groups all",		15,	0,
X    "show groups subscr",	18,	0,
X    "show groups total",	17,	0,
X    "show groups unsub",	17,	0,
X    "show kill",		9,	0,
X    "show map",			8,	-1,
X    "show map #",		10,	0,
X    "show map key",		12,	0,
X    "show map menu",		13,	0,
X    "show map show",		13,	0,
X    "sort",			4,	-1,
X    "sort age",			8,	0,
X    "sort arrival",		12,	0,
X    "sort subject",		12,	0,
X    "toggle",			6,	3,
X    "unread",			6,	0,
X    "unset",			5,	3,
X    "unshar",			6,	0, /* QUICK HACK */
X    NULL,			0,	0
X};
X
Xalt_completion(buf, index)
Xchar *buf;
Xint index;
X{
X    static char *head, *tail = NULL, buffer[FILENAME];
X    static int len;
X    static struct alt_commands *alt, *help_alt;
X    static int (*other_compl)();
X    int temp;
X    register char *p, *q;
X    extern int file_completion(), var_completion(), cmd_completion();
X    extern int list_offset;
X    
X    if (other_compl) {
X	temp = (*other_compl)(buf, index);
X	if (index == 0 && temp == 1 && tail) strcpy(tail, head);
X	if (index < 0 || (index == 0 && temp == 0)) {
X	    other_compl = NULL;
X	    list_offset = 0;
X	}
X	return temp;
X    }
X    
X    if (index < 0) return 0;
X
X    if (buf) {
X	head = buf;
X	tail = buf + index;
X	alt = help_alt = alt_commands;
X	len = tail - head;
X	other_compl = NULL;
X	
X	for (; alt->alt_name; alt++) {
X	    if (len <= alt->alt_len || head[alt->alt_len] != SP) continue;
X	    index = strncmp(alt->alt_name, head, alt->alt_len);
X	    if (index < 0) continue;
X	    if (index > 0) break;
X
X	    if (alt->alt_type < 0) {
X		if (len > alt->alt_len) continue;
X		break;
X	    }
X	    
X	    if (alt->alt_type == 0) return -1; /* cannot be further compl */
X
X	    head += alt->alt_len;
X	    while (*head && *head == SP) head++;
X	    len = tail - head;
X	    temp = -1;
X	    
X	    switch (alt->alt_type) {
X	     case 1:
X		other_compl = file_completion;
X		tail = NULL;
X		temp = file_completion(head, len);
X		break;
X		
X	     case 2:
X		other_compl = file_completion;
X		sprintf(buffer, "%s.%s",
X			relative(lib_directory, "help"), head);
X		len = strlen(buffer);
X		head = buffer + len;
X		list_offset = 5;
X		temp = file_completion(buffer, len);
X		break;
X		
X	     case 3:
X		/* [set ]variable[ value] */
X		for (p = head; *p; ) 
X		    if (*p++ == SP) return -1;
X		other_compl = var_completion;
X		tail = NULL;
X		temp = var_completion(head, len);
X		break;
X		
X	     case 4:
X		/* [map XXX ]Y command[ N] */
X		for (p = head, temp = 0; *p; ) 
X		    if (*p++ == SP) {
X			while (*p && *p == SP) p++;
X			head = p;
X			temp++;
X		    }
X		if (temp != 1) return -1;
X
X		other_compl = cmd_completion;
X		tail = NULL;
X		len = p - head;
X		temp = cmd_completion(head, len);
X		break;
X	    }
X	    if (temp <= 0) other_compl = NULL;
X	    return temp;
X	}
X	
X	alt = alt_commands;
X	return 1;
X    }
X	
X    if (index) {
X	list_completion((char *)NULL);
X	if (help_alt->alt_name == NULL) help_alt = alt_commands;
X	list_offset = 0;
X	if (p = strrchr(head, ' ')) list_offset = p - head;
X	
X	while (help_alt->alt_name) {
X	    if (len > help_alt->alt_len ||
X		(index = strncmp(help_alt->alt_name, head, len)) < 0) {
X		help_alt++;
X		continue;
X	    }
X	    if (index > 0) {
X		help_alt = alt_commands;
X		break;
X	    }
X	    p = help_alt->alt_name;
X	    if (list_completion(p) == 0) break;
X	    temp = help_alt->alt_len;
X	
X	    do help_alt++;
X	    while ((q = help_alt->alt_name) && help_alt->alt_len > temp &&
X		   strncmp(p, q, temp) == 0);
X	}
X	fl;
X	list_offset = 0;
X	return 1;
X    }
X
X    for (; alt->alt_name; alt++) {
X	if (len == 0) 
X	    index = 0;
X	else
X	    index = strncmp(alt->alt_name, head, len);
X	if (index < 0) continue;
X	if (index > 0) break;
X	
X	p = alt->alt_name;
X	sprintf(tail, "%s ", p + len);
X	temp = alt->alt_len;
X	
X	do alt++;
X	while ((q = alt->alt_name) && alt->alt_len > temp &&
X	       strncmp(p, q, temp) == 0);
X	
X	return 1;
X    }
X    return 0;
X}
X
X    
Xparse_command(cmd, ok_val, initf)
Xchar *cmd;
Xint ok_val;
XFILE *initf;
X{
X    if (!split_command(cmd)) return ok_val;
X
X    if (*ARGTAIL == '!') {
X	if (run_shell(ARGTAIL+1, ok_val == AC_PROMPT)) {
X	    any_key(0);
X	    return AC_REDRAW;
X	}
X	return ok_val;
X    }
X
X    SWITCH( argv(0) ) {
X
X	CASE( "unset" ) {
X	    if (argv(1) == NULL) goto stx_err;
X	    
X	    if (set_variable(argv(1), 0, (char *)NULL))
X		return AC_REDRAW;
X	    else
X		return ok_val;
X	}
X    
X	CASE( "set" ) {
X	    if (ARGTAIL == NULL) {
X		disp_variables();
X		return AC_REDRAW;
X	    }
X
X	    cmd = argv(1);	/* get ARGTAIL right */
X	    if (set_variable(cmd, 1, ARGTAIL))
X		return AC_REDRAW;
X	    else
X		return ok_val;
X	}
X
X	CASE( "toggle" ) {
X	    if (argv(1) == NULL) goto stx_err;
X	    toggle_variable(argv(1));
X	    break;
X	}
X	
X	CASE( "define" ) {
X	    if (in_init) {
X		if (argv(1) == NULL) {
X		    init_message("macro number missing");
X		    break;
X		}
X		m_define(argv(1), initf);
X	    } else
X		if (m_define(argv(1), (FILE *)NULL))
X		    return AC_REDRAW;
X	    
X	    break;
X	}
X	    
X	CASE( "map" ) {
X	    if (argv(2) == NULL) {
X		if (do_show("map", 1))
X		    return AC_REDRAW;
X		break;
X	    }
X
X	    do_map();
X	    break;
X	}
X		
X	CASE( "cd" ) {
X	    if (change_dir(argv(1), in_init))
X		init_message("chdir %s FAILED", argv(1));
X	    
X	    break;
X	}
X	
X	if (in_init) {
X	    
X	    CASE( "load" ) {
X		if (argv(1)) load_init_file(argv(1), (FILE **)NULL);
X		break;
X	    }
X
X	    CASE( "sequence" ) {
X		return START_SEQUENCE;
X	    }
X
X	    print_command("unknown command");
X	    break;
X	}
X	
X	/* 
X	 * commands only available from : command line 
X	 */
X
X	if (ok_val != AC_REDRAW) {
X	    extern in_menu_mode;
X	    
X	    alt_cmd_key = lookup_command(sw_string, 
X				 in_menu_mode ? K_ONLY_MENU : K_ONLY_MORE);
X	    if (alt_cmd_key != K_INVALID && alt_cmd_key != K_HELP)
X		return AC_KEYCMD;
X	}
X	
X	CASE( "q" ) {
X	    break;
X	}
X	
X	CASE( "Q" ) {
X	    return AC_QUIT;
X	}
X	
X	CASE( "q!" ) {
X	    if (restore_bak())
X		return AC_QUIT;
X	    break;
X	}
X	
X	CASE( "x" ) {
X	    update_rc(current_group);
X	    return AC_QUIT;
X	}
X	
X	CASE( "help" ) {
X	    if (argv(1) == NULL)
X		display_help("help");
X	    else
X		display_help(argv(1));
X	    return AC_REDRAW;
X	}
X	
X	CASE( "man" ) {
X	    char *manual;
X	    group_header *orig_group;
X	    int orig_layout, orig_fsort;
X	    import int fmt_linenum, dont_sort_folders;
X	    
X	    manual = relative(lib_directory, "Manual");
X	    if (!file_exist(manual, "fr")) {
X		manual = relative(db_directory, "Manual");
X		if (!file_exist(manual, "fr")) {
X		    msg("Online manual is not available");
X		    break;
X		}
X	    }
X	    orig_group = current_group;
X	    orig_layout = fmt_linenum;
X	    orig_fsort = dont_sort_folders;
X	    
X	    fmt_linenum = 4;
X	    dont_sort_folders = 1;
X	    
X	    folder_menu(manual);
X	    
X	    fmt_linenum = orig_layout;
X	    dont_sort_folders = orig_fsort;
X	    init_group(orig_group);
X	    
X	    return AC_REDRAW;
X	}
X	
X	CASE( "sort" ) {
X	    if ARG(1, "age")
X		unsort_articles(0);
X	    else if (ARG(1, "no") || ARG(1, "arrival"))
X		unsort_articles(1);	    
X	    else
X		sort_articles();
X	    return AC_REORDER;
X	}
X
X	CASE( "unread" ) {
X	    if (restore_rc(current_group, argv(2) ? ARGVAL(2) : 0))
X		return AC_HEADER;
X	    break;
X	}
X	
X	CASE( "dump" ) {
X	    if (do_show(argv(1), 2))
X		return AC_REDRAW;
X	    break;
X	}
X	
X	CASE( "show" ) {
X	    if (do_show(argv(1), 2))
X		return AC_REDRAW;
X	    break;
X	}
X
X	CASE( "compile" ) {
X	    import int do_kill_handling;
X	    
X	    clrdisp();
X	    rm_kill_file();
X	    do_kill_handling = init_kill() && do_kill_handling;
X	    return AC_REDRAW;
X	}
X
X	CASE( "pwd" ) {
X	    FILE *p = popen("exec pwd", "r");
X	    char dir[FILENAME];
X	    if (p) {
X		if (fgets(dir, FILENAME, p)) {
X		    dir[strlen(dir) - 1] = NUL;
X		    msg("%s", dir);
X		}
X		pclose(p);
X	    }
X	    break;
X	}
X
X	CASE( "rmail" ) {
X	    import char *mail_box;
X	    group_header *orig_group;
X	    
X	    if (mail_box == NULL) {
X		msg("'mail' path not defined");
X		break;
X	    }
X	    
X	    orig_group = current_group;
X	    folder_menu(mail_box);
X	    init_group(orig_group);
X
X	    return AC_REDRAW;
X	}
X	
X	CASE( "mkdir" ) {
X	    char *dir, *run_mkdir();
X	    char name_buf[FILENAME];
X    
X	    if (dir = run_mkdir(argv(1), name_buf)) {
X		prompt("Change to %s", dir);
X		if (yes(0)) change_dir(dir, 0);
X	    }
X	    break;
X	}
X	
X	CASE( "sh" ) {
X	    suspend_nn();
X	    s_redraw = 0;
X	    return AC_REDRAW;
X	}
X	
X	CASE( "admin" ) {
X	    group_header *cur_group;
X	    
X	    cur_group = current_group;
X	    no_raw();
X	    clrdisp();
X	    printf("\n\n\n\rADMINISTRATION MODE\r\n\n\n");
X	    admin_mode((char *)NULL);
X	    clrdisp();
X	    raw();
X	    init_group(cur_group);
X	    return AC_REDRAW;
X	}
X	
X	CASE( "coredump" ) {
X	    no_raw();
X	    abort();
X	}
X
X	msg("unknown command: \"%s\"", argv(0));
X     }
X
X    return ok_val;
X
X stx_err:
X    print_command("syntax error");
X    return ok_val;
X}
X
X
Xstatic print_command(str)
Xchar *str;
X{
X    char **av;
X
X    if (!in_init) {
X	msg(str);
X	return;
X    }
X    
X    printf("\r%s:", str);
X    for (av = argvec; *av; av++)
X        printf(" %s", *av);
X    putchar(NL);
X}
X
X
Xstatic do_show(table, mode_arg)
Xchar *table;
Xint mode_arg;
X{
X    if (in_init || table == NULL) return 0;
X    
X    no_raw();
X 
X    SWITCH( table ) {
X	
X	CASE( "kill" ) {
X	    clrdisp();
X	    dump_kill_list();
X	    break;
X	}
X    
X	CASE( "groups" ) {
X	
X	    clrdisp();
X	    if ARG(mode_arg, "all")
X		group_overview(1);
X	    else 
X	    if ARG(mode_arg, "total")
X		group_overview(2);
X	    else
X	    if ARG(mode_arg, "unsub")
X		group_overview(3);
X	    else
X		group_overview(0);
X
X	    break;
X	}
X    
X	CASE( "map" ) {
X
X	    if (argv(mode_arg) == NULL) {
X		init_message("map name missing");
X		goto err;
X	    }
X	    
X	    if (argv(mode_arg)[0] == '#') {
X		clrdisp();
X		dump_multi_keys();
X		break;
X	    }
X	    
X	    SWITCH( argv(mode_arg) ) {
X		    
X		CASE( "key" ) {
X		    clrdisp();
X		    dump_global_map();
X		    break;
X		}
X		CASE( "menu" ) {
X		    clrdisp();
X		    dump_key_map(menu_key_map, "menu", K_ONLY_MENU);
X		    break;
X		}
X		CASE( "show" ) {
X		    clrdisp();
X		    dump_key_map(more_key_map, "show", K_ONLY_MORE);
X		    break;
X		}
X
X		init_message("unknown map '%s'", argv(mode_arg));
X		goto err;
X		/*NOTREACHED*/
X	    }
X
X	    break;
X	}
X
X	init_message("unknown table '%s'", table);
X	goto err;
X	/*NOTREACHED*/
X    }
X    
X    raw();	
X    return 1;
Xerr:    
X    raw();	
X    return 0;
X}
X
X    
Xstatic do_map()
X{
X    int code, map_menu, map_show;
X    
X    SWITCH( argv(1) ) {
X	
X	CASE( "key" ) {
X	    if (argv(3) == NULL) break;
X	    global_key_map[parse_key(argv(2))] = parse_key(argv(3));
X	    return;
X	}
X	
X	if (argv(1)[0] == '#') {
X	    char multi_buffer[16], *mb;
X	    int i, parse_key();
X	    
X	    if (!isdigit(argv(1)[1])) break;
X	    
X	    for (i = 2, mb = multi_buffer; argv(i); i++)
X		*mb++ = (char)parse_key(argv(i));
X	    *mb = NUL;
X	    
X	    enter_multi_key(K_function(argv(1)[1] - '0'),
X			    copy_str(multi_buffer));
X	    
X	    return;
X	}
X	
X	code = K_UNBOUND;
X	map_menu = map_show = 0;
X	
X	CASE( "menu" ) {
X	    map_menu++;
X	}
X	CASE( "show" ) {
X	    map_show++;
X	}
X	CASE( "both" ) {
X	    map_menu++;
X	    map_show++;
X	}
X	
X	if (map_menu) {
X	    if (argv(3))
X		code = lookup_command(argv(3), K_ONLY_MENU);
X
X	    if (code == K_MACRO)
X		if (argv(4)) 
X		    code |= atoi(argv(4));
X		else
X		    goto mac_err;
X		
X	    if (code != K_INVALID) {
X		menu_key_map[parse_key(argv(2))] = code;
X		return;
X	    }
X	}
X	
X	if (map_show) {
X	    if (argv(3))
X		code = lookup_command(argv(3), K_ONLY_MORE);
X	    
X	    if (code == K_MACRO)
X		if (argv(4)) 
X		    code |= atoi(argv(4));
X		else
X		    goto mac_err;
X		
X	    if (code != K_INVALID) {
X		more_key_map[parse_key(argv(2))] = code;
X		return;
X	    }
X	}
X
X	if (argv(4)) break;
X	
X	if (code == K_INVALID) {
X	    init_message("unknown key command: %s", argv(3));
X	    return;
X	}
X    }	
X
X    print_command("syntax error");
X    return;
X    
X mac_err:
X    print_command("macro number missing");
X    return;
X}
X
X
X
Xdisplay_help(subject)
Xchar *subject;
X{
X    char file[FILENAME];
X    
X    strcpy(file, "help.");
X    strcpy(file+5, subject);
X    
X    display_file(file, CLEAR_DISPLAY | CONFIRMATION);
X}
NO_NEWS_IS_GOOD_NEWS
chmod 0644 init.c || echo "restore of init.c fails"
set `wc -c init.c`;Sum=$1
if test "$Sum" != "15652"
then echo original size 15652, current size $Sum;fi
echo "x - extracting init.sample (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > init.sample &&
X#
X# Sample global init file
X#
X#	THIS IS JUST AN EXAMPLE OF WHAT YOU CAN DO IN THE GLOBAL
X#	SEQUENCE FILE.  DO NOT USE IT AS IS (OR YOU WILL BE IN BIG
X#	TROUBLES :-).
X
X# these are some of the variables you may want to set-up globally;
X# check with the manual to see if you really need them!
X
Xset default-save-file +$G
Xset header-lines _FOD=S
Xset mail-format
Xset newsrc
Xset pager /bin/less
Xset printer lp -s -dnews-pr
Xset retry-on-error 2
Xset save-counter .%02
X
Xsequence
X
X	# groups everybody should read first (local groups)
X< texas.
X< general
X
X	# also put local test first -- if users want to experiment, they want
X	# to see the results immediately.
X< test
X
X	# ignore some groups for ordinary users; anybody can get these
X	# by including them in their own init file.
X
X	# ignore non-local test groups
X! .test
X	# ignore offensive groups
X! .sex
X! .bizarre
X! rec.humor
X
X	# the default sequence for the other groups
X	# subgroups are presented in alphabetical order
X
X	# danish/scandinavian groups
Xdk.
Xnordunet.
X
X	# ordinary users will not get any of the following groups.
X	#
X	# they mey include a @ in their private presentation
X	# sequence to disable the '!!' operator, or they may include
X	# the (few) groups they want to see.
X!!
X
X	# european groups
X	# read eunet.general before eunet.followup and other eunet groups
Xeunet.general
Xeunet.followup
Xeunet.
X
X	# new groups are presented here
XNEW
X
X	# world groups - prefer technical groups to other groups.
Xgnu.
Xnews.
Xcomp.
Xsci.
Xbionet.
Xalt.
Xrec.
Xmisc.
Xtalk.
X
X	# delay junk (we then only see non-cross postings.)
X> junk
X
X# groups that are not mentioned above will be shown here in alphabetical
X# order
X
X
NO_NEWS_IS_GOOD_NEWS
chmod 0644 init.sample || echo "restore of init.sample fails"
set `wc -c init.sample`;Sum=$1
if test "$Sum" != "1643"
then echo original size 1643, current size $Sum;fi
echo "x - extracting install_aux (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > install_aux &&
Xset -u
Xecho
X
XOP="$1"
Xshift
XOWNER="$1"
Xshift
XGROUP="$1"
Xshift
XDIR="$1"
Xshift
XFILES="$1"
Xshift
XMODES="$1"
Xshift
X
Xcase "$OP" in
X
Xincr)
X	# increase update number
X
X	awk 'NF==3{printf "%s %s %d\n",$1,$2,$3+1}' update.h > update1.h 
X	mv update1.h update.h 
X
X	$DIR/log_entry I "$1"
X
X	echo "INSTALLATION COMPLETED"
X
X	if [ -n "$2" ]
X	then
X		echo
X		echo "--------------------------------------------------------"
X		if [ -f $2/MASTER ]
X		then
X			echo "Remember to restart $DIR/nnmaster"
X		else
X			echo "Now run 'make initdb'"
X		fi
X		echo "--------------------------------------------------------"
X	fi
X	;;
X
Xbin)
X	LINKS="$1"
X
X	echo Installing user programs in $DIR:
X	echo "   " $FILES $LINKS
X
X	if [ -f $DIR/nn ]
X	then 
X	     (
X		cd $DIR
X		mv nn nn.old 
X		rm -f $FILES $LINKS
X	     )
X	fi
X
X	cp $FILES $DIR
X
X	for link in $LINKS
X	do
X		ln $DIR/nn $DIR/$link
X	done
X	;;
X
Xaux)
X	echo Installing $OP files in $DIR:
X	echo "   " $FILES
X
X	if [ ! -d $DIR ]
X	then
X		mkdir $DIR
X		chown $OWNER $DIR
X		chgrp $GROUP $DIR
X		chmod 755 $DIR 
X		echo "   " Created directory $DIR
X	fi
X
X	cp $FILES $DIR
X	;;
X
Xhelp)
X	echo Installing $OP files in $DIR:
X	echo "   " $FILES
X
X	for h in $FILES
X	do
X		./cvt-help < $h > $DIR/$h
X	done
X	;;
X
Xmaster)
X	MASTER="$FILES"
X	echo Installing $MASTER in $DIR:
X
X	if [ -f $DIR/$MASTER ]
X	then
X	    (
X		cd $DIR
X		if [ -f MPID ]
X		then
X			echo "Stopping running master..."
X			kill -1 `cat MPID`
X			sleep 5
X		fi
X		mv $MASTER ${MASTER}.old
X	   )
X	fi
X
X	cp $FILES $DIR
X	;;
X
X1*)
X	echo Installing manual section $FILES in $DIR
X
X	NEW=""
X
X	if [ -d $DIR ]
X	then
X		for i in *.$OP
X		do
X			MAN=`basename ${i} .$OP`
X			cp $i $DIR/${MAN}.$FILES
X			NEW="$NEW ${MAN}.$FILES"
X		done
X
X		FILES="$NEW"
X	else
X		echo $DIR not found
X		exit 0
X	fi
X	;;
X
Xonline)
X	if [ ! -d $DIR ]
X	then
X		echo You must install the package first
X		exit 0
X	fi
X
X	echo Formatting online manual....
X	rm -f $DIR/Manual
X	sh mk_online_man $FILES > $DIR/Manual
X	echo Done
X
X	FILES="Manual"
X	;;
X
Xdb)
X	if [ ! -d $DIR ]
X	then
X		echo Creating Database Directory $DIR
X		mkdir $DIR
X	fi
X
X	if [ ! -d $DIR/DATA ]
X	then
X		mkdir $DIR/DATA
X	fi
X	;;
X
Xinit)
X	echo Running $FILES to initialize database.
X	echo
X	$DIR/$FILES $1
X	echo
X	echo "Now start $DIR/$FILES -r"
X	exit 0
X	;;
Xesac
X
Xcd $DIR 
Xchown $OWNER $FILES
Xchgrp $GROUP $FILES
Xchmod $MODES $FILES
X
Xexit 0
NO_NEWS_IS_GOOD_NEWS
chmod 0644 install_aux || echo "restore of install_aux fails"
set `wc -c install_aux`;Sum=$1
if test "$Sum" != "2276"
then echo original size 2276, current size $Sum;fi
echo "x - extracting keymap.c (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > keymap.c &&
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 *	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_UNBOUND, 
X/* BS  ^H */		K_PREV_PAGE, 
X/* TAB ^I */	K_UNBOUND, 
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_UNBOUND, 
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_UNBOUND, 
X/* b   */	K_UNBOUND, 
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 *	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 *
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_UNBOUND, 
X/* BS  ^H */		K_PREV_LINE,
X/* TAB ^I */	K_UNBOUND, 
X/* NL  ^J */		K_CONTINUE,
X/* VT  ^K */	K_UNBOUND, 
X/* FF  ^L */		K_REDRAW,
X/* CR  ^M */		K_CONTINUE,
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_UNBOUND, 
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_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_UNBOUND, 
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_UNBOUND, 
X/* K   */		K_KILL_HANDLING,
X/* L   */		K_LAYOUT,
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-group",		K_ADVANCE_GROUP,	0,
X
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
X    "find",			K_GOTO_MATCH,		K_ONLY_MORE,
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    "kill-select",		K_KILL_HANDLING,	0,
X
X    "layout",			K_LAYOUT,		K_ONLY_MENU,
X    "leave-article",		K_LEAVE_ARTICLE,	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
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 char 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	    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
Xparse_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 CTRL(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)
Xint 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 int 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 c, 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}
NO_NEWS_IS_GOOD_NEWS
chmod 0644 keymap.c || echo "restore of keymap.c fails"
set `wc -c keymap.c`;Sum=$1
if test "$Sum" != "16844"
then echo original size 16844, current size $Sum;fi
echo "x - extracting keymap.h (Text)"
sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > keymap.h &&
X/*
X * keyboard (re)mapping
X *
X * you cannot assign alternative commands to the "article identifier"
X * keys in the selection mode
X */
X
X#define K_INVALID		0x0000 /* unknown command (for lookup) */
X
X#define K_UNBOUND		0x0001 /* unbound command key 		*/
X
X#define K_REDRAW		0x0002 /* redraw 			*/
X#define K_CONTINUE		0x0003 /* continue with next ... 	*/
X#define K_LAST_MESSAGE		0x0004 /* repeat last message 		*/
X#define K_HELP			0x0005 /* online help 			*/
X#define K_SHELL			0x0006 /* shell escape 		*/
X#define K_VERSION		0x0007 /* print version 		*/
X#define K_EXTENDED_CMD		0x0008 /* extended commands		*/
X
X#define K_QUIT			0x0009 /* quit 			*/
X
X#define K_SAVE_NO_HEADER 	0x0011 /* save articles without header */
X#define K_SAVE_SHORT_HEADER 	0x0012 /* save article with short header */
X#define K_SAVE_FULL_HEADER 	0x0013 /* save articles with full header */
X
X#define K_PRINT			0x0014 /* print ariticle 		*/
X
X#define K_UNSHAR		0x0015 /* unshar article		*/
X
X#define K_REPLY			0x0016 /* reply to article 		*/
X#define K_FOLLOW_UP		0x0017 /* follow up to article 	*/
X#define K_POST			0x0018 /* post an article		*/
X#define K_MAIL_OR_FORWARD 	0x0019 /* mail (forward article) 	*/
X#define K_CANCEL		0x001a /* cancel article 		*/
X#define K_UNSUBSCRIBE		0x001b /* (un)subscribe to group 	*/
X#define K_GROUP_OVERVIEW 	0x001c /* group overview 		*/
X#define K_PATCH			0x001d /* pipe article to patch         */
X
X#define K_GOTO_GROUP		0x0020 /* goto named group/folder	*/
X
X#define K_KILL_HANDLING		0x0021 /* enter kill menu		*/
X
X    /* scrolling/menu movement */
X
X#define K_NEXT_PAGE		0x0024 /* next page 			*/
X#define K_NEXT_HALF_PAGE 	0x0025 /* next half page		*/
X#define K_NEXT_LINE		0x0026 /* next line			*/
X#define K_PREV_PAGE		0x0027 /* previous page 		*/
X#define K_PREV_HALF_PAGE 	0x0028 /* previous half page		*/
X#define K_PREV_LINE		0x0029 /* previous line		*/
X
X#define K_HEADER_PAGE		0x002a /* first page incl. header	*/
NO_NEWS_IS_GOOD_NEWS
echo "End of part 5"
echo "File keymap.h is continued in part 6"
echo "6" > s2_seq_.tmp
exit 0

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.