home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / tass.lzh / group.c < prev    next >
Text File  |  1993-01-24  |  28KB  |  825 lines

  1.  
  2.  
  3. #include       <stdio.h>
  4. #include       <signal.h>
  5. #ifdef         REGEXP
  6. #include       <regexp.h>
  7. #endif         /* REGEXP */
  8. #ifdef OSK
  9. #include       <ctype.h>
  10. #endif /* OSK */
  11. #include       "tass.h"
  12.  
  13. #ifdef GET_DIST
  14. extern char    *index ();
  15. #endif /* GET_DIST */
  16.  
  17. int index_point;
  18. int first_subj_on_screen;
  19. int last_subj_on_screen;
  20. char subject_search_string[LEN+1];     /* last search pattern */
  21. extern int cur_groupnum;
  22. extern int last_resp;          /* page.c */
  23. extern int this_resp;          /* page.c */
  24. extern int space_mode;         /* select.c */
  25. extern char *cvers;
  26.  
  27. char *glob_group;
  28.  
  29.  
  30. #ifdef SIGTSTP
  31. void
  32. group_susp(i)
  33. int i;
  34. {
  35.  
  36.        Raw(FALSE);
  37.        putchar('\n');
  38.        signal(SIGTSTP, SIG_DFL);
  39.        kill(0, SIGTSTP);
  40.  
  41.        signal(SIGTSTP, group_susp);
  42.        Raw(TRUE);
  43.        mail_setup();
  44.        show_group_page(glob_group, TRUE);
  45. }
  46. #endif
  47.  
  48.  
  49. group_page(group)
  50. char *group;
  51. {
  52.        char ch;
  53.        int i, n;
  54.        char group_path[200];
  55.        char *p;
  56.        char buf[200];
  57.  
  58.        glob_group = group;
  59.  
  60.        strcpy(group_path, group);              /* turn comp.unix.amiga into */
  61.        for (p = group_path; *p; p++)           /* comp/unix/amiga */
  62.                if (*p == '.')
  63.                        *p = '/';
  64. #ifdef OSK
  65.                else if ((!isalnum (*p)) || ((unsigned char) *p >= 0x80))
  66.                        *p = '_';
  67. #endif /* OSK */
  68.  
  69.        last_resp = -1;
  70.        this_resp = -1;
  71.        index_group(group, group_path);         /* update index file */
  72.        read_newsrc_line(group);                /* get sequencer information */
  73.  
  74.        if (space_mode) {
  75.                for (i = 0; i < top_base; i++)
  76.                        if (new_responses(i))
  77.                                break;
  78.                if (i < top_base)
  79.                        index_point = i;
  80.                else
  81.                        index_point = top_base - 1;
  82.        } else
  83.                index_point = top_base - 1;
  84.  
  85.        show_group_page(group, TRUE);
  86.  
  87.        while (1) {
  88.                if ((n = ReadCh()) == EOF)
  89.                        longjmp (jmp_buffer, 1);
  90.                ch = (char) n;
  91.  
  92.                if (ch > '0' && ch <= '9') {    /* 0 goes to basenote */
  93.                        prompt_subject_num(ch, group);
  94.                } else switch (ch) {
  95.                        case 'I':       /* toggle inverse video */
  96.                                inverse_okay = !inverse_okay;
  97.                                if (inverse_okay)
  98.                                        info_message("Inverse video enabled");
  99.                                else
  100.                                        info_message("Inverse video disabled");
  101.                                break;
  102.  
  103.                        case 's':       /* subscribe to this group */
  104.                                subscribe(group, ':', my_group[cur_groupnum],
  105.                                                                        TRUE);
  106.                                sprintf(buf, "subscribed to %s", group);
  107.                                info_message(buf);
  108.                                break;
  109.  
  110.                        case 'u':       /* unsubscribe to this group */
  111.                                subscribe(group, '!', my_group[cur_groupnum],
  112.                                                                        TRUE);
  113.                                sprintf(buf, "unsubscribed to %s", group);
  114.                                info_message(buf);
  115.                                break;
  116.  
  117.                        case 'g':       /* choose a new group by name */
  118.                                n = choose_new_group();
  119.                                if (n >= 0 && n != cur_groupnum) {
  120.                                        fix_new_highest(cur_groupnum);
  121.                                        cur_groupnum = n;
  122.                                        index_point = -3;
  123.                                        goto group_done;
  124.                                }
  125.                                break;
  126.  
  127.                        case 'c':       /* catchup--mark all articles as read */
  128.                            if (prompt_yn("Mark everything as read? (y/n): ")) {
  129.                                for (n = 0; n < top; n++)
  130.                                        arts[n].unread = 0;
  131.                                show_group_page(group, FALSE);
  132.                                info_message("All articles marked as read");
  133.                            }
  134.                            break;
  135.  
  136. #ifdef USE_ARROW
  137.                        case 27:        /* common arrow keys */
  138.                                ch = ReadCh();
  139.                                if (ch == '[' || ch == 'O')
  140.                                        ch = ReadCh();
  141.                                switch (ch) {
  142.                                case 'A':
  143.                                case 'D':
  144.                                case 'i':
  145.                                        goto group_up;
  146.  
  147.                                case 'B':
  148.                                case 'I':
  149.                                case 'C':
  150.                                        goto group_down;
  151.                                }
  152.                                break;
  153. #endif /* USE_ARROW */
  154.  
  155.                        case 'n':       /* next group */
  156.                                clear_message();
  157.                                if (cur_groupnum + 1 >= local_top)
  158.                                        info_message("No more groups");
  159.                                else {
  160.                                        fix_new_highest(cur_groupnum);
  161.                                        cur_groupnum++;
  162.                                        index_point = -3;
  163.                                        space_mode = FALSE;
  164.                                        goto group_done;
  165.                                }
  166.                                break;
  167.  
  168.                        case 'p':       /* previous group */
  169.                                clear_message();
  170.                                if (cur_groupnum <= 0)
  171.                                        info_message("No previous group");
  172.                                else {
  173.                                        fix_new_highest(cur_groupnum);
  174.                                        cur_groupnum--;
  175.                                        index_point = -3;
  176.                                        space_mode = FALSE;
  177.                                        goto group_done;
  178.                                }
  179.                                break;
  180.  
  181.                        case ' ':
  182.                                if (top_base <= 0)
  183.                                        info_message("*** No Articles ***");
  184.                                else if (last_subj_on_screen == top_base)
  185.                                        info_message("*** End of Articles ***");
  186.                                else
  187.                                        clear_message();
  188.                                break;
  189.  
  190.                        case '\t':
  191.                                fix_new_highest(cur_groupnum);
  192.                                space_mode = TRUE;
  193.  
  194.                                if (index_point < 0
  195.                                || (n=next_unread((int) base[index_point]))<0) {
  196.                                        for (i = cur_groupnum+1;
  197.                                                        i < local_top; i++)
  198.                                                if (unread[i] > 0)
  199.                                                        break;
  200.                                        if (i >= local_top)
  201.                                                goto group_done;
  202.  
  203.                                        cur_groupnum = i;
  204.                                        index_point = -3;
  205.                                        goto group_done;
  206.                                }
  207.                                index_point = show_page(n, group, group_path);
  208.                                if (index_point < 0)
  209.                                        goto group_done;
  210.                                show_group_page(group, TRUE);
  211.                                break;
  212.        
  213.  
  214.                        case 'N':       /* go to next unread article */
  215.                                if (index_point < 0) {
  216.                                        info_message("No next unread article");
  217.                                        break;
  218.                                }
  219.  
  220.                                n = next_unread( (int) base[index_point]);
  221.                                if (n == -1)
  222.                                        info_message("No next unread article");
  223.                                else {
  224.                                        index_point =
  225.                                                show_page(n, group, group_path, TRUE);
  226.                                        if (index_point < 0) {
  227.                                                fix_new_highest(cur_groupnum);
  228.                                                space_mode = FALSE;
  229.                                                goto group_done;
  230.                                        }
  231.                                        show_group_page(group, TRUE);
  232.                                }
  233.                                break;
  234.  
  235.                        case 'P':       /* go to previous unread article */
  236.                                if (index_point < 0) {
  237.                                    info_message("No previous unread article");
  238.                                    break;
  239.                                }
  240.  
  241.                                n = prev_response( (int) base[index_point]);
  242.                                n = prev_unread(n);
  243.                                if (n == -1)
  244.                                    info_message("No previous unread article");
  245.                                else {
  246.                                        index_point =
  247.                                                show_page(n, group, group_path, TRUE);
  248.                                        if (index_point < 0) {
  249.                                                fix_new_highest(cur_groupnum);
  250.                                                space_mode = FALSE;
  251.                                                goto group_done;
  252.                                        }
  253.                                        show_group_page(group, TRUE);
  254.                                }
  255.                                break;
  256.  
  257.                        case 'w':       /* post a basenote */
  258.                                post_base(group);
  259.                                update_newsrc(group, my_group[cur_groupnum]);
  260.                                index_group(group, group_path);
  261.                                read_newsrc_line(group);
  262.                                index_point = top_base - 1;
  263.                                show_group_page(group, TRUE);
  264.                                break;
  265.  
  266.                        case 't':       /* return to group selection page */
  267.                        case ctrl('B'): /* cursor key */
  268.                                fix_new_highest(cur_groupnum);
  269.                                goto group_done;
  270.  
  271. #ifndef        OSK
  272.                        case '\r':
  273. #else  /* OSK */
  274.                        case '\l':
  275. #endif /* OSK */
  276.                        case '\n':      /* read current basenote */
  277.                        case ctrl('F'): /* cursor key */
  278.                                if (index_point < 0) {
  279.                                        info_message("*** No Articles ***");
  280.                                        break;
  281.                                }
  282.                                index_point = show_page((int) base[index_point],
  283.                                                        group, group_path, TRUE);
  284.                                if (index_point < 0) {
  285.                                        fix_new_highest(cur_groupnum);
  286.                                        space_mode = FALSE;
  287.                                        goto group_done;
  288.                                }
  289.                                show_group_page(group, TRUE);
  290.                                break;
  291.  
  292.                        case ctrl('D'):         /* page down */
  293.                        case ctrl('V'):         /* full page down */
  294.                                if (!top_base || index_point == top_base - 1)
  295.                                        break;
  296.  
  297.                                erase_subject_arrow();
  298.                                index_point += (ch == ctrl('V')) ? 
  299.                                                NOTESLINES :
  300.                                                NOTESLINES / 2;
  301.                                if (index_point >= top_base)
  302.                                        index_point = top_base - 1;
  303.  
  304.                                if (index_point < first_subj_on_screen
  305.                                || index_point >= last_subj_on_screen)
  306.                                        show_group_page(group, TRUE);
  307.                                else
  308.                                        draw_subject_arrow();
  309.                                break;
  310.  
  311.                        case '-':       /* go to last viewed article */
  312.                                if (this_resp < 0) {
  313.                                        info_message("No last message");
  314.                                        break;
  315.                                }
  316.                                index_point = show_page(this_resp,
  317.                                                        group, group_path, TRUE);
  318.                                if (index_point < 0) {
  319.                                        fix_new_highest(cur_groupnum);
  320.                                        space_mode = FALSE;
  321.                                        goto group_done;
  322.                                }
  323.                                show_group_page(group, TRUE);
  324.                                break;
  325.  
  326.                        case ctrl('U'):         /* page up */
  327.                        case ctrl('Z'):         /* full page up */
  328.                                if (!top_base)
  329.                                        break;
  330.  
  331.                                erase_subject_arrow();
  332.                                index_point -= (ch == ctrl('Z')) ?
  333.                                                NOTESLINES :
  334.                                                NOTESLINES / 2;
  335.                                if (index_point < 0)
  336.                                        index_point = 0;
  337.                                if (index_point < first_subj_on_screen
  338.                                || index_point >= last_subj_on_screen)
  339.                                        show_group_page(group, TRUE);
  340.                                else
  341.                                        draw_subject_arrow();
  342.                                break;
  343.  
  344.                        case 'v':
  345.                                info_message(cvers);
  346.                                break;
  347.  
  348.                        case '!':
  349.                                shell_escape();
  350.                                show_group_page(group, TRUE);
  351.                                break;
  352.  
  353.                        case ctrl('N'):
  354.                        case 'j':               /* line down */
  355. #ifdef USE_ARROW
  356. group_down:
  357. #endif /* USE_ARROW */
  358.                                if (!top_base || index_point + 1 >= top_base)
  359.                                        break;
  360.  
  361.                                erase_subject_arrow();
  362.                                index_point++;
  363.                                if (index_point >= last_subj_on_screen)
  364.                                        show_group_page(group, FALSE);
  365.                                else
  366.                                        draw_subject_arrow();
  367.                                break;
  368.  
  369.                        case ctrl('P'):
  370.                        case 'k':               /* line up */
  371. #ifdef USE_ARROW
  372. group_up:
  373. #endif /* USE_ARROW */
  374.                                if (!top_base || !index_point)
  375.                                        break;
  376.  
  377.                                erase_subject_arrow();
  378.                                index_point--;
  379.                                if (index_point + 1 <= first_subj_on_screen)
  380.                                        show_group_page(group, FALSE);
  381.                                else
  382.                                        draw_subject_arrow();
  383.                                break;
  384.  
  385.                        case ctrl('R'):
  386.                        case ctrl('L'):
  387.                        case ctrl('W'):
  388.                        case 'i':               /* return to index */
  389.                                        show_group_page(group, FALSE);
  390.                                        break;
  391.  
  392.                        case '/':               /* forward search */
  393.                                        search_subject(TRUE, group);
  394.                                        break;
  395.  
  396.                        case '?':               /* backward search */
  397.                                        search_subject(FALSE, group);
  398.                                        break;
  399.  
  400. #ifndef        OSK
  401.                        case 'q':               /* quit */
  402.                                        index_point = -2;
  403.                                        fix_new_highest(cur_groupnum);
  404.                                        space_mode = FALSE;
  405.                                        goto group_done;
  406. #endif /* OSK */
  407.  
  408.                        case 'h':
  409.                                tass_group_help();
  410.                                show_group_page(group, TRUE);
  411.                                break;
  412.  
  413.                        default:
  414.                            info_message("Bad command.  Type 'h' for help.");
  415.                }
  416.        }
  417.  
  418. group_done:
  419.        update_newsrc(group, my_group[cur_groupnum]);
  420.  
  421.        if (index_point == -2)
  422.                tass_done(0);
  423. }
  424.  
  425.  
  426. /*
  427.  *  Correct highest[] for the group selection page display since
  428.  *  new articles may have been read or marked unread
  429.  */
  430.  
  431. fix_new_highest(groupnum)
  432. int groupnum;
  433. {
  434.        int i;
  435.        int sum = 0;
  436.  
  437.        for (i = 0; i < top; i++)
  438.                if (arts[i].unread)
  439.                        sum++;
  440.  
  441.        unread[groupnum] = sum;
  442. }
  443.  
  444.  
  445. show_mail () {
  446.        if (mail_check()) {                     /* you have mail message in */
  447.                MoveCursor(0, COLS - 14);               /* upper right */
  448.                printf("you have mail");
  449.                fflush (stdout);
  450.        }
  451. }
  452.  
  453. show_group_page(group, clr)
  454. char *group;
  455. int clr;
  456. {
  457.        int i;
  458.        int n;
  459.        char resps[10];
  460.        char new_resps;
  461.        int respnum;
  462.  
  463. #ifdef SIGTSTP
  464.        signal(SIGTSTP, group_susp);
  465. #endif
  466.  
  467.        if (clr) {
  468.                ClearScreen();
  469.                printf("%s\r\012", nice_time());        /* time in upper left */
  470.                center_line(1, group);
  471.        }
  472.  
  473.        show_mail ();
  474.  
  475.        MoveCursor(INDEX_TOP, 0);
  476.  
  477.        first_subj_on_screen = (index_point / NOTESLINES) * NOTESLINES;
  478.        if (first_subj_on_screen < 0)
  479.                first_subj_on_screen = 0;
  480.  
  481.        last_subj_on_screen = first_subj_on_screen + NOTESLINES;
  482.        if (last_subj_on_screen >= top_base) {
  483.                last_subj_on_screen = top_base;
  484.                first_subj_on_screen = top_base - NOTESLINES;
  485.  
  486.                if (first_subj_on_screen < 0)
  487.                        first_subj_on_screen = 0;
  488.        }
  489.  
  490.        for (i = first_subj_on_screen; i < last_subj_on_screen; i++) {
  491.                if (new_responses(i))
  492.                        new_resps = '+';
  493.                else
  494.                        new_resps = ' ';
  495.  
  496.                n = nresp(i);
  497.                if (n)
  498.                        sprintf(resps, "%4d", n);
  499.                else
  500.                        strcpy(resps, "    ");
  501.  
  502.                respnum = base[i];
  503.  
  504.                MoveCursor(INDEX_TOP + i - first_subj_on_screen, 3);
  505.                printf("%4d %c %s", i + 1, new_resps, arts[respnum].subject);
  506.                CleartoEOLN ();
  507.                MoveCursor(INDEX_TOP + i - first_subj_on_screen, COLS - 35);
  508.                printf ("%s %-.30s", resps, arts[respnum].from);
  509.                MoveCursor(INDEX_TOP + i - first_subj_on_screen, COLS - 1);
  510.                CleartoEOLN ();
  511.        }
  512.  
  513.        if (top_base <= 0)
  514.                info_message("*** No Articles ***");
  515.        else if (last_subj_on_screen == top_base)
  516.                info_message("*** End of Articles ***");
  517.  
  518.        if (top_base > 0)
  519.                draw_subject_arrow();
  520. }
  521.  
  522. draw_subject_arrow() {
  523.  
  524.        draw_arrow(INDEX_TOP + (index_point-first_subj_on_screen) );
  525. }
  526.  
  527. erase_subject_arrow() {
  528.  
  529.        erase_arrow(INDEX_TOP + (index_point-first_subj_on_screen) );
  530. }
  531.  
  532.  
  533. prompt_subject_num(ch, group)
  534. char ch;
  535. char *group;
  536. {
  537. int num;
  538.  
  539.  
  540.        clear_message();
  541.  
  542.        if ((num = parse_num(ch, "Read article> ")) == -1) {
  543.                clear_message();
  544.                return FALSE;
  545.        }
  546.        num--;          /* index from 0 (internal) vs. 1 (user) */
  547.  
  548.        if (num >= top_base)
  549.                num = top_base - 1;
  550.  
  551.        if (num >= first_subj_on_screen
  552.        &&  num < last_subj_on_screen) {
  553.                erase_subject_arrow();
  554.                index_point = num;
  555.                draw_subject_arrow();
  556.        } else {
  557.                index_point = num;
  558.                show_group_page(group, TRUE);
  559.        }
  560. }
  561.  
  562. void
  563. search_subject(forward, group)
  564. int forward;
  565. char *group;
  566. {
  567.        char buf[LEN+1];
  568.        int i;
  569. #ifndef        REGEXP
  570.        extern char *regcmp();
  571.        extern char *regex();
  572.        char *re;
  573. #else  /* REGEXP */
  574.        regexp *re;
  575. #endif /* REGEXP */
  576.        char *prompt;
  577.  
  578.        clear_message();
  579.  
  580.        if (forward)
  581.                prompt = "/";
  582.        else
  583.                prompt = "?";
  584.  
  585.        if (!parse_string(prompt, buf))
  586.                return;
  587.  
  588.        if (strlen(buf))
  589.                strcpy(subject_search_string, buf);
  590.        else if (!strlen(subject_search_string)) {
  591.                info_message("No search pattern");
  592.                return;
  593.        }
  594.  
  595.        i = index_point;
  596.  
  597.        glob_name(subject_search_string, buf);
  598.  
  599. #ifndef        REGEXP
  600.        if ((re = regcmp(buf, NULL)) == NULL) {
  601. #else  /* REGEXP */
  602.        if ((re = regcomp (buf)) == NULL) {
  603. #endif /* REGEXP */
  604.                info_message("Bad search pattern");
  605.                return;
  606.        }
  607.  
  608.        do {
  609.                if (forward)
  610.                        i++;
  611.                else
  612.                        i--;
  613.  
  614.                if (i >= top_base)
  615.                        i = 0;
  616.                if (i < 0)
  617.                        i = top_base - 1;
  618.  
  619. #ifndef        REGEXP
  620.                if (regex(re, arts[ base[i] ].subject) != NULL) {
  621. #else  /* REGEXP */
  622.                if (regexec (re, arts[ base[i] ].subject) != NULL) {
  623. #endif /* REGEXP */
  624.                        if (i >= first_subj_on_screen
  625.                        &&  i < last_subj_on_screen) {
  626.                                erase_subject_arrow();
  627.                                index_point = i;
  628.                                draw_subject_arrow();
  629.                        } else {
  630.                                index_point = i;
  631.                                show_group_page(group, TRUE);
  632.                        }
  633.                        return;
  634.                }
  635.        } while (i != index_point);
  636.  
  637.        info_message("No match");
  638. }
  639.  
  640.  
  641. /*
  642.  *  Post an original article (not a followup)
  643.  */
  644.  
  645. post_base(group)
  646. char *group;
  647. {
  648.        FILE *fp;
  649.        char nam[100];
  650.        char ch;
  651.        char subj[LEN+1];
  652.        char buf[200];
  653.        int line;
  654. #ifdef GET_DIST
  655.        char *ptr;
  656. #endif /* GET_DIST */
  657.  
  658.        if (!parse_string("Subject: ", subj))
  659.                return(FALSE);
  660.        if (subj[0] == '\0')
  661.                return(FALSE);
  662.  
  663. #ifdef USE_UID
  664.        setuid(real_uid);
  665.        setgid(real_gid);
  666. #endif /* USE_UID */
  667.  
  668.        sprintf(nam, "%s/.article", homedir);
  669.        umask (omask);
  670.        if ((fp = fopen(nam, "w")) == NULL) {
  671.                umask (0);
  672.                fprintf(stderr, "can't open %s: ", nam);
  673.                perror("");
  674.                return(FALSE);
  675.        }
  676. #ifndef        OSK
  677.        chmod(nam, 0600);
  678. #else  /* OSK */
  679.        chmod(nam, 013);
  680. #endif /* OSK */
  681.  
  682.        fprintf(fp, "Subject: %s\n", subj);
  683.        fprintf(fp, "Newsgroups: %s\n", group);
  684. #ifndef        GET_DIST
  685. /*     fprintf(fp, "Distribution: \n");        */
  686.        line = 2;
  687. #else  /* GET_DIST */
  688.        strcpy (buf, group);
  689.        if (ptr = index (buf, '.'))
  690.                *ptr = '\0';
  691.        fprintf(fp, "Distribution: %s\n", buf);
  692.        line = 3;
  693. #endif /* GET_DIST */
  694.        if (*my_org) {
  695.                fprintf(fp, "Organization: %s\n", my_org);
  696.                ++line;
  697.        }
  698.        fprintf(fp, "\n");
  699.        ++line;
  700.  
  701. #ifdef APPEND_SIG
  702.        add_signature (fp);
  703. #endif /* APPEND_SIG */
  704.  
  705.        fclose(fp);
  706.        umask (0);
  707.  
  708.        ch = 'e';
  709.        while (1) {
  710.                switch (ch) {
  711.                case 'e':
  712.                        invoke_editor(nam, line);
  713.                        break;
  714.  
  715.                case 'a':
  716.                        return FALSE;
  717.  
  718.                case 'p':
  719.                        printf("\rPosting...  ");
  720.                        CleartoEOLN ();
  721. #ifndef        OSK
  722.                        sprintf(buf, "%s/inews -h < %s", LIBDIR, nam);
  723. #else  /* OSK */
  724.                        sprintf(buf, "inews -h <%s", nam);
  725. #endif /* OSK */
  726.                        if (invoke_cmd(buf)) {
  727.                                printf("article posted ");
  728.                                fflush(stdout);
  729.                                goto post_base_done;
  730.                        } else {
  731.                                printf("article rejected ");
  732.                                fflush(stdout);
  733.                                break;
  734.                        }
  735.                }
  736.  
  737.                do {
  738.                        MoveCursor(LINES, 0);
  739.                        fputs("abort, edit, post: ", stdout);
  740.                        fflush(stdout);
  741.                        ch = ReadCh();
  742.                } while (ch != 'a' && ch != 'e' && ch != 'p');
  743.        }
  744.  
  745. post_base_done:
  746. #ifdef USE_UID
  747.        setuid(tass_uid);
  748.        setgid(tass_gid);
  749. #endif /* USE_UID */
  750.  
  751.        continue_prompt();
  752.  
  753.        return(TRUE);
  754. }
  755.  
  756.  
  757. /*
  758.  *  Return the number of unread articles there are within a thread
  759.  */
  760.  
  761. new_responses(thread)
  762. int thread;
  763. {
  764.        int i;
  765.        int sum = 0;
  766.  
  767.        for (i = base[thread]; i >= 0; i = arts[i].thread)
  768.                if (arts[i].unread)
  769.                        sum++;
  770.  
  771.        return sum;
  772. }
  773.  
  774. void
  775. tass_group_help() {
  776.        char ch;
  777.  
  778. group_help_start:
  779.  
  780.        ClearScreen();
  781.        center_line(0, TASS_HEADER);
  782.        center_line(1, "Index Page Commands (page 1 of 2)");
  783.  
  784.        MoveCursor(3, 0);
  785.  
  786.        printf("4        Select article 4\r\012");
  787.        printf("^D, ^V   half / full Page down\r\012");
  788.        printf("^U, ^Z   half / full  Page up\r\012");
  789.        printf("<CR>     Read current article\r\012");
  790.        printf("<TAB>    View next unread article or group\r\012");
  791.        printf("c        Mark all articles as read\r\012");
  792.        printf("g        Choose a new group by name\r\012");
  793.        printf("j        Down a line\r\012");
  794.        printf("k        Up a line\r\012");
  795.        printf("n        Go to next group\r\012");
  796.        printf("N        Go to next unread article\r\012");
  797.        printf("p        Go to previous group\r\012");
  798.        printf("P        Go to previous unread article\r\012");
  799.        printf("q        Quit\r\012");
  800.  
  801.        center_line(LINES, "-- hit space for more commands --");
  802.        ch = ReadCh();
  803.        if (ch != ' ')
  804.                return;
  805.  
  806.        ClearScreen();
  807.        center_line(0, TASS_HEADER);
  808.        center_line(1, "Index Page Commands (page 2 of 2)");
  809.  
  810.        MoveCursor(3, 0);
  811.  
  812.        printf("s        Subscribe to this group\r\012");
  813.        printf("t        Return to group selection index\r\012");
  814.        printf("u        Unsubscribe to this group\r\012");
  815.        printf("w        Post an article\r\012");
  816.        printf("/        Search forward for subject\r\012");
  817.        printf("?        Search backward for subject\r\012");
  818.        printf("-        Show last message\r\012");
  819.  
  820.        center_line(LINES, "-- hit any key --");
  821.        ch = ReadCh();
  822.        if (ch == 'b')
  823.                goto group_help_start;
  824. }
  825.