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 >
Internet Message Format  |  1991-08-23  |  51KB

  1. Path: wupost!uunet!mcsun!unido!estevax!norisc!iain
  2. From: iain@norisc.UUCP (Iain Lea)
  3. Newsgroups: alt.sources
  4. Subject: tin v1.00 - YAN (Yet Another Newsreader) Part 02/08
  5. Message-ID: <583@norisc.UUCP>
  6. Date: 23 Aug 91 13:51:40 GMT
  7. Sender: iain@norisc.UUCP (Iain Lea)
  8. Organization: What organization?
  9. Lines: 2261
  10.  
  11. Submitted-by: iain@estevax.uucp
  12. Archive-name: tin/part02
  13.  
  14. #!/bin/sh
  15. # this is tin.shar.02 (part 2 of tin)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file art.c continued
  18. #
  19. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  20.  then TOUCH=touch
  21.  else TOUCH=true
  22. fi
  23. if test ! -r shar3_seq_.tmp; then
  24.     echo "Please unpack part 1 first!"
  25.     exit 1
  26. fi
  27. (read Scheck
  28.  if test "$Scheck" != 2; then
  29.     echo "Please unpack part $Scheck next!"
  30.     exit 1
  31.  else
  32.     exit 0
  33.  fi
  34. ) < shar3_seq_.tmp || exit 1
  35. echo "x - Continuing file art.c"
  36. sed 's/^X//' << 'SHAR_EOF' >> art.c &&
  37. X        return -1;
  38. X    }
  39. X    /* s1->from greater than s2->from */
  40. X    if (strcmp (s1->from, s2->from) > 0) {
  41. X        return 1;
  42. X    }
  43. X    return 0;
  44. X}
  45. X
  46. X
  47. Xint date_comp (s1, s2)
  48. X    struct header *s1;
  49. X    struct header *s2;
  50. X{
  51. X    /* s1->date less than s2->date */
  52. X    if (strcmp (s1->date, s2->date) < 0) {
  53. X        return -1;
  54. X    }
  55. X    /* s1->date greater than s2->date */
  56. X    if (strcmp (s1->date, s2->date) > 0) {
  57. X        return 1;
  58. X    }
  59. X    return 0;
  60. X}
  61. X
  62. X
  63. Xset_article (art)
  64. X    struct header *art;
  65. X{    
  66. X    art->subject = (char *) 0;
  67. X    art->from = (char *) 0;
  68. X    art->date[0] = '\0';
  69. X    art->archive = (char *) 0;
  70. X    art->part = (char *) 0;
  71. X    art->patch = (char *) 0;
  72. X    art->unread = ART_UNREAD;
  73. X    art->inthread = FALSE;
  74. X    art->tagged = FALSE;
  75. X}
  76. SHAR_EOF
  77. echo "File art.c is complete" &&
  78. $TOUCH -am 0822182791 art.c &&
  79. chmod 0600 art.c ||
  80. echo "restore of art.c failed"
  81. set `wc -c art.c`;Wc_c=$1
  82. if test "$Wc_c" != "23276"; then
  83.     echo original size 23276, current size $Wc_c
  84. fi
  85. # ============= curses.c ==============
  86. echo "x - extracting curses.c (Text)"
  87. sed 's/^X//' << 'SHAR_EOF' > curses.c &&
  88. X/*
  89. X *  curses.c
  90. X */
  91. X/*
  92. X *  This is a screen management library borrowed with permission from the
  93. X *  Elm mail system (a great mailer--I highly recommend it!).
  94. X *
  95. X *  I've hacked this library to only provide what Tass needs.
  96. X *
  97. X *  Original copyright follows:
  98. X */
  99. X
  100. X/*******************************************************************************
  101. X *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
  102. X *
  103. X *             Copyright (c) 1986 Dave Taylor
  104. X ******************************************************************************/
  105. X
  106. X#include <stdio.h>
  107. X#include <curses.h>
  108. X#include <sys/ioctl.h>
  109. X
  110. X#ifdef TRUE
  111. X#undef TRUE
  112. X#define        TRUE        1
  113. X#endif
  114. X
  115. X#ifdef FALSE
  116. X#undef FALSE
  117. X#define        FALSE        0
  118. X#endif
  119. X
  120. X#define        BACKSPACE    '\b'
  121. X#define        VERY_LONG_STRING    2500
  122. X
  123. Xint LINES=23;
  124. Xint COLS=80;
  125. X
  126. Xint inverse_okay = TRUE;
  127. X
  128. X#ifdef BSD
  129. X#  ifndef BSD4_1
  130. X#    include <sgtty.h>
  131. X#  else
  132. X#    include <termio.h>
  133. X#  endif
  134. X#else
  135. X#  ifndef SYSV
  136. X#    include <termio.h>
  137. X#  endif
  138. X#endif
  139. X
  140. X
  141. X#include <ctype.h>
  142. X
  143. X/*
  144. X#ifdef BSD
  145. X#undef tolower
  146. X#endif
  147. X*/
  148. X
  149. X#define TTYIN    0
  150. X
  151. X#ifdef SHORTNAMES
  152. X# define _clearinverse    _clrinv
  153. X# define _cleartoeoln    _clrtoeoln
  154. X# define _cleartoeos    _clr2eos
  155. X#endif
  156. X
  157. X#ifndef BSD
  158. Xstruct termio _raw_tty, 
  159. X              _original_tty;
  160. X#else
  161. X#define TCGETA    TIOCGETP
  162. X#define TCSETAW    TIOCSETP
  163. X
  164. Xstruct sgttyb _raw_tty,
  165. X          _original_tty;
  166. X#endif
  167. X
  168. Xstatic int _inraw = 0;                  /* are we IN rawmode?    */
  169. X
  170. X#define DEFAULT_LINES_ON_TERMINAL    24
  171. X#define DEFAULT_COLUMNS_ON_TERMINAL    80
  172. X
  173. Xstatic
  174. Xchar *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
  175. X    *_setinverse, *_clearinverse, *_setunderline, *_clearunderline;
  176. X
  177. Xstatic
  178. Xint _lines,_columns;
  179. X
  180. Xstatic char _terminal[1024];              /* Storage for terminal entry */
  181. Xstatic char _capabilities[1024];           /* String for cursor motion */
  182. X
  183. Xstatic char *ptr = _capabilities;    /* for buffering         */
  184. X
  185. Xint    outchar();            /* char output for tputs */
  186. Xchar  *tgetstr(),                    /* Get termcap capability */
  187. X      *tgoto();                /* and the goto stuff    */
  188. X
  189. Xint InitScreen()
  190. X{
  191. X    int  tgetent(),      /* get termcap entry */
  192. X         err;
  193. X    char termname[40];
  194. X    char *strcpy(), *getenv();
  195. X    
  196. X    if (getenv("TERM") == NULL) {
  197. X        fprintf(stderr,
  198. X          "TERM variable not set; Tass requires screen capabilities\n");
  199. X        return(FALSE);
  200. X    }
  201. X    if (strcpy(termname, getenv("TERM")) == NULL) {
  202. X        fprintf(stderr,"Can't get TERM variable\n");
  203. X        return(FALSE);
  204. X    }
  205. X    if ((err = tgetent(_terminal, termname)) != 1) {
  206. X        fprintf(stderr,"Can't get entry for TERM\n");
  207. X        return(FALSE);
  208. X    }
  209. X
  210. X    /* load in all those pesky values */
  211. X    _clearscreen       = tgetstr("cl", &ptr);
  212. X    _moveto            = tgetstr("cm", &ptr);
  213. X    _cleartoeoln       = tgetstr("ce", &ptr);
  214. X    _cleartoeos        = tgetstr("cd", &ptr);
  215. X    _lines                 = tgetnum("li");
  216. X    _columns       = tgetnum("co");
  217. X    _setinverse        = tgetstr("so", &ptr);
  218. X    _clearinverse      = tgetstr("se", &ptr);
  219. X    _setunderline      = tgetstr("us", &ptr);
  220. X    _clearunderline    = tgetstr("ue", &ptr);
  221. X
  222. X    if (!_clearscreen) {
  223. X        fprintf(stderr,
  224. X            "Terminal must have clearscreen (cl) capability\n");
  225. X        return(FALSE);
  226. X    }
  227. X    if (!_moveto) {
  228. X        fprintf(stderr,
  229. X            "Terminal must have cursor motion (cm)\n");
  230. X        return(FALSE);
  231. X    }
  232. X    if (!_cleartoeoln) {
  233. X        fprintf(stderr,
  234. X            "Terminal must have clear to end-of-line (ce)\n");
  235. X        return(FALSE);
  236. X    }
  237. X    if (!_cleartoeos) {
  238. X        fprintf(stderr,
  239. X            "Terminal must have clear to end-of-screen (cd)\n");
  240. X        return(FALSE);
  241. X    }
  242. X    if (_lines == -1)
  243. X        _lines = DEFAULT_LINES_ON_TERMINAL;
  244. X    if (_columns == -1)
  245. X        _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  246. X    return(TRUE);
  247. X}
  248. X
  249. Xvoid ScreenSize(num_lines, num_columns)
  250. X    int *num_lines, *num_columns;
  251. X{
  252. X    /** returns the number of lines and columns on the display. **/
  253. X
  254. X    if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
  255. X    if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  256. X
  257. X    *num_lines = _lines - 1;        /* assume index from zero*/
  258. X    *num_columns = _columns;        /* assume index from one */
  259. X}
  260. X
  261. Xvoid ClearScreen()
  262. X{
  263. X    /* clear the screen: returns -1 if not capable */
  264. X
  265. X    tputs(_clearscreen, 1, outchar);
  266. X    fflush(stdout);      /* clear the output buffer */
  267. X}
  268. X
  269. Xvoid MoveCursor(row, col)
  270. Xint row, col;
  271. X{
  272. X    /** move cursor to the specified row column on the screen.
  273. X            0,0 is the top left! **/
  274. X
  275. X    char *stuff, *tgoto();
  276. X
  277. X    stuff = tgoto(_moveto, col, row);
  278. X    tputs(stuff, 1, outchar);
  279. X    fflush(stdout);
  280. X}
  281. X
  282. Xvoid CleartoEOLN()
  283. X{
  284. X    /** clear to end of line **/
  285. X
  286. X    tputs(_cleartoeoln, 1, outchar);
  287. X    fflush(stdout);  /* clear the output buffer */
  288. X}
  289. X
  290. Xvoid CleartoEOS()
  291. X{
  292. X    /** clear to end of screen **/
  293. X
  294. X    tputs(_cleartoeos, 1, outchar);
  295. X    fflush(stdout);  /* clear the output buffer */
  296. X}
  297. X
  298. X
  299. Xvoid StartInverse()
  300. X{
  301. X    /** set inverse video mode **/
  302. X
  303. X    if (_setinverse && inverse_okay)
  304. X        tputs(_setinverse, 1, outchar);
  305. X/*    fflush(stdout);    */
  306. X}
  307. X
  308. X
  309. Xvoid EndInverse()
  310. X{
  311. X    /** compliment of startinverse **/
  312. X
  313. X    if (_clearinverse && inverse_okay)
  314. X        tputs(_clearinverse, 1, outchar);
  315. X/*    fflush(stdout);    */
  316. X}
  317. X
  318. X
  319. Xint RawState()
  320. X{
  321. X    /** returns either 1 or 0, for ON or OFF **/
  322. X
  323. X    return( _inraw );
  324. X}
  325. X
  326. X
  327. Xvoid Raw(state)
  328. X    int state;
  329. X{
  330. X    /** state is either TRUE or FALSE, as indicated by call **/
  331. X
  332. X    if (state == FALSE && _inraw) {
  333. X      (void) ioctl(TTYIN, TCSETAW, &_original_tty);
  334. X      _inraw = 0;
  335. X    }
  336. X    else if (state == TRUE && ! _inraw) {
  337. X
  338. X      (void) ioctl(TTYIN, TCGETA, &_original_tty);    /** current setting **/
  339. X
  340. X      (void) ioctl(TTYIN, TCGETA, &_raw_tty);    /** again! **/
  341. X#ifdef BSD
  342. X      _raw_tty.sg_flags &= ~(ECHO | CRMOD);    /* echo off */
  343. X      _raw_tty.sg_flags |= CBREAK;    /* raw on    */
  344. X#else
  345. X      _raw_tty.c_lflag &= ~(ICANON | ECHO);    /* noecho raw mode        */
  346. X
  347. X      _raw_tty.c_cc[VMIN] = '\01';    /* minimum # of chars to queue    */
  348. X      _raw_tty.c_cc[VTIME] = '\0';    /* minimum time to wait for input */
  349. X#endif
  350. X
  351. X      (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
  352. X
  353. X      _inraw = 1;
  354. X    }
  355. X}
  356. X
  357. Xint ReadCh()
  358. X{
  359. X    /** read a character with Raw mode set! **/
  360. X
  361. X    register int result;
  362. X    char ch;
  363. X    result = read(0, &ch, 1);
  364. X        return((result <= 0 ) ? EOF : ch & 0x7F);
  365. X}
  366. X
  367. X
  368. Xint outchar(c)
  369. Xchar c;
  370. X{
  371. X    /** output the given character.  From tputs... **/
  372. X    /** Note: this CANNOT be a macro!              **/
  373. X
  374. X    putc(c, stdout);
  375. X}
  376. X
  377. SHAR_EOF
  378. $TOUCH -am 0819150191 curses.c &&
  379. chmod 0600 curses.c ||
  380. echo "restore of curses.c failed"
  381. set `wc -c curses.c`;Wc_c=$1
  382. if test "$Wc_c" != "6075"; then
  383.     echo original size 6075, current size $Wc_c
  384. fi
  385. # ============= debug.c ==============
  386. echo "x - extracting debug.c (Text)"
  387. sed 's/^X//' << 'SHAR_EOF' > debug.c &&
  388. X/*
  389. X *  Project   : tin - a visual threaded usenet newsreader
  390. X *  Module    : debug.c
  391. X *  Author    : I.Lea
  392. X *  Created   : 01-04-91
  393. X *  Updated   : 22-08-91
  394. X *  Release   : 1.0
  395. X *  Notes     : debug routines
  396. X *  Copyright : (c) Copyright 1991 by Iain Lea
  397. X *                You may  freely  copy or  redistribute  this software,
  398. X *              so  long as there is no profit made from its use, sale
  399. X *              trade or  reproduction.  You may not change this copy-
  400. X *              right notice, and it must be included in any copy made
  401. X */
  402. X
  403. X#include "tin.h"
  404. X
  405. Xint debug;
  406. X
  407. X
  408. Xdebug_print_arts ()
  409. X{
  410. X    int i;
  411. X
  412. X    if (! debug)
  413. X        return;
  414. X
  415. X    for (i = 0; i < top; i++) {    /* for each group */
  416. X        debug_print_header (&arts[i]);
  417. X    }
  418. X}
  419. X
  420. X
  421. Xvoid debug_print_header (s)
  422. X    struct header *s;
  423. X{
  424. X    FILE *fp;
  425. X
  426. X    if (! debug)
  427. X        return;
  428. X
  429. X    if ((fp = fopen ("/tmp/DUMP","a+")) != NULL) {
  430. X        fprintf (fp,"art=[%5ld] killed=[%s]\n", s->artnum,
  431. X        (s->tagged ? "TRUE" : "FALSE"));
  432. X        fprintf (fp,"subj=[%-38s]  from=[%-20s]\n", s->subject, s->from);
  433. X        fprintf (fp,"arch=[%-38s]  part=[%s]  patch=[%s]\n", s->archive, s->part, s->patch);
  434. X        fprintf (fp,"thread=[%s]  inthread=[%s]  unread=[%s]\n",
  435. X        (s->thread == ART_NORMAL ? "ART_NORMAL" : "ART_EXPIRED"),
  436. X        (s->inthread ? "TRUE" : "FALSE"),
  437. X        (s->unread ? "TRUE" : "FALSE"));
  438. X        fflush (fp);
  439. X        fclose (fp);
  440. X        chmod ("/tmp/DUMP", 0666);
  441. X    }
  442. X}
  443. X
  444. X
  445. Xdebug_print_comment (comment)
  446. X    char *comment;
  447. X{
  448. X    FILE *fp;
  449. X
  450. X    if (! debug)
  451. X        return;
  452. X
  453. X    if ((fp = fopen ("/tmp/BASE","a+")) != NULL) {
  454. X        fprintf (fp,"\n%s\n\n", comment);
  455. X        fflush (fp);
  456. X        fclose (fp);
  457. X        chmod ("/tmp/BASE", 0666);
  458. X    }
  459. X}
  460. X
  461. X
  462. Xvoid debug_print_base ()
  463. X{
  464. X    FILE *fp;
  465. X    int i;
  466. X
  467. X    if (! debug)
  468. X        return;
  469. X
  470. X    if ((fp = fopen ("/tmp/BASE","a+")) != NULL) {
  471. X        for (i = 0; i < top_base; i++) {
  472. X            fprintf (fp, "base[%3d]=[%5ld]\n",i,base[i]);
  473. X        }
  474. X        fflush (fp);
  475. X        fclose (fp);
  476. X        chmod ("/tmp/BASE", 0666);
  477. X    }
  478. X}
  479. X
  480. X
  481. Xvoid debug_print_active ()
  482. X{
  483. X    FILE *fp;
  484. X    int i;
  485. X
  486. X    if (! debug)
  487. X        return;
  488. X
  489. X    if ((fp = fopen ("/tmp/ACTIVE","w")) != NULL) {
  490. X        for (i = 0; i < num_active; i++) {    /* for each group */
  491. X            fprintf (fp, "[%4d]=[%-28s] max=[%4ld] min=[%4ld] nxt=[%4d] flag=[%d]\n",
  492. X                i, active[i].name, active[i].max, active[i].min, active[i].next, active[i].flag);
  493. X        }
  494. X        fflush (fp);
  495. X        fclose (fp);
  496. X        chmod ("/tmp/ACTIVE", 0666);
  497. X    }
  498. X}
  499. SHAR_EOF
  500. $TOUCH -am 0822123191 debug.c &&
  501. chmod 0600 debug.c ||
  502. echo "restore of debug.c failed"
  503. set `wc -c debug.c`;Wc_c=$1
  504. if test "$Wc_c" != "2276"; then
  505.     echo original size 2276, current size $Wc_c
  506. fi
  507. # ============= group.c ==============
  508. echo "x - extracting group.c (Text)"
  509. sed 's/^X//' << 'SHAR_EOF' > group.c &&
  510. X/*
  511. X *  Project   : tin - a visual threaded usenet newsreader
  512. X *  Module    : group.c
  513. X *  Author    : R.Skrenta / I.Lea
  514. X *  Created   : 01-04-91
  515. X *  Updated   : 13-08-91
  516. X *  Release   : 1.0
  517. X *  Notes     :
  518. X *  Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
  519. X *                You may  freely  copy or  redistribute  this software,
  520. X *              so  long as there is no profit made from its use, sale
  521. X *              trade or  reproduction.  You may not change this copy-
  522. X *              right notice, and it must be included in any copy made
  523. X */
  524. X
  525. X#include    "tin.h"
  526. X
  527. Xextern char cvers[LEN+1];
  528. Xextern int cur_groupnum;
  529. Xextern int last_resp;        /* page.c */
  530. Xextern int this_resp;        /* page.c */
  531. Xextern int space_mode;        /* select.c */
  532. X
  533. Xchar *glob_group;
  534. Xint index_point;
  535. Xint first_subj_on_screen;
  536. Xint last_subj_on_screen;
  537. X
  538. X
  539. X#ifdef SIGTSTP
  540. Xvoid group_susp (sig)
  541. X    int sig;
  542. X{
  543. X    Raw(FALSE);
  544. X    putchar('\n');
  545. X    signal(SIGTSTP, SIG_DFL);
  546. X#ifdef BSD
  547. X    sigsetmask(sigblock(0) & ~(1 << (SIGTSTP -1)));
  548. X#endif
  549. X    kill(0, SIGTSTP);
  550. X
  551. X    signal(SIGTSTP, group_susp);
  552. X
  553. X    if (! update) {
  554. X        Raw(TRUE);
  555. X    }
  556. X    
  557. X#ifndef USE_CLEARSCREEN
  558. X    ClearScreen ();
  559. X#endif
  560. X    mail_setup();
  561. X    show_group_page(glob_group);
  562. X}
  563. X#endif
  564. X
  565. X
  566. Xvoid group_page (group)
  567. X    char *group;
  568. X{
  569. X    char buf[LEN+1];
  570. X    char group_path[LEN+1];
  571. X    char ch;
  572. X    char *p;
  573. X    int flag, i, n;
  574. X    int kill_state;
  575. X    long old_artnum;
  576. X    int old_top;
  577. X    int ret1, ret2;
  578. X    int sav_groupnum;
  579. X    int thread_marked_unread = FALSE;
  580. X
  581. X    glob_group = group;
  582. X    sav_groupnum = cur_groupnum;
  583. X    
  584. X    strcpy (group_path, group);            /* turn comp.unix.amiga into */
  585. X    for (p = group_path; *p; p++)        /* comp/unix/amiga */
  586. X        if (*p == '.')
  587. X            *p = '/';
  588. X
  589. X    last_resp = -1;
  590. X    this_resp = -1;
  591. X    index_group (group, group_path);    /* update index file */
  592. X    read_newsrc_line (group);            /* get sequencer information */
  593. X
  594. X    if (space_mode) {
  595. X        for (i = 0; i < top_base; i++) {
  596. X            if (new_responses (i)) {
  597. X                break;
  598. X            }
  599. X        }
  600. X        if (i < top_base) {
  601. X            index_point = i;
  602. X        } else {
  603. X            index_point = top_base - 1;
  604. X        }
  605. X    } else {
  606. X        index_point = top_base - 1;
  607. X    }
  608. X    
  609. X    clear_note_area ();
  610. X
  611. X    show_group_page (group);
  612. X
  613. X    while (1) {
  614. X        ch = ReadCh();
  615. X
  616. X        if (ch > '0' && ch <= '9') {    /* 0 goes to basenote */
  617. X            prompt_subject_num(ch, group);
  618. X        } else switch (ch) {
  619. X            case '!':
  620. X                shell_escape ();
  621. X                show_group_page (group);
  622. X                break;
  623. X
  624. X            case '$':    /* show last page of articles */
  625. Xend_of_list:            
  626. X                index_point = top_base - 1;
  627. X                show_group_page (group);
  628. X                break;
  629. X                
  630. X            case '-':    /* go to last viewed article */
  631. X                if (this_resp < 0) {
  632. X                    info_message(txt_no_last_message);
  633. X                    break;
  634. X                }
  635. X                index_point = show_page (this_resp, group, group_path);
  636. X                if (index_point < 0) {
  637. X                    space_mode = FALSE;
  638. X                    goto group_done;
  639. X                }
  640. X                clear_note_area ();
  641. X                show_group_page (group);
  642. X                break;
  643. X
  644. X            case '/':    /* forward/backward search */
  645. X            case '?':
  646. X                i = (ch == '/');
  647. X                search_subject (i, group);
  648. X                break;
  649. X
  650. X            case '\r':
  651. X            case '\n':    /* read current basenote */
  652. X                if (index_point < 0) {
  653. X                    info_message(txt_no_arts);
  654. X                    break;
  655. X                }
  656. X                i = (int) base[index_point];
  657. X                index_point = show_page(i, group, group_path);
  658. X                if (index_point < 0) {
  659. X                    space_mode = FALSE;
  660. X                    goto group_done;
  661. X                }
  662. X                clear_note_area ();
  663. X                show_group_page (group);
  664. X                break;
  665. X
  666. X            case '\t':
  667. X                space_mode = TRUE;
  668. X
  669. X                if (index_point < 0
  670. X                || (n=next_unread((int) base[index_point]))<0) {
  671. X                    for (i = cur_groupnum+1;
  672. X                            i < local_top; i++)
  673. X                        if (unread[i] > 0)
  674. X                            break;
  675. X                    if (i >= local_top)
  676. X                        goto group_done;
  677. X
  678. X                    cur_groupnum = i;
  679. X                    index_point = -3;
  680. X                    goto group_done;
  681. X                }
  682. X                index_point = show_page(n, group, group_path);
  683. X                if (index_point < 0)
  684. X                    goto group_done;
  685. X                clear_note_area ();
  686. X                show_group_page(group);
  687. X                break;
  688. X    
  689. X            case 27:    /* common arrow keys */
  690. X                ch = ReadCh();
  691. X                if (ch == '[' || ch == 'O')
  692. X                    ch = ReadCh();
  693. X                switch (ch) {
  694. X                case 'A':
  695. X                case 'D':
  696. X                    goto group_up;
  697. X
  698. X                case 'B':
  699. X                case 'C':
  700. X                    goto group_down;
  701. X
  702. X                case 'G':        /* ansi  PgDn */
  703. X                case 'U':        /* at386 PgDn */
  704. X                    goto group_page_down;
  705. X
  706. X                case 'I':        /* ansi  PgUp */
  707. X                case 'V':        /* at386 PgUp */
  708. X                    goto group_page_up;
  709. X
  710. X                case 'H':        /* at386  Home */
  711. X                    index_point = 0;
  712. X                    show_group_page (group);
  713. X                    break;
  714. X                    
  715. X                case 'F':        /* ansi  End */
  716. X                case 'Y':        /* at386  End */
  717. X                    goto end_of_list;
  718. X                }
  719. X                break;
  720. X
  721. X            case ctrl('D'):        /* page down */
  722. X            case ' ':    
  723. Xgroup_page_down:
  724. X                if (!top_base || index_point == top_base - 1)
  725. X                    break;
  726. X
  727. X                erase_subject_arrow();
  728. X                index_point += NOTESLINES / 2;
  729. X                if (index_point >= top_base)
  730. X                    index_point = top_base - 1;
  731. X
  732. X                if (index_point < first_subj_on_screen
  733. X                || index_point >= last_subj_on_screen)
  734. X                    show_group_page(group);
  735. X                else
  736. X                    draw_subject_arrow();
  737. X                break;
  738. X
  739. X            case ctrl('K'):        /* kill article */
  740. X                 if (index_point < 0) {
  741. X                     info_message (txt_no_arts);
  742. X                    break;
  743. X                }
  744. X                if (kill_articles) {
  745. X                    old_top = top;
  746. X                    n = base[index_point];
  747. X                    old_artnum = arts[n].artnum;
  748. X                    if (kill_art_menu (group, (int) base[index_point])) {
  749. X                        kill_any_articles (group);
  750. X                        reload_index_file (group, TRUE);
  751. X                        index_point = find_new_pos (old_top, old_artnum, index_point);
  752. X                    }
  753. X                    show_group_page (group);
  754. X                } else {
  755. X                    info_message (txt_switch_on_kill_art_menu);
  756. X                }
  757. X                break;
  758. X
  759. X            case ctrl('L'):        /* return to index */
  760. X            case ctrl('R'):
  761. X            case ctrl('W'):
  762. X#ifndef USE_CLEARSCREEN
  763. X                ClearScreen ();
  764. X#endif
  765. X                show_group_page(group);
  766. X                break;
  767. X
  768. X            case ctrl('N'):
  769. X            case 'j':        /* line down */
  770. Xgroup_down:
  771. X                if (!top_base || index_point + 1 >= top_base)
  772. X                    break;
  773. X
  774. X                if (index_point + 1 >= last_subj_on_screen) {
  775. X#ifndef USE_CLEARSCREEN
  776. X                    erase_subject_arrow();
  777. X#endif                    
  778. X                    index_point++;
  779. X                    show_group_page(group);
  780. X                } else {
  781. X                    erase_subject_arrow();
  782. X                    index_point++;
  783. X                    draw_subject_arrow();
  784. X                }
  785. X                break;
  786. X
  787. X            case ctrl('P'):
  788. X            case 'k':        /* line up */
  789. Xgroup_up:
  790. X                if (!top_base || !index_point)
  791. X                    break;
  792. X
  793. X                if (index_point <= first_subj_on_screen) {
  794. X                    index_point--;
  795. X                    show_group_page(group);
  796. X                } else {
  797. X                    erase_subject_arrow();
  798. X                    index_point--;
  799. X                    draw_subject_arrow();
  800. X                }
  801. X                break;
  802. X
  803. X            case ctrl('U'):        /* page up */
  804. X            case 'b':
  805. Xgroup_page_up:
  806. X                if (!top_base)
  807. X                    break;
  808. X
  809. X#ifndef USE_CLEARSCREEN
  810. X                clear_message ();
  811. X#endif
  812. X                erase_subject_arrow();
  813. X                index_point -= NOTESLINES / 2;
  814. X                if (index_point < 0)
  815. X                    index_point = 0;
  816. X                if (index_point < first_subj_on_screen
  817. X                || index_point >= last_subj_on_screen)
  818. X                    show_group_page(group);
  819. X                else
  820. X                    draw_subject_arrow();
  821. X                break;
  822. X
  823. X            case 'a':    /* author search forward */
  824. X            case 'A':    /* author search backward */
  825. X                if (index_point < 0) {
  826. X                    info_message(txt_no_arts);
  827. X                    break;
  828. X                }
  829. X
  830. X                i = (ch == 'a');
  831. X
  832. X                n = search_author((int) base[index_point], i);
  833. X                if (n < 0)
  834. X                    break;
  835. X
  836. X                index_point = show_page(n, group, group_path);
  837. X                if (index_point < 0) {
  838. X                    space_mode = FALSE;
  839. X                    goto group_done;
  840. X                }
  841. X                clear_note_area ();
  842. X                show_group_page (group);
  843. X                break;
  844. X
  845. X            case 'B':    /* bug/gripe/comment mailed to author */
  846. X                mail_bug_report ();
  847. X#ifndef USE_CLEARSCREEN
  848. X                ClearScreen ();
  849. X#endif
  850. X                show_group_page (group);
  851. X                break;
  852. X                
  853. X            case 'c':    /* catchup--mark all articles as read */
  854. X                if (prompt_yn (LINES, txt_mark_all_read, 'y')) {
  855. X                    for (n = 0; n < top; n++) {
  856. X                        arts[n].unread = ART_READ;
  857. X                    }
  858. X                    if (cur_groupnum + 1 < local_top) {
  859. X                        cur_groupnum++;
  860. X                    }
  861. X                    goto group_done;
  862. X                }
  863. X                break;
  864. X
  865. X            case 'g':    /* choose a new group by name */
  866. X                n = choose_new_group ();
  867. X                if (n >= 0 && n != cur_groupnum) {
  868. X                    cur_groupnum = n;
  869. X                    index_point = -3;
  870. X                    goto group_done;
  871. X                }
  872. X                break;
  873. X
  874. X            case 'h':
  875. X                help_group_commands ();
  876. X                show_group_page (group);
  877. X                break;
  878. X
  879. X            case 'H':
  880. X                help_group_info ();
  881. X                show_group_page (group);
  882. X                break;
  883. X
  884. X            case 'I':    /* toggle inverse video */
  885. X                inverse_okay = !inverse_okay;
  886. X                if (inverse_okay)
  887. X                    info_message(txt_inverse_on);
  888. X                else
  889. X                    info_message(txt_inverse_off);
  890. X                show_group_page(group);
  891. X                break;
  892. X
  893. X            case 'K':    /* mark rest of thread as read */
  894. X                if (index_point < 0) {
  895. X                    info_message (txt_no_next_unread_art);
  896. X                    break;
  897. X                }
  898. X                if (new_responses (index_point)) {
  899. X                    for (i = base[index_point]; i >= 0; i = arts[i].thread)
  900. X                        arts[i].unread = 0;
  901. X                    if (draw_arrow_mark) {
  902. X                        MoveCursor(INDEX_TOP + (index_point - first_subj_on_screen), 8);
  903. X                        putchar(' ');
  904. X                        MoveCursor (LINES, 0);
  905. X                        fflush(stdout);
  906. X                    } else {
  907. X                        i =    index_point-first_subj_on_screen;
  908. X                        screen[i].col[8] = ' ';
  909. X                        draw_subject_arrow();
  910. X                    }
  911. X                    flag = FALSE;
  912. X                } else
  913. X                    flag = TRUE;
  914. X
  915. X                n = next_unread (next_response ((int) base[index_point]));
  916. X                if (n < 0) {
  917. X                    if (flag)
  918. X                        info_message (txt_no_next_unread_art);
  919. X                    else
  920. X                        MoveCursor (LINES, 0);
  921. X                    break;
  922. X                }
  923. X
  924. X                if ((n = which_base(n)) < 0) {
  925. X                    info_message("Internal error: K which_base < 0");
  926. X                    break;
  927. X                }
  928. X
  929. X                if (n >= last_subj_on_screen) {
  930. X                    index_point = n;
  931. X                    show_group_page(group);
  932. X                } else {
  933. X                    erase_subject_arrow();
  934. X                    index_point = n;
  935. X                    draw_subject_arrow();
  936. X                }
  937. X                break;
  938. X
  939. X            case 'M':    /* options menu */
  940. X                old_top = top;
  941. X                n = base[index_point];
  942. X                old_artnum = arts[n].artnum;
  943. X                n = sort_art_type;
  944. X                kill_state = change_rcfile (group, TRUE);
  945. X                if (kill_state == NO_KILLING && n != sort_art_type) {
  946. X                    make_threads (TRUE);
  947. X                    find_base ();
  948. X                }
  949. X                index_point = find_new_pos (old_top, old_artnum, index_point);
  950. X                show_group_page (group);
  951. X                break;
  952. X
  953. X            case 'n':    /* next group */
  954. X                clear_message();
  955. X                if (cur_groupnum + 1 >= local_top)
  956. X                    info_message(txt_no_more_groups);
  957. X                else {
  958. X                    cur_groupnum++;
  959. X                    index_point = -3;
  960. X                    space_mode = FALSE;
  961. X                    goto group_done;
  962. X                }
  963. X                break;
  964. X
  965. X            case 'N':    /* go to next unread article */
  966. X                if (index_point < 0) {
  967. X                    info_message(txt_no_next_unread_art);
  968. X                    break;
  969. X                }
  970. X
  971. X                n = next_unread( (int) base[index_point]);
  972. X                if (n == -1)
  973. X                    info_message(txt_no_next_unread_art);
  974. X                else {
  975. X                    index_point = show_page(n, group, group_path);
  976. X                    if (index_point < 0) {
  977. X                        space_mode = FALSE;
  978. X                        goto group_done;
  979. X                    }
  980. X                    clear_note_area ();
  981. X                    show_group_page(group);
  982. X                }
  983. X                break;
  984. X
  985. X            case 'p':    /* previous group */
  986. X                clear_message();
  987. X                if (cur_groupnum <= 0)
  988. X                    info_message(txt_no_prev_group);
  989. X                else {
  990. X                    cur_groupnum--;
  991. X                    index_point = -3;
  992. X                    space_mode = FALSE;
  993. X                    goto group_done;
  994. X                }
  995. X                break;
  996. X
  997. X            case 'P':    /* go to previous unread article */
  998. X                if (index_point < 0) {
  999. X                    info_message(txt_no_prev_unread_art);
  1000. X                    break;
  1001. X                }
  1002. X                n = prev_response( (int) base[index_point]);
  1003. X                n = prev_unread(n);
  1004. X                if (n == -1)
  1005. X                    info_message(txt_no_prev_unread_art);
  1006. X                else {
  1007. X                    index_point = show_page (n, group, group_path);
  1008. X                    if (index_point < 0) {
  1009. X                        space_mode = FALSE;
  1010. X                        goto group_done;
  1011. X                    }
  1012. X                    clear_note_area ();
  1013. X                    show_group_page(group);
  1014. X                }
  1015. X                break;
  1016. X
  1017. X            case 'q':        /* quit */
  1018. X                index_point = -2;
  1019. X                space_mode = FALSE;
  1020. X                goto group_done;
  1021. X
  1022. X            case 's':    /* subscribe to this group */
  1023. X                subscribe(group, ':', my_group[cur_groupnum], TRUE);
  1024. X                sprintf(buf, txt_subscribed_to, group);
  1025. X                info_message(buf);
  1026. X                break;
  1027. X
  1028. X            case 'S':    /* save regex pattern to file/s */
  1029. X                n = save_regex_arts (group_path, group);
  1030. X                ret1 = post_process_files ();
  1031. X                ret2 = untag_all_articles ();
  1032. X                if (ret1 || ret2 || n) {
  1033. X                    show_group_page (group);
  1034. X                }
  1035. X                free_save_array ();
  1036. X                break;
  1037. X            
  1038. X            case 't':
  1039. X            case 'i':    /* return to group selection page */
  1040. X                goto group_done;
  1041. X
  1042. X            case 'T':    /* tag/untag article for saving */
  1043. X                 if (index_point >= 0) {
  1044. X                    if (arts[base[index_point]].tagged) {
  1045. X                        arts[base[index_point]].tagged = 0;
  1046. X                        show_group_page (group);
  1047. X                        info_message ("untagged");
  1048. X                    } else {
  1049. X                        arts[base[index_point]].tagged = ++num_of_tagged_files;
  1050. X                        show_group_page (group);
  1051. X                        info_message ("tagged for saving");
  1052. X                    }
  1053. X                }
  1054. X                break;
  1055. X
  1056. X            case 'u':    /* unsubscribe to this group */
  1057. X                subscribe(group, '!', my_group[cur_groupnum], TRUE);
  1058. X                sprintf(buf, txt_unsubscribed_to, group);
  1059. X                info_message(buf);
  1060. X                break;
  1061. X
  1062. X            case 'U':    /* untag all articles */
  1063. X                 if (index_point >= 0) {
  1064. X                    untag_all_articles ();
  1065. X                    show_group_page (group);
  1066. X                }
  1067. X                break;
  1068. X
  1069. X            case 'v':
  1070. X                info_message (cvers);
  1071. X                break;
  1072. X
  1073. X            case 'w':    /* post a basenote */
  1074. X                post_base (group);
  1075. X                update_newsrc (group, my_group[cur_groupnum]);
  1076. X                index_group (group, group_path);
  1077. X                read_newsrc_line (group);
  1078. X                index_point = top_base - 1;
  1079. X                show_group_page (group);
  1080. X                break;
  1081. X
  1082. X            case 'W':    /* display messages posted by user */
  1083. X                if (user_posted_messages ()) {
  1084. X                    show_group_page(group);
  1085. X                }
  1086. X                break;
  1087. X
  1088. X            case 'z':    /* mark article as unread (to return) */
  1089. X                 if (index_point < 0) {
  1090. X                     info_message (txt_no_arts);
  1091. X                    break;
  1092. X                }
  1093. X                i = base[index_point];
  1094. X                arts[i].unread = ART_UNREAD;
  1095. X                i = index_point-first_subj_on_screen;
  1096. X                screen[i].col[8] = '+';
  1097. X                if (draw_arrow_mark) {
  1098. X                    MoveCursor(INDEX_TOP + (index_point - first_subj_on_screen), 8);
  1099. X                    putchar ('+');
  1100. X                } else {
  1101. X                    draw_subject_arrow();
  1102. X                }
  1103. X                info_message(txt_art_marked_as_unread);
  1104. X                break;
  1105. X
  1106. X            case 'Z':    /* mark thread as unread */
  1107. X                 if (index_point < 0) {
  1108. X                     info_message (txt_no_arts);
  1109. X                    break;
  1110. X                }
  1111. X                for (i = base[index_point] ; i != -1 ; i = arts[i].thread) {
  1112. X                    arts[i].unread = ART_UNREAD;
  1113. X                    thread_marked_unread = TRUE;
  1114. X                }
  1115. X                if (thread_marked_unread) {
  1116. X                    i = index_point-first_subj_on_screen;
  1117. X                    screen[i].col[8] = '+';
  1118. X                    if (draw_arrow_mark) {
  1119. X                        MoveCursor(INDEX_TOP + (index_point - first_subj_on_screen), 8);
  1120. X                        putchar ('+');
  1121. X                    } else {
  1122. X                        draw_subject_arrow();
  1123. X                    }
  1124. X                    info_message(txt_thread_marked_as_unread);
  1125. X                    thread_marked_unread = FALSE;
  1126. X                }
  1127. X                break;
  1128. X
  1129. X            default:
  1130. X                info_message(txt_bad_command);
  1131. X        }
  1132. X    }
  1133. X
  1134. Xgroup_done:
  1135. X    fix_new_highest (sav_groupnum);
  1136. X    update_newsrc (group, my_group[sav_groupnum]);
  1137. X    clear_note_area ();
  1138. X
  1139. X    if (index_point == -2)
  1140. X        tin_done(0);
  1141. X}
  1142. X
  1143. X
  1144. X/*
  1145. X *  Correct highest[] for the group selection page display since
  1146. X *  new articles may have been read or marked unread
  1147. X */
  1148. X
  1149. Xvoid fix_new_highest (groupnum)
  1150. X    int groupnum;
  1151. X{
  1152. X    register int i;
  1153. X    int sum = 0;
  1154. X
  1155. X    for (i = 0; i < top; i++) {
  1156. X        if (arts[i].unread) {
  1157. X            sum++;
  1158. X        }
  1159. X    }
  1160. X    
  1161. X    unread[groupnum] = sum;
  1162. X}
  1163. X
  1164. X
  1165. Xvoid show_group_page (group)
  1166. X    char *group;
  1167. X{
  1168. X    char new_resps[8];
  1169. X    char resps[8];
  1170. X    char from[LEN+1];
  1171. X    char subject[LEN+1];
  1172. X    int i, j;
  1173. X    int n;
  1174. X    int respnum;
  1175. X
  1176. X#ifdef SIGTSTP
  1177. X    signal(SIGTSTP, group_susp);
  1178. X#endif
  1179. X
  1180. X#ifdef USE_CLEARSCREEN
  1181. X    ClearScreen();
  1182. X#else
  1183. X    MoveCursor(0, 0);        /* top left corner */
  1184. X    CleartoEOLN ();
  1185. X#endif
  1186. X
  1187. X    printf("%s\r\n", nice_time());    /* time in upper left */
  1188. X
  1189. X#ifndef USE_CLEARSCREEN
  1190. X    MoveCursor(1, 0);
  1191. X    CleartoEOLN ();
  1192. X    MoveCursor(2, 0);
  1193. X    CleartoEOLN ();
  1194. X#endif
  1195. X
  1196. X    StartInverse();
  1197. X    center_line(1, group);
  1198. X    EndInverse();
  1199. X
  1200. X    MoveCursor(0, (COLS - (int) strlen (txt_type_h_for_help))+1);    /* upper right */
  1201. X    if (mail_check()) {            /* you have mail message in */
  1202. X        printf(txt_you_have_mail);
  1203. X    } else {
  1204. X        printf(txt_type_h_for_help);
  1205. X    }
  1206. X
  1207. X    MoveCursor(1, (COLS - (int) strlen (txt_type_h_for_help))+1);    /* in upper middle */
  1208. X    if (kill_articles) {        /* display KILL on screen */
  1209. X        printf("KILL ON   ");
  1210. X    } else {
  1211. X        printf("          ");
  1212. X    }
  1213. X    if (post_process) {        /* display POST on screen */
  1214. X        printf("POST ON");
  1215. X    } else {
  1216. X        printf("       ");
  1217. X    }
  1218. X        
  1219. X    MoveCursor(INDEX_TOP, 0);
  1220. X
  1221. X    first_subj_on_screen = (index_point / NOTESLINES) * NOTESLINES;
  1222. X    if (first_subj_on_screen < 0)
  1223. X        first_subj_on_screen = 0;
  1224. X
  1225. X    last_subj_on_screen = first_subj_on_screen + NOTESLINES;
  1226. X    if (last_subj_on_screen >= top_base) {
  1227. X        last_subj_on_screen = top_base;
  1228. X        first_subj_on_screen = top_base - NOTESLINES;
  1229. X
  1230. X        if (first_subj_on_screen < 0)
  1231. X            first_subj_on_screen = 0;
  1232. X    }
  1233. X
  1234. X    for (j=0, i = first_subj_on_screen; i < last_subj_on_screen; i++, j++) {
  1235. X        respnum = base[i];
  1236. X
  1237. X        if (arts[respnum].tagged) {
  1238. X            sprintf (new_resps, "%2d", arts[respnum].tagged);
  1239. X        } else if (new_responses(i)) {
  1240. X            strcpy (new_resps, " +");
  1241. X        } else {
  1242. X            strcpy (new_resps, "  ");
  1243. X        }
  1244. X
  1245. X        n = nresp(i);
  1246. X        if (n)
  1247. X            sprintf (resps, "%4d", n);
  1248. X        else
  1249. X            strcpy (resps, "    ");
  1250. X
  1251. X        if (show_author) {
  1252. X            my_strncpy (subject, arts[respnum].subject, max_subj);
  1253. X            my_strncpy (from, arts[respnum].from, max_from);
  1254. X
  1255. X            sprintf (screen[j].col, "  %4d %s  %-*s%s %-*s\r\n",
  1256. X                   i+1, new_resps, max_subj, subject, resps, max_from, from);
  1257. X        } else {
  1258. X            sprintf(screen[j].col, "  %4d %s  %-*s %s\r\n",
  1259. X                   i+1, new_resps, max_subj+max_from, arts[respnum].subject, resps);
  1260. X        }
  1261. X        printf("%s", screen[j].col);
  1262. X    }
  1263. X
  1264. X#ifndef USE_CLEARSCREEN
  1265. X    CleartoEOS ();
  1266. X#endif
  1267. X
  1268. X    if (top_base <= 0)
  1269. X        info_message(txt_no_arts);
  1270. X    else if (last_subj_on_screen == top_base)
  1271. X        info_message(txt_end_of_arts);
  1272. X
  1273. X    if (top_base > 0)
  1274. X        draw_subject_arrow();
  1275. X}
  1276. X
  1277. Xvoid draw_subject_arrow()
  1278. X{
  1279. X    draw_arrow (INDEX_TOP + (index_point-first_subj_on_screen));
  1280. X}
  1281. X
  1282. Xvoid erase_subject_arrow()
  1283. X{
  1284. X    erase_arrow (INDEX_TOP + (index_point-first_subj_on_screen));
  1285. X}
  1286. X
  1287. X
  1288. Xint prompt_subject_num (ch, group)
  1289. X    char ch;
  1290. X    char *group;
  1291. X{
  1292. X    int num;
  1293. X
  1294. X    clear_message();
  1295. X
  1296. X    if ((num = parse_num(ch, txt_read_art)) == -1) {
  1297. X        clear_message();
  1298. X        return FALSE;
  1299. X    }
  1300. X    num--;        /* index from 0 (internal) vs. 1 (user) */
  1301. X
  1302. X    if (num >= top_base)
  1303. X        num = top_base - 1;
  1304. X
  1305. X    if (num >= first_subj_on_screen
  1306. X    &&  num < last_subj_on_screen) {
  1307. X        erase_subject_arrow();
  1308. X        index_point = num;
  1309. X        draw_subject_arrow();
  1310. X    } else {
  1311. X#ifndef USE_CLEARSCREEN
  1312. X        erase_subject_arrow();
  1313. X#endif        
  1314. X        index_point = num;
  1315. X        show_group_page(group);
  1316. X    }
  1317. X    return TRUE;
  1318. X}
  1319. X
  1320. X/*
  1321. X *  Return the number of unread articles there are within a thread
  1322. X */
  1323. X
  1324. Xint new_responses (thread)
  1325. X    int thread;
  1326. X{
  1327. X    int i;
  1328. X    int sum = 0;
  1329. X
  1330. X    for (i = base[thread]; i >= 0; i = arts[i].thread)
  1331. X            if (arts[i].unread)
  1332. X                sum++;
  1333. X    
  1334. X    return sum;
  1335. X}
  1336. X
  1337. X
  1338. Xvoid clear_note_area ()
  1339. X{
  1340. X#ifndef USE_CLEARSCREEN
  1341. X    MoveCursor (3, 0);        /* top left corner */
  1342. X    CleartoEOS ();
  1343. X#endif
  1344. X}
  1345. X
  1346. X/*
  1347. X *  Post an original article (not a followup)
  1348. X */
  1349. X
  1350. Xint post_base (group)
  1351. X    char *group;
  1352. X{
  1353. X    FILE *fp;
  1354. X    char nam[LEN+1];
  1355. X    char ch;
  1356. X    char ch_default = 'p';
  1357. X    char subj[LEN+1];
  1358. X    char buf[LEN+1];
  1359. X
  1360. X    if (!parse_string(txt_post_subject, subj))
  1361. X        return FALSE;
  1362. X    if (subj[0] == '\0')
  1363. X        return FALSE;
  1364. X
  1365. X    setuid(real_uid);
  1366. X    setgid(real_gid);
  1367. X
  1368. X    sprintf(nam, "%s/.article", homedir);
  1369. X    if ((fp = fopen(nam, "w")) == NULL) {
  1370. X        error_message (txt_cannot_open, nam);
  1371. X        setuid (tin_uid);
  1372. X        setgid (tin_gid);
  1373. X        return FALSE;
  1374. X    }
  1375. X    chmod(nam, 0600);
  1376. X
  1377. X    fprintf(fp, "Subject: %s\n", subj);
  1378. X    fprintf(fp, "Newsgroups: %s\n", group);
  1379. X    fprintf(fp, "Distribution: \n");
  1380. X    if (*my_org)
  1381. X        fprintf(fp, "Organization: %s\n", my_org);
  1382. X    if (*reply_to)
  1383. X        fprintf(fp, "Reply-To: %s\n", reply_to);
  1384. X    fprintf(fp, "\n");
  1385. X
  1386. X    add_signature (fp, FALSE);
  1387. X    fclose(fp);
  1388. X
  1389. X    ch = 'e';
  1390. X    while (1) {
  1391. X        switch (ch) {
  1392. X        case 'e':
  1393. X            start_line_offset = 5;
  1394. X            invoke_editor(nam);
  1395. X            break;
  1396. X
  1397. X        case 'a':
  1398. X            clear_message ();
  1399. X            setuid(tin_uid);
  1400. X            setgid(tin_gid);
  1401. X            return FALSE;
  1402. X
  1403. X        case 'p':
  1404. X            wait_message (txt_posting);
  1405. X            sprintf (buf, "%s/inews -h < %s", LIBDIR, nam);
  1406. X            if (invoke_cmd (buf)) {
  1407. X                info_message (txt_art_posted);
  1408. X                goto post_base_done;
  1409. X            } else {
  1410. X                info_message (txt_art_rejected);
  1411. X                break;
  1412. X            }
  1413. X        }
  1414. X
  1415. X        do {
  1416. X            sprintf (msg, "%s%c", txt_abort_edit_post, ch_default);
  1417. X            wait_message (msg);
  1418. X            MoveCursor(LINES, (int) strlen (txt_abort_edit_post));
  1419. X            if ((ch = ReadCh()) == CR)
  1420. X                ch = ch_default;
  1421. X        } while (ch != 'a' && ch != 'e' && ch != 'p');
  1422. X    }
  1423. X
  1424. Xpost_base_done:
  1425. X    setuid (tin_uid);
  1426. X    setgid (tin_gid);
  1427. X
  1428. X    update_art_posted_file (group, subj);
  1429. X    
  1430. X    return TRUE;
  1431. X}
  1432. X
  1433. X
  1434. Xint find_new_pos (old_top, old_artnum, cur_pos)
  1435. X    int old_top;
  1436. X    long old_artnum;
  1437. X    int cur_pos;
  1438. X{
  1439. X    int pos;
  1440. X    
  1441. X    if (top != old_top) {
  1442. X        if ((pos = valid_artnum (old_artnum)) >= 0) {
  1443. X            if ((pos = which_base (pos)) >= 0) {
  1444. X                return pos;
  1445. X            } else {
  1446. X                return top_base - 1;
  1447. X            }
  1448. X        } else {
  1449. X            return top_base - 1;
  1450. X        }
  1451. X    }
  1452. X
  1453. X    return cur_pos;
  1454. X}
  1455. X
  1456. SHAR_EOF
  1457. $TOUCH -am 0819093091 group.c &&
  1458. chmod 0600 group.c ||
  1459. echo "restore of group.c failed"
  1460. set `wc -c group.c`;Wc_c=$1
  1461. if test "$Wc_c" != "20085"; then
  1462.     echo original size 20085, current size $Wc_c
  1463. fi
  1464. # ============= hashstr.c ==============
  1465. echo "x - extracting hashstr.c (Text)"
  1466. sed 's/^X//' << 'SHAR_EOF' > hashstr.c &&
  1467. X/*
  1468. X *  Project   : tin - a visual threaded usenet newsreader
  1469. X *  Module    : hashstr.c
  1470. X *  Author    : R.Skrenta
  1471. X *  Created   : 01-04-91
  1472. X *  Updated   : 10-08-91
  1473. X *  Release   : 1.0
  1474. X *  Notes     :
  1475. X *  Copyright : (c) Copyright 1991 by Rich Skrenta
  1476. X *                You may  freely  copy or  redistribute  this software,
  1477. X *              so  long as there is no profit made from its use, sale
  1478. X *              trade or  reproduction.  You may not change this copy-
  1479. X *              right notice, and it must be included in any copy made
  1480. X */
  1481. X
  1482. X#include    <stdio.h>
  1483. X#ifdef BSD
  1484. X#include    <strings.h>
  1485. X#else
  1486. X#include    <string.h>
  1487. X#include    <malloc.h>
  1488. X#endif
  1489. X
  1490. X/*
  1491. X *  Maintain a table of all strings we have seen.
  1492. X *  If a new string comes in, add it to the table and return a pointer
  1493. X *  to it.  If we've seen it before, just return the pointer to it.
  1494. X *
  1495. X *  Usage:  hash_str("some string") returns char *
  1496. X *
  1497. X *  Spillovers are chained on the end
  1498. X *
  1499. X *  !!! NOTE: CHECK OUT add_string FOR THE *iptr TRICK THAT IS LATER !!!
  1500. X *  !!! USED IN dump_index (art.c)                                   !!!
  1501. X *
  1502. X */
  1503. X
  1504. X
  1505. X/*
  1506. X *  Arbitrary table size, but make sure it's prime!
  1507. X */
  1508. X
  1509. X/* #define        TABLE_SIZE    1409    */
  1510. X
  1511. X#define        TABLE_SIZE    2411
  1512. X
  1513. X
  1514. X
  1515. Xstruct hashnode {
  1516. X    char *s;            /* the string we're saving */
  1517. X    struct hashnode *next;        /* chain for spillover */
  1518. X};
  1519. X
  1520. Xstruct hashnode *table[TABLE_SIZE];
  1521. X
  1522. Xextern char *my_malloc();
  1523. Xstruct hashnode *add_string();
  1524. X
  1525. X
  1526. Xchar *hash_str(s)
  1527. Xchar *s;
  1528. X{
  1529. X    struct hashnode *p;    /* used to descend the spillover structs */
  1530. X    long h;            /* result of hash:  index into hash table */
  1531. X
  1532. X    if (s == NULL)
  1533. X        return(NULL);
  1534. X
  1535. X    {
  1536. X        char *t = s;
  1537. X
  1538. X        h = *t++;
  1539. X        while (*t)
  1540. X            h = ((h << 1) ^ *t++) % TABLE_SIZE;
  1541. X    /*        h = (h * 128 + *t++) % TABLE_SIZE;    */
  1542. X    }
  1543. X
  1544. X    p = table[h];
  1545. X
  1546. X    if (p == NULL) {
  1547. X        table[h] = add_string(s);
  1548. X        return table[h]->s;
  1549. X    }
  1550. X
  1551. X    while (1) {
  1552. X        if (strcmp(s, p->s) == 0)
  1553. X            return(p->s);
  1554. X
  1555. X        if (p->next == NULL) {
  1556. X            p->next = add_string(s);
  1557. X            return p->next->s;
  1558. X        } else
  1559. X            p = p->next;
  1560. X    }
  1561. X}
  1562. X
  1563. X
  1564. Xstruct hashnode *add_string(s)
  1565. Xchar *s;
  1566. X{
  1567. X    struct hashnode *p;
  1568. X    extern char *strcpy();
  1569. X    int *iptr;
  1570. X
  1571. X    p = (struct hashnode *) my_malloc(sizeof(*p));
  1572. X
  1573. X    p->next = NULL;
  1574. X    iptr = (int *) my_malloc((unsigned) strlen(s) + sizeof(int) + 1);
  1575. X    *iptr++ = -1;
  1576. X    p->s = (char *) iptr;
  1577. X    strcpy(p->s, s);
  1578. X    return(p);
  1579. X}
  1580. X
  1581. X
  1582. Xvoid hash_init ()
  1583. X{
  1584. X    int i;
  1585. X
  1586. X    for (i = 0; i < TABLE_SIZE; i++)
  1587. X        table[i] = NULL;
  1588. X}
  1589. X
  1590. X
  1591. Xvoid hash_reclaim ()
  1592. X{
  1593. X    int i;
  1594. X    struct hashnode *p, *next;
  1595. X    int *iptr;
  1596. X
  1597. X    for (i = 0; i < TABLE_SIZE; i++)
  1598. X        if (table[i] != NULL) {
  1599. X            p = table[i];
  1600. X            while (p != NULL) {
  1601. X                next = p->next;
  1602. X                iptr = (int *) p->s;
  1603. X                free(--iptr);
  1604. X                free(p);
  1605. X                p = next;
  1606. X            }
  1607. X            table[i] = NULL;
  1608. X        }
  1609. X}
  1610. X
  1611. X
  1612. SHAR_EOF
  1613. $TOUCH -am 0819085991 hashstr.c &&
  1614. chmod 0600 hashstr.c ||
  1615. echo "restore of hashstr.c failed"
  1616. set `wc -c hashstr.c`;Wc_c=$1
  1617. if test "$Wc_c" != "2673"; then
  1618.     echo original size 2673, current size $Wc_c
  1619. fi
  1620. # ============= help.c ==============
  1621. echo "x - extracting help.c (Text)"
  1622. sed 's/^X//' << 'SHAR_EOF' > help.c &&
  1623. X/*
  1624. X *  Project   : tin - a visual threaded usenet newsreader
  1625. X *  Module    : help.c
  1626. X *  Author    : R.Skrenta / I.Lea
  1627. X *  Created   : 01-04-91
  1628. X *  Updated   : 22-08-91
  1629. X *  Release   : 1.0
  1630. X *  Notes     :
  1631. X *  Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
  1632. X *                You may  freely  copy or  redistribute  this software,
  1633. X *              so  long as there is no profit made from its use, sale
  1634. X *              trade or  reproduction.  You may not change this copy-
  1635. X *              right notice, and it must be included in any copy made
  1636. X */
  1637. X
  1638. X#include    "tin.h"
  1639. X#include    "nntp.h"
  1640. X
  1641. X/*
  1642. Xvoid basename (dirname, basename)
  1643. X    char *dirname;
  1644. X    char *basename;
  1645. X{
  1646. X    int i;
  1647. X    
  1648. X    strcpy (basename, dirname);
  1649. X    
  1650. X    for (i=(int) strlen(dirname)-1 ; i ; i--) {
  1651. X        if (dirname[i] == '/') {
  1652. X            strcpy (basename, dirname+(i+1));
  1653. X            break;
  1654. X        }
  1655. X    }
  1656. X}
  1657. X*/
  1658. X
  1659. Xvoid help_select_commands ()
  1660. X{
  1661. X    char ch;
  1662. X
  1663. Xselect_help_start:
  1664. X
  1665. X    ClearScreen ();
  1666. X    center_line (0, page_header);
  1667. X    StartInverse ();
  1668. X    center_line (1, txt_group_select_com_1);
  1669. X    EndInverse ();
  1670. X
  1671. X    MoveCursor(3, 0);
  1672. X
  1673. X    printf(txt_help_g_4);
  1674. X    printf(txt_help_ctrl_d);
  1675. X    printf(txt_help_ctrl_l);
  1676. X    printf(txt_help_g_ctrl_k);
  1677. X    printf(txt_help_g_ctrl_r);
  1678. X    printf(txt_help_g_cr);
  1679. X    printf(txt_help_g_tab);
  1680. X    printf(txt_help_b);
  1681. X    printf(txt_help_bug, BUG_REPORT_ADDRESS);
  1682. X    printf(txt_help_g_c);
  1683. X    printf(txt_help_g);
  1684. X    printf(txt_help_j);
  1685. X    printf(txt_help_h);
  1686. X    printf(txt_help_m);
  1687. X    printf(txt_help_M);
  1688. X    printf(txt_help_q);
  1689. X    printf(txt_help_s);
  1690. X    printf(txt_help_S);
  1691. X    printf(txt_help_W);
  1692. X
  1693. X    center_line(LINES, txt_hit_space_for_more);
  1694. X    ch = ReadCh();
  1695. X    if (ch != ' ') {
  1696. X#ifndef USE_CLEARSCREEN
  1697. X    ClearScreen ();
  1698. X#endif    
  1699. X        return;
  1700. X    }    
  1701. X
  1702. X    ClearScreen();
  1703. X    center_line(0, page_header);
  1704. X    center_line(1, txt_group_select_com_2);
  1705. X
  1706. X    MoveCursor(3, 0);
  1707. X
  1708. X    printf(txt_help_g_y);
  1709. X    printf(txt_help_g_dollar);
  1710. X    printf(txt_help_g_search);
  1711. X
  1712. X    center_line(LINES, txt_hit_any_key);
  1713. X    ch = ReadCh();
  1714. X    if (ch == 'b')
  1715. X        goto select_help_start;
  1716. X
  1717. X#ifndef USE_CLEARSCREEN
  1718. X    ClearScreen ();
  1719. X#endif    
  1720. X}
  1721. X
  1722. X
  1723. Xvoid help_select_info ()
  1724. X{
  1725. X}
  1726. X
  1727. X
  1728. Xvoid help_group_commands ()
  1729. X{
  1730. X    char ch;
  1731. X
  1732. Xgroup_help_start:
  1733. X
  1734. X    ClearScreen ();
  1735. X    center_line (0, page_header);
  1736. X    StartInverse ();
  1737. X    center_line (1, txt_index_page_com_1);
  1738. X    EndInverse ();
  1739. X
  1740. X    MoveCursor(3, 0);
  1741. X
  1742. X    printf(txt_help_i_4);
  1743. X    printf(txt_help_ctrl_d);
  1744. X    printf(txt_help_ctrl_k);
  1745. X    printf(txt_help_ctrl_l);
  1746. X    printf(txt_help_i_cr);
  1747. X    printf(txt_help_i_tab);
  1748. X    printf(txt_help_a);
  1749. X    printf(txt_help_b);
  1750. X    printf(txt_help_bug, BUG_REPORT_ADDRESS);
  1751. X    printf(txt_help_c);
  1752. X    printf(txt_help_g);
  1753. X    printf(txt_help_h);
  1754. X    printf(txt_help_I);
  1755. X    printf(txt_help_j);
  1756. X    printf(txt_help_K);
  1757. X    printf(txt_help_M);
  1758. X    printf(txt_help_i_n);
  1759. X    printf(txt_help_i_p);
  1760. X    printf(txt_help_q);
  1761. X
  1762. X    center_line(LINES, txt_hit_space_for_more);
  1763. X    ch = ReadCh();
  1764. X    if (ch != ' ') {
  1765. X#ifndef USE_CLEARSCREEN
  1766. X    ClearScreen ();
  1767. X#endif    
  1768. X        return;
  1769. X    }
  1770. X
  1771. X    ClearScreen();
  1772. X    center_line(0, page_header);
  1773. X    StartInverse ();
  1774. X    center_line(1, txt_index_page_com_2);
  1775. X    EndInverse ();
  1776. X
  1777. X    MoveCursor(3, 0);
  1778. X
  1779. X    printf(txt_help_s);
  1780. X    printf(txt_help_i_S);
  1781. X    printf(txt_help_t);
  1782. X    printf(txt_help_T);
  1783. X    printf(txt_help_U);
  1784. X    printf(txt_help_w);
  1785. X    printf(txt_help_W);
  1786. X    printf(txt_help_p_z);
  1787. X    printf(txt_help_i_search);
  1788. X    printf(txt_help_dash);
  1789. X
  1790. X    center_line(LINES, txt_hit_any_key);
  1791. X    ch = ReadCh();
  1792. X    if (ch == 'b')
  1793. X        goto group_help_start;
  1794. X
  1795. X#ifndef USE_CLEARSCREEN
  1796. X    ClearScreen ();
  1797. X#endif    
  1798. X}
  1799. X
  1800. X
  1801. Xvoid help_group_info ()
  1802. X{
  1803. X}
  1804. X
  1805. X
  1806. Xvoid help_page_commands ()
  1807. X{
  1808. X    char ch;
  1809. X
  1810. Xpage_help_start:
  1811. X
  1812. X    ClearScreen ();
  1813. X    center_line (0, page_header);
  1814. X    StartInverse ();
  1815. X    center_line (1, txt_art_pager_com_1);
  1816. X    EndInverse ();
  1817. X
  1818. X    MoveCursor(3, 0);
  1819. X
  1820. X    printf(txt_help_p_0);
  1821. X    printf(txt_help_p_4);
  1822. X    printf(txt_help_ctrl_h);
  1823. X    printf(txt_help_ctrl_k);
  1824. X    printf(txt_help_ctrl_l);
  1825. X    printf(txt_help_p_ctrl_r);
  1826. X    printf(txt_help_p_cr);
  1827. X    printf(txt_help_p_tab);
  1828. X    printf(txt_help_b);
  1829. X    printf(txt_help_a);
  1830. X    printf(txt_help_bug, BUG_REPORT_ADDRESS);
  1831. X    printf(txt_help_c);
  1832. X    printf(txt_help_p_d);
  1833. X    printf(txt_help_p_f);
  1834. X    printf(txt_help_h);
  1835. X    printf(txt_help_p_i);
  1836. X    printf(txt_help_I);
  1837. X    printf(txt_help_p_k);
  1838. X    printf(txt_help_p_m);
  1839. X
  1840. X    center_line(LINES, txt_hit_space_for_more);
  1841. X    ch = ReadCh();
  1842. X    if (ch != ' ') {
  1843. X#ifndef USE_CLEARSCREEN
  1844. X    ClearScreen ();
  1845. X#endif    
  1846. X        return;
  1847. X    }
  1848. X
  1849. X    ClearScreen();
  1850. X    center_line(0, page_header);
  1851. X    StartInverse ();
  1852. X    center_line(1, txt_art_pager_com_2);
  1853. X    EndInverse ();
  1854. X
  1855. X    MoveCursor(3, 0);
  1856. X
  1857. X    printf(txt_help_M);
  1858. X    printf(txt_help_p_n);
  1859. X    printf(txt_help_p_o);
  1860. X    printf(txt_help_p_p);
  1861. X    printf(txt_help_q);
  1862. X    printf(txt_help_p_r);
  1863. X    printf(txt_help_p_s);
  1864. X    printf(txt_help_T);
  1865. X    printf(txt_help_w);
  1866. X    printf(txt_help_W);
  1867. X    printf(txt_help_p_z);
  1868. X    printf(txt_help_dash);
  1869. X    printf(txt_help_p_pipe);
  1870. X    printf(txt_help_p_search);
  1871. X
  1872. X    center_line(LINES, txt_hit_any_key);
  1873. X    ch = ReadCh();
  1874. X
  1875. X    if (ch == 'b')
  1876. X        goto page_help_start;
  1877. X
  1878. X#ifndef USE_CLEARSCREEN
  1879. X    ClearScreen ();
  1880. X#endif    
  1881. X}
  1882. X
  1883. X
  1884. Xvoid help_page_info ()
  1885. X{
  1886. X}
  1887. SHAR_EOF
  1888. $TOUCH -am 0822160291 help.c &&
  1889. chmod 0600 help.c ||
  1890. echo "restore of help.c failed"
  1891. set `wc -c help.c`;Wc_c=$1
  1892. if test "$Wc_c" != "4794"; then
  1893.     echo original size 4794, current size $Wc_c
  1894. fi
  1895. # ============= kill.c ==============
  1896. echo "x - extracting kill.c (Text)"
  1897. sed 's/^X//' << 'SHAR_EOF' > kill.c &&
  1898. X/*
  1899. X *  Project   : tin - a visual threaded usenet newsreader
  1900. X *  Module    : kill.c
  1901. X *  Author    : I.Lea
  1902. X *  Created   : 01-04-91
  1903. X *  Updated   : 16-08-91
  1904. X *  Release   : 1.0
  1905. X *  Notes     : kill articles
  1906. X *  Copyright : (c) Copyright 1991 by Iain Lea
  1907. X *                You may  freely  copy or  redistribute  this software,
  1908. X *              so  long as there is no profit made from its use, sale
  1909. X *              trade or  reproduction.  You may not change this copy-
  1910. X *              right notice, and it must be included in any copy made
  1911. X */
  1912. X
  1913. X#include    "tin.h"
  1914. X
  1915. Xextern char index_file[LEN+1];
  1916. X
  1917. Xstruct kill_t *killf;
  1918. Xint kill_num = 0;
  1919. Xint max_kill;
  1920. X
  1921. X/*
  1922. X *  read_kill_file - read ~/.tin/kill file contents into kill array
  1923. X */
  1924. X
  1925. Xint read_kill_file ()
  1926. X{
  1927. X    char buf[LEN+1];
  1928. X    FILE *fp;
  1929. X
  1930. X    free_kill_array ();
  1931. X    
  1932. X    if ((fp = fopen (killfile, "r")) != NULL) {
  1933. X        kill_num=0;
  1934. X        while (fgets (buf, LEN, fp) != NULL) {
  1935. X            if (buf[0] != '#') {
  1936. X                if (kill_num == max_kill-1) {
  1937. X                    expand_kill ();
  1938. X                }
  1939. X                killf[kill_num].kill_type = atoi (buf);
  1940. X                if (fgets (buf, LEN, fp) != NULL) {
  1941. X                    killf[kill_num].kill_group = atol (buf);
  1942. X                } else {    
  1943. X                    goto corrupt_killfile;
  1944. X                }    
  1945. X                switch (killf[kill_num].kill_type) {
  1946. X                    case KILL_SUBJ:
  1947. X                        if (fgets (buf, LEN, fp) != NULL) {
  1948. X                            buf[strlen (buf)-1] = '\0';
  1949. X                            killf[kill_num].kill_subj = str_dup (buf);
  1950. X                        }
  1951. X                        break;
  1952. X                    case KILL_FROM:
  1953. X                        if (fgets (buf, LEN, fp) != NULL) {
  1954. X                            buf[strlen (buf)-1] = '\0';
  1955. X                            killf[kill_num].kill_from = str_dup (buf);
  1956. X                        }
  1957. X                        break;
  1958. X                    case KILL_BOTH:
  1959. X                        if (fgets (buf, LEN, fp) != NULL) {
  1960. X                            buf[strlen (buf)-1] = '\0';
  1961. X                            killf[kill_num].kill_subj = str_dup (buf);
  1962. X                        }
  1963. X                        if (fgets (buf, LEN, fp) != NULL) {
  1964. X                            buf[strlen (buf)-1] = '\0';
  1965. X                            killf[kill_num].kill_from = str_dup (buf);
  1966. X                        }
  1967. X                        break;
  1968. X                    default:
  1969. X                        goto corrupt_killfile;
  1970. X                }
  1971. X                kill_num++;
  1972. X            }
  1973. X        }
  1974. X        fclose (fp);
  1975. X        return TRUE;        
  1976. X    } else {
  1977. X        return FALSE;
  1978. X    }
  1979. X
  1980. Xcorrupt_killfile:
  1981. X    fclose (fp);
  1982. X    killf[kill_num].kill_type = 0;
  1983. X    error_message ("corrupt kill file %s", killfile);
  1984. X    return FALSE;
  1985. X}
  1986. X
  1987. X/*
  1988. X *  write_kill_file - write kill strings to ~/.tin/kill
  1989. X */
  1990. X
  1991. Xvoid write_kill_file ()
  1992. X{
  1993. X    FILE *fp;
  1994. X    int i;
  1995. X    
  1996. X    if (kill_num && (fp = fopen (killfile, "w")) != NULL) {
  1997. X        wait_message (txt_saving);
  1998. X        fprintf (fp, "# 1st line  1=(Subject: only)  2=(From: only)  3=(Subject: & From:)\n");
  1999. X        fprintf (fp, "# 2nd line  0=(kill on all newsgroups)  >0=(kill on specific newsgroup)\n");
  2000. X        for (i=0 ; i < kill_num ; i++) {
  2001. X            if (killf[i].kill_type && (killf[i].kill_subj || killf[i].kill_from)) {
  2002. X                fprintf (fp, "#\n# kill description %d\n", i+1);
  2003. X                fprintf (fp, "%d\n", killf[i].kill_type);
  2004. X                fprintf (fp, "%ld\n", killf[i].kill_group);
  2005. X                switch (killf[i].kill_type) {
  2006. X                    case KILL_SUBJ:
  2007. X                        fprintf (fp, "%s\n", killf[i].kill_subj);
  2008. X                        break;
  2009. X                    case KILL_FROM:
  2010. X                        fprintf (fp, "%s\n", killf[i].kill_from);
  2011. X                        break;
  2012. X                    case KILL_BOTH:
  2013. X                        fprintf (fp, "%s\n", killf[i].kill_subj);
  2014. X                        fprintf (fp, "%s\n", killf[i].kill_from);
  2015. X                        break;
  2016. X                }
  2017. X            }
  2018. X        }
  2019. X        fclose (fp);
  2020. X        chmod (killfile, 0600);
  2021. X    }
  2022. X}
  2023. X
  2024. X/*
  2025. X *  options menu so that the user can dynamically change parameters
  2026. X */
  2027. Xint kill_art_menu (group_name, index)
  2028. X    char *group_name;
  2029. X    int index;
  2030. X{
  2031. X    char text[LEN+1];
  2032. X    char kill_from[LEN+1];
  2033. X    char kill_subj[LEN+1];
  2034. X    char kill_group[LEN+1];
  2035. X    char ch_default = 's';
  2036. X    char *str;    
  2037. X    int ch;
  2038. X    int counter;
  2039. X    int kill_from_ok = FALSE;
  2040. X    int kill_subj_ok = FALSE;
  2041. X    int kill_every_group;
  2042. X    
  2043. X    sprintf (kill_group, "%s only", group_name);
  2044. X    my_strncpy (text, arts[index].subject, 45);
  2045. X    sprintf (kill_subj, txt_kill_subject, text);
  2046. X    my_strncpy (text, arts[index].from, 45);
  2047. X    sprintf (kill_from, txt_kill_from, text);
  2048. X    text[0] = '\0';
  2049. X    
  2050. X    ClearScreen ();
  2051. X    printf("%s\r\n", nice_time());    /* time in upper left */
  2052. X
  2053. X    StartInverse ();
  2054. X    center_line (1, txt_kill_menu);
  2055. X    EndInverse ();
  2056. X    
  2057. X    MoveCursor(INDEX_TOP, 0);
  2058. X    printf ("%s\r\n\r\n", txt_kill_text);
  2059. X    printf ("%s\r\n\r\n\r\n", txt_kill_text_type);
  2060. X    printf ("%s\r\n\r\n", kill_subj);
  2061. X    printf ("%s\r\n\r\n\r\n", kill_from);
  2062. X    printf ("%s%s", txt_kill_group, kill_group);
  2063. X    fflush(stdout);
  2064. X
  2065. X    show_menu_help (txt_help_kill_text);
  2066. X    parse_menu_string (INDEX_TOP, strlen (txt_kill_text), text);
  2067. X
  2068. X    if (text[0]) {
  2069. X        show_menu_help (txt_help_kill_text_type);
  2070. X        counter = 1;
  2071. X        MoveCursor (INDEX_TOP+2, strlen (txt_kill_text_type));
  2072. X        str = "Subject: line only    ";
  2073. X        printf ("%s", str);
  2074. X        fflush(stdout);
  2075. X        do {
  2076. X            MoveCursor (INDEX_TOP+2, strlen (txt_kill_text_type));
  2077. X            if ((ch    = ReadCh()) == ' ') {
  2078. X                counter++;
  2079. X                if (counter == KILL_BOTH+1) {
  2080. X                    counter = KILL_SUBJ;
  2081. X                }
  2082. X                switch (counter) {
  2083. X                    case KILL_SUBJ:
  2084. X                        str = "Subject: line only    ";
  2085. X                        break;
  2086. X                    case KILL_FROM:
  2087. X                        str = "From: line only       ";
  2088. X                        break;
  2089. X                    case KILL_BOTH:
  2090. X                        str = "Subject: & From: lines";
  2091. X                        break;
  2092. X                }
  2093. X                printf ("%s", str);
  2094. X                fflush(stdout);
  2095. X            }
  2096. X        } while (ch != CR);
  2097. X    }
  2098. X
  2099. X    if (! text[0]) {
  2100. X        show_menu_help (txt_help_kill_subject);
  2101. X        kill_subj_ok = prompt_yn (INDEX_TOP+5, kill_subj, 'y');
  2102. X
  2103. X        show_menu_help (txt_help_kill_from);
  2104. X        kill_from_ok = prompt_yn (INDEX_TOP+7, kill_from, 'n');
  2105. X    }
  2106. X
  2107. X    if (text[0] || kill_subj_ok || kill_from_ok) {
  2108. X        show_menu_help (txt_help_kill_group);
  2109. X        kill_every_group = FALSE;
  2110. X        MoveCursor (INDEX_TOP+10, strlen (txt_kill_group));
  2111. X        str = kill_group;
  2112. X        printf ("%s", str);
  2113. X        fflush(stdout);
  2114. X        do {
  2115. X            MoveCursor (INDEX_TOP+10, strlen (txt_kill_group));
  2116. X            if ((ch    = ReadCh()) == ' ') {
  2117. X                kill_every_group = !kill_every_group;
  2118. X                if (kill_every_group) {
  2119. X                    str = "All groups";
  2120. X                } else {
  2121. X                    str = kill_group;
  2122. X                }
  2123. X                CleartoEOLN (); 
  2124. X                printf ("%s", str);
  2125. X                fflush(stdout);
  2126. X            }
  2127. X        } while (ch != CR);
  2128. X    }
  2129. X
  2130. X    while (1) {
  2131. X        do {
  2132. X            sprintf (msg, "%s%c", txt_abort_edit_save_killfile, ch_default);
  2133. X            wait_message (msg);
  2134. X            MoveCursor(LINES, strlen (txt_abort_edit_save_killfile));
  2135. X            if ((ch = ReadCh()) == CR)
  2136. X                ch = ch_default;
  2137. X        } while (ch != 'a' && ch != 'e' && ch != 's');
  2138. X        switch (ch) {
  2139. X            case 'e':
  2140. X                start_line_offset = 2;
  2141. X                invoke_editor (killfile);
  2142. X                untag_all_articles ();
  2143. X                read_kill_file ();
  2144. X                reload_index_file (group_name, FALSE);
  2145. X                return TRUE;
  2146. X
  2147. X            case 'a':
  2148. X                return FALSE;
  2149. X            
  2150. X            case 's':
  2151. X                if (kill_num > max_kill-1) {
  2152. X                    expand_kill ();
  2153. X                }
  2154. X                if (text[0]) {
  2155. X                    switch (counter) {
  2156. X                        case KILL_SUBJ:
  2157. X                            killf[kill_num].kill_subj = str_dup (text);
  2158. X                            break;
  2159. X                        case KILL_FROM:
  2160. X                            killf[kill_num].kill_from = str_dup (text);
  2161. X                            break;
  2162. X                        case KILL_BOTH:
  2163. X                            killf[kill_num].kill_subj = str_dup (text);
  2164. X                            killf[kill_num].kill_from = str_dup (text);
  2165. X                            break;
  2166. X                    }
  2167. X                    killf[kill_num].kill_type = counter;
  2168. X                    if (kill_every_group) {
  2169. X                        killf[kill_num].kill_group= 0L;
  2170. X                    } else {
  2171. X                        killf[kill_num].kill_group= hash_s (group_name);
  2172. X                    }
  2173. X                    kill_num++;
  2174. X                } else {
  2175. X                    if (kill_subj_ok) {
  2176. X                        killf[kill_num].kill_type = KILL_SUBJ;
  2177. X                        killf[kill_num].kill_subj = str_dup (arts[index].subject);
  2178. X                    }
  2179. X                    if (kill_from_ok) {
  2180. X                        killf[kill_num].kill_type |= KILL_FROM;
  2181. X                        killf[kill_num].kill_from = str_dup (arts[index].from);
  2182. X                    }
  2183. X                    if (killf[kill_num].kill_type) {        
  2184. X                        if (kill_every_group) {
  2185. X                            killf[kill_num].kill_group= 0L;
  2186. X                        } else {
  2187. X                            killf[kill_num].kill_group= hash_s (group_name);
  2188. X                        }
  2189. X                        kill_num++;
  2190. X                    }
  2191. X                }
  2192. X                write_kill_file ();
  2193. X                return TRUE;
  2194. X        }    
  2195. X    }
  2196. X}
  2197. X
  2198. X
  2199. Xint untag_all_articles ()
  2200. X{
  2201. X    int untagged = FALSE;
  2202. X    register int i;
  2203. X
  2204. X    for (i=0 ; i < top ; i++) {
  2205. X        if (arts[i].tagged) {
  2206. X            arts[i].tagged = FALSE;
  2207. X            untagged = TRUE;
  2208. X        }
  2209. X    }
  2210. X    num_of_tagged_files = 0;
  2211. X
  2212. X    return (untagged);
  2213. X}
  2214. X
  2215. X
  2216. Xint kill_any_articles (group)
  2217. X    char *group;
  2218. X{
  2219. X    int killed = FALSE;
  2220. X    int run_ok = FALSE;
  2221. X    long group_hash;
  2222. X    register int i, j;
  2223. X
  2224. X    if (! kill_articles) {
  2225. X        return killed;
  2226. X    }
  2227. X
  2228. X    if (kill_num) {
  2229. X        group_hash = hash_s (group);
  2230. X        for (i=0 ; i < kill_num ; i++) {
  2231. X                if (killf[i].kill_group == 0L ||
  2232. X                    killf[i].kill_group == group_hash) {
  2233. X                    run_ok = TRUE;    
  2234. X                }
  2235. X        }
  2236. X        if (! run_ok) {
  2237. X            return (killed);
  2238. X        }
  2239. X        if (debug && ! update) {
  2240. X            wait_message ("Killing articles...");
  2241. X        }
  2242. X        for (i=0 ; i < top ; i++) {
  2243. X            for (j=0 ; j < kill_num && ! arts[i].tagged ; j++) {
  2244. X                if (killf[j].kill_group == 0L ||
  2245. X                    killf[j].kill_group == group_hash) {
  2246. X                    switch (killf[j].kill_type) {
  2247. X                        case KILL_SUBJ:
  2248. X                            if (str_str (arts[i].subject, killf[j].kill_subj) != 0) {
  2249. X                                arts[i].tagged = TRUE;
  2250. X                                killed = TRUE;
  2251. X                            }
  2252. X                            break;
  2253. X                        case KILL_FROM:
  2254. X                            if (str_str (arts[i].from, killf[j].kill_from) != 0) {
  2255. X                                arts[i].tagged = TRUE;
  2256. X                                killed = TRUE;
  2257. X                            }
  2258. X                            break;
  2259. SHAR_EOF
  2260. echo "End of tin part 2"
  2261. echo "File kill.c is continued in part 3"
  2262. echo "3" > shar3_seq_.tmp
  2263. exit 0
  2264.  
  2265. --
  2266. NAME   Iain Lea
  2267. EMAIL  norisc!iain@estevax.UUCP  ...!unido!estevax!norisc!iain
  2268. SNAIL  Siemens AG, AUT 922C, Postfach 4848, Nuernberg, Germany
  2269. PHONE  +49-911-895-3853, +49-911-895-3877, +49-911-331963
  2270.