home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / nn.tar / nn-6.5.1 / more.c < prev    next >
C/C++ Source or Header  |  1996-08-11  |  33KB  |  1,553 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Article browser.
  5.  */
  6.  
  7. #include "config.h"
  8. #include "articles.h"
  9. #include "news.h"
  10. #include "keymap.h"
  11. #include "nn_term.h"
  12. #include "menu.h"
  13. #include "regexp.h"
  14.  
  15. /* more.c */
  16.  
  17. static void more_auto_select __APROTO((void));
  18. static char *a_st_flags __APROTO((flag_type flag));
  19. static void brief_header_line __APROTO((register article_header *ah, int lno));
  20.  
  21.  
  22. export int  monitor_mode = 0;
  23. export int  compress_mode = 0;
  24. export int  show_article_date = 1;
  25. export int  first_page_lines = 0;
  26. export int  overlap = 2;
  27. export int  mark_overlap = 0;
  28. export char *header_lines = NULL;
  29. export int  min_pv_window = 7;
  30. export int  wrap_headers = 6;
  31. export int  data_bits = 7;
  32. export int  scroll_clear_page = 1;
  33. export int  expired_msg_delay = 1;
  34. export char *trusted_escapes = NULL;
  35. export int  new_read_prompt = 1;
  36. export int  re_layout_more = -1;
  37. export int  scroll_last_lines = 0;
  38. export int  ignore_formfeed = 0;
  39.  
  40. import int  preview_window;
  41. import int  novice;
  42. import int  slow_mode;
  43. import int  auto_preview_mode;
  44. import int  flush_typeahead;
  45. import int  case_fold_search;
  46. import int  echo_prefix_key;
  47. import int  re_layout;
  48. import char *folder_save_file, *default_save_file;
  49. import int show_art_next_invalid;
  50. import int mouse_y,mouse_x;  
  51. import int mouse_state;            
  52. extern int STANDOUT;
  53. extern int alt_cmd_key, in_menu_mode, any_message;
  54. import long n_selected;
  55.  
  56. import char delayed_msg[];
  57.  
  58. extern char *init_save();
  59.  
  60. static int rot13_must_init = 1;
  61. static char rot13_table[128];
  62. export int rot13_active = 0;
  63. #define ROT13_DECODE(c)     ((c & 0x80) ? c : rot13_table[c])
  64.  
  65. static int compress_space;
  66.  
  67. static regexp *regular_expr = NULL;
  68.  
  69. #define LINEMAX    100        /* most articles are less than 100 lines */
  70.  
  71. export int  mark_overlap_shading = 0;
  72.  
  73. static struct header_def {
  74.     char field;
  75.     char *text;
  76.     char **news;
  77.     char **digest;
  78. } header_defs[] = {
  79.     'A', "Approved",    &news.ng_appr,        0,
  80.     'B', "Distribution",&news.ng_dist,        0,
  81.     'c', "Comment-To",    &news.ng_comment,    0,
  82.     'C', "Control",    &news.ng_control,    0,
  83.     'D', "Date",    &news.ng_date,        &digest.dg_date,
  84.     'F', "From",    &news.ng_from,        &digest.dg_from,
  85.     'f', "Sender",    &news.ng_sender,    0,
  86.     'I', "Message-Id",    &news.ng_ident,        0,
  87.     'J', "Originator",    &news.ng_origr,        0,
  88.     'K', "Keywords",    &news.ng_keyw,        0,
  89.     'L', "Lines",    &news.ng_xlines,    0,
  90.     'N', "Newsgroups",    &news.ng_groups,    0,
  91.     'O', "Organization",&news.ng_org,        0,
  92.     'P', "Path",    &news.ng_path,        0,
  93.     'R', "Reply-To",    &news.ng_reply,        0,
  94.     'S', "Subject",    &news.ng_subj,        &digest.dg_subj,
  95.     'W', "Followup-To",    &news.ng_follow,    0,
  96.     'X', "References",    &news.ng_ref,        0,
  97.     'Y', "Summary",    &news.ng_summ,        0,
  98.     'd', "Date-Received", &news.ng_rdate,    0,
  99.     'g', "Newsgroup",    &news.ng_groups,    0,
  100.     'G', "Newsgroup",    &news.ng_groups,    0,
  101.     'n', "Newsgroups",    &news.ng_groups,    0,
  102.     'x', "Back-Ref",    &news.ng_bref,        0,
  103.     'v', "Save-File",    NULL,            0,
  104.     'a', "Spool-File",    NULL,            0,
  105.     'i', "DB-Info",    NULL,            0,
  106.     0
  107. };
  108.  
  109. int
  110. get_header_field(code, namep, valp, ah)
  111. char code, **namep, **valp;
  112. register article_header *ah;
  113. {
  114.     static char special[FILENAME];
  115.     register struct header_def *hdef;
  116.     char *lp;
  117.  
  118.     lp = NULL;
  119.     for (hdef = header_defs; hdef->field; hdef++) {
  120.     if (hdef->field != code) continue;
  121.  
  122.     if ((ah->flag & A_DIGEST) && hdef->digest)
  123.         lp = *(hdef->digest);
  124.     if (lp == NULL && hdef->news)
  125.         lp = *(hdef->news);
  126.     break;
  127.     }
  128.     
  129.     switch (code) {
  130.      case 'n':
  131.      case 'g':
  132.     if (lp == NULL) break;
  133.     if (!(current_group->group_flag & G_MERGED) && strchr(lp, ',') == NULL)
  134.         return 0;
  135.     if (code == 'n') break;
  136.     /*FALLTHRU*/
  137.      case 'G':
  138.     if (ah->a_number > 0) {
  139.         sprintf(special, "%s/%ld", 
  140.             current_group->group_name, (long)ah->a_number);
  141.         lp = special;
  142.     } else
  143.         lp = current_group->group_name;
  144.     break;
  145.  
  146.      case 'a':
  147.     if (current_group->group_flag & G_FOLDER)
  148.         lp = current_group->archive_file;
  149.     else
  150.     if (group_file_name && *group_file_name)
  151.         lp = group_path_name;
  152.     break;
  153.  
  154.      case 'v':
  155.     if ((lp = current_group->save_file) == NULL)
  156.         lp = (current_group->group_flag & G_FOLDER) ?
  157.         folder_save_file : default_save_file;
  158.     if (lp == NULL) return 0;
  159.     if (expand_file_name(special, lp, 2)) lp = special;
  160.     break;
  161.  
  162.      case 'i':
  163.     sprintf(special, "#%ld fl=%lx re=%d li=%d hp=%ld fp=%ld lp=%ld ts=%ld",
  164.         (long)ah->a_number, (long)ah->flag, ah->replies, ah->lines,
  165.         (long)ah->hpos, (long)ah->fpos, (long)ah->lpos,
  166.         (long)ah->t_stamp);
  167.     lp = special;
  168.     break;
  169.     }
  170.     if (lp == NULL) return 0;
  171.  
  172.     *namep = hdef->text;
  173.     *valp = lp;
  174.     return 1;
  175. }
  176.  
  177. static char *scan_codes;
  178. static article_header *scan_arthdr;
  179.  
  180. void
  181. scan_header_fields(fields, ah)
  182. char *fields;
  183. article_header *ah;
  184. {
  185.     scan_codes = fields;
  186.     scan_arthdr = ah;
  187. }
  188.  
  189. int
  190. next_header_field(namep, valp, attrp)
  191. char **namep, **valp;
  192. fct_type *attrp;
  193. {
  194.     fct_type attr;
  195.  
  196.     while (*scan_codes) {
  197.     attr = NULL_FCT;
  198.     *namep = NULL;
  199.  
  200.     switch (*scan_codes) {
  201.      case '*':
  202.         scan_codes++;
  203.         return 1;    /* name == NULL */
  204.         
  205.      case '=':
  206.         attr = highlight;
  207.         scan_codes++;
  208.         break;
  209.         
  210.      case '_':
  211.         attr = underline;
  212.         scan_codes++;
  213.         break;
  214.  
  215.      case '+':
  216.         attr = shadeline;
  217.         scan_codes++;
  218.         break;
  219.     }
  220.     
  221.     if (*scan_codes == NUL) break;
  222.  
  223.     if (attrp) *attrp = attr;
  224.     if (get_header_field(*scan_codes++, namep, valp, scan_arthdr))
  225.         return 1;
  226.     }
  227.     return 0;
  228. }
  229.  
  230. static void
  231. more_auto_select()
  232. {
  233.     register article_header *ah;
  234.     register int32 n;
  235.     int count = 0;
  236.  
  237.     for (n = 0; n < n_articles; n++) {
  238.     ah = articles[n];
  239.     if (ah->attr == A_READ) continue;
  240.     if (ah->attr & A_SELECT) continue;
  241.  
  242.     if (auto_select_article(ah, 2)) {
  243.         ah->attr = A_AUTO_SELECT;
  244.         show_art_next_invalid = 1;
  245.         count++;
  246.     }
  247.     }
  248.  
  249.     if (count) msg("Selected %d articles", count);
  250. }
  251.  
  252. static char *a_st_flags(flag)
  253. flag_type flag;
  254. {
  255.     static char buf[40];
  256.     register char *cp;
  257.     static flag_type prevflag = 0;
  258.  
  259.     flag &= A_ST_FILED | A_ST_REPLY | A_ST_FOLLOW;
  260.     if (flag == 0) {
  261.     prevflag = 0;
  262.     return "";
  263.     }
  264.  
  265.     if (flag == prevflag) return buf;
  266.     prevflag = flag;
  267.  
  268.     cp = buf;
  269.     *cp++ = '(';
  270.     if (flag & A_ST_FILED) {
  271.     *cp++ = 'F';
  272.     *cp++ = 'i';
  273.     *cp++ = 'l';
  274.     *cp++ = 'e';
  275.     *cp++ = 'd';
  276.     }
  277.  
  278.     if (flag & A_ST_REPLY) {
  279.     if (cp[-1] != '(') *cp++ = SP;
  280.     *cp++ = 'R';
  281.     *cp++ = 'e';
  282.     }
  283.  
  284.     if (flag & A_ST_FOLLOW) {
  285.     if (cp[-1] != '(') *cp++ = SP;
  286.     *cp++ = 'F';
  287.     *cp++ = 'o';
  288.     *cp++ = 'l';
  289.     }
  290.  
  291.     strcpy(cp, new_read_prompt ? ")--" : ")------");
  292.     return buf;
  293. }
  294.  
  295. static void
  296. brief_header_line(ah, lno)
  297. register article_header *ah;
  298. int lno;
  299. {
  300.     int o_re_layout;
  301.  
  302.     so_gotoxy(0, lno, 0);
  303.     so_printf("%s: ", ah->sender);
  304.     o_re_layout = re_layout;
  305.     if (re_layout_more >= 0) re_layout = re_layout_more;
  306.     prt_replies(ah->replies);
  307.     re_layout = o_re_layout;
  308.     so_printf("%s", ah->subject);
  309.     so_end();
  310. }
  311.  
  312. #ifdef NOV
  313. /* fill in ah->?pos from the article itself */
  314. /* This should really go into more itself */
  315. void
  316. setpos(ah, art)
  317. register article_header *ah;
  318. register FILE *art;
  319. {
  320.   /* XXX: set to zero here? Digests? */
  321.   register long startpos = ftell(art);
  322.   char     line[1024];
  323.  
  324.   ah->fpos = 0;            /* initialize in case not found */
  325.  
  326.   /* header position == beginning of file */
  327.   ah->hpos = 0;
  328.  
  329.   /* find the length */
  330.   fseek(art, 0L, 2);
  331.   ah->lpos = ftell(art);
  332.  
  333.   /* always start from the beginning */
  334.   fseek(art, 0L, 0);
  335.   while (fgets(line, sizeof(line), art) != NULL) 
  336.     if (*line == '\n') {    /* end of header? */
  337.       ah->fpos = ftell(art);    /* start of article */
  338.       break;
  339.     }
  340.   fseek(art, startpos, 0);
  341. }
  342. #endif /* NOV */
  343.  
  344.  
  345. int
  346. more(ah, mode, screen_offset)
  347. article_header *ah;
  348. int mode, screen_offset;
  349. {
  350.     register char *lp;
  351.     register int c, col, lno = 0;
  352.     register FILE *art;
  353.     int more_cmd, eof, skip_spaces, has_space, window_lines;
  354.     int form_feed, last_ff_line, ignore_nl = 0;
  355.     off_t lineposbuf[LINEMAX];
  356.     off_t *linepos = lineposbuf;
  357.     int linemax = LINEMAX;
  358.     char linebuf[200], skip_char;
  359.     int skip_wrap;
  360.     news_header_buffer ngheader, dgheader;
  361.     struct news_header news_save;
  362.     struct digest_header digest_save;
  363.     int linenum, maxline, topline, print_lines, lno1;
  364.     int scroll_lines, scroll_from;
  365.     off_t scroll_offset;
  366.     int underline_line, fake_underline;
  367.     int match_lines, match_redraw, match_topline = 0, match_botline;
  368.     int goto_line, prev_goto, stop_line, extra_lines;
  369.     flag_type in_digest = ah->flag & A_DIGEST;
  370.     article_header digestah;
  371.     char *fname, *hdrline;
  372.     char pr_fmt[200], send_date[40];
  373.     int match_expr, shade_overlap, shade_line;
  374.     int *key_map;
  375.     key_type cur_key;
  376.     fct_type hdrattr;
  377.     char *match_start, *match_end = NULL;
  378.     int open_modes, o_mode;
  379. #ifdef RESIZING
  380.     int entry_col = Columns;
  381. #endif
  382.  
  383. #define more_return(cmd) \
  384.     { more_cmd = cmd; goto more_exit; }
  385.  
  386.     if (ah->a_group != NULL) init_group(ah->a_group);
  387.  
  388.     open_modes = SKIP_HEADER;
  389.     if (show_article_date || header_lines) {
  390.     open_modes |= FILL_NEWS_HEADER;
  391.     if (header_lines == NULL)
  392.         open_modes |= GET_DATE_ONLY;
  393.     else
  394.         open_modes |= GET_ALL_FIELDS;
  395.     if (in_digest) open_modes |= FILL_DIGEST_HEADER;
  396.     }
  397.  
  398.     art = open_news_article(ah, open_modes, ngheader, dgheader);
  399.  
  400.     if (art == NULL) {
  401.     if (expired_msg_delay >= 0) {
  402.         msg("Canceled or expired: \"%s: %-.35s\"", ah->sender, ah->subject);
  403.         if ((mode & MM_PREVIEW) == 0 && expired_msg_delay > 0)
  404.         user_delay(expired_msg_delay);
  405.     }
  406.     return MC_NEXT;
  407.     }
  408.  
  409.     o_mode = in_menu_mode;
  410.     in_menu_mode = 0;
  411.  
  412.     if (screen_offset)
  413.     if (preview_window < 1 && Lines - screen_offset < min_pv_window)
  414.         screen_offset = 0;
  415.         else {
  416.         brief_header_line(ah, screen_offset++);
  417.         if (!STANDOUT) screen_offset++;
  418.         clrline();
  419.     }
  420.  
  421.     if (show_article_date) {
  422.     if (in_digest && digest.dg_date)
  423.         strncpy(send_date, digest.dg_date, 40);
  424.     else
  425.         if (news.ng_date) {
  426.         strncpy(send_date, news.ng_date, 40);
  427.         } else
  428.         send_date[0] = NUL;
  429.     send_date[39] = NUL;
  430.     if ((lp = strrchr(send_date, ':'))) *lp = NUL;
  431.     }
  432.  
  433.     linepos[0] = ah->hpos;
  434.     linepos[1] = ah->fpos;
  435.     maxline = 1;
  436.     topline = 1;
  437.     hdrline = screen_offset == 0 ? header_lines : "";
  438.  
  439.     rot13_active = 0;
  440.     compress_space = compress_mode;
  441.     last_ff_line = goto_line = -1, prev_goto = 1;
  442.     skip_char = NUL; skip_wrap = 0;
  443.     match_lines = match_redraw = match_expr = 0;
  444.     underline_line = -1;
  445.     fake_underline = 0;
  446.     shade_overlap = 0;
  447.  
  448.     /* initialization added by Peter Wemm..  These vars may be used before
  449.        set, what should they *really* be set to to be safe? XXXX */
  450.     window_lines = 0;
  451.     form_feed = 0;
  452.     lno1 = 0;
  453.     match_botline = 0;
  454.     extra_lines = 0;
  455.     cur_key = 0;
  456.     /* end */
  457.  
  458.     scroll_lines = scroll_from = 0;
  459.     scroll_offset = 0;
  460.     if (scroll_last_lines < 0)
  461.     scroll_from = -1;
  462.     else if (scroll_last_lines > 0) {
  463.     if (ah->lines > 0)
  464.         scroll_from = ah->lines - scroll_last_lines;
  465.     else
  466.         scroll_offset = ah->lpos - (scroll_last_lines * 64);
  467.     }
  468.  
  469.     stop_line = first_page_lines ? first_page_lines : -1;
  470.  
  471.     if (new_read_prompt) {
  472.     char *xp, *group_name = current_group->group_name;
  473.     int len, maxl;
  474.  
  475.     maxl = novice ? 18 : 25;
  476.     
  477.     if ((len = strlen(group_name)) > maxl) {
  478.         for (xp = group_name + len - maxl; *xp; xp++) {
  479.         if (*xp == '.') break;
  480.         if (*xp == '/') { xp++; break; }
  481.         }
  482.         if (*xp)
  483.         group_name = xp;
  484.         else
  485.         group_name += len - maxl;
  486.     }
  487.     
  488.     if (mode & (MM_PREVIEW | MM_DIGEST) || n_selected == 0)
  489.         sprintf(pr_fmt,
  490.             "\1\2--%s-- %s%s %s--%%s--%%s\1",
  491.             group_name,
  492.             (mode & MM_DIGEST) ? "DIGEST" :
  493.             (mode & MM_PREVIEW) ? "PREVIEW" : "LAST",
  494.             (ah->flag & A_NEXT_SAME) ? "+next" : "",
  495.             novice ? "--help:?" : "");
  496.     else
  497.         sprintf(pr_fmt,
  498.             "\1\2--%s-- %ld MORE%s %s--%%s--%%s\1",
  499.             group_name,
  500.             n_selected,
  501.             (ah->flag & A_NEXT_SAME) ? "+next" : "",
  502.             novice ? "--help:?" : "");
  503.     } else
  504.     sprintf(pr_fmt,
  505.         "\1\2-- %s%s %s-----%%s%s-----%%s\1",
  506.         (mode & MM_PREVIEW) ? "PREVIEW " : "",
  507.         (mode & MM_DIGEST) ? "FULL DIGEST" :
  508.         (mode & MM_LAST_SELECTED) ? "LAST ARTICLE" : "ARTICLE",
  509.         novice ? "-- help:? " : "",
  510.         (ah->flag & A_NEXT_SAME) ? " (+next)" : "");
  511.  
  512.     if (screen_offset) goto safe_redraw;
  513.  
  514.  redraw:        /* redraw that will destroy whole screen */
  515.     screen_offset = 0;
  516.  
  517.  safe_redraw:     /* redraw of "more window" only */
  518.     linenum = topline;
  519.  
  520.  next_page:
  521.     no_raw();
  522.  
  523.     s_keyboard = 0;
  524.  
  525.     if (stop_line) {
  526.     lno = screen_offset;
  527.     if (scroll_clear_page || linenum <= 1) {
  528.         if (lno) {
  529.         gotoxy(0, lno);
  530.         clrpage();
  531.         } else
  532.         clrdisp();
  533.     }
  534.  
  535.     if (linenum == 1)
  536.     {
  537.         hdrline = screen_offset == 0 ? header_lines : "";
  538.         if (hdrline && hdrline[0] == '@') {
  539.         linenum = 0;
  540.         fseek(art, linepos[0], 0);
  541.         hdrline = NULL;
  542.         }
  543.     }
  544.  
  545.       print_header:
  546.     if (hdrline == NULL || *hdrline == '*') {
  547.         if (hdrline && *++hdrline == NUL) hdrline = NULL;
  548.  
  549.         if (linenum <= 1) {
  550.         if (linenum == 0 || (mode & MM_DIGEST)) {
  551.             if (screen_offset) {
  552.             lno--;
  553.             if (!STANDOUT) lno--;
  554.             gotoxy(0, lno);
  555.             }
  556.  
  557.             so_printxy(0, lno,
  558.                    "Newsgroup: %s, article: %ld%s",
  559.                    current_group->group_name,
  560.                    (long)(ah->a_number),
  561.                    ((mode & MM_DIGEST) || in_digest)
  562.                    ? "  *DIGEST*" : "");
  563. /*            fseek(art, linepos[0], 0); */
  564.  
  565.             lno++;
  566.             if (!STANDOUT) lno++;
  567.         } else {
  568.             if (screen_offset == 0 && linenum == 1) {
  569.             if (show_article_date) so_printxy(-1, 0, send_date);
  570.  
  571.             brief_header_line(ah, lno++);
  572.             if (!STANDOUT) lno++;
  573.             }
  574.         }
  575.         }
  576.     }
  577.  
  578.     if (hdrline && screen_offset == 0) {
  579.  
  580.         scan_header_fields(hdrline, ah);
  581.         while (next_header_field(&fname, &hdrline, &hdrattr)) {
  582.  
  583.         if (fname == NULL) {
  584.             hdrline = --scan_codes;    /* this is a hack! */
  585.             goto print_header;
  586.         }
  587.         lp = hdrline;
  588.  
  589.         gotoxy(0, lno++);
  590.         tprintf("%s: ", fname);
  591.         c = col = strlen(fname) + 2;
  592.  
  593.          split_header_line:
  594.         if (hdrattr) CALL(hdrattr)(1);
  595.  
  596.         while (*lp && c < Columns) {
  597.             if (isspace(*lp)) {
  598.             while (lp[1] && isspace(lp[1])) lp++;
  599.             if (wrap_headers > 0 &&
  600.                 (c + wrap_headers) >= Columns &&
  601.                 (int)strlen(lp) >= wrap_headers) {
  602.                 lp++;
  603.                 break;
  604.             }
  605.             *lp = SP;
  606.             }
  607.             tputc(*lp++);
  608.             c++;
  609.         }
  610.         if (hdrattr) CALL(hdrattr)(0);
  611.         if (*lp && wrap_headers >= 0) {
  612.             gotoxy(col, lno++);
  613.             c = col;
  614.             goto split_header_line;
  615.         }
  616.         }
  617.  
  618.         hdrline = NULL;
  619.         tputc(NL);
  620.         lno++;
  621.     }
  622.  
  623.     lno1 = lno;
  624.     topline = linenum;
  625.  
  626.     window_lines = Lines - lno - 2;
  627.     print_lines = window_lines;
  628.  
  629.     ignore_nl = 1;    /* ignore blank lines at top op screen */
  630.     } else {
  631.     tputc(CR);
  632.     clrline();
  633.     print_lines = extra_lines;    /* LINT complaints here -- ignore */
  634.     }
  635.  
  636.     if (stop_line > 0) {
  637.     if (print_lines > stop_line) {
  638.         extra_lines = print_lines - stop_line;
  639.         print_lines = stop_line;
  640.         underline_line = -1;
  641.         shade_overlap = 0;
  642.     }
  643.     stop_line = 0;
  644.     } else
  645.     stop_line = -1;
  646.  
  647.  next_line:
  648.  
  649.     if (linenum == linemax) {
  650.     linemax += 500;
  651.     if (linepos == lineposbuf) {
  652.         linepos = newobj(off_t, linemax);
  653.         for (linenum = 0; linenum < LINEMAX; linenum++)
  654.         linepos[linenum] = lineposbuf[linenum];
  655.     } else
  656.         linepos = resizeobj(linepos, off_t, linemax);
  657.     }
  658.  
  659.     if (goto_line == linenum) {
  660.     goto_line = -1;
  661.     goto next_page;
  662.     }
  663.  
  664.     eof = 0;
  665.  
  666.     if (linenum > maxline)
  667.     linepos[++maxline] = ftell(art);
  668.     else
  669.     if (linenum > 0)
  670.     fseek(art, linepos[linenum], 0);
  671.  
  672.  
  673.     if (linepos[linenum] >= ah->lpos) {
  674.     if (match_expr) {
  675.         match_expr = 0;
  676.         topline = match_topline;    /* LINT complaints here -- ignore */
  677.         linenum = match_botline;    /* LINT complaints here -- ignore */
  678.         fseek(art, linepos[linenum], 0);
  679.         msg("Not found");
  680.         goto Prompt;
  681.     }
  682.     eof++;
  683.     if (goto_line > 0) {
  684.         goto_line = -1;
  685.         linenum -= window_lines/2;
  686.         goto next_page;
  687.     }
  688.     goto Prompt;
  689.     }
  690.  
  691.     if (linenum == 0) {
  692.     if (ftell(art) >= linepos[1]) {
  693.         linenum = 2;    /* current line is 1st line ! */
  694.         lno1 = lno;
  695.     }
  696.     } else
  697.     {
  698.     if (match_expr && linenum == match_botline)
  699.         msg("Searching...");
  700.     linenum++;
  701.     }
  702.  
  703.     lp = linebuf;
  704.     col = 0;
  705.     form_feed = 0;
  706.  
  707.  next_char:
  708.  
  709.     c = getc(art);
  710.     if (c == EOF) {
  711.     eof++;
  712.     if (lp == linebuf) goto Prompt;
  713.     goto end_line;
  714.     }
  715.  
  716.     if (c & 0200) {
  717.     if (monitor_mode || data_bits != 8) {
  718.         col += 4;
  719.         if (col > Columns) {    /* then there is no room for M-^X */
  720.         ungetc(c, art);
  721.         goto long_line;
  722.         }
  723.         c &= 0177;
  724.         *lp++ = 'M';
  725.         *lp++ = '-';
  726.         if (c < SP) {
  727.         *lp++ = '^';
  728.         c += '@';
  729.         } else
  730.         col--;
  731.     }
  732.     } else
  733.     if (c < SP) {
  734.     if (monitor_mode) {
  735.         if (c == NL) {
  736.         *lp++ = '$';
  737.             goto end_line;
  738.         }
  739.         if (col + 2 > Columns) {
  740.         *lp++ = '\\';
  741.         ungetc(c, art);
  742.         goto end_line;
  743.         }
  744.         *lp++ = '^';
  745.         c += '@';
  746.         col++;
  747.     } else
  748.     switch (c) {
  749.  
  750.      case '\f':
  751.         if (ignore_formfeed == 1)
  752.         goto default_control;
  753.         last_ff_line = linenum;
  754.         if (lp == linebuf) {
  755.         if (goto_line > 0 || skip_char || match_expr || lno == lno1)
  756.             goto next_line;
  757.         form_feed = 1;
  758.         goto Prompt;
  759.         }
  760.         form_feed = 1;
  761.         goto end_line;
  762.  
  763.      case CR:
  764.         if (lp == linebuf || ignore_nl) goto next_char;
  765.         ignore_nl = 1;
  766.         goto end_line;
  767.  
  768.      case NL:
  769.         if (ignore_nl) {
  770.         ignore_nl = 0;
  771.         if (lp == linebuf) {
  772.             if (lno == lno1) {
  773.             ignore_nl = 1;
  774.             goto next_line;
  775.             }
  776.             goto next_char;
  777.         }
  778.         }
  779.         goto end_line;
  780.  
  781.      case BS:
  782.         if (col) {
  783.         lp--;
  784.         col--;
  785.         }
  786.         goto next_char;
  787.  
  788.      case TAB:
  789.         if (col + 8 - (col & 07) >= Columns)
  790.         goto long_line;
  791.  
  792.         do {
  793.         *lp++ = SP;
  794.         col++;
  795.         } while (col & 07);
  796.         goto next_char;
  797.  
  798.      case 033: /* ESC may be a start/end of kanji or similar */
  799.         if (trusted_escapes != NULL) {
  800.         if (col + 3 > Columns) {
  801.             ungetc(c, art);
  802.             goto long_line;
  803.         }
  804.         if (strcmp(trusted_escapes, "all") == 0) break;
  805.         c = getc(art);
  806.         if (c == EOF) goto next_char;
  807.         ungetc(c, art);
  808.         for (fname = trusted_escapes; *fname; fname++)
  809.             if (c == *fname) break;
  810.         c = 033;
  811.         if (*fname != NUL) break;
  812.         }
  813.         /* FALL THRU */
  814.             
  815. default_control:
  816.      default:
  817.         if (col + 2 > Columns) {
  818.         ungetc(c, art);
  819.         goto long_line;
  820.         }
  821.         *lp++ = '^';
  822.         c += '@';
  823.         col++;
  824.         break;
  825.     }
  826.     } else
  827.     if (rot13_active && linenum > 0)
  828.     c = ROT13_DECODE(c);
  829.  
  830.     *lp++ = c;
  831.     col++;
  832.     ignore_nl = 0;
  833.  
  834.     if (col < Columns) goto next_char;
  835.  
  836. long_line:
  837.     ignore_nl = 1;
  838.  
  839.  end_line:
  840.     /* if we are seaching for a specific line, repeat until it is found */
  841.     if (skip_wrap) {
  842.     skip_wrap = ignore_nl;
  843.     goto next_line;
  844.     }
  845.     if (goto_line >= linenum) goto next_line;
  846.     if (skip_char) {
  847.     if (lp == linebuf || linebuf[0] == skip_char) {
  848.         skip_wrap = ignore_nl;
  849.         goto next_line;
  850.     }
  851.     skip_char = NUL;
  852.     if (overlap > 0) {
  853.         underline_line = linenum - 1;
  854.         linenum -= overlap + 1;
  855.         shade_overlap = mark_overlap_shading;
  856.         goto next_page;
  857.     }
  858.     }
  859.  
  860.     *lp++ = NUL;
  861.  
  862.     if (match_expr) {
  863.     if (!regexec_cf(regular_expr, linebuf))
  864.         goto next_line;
  865.     match_expr = 0;
  866.     match_lines = 1;
  867.     if (linenum > match_botline) {
  868.         match_redraw = 0;
  869.         if (last_ff_line > linenum) last_ff_line = -1;
  870.         linenum -= 5;
  871.         if (linenum < last_ff_line) linenum = last_ff_line;
  872.         goto next_page;
  873.     }
  874.     match_redraw = (stop_line < 0);
  875.     stop_line = -1;
  876.     lno = lno1 + linenum - topline - 1;
  877.     print_lines = window_lines - lno + lno1;
  878.     }
  879.  
  880.     /* now print the line */
  881.  
  882.     shade_line = 0;
  883.     if ((shade_overlap > 0 && linenum <= underline_line) ||
  884.     (shade_overlap < 0 && linenum > underline_line)) {
  885.     if (match_redraw) goto no_print;
  886.     match_start = NULL;
  887.     shade_line = 1;
  888.     } else
  889.     if (match_lines && underline_line != linenum &&
  890.     regexec_cf(regular_expr, linebuf)) {
  891.     match_start = regular_expr->startp[0];
  892.     match_end = regular_expr->endp[0];
  893.     if (match_start == match_end) {
  894.         match_start = NULL; /* null string */
  895.         if (match_redraw) goto no_print;
  896.     }
  897.     } else {
  898.     if (match_redraw) goto no_print;
  899.     match_start = NULL;
  900.     }
  901.  
  902.     gotoxy(0, lno);
  903.     if (!scroll_clear_page) clrline();
  904.  
  905.     if (shade_line)
  906.     shadeline(1);
  907.     else
  908.     if (mark_overlap && underline_line == linenum)
  909.     if (!underline(1))
  910.         fake_underline = 1;
  911.     skip_spaces = has_space = 0;
  912.  
  913.     for (lp = linebuf; (c = *lp); lp++) {
  914.  
  915.     if (match_start) {
  916.         if (lp == match_start) highlight(1);
  917.         if (lp == match_end) {
  918.         highlight(0);
  919.         match_start = NULL;
  920.         if (regexec_cf(regular_expr, lp)) {
  921.             match_start = regular_expr->startp[0];
  922.             match_end = regular_expr->endp[0];
  923.             lp--;
  924.             continue;
  925.          }
  926.         if (match_redraw) goto no_print;
  927.         }
  928.     }
  929.  
  930.     if (c == SP) {
  931.         if (skip_spaces) {
  932.         if (has_space) continue;
  933.         has_space++;
  934.         }
  935.         if (fake_underline) c = '_';
  936.     } else {
  937.         if (compress_space && c != ' ') {
  938.         skip_spaces = 1;
  939.         has_space = 0;
  940.         }
  941.     }
  942.  
  943.     tputc(c);
  944.     }
  945.  
  946.     if (match_start) highlight(0);
  947.  
  948.     if (shade_line) {
  949.     shadeline(0);
  950.     if (shade_overlap > 0 && underline_line == linenum) {
  951.         underline_line = -1;
  952.         shade_overlap = 0;
  953.     }
  954.     } else
  955.     if (mark_overlap && underline_line == linenum) {
  956.     while (lp - linebuf < 10) {
  957.         tputc(fake_underline ? '_' : ' ');
  958.         lp++;
  959.     }
  960.     underline(0);
  961.     underline_line = -1;
  962.     fake_underline = 0;
  963.     }
  964.  
  965. no_print:
  966.  
  967.     ++lno;
  968.     if (--print_lines > 0 && s_keyboard == 0 && form_feed == 0) goto next_line;
  969.  
  970.     if (shade_overlap) {
  971.     underline_line = -1;
  972.     shade_overlap = 0;
  973.     }
  974.  
  975.     if (!eof && linenum >= maxline) {
  976.     if (ignore_nl) {
  977.         c = getc(art);
  978.         if (c == EOF)
  979.         eof++;
  980.         else if (c != NL)
  981.         ungetc(c, art);
  982.         else
  983.         ignore_nl = 0;
  984.     }
  985.  
  986.     if (!eof && ftell(art) >= ah->lpos) eof++;
  987.     }
  988.  
  989.     match_redraw = 0;
  990.  
  991.  Prompt:
  992.  
  993.     if (eof && lno == screen_offset) more_return(MC_NEXT);
  994.  
  995.     if (scroll_lines > 0) {
  996.     if (eof)
  997.         scroll_lines = 0;
  998.     else {
  999.         print_lines = 1;
  1000.         scroll_lines--;
  1001.         prompt_line = lno;
  1002.         goto scroll_next;
  1003.     }
  1004.     }
  1005.     
  1006.     nn_raw();
  1007.  
  1008.     prompt_line = lno;
  1009.  
  1010.     if (!scroll_clear_page)
  1011.     clrpage();
  1012.  
  1013.  dflt_prompt:
  1014.  
  1015.     prompt(pr_fmt,
  1016.        pct((long)(ah->fpos), (long)(ah->lpos),
  1017.            (long)(linepos[topline]), (long)ftell(art)),
  1018.        a_st_flags(ah->flag));
  1019.  
  1020.     if (delayed_msg[0] != NUL) {
  1021.     msg(delayed_msg);
  1022.     delayed_msg[0] = NUL;
  1023.     }
  1024.  
  1025.  same_prompt:
  1026.  
  1027.     if (flush_typeahead) flush_input();
  1028.  
  1029.     key_map = more_key_map;
  1030.  
  1031.  prefix_key:    
  1032.     if ((c = get_c()) & GETC_COMMAND)
  1033.     c &= ~GETC_COMMAND;
  1034.     else
  1035.     c = key_map[cur_key = c];
  1036.  
  1037.     if (s_hangup) c = K_QUIT;
  1038.  
  1039.     if (c & K_PREFIX_KEY) {
  1040.     key_map = keymaps[c & ~K_PREFIX_KEY].km_map;
  1041.     if (echo_prefix_key) msg("%s", key_name(cur_key));
  1042.     goto prefix_key;
  1043.     }
  1044.  
  1045.     if (any_message && c != K_LAST_MESSAGE) clrmsg(0);
  1046.  
  1047.     if (c & K_MACRO) {
  1048.     m_invoke(c & ~K_MACRO);
  1049.     goto same_prompt;
  1050.     }
  1051.  
  1052. #define STATE(new_state)  c = new_state; goto alt_key; 
  1053.  
  1054.  alt_key:
  1055.  
  1056.     switch (c) {
  1057.      case K_UNBOUND:
  1058.     ding();
  1059.     /*FALLTHRU*/
  1060.      case K_INVALID:
  1061.     goto same_prompt;
  1062.  
  1063.      case K_REDRAW:
  1064. #ifdef RESIZING
  1065.     if (Columns != entry_col) {
  1066.         entry_col = Columns;
  1067.         maxline = topline = 1;
  1068.     }
  1069. #endif
  1070.      goto redraw;
  1071.  
  1072.      case K_M_CONTINUE:
  1073.     if (mouse_y >= 0) {
  1074.          if (mouse_y >= prompt_line) {
  1075.          STATE(K_NEXT_ARTICLE);
  1076.          } else if (mouse_y == 0) {
  1077.          if (topline == 1) {
  1078.             STATE(K_PREVIOUS);
  1079.          } else {
  1080.             STATE(K_PREV_PAGE);
  1081.          }
  1082.          } else {
  1083.         STATE(K_CONTINUE);
  1084.          }
  1085.      }
  1086.  
  1087.      case K_NEXT_PAGE:
  1088.     if (eof) {
  1089.         ding();
  1090.         goto same_prompt;
  1091.     }
  1092.  
  1093.     /* FALL THRU */
  1094.      case K_CONTINUE:
  1095.      if (eof) break;
  1096.     if (screen_offset == 0 && form_feed == 0 && stop_line) {
  1097.         if ((scroll_from && linenum > scroll_from) ||
  1098.         (scroll_offset && ftell(art) > scroll_offset)) {
  1099.         scroll_lines = Lines - 2 - overlap;
  1100.         print_lines = 1;
  1101.         goto scroll;
  1102.         }
  1103.         if (linenum > overlap) {
  1104.         underline_line = linenum;
  1105.         linenum -= overlap;
  1106.         shade_overlap = mark_overlap_shading;
  1107.         }
  1108.     }
  1109.     goto next_page;
  1110.  
  1111.      case K_LAST_MESSAGE:
  1112.     msg((char *)NULL);
  1113.     goto dflt_prompt;
  1114.  
  1115.      case K_HELP:
  1116.     display_help("more");
  1117.     goto redraw;
  1118.  
  1119.      case K_SHELL:
  1120.     tputc(CR);
  1121.     if (shell_escape()) goto redraw;
  1122.     goto dflt_prompt;
  1123.  
  1124.      case K_VERSION:
  1125.     prompt(P_VERSION);
  1126.     goto same_prompt;
  1127.  
  1128.       case K_M_TOGGLE:
  1129.      if (mouse_state) {
  1130.          xterm_mouse_off();
  1131.          mouse_state = 0;
  1132.      } else {
  1133.          xterm_mouse_on();
  1134.          mouse_state = 1;
  1135.      }
  1136.       goto dflt_prompt;
  1137.  
  1138.      case K_EXTENDED_CMD:
  1139.     news_save = news;
  1140.     digest_save = digest;
  1141.     more_cmd = alt_command();
  1142.     news = news_save;
  1143.     digest = digest_save;
  1144.  
  1145.     switch (more_cmd) {
  1146.  
  1147.      case AC_UNCHANGED:
  1148.         goto same_prompt;
  1149.  
  1150.      case AC_QUIT:
  1151.         more_return( MC_QUIT );
  1152.  
  1153.      case AC_PROMPT:
  1154.         goto dflt_prompt;
  1155.  
  1156.      case AC_REENTER_GROUP:
  1157.         more_return( MC_REENTER_GROUP );
  1158.  
  1159.      case AC_REORDER:
  1160.         more_return( MC_MENU );
  1161.  
  1162.      case AC_REDRAW:
  1163.         goto redraw;
  1164.  
  1165.      case AC_KEYCMD:
  1166.         c = alt_cmd_key;
  1167.         goto alt_key;
  1168.     }
  1169.     /* XXX: fall-thru? */
  1170.      case K_QUIT:
  1171.     ah->attr = A_LEAVE_NEXT;
  1172.     more_return( MC_QUIT );
  1173.  
  1174.      case K_SAVE_NO_HEADER:
  1175.      case K_SAVE_SHORT_HEADER:
  1176.      case K_SAVE_FULL_HEADER:
  1177.      case K_PRINT:
  1178.      case K_UNSHAR:
  1179.      case K_PATCH:
  1180.      case K_UUDECODE:
  1181.     news_save = news;
  1182.     digest_save = digest;
  1183.  
  1184.     tputc(CR);
  1185.     if (init_save(c, (char **)NULL) != NULL) {
  1186.         if (c == K_UNSHAR)
  1187.         prompt_line = Lines - 2;
  1188.  
  1189.         save(ah);
  1190.         end_save();
  1191.     }
  1192.     news = news_save;
  1193.     digest = digest_save;
  1194.     if (!slow_mode && (c == K_UNSHAR || c == K_PATCH)) {
  1195.         tprintf("\r\n\n");
  1196.         any_key(0);
  1197.         goto redraw;
  1198.     }
  1199.     goto Prompt;
  1200.  
  1201.      case K_FOLLOW_UP:
  1202. #ifdef NNTP_POST
  1203.      if (use_nntp && nntp_no_post()) goto Prompt;
  1204. #endif
  1205.      case K_REPLY:
  1206.      case K_MAIL_OR_FORWARD:
  1207.     news_save = news;
  1208.     digest_save = digest;
  1209.     more_cmd = answer(ah, c, -1);
  1210.     news = news_save;
  1211.     digest = digest_save;
  1212.     if (more_cmd)
  1213.         if (slow_mode) clrdisp(); else goto redraw;
  1214.     goto Prompt;
  1215.  
  1216.      case K_POST:
  1217.     if (post_menu())
  1218.         if (slow_mode) clrdisp(); else goto redraw;
  1219.     goto Prompt;
  1220.  
  1221.      case K_CANCEL:
  1222.     if (current_group->group_flag & G_FOLDER) {
  1223.         prompt("%s this folder entry",
  1224.            (ah->attr == A_CANCEL) ? "UNcancel" : "Cancel");
  1225.         if (yes(0)) fcancel(ah);
  1226.         goto Prompt;
  1227.     }
  1228.  
  1229.     if (cancel(ah) > 0) goto Prompt;
  1230.     more_return(MC_NEXT);
  1231.  
  1232.      case K_UNSUBSCRIBE:
  1233.     if (!unsubscribe(current_group)) goto Prompt;
  1234.     if ((current_group->group_flag & G_UNSUBSCRIBED) == 0) goto Prompt;
  1235.     more_return(MC_NEXTGROUP);
  1236.  
  1237.      case K_GROUP_OVERVIEW:
  1238.     group_overview(-1);
  1239.     goto redraw;
  1240.  
  1241.      case K_KILL_HANDLING:
  1242.     switch (kill_menu(ah)) {
  1243.      case 0:
  1244.         more_auto_select();
  1245.         ah->attr = 0;
  1246.         break;
  1247.      case 1:
  1248.         more_return(MC_DO_KILL);
  1249.      default:
  1250.         break;
  1251.     }
  1252.     goto Prompt;
  1253.  
  1254.      case K_READ_GROUP_UPDATE:
  1255.     if (mode & MM_PREVIEW) more_return(MC_MENU);
  1256.     prompt("Mark rest of current group as read?");
  1257.     if (yes(1) <= 0) goto Prompt;
  1258.     more_return(MC_READGROUP);
  1259.  
  1260.      case K_NEXT_GROUP_NO_UPDATE:
  1261.     if (mode & MM_PREVIEW) more_return(MC_MENU);
  1262.     more_return(MC_NEXTGROUP);
  1263.  
  1264.      case K_BACK_TO_MENU:
  1265.     more_return(MC_MENU);
  1266.  
  1267.      case K_PREVIOUS:
  1268.     if ((mode & MM_PREVIOUS) == 0) {
  1269.         msg("No previous article");
  1270.         goto dflt_prompt;
  1271.     }
  1272.     more_return(MC_PREV);
  1273.  
  1274.     /*FALLTHRU*/
  1275.      case K_ADVANCE_GROUP:
  1276.      case K_BACK_GROUP:
  1277.      case K_GOTO_GROUP:
  1278.     news_save = news;
  1279.     digest_save = digest;
  1280.     more_cmd = goto_group(c, ah, (flag_type)0);
  1281.     news = news_save;
  1282.     digest = digest_save;
  1283.  
  1284.     switch (more_cmd) {
  1285.      case ME_NO_REDRAW:
  1286.         goto Prompt;
  1287.  
  1288.      case ME_QUIT:
  1289.         more_return( ME_QUIT );
  1290.  
  1291.      default:
  1292.         goto redraw;
  1293.     }
  1294.  
  1295.      case K_NEXT_LINE:
  1296.     if (eof) break;
  1297.     if (screen_offset) goto same_prompt;
  1298.  
  1299.     print_lines = 1;
  1300.     goto scroll;
  1301.  
  1302.      case K_NEXT_HALF_PAGE:
  1303.     if (eof) break;
  1304.     if (screen_offset) goto same_prompt;
  1305.  
  1306.     print_lines = window_lines/2;
  1307.  
  1308.      scroll:
  1309.     gotoxy(0, prompt_line);
  1310.     clrpage();
  1311.     no_raw();
  1312.  
  1313.     if (print_lines + lno < (Lines - 1))
  1314.         goto next_page;
  1315.  
  1316.     stop_line = -1;
  1317.  
  1318.      scroll_next:
  1319.     gotoxy(0, Lines-1);
  1320.     c = print_lines + lno - Lines + 2;
  1321.     while (--c >= 0) {
  1322.         tputc(NL);
  1323.         if (--lno1 < 0) topline++;
  1324.         prompt_line--;
  1325.     }
  1326.     if (lno1 < 0) lno1 = 0;
  1327.     if (prompt_line < 0) prompt_line = 0;
  1328.     lno = prompt_line;
  1329.     goto next_line;
  1330.  
  1331.      case K_PREV_HALF_PAGE:
  1332.     /* XXX: Bug: will not back over headers */
  1333.     if (topline <= 1) goto Prompt;
  1334.     linenum = topline - window_lines/2;
  1335.     if (linenum < 1) linenum = 1;
  1336.     goto next_page;
  1337.  
  1338.      case K_PREV_PAGE:
  1339.     /* XXX: Bug: will not back over headers */
  1340.     if (topline <= 1) goto Prompt;
  1341.     linenum = topline - window_lines + overlap; /* not perfect after FF */
  1342.     underline_line = topline;
  1343.     shade_overlap = -mark_overlap_shading;
  1344.     if (linenum < 1) linenum = 1;
  1345.     goto next_page;
  1346.  
  1347.      case K_SKIP_LINES:
  1348.     skip_char = linebuf[0];
  1349.     goto next_page;
  1350.  
  1351.      case K_GOTO_LINE:
  1352.     prompt("\1Go to line:\1 ");
  1353.     if ((fname = get_s(NONE, NONE, "$^", NULL_FCT)) == NULL)
  1354.         goto Prompt;
  1355.  
  1356.     if (*fname == NUL) {
  1357.         if (prev_goto < 0) goto Prompt;
  1358.         goto_line = prev_goto;
  1359.  
  1360.     } else
  1361.     if (*fname == '$')
  1362.         goto_line = 30000;
  1363.     else
  1364.     if (*fname == '^')
  1365.         goto_line = 1;
  1366.     else {
  1367.         goto_line = atoi(fname);
  1368.         if (goto_line <= 0) {
  1369.         goto_line = -1;
  1370.         goto Prompt;
  1371.         }
  1372.     }
  1373.  
  1374.      goto_page:
  1375.     prev_goto = topline;
  1376.  
  1377.     if (goto_line <= maxline) {
  1378.         linenum = goto_line;
  1379.         goto_line = -1;
  1380.     }
  1381.  
  1382.     goto next_page;
  1383.  
  1384.      case K_SELECT_SUBJECT:
  1385.     more_return(MC_ALLSUBJ);
  1386.  
  1387.      case K_HEADER_PAGE:
  1388.     fseek(art, linepos[0], 0);
  1389.     goto_line = 0;
  1390.     goto goto_page;
  1391.  
  1392.      case K_FIRST_PAGE:
  1393.     goto_line = 1;
  1394.     goto goto_page;
  1395.  
  1396.      case K_LAST_PAGE:
  1397.     goto_line = 30000;
  1398.     goto goto_page;
  1399.  
  1400.      case K_GOTO_MATCH:
  1401.     prompt("\1/\1");
  1402.     if ((fname = get_s(NONE, NONE, "/", NULL_FCT)) == NULL)
  1403.         goto Prompt;
  1404.  
  1405.     if (*fname && *fname != '/') {
  1406.         if (regular_expr) freeobj(regular_expr);
  1407.         if (case_fold_search) fold_string(fname);
  1408.         regular_expr = regcomp(fname);
  1409.         match_lines = 0;
  1410.     }
  1411.     /* XXX: fall here? */
  1412.      case K_NEXT_MATCH:
  1413.     if (regular_expr == NULL) {
  1414.         msg("No previous expression");
  1415.         goto Prompt;
  1416.     }
  1417.  
  1418.     match_expr = 1;
  1419.     if (match_topline != topline) prev_goto = topline;
  1420.     match_topline = topline;
  1421.     match_botline = linenum;
  1422.     if (match_lines == 0 && topline <= 1) linenum = topline;
  1423.     match_lines = 0;
  1424.     goto next_line;        /* don't clear the screen if no match */
  1425.  
  1426.      case K_FULL_DIGEST:
  1427.     if (mode & MM_DIGEST)
  1428.         more_return( MC_NO_REDRAW );
  1429.  
  1430.     if (!in_digest)
  1431.         goto same_prompt;
  1432.  
  1433.     /* could do something more clever here later */
  1434.     digestah = *ah;
  1435.     digestah.flag &= ~A_DIGEST;
  1436.     digestah.hpos = digestah.fpos = 0;
  1437.     fseek(art, 0L, 2);
  1438.     digestah.lpos = ftell(art);
  1439.  
  1440.     switch (more(&digestah, mode | MM_DIGEST, screen_offset)) {
  1441.  
  1442.      case MC_REDRAW:
  1443.         goto redraw;
  1444.  
  1445.      case MC_NO_REDRAW:
  1446.         goto safe_redraw;
  1447.  
  1448.      case MC_QUIT:
  1449.         more_return( MC_QUIT );
  1450.  
  1451.      case MC_REENTER_GROUP:
  1452.         more_return( MC_REENTER_GROUP );
  1453.  
  1454.      default:
  1455.         goto safe_redraw;
  1456.     }
  1457.  
  1458.      case K_LEAVE_NEXT:
  1459.     ah->attr = A_LEAVE_NEXT;
  1460.     more_return(MC_PREVIEW_NEXT);
  1461.  
  1462.      case K_LEAVE_ARTICLE:
  1463.     ah->attr = (mode & MM_PREVIEW) ? A_SELECT : A_LEAVE;
  1464.  
  1465.     /*FALLTHRU*/
  1466.      case K_NEXT_ARTICLE:
  1467.     if ((mode & MM_PREVIEW) == 0) break;
  1468.     more_return(MC_PREVIEW_NEXT);
  1469.  
  1470.      case K_BACK_ARTICLE:
  1471.     if (mode & MM_FIRST_ARTICLE) {
  1472.         msg("First article is displayed");
  1473.         goto same_prompt;
  1474.     }
  1475.     more_return(MC_BACK_ART);
  1476.  
  1477.      case K_FORW_ARTICLE:
  1478.     if (mode & MM_LAST_ARTICLE) {
  1479.         msg("Last article is displayed");
  1480.         goto same_prompt;
  1481.     }
  1482.     more_return(MC_FORW_ART);
  1483.  
  1484.      case K_NEXT_SUBJECT:
  1485.     more_return(MC_NEXTSUBJ);
  1486.  
  1487.      case K_ROT13:
  1488.     if (rot13_must_init) {
  1489.         register i;
  1490.         for (i=0; i<=127; i++) {
  1491.         c = i;
  1492.         if (c >= 'a' && c <= 'm') c += 13;
  1493.         else if (c >= 'n' && c <= 'z') c -= 13;
  1494.         else if (c >= 'A' && c <= 'M') c += 13;
  1495.         else if (c >= 'N' && c <= 'Z') c -= 13;
  1496.         rot13_table[i] = c;
  1497.         }
  1498.         rot13_must_init = 0;
  1499.     }
  1500.  
  1501.     rot13_active = !rot13_active;
  1502.     goto safe_redraw;
  1503.  
  1504.      case K_COMPRESS:
  1505.     compress_space = !compress_space;
  1506.     goto safe_redraw;
  1507.  
  1508.      case K_PREVIEW:
  1509.     if (mode & MM_PREVIEW)
  1510.         more_return(MC_PREVIEW_OTHER);
  1511.  
  1512.     /* fall thru to "default" */
  1513.  
  1514.      default:
  1515.     msg("Command %d not supported", c);
  1516.     goto dflt_prompt;
  1517.     }
  1518.  
  1519.     more_return(MC_NEXT);
  1520.  
  1521.  more_exit:
  1522.     in_menu_mode = o_mode;
  1523.     rot13_active = 0;
  1524.  
  1525.     if (linepos != lineposbuf) freeobj(linepos);
  1526.  
  1527.     no_raw();
  1528.     fclose(art);
  1529.  
  1530.     if (mode & MM_PREVIEW)
  1531.     if (more_cmd != MC_QUIT && more_cmd != MC_REENTER_GROUP) {
  1532.         gotoxy(0, screen_offset);
  1533.         clrpage();
  1534.         if (auto_preview_mode && ah->attr == 0)
  1535.         ah->attr = A_READ;
  1536.         if (screen_offset == 0) prompt_line = -1;
  1537.     }
  1538.  
  1539.     return more_cmd;
  1540. }
  1541.  
  1542.  
  1543. void
  1544. rot13_line(cp)
  1545. register char *cp;
  1546. {
  1547.     register int c;
  1548.  
  1549.     while ((c = *cp))
  1550.     *cp++ = ROT13_DECODE(c);
  1551. }
  1552.  
  1553.