home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
3
/
3898
< prev
next >
Wrap
Internet Message Format
|
1991-08-23
|
51KB
Path: wupost!uunet!mcsun!unido!estevax!norisc!iain
From: iain@norisc.UUCP (Iain Lea)
Newsgroups: alt.sources
Subject: tin v1.00 - YAN (Yet Another Newsreader) Part 02/08
Message-ID: <583@norisc.UUCP>
Date: 23 Aug 91 13:51:40 GMT
Sender: iain@norisc.UUCP (Iain Lea)
Organization: What organization?
Lines: 2261
Submitted-by: iain@estevax.uucp
Archive-name: tin/part02
#!/bin/sh
# this is tin.shar.02 (part 2 of tin)
# do not concatenate these parts, unpack them in order with /bin/sh
# file art.c continued
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
if test ! -r shar3_seq_.tmp; then
echo "Please unpack part 1 first!"
exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
echo "Please unpack part $Scheck next!"
exit 1
else
exit 0
fi
) < shar3_seq_.tmp || exit 1
echo "x - Continuing file art.c"
sed 's/^X//' << 'SHAR_EOF' >> art.c &&
X return -1;
X }
X /* s1->from greater than s2->from */
X if (strcmp (s1->from, s2->from) > 0) {
X return 1;
X }
X return 0;
X}
X
X
Xint date_comp (s1, s2)
X struct header *s1;
X struct header *s2;
X{
X /* s1->date less than s2->date */
X if (strcmp (s1->date, s2->date) < 0) {
X return -1;
X }
X /* s1->date greater than s2->date */
X if (strcmp (s1->date, s2->date) > 0) {
X return 1;
X }
X return 0;
X}
X
X
Xset_article (art)
X struct header *art;
X{
X art->subject = (char *) 0;
X art->from = (char *) 0;
X art->date[0] = '\0';
X art->archive = (char *) 0;
X art->part = (char *) 0;
X art->patch = (char *) 0;
X art->unread = ART_UNREAD;
X art->inthread = FALSE;
X art->tagged = FALSE;
X}
SHAR_EOF
echo "File art.c is complete" &&
$TOUCH -am 0822182791 art.c &&
chmod 0600 art.c ||
echo "restore of art.c failed"
set `wc -c art.c`;Wc_c=$1
if test "$Wc_c" != "23276"; then
echo original size 23276, current size $Wc_c
fi
# ============= curses.c ==============
echo "x - extracting curses.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > curses.c &&
X/*
X * curses.c
X */
X
X/*
X * This is a screen management library borrowed with permission from the
X * Elm mail system (a great mailer--I highly recommend it!).
X *
X * I've hacked this library to only provide what Tass needs.
X *
X * Original copyright follows:
X */
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $
X *
X * Copyright (c) 1986 Dave Taylor
X ******************************************************************************/
X
X#include <stdio.h>
X#include <curses.h>
X#include <sys/ioctl.h>
X
X#ifdef TRUE
X#undef TRUE
X#define TRUE 1
X#endif
X
X#ifdef FALSE
X#undef FALSE
X#define FALSE 0
X#endif
X
X#define BACKSPACE '\b'
X#define VERY_LONG_STRING 2500
X
Xint LINES=23;
Xint COLS=80;
X
Xint inverse_okay = TRUE;
X
X#ifdef BSD
X# ifndef BSD4_1
X# include <sgtty.h>
X# else
X# include <termio.h>
X# endif
X#else
X# ifndef SYSV
X# include <termio.h>
X# endif
X#endif
X
X
X#include <ctype.h>
X
X/*
X#ifdef BSD
X#undef tolower
X#endif
X*/
X
X#define TTYIN 0
X
X#ifdef SHORTNAMES
X# define _clearinverse _clrinv
X# define _cleartoeoln _clrtoeoln
X# define _cleartoeos _clr2eos
X#endif
X
X#ifndef BSD
Xstruct termio _raw_tty,
X _original_tty;
X#else
X#define TCGETA TIOCGETP
X#define TCSETAW TIOCSETP
X
Xstruct sgttyb _raw_tty,
X _original_tty;
X#endif
X
Xstatic int _inraw = 0; /* are we IN rawmode? */
X
X#define DEFAULT_LINES_ON_TERMINAL 24
X#define DEFAULT_COLUMNS_ON_TERMINAL 80
X
Xstatic
Xchar *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
X *_setinverse, *_clearinverse, *_setunderline, *_clearunderline;
X
Xstatic
Xint _lines,_columns;
X
Xstatic char _terminal[1024]; /* Storage for terminal entry */
Xstatic char _capabilities[1024]; /* String for cursor motion */
X
Xstatic char *ptr = _capabilities; /* for buffering */
X
Xint outchar(); /* char output for tputs */
Xchar *tgetstr(), /* Get termcap capability */
X *tgoto(); /* and the goto stuff */
X
Xint InitScreen()
X{
X int tgetent(), /* get termcap entry */
X err;
X char termname[40];
X char *strcpy(), *getenv();
X
X if (getenv("TERM") == NULL) {
X fprintf(stderr,
X "TERM variable not set; Tass requires screen capabilities\n");
X return(FALSE);
X }
X if (strcpy(termname, getenv("TERM")) == NULL) {
X fprintf(stderr,"Can't get TERM variable\n");
X return(FALSE);
X }
X if ((err = tgetent(_terminal, termname)) != 1) {
X fprintf(stderr,"Can't get entry for TERM\n");
X return(FALSE);
X }
X
X /* load in all those pesky values */
X _clearscreen = tgetstr("cl", &ptr);
X _moveto = tgetstr("cm", &ptr);
X _cleartoeoln = tgetstr("ce", &ptr);
X _cleartoeos = tgetstr("cd", &ptr);
X _lines = tgetnum("li");
X _columns = tgetnum("co");
X _setinverse = tgetstr("so", &ptr);
X _clearinverse = tgetstr("se", &ptr);
X _setunderline = tgetstr("us", &ptr);
X _clearunderline = tgetstr("ue", &ptr);
X
X if (!_clearscreen) {
X fprintf(stderr,
X "Terminal must have clearscreen (cl) capability\n");
X return(FALSE);
X }
X if (!_moveto) {
X fprintf(stderr,
X "Terminal must have cursor motion (cm)\n");
X return(FALSE);
X }
X if (!_cleartoeoln) {
X fprintf(stderr,
X "Terminal must have clear to end-of-line (ce)\n");
X return(FALSE);
X }
X if (!_cleartoeos) {
X fprintf(stderr,
X "Terminal must have clear to end-of-screen (cd)\n");
X return(FALSE);
X }
X if (_lines == -1)
X _lines = DEFAULT_LINES_ON_TERMINAL;
X if (_columns == -1)
X _columns = DEFAULT_COLUMNS_ON_TERMINAL;
X return(TRUE);
X}
X
Xvoid ScreenSize(num_lines, num_columns)
X int *num_lines, *num_columns;
X{
X /** returns the number of lines and columns on the display. **/
X
X if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
X if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
X
X *num_lines = _lines - 1; /* assume index from zero*/
X *num_columns = _columns; /* assume index from one */
X}
X
Xvoid ClearScreen()
X{
X /* clear the screen: returns -1 if not capable */
X
X tputs(_clearscreen, 1, outchar);
X fflush(stdout); /* clear the output buffer */
X}
X
Xvoid MoveCursor(row, col)
Xint row, col;
X{
X /** move cursor to the specified row column on the screen.
X 0,0 is the top left! **/
X
X char *stuff, *tgoto();
X
X stuff = tgoto(_moveto, col, row);
X tputs(stuff, 1, outchar);
X fflush(stdout);
X}
X
Xvoid CleartoEOLN()
X{
X /** clear to end of line **/
X
X tputs(_cleartoeoln, 1, outchar);
X fflush(stdout); /* clear the output buffer */
X}
X
Xvoid CleartoEOS()
X{
X /** clear to end of screen **/
X
X tputs(_cleartoeos, 1, outchar);
X fflush(stdout); /* clear the output buffer */
X}
X
X
Xvoid StartInverse()
X{
X /** set inverse video mode **/
X
X if (_setinverse && inverse_okay)
X tputs(_setinverse, 1, outchar);
X/* fflush(stdout); */
X}
X
X
Xvoid EndInverse()
X{
X /** compliment of startinverse **/
X
X if (_clearinverse && inverse_okay)
X tputs(_clearinverse, 1, outchar);
X/* fflush(stdout); */
X}
X
X
Xint RawState()
X{
X /** returns either 1 or 0, for ON or OFF **/
X
X return( _inraw );
X}
X
X
Xvoid Raw(state)
X int state;
X{
X /** state is either TRUE or FALSE, as indicated by call **/
X
X if (state == FALSE && _inraw) {
X (void) ioctl(TTYIN, TCSETAW, &_original_tty);
X _inraw = 0;
X }
X else if (state == TRUE && ! _inraw) {
X
X (void) ioctl(TTYIN, TCGETA, &_original_tty); /** current setting **/
X
X (void) ioctl(TTYIN, TCGETA, &_raw_tty); /** again! **/
X#ifdef BSD
X _raw_tty.sg_flags &= ~(ECHO | CRMOD); /* echo off */
X _raw_tty.sg_flags |= CBREAK; /* raw on */
X#else
X _raw_tty.c_lflag &= ~(ICANON | ECHO); /* noecho raw mode */
X
X _raw_tty.c_cc[VMIN] = '\01'; /* minimum # of chars to queue */
X _raw_tty.c_cc[VTIME] = '\0'; /* minimum time to wait for input */
X#endif
X
X (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
X
X _inraw = 1;
X }
X}
X
Xint ReadCh()
X{
X /** read a character with Raw mode set! **/
X
X register int result;
X char ch;
X result = read(0, &ch, 1);
X return((result <= 0 ) ? EOF : ch & 0x7F);
X}
X
X
Xint outchar(c)
Xchar c;
X{
X /** output the given character. From tputs... **/
X /** Note: this CANNOT be a macro! **/
X
X putc(c, stdout);
X}
X
SHAR_EOF
$TOUCH -am 0819150191 curses.c &&
chmod 0600 curses.c ||
echo "restore of curses.c failed"
set `wc -c curses.c`;Wc_c=$1
if test "$Wc_c" != "6075"; then
echo original size 6075, current size $Wc_c
fi
# ============= debug.c ==============
echo "x - extracting debug.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > debug.c &&
X/*
X * Project : tin - a visual threaded usenet newsreader
X * Module : debug.c
X * Author : I.Lea
X * Created : 01-04-91
X * Updated : 22-08-91
X * Release : 1.0
X * Notes : debug routines
X * Copyright : (c) Copyright 1991 by Iain Lea
X * You may freely copy or redistribute this software,
X * so long as there is no profit made from its use, sale
X * trade or reproduction. You may not change this copy-
X * right notice, and it must be included in any copy made
X */
X
X#include "tin.h"
X
Xint debug;
X
X
Xdebug_print_arts ()
X{
X int i;
X
X if (! debug)
X return;
X
X for (i = 0; i < top; i++) { /* for each group */
X debug_print_header (&arts[i]);
X }
X}
X
X
Xvoid debug_print_header (s)
X struct header *s;
X{
X FILE *fp;
X
X if (! debug)
X return;
X
X if ((fp = fopen ("/tmp/DUMP","a+")) != NULL) {
X fprintf (fp,"art=[%5ld] killed=[%s]\n", s->artnum,
X (s->tagged ? "TRUE" : "FALSE"));
X fprintf (fp,"subj=[%-38s] from=[%-20s]\n", s->subject, s->from);
X fprintf (fp,"arch=[%-38s] part=[%s] patch=[%s]\n", s->archive, s->part, s->patch);
X fprintf (fp,"thread=[%s] inthread=[%s] unread=[%s]\n",
X (s->thread == ART_NORMAL ? "ART_NORMAL" : "ART_EXPIRED"),
X (s->inthread ? "TRUE" : "FALSE"),
X (s->unread ? "TRUE" : "FALSE"));
X fflush (fp);
X fclose (fp);
X chmod ("/tmp/DUMP", 0666);
X }
X}
X
X
Xdebug_print_comment (comment)
X char *comment;
X{
X FILE *fp;
X
X if (! debug)
X return;
X
X if ((fp = fopen ("/tmp/BASE","a+")) != NULL) {
X fprintf (fp,"\n%s\n\n", comment);
X fflush (fp);
X fclose (fp);
X chmod ("/tmp/BASE", 0666);
X }
X}
X
X
Xvoid debug_print_base ()
X{
X FILE *fp;
X int i;
X
X if (! debug)
X return;
X
X if ((fp = fopen ("/tmp/BASE","a+")) != NULL) {
X for (i = 0; i < top_base; i++) {
X fprintf (fp, "base[%3d]=[%5ld]\n",i,base[i]);
X }
X fflush (fp);
X fclose (fp);
X chmod ("/tmp/BASE", 0666);
X }
X}
X
X
Xvoid debug_print_active ()
X{
X FILE *fp;
X int i;
X
X if (! debug)
X return;
X
X if ((fp = fopen ("/tmp/ACTIVE","w")) != NULL) {
X for (i = 0; i < num_active; i++) { /* for each group */
X fprintf (fp, "[%4d]=[%-28s] max=[%4ld] min=[%4ld] nxt=[%4d] flag=[%d]\n",
X i, active[i].name, active[i].max, active[i].min, active[i].next, active[i].flag);
X }
X fflush (fp);
X fclose (fp);
X chmod ("/tmp/ACTIVE", 0666);
X }
X}
SHAR_EOF
$TOUCH -am 0822123191 debug.c &&
chmod 0600 debug.c ||
echo "restore of debug.c failed"
set `wc -c debug.c`;Wc_c=$1
if test "$Wc_c" != "2276"; then
echo original size 2276, current size $Wc_c
fi
# ============= group.c ==============
echo "x - extracting group.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > group.c &&
X/*
X * Project : tin - a visual threaded usenet newsreader
X * Module : group.c
X * Author : R.Skrenta / I.Lea
X * Created : 01-04-91
X * Updated : 13-08-91
X * Release : 1.0
X * Notes :
X * Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
X * You may freely copy or redistribute this software,
X * so long as there is no profit made from its use, sale
X * trade or reproduction. You may not change this copy-
X * right notice, and it must be included in any copy made
X */
X
X#include "tin.h"
X
Xextern char cvers[LEN+1];
Xextern int cur_groupnum;
Xextern int last_resp; /* page.c */
Xextern int this_resp; /* page.c */
Xextern int space_mode; /* select.c */
X
Xchar *glob_group;
Xint index_point;
Xint first_subj_on_screen;
Xint last_subj_on_screen;
X
X
X#ifdef SIGTSTP
Xvoid group_susp (sig)
X int sig;
X{
X Raw(FALSE);
X putchar('\n');
X signal(SIGTSTP, SIG_DFL);
X#ifdef BSD
X sigsetmask(sigblock(0) & ~(1 << (SIGTSTP -1)));
X#endif
X kill(0, SIGTSTP);
X
X signal(SIGTSTP, group_susp);
X
X if (! update) {
X Raw(TRUE);
X }
X
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X mail_setup();
X show_group_page(glob_group);
X}
X#endif
X
X
Xvoid group_page (group)
X char *group;
X{
X char buf[LEN+1];
X char group_path[LEN+1];
X char ch;
X char *p;
X int flag, i, n;
X int kill_state;
X long old_artnum;
X int old_top;
X int ret1, ret2;
X int sav_groupnum;
X int thread_marked_unread = FALSE;
X
X glob_group = group;
X sav_groupnum = cur_groupnum;
X
X strcpy (group_path, group); /* turn comp.unix.amiga into */
X for (p = group_path; *p; p++) /* comp/unix/amiga */
X if (*p == '.')
X *p = '/';
X
X last_resp = -1;
X this_resp = -1;
X index_group (group, group_path); /* update index file */
X read_newsrc_line (group); /* get sequencer information */
X
X if (space_mode) {
X for (i = 0; i < top_base; i++) {
X if (new_responses (i)) {
X break;
X }
X }
X if (i < top_base) {
X index_point = i;
X } else {
X index_point = top_base - 1;
X }
X } else {
X index_point = top_base - 1;
X }
X
X clear_note_area ();
X
X show_group_page (group);
X
X while (1) {
X ch = ReadCh();
X
X if (ch > '0' && ch <= '9') { /* 0 goes to basenote */
X prompt_subject_num(ch, group);
X } else switch (ch) {
X case '!':
X shell_escape ();
X show_group_page (group);
X break;
X
X case '$': /* show last page of articles */
Xend_of_list:
X index_point = top_base - 1;
X show_group_page (group);
X break;
X
X case '-': /* go to last viewed article */
X if (this_resp < 0) {
X info_message(txt_no_last_message);
X break;
X }
X index_point = show_page (this_resp, group, group_path);
X if (index_point < 0) {
X space_mode = FALSE;
X goto group_done;
X }
X clear_note_area ();
X show_group_page (group);
X break;
X
X case '/': /* forward/backward search */
X case '?':
X i = (ch == '/');
X search_subject (i, group);
X break;
X
X case '\r':
X case '\n': /* read current basenote */
X if (index_point < 0) {
X info_message(txt_no_arts);
X break;
X }
X i = (int) base[index_point];
X index_point = show_page(i, group, group_path);
X if (index_point < 0) {
X space_mode = FALSE;
X goto group_done;
X }
X clear_note_area ();
X show_group_page (group);
X break;
X
X case '\t':
X space_mode = TRUE;
X
X if (index_point < 0
X || (n=next_unread((int) base[index_point]))<0) {
X for (i = cur_groupnum+1;
X i < local_top; i++)
X if (unread[i] > 0)
X break;
X if (i >= local_top)
X goto group_done;
X
X cur_groupnum = i;
X index_point = -3;
X goto group_done;
X }
X index_point = show_page(n, group, group_path);
X if (index_point < 0)
X goto group_done;
X clear_note_area ();
X show_group_page(group);
X break;
X
X case 27: /* common arrow keys */
X ch = ReadCh();
X if (ch == '[' || ch == 'O')
X ch = ReadCh();
X switch (ch) {
X case 'A':
X case 'D':
X goto group_up;
X
X case 'B':
X case 'C':
X goto group_down;
X
X case 'G': /* ansi PgDn */
X case 'U': /* at386 PgDn */
X goto group_page_down;
X
X case 'I': /* ansi PgUp */
X case 'V': /* at386 PgUp */
X goto group_page_up;
X
X case 'H': /* at386 Home */
X index_point = 0;
X show_group_page (group);
X break;
X
X case 'F': /* ansi End */
X case 'Y': /* at386 End */
X goto end_of_list;
X }
X break;
X
X case ctrl('D'): /* page down */
X case ' ':
Xgroup_page_down:
X if (!top_base || index_point == top_base - 1)
X break;
X
X erase_subject_arrow();
X index_point += NOTESLINES / 2;
X if (index_point >= top_base)
X index_point = top_base - 1;
X
X if (index_point < first_subj_on_screen
X || index_point >= last_subj_on_screen)
X show_group_page(group);
X else
X draw_subject_arrow();
X break;
X
X case ctrl('K'): /* kill article */
X if (index_point < 0) {
X info_message (txt_no_arts);
X break;
X }
X if (kill_articles) {
X old_top = top;
X n = base[index_point];
X old_artnum = arts[n].artnum;
X if (kill_art_menu (group, (int) base[index_point])) {
X kill_any_articles (group);
X reload_index_file (group, TRUE);
X index_point = find_new_pos (old_top, old_artnum, index_point);
X }
X show_group_page (group);
X } else {
X info_message (txt_switch_on_kill_art_menu);
X }
X break;
X
X case ctrl('L'): /* return to index */
X case ctrl('R'):
X case ctrl('W'):
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X show_group_page(group);
X break;
X
X case ctrl('N'):
X case 'j': /* line down */
Xgroup_down:
X if (!top_base || index_point + 1 >= top_base)
X break;
X
X if (index_point + 1 >= last_subj_on_screen) {
X#ifndef USE_CLEARSCREEN
X erase_subject_arrow();
X#endif
X index_point++;
X show_group_page(group);
X } else {
X erase_subject_arrow();
X index_point++;
X draw_subject_arrow();
X }
X break;
X
X case ctrl('P'):
X case 'k': /* line up */
Xgroup_up:
X if (!top_base || !index_point)
X break;
X
X if (index_point <= first_subj_on_screen) {
X index_point--;
X show_group_page(group);
X } else {
X erase_subject_arrow();
X index_point--;
X draw_subject_arrow();
X }
X break;
X
X case ctrl('U'): /* page up */
X case 'b':
Xgroup_page_up:
X if (!top_base)
X break;
X
X#ifndef USE_CLEARSCREEN
X clear_message ();
X#endif
X erase_subject_arrow();
X index_point -= NOTESLINES / 2;
X if (index_point < 0)
X index_point = 0;
X if (index_point < first_subj_on_screen
X || index_point >= last_subj_on_screen)
X show_group_page(group);
X else
X draw_subject_arrow();
X break;
X
X case 'a': /* author search forward */
X case 'A': /* author search backward */
X if (index_point < 0) {
X info_message(txt_no_arts);
X break;
X }
X
X i = (ch == 'a');
X
X n = search_author((int) base[index_point], i);
X if (n < 0)
X break;
X
X index_point = show_page(n, group, group_path);
X if (index_point < 0) {
X space_mode = FALSE;
X goto group_done;
X }
X clear_note_area ();
X show_group_page (group);
X break;
X
X case 'B': /* bug/gripe/comment mailed to author */
X mail_bug_report ();
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X show_group_page (group);
X break;
X
X case 'c': /* catchup--mark all articles as read */
X if (prompt_yn (LINES, txt_mark_all_read, 'y')) {
X for (n = 0; n < top; n++) {
X arts[n].unread = ART_READ;
X }
X if (cur_groupnum + 1 < local_top) {
X cur_groupnum++;
X }
X goto group_done;
X }
X break;
X
X case 'g': /* choose a new group by name */
X n = choose_new_group ();
X if (n >= 0 && n != cur_groupnum) {
X cur_groupnum = n;
X index_point = -3;
X goto group_done;
X }
X break;
X
X case 'h':
X help_group_commands ();
X show_group_page (group);
X break;
X
X case 'H':
X help_group_info ();
X show_group_page (group);
X break;
X
X case 'I': /* toggle inverse video */
X inverse_okay = !inverse_okay;
X if (inverse_okay)
X info_message(txt_inverse_on);
X else
X info_message(txt_inverse_off);
X show_group_page(group);
X break;
X
X case 'K': /* mark rest of thread as read */
X if (index_point < 0) {
X info_message (txt_no_next_unread_art);
X break;
X }
X if (new_responses (index_point)) {
X for (i = base[index_point]; i >= 0; i = arts[i].thread)
X arts[i].unread = 0;
X if (draw_arrow_mark) {
X MoveCursor(INDEX_TOP + (index_point - first_subj_on_screen), 8);
X putchar(' ');
X MoveCursor (LINES, 0);
X fflush(stdout);
X } else {
X i = index_point-first_subj_on_screen;
X screen[i].col[8] = ' ';
X draw_subject_arrow();
X }
X flag = FALSE;
X } else
X flag = TRUE;
X
X n = next_unread (next_response ((int) base[index_point]));
X if (n < 0) {
X if (flag)
X info_message (txt_no_next_unread_art);
X else
X MoveCursor (LINES, 0);
X break;
X }
X
X if ((n = which_base(n)) < 0) {
X info_message("Internal error: K which_base < 0");
X break;
X }
X
X if (n >= last_subj_on_screen) {
X index_point = n;
X show_group_page(group);
X } else {
X erase_subject_arrow();
X index_point = n;
X draw_subject_arrow();
X }
X break;
X
X case 'M': /* options menu */
X old_top = top;
X n = base[index_point];
X old_artnum = arts[n].artnum;
X n = sort_art_type;
X kill_state = change_rcfile (group, TRUE);
X if (kill_state == NO_KILLING && n != sort_art_type) {
X make_threads (TRUE);
X find_base ();
X }
X index_point = find_new_pos (old_top, old_artnum, index_point);
X show_group_page (group);
X break;
X
X case 'n': /* next group */
X clear_message();
X if (cur_groupnum + 1 >= local_top)
X info_message(txt_no_more_groups);
X else {
X cur_groupnum++;
X index_point = -3;
X space_mode = FALSE;
X goto group_done;
X }
X break;
X
X case 'N': /* go to next unread article */
X if (index_point < 0) {
X info_message(txt_no_next_unread_art);
X break;
X }
X
X n = next_unread( (int) base[index_point]);
X if (n == -1)
X info_message(txt_no_next_unread_art);
X else {
X index_point = show_page(n, group, group_path);
X if (index_point < 0) {
X space_mode = FALSE;
X goto group_done;
X }
X clear_note_area ();
X show_group_page(group);
X }
X break;
X
X case 'p': /* previous group */
X clear_message();
X if (cur_groupnum <= 0)
X info_message(txt_no_prev_group);
X else {
X cur_groupnum--;
X index_point = -3;
X space_mode = FALSE;
X goto group_done;
X }
X break;
X
X case 'P': /* go to previous unread article */
X if (index_point < 0) {
X info_message(txt_no_prev_unread_art);
X break;
X }
X n = prev_response( (int) base[index_point]);
X n = prev_unread(n);
X if (n == -1)
X info_message(txt_no_prev_unread_art);
X else {
X index_point = show_page (n, group, group_path);
X if (index_point < 0) {
X space_mode = FALSE;
X goto group_done;
X }
X clear_note_area ();
X show_group_page(group);
X }
X break;
X
X case 'q': /* quit */
X index_point = -2;
X space_mode = FALSE;
X goto group_done;
X
X case 's': /* subscribe to this group */
X subscribe(group, ':', my_group[cur_groupnum], TRUE);
X sprintf(buf, txt_subscribed_to, group);
X info_message(buf);
X break;
X
X case 'S': /* save regex pattern to file/s */
X n = save_regex_arts (group_path, group);
X ret1 = post_process_files ();
X ret2 = untag_all_articles ();
X if (ret1 || ret2 || n) {
X show_group_page (group);
X }
X free_save_array ();
X break;
X
X case 't':
X case 'i': /* return to group selection page */
X goto group_done;
X
X case 'T': /* tag/untag article for saving */
X if (index_point >= 0) {
X if (arts[base[index_point]].tagged) {
X arts[base[index_point]].tagged = 0;
X show_group_page (group);
X info_message ("untagged");
X } else {
X arts[base[index_point]].tagged = ++num_of_tagged_files;
X show_group_page (group);
X info_message ("tagged for saving");
X }
X }
X break;
X
X case 'u': /* unsubscribe to this group */
X subscribe(group, '!', my_group[cur_groupnum], TRUE);
X sprintf(buf, txt_unsubscribed_to, group);
X info_message(buf);
X break;
X
X case 'U': /* untag all articles */
X if (index_point >= 0) {
X untag_all_articles ();
X show_group_page (group);
X }
X break;
X
X case 'v':
X info_message (cvers);
X break;
X
X case 'w': /* post a basenote */
X post_base (group);
X update_newsrc (group, my_group[cur_groupnum]);
X index_group (group, group_path);
X read_newsrc_line (group);
X index_point = top_base - 1;
X show_group_page (group);
X break;
X
X case 'W': /* display messages posted by user */
X if (user_posted_messages ()) {
X show_group_page(group);
X }
X break;
X
X case 'z': /* mark article as unread (to return) */
X if (index_point < 0) {
X info_message (txt_no_arts);
X break;
X }
X i = base[index_point];
X arts[i].unread = ART_UNREAD;
X i = index_point-first_subj_on_screen;
X screen[i].col[8] = '+';
X if (draw_arrow_mark) {
X MoveCursor(INDEX_TOP + (index_point - first_subj_on_screen), 8);
X putchar ('+');
X } else {
X draw_subject_arrow();
X }
X info_message(txt_art_marked_as_unread);
X break;
X
X case 'Z': /* mark thread as unread */
X if (index_point < 0) {
X info_message (txt_no_arts);
X break;
X }
X for (i = base[index_point] ; i != -1 ; i = arts[i].thread) {
X arts[i].unread = ART_UNREAD;
X thread_marked_unread = TRUE;
X }
X if (thread_marked_unread) {
X i = index_point-first_subj_on_screen;
X screen[i].col[8] = '+';
X if (draw_arrow_mark) {
X MoveCursor(INDEX_TOP + (index_point - first_subj_on_screen), 8);
X putchar ('+');
X } else {
X draw_subject_arrow();
X }
X info_message(txt_thread_marked_as_unread);
X thread_marked_unread = FALSE;
X }
X break;
X
X default:
X info_message(txt_bad_command);
X }
X }
X
Xgroup_done:
X fix_new_highest (sav_groupnum);
X update_newsrc (group, my_group[sav_groupnum]);
X clear_note_area ();
X
X if (index_point == -2)
X tin_done(0);
X}
X
X
X/*
X * Correct highest[] for the group selection page display since
X * new articles may have been read or marked unread
X */
X
Xvoid fix_new_highest (groupnum)
X int groupnum;
X{
X register int i;
X int sum = 0;
X
X for (i = 0; i < top; i++) {
X if (arts[i].unread) {
X sum++;
X }
X }
X
X unread[groupnum] = sum;
X}
X
X
Xvoid show_group_page (group)
X char *group;
X{
X char new_resps[8];
X char resps[8];
X char from[LEN+1];
X char subject[LEN+1];
X int i, j;
X int n;
X int respnum;
X
X#ifdef SIGTSTP
X signal(SIGTSTP, group_susp);
X#endif
X
X#ifdef USE_CLEARSCREEN
X ClearScreen();
X#else
X MoveCursor(0, 0); /* top left corner */
X CleartoEOLN ();
X#endif
X
X printf("%s\r\n", nice_time()); /* time in upper left */
X
X#ifndef USE_CLEARSCREEN
X MoveCursor(1, 0);
X CleartoEOLN ();
X MoveCursor(2, 0);
X CleartoEOLN ();
X#endif
X
X StartInverse();
X center_line(1, group);
X EndInverse();
X
X MoveCursor(0, (COLS - (int) strlen (txt_type_h_for_help))+1); /* upper right */
X if (mail_check()) { /* you have mail message in */
X printf(txt_you_have_mail);
X } else {
X printf(txt_type_h_for_help);
X }
X
X MoveCursor(1, (COLS - (int) strlen (txt_type_h_for_help))+1); /* in upper middle */
X if (kill_articles) { /* display KILL on screen */
X printf("KILL ON ");
X } else {
X printf(" ");
X }
X if (post_process) { /* display POST on screen */
X printf("POST ON");
X } else {
X printf(" ");
X }
X
X MoveCursor(INDEX_TOP, 0);
X
X first_subj_on_screen = (index_point / NOTESLINES) * NOTESLINES;
X if (first_subj_on_screen < 0)
X first_subj_on_screen = 0;
X
X last_subj_on_screen = first_subj_on_screen + NOTESLINES;
X if (last_subj_on_screen >= top_base) {
X last_subj_on_screen = top_base;
X first_subj_on_screen = top_base - NOTESLINES;
X
X if (first_subj_on_screen < 0)
X first_subj_on_screen = 0;
X }
X
X for (j=0, i = first_subj_on_screen; i < last_subj_on_screen; i++, j++) {
X respnum = base[i];
X
X if (arts[respnum].tagged) {
X sprintf (new_resps, "%2d", arts[respnum].tagged);
X } else if (new_responses(i)) {
X strcpy (new_resps, " +");
X } else {
X strcpy (new_resps, " ");
X }
X
X n = nresp(i);
X if (n)
X sprintf (resps, "%4d", n);
X else
X strcpy (resps, " ");
X
X if (show_author) {
X my_strncpy (subject, arts[respnum].subject, max_subj);
X my_strncpy (from, arts[respnum].from, max_from);
X
X sprintf (screen[j].col, " %4d %s %-*s%s %-*s\r\n",
X i+1, new_resps, max_subj, subject, resps, max_from, from);
X } else {
X sprintf(screen[j].col, " %4d %s %-*s %s\r\n",
X i+1, new_resps, max_subj+max_from, arts[respnum].subject, resps);
X }
X printf("%s", screen[j].col);
X }
X
X#ifndef USE_CLEARSCREEN
X CleartoEOS ();
X#endif
X
X if (top_base <= 0)
X info_message(txt_no_arts);
X else if (last_subj_on_screen == top_base)
X info_message(txt_end_of_arts);
X
X if (top_base > 0)
X draw_subject_arrow();
X}
X
Xvoid draw_subject_arrow()
X{
X draw_arrow (INDEX_TOP + (index_point-first_subj_on_screen));
X}
X
Xvoid erase_subject_arrow()
X{
X erase_arrow (INDEX_TOP + (index_point-first_subj_on_screen));
X}
X
X
Xint prompt_subject_num (ch, group)
X char ch;
X char *group;
X{
X int num;
X
X clear_message();
X
X if ((num = parse_num(ch, txt_read_art)) == -1) {
X clear_message();
X return FALSE;
X }
X num--; /* index from 0 (internal) vs. 1 (user) */
X
X if (num >= top_base)
X num = top_base - 1;
X
X if (num >= first_subj_on_screen
X && num < last_subj_on_screen) {
X erase_subject_arrow();
X index_point = num;
X draw_subject_arrow();
X } else {
X#ifndef USE_CLEARSCREEN
X erase_subject_arrow();
X#endif
X index_point = num;
X show_group_page(group);
X }
X return TRUE;
X}
X
X/*
X * Return the number of unread articles there are within a thread
X */
X
Xint new_responses (thread)
X int thread;
X{
X int i;
X int sum = 0;
X
X for (i = base[thread]; i >= 0; i = arts[i].thread)
X if (arts[i].unread)
X sum++;
X
X return sum;
X}
X
X
Xvoid clear_note_area ()
X{
X#ifndef USE_CLEARSCREEN
X MoveCursor (3, 0); /* top left corner */
X CleartoEOS ();
X#endif
X}
X
X/*
X * Post an original article (not a followup)
X */
X
Xint post_base (group)
X char *group;
X{
X FILE *fp;
X char nam[LEN+1];
X char ch;
X char ch_default = 'p';
X char subj[LEN+1];
X char buf[LEN+1];
X
X if (!parse_string(txt_post_subject, subj))
X return FALSE;
X if (subj[0] == '\0')
X return FALSE;
X
X setuid(real_uid);
X setgid(real_gid);
X
X sprintf(nam, "%s/.article", homedir);
X if ((fp = fopen(nam, "w")) == NULL) {
X error_message (txt_cannot_open, nam);
X setuid (tin_uid);
X setgid (tin_gid);
X return FALSE;
X }
X chmod(nam, 0600);
X
X fprintf(fp, "Subject: %s\n", subj);
X fprintf(fp, "Newsgroups: %s\n", group);
X fprintf(fp, "Distribution: \n");
X if (*my_org)
X fprintf(fp, "Organization: %s\n", my_org);
X if (*reply_to)
X fprintf(fp, "Reply-To: %s\n", reply_to);
X fprintf(fp, "\n");
X
X add_signature (fp, FALSE);
X fclose(fp);
X
X ch = 'e';
X while (1) {
X switch (ch) {
X case 'e':
X start_line_offset = 5;
X invoke_editor(nam);
X break;
X
X case 'a':
X clear_message ();
X setuid(tin_uid);
X setgid(tin_gid);
X return FALSE;
X
X case 'p':
X wait_message (txt_posting);
X sprintf (buf, "%s/inews -h < %s", LIBDIR, nam);
X if (invoke_cmd (buf)) {
X info_message (txt_art_posted);
X goto post_base_done;
X } else {
X info_message (txt_art_rejected);
X break;
X }
X }
X
X do {
X sprintf (msg, "%s%c", txt_abort_edit_post, ch_default);
X wait_message (msg);
X MoveCursor(LINES, (int) strlen (txt_abort_edit_post));
X if ((ch = ReadCh()) == CR)
X ch = ch_default;
X } while (ch != 'a' && ch != 'e' && ch != 'p');
X }
X
Xpost_base_done:
X setuid (tin_uid);
X setgid (tin_gid);
X
X update_art_posted_file (group, subj);
X
X return TRUE;
X}
X
X
Xint find_new_pos (old_top, old_artnum, cur_pos)
X int old_top;
X long old_artnum;
X int cur_pos;
X{
X int pos;
X
X if (top != old_top) {
X if ((pos = valid_artnum (old_artnum)) >= 0) {
X if ((pos = which_base (pos)) >= 0) {
X return pos;
X } else {
X return top_base - 1;
X }
X } else {
X return top_base - 1;
X }
X }
X
X return cur_pos;
X}
X
SHAR_EOF
$TOUCH -am 0819093091 group.c &&
chmod 0600 group.c ||
echo "restore of group.c failed"
set `wc -c group.c`;Wc_c=$1
if test "$Wc_c" != "20085"; then
echo original size 20085, current size $Wc_c
fi
# ============= hashstr.c ==============
echo "x - extracting hashstr.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > hashstr.c &&
X/*
X * Project : tin - a visual threaded usenet newsreader
X * Module : hashstr.c
X * Author : R.Skrenta
X * Created : 01-04-91
X * Updated : 10-08-91
X * Release : 1.0
X * Notes :
X * Copyright : (c) Copyright 1991 by Rich Skrenta
X * You may freely copy or redistribute this software,
X * so long as there is no profit made from its use, sale
X * trade or reproduction. You may not change this copy-
X * right notice, and it must be included in any copy made
X */
X
X#include <stdio.h>
X#ifdef BSD
X#include <strings.h>
X#else
X#include <string.h>
X#include <malloc.h>
X#endif
X
X/*
X * Maintain a table of all strings we have seen.
X * If a new string comes in, add it to the table and return a pointer
X * to it. If we've seen it before, just return the pointer to it.
X *
X * Usage: hash_str("some string") returns char *
X *
X * Spillovers are chained on the end
X *
X * !!! NOTE: CHECK OUT add_string FOR THE *iptr TRICK THAT IS LATER !!!
X * !!! USED IN dump_index (art.c) !!!
X *
X */
X
X
X/*
X * Arbitrary table size, but make sure it's prime!
X */
X
X/* #define TABLE_SIZE 1409 */
X
X#define TABLE_SIZE 2411
X
X
X
Xstruct hashnode {
X char *s; /* the string we're saving */
X struct hashnode *next; /* chain for spillover */
X};
X
Xstruct hashnode *table[TABLE_SIZE];
X
Xextern char *my_malloc();
Xstruct hashnode *add_string();
X
X
Xchar *hash_str(s)
Xchar *s;
X{
X struct hashnode *p; /* used to descend the spillover structs */
X long h; /* result of hash: index into hash table */
X
X if (s == NULL)
X return(NULL);
X
X {
X char *t = s;
X
X h = *t++;
X while (*t)
X h = ((h << 1) ^ *t++) % TABLE_SIZE;
X /* h = (h * 128 + *t++) % TABLE_SIZE; */
X }
X
X p = table[h];
X
X if (p == NULL) {
X table[h] = add_string(s);
X return table[h]->s;
X }
X
X while (1) {
X if (strcmp(s, p->s) == 0)
X return(p->s);
X
X if (p->next == NULL) {
X p->next = add_string(s);
X return p->next->s;
X } else
X p = p->next;
X }
X}
X
X
Xstruct hashnode *add_string(s)
Xchar *s;
X{
X struct hashnode *p;
X extern char *strcpy();
X int *iptr;
X
X p = (struct hashnode *) my_malloc(sizeof(*p));
X
X p->next = NULL;
X iptr = (int *) my_malloc((unsigned) strlen(s) + sizeof(int) + 1);
X *iptr++ = -1;
X p->s = (char *) iptr;
X strcpy(p->s, s);
X return(p);
X}
X
X
Xvoid hash_init ()
X{
X int i;
X
X for (i = 0; i < TABLE_SIZE; i++)
X table[i] = NULL;
X}
X
X
Xvoid hash_reclaim ()
X{
X int i;
X struct hashnode *p, *next;
X int *iptr;
X
X for (i = 0; i < TABLE_SIZE; i++)
X if (table[i] != NULL) {
X p = table[i];
X while (p != NULL) {
X next = p->next;
X iptr = (int *) p->s;
X free(--iptr);
X free(p);
X p = next;
X }
X table[i] = NULL;
X }
X}
X
X
SHAR_EOF
$TOUCH -am 0819085991 hashstr.c &&
chmod 0600 hashstr.c ||
echo "restore of hashstr.c failed"
set `wc -c hashstr.c`;Wc_c=$1
if test "$Wc_c" != "2673"; then
echo original size 2673, current size $Wc_c
fi
# ============= help.c ==============
echo "x - extracting help.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > help.c &&
X/*
X * Project : tin - a visual threaded usenet newsreader
X * Module : help.c
X * Author : R.Skrenta / I.Lea
X * Created : 01-04-91
X * Updated : 22-08-91
X * Release : 1.0
X * Notes :
X * Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
X * You may freely copy or redistribute this software,
X * so long as there is no profit made from its use, sale
X * trade or reproduction. You may not change this copy-
X * right notice, and it must be included in any copy made
X */
X
X#include "tin.h"
X#include "nntp.h"
X
X/*
Xvoid basename (dirname, basename)
X char *dirname;
X char *basename;
X{
X int i;
X
X strcpy (basename, dirname);
X
X for (i=(int) strlen(dirname)-1 ; i ; i--) {
X if (dirname[i] == '/') {
X strcpy (basename, dirname+(i+1));
X break;
X }
X }
X}
X*/
X
Xvoid help_select_commands ()
X{
X char ch;
X
Xselect_help_start:
X
X ClearScreen ();
X center_line (0, page_header);
X StartInverse ();
X center_line (1, txt_group_select_com_1);
X EndInverse ();
X
X MoveCursor(3, 0);
X
X printf(txt_help_g_4);
X printf(txt_help_ctrl_d);
X printf(txt_help_ctrl_l);
X printf(txt_help_g_ctrl_k);
X printf(txt_help_g_ctrl_r);
X printf(txt_help_g_cr);
X printf(txt_help_g_tab);
X printf(txt_help_b);
X printf(txt_help_bug, BUG_REPORT_ADDRESS);
X printf(txt_help_g_c);
X printf(txt_help_g);
X printf(txt_help_j);
X printf(txt_help_h);
X printf(txt_help_m);
X printf(txt_help_M);
X printf(txt_help_q);
X printf(txt_help_s);
X printf(txt_help_S);
X printf(txt_help_W);
X
X center_line(LINES, txt_hit_space_for_more);
X ch = ReadCh();
X if (ch != ' ') {
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X return;
X }
X
X ClearScreen();
X center_line(0, page_header);
X center_line(1, txt_group_select_com_2);
X
X MoveCursor(3, 0);
X
X printf(txt_help_g_y);
X printf(txt_help_g_dollar);
X printf(txt_help_g_search);
X
X center_line(LINES, txt_hit_any_key);
X ch = ReadCh();
X if (ch == 'b')
X goto select_help_start;
X
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X}
X
X
Xvoid help_select_info ()
X{
X}
X
X
Xvoid help_group_commands ()
X{
X char ch;
X
Xgroup_help_start:
X
X ClearScreen ();
X center_line (0, page_header);
X StartInverse ();
X center_line (1, txt_index_page_com_1);
X EndInverse ();
X
X MoveCursor(3, 0);
X
X printf(txt_help_i_4);
X printf(txt_help_ctrl_d);
X printf(txt_help_ctrl_k);
X printf(txt_help_ctrl_l);
X printf(txt_help_i_cr);
X printf(txt_help_i_tab);
X printf(txt_help_a);
X printf(txt_help_b);
X printf(txt_help_bug, BUG_REPORT_ADDRESS);
X printf(txt_help_c);
X printf(txt_help_g);
X printf(txt_help_h);
X printf(txt_help_I);
X printf(txt_help_j);
X printf(txt_help_K);
X printf(txt_help_M);
X printf(txt_help_i_n);
X printf(txt_help_i_p);
X printf(txt_help_q);
X
X center_line(LINES, txt_hit_space_for_more);
X ch = ReadCh();
X if (ch != ' ') {
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X return;
X }
X
X ClearScreen();
X center_line(0, page_header);
X StartInverse ();
X center_line(1, txt_index_page_com_2);
X EndInverse ();
X
X MoveCursor(3, 0);
X
X printf(txt_help_s);
X printf(txt_help_i_S);
X printf(txt_help_t);
X printf(txt_help_T);
X printf(txt_help_U);
X printf(txt_help_w);
X printf(txt_help_W);
X printf(txt_help_p_z);
X printf(txt_help_i_search);
X printf(txt_help_dash);
X
X center_line(LINES, txt_hit_any_key);
X ch = ReadCh();
X if (ch == 'b')
X goto group_help_start;
X
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X}
X
X
Xvoid help_group_info ()
X{
X}
X
X
Xvoid help_page_commands ()
X{
X char ch;
X
Xpage_help_start:
X
X ClearScreen ();
X center_line (0, page_header);
X StartInverse ();
X center_line (1, txt_art_pager_com_1);
X EndInverse ();
X
X MoveCursor(3, 0);
X
X printf(txt_help_p_0);
X printf(txt_help_p_4);
X printf(txt_help_ctrl_h);
X printf(txt_help_ctrl_k);
X printf(txt_help_ctrl_l);
X printf(txt_help_p_ctrl_r);
X printf(txt_help_p_cr);
X printf(txt_help_p_tab);
X printf(txt_help_b);
X printf(txt_help_a);
X printf(txt_help_bug, BUG_REPORT_ADDRESS);
X printf(txt_help_c);
X printf(txt_help_p_d);
X printf(txt_help_p_f);
X printf(txt_help_h);
X printf(txt_help_p_i);
X printf(txt_help_I);
X printf(txt_help_p_k);
X printf(txt_help_p_m);
X
X center_line(LINES, txt_hit_space_for_more);
X ch = ReadCh();
X if (ch != ' ') {
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X return;
X }
X
X ClearScreen();
X center_line(0, page_header);
X StartInverse ();
X center_line(1, txt_art_pager_com_2);
X EndInverse ();
X
X MoveCursor(3, 0);
X
X printf(txt_help_M);
X printf(txt_help_p_n);
X printf(txt_help_p_o);
X printf(txt_help_p_p);
X printf(txt_help_q);
X printf(txt_help_p_r);
X printf(txt_help_p_s);
X printf(txt_help_T);
X printf(txt_help_w);
X printf(txt_help_W);
X printf(txt_help_p_z);
X printf(txt_help_dash);
X printf(txt_help_p_pipe);
X printf(txt_help_p_search);
X
X center_line(LINES, txt_hit_any_key);
X ch = ReadCh();
X
X if (ch == 'b')
X goto page_help_start;
X
X#ifndef USE_CLEARSCREEN
X ClearScreen ();
X#endif
X}
X
X
Xvoid help_page_info ()
X{
X}
SHAR_EOF
$TOUCH -am 0822160291 help.c &&
chmod 0600 help.c ||
echo "restore of help.c failed"
set `wc -c help.c`;Wc_c=$1
if test "$Wc_c" != "4794"; then
echo original size 4794, current size $Wc_c
fi
# ============= kill.c ==============
echo "x - extracting kill.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > kill.c &&
X/*
X * Project : tin - a visual threaded usenet newsreader
X * Module : kill.c
X * Author : I.Lea
X * Created : 01-04-91
X * Updated : 16-08-91
X * Release : 1.0
X * Notes : kill articles
X * Copyright : (c) Copyright 1991 by Iain Lea
X * You may freely copy or redistribute this software,
X * so long as there is no profit made from its use, sale
X * trade or reproduction. You may not change this copy-
X * right notice, and it must be included in any copy made
X */
X
X#include "tin.h"
X
Xextern char index_file[LEN+1];
X
Xstruct kill_t *killf;
Xint kill_num = 0;
Xint max_kill;
X
X/*
X * read_kill_file - read ~/.tin/kill file contents into kill array
X */
X
Xint read_kill_file ()
X{
X char buf[LEN+1];
X FILE *fp;
X
X free_kill_array ();
X
X if ((fp = fopen (killfile, "r")) != NULL) {
X kill_num=0;
X while (fgets (buf, LEN, fp) != NULL) {
X if (buf[0] != '#') {
X if (kill_num == max_kill-1) {
X expand_kill ();
X }
X killf[kill_num].kill_type = atoi (buf);
X if (fgets (buf, LEN, fp) != NULL) {
X killf[kill_num].kill_group = atol (buf);
X } else {
X goto corrupt_killfile;
X }
X switch (killf[kill_num].kill_type) {
X case KILL_SUBJ:
X if (fgets (buf, LEN, fp) != NULL) {
X buf[strlen (buf)-1] = '\0';
X killf[kill_num].kill_subj = str_dup (buf);
X }
X break;
X case KILL_FROM:
X if (fgets (buf, LEN, fp) != NULL) {
X buf[strlen (buf)-1] = '\0';
X killf[kill_num].kill_from = str_dup (buf);
X }
X break;
X case KILL_BOTH:
X if (fgets (buf, LEN, fp) != NULL) {
X buf[strlen (buf)-1] = '\0';
X killf[kill_num].kill_subj = str_dup (buf);
X }
X if (fgets (buf, LEN, fp) != NULL) {
X buf[strlen (buf)-1] = '\0';
X killf[kill_num].kill_from = str_dup (buf);
X }
X break;
X default:
X goto corrupt_killfile;
X }
X kill_num++;
X }
X }
X fclose (fp);
X return TRUE;
X } else {
X return FALSE;
X }
X
Xcorrupt_killfile:
X fclose (fp);
X killf[kill_num].kill_type = 0;
X error_message ("corrupt kill file %s", killfile);
X return FALSE;
X}
X
X/*
X * write_kill_file - write kill strings to ~/.tin/kill
X */
X
Xvoid write_kill_file ()
X{
X FILE *fp;
X int i;
X
X if (kill_num && (fp = fopen (killfile, "w")) != NULL) {
X wait_message (txt_saving);
X fprintf (fp, "# 1st line 1=(Subject: only) 2=(From: only) 3=(Subject: & From:)\n");
X fprintf (fp, "# 2nd line 0=(kill on all newsgroups) >0=(kill on specific newsgroup)\n");
X for (i=0 ; i < kill_num ; i++) {
X if (killf[i].kill_type && (killf[i].kill_subj || killf[i].kill_from)) {
X fprintf (fp, "#\n# kill description %d\n", i+1);
X fprintf (fp, "%d\n", killf[i].kill_type);
X fprintf (fp, "%ld\n", killf[i].kill_group);
X switch (killf[i].kill_type) {
X case KILL_SUBJ:
X fprintf (fp, "%s\n", killf[i].kill_subj);
X break;
X case KILL_FROM:
X fprintf (fp, "%s\n", killf[i].kill_from);
X break;
X case KILL_BOTH:
X fprintf (fp, "%s\n", killf[i].kill_subj);
X fprintf (fp, "%s\n", killf[i].kill_from);
X break;
X }
X }
X }
X fclose (fp);
X chmod (killfile, 0600);
X }
X}
X
X/*
X * options menu so that the user can dynamically change parameters
X */
X
Xint kill_art_menu (group_name, index)
X char *group_name;
X int index;
X{
X char text[LEN+1];
X char kill_from[LEN+1];
X char kill_subj[LEN+1];
X char kill_group[LEN+1];
X char ch_default = 's';
X char *str;
X int ch;
X int counter;
X int kill_from_ok = FALSE;
X int kill_subj_ok = FALSE;
X int kill_every_group;
X
X sprintf (kill_group, "%s only", group_name);
X my_strncpy (text, arts[index].subject, 45);
X sprintf (kill_subj, txt_kill_subject, text);
X my_strncpy (text, arts[index].from, 45);
X sprintf (kill_from, txt_kill_from, text);
X text[0] = '\0';
X
X ClearScreen ();
X printf("%s\r\n", nice_time()); /* time in upper left */
X
X StartInverse ();
X center_line (1, txt_kill_menu);
X EndInverse ();
X
X MoveCursor(INDEX_TOP, 0);
X printf ("%s\r\n\r\n", txt_kill_text);
X printf ("%s\r\n\r\n\r\n", txt_kill_text_type);
X printf ("%s\r\n\r\n", kill_subj);
X printf ("%s\r\n\r\n\r\n", kill_from);
X printf ("%s%s", txt_kill_group, kill_group);
X fflush(stdout);
X
X show_menu_help (txt_help_kill_text);
X parse_menu_string (INDEX_TOP, strlen (txt_kill_text), text);
X
X if (text[0]) {
X show_menu_help (txt_help_kill_text_type);
X counter = 1;
X MoveCursor (INDEX_TOP+2, strlen (txt_kill_text_type));
X str = "Subject: line only ";
X printf ("%s", str);
X fflush(stdout);
X do {
X MoveCursor (INDEX_TOP+2, strlen (txt_kill_text_type));
X if ((ch = ReadCh()) == ' ') {
X counter++;
X if (counter == KILL_BOTH+1) {
X counter = KILL_SUBJ;
X }
X switch (counter) {
X case KILL_SUBJ:
X str = "Subject: line only ";
X break;
X case KILL_FROM:
X str = "From: line only ";
X break;
X case KILL_BOTH:
X str = "Subject: & From: lines";
X break;
X }
X printf ("%s", str);
X fflush(stdout);
X }
X } while (ch != CR);
X }
X
X if (! text[0]) {
X show_menu_help (txt_help_kill_subject);
X kill_subj_ok = prompt_yn (INDEX_TOP+5, kill_subj, 'y');
X
X show_menu_help (txt_help_kill_from);
X kill_from_ok = prompt_yn (INDEX_TOP+7, kill_from, 'n');
X }
X
X if (text[0] || kill_subj_ok || kill_from_ok) {
X show_menu_help (txt_help_kill_group);
X kill_every_group = FALSE;
X MoveCursor (INDEX_TOP+10, strlen (txt_kill_group));
X str = kill_group;
X printf ("%s", str);
X fflush(stdout);
X do {
X MoveCursor (INDEX_TOP+10, strlen (txt_kill_group));
X if ((ch = ReadCh()) == ' ') {
X kill_every_group = !kill_every_group;
X if (kill_every_group) {
X str = "All groups";
X } else {
X str = kill_group;
X }
X CleartoEOLN ();
X printf ("%s", str);
X fflush(stdout);
X }
X } while (ch != CR);
X }
X
X while (1) {
X do {
X sprintf (msg, "%s%c", txt_abort_edit_save_killfile, ch_default);
X wait_message (msg);
X MoveCursor(LINES, strlen (txt_abort_edit_save_killfile));
X if ((ch = ReadCh()) == CR)
X ch = ch_default;
X } while (ch != 'a' && ch != 'e' && ch != 's');
X switch (ch) {
X case 'e':
X start_line_offset = 2;
X invoke_editor (killfile);
X untag_all_articles ();
X read_kill_file ();
X reload_index_file (group_name, FALSE);
X return TRUE;
X
X case 'a':
X return FALSE;
X
X case 's':
X if (kill_num > max_kill-1) {
X expand_kill ();
X }
X if (text[0]) {
X switch (counter) {
X case KILL_SUBJ:
X killf[kill_num].kill_subj = str_dup (text);
X break;
X case KILL_FROM:
X killf[kill_num].kill_from = str_dup (text);
X break;
X case KILL_BOTH:
X killf[kill_num].kill_subj = str_dup (text);
X killf[kill_num].kill_from = str_dup (text);
X break;
X }
X killf[kill_num].kill_type = counter;
X if (kill_every_group) {
X killf[kill_num].kill_group= 0L;
X } else {
X killf[kill_num].kill_group= hash_s (group_name);
X }
X kill_num++;
X } else {
X if (kill_subj_ok) {
X killf[kill_num].kill_type = KILL_SUBJ;
X killf[kill_num].kill_subj = str_dup (arts[index].subject);
X }
X if (kill_from_ok) {
X killf[kill_num].kill_type |= KILL_FROM;
X killf[kill_num].kill_from = str_dup (arts[index].from);
X }
X if (killf[kill_num].kill_type) {
X if (kill_every_group) {
X killf[kill_num].kill_group= 0L;
X } else {
X killf[kill_num].kill_group= hash_s (group_name);
X }
X kill_num++;
X }
X }
X write_kill_file ();
X return TRUE;
X }
X }
X}
X
X
Xint untag_all_articles ()
X{
X int untagged = FALSE;
X register int i;
X
X for (i=0 ; i < top ; i++) {
X if (arts[i].tagged) {
X arts[i].tagged = FALSE;
X untagged = TRUE;
X }
X }
X num_of_tagged_files = 0;
X
X return (untagged);
X}
X
X
Xint kill_any_articles (group)
X char *group;
X{
X int killed = FALSE;
X int run_ok = FALSE;
X long group_hash;
X register int i, j;
X
X if (! kill_articles) {
X return killed;
X }
X
X if (kill_num) {
X group_hash = hash_s (group);
X for (i=0 ; i < kill_num ; i++) {
X if (killf[i].kill_group == 0L ||
X killf[i].kill_group == group_hash) {
X run_ok = TRUE;
X }
X }
X if (! run_ok) {
X return (killed);
X }
X if (debug && ! update) {
X wait_message ("Killing articles...");
X }
X for (i=0 ; i < top ; i++) {
X for (j=0 ; j < kill_num && ! arts[i].tagged ; j++) {
X if (killf[j].kill_group == 0L ||
X killf[j].kill_group == group_hash) {
X switch (killf[j].kill_type) {
X case KILL_SUBJ:
X if (str_str (arts[i].subject, killf[j].kill_subj) != 0) {
X arts[i].tagged = TRUE;
X killed = TRUE;
X }
X break;
X case KILL_FROM:
X if (str_str (arts[i].from, killf[j].kill_from) != 0) {
X arts[i].tagged = TRUE;
X killed = TRUE;
X }
X break;
SHAR_EOF
echo "End of tin part 2"
echo "File kill.c is continued in part 3"
echo "3" > shar3_seq_.tmp
exit 0
--
NAME Iain Lea
EMAIL norisc!iain@estevax.UUCP ...!unido!estevax!norisc!iain
SNAIL Siemens AG, AUT 922C, Postfach 4848, Nuernberg, Germany
PHONE +49-911-895-3853, +49-911-895-3877, +49-911-331963