Newsgroups: comp.sources.misc From: iain@estevax.uucp (Iain J. Lea) Subject: v23i017: tin - threaded full screen newsreader v1.0 PL2, Part03/09 Message-ID: <1991Sep25.205118.1911@sparky.imd.sterling.com> X-Md4-Signature: 783c40b3b984ffbc96f69cb5a9e9092b Date: Wed, 25 Sep 1991 20:51:18 GMT Approved: kent@sparky.imd.sterling.com Submitted-by: iain@estevax.uucp (Iain J. Lea) Posting-number: Volume 23, Issue 17 Archive-name: tin/part03 Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX #!/bin/sh # this is tin.shar.03 (part 3 of tin1.02) # do not concatenate these parts, unpack them in order with /bin/sh # file curses.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" != 3; then echo "Please unpack part $Scheck next!" exit 1 else exit 0 fi ) < shar3_seq_.tmp || exit 1 echo "x - Continuing file curses.c" sed 's/^X//' << 'SHAR_EOF' >> curses.c && 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 echo "File curses.c is complete" && $TOUCH -am 0923175591 curses.c && chmod 0600 curses.c || echo "restore of curses.c failed" set `wc -c curses.c`;Wc_c=$1 if test "$Wc_c" != "6043"; then echo original size 6043, 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 : 06-09-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 Xvoid debug_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 if (s->archive) { X fprintf (fp, "arch=[%-38s] ", s->archive); X } else { X fprintf (fp, "arch=[%-38s] ", ""); X } X if (s->part) { X fprintf (fp, "part=[%s] ", s->part); X } else { X fprintf (fp, "part=[%s] ", ""); X } X if (s->patch) { X fprintf (fp, "patch=[%s]\n", s->patch); X } else { X fprintf (fp, "patch=[%s]\n", ""); X } 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 Xvoid debug_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 0923175591 debug.c && chmod 0600 debug.c || echo "restore of debug.c failed" set `wc -c debug.c`;Wc_c=$1 if test "$Wc_c" != "2575"; then echo original size 2575, current size $Wc_c fi # ============= feed.c ============== echo "x - extracting feed.c (Text)" sed 's/^X//' << 'SHAR_EOF' > feed.c && X/* X * Project : tin - a visual threaded usenet newsreader X * Module : feed.c X * Author : I.Lea X * Created : 31-08-91 X * Updated : 22-09-91 X * Release : 1.0 X * Notes : provides same interface to mail,pipe,print and save commands 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 *glob_group; /* Group name */ Xextern char note_h_subj[LEN+1]; /* Subject: */ Xextern char note_h_from[LEN+1]; /* From: */ Xextern FILE *note_fp; /* the body of the current article */ Xextern int note_end; /* end of article ? */ Xextern int note_page; /* what page we're on */ Xextern long note_mark[MAX_PAGES]; /* ftells on beginnings of pages */ X Xchar default_mail_address[LEN]; Xchar default_pipe_command[LEN]; Xchar default_save_file[LEN]; Xchar default_regex_pattern[LEN]; Xchar proc_ch_default; /* set in change_rcfile () */ X X Xvoid feed_articles (function, level, prompt, respnum, group_path) X int function; X int level; X char *prompt; X int respnum; X char *group_path; X{ X char address[LEN+1]; X char command[LEN+1]; X char file[LEN+1], *p; X char mailbox[LEN+1]; X char pattern[LEN+1]; X char ch = 'a', ch_default = 'a'; X char proc_ch = proc_ch_default; X FILE *fp; X int b, i, j, count = 1; X int is_mailbox = FALSE; X int orig_note_end; X int orig_note_page; X int ret1, ret2; X int redraw_screen = FALSE; X X if (level == PAGE_LEVEL) { X orig_note_end = note_end; X orig_note_page = note_page; X } X X b = which_base (respnum); X X if (num_of_tagged_files) { X ch_default = 'T'; X } X if (! num_of_tagged_files && nresp (b)) { X ch_default = 't'; X } X do { X sprintf (msg, "%s%s%c", prompt, txt_art_thread_regex_tag, ch_default); X wait_message (msg); X MoveCursor (LINES, strlen (msg)-1); X if ((ch = ReadCh ()) == CR) X ch = ch_default; X } while (ch != 'a' && ch != 't' && ch != 'T' && ch != 'r' && ch != 'e'); X X if (ch == 'e') { /* exit */ X clear_message (); X return; X } X X if (ch == 'r') { X sprintf (msg, txt_feed_pattern, default_regex_pattern); X if (! parse_string (msg, pattern)) { X clear_message (); X return; X } X if (strlen (pattern)) { X my_strncpy (default_regex_pattern, pattern, LEN); X } else { X if (default_regex_pattern[0]) { X my_strncpy (pattern, default_regex_pattern, LEN); X } else { X info_message (txt_no_match); X return; X } X } X } X X switch (function) { X case FEED_MAIL: X sprintf (msg, txt_mail_art_to, default_mail_address); X if (! parse_string (msg, address)) { X clear_message (); X return; X } X if (strlen (address)) { X strcpy (default_mail_address, address); X } else { X if (default_mail_address[0]) { X strcpy (address, default_mail_address); X } else { X info_message (txt_no_mail_address); X return; X } X } X break; X case FEED_PIPE: X sprintf (msg, txt_pipe_to_command, default_pipe_command); X if (! parse_string (msg, command)) { X clear_message (); X return; X } X if (strlen (command)) { X strcpy (default_pipe_command, command); X } else { X if (default_pipe_command[0]) { X strcpy (command, default_pipe_command); X } else { X info_message (txt_no_command); X return; X } X } X if ((fp = popen (command, "w")) == NULL) { X error_message (txt_command_failed_s, command); X return; X } X Raw (FALSE); X break; X case FEED_PRINT: X if (default_printer) { X sprintf (command, "%s -P%s > /dev/null 2>&1", X printer, get_val ("PRINTER","ps0")); X } else { X sprintf (command, "%s > /dev/null 2>&1", printer); X } X if ((fp = popen (command, "w")) == NULL) { X error_message (txt_command_failed_s, command); X return; X } X break; X case FEED_SAVE: /* ask user for filename */ X free_save_array (); X if ((save_archive_name == FALSE || arts[respnum].archive == (char *) 0)) { X sprintf (msg, txt_save_filename, default_save_file); X if (! parse_string (msg, file)) { X clear_message (); X return; X } X if (strlen (file)) { X strcpy (default_save_file, file); X } else { X if (default_save_file[0]) { X strcpy (file, default_save_file); X } else { X info_message (txt_no_filename); X return; X } X } X for (p = file; *p && (*p == ' ' || *p == '\t'); p++) { X continue; X } X if (! *p) { X info_message (txt_no_filename); X return; X } X if ((file[0] == '~' || file[0] == '+') && strlen (file) == 1) { X info_message (txt_no_filename); X return; X } X if (is_mailbox = create_path (file)) { X if ((int) strlen (file) > 1) { X my_strncpy (mailbox, file+1, LEN); X } else { X my_strncpy (mailbox, glob_group, LEN); X /* X * convert 1st letter to uppercase X */ X if (mailbox[0] >= 'a' && mailbox[0] <= 'z') { X mailbox[0] = mailbox[0] - 32; X } X } X my_strncpy (file, mailbox, LEN); X } else { /* ask for post processing type */ X do { X sprintf (msg, "%s%c", txt_post_procees_type, proc_ch_default); X wait_message (msg); X MoveCursor (LINES, strlen (msg)-1); X if ((proc_ch = ReadCh ()) == CR) X proc_ch = proc_ch_default; X } while (proc_ch != 'n' && proc_ch != 's' && X proc_ch != 'u' && proc_ch != 'U' && X proc_ch != 'p'); X } X } X clear_message (); X break; X } X X switch (ch) { X case 'a': /* article */ X if (level == GROUP_LEVEL) { X open_note (arts[respnum].artnum, group_path); X } X switch (function) { X case FEED_MAIL: X redraw_screen = mail_to_someone (address); X break; X case FEED_PIPE: X fseek (note_fp, 0L, 0); X copy_fp (note_fp, fp, ""); X break; X case FEED_PRINT: X wait_message (txt_printing); X if (print_header) { X fseek(note_fp, 0L, 0); X } else { X fprintf (fp, "From: %s\n", note_h_from); X fprintf (fp, "Subject: %s\n\n", note_h_subj); X fseek (note_fp, note_mark[0], 0); X } X copy_fp(note_fp, fp, ""); X pclose (fp); X break; X case FEED_SAVE: X add_to_save_list (0, &arts[respnum], is_mailbox, file); X (void) save_art_to_file (respnum, 0, FALSE, ""); X break; X } X if (level == GROUP_LEVEL) { X note_cleanup (); X } X break; X X case 't': /* thread */ X for (i = base[b]; i >= 0; i = arts[i].thread) { X if (function == FEED_PRINT) { X if ((fp = popen (command, "w")) == NULL) { X error_message (txt_command_failed_s, command); X return; X } X } X if (level == PAGE_LEVEL) { X note_cleanup (); X } X open_note (arts[i].artnum, group_path); X switch (function) { X case FEED_MAIL: X mail_to_someone (address); X break; X case FEED_PIPE: X fseek (note_fp, 0L, 0); X copy_fp (note_fp, fp, ""); X break; X case FEED_PRINT: X sprintf (msg, "%s%d", txt_printing, count++); X wait_message (msg); X if (print_header) { X fseek(note_fp, 0L, 0); X } else { X fprintf (fp, "From: %s\n", note_h_from); X fprintf (fp, "Subject: %s\n\n", note_h_subj); X fseek (note_fp, note_mark[0], 0); X } X copy_fp(note_fp, fp, ""); X pclose (fp); X break; X case FEED_SAVE: X add_to_save_list (i, &arts[i], is_mailbox, file); X break; X } X } X if (function == FEED_SAVE) { X sort_save_list (); X (void) save_thread_to_file (is_mailbox, group_path); X } X break; X X case 'T': /* tagged articles */ X for (i=1 ; i <= num_of_tagged_files ; i++) { X for (j=0 ; j < top ; j++) { X if (arts[j].tagged && arts[j].tagged == i) { X if (function == FEED_PRINT) { X if ((fp = popen (command, "w")) == NULL) { X error_message (txt_command_failed_s, command); X return; X } X } X if (level == PAGE_LEVEL) { X note_cleanup (); X } X open_note (arts[j].artnum, group_path); X switch (function) { X case FEED_MAIL: X mail_to_someone (address); X break; X case FEED_PIPE: X fseek (note_fp, 0L, 0); X copy_fp (note_fp, fp, ""); X break; X case FEED_PRINT: X sprintf (msg, "%s%d", txt_printing, count++); X wait_message (msg); X if (print_header) { X fseek(note_fp, 0L, 0); X } else { X fprintf (fp, "From: %s\n", note_h_from); X fprintf (fp, "Subject: %s\n\n", note_h_subj); X fseek (note_fp, note_mark[0], 0); X } X copy_fp(note_fp, fp, ""); X pclose (fp); X break; X case FEED_SAVE: X add_to_save_list (j, &arts[j], is_mailbox, file); X break; X } X } X } X } X if (function == FEED_SAVE) { X (void) save_regex_arts (is_mailbox, group_path); X } X break; X X case 'r': /* regex pattern matched articles */ X for (i=0 ; i < top ; i++) { X#ifdef DONT_USE_REGEX X if (str_str (arts[i].subject, pattern) != 0) { X#else X if (wildmat (arts[i].subject, pattern)) { X#endif X if (function == FEED_PRINT) { X if ((fp = popen (command, "w")) == NULL) { X error_message (txt_command_failed_s, command); X return; X } X } X if (level == PAGE_LEVEL) { X note_cleanup (); X } X open_note (arts[i].artnum, group_path); X switch (function) { X case FEED_MAIL: X mail_to_someone (address); X break; X case FEED_PIPE: X fseek (note_fp, 0L, 0); X copy_fp (note_fp, fp, ""); X break; X case FEED_PRINT: X sprintf (msg, "%s%d", txt_printing, count++); X wait_message (msg); X if (print_header) { X fseek(note_fp, 0L, 0); X } else { X fprintf (fp, "From: %s\n", note_h_from); X fprintf (fp, "Subject: %s\n\n", note_h_subj); X fseek (note_fp, note_mark[0], 0); X } X copy_fp(note_fp, fp, ""); X pclose (fp); X break; X case FEED_SAVE: X add_to_save_list (i, &arts[i], is_mailbox, file); X break; X } X } X } X if (function == FEED_SAVE) { X sort_save_list (); X (void) save_regex_arts (is_mailbox, group_path); X } X break; X } X X switch (function) { X case FEED_PIPE: X pclose (fp); X Raw (TRUE); X continue_prompt (); X redraw_screen = TRUE; X break; X case FEED_PRINT: X info_message (txt_printed); X redraw_screen = mail_check (); /* in case of sending to oneself */ X break; X case FEED_SAVE: X ret1 = (mark_saved_read ? TRUE : FALSE); X if (proc_ch != 'n' && is_mailbox == FALSE) { X ret2 = post_process_files (proc_ch); X } X if (ret1 || ret2) { X redraw_screen = TRUE; X } X free_save_array (); X break; X } X X if (level == PAGE_LEVEL) { X if (ch != 'a') { X open_note (arts[respnum].artnum, group_path); X } X note_end = orig_note_end; X note_page = orig_note_page; X fseek (note_fp, note_mark[note_page], 0); X if (redraw_screen) { X if (note_page == 0) { X show_note_page (respnum, glob_group); X } else { X redraw_page (respnum, glob_group); X } X } X } else { X if (redraw_screen) { X show_group_page (glob_group); X } X } X} SHAR_EOF $TOUCH -am 0923175591 feed.c && chmod 0600 feed.c || echo "restore of feed.c failed" set `wc -c feed.c`;Wc_c=$1 if test "$Wc_c" != "11087"; then echo original size 11087, 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 : 22-09-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 Xvoid group_page (group) X char *group; X{ 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 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 if (index_point != top_base - 1) { X index_point = top_base - 1; X show_group_page (group); X } 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 '|': /* pipe article/thread/tagged arts to command */ X if (index_point >= 0) { X feed_articles (FEED_PIPE, GROUP_LEVEL, "Pipe", X (int) base[index_point], group_path); X } 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 ; 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 if (index_point != 0) { X index_point = 0; X show_group_page (group); X } 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 show_info_page (HELP_INFO, help_group, txt_index_page_com); 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 draw_arrow_mark = TRUE; X info_message (txt_inverse_off); X } 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 mark_screen (SCREEN_READ_UNREAD, " "); 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': /* mail article to somebody */ X if (index_point >= 0) { X feed_articles (FEED_MAIL, GROUP_LEVEL, "Mail", X (int) base[index_point], group_path); 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 = pos_first_unread; 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 = pos_first_unread; X goto group_done; X } X clear_note_area (); X show_group_page (group); X } X break; X X case 'o': /* output art/thread/tagged arts to printer */ X if (index_point >= 0) { X feed_articles (FEED_PRINT, GROUP_LEVEL, "Print", X (int) base[index_point], group_path); 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 = pos_first_unread; 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 = pos_first_unread; 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': /* save regex pattern to file/s */ X if (index_point >= 0) { X feed_articles (FEED_SAVE, GROUP_LEVEL, "Save", X (int) base[index_point], group_path); X } X break; X X case 't': X case 'i': /* return to group selection page */ X goto group_done; X X case 'T': /* tag/untag art for mailing/piping/printing/saving */ X if (index_point >= 0) { X n = base[index_point]; X if (arts[n].tagged) { X arts[n].tagged = 0; X sprintf (msg, "%3s", (arts[n].unread ? " +" : " ")); X info_message (txt_untagged_art); X } else { X arts[n].tagged = ++num_of_tagged_files; X sprintf (msg, "%3d", arts[n].tagged); X info_message (txt_tagged_art); X } X mark_screen (SCREEN_READ_UNREAD, msg); X } 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 if (post_base (group)) { X update_newsrc (group, my_group[cur_groupnum], FALSE); X index_group (group, group_path); X read_newsrc_line (group); X index_point = top_base - 1; X show_group_page (group); X } 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 mark_screen (SCREEN_READ_UNREAD, " +"); 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 mark_screen (SCREEN_READ_UNREAD, " +"); 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], FALSE); 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 buf[LEN]; X char new_resps[8]; X char resps[8]; X char from[LEN]; X char subject[LEN]; X int col, i, j, n; X int len_from; X int len_subj; X int respnum; X X#ifdef SIGTSTP X if (do_sigtstp) { X#ifdef POSIX_JOB_CONTROL X sigemptyset (&group_act.sa_mask); X group_act.sa_flags = SA_RESTART | SA_RESETHAND; X group_act.sa_handler = group_suspend; X sigaction (SIGTSTP, &group_act, 0L); X#else X signal (SIGTSTP, group_suspend); X#endif X } X#endif X X#ifdef SIGWINCH X signal (SIGWINCH, group_resize); X#endif X X#ifdef USE_CLEARSCREEN X ClearScreen (); X#else X MoveCursor (0, 0); X CleartoEOLN (); X#endif X X sprintf (buf, "%s (%d)", group, top_base); X center_line (0, TRUE, buf); X X if (col = (COLS - (int) strlen (txt_type_h_for_help))+1) { X MoveCursor (0, 0); X if (kill_articles) { /* display KILL on screen */ X printf ("KILL ON"); X } X X MoveCursor (0, col); 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 X#ifndef USE_CLEARSCREEN X MoveCursor (1, 0); X CleartoEOLN (); X#endif X X MoveCursor (INDEX_TOP, 0); X X if (NOTESLINES <= 0) { X first_subj_on_screen = 0; X } else { X first_subj_on_screen = (index_point / NOTESLINES) * NOTESLINES; X if (first_subj_on_screen < 0) X first_subj_on_screen = 0; X } 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 if (show_author) { X#ifdef RESP_AT_END X len_from = max_from-BLANK_GROUP_COLS; X#else X len_from = max_from-BLANK_GROUP_COLS; X#endif X } else { X#ifdef RESP_AT_END X len_subj = (max_subj+max_from)-BLANK_GROUP_COLS; X#else X len_subj = (max_subj+max_from+3)-BLANK_GROUP_COLS; X#endif 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, "%3d", 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, "%-3d", n); X } else { X strcpy (resps, " "); X } X X my_strncpy (from, arts[respnum].from, max_from); X X if (show_author) { X#ifdef RESP_AT_END X my_strncpy (subject, arts[respnum].subject, max_subj); X sprintf (screen[j].col, " %4d%3s %-*s%s %-*s\r\n", X i+1, new_resps, max_subj, subject, resps, len_from, from); X#else X my_strncpy (subject, arts[respnum].subject, max_subj); X sprintf (screen[j].col, " %4d%3s %s%-*s %-*s\r\n", X i+1, new_resps, resps, max_subj, subject, len_from, from); X#endif X } else { X#ifdef RESP_AT_END X my_strncpy (subject, arts[respnum].subject, max_subj+max_from); X sprintf(screen[j].col, " %4d%3s %-*s %s\r\n", X i+1, new_resps, len_subj, subject, resps); X#else X my_strncpy (subject, arts[respnum].subject, max_subj+max_from+3); X sprintf(screen[j].col, " %4d%3s %s%-*s\r\n", X i+1, new_resps, resps, len_subj, subject); X#endif 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 return; X } else if (last_subj_on_screen == top_base) { X info_message(txt_end_of_arts); X } X 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 (INDEX_TOP, 0); X CleartoEOS (); X#endif 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 X Xmark_screen (col, value) X int col; X char *value; X{ X int i, len; X X len = strlen (value); X X if (draw_arrow_mark) { X MoveCursor(INDEX_TOP + (index_point - first_subj_on_screen), col); X printf ("%s", value); X MoveCursor (LINES, 0); X fflush(stdout); X } else { X for (i=0 ; i < len ; i++) { X screen[index_point-first_subj_on_screen].col[col+i] = value[i]; X } X draw_subject_arrow(); X } X} SHAR_EOF $TOUCH -am 0923175591 group.c && chmod 0600 group.c || echo "restore of group.c failed" set `wc -c group.c`;Wc_c=$1 if test "$Wc_c" != "19165"; then echo original size 19165, 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 : 05-09-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 X#ifdef BSD X#include X#else X#include X#include X#endif X#include "proto.h" 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 * Arbitrary table size, but make sure it's prime! X */ X X/* #define TABLE_SIZE 1409 */ X X#define TABLE_SIZE 2411 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 X Xchar *hash_str (s) X char *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 == (char *) 0) { X return ((char *) 0); X } X X { X unsigned char *t = (unsigned char *) s; X X h = *t++; X while (*t) X h = ((h << 1) ^ *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 X if (p->next == (struct hashnode *) 0) { X p->next = add_string (s); X return p->next->s; X } else X p = p->next; X } X /* NOTREACHED */ X} X X Xstruct hashnode *add_string (s) X char *s; X{ X struct hashnode *p; X int *iptr; X X p = (struct hashnode *) my_malloc (sizeof (*p)); X X p->next = (struct hashnode *) 0; 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] = (struct hashnode *) 0; X } 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] != (struct hashnode *) 0) { X p = table[i]; X while (p != (struct hashnode *) 0) { X next = p->next; X if (p->s != (char *) 0) { X iptr = (int *) p->s; X free ((char *) --iptr); X } X free ((char *) p); X p = next; X } X table[i] = (struct hashnode *) 0; X } X} SHAR_EOF $TOUCH -am 0923175591 hashstr.c && chmod 0600 hashstr.c || echo "restore of hashstr.c failed" set `wc -c hashstr.c`;Wc_c=$1 if test "$Wc_c" != "2811"; then echo original size 2811, 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 : 24-09-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 Xchar *help_select[] = { X txt_help_g_4, X txt_help_ctrl_d, X txt_help_ctrl_l, X txt_help_g_ctrl_k, X txt_help_g_ctrl_r, X txt_help_g_cr, X txt_help_g_tab, X txt_help_b, X txt_help_bug_report, X txt_help_sel_c, X txt_help_g, X txt_help_j, X txt_help_h, X txt_help_I, X txt_help_m, X txt_help_M, X txt_help_q, X txt_help_s, X txt_help_S, X txt_help_v, X txt_help_w, X txt_help_W, X txt_help_g_y, X txt_help_g_z, X txt_help_g_dollar, X txt_help_g_search, X (char *) 0 X}; X Xchar *help_group[] = { X txt_help_i_4, X txt_help_ctrl_d, X txt_help_ctrl_k, X txt_help_ctrl_l, X txt_help_i_cr, X txt_help_i_tab, X txt_help_a, X txt_help_b, X txt_help_bug_report, X txt_help_c, X txt_help_g, X txt_help_h, X txt_help_I, X txt_help_j, X txt_help_K, X txt_help_p_m, X txt_help_M, X txt_help_o, X txt_help_i_n, X txt_help_i_p, X txt_help_q, X txt_help_p_s, X txt_help_t, X txt_help_T, X txt_help_U, X txt_help_v, X txt_help_w, X txt_help_W, X txt_help_p_z, X txt_help_i_search, X txt_help_dash, X txt_help_pipe, X (char *) 0 X}; X Xchar *help_page[] = { X txt_help_p_0, X txt_help_p_4, X txt_help_ctrl_h, X txt_help_ctrl_k, X txt_help_ctrl_l, X txt_help_p_ctrl_r, X txt_help_p_cr, X txt_help_p_tab, X txt_help_b, X txt_help_a, X txt_help_bug_report, X txt_help_c, X txt_help_C, X txt_help_p_d, X txt_help_p_f, X txt_help_p_g, X txt_help_h, X txt_help_p_i, X txt_help_I, X txt_help_p_k, X txt_help_p_m, X txt_help_M, X txt_help_p_n, X txt_help_o, X txt_help_p_p, X txt_help_q, X txt_help_p_r, X txt_help_p_s, X txt_help_t, X txt_help_T, X txt_help_v, X txt_help_w, X txt_help_W, X txt_help_p_z, X txt_help_p_search, X txt_help_dash, X txt_help_pipe, X txt_help_thread, X (char *) 0 X}; X X Xvoid show_info_page (type, help, title) X int type; X char *help[]; X char *title; X{ X char buf[LEN+1]; X char ch; X int i, len; X int group_len = 0; X int old_page = 0; X int cur_page = 1; X int max_page = 1; X int pos_help = 0; X X if (NOTESLINES <= 0) { X return; X } X X /* X * find how many elements in array X */ X if (type == HELP_INFO) { X for (i=0 ; help[i] ; i++) { X continue; X } X } else { X for (i=0 ; posted[i].date[0] ; i++) { X len = strlen (posted[i].group); X if (len > group_len) { X group_len = len; X } X } X } X X max_page = i / NOTESLINES; X if (i % NOTESLINES) { X max_page++; X } X X while (1) { X if (cur_page != old_page) { X ClearScreen (); X sprintf (buf, title, cur_page, max_page); X center_line (0, TRUE, buf); X MoveCursor (INDEX_TOP, 0); X X if (type == HELP_INFO) { X for (i=pos_help ; i < (pos_help + NOTESLINES) && help[i] ; i++) { X printf ("%s", help[i]); X } X } else { X for (i=pos_help ; i < (pos_help + NOTESLINES) && posted[i].date[0] ; i++) { X sprintf (msg, "%8s %-*s %s", posted[i].date, X group_len, posted[i].group, posted[i].subj); X msg[COLS-2] = '\0'; X printf ("%s\r\n", msg); X } X } X } X X if (cur_page != old_page) { X center_line (LINES, FALSE, txt_hit_space_for_more); X } X X old_page = cur_page; X X ch = ReadCh (); X switch (ch) { X case 27: /* (ESC) common arrow keys */ X ch = ReadCh(); X if (ch == '[' || ch == 'O') X ch = ReadCh(); X switch (ch) { X case 'B': /* page down */ X case 'C': X case 'G': /* ansi */ X case 'U': /* at386 */ X if (cur_page < max_page) { X pos_help = cur_page*NOTESLINES; X cur_page++; X } X break; X X case 'A': /* page up */ X case 'D': X case 'i': X case 'I': /* ansi */ X case 'V': /* at386 */ X if (cur_page > 1) { X cur_page--; X pos_help = (cur_page-1)*NOTESLINES; X } X break; X X case 'H': /* at386 Home */ X if (cur_page != 1) { X cur_page = 1; X pos_help = 0; X } X break; X X case 'F': /* ansi End */ X case 'Y': /* at386 End */ X if (cur_page != max_page) { X cur_page = max_page; X pos_help = (max_page-1) * NOTESLINES; X } X break; X } X break; X X case ctrl('D'): /* page down */ X case ' ': X if (cur_page < max_page) { X pos_help = cur_page*NOTESLINES; X cur_page++; X } X break; X X case ctrl('U'): /* page up */ X case 'b': X if (cur_page > 1) { X cur_page--; X pos_help = (cur_page-1)*NOTESLINES; X } X break; X X case ctrl('R'): /* Home */ X if (cur_page != 1) { X cur_page = 1; X pos_help = 0; X } X break; X X case '$': /* End */ X if (cur_page != max_page) { X cur_page = max_page; X pos_help = (max_page-1) * NOTESLINES; X } X break; X X default: X#ifndef USE_CLEARSCREEN X ClearScreen (); X#endif X return; X } X } X} X X Xvoid help_select_info () X{ X} X X Xvoid help_group_info () X{ X} X X Xvoid help_page_info () X{ X} SHAR_EOF $TOUCH -am 0924083991 help.c && chmod 0600 help.c || echo "restore of help.c failed" set `wc -c help.c`;Wc_c=$1 if test "$Wc_c" != "5124"; then echo original size 5124, 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 : 28-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 set_real_uid_gid (); X X if ((fp = fopen (killfile, "r")) != NULL) { X kill_num=0; X while (fgets (buf, sizeof buf, fp) != NULL) { X if (buf[0] != '#') { X if (kill_num == max_kill-1) { X expand_kill (); X } X killf[kill_num].kill_type = (int) atoi (buf); X if (fgets (buf, sizeof buf, fp) != NULL) { X killf[kill_num].kill_group = (long) atol (buf); X } else { X goto corrupt_killfile; X } X switch (killf[kill_num].kill_type) { X case KILL_SUBJ: X if (fgets (buf, sizeof buf, 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, sizeof buf, 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, sizeof buf, fp) != NULL) { X buf[strlen (buf)-1] = '\0'; X killf[kill_num].kill_subj = str_dup (buf); X } X if (fgets (buf, sizeof buf, 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 set_tin_uid_gid (); X return TRUE; X } else { X set_tin_uid_gid (); 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 set_tin_uid_gid (); 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 set_real_uid_gid (); 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 set_tin_uid_gid (); 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; SHAR_EOF echo "End of tin1.02 part 3" echo "File kill.c is continued in part 4" echo "4" > shar3_seq_.tmp exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.