home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3958 < prev    next >
Encoding:
Internet Message Format  |  1991-09-04  |  49.0 KB

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