home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / nn / part08 < prev    next >
Encoding:
Internet Message Format  |  1989-06-22  |  48.8 KB

  1. Subject:  v19i069:  NN, a Usenet news reader, Part08/15
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: storm@texas.dk (Kim F. Storm)
  7. Posting-number: Volume 19, Issue 69
  8. Archive-name: nn/part08
  9.  
  10. #!/bin/sh
  11. # this is part 8 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file more.c continued
  14. #
  15. CurArch=8
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file more.c"
  26. sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' >> more.c
  27. X    match_lines = 1;
  28. X    if (linenum > match_botline) {
  29. X        match_redraw = 0;
  30. X        linenum -= 5;
  31. X        goto next_page;
  32. X    } 
  33. X    match_redraw = (stop_line < 0);
  34. X    stop_line = -1;
  35. X    lno = lno1 + linenum - topline - 1;
  36. X    print_lines = window_lines - lno + lno1;
  37. X    }
  38. X    
  39. X    /* now print the line */
  40. X
  41. X    if (match_lines && underline_line != linenum && 
  42. X    regexec(regular_expr, linebuf)) {
  43. X    match_start = regular_expr->startp[0];
  44. X    match_end = regular_expr->endp[0];
  45. X    } else {
  46. X    if (match_redraw) goto no_print;
  47. X    match_start = NULL;
  48. X    }
  49. X
  50. X    gotoxy(0, lno);
  51. X
  52. X    if (mark_overlap && underline_line == linenum)
  53. X    if (!underline(1))
  54. X        fake_underline = 1;
  55. X    skip_spaces = has_space = 0;
  56. X    
  57. X    for (lp = linebuf; c = *lp; lp++) {
  58. X
  59. X    if (match_start) {
  60. X        if (lp == match_start) highlight(1);        
  61. X        if (lp == match_end) {
  62. X        highlight(0);
  63. X        match_start = NULL;
  64. X        if (match_redraw) goto no_print;
  65. X        }
  66. X    }
  67. X
  68. X    if (c == SP) {
  69. X        if (skip_spaces) {
  70. X        if (has_space) continue;
  71. X        has_space++;
  72. X        }
  73. X        if (fake_underline) c = '_';
  74. X    } else {
  75. X        if (compress_space && c != ' ') {
  76. X        skip_spaces = 1;
  77. X        has_space = 0;
  78. X        }
  79. X        if (rot13) c = rot13tab[c];
  80. X    }
  81. X
  82. X    putchar(c);
  83. X    }
  84. X
  85. X    if (match_start) highlight(0);
  86. X    
  87. X    if (mark_overlap && underline_line == linenum) {
  88. X    while (lp - linebuf < 10) {
  89. X        putchar(fake_underline ? '_' : ' ');
  90. X        lp++;
  91. X    }
  92. X    underline(0);
  93. X    underline_line = -1;
  94. X    fake_underline = 0;
  95. X    }
  96. X
  97. Xno_print:
  98. X    
  99. X    ++lno;
  100. X    if (--print_lines > 0 && s_keyboard == 0 && form_feed == 0) goto next_line;
  101. X
  102. X    if (!eof && linenum >= maxline) {
  103. X    if (ignore_nl) {
  104. X        c = getc(art);
  105. X        if (c == EOF)
  106. X        eof++;
  107. X        else if (c != NL)
  108. X        ungetc(c, art);
  109. X        else
  110. X        ignore_nl = 0;
  111. X    }
  112. X    
  113. X    if (!eof && ftell(art) >= ah->lpos) eof++;
  114. X    }
  115. X    
  116. X    match_redraw = 0;
  117. X
  118. X Prompt:
  119. X    
  120. X    raw();
  121. X    prompt_line = lno;
  122. X
  123. X dflt_prompt:
  124. X
  125. X    prompt(pr_fmt,
  126. X       pct((long)(ah->fpos), (long)(ah->lpos), 
  127. X           (long)(linepos[topline]), (long)ftell(art)));
  128. X
  129. X    if (delayed_msg != NULL) {
  130. X    msg(delayed_msg);
  131. X    delayed_msg = NULL;
  132. X    }
  133. X    
  134. X same_prompt:
  135. X
  136. X    if ((c = get_c()) & GETC_COMMAND)
  137. X    c &= ~GETC_COMMAND;
  138. X    else
  139. X    c = more_key_map[c];
  140. X
  141. X    if (s_hangup) c = K_QUIT;
  142. X    
  143. X    if (any_message) clrmsg(0);
  144. X    
  145. X    if (c & K_MACRO) {
  146. X    m_invoke(c & ~K_MACRO);
  147. X    goto same_prompt;
  148. X    }
  149. X    
  150. X alt_key:
  151. X
  152. X    switch (c) {
  153. X     case K_UNBOUND:
  154. X    ding();
  155. X    goto same_prompt;
  156. X    
  157. X     case K_REDRAW:
  158. X#ifdef RESIZING
  159. X    if (Columns != entry_col) {
  160. X        entry_col = Columns;
  161. X        maxline = topline = 1;
  162. X    }
  163. X#endif    
  164. X     goto redraw;
  165. X    
  166. X     case K_CONTINUE:
  167. X    if (eof) break;
  168. X    if (screen_offset == 0 && form_feed == 0 && stop_line) {
  169. X        if (linenum > overlap) {
  170. X        underline_line = linenum;
  171. X        linenum -= overlap;
  172. X        }
  173. X    }
  174. X    goto next_page;
  175. X
  176. X     case K_LAST_MESSAGE:
  177. X    msg((char *)NULL);
  178. X    goto dflt_prompt;
  179. X    
  180. X     case K_HELP:
  181. X    display_help("more");
  182. X    goto redraw;
  183. X    
  184. X     case K_SHELL:
  185. X    putchar(CR);
  186. X    if (shell_escape()) goto redraw;
  187. X    goto dflt_prompt;
  188. X    
  189. X     case K_EXTENDED_CMD:
  190. X    switch (alt_command()) {
  191. X
  192. X     case AC_QUIT:
  193. X        more_return( MC_QUIT );
  194. X
  195. X     case AC_PROMPT:
  196. X     case AC_HEADER:
  197. X        goto dflt_prompt;
  198. X
  199. X     case AC_REORDER:
  200. X        more_return( MC_MENU );
  201. X        
  202. X     case AC_REDRAW:
  203. X        goto redraw;
  204. X
  205. X     case AC_KEYCMD:
  206. X        c = alt_cmd_key;
  207. X        goto alt_key;
  208. X    }
  209. X    
  210. X     case K_QUIT:
  211. X    more_return( MC_QUIT );
  212. X
  213. X     case K_SAVE_NO_HEADER:
  214. X     case K_SAVE_SHORT_HEADER:
  215. X     case K_SAVE_FULL_HEADER:
  216. X     case K_PRINT:
  217. X     case K_UNSHAR:
  218. X     case K_PATCH:
  219. X    
  220. X    putchar(CR);
  221. X    if (init_save(c, (char **)NULL) != NULL) {
  222. X        if (c == K_UNSHAR) 
  223. X        prompt_line = Lines - 2;
  224. X        
  225. X        save(ah);
  226. X        end_save();
  227. X    }
  228. X
  229. X    goto Prompt;
  230. X    
  231. X     case K_REPLY:
  232. X     case K_FOLLOW_UP:
  233. X     case K_MAIL_OR_FORWARD:
  234. X    if (answer(ah, c, -1)) clrdisp();
  235. X    goto Prompt;
  236. X
  237. X     case K_POST:
  238. X    if (post_menu()) clrdisp();
  239. X    goto Prompt;
  240. X    
  241. X     case K_CANCEL:
  242. X    if (current_group->group_flag & G_FOLDER) {
  243. X        prompt("%s this folder entry",
  244. X           (ah->flag & A_CANCEL) ? "UNcancel" : "Cancel");
  245. X        if (yes(0)) fcancel(ah);
  246. X        goto Prompt;
  247. X    }
  248. X    
  249. X    if (cancel(ah) == 0) goto Prompt;
  250. X    more_return(MC_NEXT);
  251. X
  252. X     case K_UNSUBSCRIBE:
  253. X    if (!unsubscribe(current_group)) goto Prompt;
  254. X    if (current_group->group_flag & G_SUBSCRIPTION) goto Prompt;
  255. X    more_return(MC_NEXTGROUP);
  256. X
  257. X     case K_GROUP_OVERVIEW:
  258. X    group_overview(0);
  259. X    goto redraw;
  260. X    
  261. X     case K_KILL_HANDLING:
  262. X    kill_menu(ah);
  263. X    goto Prompt;
  264. X    
  265. X     case K_READ_GROUP_UPDATE:
  266. X    if (mode & MM_PREVIEW) more_return(MC_MENU);
  267. X    prompt("Mark rest of current group as read?");
  268. X    if (yes(1) <= 0) goto Prompt;
  269. X    more_return(MC_READGROUP);
  270. X
  271. X     case K_NEXT_GROUP_NO_UPDATE:
  272. X    if (mode & MM_PREVIEW) more_return(MC_MENU);
  273. X    prompt("Skip to next group (current group is not updated) ?");
  274. X    if (yes(0) <= 0) goto Prompt;
  275. X    more_return(MC_NEXTGROUP);
  276. X
  277. X     case K_BACK_TO_MENU:
  278. X    more_return(MC_MENU);
  279. X    
  280. X     case K_PREVIOUS:
  281. X    if ((mode & MM_PREVIOUS) == 0) {
  282. X        msg("No previous article");
  283. X        goto dflt_prompt;
  284. X    }
  285. X    more_return(MC_PREV);
  286. X    
  287. X     case K_ADVANCE_GROUP:
  288. X     case K_BACK_GROUP:
  289. X     case K_GOTO_GROUP:
  290. X    switch (goto_group(c, ah)) {
  291. X     case ME_NO_REDRAW:
  292. X        goto Prompt;
  293. X
  294. X     case ME_QUIT:
  295. X        more_return( ME_QUIT );
  296. X
  297. X     default:
  298. X        goto redraw;
  299. X    }
  300. X
  301. X     case K_NEXT_LINE:
  302. X    if (eof) break;
  303. X    if (screen_offset) goto same_prompt;
  304. X    
  305. X    print_lines = 1;
  306. X    goto scroll;
  307. X    
  308. X     case K_NEXT_HALF_PAGE:
  309. X    if (eof) break;
  310. X    if (screen_offset) goto same_prompt;
  311. X
  312. X    print_lines = window_lines/2;
  313. X
  314. X     scroll:
  315. X    gotoxy(0, prompt_line);
  316. X    clrpage(prompt_line);
  317. X    no_raw();
  318. X    
  319. X    if (print_lines + lno < Lines)
  320. X        goto next_page;
  321. X        
  322. X    gotoxy(0, Lines-1);
  323. X    c = print_lines + lno - Lines + 1;
  324. X    while (--c >= 0) {
  325. X        putchar(NL);
  326. X        if (--lno1 < 0) topline++;
  327. X        prompt_line--;
  328. X    }
  329. X    if (lno1 < 0) lno1 = 0;
  330. X    if (prompt_line < 0) prompt_line = 0;
  331. X    lno = prompt_line;
  332. X    goto next_line;
  333. X    
  334. X     case K_PREV_HALF_PAGE:
  335. X    if (topline <= 1) goto Prompt;
  336. X    linenum = topline - window_lines/2;
  337. X    if (linenum < 1) linenum = 1;
  338. X    goto next_page;
  339. X    
  340. X     case K_PREV_PAGE:
  341. X    if (topline <= 1) goto Prompt;
  342. X    linenum = topline - window_lines + overlap; /* not perfect after FF */
  343. X    underline_line = topline;
  344. X    if (linenum < 1) linenum = 1;
  345. X    goto next_page;
  346. X    
  347. X     case K_GOTO_LINE:
  348. X    prompt("\1Go to line:\1 ");
  349. X    if ((fname = get_s(NONE, NONE, "$^", NO_COMPLETION)) == NULL) 
  350. X        goto Prompt;
  351. X
  352. X    if (*fname == NUL) {
  353. X        if (prev_goto < 0) goto Prompt;
  354. X        goto_line = prev_goto;
  355. X
  356. X    } else
  357. X    if (*fname == '$')
  358. X        goto_line = 30000;
  359. X    else
  360. X    if (*fname == '^')
  361. X        goto_line = 1;
  362. X    else {
  363. X        goto_line = atoi(fname);
  364. X        if (goto_line <= 0) {
  365. X        goto_line = -1;
  366. X        goto Prompt;
  367. X        }
  368. X    }
  369. X
  370. X     goto_page:
  371. X    prev_goto = topline;
  372. X    
  373. X    if (goto_line <= maxline)
  374. X        linenum = goto_line;
  375. X    
  376. X    goto next_page;    
  377. X
  378. X     case K_SELECT_SUBJECT:
  379. X    more_return(MC_ALLSUBJ);
  380. X
  381. X     case K_HEADER_PAGE:
  382. X    fseek(art, linepos[0], 0);
  383. X    goto_line = 0;
  384. X    goto goto_page;
  385. X    
  386. X     case K_FIRST_PAGE:
  387. X    goto_line = 1;
  388. X    goto goto_page;
  389. X
  390. X     case K_LAST_PAGE:
  391. X    goto_line = 30000;
  392. X    goto goto_page;
  393. X
  394. X     case K_GOTO_MATCH:
  395. X    prompt("\1/\1");
  396. X    if ((fname = get_s(NONE, NONE, "/", NO_COMPLETION)) == NULL) 
  397. X        goto Prompt;
  398. X
  399. X    if (*fname && *fname != '/') {
  400. X        if (regular_expr) free(regular_expr);
  401. X        regular_expr = regcomp(fname);
  402. X    }
  403. X
  404. X     case K_NEXT_MATCH:
  405. X    if (regular_expr == NULL) {
  406. X        msg("No previous expression");
  407. X        goto Prompt;
  408. X    }
  409. X    
  410. X    match_expr = 1;
  411. X    if (match_topline != topline) prev_goto = topline;
  412. X    match_topline = topline;
  413. X    match_botline = linenum;
  414. X    if (match_lines == 0 && topline <= 1) linenum = topline;
  415. X    match_lines = 0;
  416. X    goto next_line;        /* don't clear the screen if no match */
  417. X    
  418. X     case K_FULL_DIGEST:
  419. X    if (mode & MM_DIGEST) 
  420. X        more_return( MC_NO_REDRAW );
  421. X
  422. X    if (!in_digest) 
  423. X        goto same_prompt;
  424. X    
  425. X    /* could do something more clever here later */
  426. X    digestah = *ah;
  427. X    digestah.flag &= ~A_DIGEST;
  428. X    digestah.hpos = digestah.fpos = 0;
  429. X    fseek(art, 0L, 2);
  430. X    digestah.lpos = ftell(art);
  431. X    
  432. X    switch (more(&digestah, mode | MM_DIGEST, screen_offset)) {
  433. X        
  434. X     case MC_REDRAW:
  435. X        goto redraw;
  436. X        
  437. X     case MC_NO_REDRAW:
  438. X        goto safe_redraw;
  439. X        
  440. X     case MC_QUIT:
  441. X        more_return( MC_QUIT );
  442. X        
  443. X     default:
  444. X        goto safe_redraw;
  445. X    }
  446. X
  447. X     case K_LEAVE_ARTICLE:
  448. X    ah->flag |= A_SELECT;
  449. X    /* fall thru */
  450. X
  451. X     case K_NEXT_ARTICLE:
  452. X    if ((mode & MM_PREVIEW) == 0) break;
  453. X    more_return(MC_PREVIEW_NEXT);
  454. X
  455. X     case K_NEXT_SUBJECT:
  456. X    more_return(MC_NEXTSUBJ);
  457. X    
  458. X     case K_ROT13:
  459. X    if (norot13) {
  460. X        register i;
  461. X        for (i=0; i<=127; i++) {
  462. X        c = i;
  463. X        if (c >= 'a' && c <= 'm') c += 13;
  464. X        else if (c >= 'n' && c <= 'z') c -= 13;
  465. X        else if (c >= 'A' && c <= 'M') c += 13;
  466. X        else if (c >= 'N' && c <= 'Z') c -= 13;
  467. X        rot13tab[i] = c;
  468. X        }
  469. X        norot13 = 0;
  470. X    }
  471. X    
  472. X    rot13 = !rot13;
  473. X    goto safe_redraw;
  474. X    
  475. X     case K_COMPRESS:
  476. X    compress_space = !compress_space;
  477. X    goto safe_redraw;
  478. X    
  479. X     case K_PREVIEW:
  480. X    if (mode & MM_PREVIEW)
  481. X        more_return(MC_PREVIEW_OTHER);
  482. X
  483. X    /* fall thru to "default" */
  484. X
  485. X     default:
  486. X    msg("Command %d not supported", c);
  487. X    goto dflt_prompt;
  488. X    }
  489. X
  490. X    more_return(MC_NEXT);
  491. X
  492. X more_exit:
  493. X    in_menu_mode = o_mode;
  494. X    
  495. X    no_raw();
  496. X    fclose(art);
  497. X
  498. X    if ((mode & MM_PREVIEW) && more_cmd != MC_QUIT) {
  499. X    gotoxy(0, screen_offset);
  500. X    clrpage(screen_offset);
  501. X    if (more_cmd == MC_PREVIEW_NEXT) {
  502. X        if (screen_offset == 0) prompt_line = -1;
  503. X    } else {
  504. X        if (screen_offset == 0) return MC_REDRAW;
  505. X        if (more_cmd != MC_PREVIEW_OTHER) return MC_NO_REDRAW;
  506. X    }
  507. X    }
  508. X    
  509. X    return more_cmd;
  510. X}
  511. X
  512. NO_NEWS_IS_GOOD_NEWS
  513. echo "File more.c is complete"
  514. chmod 0644 more.c || echo "restore of more.c fails"
  515. set `wc -c more.c`;Sum=$1
  516. if test "$Sum" != "19863"
  517. then echo original size 19863, current size $Sum;fi
  518. echo "x - extracting news.c (Text)"
  519. sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > news.c &&
  520. X#include "config.h"
  521. X#include "news.h"
  522. X
  523. Xexport retry_on_error = 0;
  524. X
  525. X
  526. XFILE *open_news_article(art, modes, buffer1, buffer2)
  527. Xarticle_header         *art;
  528. Xint             modes;
  529. Xnews_header_buffer    buffer1, buffer2;
  530. X{
  531. X    char *body;
  532. X    char *digest_buffer;
  533. X    char *parse_header(), **art_hdr_field();
  534. X    struct stat statb;
  535. X    int retry;
  536. X    FILE *f;
  537. X#ifdef NNTP
  538. X    FILE *nntp_get_article();
  539. X#endif /* NNTP */
  540. X
  541. X    if (art->flag & A_FOLDER) {
  542. X    f = open_file(group_path_name, OPEN_READ);
  543. X    if (f == NULL) return NULL;
  544. X    fseek(f, art->hpos, 0);
  545. X#ifdef NNTP    
  546. X    } else
  547. X    if (use_nntp) {
  548. X    f = nntp_get_article(art->a_number);
  549. X    if (f == NULL) return NULL;
  550. X#endif /* NNTP */
  551. X    } else {
  552. X    sprintf(group_file_name, "%d", art->a_number);
  553. X
  554. X    retry = retry_on_error;
  555. X    while ((f = open_file(group_path_name, OPEN_READ)) == NULL)
  556. X        if (--retry < 0) return NULL;
  557. X
  558. X    /* necessary because empty files wreak havoc */
  559. X    if (fstat(fileno(f), &statb) < 0 ||
  560. X        statb.st_size < art->lpos || statb.st_size <= (off_t)0) {
  561. X        fclose(f);
  562. X        return NULL;
  563. X    }
  564. X    }
  565. X    
  566. X    digest_buffer = buffer1;
  567. X    
  568. X    if (modes & FILL_NEWS_HEADER) {
  569. X
  570. X    news.ng_from     = NULL;
  571. X    news.ng_reply     = NULL;
  572. X    news.ng_name     = NULL;
  573. X    news.ng_subj     = NULL;
  574. X    news.ng_groups     = NULL;
  575. X    news.ng_ref     = NULL;
  576. X
  577. X    news.ng_xlines     = NULL;
  578. X
  579. X    if (modes & GET_ALL_FIELDS) {
  580. X        news.ng_path     = NULL;
  581. X        news.ng_reply     = NULL;
  582. X        news.ng_ident     = NULL;
  583. X        news.ng_follow     = NULL;
  584. X        news.ng_keyw     = NULL;
  585. X        news.ng_dist     = NULL;
  586. X        news.ng_org     = NULL;
  587. X        news.ng_appr     = NULL;
  588. X        news.ng_date    = NULL;
  589. X    }
  590. X
  591. X    if (modes & GET_DATE_ONLY)
  592. X        news.ng_date    = NULL;
  593. X    
  594. X    body = parse_header(f, art_hdr_field, modes, buffer1);
  595. X    
  596. X    news.ng_lines = news.ng_xlines ? atoi(news.ng_xlines) : -1;
  597. X    
  598. X    if (modes & FILL_OFFSETS) {
  599. X        art->fpos = news.ng_fpos = ftell(f);
  600. X
  601. X        fseek(f, (off_t)0, 2);
  602. X        news.ng_lpos = ftell(f);
  603. X    }
  604. X
  605. X    news.ng_flag = 0;
  606. X
  607. X    if (news.ng_appr) news.ng_flag |= N_MODERATED;
  608. X    
  609. X    if (modes & DIGEST_CHECK && is_digest(body))
  610. X        news.ng_flag |= N_DIGEST;
  611. X    
  612. X    digest_buffer = buffer2;
  613. X    }
  614. X
  615. X    if (modes & FILL_DIGEST_HEADER) {
  616. X    fseek(f, art->hpos, 0);
  617. X    parse_digest_header(f, modes & GET_ALL_FIELDS, digest_buffer);
  618. X    }
  619. X
  620. X    fseek(f, (modes & SKIP_HEADER) ? art->fpos : art->hpos, 0);
  621. X    
  622. X    return f;
  623. X}
  624. X
  625. X
  626. X
  627. Xchar *parse_header(f, hdr_field, modes, hdrbuf)
  628. XFILE             *f;
  629. Xchar             **(*hdr_field)();
  630. Xint             modes;
  631. Xnews_header_buffer    hdrbuf;
  632. X{
  633. X    register char *bp, **fptr;
  634. X    int siz, all, date_only;
  635. X    off_t pos;
  636. X    
  637. X    pos = ftell(f);
  638. X
  639. X/* read first NEWS_HEADER_BUFFER bytes (should be more than enough) */
  640. X
  641. X    all     = modes & GET_ALL_FIELDS;
  642. X    date_only     = modes & GET_DATE_ONLY;
  643. X    
  644. X    siz = fread(hdrbuf, sizeof(char), NEWS_HEADER_BUFFER, f);
  645. X    
  646. X    bp = hdrbuf;
  647. X    bp[siz-1] = NUL;
  648. X    
  649. X    /* decode subarticle header */
  650. X    while (*bp) {
  651. X
  652. X    if (*bp == NL) {    /* empty line following header */
  653. X        ++bp;
  654. X        fseek(f, pos + (bp - hdrbuf), 0);
  655. X        return bp;
  656. X    }
  657. X    
  658. X    if (*bp == SP) {    /* for comp.ai.neural-nets digests */
  659. X        bp++;        /* which have <NL><space><NL> after header */
  660. X        continue;
  661. X    }
  662. X
  663. X    if (date_only && *bp != 'D')
  664. X        fptr = NULL;
  665. X    else
  666. X        if (fptr = (*hdr_field)(bp, all)) {
  667. X        while (*bp && *bp != ':' && isascii(*bp) && !isspace(*bp))
  668. X            bp++;
  669. X        bp++;
  670. X        while (*bp && isascii(*bp) && isspace(*bp)) bp++;
  671. X        *fptr = bp;
  672. X        }
  673. X    while (*bp && *bp != NL) bp++;
  674. X    if (fptr && bp == *fptr) *fptr = NULL;
  675. X    if (*bp) *bp++ = NUL;
  676. X    }
  677. X
  678. X    return bp;
  679. X}
  680. X
  681. X
  682. Xstatic char **art_hdr_field(lp, all)
  683. Xregister char *lp;
  684. Xint all;
  685. X{
  686. X    
  687. X#define check(name, lgt, field) \
  688. X    if (strncmp(name, lp, lgt) == 0) return &news.field
  689. X
  690. X    switch (*lp++) {
  691. X
  692. X     case 'A':
  693. X    if (!all) break;
  694. X    check("pproved: ",     9, ng_appr);
  695. X    break;
  696. X
  697. X     case 'D':
  698. X    check("ate: ",          5, ng_date);
  699. X    if (!all) break;
  700. X    check("istribution: ",     13, ng_dist);
  701. X    break;
  702. X
  703. X     case 'F':
  704. X    check("rom: ",         5, ng_from);
  705. X    if (!all) break;
  706. X    check("ollowup-To: ",    12, ng_follow);
  707. X    break;
  708. X
  709. X     case 'K':
  710. X    if (!all) break;
  711. X    check("eywords: ",     9, ng_keyw);
  712. X    break;
  713. X
  714. X     case 'L':
  715. X    check("ines: ",          6, ng_xlines);
  716. X    break;
  717. X
  718. X     case 'M':
  719. X    if (!all) break;
  720. X    check("essage-ID: ",    11, ng_ident);
  721. X    break;
  722. X
  723. X     case 'N':
  724. X    check("ewsgroups: ",    11, ng_groups);
  725. X    break;
  726. X
  727. X     case 'O':
  728. X    if (!all) break;
  729. X    check("rganization: ",    13, ng_org);
  730. X    check("rganisation: ",    13, ng_org);
  731. X    break;
  732. X
  733. X     case 'P':
  734. X    if (!all) break;
  735. X    check("ath: ",         5, ng_path);
  736. X    break;
  737. X
  738. X     case 'R':
  739. X    check("eply-To: ",     9, ng_reply);
  740. X    check("eferences: ",    11, ng_ref);
  741. X    break;
  742. X
  743. X     case 'S':
  744. X    check("ubject: ",     8, ng_subj);
  745. X    if (news.ng_from == NULL)
  746. X        check("ender: ",     7, ng_from);
  747. X    break;
  748. X
  749. X     case 'T':
  750. X    check("itle: ",          6, ng_subj);
  751. X    break;
  752. X    }
  753. X
  754. X    return NULL;
  755. X
  756. X#undef check
  757. X}
  758. X
  759. X
  760. Xis_header_line(line)
  761. Xchar *line;
  762. X{
  763. X    return art_hdr_field(line, 0) != (char **)NULL;
  764. X}
  765. NO_NEWS_IS_GOOD_NEWS
  766. chmod 0644 news.c || echo "restore of news.c fails"
  767. set `wc -c news.c`;Sum=$1
  768. if test "$Sum" != "4805"
  769. then echo original size 4805, current size $Sum;fi
  770. echo "x - extracting news.h (Text)"
  771. sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > news.h &&
  772. X
  773. X
  774. Xstruct news_header {
  775. X
  776. X    int    ng_flag;    /* flags:            */
  777. X#      define N_DIGEST 1    /*   article is part of a digest*/
  778. X#      define N_MODERATED 2    /*   group is moderated        */
  779. X
  780. X    off_t    ng_fpos;    /* position of article text    */
  781. X    off_t    ng_lpos;    /* last text offset
  782. X                /* header lines:        */
  783. X    char    *ng_from;    /*   from            */
  784. X    char    *ng_name;    /*   senders name        */
  785. X    char    *ng_subj;    /*   subject            */
  786. X    char    *ng_groups;    /*   newsgroups            */
  787. X    char    *ng_path;    /*   path            */
  788. X    char    *ng_reply;    /*   reply-to            */
  789. X    char    *ng_ident;    /*   message id            */
  790. X    char    *ng_follow;    /*   followup to        */
  791. X    char    *ng_ref;    /*   references            */
  792. X    char    *ng_keyw;    /*   keywords            */
  793. X    char    *ng_dist;    /*   distibution        */
  794. X    char    *ng_org;    /*   organization        */
  795. X    char    *ng_appr;    /*   approved            */
  796. X
  797. X    char    *ng_date;    /*   date            */
  798. X    
  799. X    char    *ng_xlines;    /*   lines (from header)    */
  800. X    int    ng_lines;    /*   lines (decoded)        */
  801. X} news;
  802. X
  803. X
  804. X/*
  805. X * digest article subheader
  806. X */
  807. X
  808. Xstruct digest_header {
  809. X    off_t    dg_hpos;    /* position of article header    */
  810. X    off_t    dg_fpos;    /* position of article text    */
  811. X    off_t    dg_lpos;    /* last text position        */
  812. X                /* header lines:        */
  813. X    char    *dg_date;    /*   date            */
  814. X    char    *dg_from;    /*   from            */
  815. X    char    *dg_subj;    /*   subject            */
  816. X    char    *dg_to;        /*   to                */
  817. X    
  818. X    int    dg_lines;    /*   lines (pseudo field)    */
  819. X} digest;
  820. X
  821. X
  822. X#define    NEWS_HEADER_BUFFER    2048
  823. X
  824. Xtypedef char    news_header_buffer[NEWS_HEADER_BUFFER];
  825. X
  826. X
  827. XFILE *open_news_article(/* header, modes [, buffer1 [, buffer2]] */);
  828. X
  829. X/* modes */
  830. X
  831. X#define    FILL_NEWS_HEADER    0x0001    /* parse first header -> buffer1 */
  832. X#define    FILL_DIGEST_HEADER    0x0002    /* parse second header -> buffer[12] */
  833. X
  834. X
  835. X#define    GET_ALL_FIELDS        0x0010    /* get all fields (otherwise only   */
  836. X                    /* name, subj, groups, lines        */
  837. X
  838. X#define    GET_DATE_ONLY        0x0020    /* get Date field            */
  839. X
  840. X#define    FILL_OFFSETS        0x0080    /* fill ng_[hfl]pos */
  841. X
  842. X
  843. X#define    DIGEST_CHECK        0x0100    /* set N_DIGEST if "digest" in subj */
  844. X                    /* only valid with FILL_NEWS_HEADER */
  845. X
  846. X
  847. X#define    SKIP_HEADER        0x1000    /* position after (sub) header */
  848. X
  849. X
  850. NO_NEWS_IS_GOOD_NEWS
  851. chmod 0644 news.h || echo "restore of news.h fails"
  852. set `wc -c news.h`;Sum=$1
  853. if test "$Sum" != "1990"
  854. then echo original size 1990, current size $Sum;fi
  855. echo "x - extracting nn.1 (Text)"
  856. sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > nn.1 &&
  857. X.TH NN 1 "Release 6.3"
  858. X.\" (c) Copyright 1988, Kim F. Storm, Texas Instruments A/S, Denmark
  859. X.\" 
  860. X.\" NOTICE:  Some versions of the -man package may have problems with
  861. X.\" =======  the @ characters in this manual.  Fix your man package by
  862. X.\"          substituting ALL occurrences of the @ character in
  863. X.\"          tmac.an (or perhaps tmac.an.new) by a BEL (^G) character.
  864. X.\" 
  865. X.UC 4
  866. X.SH NAME
  867. Xnn \- efficient net news interface (No News is good news)
  868. X.SH SYNOPSIS
  869. X.B nn
  870. X[ \fIoptions\fP ]  [ -g ] [ \fInewsgroup\fP  |  +\fIfolder\fP  |  \fIfile\fP ]...
  871. X.SH DESCRIPTION
  872. X\fINn\fP is yet another net news reader.  Like the other news readers,
  873. X\fInn\fP will let you read the new (unread) articles in one news group at a
  874. Xtime, but unlike other similar programs, \fInn\fP has a menu based article 
  875. Xselection prior to reading the articles in the news group.
  876. X.PP
  877. XWhen a news group is entered, \fInn\fP will locate all the presently
  878. Xunread articles in the group, and extract their sender, subject, and
  879. Xother relevant information.  This information is then rearranged,
  880. Xsorted, and marked in various ways to give it a pleasant format when
  881. Xit is presented to the user at the terminal.
  882. X.PP
  883. XThis will be done very quickly, because \fInn\fP uses its own database
  884. Xto maintain all the necessary information on a directly accessible
  885. Xform (this database is built and maintained by the
  886. X.IR nnmaster (1M)
  887. Xprogram).
  888. X.PP
  889. XWhen the article menu appears on the screen, \fInn\fP will be in
  890. Xa mode called \fBselection mode\fP, which will be described in full
  891. Xdetail later.  In this mode, the articles which seems to be
  892. Xinteresting can be selected by single keystrokes (using the keys a-z
  893. Xand 0-9).  When all the interesting articles among the ones presently
  894. Xdisplayed have been selected, the space bar is hit, which causes
  895. X\fInn\fP to enter \fBreading mode\fP.
  896. X.PP
  897. XIn the reading mode, each of the selected articles will be presented
  898. Xto the user, who simply use the space bar to go on to the next page of
  899. Xthe current article, or to the next article.  (Of course, there are
  900. Xall sorts of commands to scroll text up and down, skip to the next
  901. Xarticle, responding to an article, decrypt an article, and so on).
  902. X.PP
  903. XWhen all the selected articles in the current group have been read,
  904. Xthe last hit on the space bar will cause \fInn\fP will continue to the
  905. Xnext group with unread articles, and enter selection mode on that group.
  906. X.SH COMMAND LINE OPTIONS
  907. X\fInn\fP accepts a lot of command line options, but only a few of
  908. Xthese are used regularly.  Options can also be set permanently by
  909. Xincluding appropriate 
  910. X.I variable
  911. Xsettings in the
  912. X.I init
  913. Xfile described later, so the less used options
  914. Xare therefore presented after the description of the
  915. Xcorresponding variables in the sections on Variables and Options towards
  916. Xthe end of this manual.
  917. X.LP
  918. XThe frequently used command line options are:
  919. X.TP
  920. X\-\fBa0\fP
  921. XMark 
  922. X.I all
  923. Xunread articles as read. \fInn\fP will ask whether all groups should
  924. Xbe updated (unconditionally), or whether it should prompt for
  925. Xconfirmation for each group.  In the latter case, terminating the
  926. Xinput or breaking the program will cause \fInn\fP to ask whether the
  927. Xrest of the groups should be updated unconditionally or whether they
  928. Xshould remain unread.  (This options is a special case of the
  929. X\-\fBa\fP\fIN\fP option described later.)
  930. X.TP
  931. X\-\fBg\fP
  932. XPrompt for the name of a news group or folder to be entered (with
  933. Xcompletion).
  934. X.TP
  935. X\-\fBl\fP\fIN\fP
  936. XPrint only the first \fIN\fP lines of the first page of each article
  937. Xbefore prompting to continue.  This is useful on slow terminals and
  938. Xmodem lines to be able to see the first few lines of longer articles.
  939. X.TP
  940. X\-\fBs\fP\fIWORD\fP
  941. XCollect only articles which contain the string
  942. X.I WORD
  943. Xin their subject (case is ignored).  This is normally combined with
  944. Xthe -x and -m options to find all articles on a specific subject.
  945. X.TP
  946. X\-\fBs/\fP\fIregexp\fP
  947. XCollect only articles whose subject matches the regular expression
  948. X.IR regexp .
  949. XThis is normally combined with the -x and -m options to find all
  950. Xarticles on a specific subject.
  951. X.TP
  952. X\-\fBm\fP 
  953. XMerge all articles into one `meta group' instead of showing
  954. Xthem one group at a time.  This is normally used together with the -x
  955. Xand -s options to get all the articles on a specific subject presented
  956. Xon a single menu (when you don't care about which group they belong
  957. Xto).  When -m is used, no articles will be marked as read.
  958. X.TP
  959. X\-\fBx\fP[\fIN\fP]
  960. XPresent (or scan) all (or the last \fIN\fP) unread as well as
  961. Xread articles.  This will 
  962. X.I never
  963. Xmark unread articles as read.
  964. X.TP
  965. X\fInews.group\fP  or  \fIfile\fP  or  \fI+folder\fP 
  966. XIf none of these arguments are given, all subscribed news groups will
  967. Xbe used.  Otherwise, only the specified news groups and/or files will
  968. Xbe collected and presented.  In specifying a news groups, the
  969. Xfollowing `meta notation' can be used: If the news group ends with a
  970. X\&`.' (or `.all'), all subgroups of the news group will be collected,
  971. Xe.g.
  972. X.br
  973. X    comp.sources.
  974. X.br
  975. XIf a news group starts with a `.' (or `all.'), all the matching
  976. Xsubgroups will be collected, e.g.
  977. X.br
  978. X    \&.sources.unix
  979. X.br
  980. XThese notations cannot be mixed (yet)!
  981. X.SH COMMAND INPUT
  982. XIn general, \fInn\fP commands consist of one or two key-strokes, and \fInn\fP
  983. Xreacts instantly to the commands you give it; you don't have to enter 
  984. X.B return
  985. Xafter each command (except where explicitly stated).
  986. X.LP
  987. XSome commands have more serious effects than others, and therefore
  988. X\fInn\fP 
  989. Xrequests you to confirm the command.  You confirm by hitting the
  990. Xthe
  991. X.B y
  992. Xkey, and reject by hitting the
  993. X.B n
  994. Xkey.  Some `trivial' requests may also be confirmed simply by hitting 
  995. X.B space.
  996. XFor example, to confirm the creation of a save file, just hit 
  997. X.B space,
  998. Xbut to unsubscribe to a news group, you must enter
  999. X.B y.
  1000. X.LP
  1001. XMany commands will require that you enter a line of text, e.g. a file
  1002. Xname or a shell command.  If you enter
  1003. X.B space
  1004. Xas the first character on a line, the line will be
  1005. Xfilled with a default value (if one is defined).  For example, the
  1006. Xdefault value for a file name is the last file name you have entered,
  1007. Xand the default shell command is your previous shell command.  You can
  1008. Xedit this default value as well as a directly typed text, using the
  1009. Xfollowing editing commands.  The \fBerase\fP,
  1010. X\fBkill\fP, and \fBinterrupt\fP keys are the keys
  1011. Xdefined by the current tty settings.  On systems without job control,
  1012. Xthe
  1013. X.B suspend
  1014. Xkey will be
  1015. X.B control-Z
  1016. Xwhile it is the current suspend character on system with job control.
  1017. X.TP
  1018. X.B erase
  1019. X.br
  1020. XDelete the last character on the line.
  1021. X.TP
  1022. X\fBdelete-word\fP   (normally ^W)
  1023. X.br
  1024. XDelete the last word or component of the input.
  1025. X.TP
  1026. X.B kill
  1027. X.br
  1028. XDelete all characters on the line.
  1029. X.TP
  1030. X\fBinterrupt\fP  and  \fBcontrol-G\fP
  1031. X.br
  1032. XCancel the command which needs the input.
  1033. X.TP
  1034. X\fBsuspend\fP
  1035. XSuspend \fInn\fP if supported by the system.  Otherwise, spawn an
  1036. Xinteractive shell.
  1037. X.TP
  1038. X.B return
  1039. X.br
  1040. XTerminate the line, and continue with the command.
  1041. X.SH BASIC COMMANDS
  1042. XThe are numerous commands in \fInn\fP, and most of them can be invoked
  1043. Xby a single keystroke.  The descriptions in this manual are based on
  1044. Xthe standard bindings of the commands to the keys, but it is possible
  1045. Xto customize these using the 
  1046. X.B map
  1047. Xcommand described later.  For each of the keystroke commands described
  1048. Xin this manual, the corresponding command name will also be shown in
  1049. Xcurly braces, e.g. {\fBcommand\fP}.
  1050. X.LP
  1051. XThe following commands work in both selection
  1052. Xmode and in reading mode.  The notation ^X means `control X':
  1053. X.TP
  1054. X\&\fB?\fP    {\fBhelp\fP}
  1055. XHelp.  Gives a one page overview of the commands available in the
  1056. Xcurrent mode.
  1057. X.TP
  1058. X\&\fB^L\fP    {\fBredraw\fP}
  1059. XRedraw screen.
  1060. X.TP
  1061. X\&\fB^R\fP    {\fBredraw\fP}
  1062. XRedraw screen (Same as ^L).
  1063. X.TP
  1064. X\&\fB^P\fP    {\fBmessage\fP}
  1065. XRepeat the last message shown on the message line.
  1066. X.TP
  1067. X\&\fB!\fP    {\fBshell\fP}
  1068. XShell escape.  The user is prompted for a command which is executed
  1069. Xby your favorite shell (see the 
  1070. X.B shell
  1071. Xvariable).  Shell escapes are described in detail later on.
  1072. X.TP
  1073. X\&\fBQ\fP    {\fBquit\fP}
  1074. XQuit \fInn\fP without marking \fIcurrent\fP group as read.  If you
  1075. Xhave selected any articles in the current group, \fInn\fP will offer
  1076. Xyou to use the same selections the next time you are about to read
  1077. Xthat group.  So, when you use the
  1078. X.B Q
  1079. Xcommand, you neither lose the current group nor the selections you
  1080. Xmight have made (unless the articles are expired in the meantime of
  1081. Xcourse).  \fInn\fP will also remember which menu pages you have
  1082. Xalready seen, and attempt to start at the last displayed menu page the
  1083. Xnext time the group is entered (if you confirm to "use old selections"
  1084. Xwhen asked).
  1085. X.TP
  1086. X\&\fBV\fP    {\fBversion\fP}
  1087. XPrint release and version information.
  1088. X.TP
  1089. X\fB:\fP\fIcommand\fP  {\fBcommand\fP}
  1090. XExecute the \fIcommand\fP by name.  This form can be used to invoke
  1091. Xany of \fInn\fP's commands, also those which cannot be bound to a key
  1092. X(such as
  1093. X.BR coredump ),
  1094. Xor those which are not bound to a key by default (such as
  1095. X.B post
  1096. Xand
  1097. X.BR unshar ).
  1098. X.SH SELECTION MODE
  1099. XIn selection mode, the screen is divided into four parts: the header
  1100. Xline showing the name of the news group and the number of articles,
  1101. Xthe menu lines which show the collected articles - one article
  1102. Xper line, the prompt line where you enter commands, and the message
  1103. Xline where \fInn\fP prints various messages to you.
  1104. X.LP
  1105. XEach menu line begins with an \fIarticle id\fP which is a unique
  1106. Xletter (or digit if your screen has more than ~30 lines).  To select
  1107. Xan articles for reading, you simply enter the corresponding \fIid\fP,
  1108. Xand the menu line will high-light to indicate that the article is
  1109. Xselected.  When you have selected all the interesting articles on the
  1110. Xpresent menu, you simply hit
  1111. X.B space.
  1112. XIf there are more articles collected for the current group than could 
  1113. Xbe presented on one screenful of text, you will
  1114. Xbe presented with the next portion of articles to select from.  When
  1115. Xyou have had the opportunity to select among all the articles in the
  1116. Xgroup, hitting
  1117. X.B space
  1118. Xwill enter reading mode.
  1119. X.LP
  1120. XIf no articles have been selected in the current group, hitting
  1121. X.B space
  1122. Xwill enter selection mode on the next news group, or exit \fInn\fP
  1123. Xif the current group was the last news group with unread articles.
  1124. XIt is thus possible to go through ALL
  1125. Xunread articles (without reading any of them) just by hitting
  1126. X.B space
  1127. Xa few times.
  1128. X.LP
  1129. XThe articles will be presented on the menu using one of the following
  1130. Xlayouts:
  1131. X.sp 0.5v
  1132. X.TP
  1133. X0:
  1134. X\fIx Name.........  Subject.............. +123\fP
  1135. X.TP
  1136. X1:
  1137. X\fIx Name.........   123  Subject..............\fP
  1138. X.TP
  1139. X2:
  1140. X\fIx 123  Subject...................................\fP
  1141. X.TP
  1142. X3:
  1143. X\fIx Subject...........................................\fP
  1144. X.LP
  1145. XHere \fIx\fP is the letter or digit that must be entered to select the
  1146. Xarticle, \fIName\fP is the real name of the sender (or the mail
  1147. Xaddress if the real name cannot be found), \fISubject\fP is the
  1148. Xcontents of the "Subject:" line in the article, and \fI123\fP is the number
  1149. Xof lines in the article.  
  1150. X.LP
  1151. XLayout 0 and 1 are just two ways to present the same information,
  1152. Xwhile layout 2 and 3 are intended for groups whose articles have very
  1153. Xlong subject lines, e.g. comp.sources.
  1154. X.LP
  1155. XLayout 1 is the default layout, and an alternative menu line layout is
  1156. Xselected using the \-\fBL\fP option or by setting the
  1157. X.B layout
  1158. Xvariable.  Once \fInn\fP is
  1159. Xstarted the layout can be changed at any time using the 
  1160. X.B L
  1161. Xkey {\fBlayout\fP}.
  1162. X.LP
  1163. XThe \fIName\fP is limited to 16 characters, and to make maximum use of
  1164. Xthis space, \fInn\fP will perform a series of simplifications on the
  1165. Xname, e.g. changing first names into initials, removing domain names
  1166. Xfrom mail addresses (if the real name is not found) etc.  It does a
  1167. Xgood job, but some people on the net put weird things into the From:
  1168. Xfield (or actually into their password file) which result in \fInn\fP
  1169. Xproducing quite cryptic "names"; these people have themselves to blame
  1170. X- not me!
  1171. X.LP
  1172. XThe \fISubject\fP is limited to ~60 characters (~75 in layout 3) and
  1173. Xis thus only an approximation to the actual subject line which may be
  1174. Xmuch longer.  To get as much out of this space, \fIRe:\fP prefixes (in
  1175. Xvarious forms) are recognized and replaced by an equivalent number of
  1176. X\&`>' characters.
  1177. X.PP
  1178. XSince articles are sorted accoring to the subject, two or more
  1179. Xadjacent articles may share the same subject (ignoring any `>'s).  In
  1180. Xthis case, only the first article will show the subject of the
  1181. Xarticle; the rest will only show the `>' characters in the subject
  1182. Xfield (or a `-' if there are no `>'s at the beginning of the line).  A
  1183. Xtypical menu will thus only show each subject once, saving a lot of
  1184. Xtime in scanning the news articles.
  1185. X.SH SELECTION MODE COMMANDS
  1186. XThe primary purpose of the selection mode is of course to select the
  1187. Xarticles to be read, but a number of other commands may also be
  1188. Xperformed in this mode: saving of articles in files, replying and
  1189. Xfollowing up on articles, mailing/forwarding articles, shell escapes
  1190. Xetc.
  1191. X.PP
  1192. XThe selected articles are marked either by showing the corresponding
  1193. Xmenu line in standout mode (reverse video), or if the terminal does
  1194. Xnot have this capability by placing an asterisk (*) after the
  1195. Xselection letter or digit.
  1196. X.LP
  1197. XThe basic article selection commands are:
  1198. X.TP
  1199. X\&\fBabc...z 01..9\fP  {\fIcannot be reassigned\fP}
  1200. XSelect the article with the given identification letter or digit, or
  1201. Xif the article is already selected, deselect it.
  1202. X.TP
  1203. X\&\fBspace\fP    {\fBcontinue\fP}
  1204. XContinue to next menu page, or if on last menu page, read the selected
  1205. Xarticles.  If no articles have been selected, continue to the next news
  1206. Xgroup.  (The 
  1207. X.B newline 
  1208. Xand 
  1209. X.B return
  1210. Xkeys have the same effect in selection
  1211. Xmode, but not in reading mode).
  1212. X.TP
  1213. X\&\fB@\fP    {\fBselect-invert\fP}
  1214. X.br
  1215. XReverse selections.  All selected articles on the current page are
  1216. Xdeselected, and vice-versa.  This is the quickest way to select all
  1217. Xarticles.
  1218. X.TP
  1219. X\&\fB~\fP    {\fBunselect-all\fP}
  1220. XDeselect all articles in the group (this works across all menu pages).
  1221. X.TP
  1222. X\&\fB+\fP    {\fBselect-auto\fP}
  1223. XPerform auto-selections in the group (see the section on "auto
  1224. Xkill/select" below).
  1225. X.LP
  1226. XDuring selection, the cursor will normally be placed on the article
  1227. Xfollowing the last selected article (initially the first article).
  1228. XThe article pointed out by the cursor is called the "current article".
  1229. XThe following commands work relative to the current cursor
  1230. Xposition.  
  1231. X.TP
  1232. X\&\fB.\fP    {\fBselect\fP}
  1233. XSelect or deselect the current article and move the cursor to the next
  1234. Xarticle.
  1235. X.TP
  1236. X\&\fB,\fP    {\fBline+1\fP}
  1237. XMove the cursor to the next article.  You can use the 
  1238. X.I down arrow
  1239. Xas well.
  1240. X.TP
  1241. X\&\fB/\fP    {\fBline-1\fP}
  1242. XMove cursor to previous article.  You can use the 
  1243. X.I up arrow
  1244. Xas well.
  1245. X.TP
  1246. X\&\fB*\fP    {\fBselect-subject\fP}
  1247. XSelect (or deselect) all articles with same subject as current
  1248. Xarticle.  This will work across several menu pages if necessary.
  1249. X.TP
  1250. X\&\fB-\fP\fIx\fP    {\fBselect-range\fP}
  1251. XSelect (or deselect) all articles between current article and the
  1252. Xarticle specified by
  1253. X.IR x .
  1254. XThis is normally used to select a range of articles, e.g. from 
  1255. X.I e
  1256. Xto 
  1257. X.I k
  1258. Xby simply typing 
  1259. X.BR e-k .
  1260. X.LP
  1261. XThe following commands move between the pages belonging to the same
  1262. Xnews group when there are more articles than will fit on a single page.
  1263. X.TP
  1264. X\&\fB>\fP    {\fBpage+1\fP}
  1265. XGoto next menu page.
  1266. X.TP
  1267. X\&\fB<\fP    {\fBpage-1\fP}
  1268. XGoto previous menu page, or to last menu page if on first menu page.
  1269. X.TP
  1270. X\&\fB$\fP    {\fBpage=$\fP}
  1271. XGoto last menu page.
  1272. X.TP
  1273. X\&\fB^\fP    {\fBpage=1\fP}
  1274. XGoto first menu page.
  1275. X.LP
  1276. XThe following commands are used to enter reading mode for the selected
  1277. Xarticles, and to move between news groups (in selection mode).
  1278. X.TP
  1279. X\&\fBspace\fP    {\fBcontinue\fP}
  1280. XEnter reading mode, or goto next menu page in current group or first
  1281. Xmenu page of next group.
  1282. X.TP
  1283. X\&\fBZ\fP    {\fBread-return\fP}
  1284. XEnter reading mode
  1285. X.I immediately
  1286. Xwith the currently selected articles.  When all
  1287. Xarticles have been read, return to selection mode in the
  1288. X.I current 
  1289. Xgroup.
  1290. X.TP
  1291. X\&\fBX\fP    {\fBread-skip\fP}
  1292. XEnter reading mode
  1293. X.I immediately
  1294. Xwith the currently selected articles.  When all
  1295. Xarticles have been read, enter selection mode in the
  1296. X.I next
  1297. Xnews group.  \fBWhen no articles are selected, it goes directly to the next
  1298. Xgroup\fP.
  1299. XThis can be used to skip all the articles in a large news group
  1300. Xwithout having to go through all the menu pages.
  1301. X.LP
  1302. XWhen the selected articles (if any) in a group have been read,
  1303. X.I all
  1304. Xarticles in that group will be marked as read!
  1305. X.LP
  1306. XIt is not possible to have single articles in a group marked `unread'.
  1307. X(New articles received after \fInn\fP was invoked are not seen by
  1308. X\fInn\fP, and of course they are not marked as read).
  1309. X.LP
  1310. XThe only alternative to marking all articles as read is to mark none
  1311. Xof the current collection as read.  This is done by the following
  1312. Xcommands:
  1313. X.TP
  1314. X\&\fBN\fP    {\fBnext-group\fP}
  1315. XGoto next news group without marking the articles in the current group
  1316. Xas read.  This can be used in combination with 
  1317. X.B Z
  1318. Xto read some articles in a group, because the
  1319. X.B Z
  1320. Xcommand does not mark the articles as read. 
  1321. X.TP
  1322. X\&\fBP\fP    {\fBprevious\fP}
  1323. XGoto previous group.  This command will enter selection mode on the
  1324. Xprevious active group (two P commands in sequence will bring you to
  1325. Xthe current group).
  1326. X.SH READING MODE COMMANDS
  1327. XIn reading mode, the articles are presented one page at a time.  To
  1328. Xget the next page of an article, simply hit
  1329. X.BR space ,
  1330. Xand when you are on the last page of an article, hit
  1331. X.B space
  1332. Xto get to the next article.  When you are on the last page of the
  1333. Xlast article, hit
  1334. X.B space
  1335. Xto enter selection mode on the next group (or the current group if
  1336. Xreading mode was entered using the
  1337. X.B Z
  1338. Xcommand).
  1339. X.LP
  1340. XThe following text scrolling commands are available:
  1341. X.TP
  1342. X\&\fBspace\fP    {\fBcontinue\fP}
  1343. XScroll
  1344. X.I one\ page\ forward
  1345. Xor continue with the next article or group as described above.
  1346. X.TP
  1347. X\&\fBbackspace / delete\fP  {\fBpage-1\fP}
  1348. XGo 
  1349. X.I one\ page\ backwards
  1350. Xin article.
  1351. X.TP
  1352. X\&\fBd\fP    {\fBpage+1/2\fP}
  1353. XScroll one
  1354. X.IR half\ page\ forward .
  1355. X.TP
  1356. X\&\fBu\fP    {\fBpage-1/2\fP}
  1357. XGo one
  1358. X.IR half\ page\ backwards .
  1359. X.TP
  1360. X\&\fBreturn\fP    {\fBline+1\fP}
  1361. XScroll 
  1362. X.I one\ line\ forward
  1363. Xin the article.
  1364. X.TP
  1365. X\&\fB^\fP    {\fBpage=1\fP}
  1366. XGoto the first page (excluding the header) of the article.
  1367. X.TP
  1368. X\&\fB$\fP    {\fBpage=$\fP}
  1369. XGoto the last page of the article.
  1370. X.TP
  1371. X\&\fBg\fP\fIN\fP    {\fBline=@\fP}
  1372. XGoto line 
  1373. X.I N
  1374. Xin the article.
  1375. X.TP
  1376. X\&\fB/\fP\fIregexp\fP    {\fBfind\fP}
  1377. XSearch forward for text matching the regular expression
  1378. X.I regexp
  1379. Xin the article.  If a matching text is found, it will be high-lighted.
  1380. X.TP
  1381. X\&\fB.\fP    {\fBfind-next\fP}
  1382. XRepeat search for last regular expression.
  1383. X.TP
  1384. X\&\fBh\fP    {\fBpage=0\fP}
  1385. XShow the 
  1386. X.I header 
  1387. Xof the article, and continue from the top of the
  1388. Xarticle.
  1389. X.TP
  1390. X\&\fBH\fP    {\fBfull-digest\fP}
  1391. XIf the current article is extracted from
  1392. Xa digest, show the entire digest article including its header.
  1393. XAnother 
  1394. X.B H 
  1395. Xcommand will return to the current subarticle.
  1396. X.TP
  1397. X\&\fBD\fP    {\fBrot13\fP}
  1398. XTurn rot13 (caesar) decryption on and off for the current article, and
  1399. Xredraw current page.
  1400. X.TP
  1401. X\&\fBc\fP    {\fBcompress\fP} 
  1402. XTurn compression on and off for the current
  1403. Xarticle.  With compression turned on, multiple spaces and tabs are
  1404. Xshown as a single space.  This makes it much easier to read right
  1405. Xjustified text which separate words with several spaces.  Redraws
  1406. Xcurrent page.
  1407. X.LP
  1408. XThe following commands are used to move among the selected articles.
  1409. X.TP
  1410. X\&\fBn\fP    {\fBnext-article\fP}
  1411. XGoto next article.  This command skips the rest of the current article
  1412. Xand jumps directly to the first page of the next article (or to the
  1413. Xnext group if it is the last article).
  1414. X.TP
  1415. X\&\fBl\fP    {\fBleave-article\fP}
  1416. XLeave current article and goto next.
  1417. XThis command behaves like the \fBnext-article\fP command, but the
  1418. Xarticle will still be selected, and when all the selected articles
  1419. Xin the group have been read as usual, these `left over' articles will
  1420. Xbe presented once more.  This is useful if you see an article which
  1421. Xyou may want to respond to unless one the following articles is
  1422. Xalready saying what you intended to say.
  1423. X.TP
  1424. X\&\fBp\fP    {\fBprevious\fP}
  1425. XGoto previous article.
  1426. X.TP
  1427. X\&\fBk\fP    {\fBnext-subject\fP}
  1428. XKill subject.  Skips rest of current article, and all following
  1429. Xarticles with the same subject.
  1430. X.br
  1431. XNote: this is not a permanent kill subject command (see the \fBK\fP command).
  1432. X.TP
  1433. X\&\fB*\fP    {\fBselect-subject\fP}
  1434. XShow next article with \fIsame\fP subject (even if it is not
  1435. Xselected).  This command will
  1436. X.I select
  1437. Xall following articles with the same subject as the current article
  1438. X(similar to the `*' command in selection mode).  This can be used to
  1439. Xselect only the first article on a subject in selection mode, and then
  1440. Xselect all follow-ups in reading mode if you find the article
  1441. Xinteresting.
  1442. X.LP
  1443. XThe following commands perform an 
  1444. Ximmediate return from reading mode to selection mode in
  1445. Xthe
  1446. X.I current
  1447. Xgroup or skip to the next group.
  1448. X.TP
  1449. X\&\fB=\fP    {\fBgoto-menu\fP}
  1450. XReturn to selection mode in the current group (think of = as the
  1451. X\&"icon" of the selection menu).  The articles already
  1452. Xread will no longer be selected on the menu (excluding the current
  1453. Xarticle).
  1454. X.TP
  1455. X\&\fBN\fP    {\fBnext-group\fP}
  1456. XSkip the rest of the selected articles in the current group and go
  1457. Xdirectly to the next group.  The unread articles in the current group are
  1458. X.I not
  1459. Xmarked as read.  (You will be asked to confirm this command.)
  1460. X.TP
  1461. X\&\fBX\fP    {\fBread-skip\fP}
  1462. XMark current group as read and go directly to the next group.  (You
  1463. Xwill be asked to confirm this command.)
  1464. X.SH PREVIEWING ARTICLES IN SELECTION MODE
  1465. XIn selection mode, it is possible to read a specific article on the
  1466. Xmenu without entering reading mode for all the selected articles on
  1467. Xthe menu.  Using the commands described below will enter reading mode
  1468. Xfor one article only, and then return to the menu mode immediately
  1469. Xafter.
  1470. X.PP
  1471. XIf there are more than 5 free lines at the bottom of the menu screen,
  1472. X\fInn\fP will use that space to show the article (a minimal preview
  1473. Xwindow can be permanently allocated with the
  1474. X.B window
  1475. Xvariable).  Otherwise,
  1476. Xthe screen will be cleared to show the article.
  1477. X.PP
  1478. XAfter previewing an article, the following article will become the
  1479. Xcurrent article.
  1480. X.TP
  1481. X\&\fB%\fP\fIx\fP    {\fBpreview\fP}
  1482. XPreview article 
  1483. X.IR x .
  1484. X.TP
  1485. X\&\fB%%\fP    {\fBpreview\fP}
  1486. XPreview the current article.
  1487. X.LP
  1488. XWhen the article is being shown, the following reading mode commands
  1489. Xare very useful:
  1490. X.TP
  1491. X\&\fB=\fP    {\fBgoto-menu\fP}
  1492. XSkip the rest of the current article, and return to menu mode.
  1493. X.TP
  1494. X\&\fBn\fP    {\fBnext-article\fP}
  1495. XSkip the rest of the current article, and \fIpreview the next article\fP.
  1496. X.TP
  1497. X\&\fBl\fP    {\fBleave-article\fP}
  1498. XSelect the article on the menu, then skip the rest of the current
  1499. Xarticle, and preview the next article.
  1500. X.TP
  1501. X\&\fB%\fP\fIy\fP    {\fBpreview\fP}
  1502. XPreview article 
  1503. X.I y .
  1504. X.SH SAVING ARTICLES
  1505. X\fInn\fP allows you to save articles in a number of ways.
  1506. X.LP
  1507. XFirst, the save commands will prompt for a file name which is expanded
  1508. Xaccording to the rules described in the section on file name expansion
  1509. Xbelow.  If the 
  1510. X.B quick-save
  1511. Xvariable is set, \fInn\fP will only prompt for a save file name when
  1512. Xthe current articles are inside a folder; otherwise, the default save
  1513. Xfile defined in the init file will be used unconditionally (except if
  1514. Xan alternative save file has been specified for the group in the group
  1515. Xpresentation sequence described later on).
  1516. X.LP
  1517. XIf the file (and directories in the path) does not exist,
  1518. X\fInn\fP
  1519. Xwill ask whether the file (and the directories) should be created.
  1520. X.LP
  1521. XIf the file name ends in an asterisk, e.g.
  1522. X.br
  1523. X    part.*
  1524. X.br
  1525. X\fInn\fP will save each of the articles in uniquely named files
  1526. Xconstructed by replacing the asterisk by numbers from the sequence 1,
  1527. X2, 3, etc.  (The format of the string that replaces the * can be
  1528. Xchanged with the
  1529. X.B save-counter
  1530. Xvariable.)
  1531. X.LP
  1532. XThe saved articles will be
  1533. X.I appended
  1534. Xto the specified file(s) followed by an empty line each.
  1535. X.LP
  1536. XWhen an article has been saved in a file, a message reporting the
  1537. Xnumber of lines saved will be shown.  This can be disabled by
  1538. Xunsetting the 
  1539. X.B save-report
  1540. Xvariable.
  1541. X.LP
  1542. XThe following commands are available in both selection mode and in
  1543. Xreading mode, but their use differs between the two modes:
  1544. X.LP
  1545. XIn
  1546. X.I reading
  1547. Xmode, the commands will just save the 
  1548. X.I current
  1549. Xarticle in the specified file.
  1550. X.LP
  1551. XIn 
  1552. X.I selection
  1553. Xmode, they prompt you for the identifier of an article you want to
  1554. Xsave.  During the saving of the article the message
  1555. X.br
  1556. X    Processing article x...
  1557. X.br
  1558. Xappears, and when the article has been saved, the displayed article
  1559. Xidentifier changes from a lower case letter to an upper case letter
  1560. X(digits are changed into the `&' character).  You will then be prompted
  1561. Xfor another article to be saved.  Just hit
  1562. X.B space 
  1563. Xwhen you don't want to save more articles.
  1564. X.LP
  1565. XIf you enter an asterisk `*' when you are prompted for an article
  1566. Xidentifier, \fInn\fP will automatically save all the \fIselected\fP
  1567. Xarticles on the \fIcurrent\fP menu page (and deselect the articles).
  1568. X.LP
  1569. XLikewise, if you enter a plus `+', \fInn\fP will save all the selected
  1570. Xarticles on \fIall\fP menu pages (and deselect the articles).
  1571. X.LP
  1572. XThis is very useful in combination with the \fIsave selected articles\fP
  1573. Xfeature to save a selection of articles in separate, successively
  1574. Xnumbered files.  Do not confuse these two concepts!  The 
  1575. X.B S*
  1576. Xand
  1577. X.B S+
  1578. Xcommands can be used to save the selected articles in a single file as
  1579. Xwell as in separate files, and the \fIsave in separate files\fP
  1580. Xfeature can be used also when saving individual articles, either in
  1581. Xthe selection mode, or in the article reading mode.
  1582. X.LP
  1583. XWhen articles are saved in a file with a full or partial header, any
  1584. Xheader lines in the
  1585. X.I body
  1586. Xof the article will be escaped by a tilde (e.g. ~From: ...) to enable
  1587. X\fInn\fP to split the folder into separate articles.  Otherwise,
  1588. X\fInn\fP might be fooled into splitting a folder into too many articles.
  1589. X.LP
  1590. XArticles can be saved in a mail compatible format by setting the 
  1591. X.B mail-format
  1592. Xvariable.
  1593. X.LP
  1594. XThe save commands are:
  1595. X.TP
  1596. X\&\fBS\fP    {\fBsave-full\fP}
  1597. XSave articles including the full article header.
  1598. X.TP
  1599. X\&\fBO\fP    {\fBsave-short\fP}
  1600. XSave articles with a short header
  1601. Xcontaining only the name of the sender, the subject, and the posting
  1602. Xdate of the article.
  1603. X.TP
  1604. X\&\fBW\fP    {\fBsave-body\fP}
  1605. XWrite article
  1606. X.I without
  1607. Xa header.
  1608. X.TP
  1609. X\&\fB:print\fP    {\fBprint\fP}
  1610. XPrint article.  Instead of a file name,
  1611. Xthis command will prompt for the print command to which the current
  1612. Xarticle will be piped.  The default print command is specified at
  1613. Xcompile time, but it can be changed by setting the
  1614. X.B printer 
  1615. Xvariable.  The output will be identical to that of the 
  1616. X.B O
  1617. Xcommand.
  1618. X.TP
  1619. X\&\fB:patch\fP    {\fBpatch\fP} 
  1620. XSend articles through \fBpatch\fP(1) (or the program defined in the
  1621. X\fBpatch-cmd\fP variable).  Instead of a file name, you will be
  1622. Xprompted for the name of a directory in which you want the patch
  1623. Xcommand to be executed.  \fInn\fP will then pipe the body of the
  1624. Xarticle through the patch command. 
  1625. X  The output from the patch process will be piped through the pager
  1626. Xdefined in the \fBpager\fP variable and appear on the screen.
  1627. X.TP
  1628. X\&\fB:unshar\fP    {\fBunshar\fP}
  1629. XUnshar articles.  You will be prompted for the name of a directory in
  1630. Xwhich you want \fInn\fP to unshar the articles. \fInn\fP will then
  1631. Xpipe the proper parts of the article body into a Bourne Shell whose
  1632. Xworking directory will be set to the specified directory.
  1633. X  During the unpacking, the normal output from the unshar process will
  1634. Xappear on the screen, and the menu or article text will be redrawn when
  1635. Xthe process is finished.
  1636. X.LP
  1637. XIn reading mode, the following keys can also be used to invoke the
  1638. Xsave commands:
  1639. X.TP
  1640. X.B s
  1641. XSame as
  1642. X.BR S .
  1643. X.TP
  1644. X.B o
  1645. XSame as
  1646. X.BR O .
  1647. X.TP
  1648. X.B w
  1649. XSame as
  1650. X.BR W .
  1651. X.TP
  1652. X.B P
  1653. XSame as
  1654. X.BR :print .
  1655. X.SH FILE NAME EXPANSION
  1656. XWhen the save commands prompts for a file name, the following file
  1657. Xname expansions are performed on the file name you enter:
  1658. X.TP
  1659. X\fB+\fP\fIfolder\fP
  1660. XThe 
  1661. X.B +
  1662. Xis replaced by the contents of the 
  1663. X.B folder
  1664. Xvariable (default value "~/News/") resulting in the name of a file in the
  1665. X.I folder
  1666. X.IR directory .
  1667. XExamples:
  1668. X.br
  1669. X    +emacs, +nn, +sources/shar/nn
  1670. X.TP
  1671. X\fB+\fP
  1672. XA single plus is replaced by the expansion of the file name contained in the 
  1673. X.B default-save-file
  1674. Xvariable.
  1675. X.TP
  1676. X\fB~/\fP\fIfile\fP
  1677. XThe
  1678. X.B ~
  1679. Xis replaced by the contents of the environment variable HOME, i.e. the
  1680. Xpath name of your home directory.
  1681. XExamples:
  1682. X.br
  1683. X    ~/News/emacs, ~/News/nn, ~/src/shar/nn
  1684. X.TP
  1685. X\fB|\fP\fIcommand-line\fP
  1686. XInstead of writing to a file, the articles are piped to the given
  1687. Xshell (/bin/sh) command-line.  Each save or write command will create a
  1688. Xseparate pipe, but all articles saved or written in one command (in
  1689. Xselection mode) are given
  1690. Xas input to the same shell command.  Example:
  1691. X.br
  1692. X    | pr | lp
  1693. X.br
  1694. XThis will print the articles on the printer after they have been piped
  1695. Xthrough pr.
  1696. X    It is possible to create separate pipes for each saved article by
  1697. Xusing a double pipe symbol in the beginning of the command, e.g.
  1698. X.br
  1699. X    || cd ~/src/nn ; patch
  1700. X.br
  1701. X.LP
  1702. XThe following symbols are expanded in a file name:
  1703. X.TP
  1704. X.B $F
  1705. Xwill be expanded to the name of the current group with the periods
  1706. Xreplaced by slashes, e.g. rec/music/synth.
  1707. X.TP
  1708. X.B $G
  1709. Xwill be expanded to the name of the current group.
  1710. X.TP
  1711. X.B $L
  1712. Xwill be expanded to the \fIlast component\fP of the name of the
  1713. Xcurrent group.  You may use this to create default save file names
  1714. Xlike +src/$L in the comp.sources groups.
  1715. X.TP
  1716. X.B $N
  1717. Xwill be expanded to the (local) article number, e.g. 1099.  In
  1718. Xselection mode it is only allowed at the end of the file name!
  1719. X.LP
  1720. XUsing these symbols, a simple naming scheme for `default folder name' is
  1721. X.B +$G
  1722. Xwhich will use the group name as folder name.  Another possibility is
  1723. X.BR +$F/$N .
  1724. X.LP
  1725. XAs mentioned above, you can also instruct \fInn\fP to save a series of
  1726. Xfiles in separate, unique files.  All that is required is that the
  1727. Xfile name ends in an asterisk, e.g.
  1728. X.br
  1729. X    +src/hype/part.*
  1730. X.br
  1731. XThis will cause each of the articles to be saved in separate, unique files
  1732. Xnamed part.1, part.2, and so on, always choosing a suffix number that
  1733. Xresults in a unique file name (i.e. if part.1 did already exist, the
  1734. Xfirst article would be saved in part.2, the next in part.3, and so on).
  1735. NO_NEWS_IS_GOOD_NEWS
  1736. echo "End of part 8"
  1737. echo "File nn.1 is continued in part 9"
  1738. echo "9" > s2_seq_.tmp
  1739. exit 0
  1740. ---
  1741. Kim F. Storm        storm@texas.dk        Tel +45 429 174 00
  1742. Texas Instruments, Marielundvej 46E, DK-2730 Herlev, Denmark
  1743.       No news is good news, but nn is better!
  1744.  
  1745.