home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume30 / tin / part08 < prev    next >
Encoding:
Text File  |  1992-05-19  |  53.6 KB  |  1,764 lines

  1. Newsgroups: comp.sources.misc
  2. From: iain%anl433.uucp@germany.eu.net (Iain J. Lea)
  3. Subject:  v30i008:  tin - threaded full screen newsreader, Part08/14
  4. Message-ID: <1992May20.172708.29647@sparky.imd.sterling.com>
  5. X-Md4-Signature: 1f08daadcd5d57916c35698dbeedda70
  6. Date: Wed, 20 May 1992 17:27:08 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: iain%anl433.uucp@germany.eu.net (Iain J. Lea)
  10. Posting-number: Volume 30, Issue 8
  11. Archive-name: tin/part08
  12. Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
  13. Supersedes: tin: Volume 29, Issue 19-30
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  TODO art.c lang.c
  22. # Wrapped by kent@sparky on Tue May 19 13:38:04 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 8 (of 14)."'
  26. if test -f 'TODO' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'TODO'\"
  28. else
  29.   echo shar: Extracting \"'TODO'\" \(4958 characters\)
  30.   sed "s/^X//" >'TODO' <<'END_OF_FILE'
  31. X!!! PLEASE NOTE THAT ON CERTAIN MACHINES (ie. mostly RISC DEC,HP) TIN
  32. X!!! WILL SOMETIMES CRASH WITH SIGBUS or SIGSEGV DUE TO THE HACK THAT
  33. X!!! IS USED IN HASHING STRINGS IN hashstr.c. SORRY BUT I HAVE NO TIME
  34. X!!! RIGHT NOW TO REIMPLEMENT THIS PART OF TIN WHICH IS A CARRY OVER
  35. X!!! FROM TASS v3.2 (Any takers ?)
  36. X
  37. XFIX FEATURES V1.x
  38. X-----------------
  39. X
  40. Xo  Fix spooldirs[] so it auto-expands as needed.
  41. X
  42. Xo  Fix num of hot arts in all/only unread mode. Calculate each time 'r'
  43. X   is executed.
  44. X
  45. Xo  In inews.c also allow reply_to var to be used in From: field.
  46. X
  47. Xo  Fix -S option to create an active file when new articles are
  48. X   saved to <savedir>. Also fix -R option to read ACTIVE file created
  49. X   by -S command. Use minimax code from tony travis to help in -R cmd
  50. X   line option.
  51. X
  52. Xo  In FAQ where it states machines that tin runs on, put a note about
  53. X   people+net address that have ported to eg. Siemens MX2 but not
  54. X   supported by main release.
  55. X
  56. Xo  Fix Sender: Path: headers within NNTP inews internally to tin
  57. X   by a #define NNTP_INEWS
  58. X
  59. Xo  Fix Save in feed.c routines. 
  60. X   Also fix so SAVING routines just use save_art_to_file() and print
  61. X   *** X Articles saved *** & none of the BS done at the moment
  62. X
  63. Xo  Fix 'z' at group level so that as art is marked unread it is also 
  64. X   checked to see if it is killed / hot.
  65. X
  66. Xo  Add option to 'M' menu to allow 'C' command to return/stay at
  67. X   group level.
  68. X
  69. Xo  Fix 'c' at article level when within thread level?
  70. X
  71. Xo  Fix -n option to hash the groups read in from ~/.tin/active and
  72. X   mark active[].flag as TRUE. then find flag=FALSE and ask user if
  73. X   they want to subscribe to group. On xenix386 takes 15 seconds on
  74. X   current -n option. Also of CNEWS just do a compare of active.times
  75. X   UNDER CNEWS USE active.times FILE FROM NNTPSERVER
  76. X   UNDER NNTP USE newnews COMMAND FROM NNTPSERVER
  77. X
  78. Xo  Add 'r' command to newsgroup level.
  79. X
  80. XFIX FEATURES V2.0
  81. X-----------------
  82. X
  83. Xo  If saving in mailbox format and mailbox does not exist query the user?
  84. X
  85. Xo  In kill.c should kill_both only kill when subj & from are matched?
  86. X
  87. Xo  Add file ~/.tin/tinheaders for following headers to be stored:
  88. X     Reply-To:
  89. X     Organisation:
  90. X     Distribution:
  91. Xo  Make binary as both standalone & NNTP as default
  92. X
  93. Xo  Add Ctrl-/ Ctrl-? to search the whole of an article (Subj,From & Body)
  94. X   at Group & Page level
  95. X
  96. Xo  Add elm like mini-menu to tin for first time users.
  97. X
  98. Xo  Add option to 'M' menu to allow unlinking/not of ~/.article
  99. X   after posting an article.
  100. X
  101. Xo  Add hashing to speedup valid_art() in big groups. Make it compile
  102. X   option so tin is still usable on Minix/small memory machines.
  103. X   -DSMALL_MEMORY_MACHINE
  104. X
  105. Xo  Add auto-aliasing of peoples mail addresses to mail aliases file.
  106. X
  107. Xo  Add Xref handling of articles so that read ones are marked read in 
  108. X   other groups. Use update_group() to do it?
  109. X   Needs to handle 'c' 'C' 'k' 'K' commands. Perhaps it should be an
  110. X   option so that performance is not impaired. (JIM).
  111. X
  112. Xo  Add ^G command to skip to next Subject: in digests.
  113. X
  114. Xo  Try compiling with -D_POSIX_SOURCE
  115. X
  116. Xo  Add filename & groupname completion.
  117. X
  118. Xo  Fix uuscram code in uudecode.
  119. X
  120. Xo  Fix code to sort arts. At page level funny things happen.
  121. X
  122. XADD FEATURES
  123. X------------
  124. X
  125. Xo  Add -P <pattern> or -P <file> to search for in new news and to
  126. X   notify user by mail. Should understand 'subject=text' 'from=text'
  127. X   'body=text' and .AND. && .OR. || for filtering purposes.
  128. X
  129. Xo  Add elm style print command with %s in it for printing in 'M'.
  130. X
  131. Xo  Add 'C' command at group level to catchup present group and
  132. X   enter next group with unread news in it.
  133. X
  134. Xo  Sort .newsrc according to preference. (sort active file as it is read)
  135. X
  136. Xo  Add time period to killing articles
  137. X
  138. XOTHER STUFF
  139. X-----------
  140. Xo  Add rebindable keymaps and provide different terminal keymaps
  141. X   (ie. keymap.ansi, keymap.wy50 etc.)
  142. X
  143. Xo  Add Virtual newsgroups (combination of newsgroups ie. virtual.ibm
  144. X   consists of comp.sys.ibm.* groups).
  145. X
  146. Xo  Add threading on References like trn with mthreads database.
  147. X
  148. Xo  Add full curses support instead of using printf()'s or joetty.
  149. X
  150. Xo  Sub all not empty groups by looking at min max values in active array
  151. X   and Unsub all empty groups by looking at min max values in active 
  152. X   array. have a command to do this in a toggle effect.
  153. X
  154. Xo  Run tests of my_strncpy() and system strncpy()
  155. X
  156. Xo  Change defaults on a per group basis
  157. XGroup        Connect   Read    Thread    Save  Savedir  Maildir  Sigfile    
  158. X                       Unread  Unthread  Mail  ProcTyp  Mailbox
  159. X-----------------------------------------------------------------------------
  160. Xjunk         local     Unread  Thread    None  Default  Default  Default
  161. Xalt.sources  1.3.3.3   Read    Thread    Save  $SRC/alt Default  ~/.Sig-alt
  162. X
  163. XAdd a menu interface to define all this. Also add edit menu for entries in
  164. Xkill file.
  165. X
  166. XEach group could have a field to say which NNTP/local connection to use so
  167. Xas to be able to plug into different NNTP servers for different newsgroups
  168. END_OF_FILE
  169.   if test 4958 -ne `wc -c <'TODO'`; then
  170.     echo shar: \"'TODO'\" unpacked with wrong size!
  171.   fi
  172.   # end of 'TODO'
  173. fi
  174. if test -f 'art.c' -a "${1}" != "-c" ; then 
  175.   echo shar: Will not clobber existing file \"'art.c'\"
  176. else
  177.   echo shar: Extracting \"'art.c'\" \(22838 characters\)
  178.   sed "s/^X//" >'art.c' <<'END_OF_FILE'
  179. X/*
  180. X *  Project   : tin - a threaded Netnews reader
  181. X *  Module    : art.c
  182. X *  Author    : I.Lea & R.Skrenta
  183. X *  Created   : 01-04-91
  184. X *  Updated   : 12-05-92
  185. X *  Notes     :
  186. X *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  187. X *              You may  freely  copy or  redistribute  this software,
  188. X *              so  long as there is no profit made from its use, sale
  189. X *              trade or  reproduction.  You may not change this copy-
  190. X *              right notice, and it must be included in any copy made
  191. X */
  192. X
  193. X#include    "tin.h"
  194. X
  195. Xchar index_file[PATH_LEN];
  196. Xchar *glob_art_group;
  197. Xstatic long last_read_article;
  198. X
  199. X
  200. X/*
  201. X *  Construct the pointers to the basenotes of each thread
  202. X *  arts[] contains every article in the group.  inthread is
  203. X *  set on each article that is after the first article in the
  204. X *  thread.  Articles which have been expired have their thread
  205. X *  set to -2 (ART_EXPIRED).
  206. X */
  207. X
  208. Xvoid find_base (only_unread)
  209. X    int only_unread;
  210. X{
  211. X    register int i;
  212. X    register int j;
  213. X
  214. X    top_base = 0;
  215. X
  216. X    debug_print_arts ();
  217. X
  218. X    if (only_unread) {
  219. X        for (i = 0; i < top; i++) {
  220. X            if (IGNORE_ART(i) || arts[i].inthread != FALSE) {
  221. X                continue;
  222. X            }    
  223. X            if (top_base >= max_art) {
  224. X                expand_art ();
  225. X            }
  226. X            if (arts[i].unread == ART_UNREAD) {
  227. X                base[top_base++] = i;
  228. X            } else {
  229. X                for (j = i ; j >= 0 ; j = arts[j].thread) {
  230. X                    if (arts[j].unread) {
  231. X                        base[top_base++] = i;
  232. X                        break;
  233. X                    }
  234. X                }
  235. X            }
  236. X        }
  237. X    } else {
  238. X        for (i = 0; i < top; i++) {
  239. X            if (IGNORE_ART(i) || arts[i].inthread != FALSE) {
  240. X                continue;
  241. X            }    
  242. X            if (top_base >= max_art) {
  243. X                expand_art ();
  244. X            }
  245. X            base[top_base++] = i;
  246. X        }
  247. X    }
  248. X}
  249. X
  250. X/* 
  251. X *  Count the number of non-expired articles in arts[]
  252. X */
  253. X
  254. Xint num_of_arts ()
  255. X{
  256. X    int sum = 0;
  257. X    register int i;
  258. X
  259. X    for (i = 0; i < top; i++) {
  260. X        if (arts[i].thread != ART_EXPIRED) {
  261. X            sum++;
  262. X        }
  263. X    }
  264. X
  265. X    return sum;
  266. X}
  267. X
  268. X/*
  269. X *  Do we have an entry for article art?
  270. X */
  271. X
  272. Xint valid_artnum (art)
  273. X    long art;
  274. X{
  275. X    register int i;
  276. X
  277. X    for (i = 0; i < top; i++)
  278. X        if (arts[i].artnum == art)
  279. X            return i;
  280. X
  281. X    return -1;
  282. X}
  283. X
  284. X/*
  285. X *  Return TRUE if arts[] contains any expired articles
  286. X *  (articles we have an entry for which don't have a corresponding
  287. X *   article file in the spool directory)
  288. X */
  289. X
  290. Xint purge_needed ()
  291. X{
  292. X    register int i;
  293. X
  294. X    for (i = 0; i < top; i++)
  295. X        if (arts[i].thread == ART_EXPIRED)
  296. X            return TRUE;
  297. X
  298. X    return FALSE;
  299. X}
  300. X
  301. X/*
  302. X *  Main group indexing routine.  Group should be the name of the
  303. X *  newsgroup, i.e. "comp.unix.amiga".  group_path should be the
  304. X *  same but with the .'s turned into /'s: "comp/unix/amiga"
  305. X *
  306. X *  Will read any existing index, create or incrementally update
  307. X *  the index by looking at the articles in the spool directory,
  308. X *  and attempt to write a new index if necessary.
  309. X */
  310. X
  311. Xvoid index_group (group, group_path)
  312. X    char *group;
  313. X    char *group_path;
  314. X{
  315. X    int killed = FALSE;
  316. X    int modified = FALSE;
  317. X    glob_art_group = group;
  318. X
  319. X    set_signals_art ();
  320. X    
  321. X    if (! update) {
  322. X        sprintf (msg, txt_group, group);
  323. X        wait_message (msg);
  324. X    }
  325. X    hash_reclaim ();
  326. X    free_art_array ();
  327. X
  328. X    /*
  329. X     *  load articles from index file if it exists
  330. X     */
  331. X    read_index_file (group);
  332. X
  333. X    /*
  334. X     *  add any articles to arts[] that are new or were killed
  335. X     */
  336. X    modified = read_group (group, group_path);
  337. X
  338. X    if (modified || purge_needed ()) {
  339. X        write_index_file (group);
  340. X    }
  341. X    read_newsrc_line (group);
  342. X    killed = kill_any_articles (group); /* do after read_newsrc_line() */
  343. X    make_threads (FALSE);
  344. X    find_base (show_only_unread);
  345. X    
  346. X    if ((modified || killed) && ! update) {
  347. X        clear_message ();
  348. X    }
  349. X}
  350. X
  351. X/*
  352. X *  Index a group.  Assumes any existing index has already been
  353. X *  loaded.
  354. X */
  355. X
  356. Xint read_group (group, group_path)
  357. X    char *group;
  358. X    char *group_path;
  359. X{
  360. X    FILE *fp;
  361. X    int count = 0;
  362. X    int modified = FALSE;
  363. X    int respnum;
  364. X    long art;
  365. X    register int i;
  366. X
  367. X    setup_base (group, group_path);    /* load article numbers into base[] */
  368. X
  369. X    for (i = 0; i < top_base; i++) {    /* for each article # */
  370. X        art = base[i];
  371. X
  372. X/*
  373. X *  Do we already have this article in our index?  Change thread from
  374. X *  (ART_EXPIRED) to (ART_NORMAL) if so and skip the header eating.
  375. X */
  376. X
  377. X        if ((respnum = valid_artnum (art)) >= 0 || art <= last_read_article) {
  378. X            if (respnum >= 0) {
  379. X                arts[respnum].thread = ART_NORMAL;
  380. X                arts[respnum].unread = ART_UNREAD;
  381. X            }    
  382. X            continue;
  383. X        }
  384. X
  385. X        if (! modified) {
  386. X            modified = TRUE;   /* we've modified the index */
  387. X                               /* it will need to be re-written */
  388. X        }
  389. X
  390. X        if ((fp = open_header_fp (group_path, art)) == (FILE *) 0) {
  391. X            continue;
  392. X        }
  393. X        
  394. X        /*
  395. X         *  Add article to arts[]
  396. X         */
  397. X        if (top >= max_art)
  398. X            expand_art();
  399. X
  400. X        arts[top].artnum = art;
  401. X        arts[top].thread = ART_NORMAL;
  402. X
  403. X        set_article (&arts[top]);
  404. X
  405. X        if (! parse_headers (fp, &arts[top])) {
  406. X            debug_nntp ("read_group", "FAILED parse_header()");
  407. X            continue;
  408. X        }
  409. X
  410. X        fclose (fp);
  411. X        last_read_article = arts[top].artnum;    /* used if arts are killed */
  412. X        top++;
  413. X
  414. X        if (++count % MODULO_COUNT_NUM == 0 && ! update) {
  415. X#ifndef SLOW_SCREEN_UPDATE
  416. X            sprintf (msg, txt_indexing_num, group, count);
  417. X#else
  418. X            sprintf (msg, txt_indexing, group);
  419. X#endif
  420. X            wait_message (msg);
  421. X        }
  422. X    }
  423. X
  424. X    return modified;
  425. X}
  426. X
  427. X
  428. X/*
  429. X *  Go through the articles in arts[] and use .thread to snake threads
  430. X *  through them.  Use the subject line to construct threads.  The
  431. X *  first article in a thread should have .inthread set to FALSE, the
  432. X *  rest TRUE.  Only do unexprired articles we haven't visited yet
  433. X *  (arts[].thread == -1 ART_NORMAL).
  434. X */
  435. X
  436. Xvoid make_threads (rethread)
  437. X    int rethread;
  438. X{
  439. X    extern int cur_groupnum;
  440. X    register int i;
  441. X    register int j;
  442. X
  443. X    if (!cmd_line) {
  444. X        if (thread_arts) {
  445. X            wait_message (txt_threading_arts);
  446. X        } else {
  447. X            wait_message (txt_unthreading_arts);
  448. X        }
  449. X    }
  450. X
  451. X    /*
  452. X     *  .thread & .inthread need to be reset if re-threading arts[]
  453. X     */
  454. X    if (rethread && active[my_group[cur_groupnum]].attribute.thread) {
  455. X        for (i=0 ; i < top ; i++) {
  456. X            arts[i].thread = ART_NORMAL;
  457. X            arts[i].inthread = FALSE;
  458. X        }
  459. X    }
  460. X
  461. X    switch (sort_art_type) {
  462. X        case SORT_BY_NOTHING:        /* don't sort at all */
  463. X            qsort ((char *) arts, top, sizeof (struct article_t), artnum_comp);
  464. X            break;
  465. X        case SORT_BY_SUBJ_DESCEND:
  466. X        case SORT_BY_SUBJ_ASCEND:
  467. X            qsort ((char *) arts, top, sizeof (struct article_t), subj_comp);
  468. X            break;
  469. X        case SORT_BY_FROM_DESCEND:
  470. X        case SORT_BY_FROM_ASCEND:
  471. X            qsort ((char *) arts, top, sizeof (struct article_t), from_comp);
  472. X            break;
  473. X        case SORT_BY_DATE_DESCEND:
  474. X        case SORT_BY_DATE_ASCEND:
  475. X            qsort ((char *) arts, top, sizeof (struct article_t), date_comp);
  476. X            break;
  477. X        default:
  478. X            break;
  479. X    }
  480. X
  481. X    if (thread_arts == 0 || active[my_group[cur_groupnum]].attribute.thread == 0) {
  482. X        return;
  483. X    }
  484. X
  485. X    for (i = 0; i < top; i++) {
  486. X        if (arts[i].thread != ART_NORMAL || IGNORE_ART(i)) {
  487. X            continue;
  488. X        }    
  489. X        for (j = i+1; j < top; j++) {
  490. X            if (! IGNORE_ART(j) && 
  491. X               ((arts[i].subject == arts[j].subject) ||
  492. X               ((arts[i].part || arts[i].patch) &&
  493. X               arts[i].archive == arts[j].archive))) {
  494. X                arts[i].thread = j;
  495. X                arts[j].inthread = TRUE;
  496. X                break;
  497. X            }
  498. X        }
  499. X    }
  500. X}
  501. X
  502. X
  503. Xint parse_headers (fp, h)
  504. X    FILE *fp;
  505. X    struct article_t *h;
  506. X{
  507. X    char buf[HEADER_LEN];
  508. X    char buf2[HEADER_LEN];
  509. X    char art_from_addr[LEN];
  510. X    char art_full_name[LEN];
  511. X    char *ptr, *ptrline, *s;
  512. X    int n = 0, len = 0, lineno = 0;
  513. X    int flag;
  514. X    int got_subject = FALSE;
  515. X    int got_from = FALSE;
  516. X    int got_date = FALSE;
  517. X    int got_archive = FALSE;
  518. X    extern int errno;
  519. X    
  520. X    buf[HEADER_LEN-1] = '\0';
  521. X
  522. X    while (fread (buf, sizeof (buf)-1, 1, fp) != 1 && errno == EINTR)
  523. X        ;        /* spin on signal interrupts */
  524. X
  525. X    if ((n = strlen (buf)) == 0) {
  526. X        return FALSE;
  527. X    }
  528. X
  529. X    buf[n-1] = '\0';
  530. X
  531. X    ptr = buf;
  532. X
  533. X    while (1) {
  534. X        for (ptrline = ptr; *ptr && *ptr != '\n'; ptr++) {
  535. X            if (((*ptr) & 0xFF) < ' ') {
  536. X                *ptr = ' ';
  537. X            }
  538. X        }
  539. X        flag = *ptr;
  540. X        *ptr++ = '\0';
  541. X        lineno++;
  542. X
  543. X        if (! got_from && match_header (ptrline, "From", buf2, HEADER_LEN)) {
  544. X            parse_from (buf2, art_from_addr, art_full_name); 
  545. X            h->from = hash_str (art_from_addr);
  546. X            h->name = hash_str (art_full_name);
  547. X            got_from = TRUE;
  548. X        } else if (! got_subject && match_header (ptrline, "Subject", buf2, HEADER_LEN)) {
  549. X            s = eat_re (buf2);
  550. X            h->subject = hash_str (eat_re (s));
  551. X            got_subject = TRUE;
  552. X        } else if (! got_date && match_header (ptrline, "Date", buf2, HEADER_LEN)) {
  553. X            parse_date (buf2, h->date);
  554. X            got_date = TRUE;
  555. X        } else if (match_header (ptrline, "Archive-name", buf2, HEADER_LEN) ||
  556. X                    match_header (ptrline, "Archive-Name", buf2, HEADER_LEN)) {
  557. X            if ((s = (char *) strchr (buf2, '/')) != NULL) {
  558. X                if (strncmp (s+1, "part", 4) == 0 ||
  559. X                    strncmp (s+1, "Part", 4) == 0) {
  560. X                    h->part = str_dup (s+5);
  561. X                    len = (int) strlen (h->part);
  562. X                    if (h->part[len-1] == '\n') {
  563. X                        h->part[len-1] = '\0';
  564. X                    }
  565. X                } else {
  566. X                    if (strncmp (s+1,"patch",5) == 0 ||
  567. X                        strncmp (s+1,"Patch",5) == 0) {
  568. X                        h->patch = str_dup (s+6);
  569. X                        len = (int) strlen (h->patch);
  570. X                        if (h->patch[len-1] == '\n') {
  571. X                            h->patch[len-1] = '\0';
  572. X                        }
  573. X                    }
  574. X                }
  575. X                if (h->part || h->patch) {
  576. X                    s = buf2;
  577. X                    while (*s && *s != '/')
  578. X                        s++;
  579. X                    *s = '\0';    
  580. X                    s = buf2;
  581. X                    h->archive = hash_str (s);
  582. X                    got_archive = TRUE;
  583. X                }
  584. X            }
  585. X        }
  586. X
  587. X        if (! flag || lineno > 25 || got_archive) {
  588. X            if (got_subject && got_from && got_date) {
  589. X                debug_print_header (h);
  590. X                return TRUE;
  591. X            } else {
  592. X                return FALSE;
  593. X            }    
  594. X        }
  595. X    }
  596. X    /* NOTREACHED */
  597. X}
  598. X
  599. X/* 
  600. X *  Write out  an index file.  Write the group name first so if
  601. X *  local indexing is done so we can disambiguate between group
  602. X *  name hash collisions by looking at the index file.
  603. X */
  604. X
  605. Xvoid write_index_file (group)
  606. X    char *group;
  607. X{
  608. X    char nam[LEN];
  609. X    FILE *fp;
  610. X    int *iptr;
  611. X    int realnum;
  612. X    register int i;
  613. X
  614. X    set_tin_uid_gid();
  615. X
  616. X        sprintf (nam, "%s.%d", index_file, process_id);
  617. X    if ((fp = fopen (nam, "w")) == NULL) {
  618. X        perror_message (txt_cannot_open, nam);
  619. X        return;
  620. X    }
  621. X
  622. X    /*
  623. X     *  dump group header info.
  624. X     */
  625. X    if (sort_art_type != SORT_BY_NOTHING) {
  626. X        qsort ((char *) arts, top, sizeof (struct article_t), artnum_comp);
  627. X    }
  628. X    fprintf (fp, "%s\n", group);
  629. X    fprintf (fp, "%d\n", num_of_arts ());
  630. X    if (top <= 0) {
  631. X        fprintf (fp, "0\n");
  632. X    } else {
  633. X        if (last_read_article > arts[top-1].artnum) {
  634. X            fprintf (fp, "%ld\n", last_read_article);
  635. X        } else {
  636. X            fprintf (fp, "%ld\n", arts[top-1].artnum);
  637. X        }
  638. X    }
  639. X
  640. X    /*
  641. X     *  dump articles
  642. X     */
  643. X    realnum = 0; 
  644. X    for (i = 0; i < top; i++) {
  645. X        if (arts[i].thread == ART_EXPIRED) { 
  646. X            continue;
  647. X        }
  648. X#ifdef DEBUG            
  649. X        debug_print_header (&arts[i]);
  650. X#endif
  651. X        fprintf(fp, "%ld\n", arts[i].artnum);
  652. X
  653. X        iptr = (int *) arts[i].subject;
  654. X        iptr--;
  655. X
  656. X        if (! arts[i].subject) {
  657. X            fprintf(fp, " \n");
  658. X        } else if (*iptr < 0 || *iptr > top) {
  659. X            fprintf(fp, " %s\n", arts[i].subject);
  660. X            *iptr = realnum;
  661. X        } else if (*iptr == i) {
  662. X            fprintf(fp, " %s\n", arts[i].subject);
  663. X        } else {
  664. X            fprintf(fp, "%%%d\n", *iptr);
  665. X        }
  666. X    
  667. X        iptr = (int *) arts[i].from;
  668. X        iptr--;
  669. X
  670. X        if (! arts[i].from) {
  671. X            fprintf (fp, " \n");
  672. X        } else if (*iptr < 0 || *iptr > top) {
  673. X            fprintf (fp, " %s\n", arts[i].from);
  674. X            *iptr = realnum;
  675. X        } else if (*iptr == i) {
  676. X            fprintf(fp, " %s\n", arts[i].from);
  677. X        } else {
  678. X            fprintf(fp, "%%%d\n", *iptr);
  679. X        }
  680. X
  681. X        iptr = (int *) arts[i].name;
  682. X        iptr--;
  683. X
  684. X        if (! arts[i].name) {
  685. X            fprintf (fp, " \n");
  686. X        } else if (*iptr < 0 || *iptr > top) {
  687. X            fprintf (fp, " %s\n", arts[i].name);
  688. X            *iptr = realnum;
  689. X        } else if (*iptr == i) {
  690. X            fprintf(fp, " %s\n", arts[i].name);
  691. X        } else {
  692. X            fprintf(fp, "%%%d\n", *iptr);
  693. X        }
  694. X
  695. X        fprintf (fp, "%s\n", arts[i].date);
  696. X            
  697. X        iptr = (int *) arts[i].archive;
  698. X        iptr--;
  699. X
  700. X        if (! arts[i].archive) {
  701. X            fprintf (fp, "\n");
  702. X        } else if (*iptr < 0 || *iptr > top) {
  703. X            fprintf (fp, " %s\n", arts[i].archive);
  704. X            *iptr = realnum;
  705. X        } else if (arts[i].part || arts[i].patch) {
  706. X            if (*iptr == i) {
  707. X                fprintf(fp, " %s\n", arts[i].archive);
  708. X            } else {
  709. X                fprintf (fp, "%%%d\n", *iptr);
  710. X            }
  711. X        } else {
  712. X            fprintf (fp, "\n");
  713. X        }
  714. X            
  715. X        if (! arts[i].part) {
  716. X            fprintf (fp, " \n");
  717. X        } else {
  718. X            fprintf (fp, "%s\n", arts[i].part);
  719. X        }
  720. X
  721. X        if (! arts[i].patch) {
  722. X            fprintf (fp, " \n");
  723. X        } else {
  724. X            fprintf (fp, "%s\n", arts[i].patch);
  725. X        }
  726. X
  727. X        realnum++;
  728. X    }
  729. X    fclose (fp);
  730. X    rename_file (nam, index_file);
  731. X    chmod (index_file, 0644);
  732. X    set_real_uid_gid();
  733. X    if (debug == 2) {
  734. X        sprintf (msg, "cp %s INDEX", index_file);
  735. X        system (msg);
  736. X    }
  737. X}
  738. X
  739. X/*
  740. X *  Read in an index file.
  741. X *
  742. X *  index file header 
  743. X *    1.  newsgroup name (ie. alt.sources)
  744. X *    2.  number of articles (ie. 26)
  745. X *    3.  number of last read article (ie. 210)
  746. X *    4.  Is this a complete/killed index file (ie. COMPLETE/KILLED)
  747. X *
  748. X *  index file record
  749. X *    1.  article number    (ie. 183)               [mandatory]
  750. X *    2.  Subject: line     (ie. Which newsreader?) [mandatory]
  751. X *    3.  From: line (addr) (ie. iain@norisc)       [mandatory]
  752. X *    4.  From: line (name) (ie. Iain Lea)          [mandatory]
  753. X *    5.  Date: of posting  (ie. 911231125959)      [mandatory]
  754. X *    6.  Archive: name     (ie. compiler)          [optional]
  755. X *    7.  Part number of Archive: name  (ie. 01)    [optional]
  756. X *    8.  Patch number of Archive: name (ie. 01)    [optional]
  757. X */
  758. X
  759. Xint read_index_file (group_name)
  760. X    char *group_name;
  761. X{
  762. X    int error = 0;
  763. X    int i, n;
  764. X    char buf[LEN], *p;
  765. X    FILE *fp = NULL;
  766. X
  767. X    top = 0;
  768. X    last_read_article = 0L;
  769. X
  770. X    if ((fp = open_index_fp (group_name)) == NULL) {
  771. X        return FALSE;
  772. X    }
  773. X
  774. X    /*
  775. X     *  load header - discard group name, num. of arts in index file after any arts were killed
  776. X     */
  777. X    if (fgets(buf, sizeof buf, fp) == NULL ||
  778. X        fgets(buf, sizeof buf, fp) == NULL) {
  779. X        error = 0;            
  780. X        goto corrupt_index;    
  781. X    }
  782. X    i = atoi (buf);
  783. X
  784. X    /*
  785. X     * num. of last_read_article including any that were killed
  786. X     */
  787. X    if (fgets(buf, sizeof buf, fp) == NULL) {
  788. X        error = 1;                
  789. X        goto corrupt_index;    
  790. X    }                            
  791. X    last_read_article = (long) atol (buf);
  792. X    
  793. X    /*
  794. X     *  load articles
  795. X     */
  796. X    for (; top < i ; top++) {
  797. X        if (top >= max_art) {
  798. X            expand_art ();
  799. X        }
  800. X
  801. X        arts[top].thread = ART_EXPIRED;
  802. X        set_article (&arts[top]);
  803. X
  804. X        /*
  805. X         * Article no.
  806. X         */
  807. X        if (fgets(buf, sizeof buf, fp) == NULL) {
  808. X            error = 2;
  809. X            goto corrupt_index;
  810. X        }
  811. X        arts[top].artnum = (long) atol (buf);
  812. X
  813. X        /*
  814. X         * Subject:
  815. X         */
  816. X        if (fgets(buf, sizeof buf, fp) == NULL) {
  817. X            error = 3;
  818. X            goto corrupt_index;
  819. X        }
  820. X
  821. X        if (buf[0] == '%') {
  822. X            n = atoi (&buf[1]);
  823. X            if (n >= top || n < 0) {
  824. X                error = 4;
  825. X                goto corrupt_index;
  826. X            }
  827. X            arts[top].subject = arts[n].subject;
  828. X        } else if (buf[0] == ' ') {
  829. X            for (p = &buf[1];  *p && *p != '\n'; p++)
  830. X                continue;    
  831. X            *p = '\0';
  832. X            arts[top].subject = hash_str (&buf[1]);
  833. X        } else {
  834. X            error = 5;
  835. X            goto corrupt_index;
  836. X        }
  837. X            
  838. X        /*
  839. X         * From: (addr part)
  840. X         */
  841. X        if (fgets(buf, sizeof buf, fp) == NULL) {
  842. X            error = 6;
  843. X            goto corrupt_index;
  844. X        }
  845. X
  846. X        if (buf[0] == '%') {
  847. X            n = atoi (&buf[1]);
  848. X            if (n >= top || n < 0) {
  849. X                error = 7;
  850. X                goto corrupt_index;
  851. X            }
  852. X            arts[top].from = arts[n].from;
  853. X        } else if (buf[0] == ' ') {
  854. X            for (p = &buf[1];  *p && *p != '\n'; p++)
  855. X                continue;
  856. X            *p = '\0';
  857. X            arts[top].from = hash_str (&buf[1]);
  858. X        } else {
  859. X            error = 8;
  860. X            goto corrupt_index;
  861. X        }
  862. X
  863. X        /*
  864. X         * From: (full name)
  865. X         */
  866. X        if (fgets(buf, sizeof buf, fp) == NULL) {
  867. X            error = 9;
  868. X            goto corrupt_index;
  869. X        }
  870. X
  871. X        if (buf[0] == '%') {
  872. X            n = atoi (&buf[1]);
  873. X            if (n > top || n < 0) {
  874. X                error = 10;
  875. X                goto corrupt_index;
  876. X            }
  877. X            if (n == top) {        /* no full name so .name = .from */
  878. X                arts[top].name = arts[top].from;
  879. X            } else {
  880. X                arts[top].name = arts[n].name;
  881. X            }
  882. X        } else if (buf[0] == ' ') {
  883. X            for (p = &buf[1];  *p && *p != '\n'; p++)
  884. X                continue;
  885. X            *p = '\0';
  886. X            arts[top].name = hash_str (&buf[1]);
  887. X        } else {
  888. X            error = 11;
  889. X            goto corrupt_index;
  890. X        }
  891. X
  892. X        /*
  893. X         * Date:
  894. X         */
  895. X        if (fgets(buf, sizeof buf, fp) == NULL) {
  896. X            error = 12;
  897. X            goto corrupt_index;
  898. X        }
  899. X
  900. X        buf[strlen (buf)-1] = '\0';
  901. X        my_strncpy (arts[top].date, buf, 12);
  902. X
  903. X        /*
  904. X         * Archive-name:
  905. X         */
  906. X        if (fgets(buf, sizeof buf, fp) == NULL) {
  907. X            error = 13;
  908. X            goto corrupt_index;
  909. X        }
  910. X
  911. X        if (buf[0] == '\n') {
  912. X            arts[top].archive = (char *) 0;
  913. X        } else if (buf[0] == '%') {
  914. X            n = atoi (&buf[1]);
  915. X            if (n > top || n < 0) {
  916. X                error = 14;
  917. X                goto corrupt_index;
  918. X            }
  919. X            arts[top].archive = arts[n].archive;
  920. X        } else if (buf[0] == ' ') {
  921. X            for (p = &buf[1]; *p && *p != '\n' ; p++)
  922. X                continue;
  923. X            *p = '\0';
  924. X            arts[top].archive = hash_str (&buf[1]);
  925. X        } else {
  926. X            error = 15;
  927. X            goto corrupt_index;
  928. X        }
  929. X
  930. X        /*
  931. X         * part no.
  932. X         */
  933. X        if (fgets(buf, sizeof buf, fp) == NULL) {
  934. X            error = 16;
  935. X            goto corrupt_index;
  936. X        }
  937. X
  938. X        if (buf[0] != ' ') { 
  939. X            buf[strlen (buf)-1] = '\0';
  940. X            arts[top].part = str_dup (buf);
  941. X        }
  942. X
  943. X        /*
  944. X         * patch no.
  945. X         */
  946. X        if (fgets(buf, sizeof buf, fp) == NULL) {
  947. X            error = 17;
  948. X            goto corrupt_index;
  949. X        }
  950. X
  951. X        if (buf[0] != ' ') { 
  952. X            buf[strlen (buf)-1] = '\0';
  953. X            arts[top].patch = str_dup (buf);
  954. X        }
  955. X
  956. X        debug_print_header (&arts[top]);
  957. X    }
  958. X
  959. X    fclose(fp);
  960. X    return TRUE;
  961. X
  962. Xcorrupt_index:
  963. X    if (! update) {
  964. X        sprintf (msg, txt_corrupt_index, index_file, error, top); 
  965. X        error_message (msg, "");
  966. X    }
  967. X
  968. X    if (debug == 2) {
  969. X        sprintf (msg, "cp %s INDEX.BAD", index_file);
  970. X        system (msg);
  971. X    }
  972. X
  973. X    last_read_article = 0L;
  974. X    if (fp) {
  975. X        fclose(fp);
  976. X    }    
  977. X    set_tin_uid_gid();
  978. X    unlink (index_file);
  979. X    set_real_uid_gid();
  980. X    top = 0;
  981. X    return FALSE;
  982. X}
  983. X
  984. X
  985. X/*
  986. X *  Look in the local $HOME/RCDIR/INDEXDIR (or wherever) directory for the
  987. X *  index file for the given group.  Hashing the group name gets
  988. X *  a number.  See if that #.1 file exists; if so, read first line.
  989. X *  Group we want?  If no, try #.2.  Repeat until no such file or
  990. X *  we find an existing file that matches our group.
  991. X */
  992. X
  993. Xvoid find_index_file (group)
  994. X    char *group;
  995. X{
  996. X    char *p;
  997. X    FILE *fp;
  998. X    int i = 1;
  999. X    static char buf[LEN];
  1000. X    char dir[PATH_LEN];
  1001. X    unsigned long h;
  1002. X
  1003. X    h = hash_groupname (group);
  1004. X
  1005. X    if (read_news_via_nntp && xindex_supported) {
  1006. X        sprintf (index_file, "/tmp/xindex.%d", process_id);
  1007. X        return;
  1008. X    }
  1009. X    
  1010. X    if (local_index) {
  1011. X        my_strncpy (dir, indexdir, sizeof (dir));
  1012. X    } else {
  1013. X        sprintf (dir, "%s/%s", spooldir, INDEXDIR);
  1014. X    }
  1015. X    
  1016. X    while (TRUE) {
  1017. X        sprintf (index_file, "%s/%lu.%d", dir, h, i);
  1018. X        
  1019. X        if ((fp = fopen (index_file, "r")) == (FILE *) 0) {
  1020. X            return;
  1021. X        }
  1022. X
  1023. X        if (fgets (buf, sizeof (buf), fp) == (char *) 0) {
  1024. X            fclose (fp);
  1025. X            return;
  1026. X        }
  1027. X        fclose (fp);
  1028. X
  1029. X        for (p = buf; *p && *p != '\n'; p++) {
  1030. X            continue;
  1031. X        }    
  1032. X        *p = '\0';
  1033. X
  1034. X        if (strcmp (buf, group) == 0) {
  1035. X            return;
  1036. X        }    
  1037. X        i++;
  1038. X    }    
  1039. X}
  1040. X
  1041. X/*
  1042. X *  Run the index file updater only for the groups we've loaded.
  1043. X */
  1044. X
  1045. Xvoid do_update ()
  1046. X{
  1047. X    int i, j;
  1048. X    char group_path[PATH_LEN];
  1049. X    char *p;
  1050. X    long beg_epoch, end_epoch;
  1051. X    
  1052. X    if (verbose) {
  1053. X        time (&beg_epoch);
  1054. X    }
  1055. X
  1056. X    for (i = 0; i < group_top; i++) {
  1057. X        my_strncpy (group_path, active[my_group[i]].name, sizeof (group_path));
  1058. X        for (p = group_path ; *p ; p++) {
  1059. X            if (*p == '.') {
  1060. X                *p = '/';
  1061. X            }
  1062. X        }
  1063. X        if (verbose) {
  1064. X            printf ("%s %s\n", (catchup ? "Catchup" : "Updating"),
  1065. X                    active[my_group[i]].name);
  1066. X            fflush (stdout);
  1067. X        }
  1068. X        index_group (active[my_group[i]].name, group_path);
  1069. X        if (catchup) {
  1070. X            for (j = 0; j < top; j++) {
  1071. X                arts[j].unread = ART_READ;
  1072. X            }
  1073. X            update_newsrc (active[my_group[i]].name, my_group[i], FALSE);
  1074. X        }
  1075. X    }
  1076. X
  1077. X    if (verbose) {
  1078. X        time (&end_epoch);
  1079. X        sprintf (msg, "%s %d groups in %ld seconds\n", 
  1080. X            (catchup ? "Caughtup" : "Updated"), group_top, end_epoch - beg_epoch);
  1081. X        wait_message (msg);
  1082. X    }
  1083. X}
  1084. X
  1085. X/*
  1086. X * convert date from ctime format to sortable format
  1087. X * "24 Jul 91 12:59:59", "Mon, 24 Jul 91 12:59:59" and
  1088. X * "Mon, 24 Jul 1991 12:59:59" are parsed and produce
  1089. X * output of the form "910724125959"
  1090. X */
  1091. X
  1092. Xchar *parse_date (date, str)
  1093. X    char *date;
  1094. X    char *str;
  1095. X{
  1096. X    char buf[4];
  1097. X    int i = 0;
  1098. X
  1099. X    /* Check for extraneous day-of-week at start of date */
  1100. X    while (isalpha(date[i]) || date[i] == ',' || date[i] == ' ') {
  1101. X        i++;
  1102. X    }
  1103. X    
  1104. X    if (date[i+1] == ' ') {    /* ie. "2 Aug..." instead of "12 Aug... */
  1105. X        str[4] = '0';        /* day */
  1106. X        str[5] = date[i++];
  1107. X        i++;
  1108. X    } else {
  1109. X        str[4] = date[i++];        /* day */
  1110. X        str[5] = date[i++];
  1111. X        i++;
  1112. X    }
  1113. X    
  1114. X    buf[0] = date[i++];        /* month in Jan,Feb,.. form */
  1115. X    buf[1] = date[i++];
  1116. X    buf[2] = date[i++];
  1117. X    buf[3] = '\0';
  1118. X
  1119. X    i++;
  1120. X    
  1121. X    str[0] = date[i++];        /* year */
  1122. X    str[1] = date[i++];
  1123. X    if (isdigit(date[i])) {         /* 19xx format */
  1124. X        str[0] = date[i++];
  1125. X        str[1] = date[i++];
  1126. X    }
  1127. X    
  1128. X    i++;
  1129. X    
  1130. X    if (strcmp (buf, "Jan") == 0) {        /* convert Jan to 01 etc */
  1131. X        str[2] = '0';
  1132. X        str[3] = '1';
  1133. X    } else if (strcmp (buf, "Feb") == 0) {
  1134. X        str[2] = '0';
  1135. X        str[3] = '2';
  1136. X    } else if (strcmp (buf, "Mar") == 0) {
  1137. X        str[2] = '0';
  1138. X        str[3] = '3';
  1139. X    } else if (strcmp (buf, "Apr") == 0) {
  1140. X        str[2] = '0';
  1141. X        str[3] = '4';
  1142. X    } else if (strcmp (buf, "May") == 0) {
  1143. X        str[2] = '0';
  1144. X        str[3] = '5';
  1145. X    } else if (strcmp (buf, "Jun") == 0) {
  1146. X        str[2] = '0';
  1147. X        str[3] = '6';
  1148. X    } else if (strcmp (buf, "Jul") == 0) {
  1149. X        str[2] = '0';
  1150. X        str[3] = '7';
  1151. X    } else if (strcmp (buf, "Aug") == 0) {
  1152. X        str[2] = '0';
  1153. X        str[3] = '8';
  1154. X    } else if (strcmp (buf, "Sep") == 0) {
  1155. X        str[2] = '0';
  1156. X        str[3] = '9';
  1157. X    } else if (strcmp (buf, "Oct") == 0) {
  1158. X        str[2] = '1';
  1159. X        str[3] = '0';
  1160. X    } else if (strcmp (buf, "Nov") == 0) {
  1161. X        str[2] = '1';
  1162. X        str[3] = '1';
  1163. X    } else if (strcmp (buf, "Dec") == 0) {
  1164. X        str[2] = '1';
  1165. X        str[3] = '2';
  1166. X    } else {
  1167. X        str[2] = '0';
  1168. X        str[3] = '0';
  1169. X    }
  1170. X    
  1171. X    str[6] = date[i++];        /* hour */
  1172. X    str[7] = date[i++];
  1173. X
  1174. X    i++;
  1175. X    
  1176. X    str[8] = date[i++];        /* minutes */
  1177. X    str[9] = date[i++];
  1178. X    
  1179. X    i++;
  1180. X    
  1181. X    str[10] = date[i++];    /* seconds */
  1182. X    str[11] = date[i++];
  1183. X
  1184. X    str[12] = '\0';        /* terminate string */
  1185. X
  1186. X    return (str);
  1187. X}
  1188. X
  1189. X
  1190. Xint artnum_comp (p1, p2)
  1191. X    char *p1;
  1192. X    char *p2;
  1193. X{
  1194. X    struct article_t *s1 = (struct article_t *) p1;
  1195. X    struct article_t *s2 = (struct article_t *) p2;
  1196. X
  1197. X    /* s1->artnum less than s2->artnum */
  1198. X    if (s1->artnum < s2->artnum) {
  1199. X        return -1;
  1200. X    }
  1201. X    /* s1->artnum greater than s2->artnum */
  1202. X    if (s1->artnum > s2->artnum) {
  1203. X        return 1;
  1204. X    }
  1205. X    return 0;
  1206. X}
  1207. X
  1208. X
  1209. Xint subj_comp (p1, p2)
  1210. X    char *p1;
  1211. X    char *p2;
  1212. X{
  1213. X    struct article_t *s1 = (struct article_t *) p1;
  1214. X    struct article_t *s2 = (struct article_t *) p2;
  1215. X
  1216. X    /* return result of strcmp (reversed for descending) */
  1217. X    return (sort_art_type == SORT_BY_SUBJ_ASCEND 
  1218. X            ? my_stricmp (s1->subject, s2->subject) 
  1219. X            : my_stricmp (s2->subject, s1->subject));
  1220. X}
  1221. X
  1222. X
  1223. Xint from_comp (p1, p2)
  1224. X    char *p1;
  1225. X    char *p2;
  1226. X{
  1227. X    struct article_t *s1 = (struct article_t *) p1;
  1228. X    struct article_t *s2 = (struct article_t *) p2;
  1229. X
  1230. X    /* return result of strcmp (reversed for descending) */
  1231. X    return (sort_art_type == SORT_BY_FROM_ASCEND 
  1232. X            ? my_stricmp (s1->from, s2->from) 
  1233. X            : my_stricmp (s2->from, s1->from));
  1234. X}
  1235. X
  1236. X
  1237. Xint date_comp (p1, p2)
  1238. X    char *p1;
  1239. X    char *p2;
  1240. X{
  1241. X    struct article_t *s1 = (struct article_t *) p1;
  1242. X    struct article_t *s2 = (struct article_t *) p2;
  1243. X    /* return result of strcmp (reversed for descending) */
  1244. X    return (sort_art_type == SORT_BY_DATE_ASCEND 
  1245. X            ? strcmp (s1->date, s2->date) 
  1246. X            : strcmp (s2->date, s1->date));
  1247. X}
  1248. X
  1249. X
  1250. Xvoid set_article (art)
  1251. X    struct article_t *art;
  1252. X{    
  1253. X    art->subject = (char *) 0;
  1254. X    art->from = (char *) 0;
  1255. X    art->name = (char *) 0;
  1256. X    art->date[0] = '\0';
  1257. X    art->archive = (char *) 0;
  1258. X    art->part = (char *) 0;
  1259. X    art->patch = (char *) 0;
  1260. X    art->unread = ART_UNREAD;
  1261. X    art->inthread = FALSE;
  1262. X    art->killed = FALSE;
  1263. X    art->tagged = FALSE;
  1264. X    art->hot = FALSE;
  1265. X}
  1266. END_OF_FILE
  1267.   if test 22838 -ne `wc -c <'art.c'`; then
  1268.     echo shar: \"'art.c'\" unpacked with wrong size!
  1269.   fi
  1270.   # end of 'art.c'
  1271. fi
  1272. if test -f 'lang.c' -a "${1}" != "-c" ; then 
  1273.   echo shar: Will not clobber existing file \"'lang.c'\"
  1274. else
  1275.   echo shar: Extracting \"'lang.c'\" \(22813 characters\)
  1276.   sed "s/^X//" >'lang.c' <<'END_OF_FILE'
  1277. X/*
  1278. X *  Project   : tin - a threaded Netnews reader
  1279. X *  Module    : lang.c
  1280. X *  Author    : I.Lea
  1281. X *  Created   : 01-04-91
  1282. X *  Updated   : 12-05-92
  1283. X *  Notes     :
  1284. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  1285. X *              You may  freely  copy or  redistribute  this software,
  1286. X *              so  long as there is no profit made from its use, sale
  1287. X *              trade or  reproduction.  You may not change this copy-
  1288. X *              right notice, and it must be included in any copy made
  1289. X */
  1290. X
  1291. X/*
  1292. X * active.c
  1293. X */
  1294. Xchar txt_subscribe_to_new_group[] = "Subscribe to %s (y/n): ";
  1295. Xchar txt_delete_bogus_group[] = "Remove bogus group %s (y/n): ";
  1296. X
  1297. X/*
  1298. X *  art.c
  1299. X */
  1300. X
  1301. Xchar txt_group[] = "Group %s...";
  1302. Xchar txt_cannot_open_art[] = "can't open article %s: ";
  1303. Xchar txt_indexing[] = "Indexing %s...";
  1304. Xchar txt_indexing_num[] = "Indexing %s...%4d";
  1305. Xchar txt_corrupt_index[] = "Index file %s corrupted. error %d on article %d";
  1306. Xchar txt_checking_for_news[] = "Checking for news...";
  1307. Xchar txt_there_is_no_news[] = "There is no news\n";
  1308. Xchar txt_killing_arts[] = "Selecting articles...";
  1309. Xchar txt_unkilling_arts[] = "Unselecting articles...";
  1310. X
  1311. X/*
  1312. X *  feed.c
  1313. X */
  1314. X
  1315. Xchar txt_art_thread_regex_tag[] = " a)rticle, t)hread, h)ot, p)attern, T)agged articles, q)uit: ";
  1316. Xchar txt_post_process_type[] = "Process n)one, s)har, u)udecode, U)udecode & zoo: ";
  1317. X#ifdef NO_REGEX 
  1318. Xchar txt_feed_pattern[] = "Enter pattern [%s]> ";
  1319. X#else
  1320. Xchar txt_feed_pattern[] = "Enter regex pattern [%s]> ";
  1321. X#endif
  1322. Xchar txt_no_command[] = "No command";
  1323. Xchar txt_piping[] = "Piping...";
  1324. Xchar txt_saved[] = "-- %d Article(s) saved --";
  1325. X
  1326. X/*
  1327. X *  group.c
  1328. X */
  1329. X
  1330. Xchar txt_cannot_post[] = "*** Posting not allowed ***";
  1331. Xchar txt_tagged_art[] = "Tagged article";
  1332. Xchar txt_untagged_art[] = "Uuntagged article";
  1333. Xchar txt_inverse_on[] = "Inverse video enabled";
  1334. Xchar txt_inverse_off[] = "Inverse video disabled";
  1335. Xchar txt_subscribed_to[] = "Subscribed to %s";
  1336. Xchar txt_unsubscribed_to[] = "Unsubscribed from %s";
  1337. Xchar txt_mark_all_read[] = "Mark all articles as read? (y/n): ";
  1338. Xchar txt_mark_thread_read[] = "Mark thread as read? (y/n): ";
  1339. Xchar txt_no_more_groups[] = "No more groups";
  1340. Xchar txt_no_prev_group[] = "No previous group";
  1341. Xchar txt_no_arts[] = "*** No Articles ***";
  1342. Xchar txt_no_groups[] = "*** No Groups ***";
  1343. Xchar txt_not_active_newsfeed[] = "Command only allowed on active news";
  1344. Xchar txt_end_of_thread[] = "*** End of Thread ***";
  1345. Xchar txt_end_of_arts[] = "*** End of Articles ***";
  1346. Xchar txt_end_of_groups[] = "*** End of Groups ***";
  1347. Xchar txt_no_next_unread_art[] = "No next unread article";
  1348. Xchar txt_no_prev_unread_art[] = "No previous unread article";
  1349. Xchar txt_no_last_message[] = "No last message";
  1350. Xchar txt_bad_command[] = "Bad command.  Type 'h' for help.";
  1351. Xchar txt_you_have_mail[] = "    You have mail\n";
  1352. Xchar txt_type_h_for_help[] = "           h=help\n";
  1353. Xchar txt_read_art[] = "Read article> ";
  1354. Xchar txt_search_forwards[] = "Search forwards [%s]> ";
  1355. Xchar txt_search_backwards[] = "Search backwards [%s]> ";
  1356. Xchar txt_author_search_forwards[] = "Author search forwards [%s]> ";
  1357. Xchar txt_author_search_backwards[] = "Author search backwards [%s]> ";
  1358. Xchar txt_no_search_string[] = "No search string";
  1359. Xchar txt_no_match[] = "No match";
  1360. Xchar txt_post_subject[] = "Post subject [%s]> ";
  1361. Xchar txt_no_subject[] = "No subject";
  1362. Xchar txt_cannot_open[] = "can't open %s";
  1363. Xchar txt_posting[] = "Posting article...";
  1364. Xchar txt_art_posted[] = "-- Article posted --";
  1365. Xchar txt_art_rejected[] = "-- Article rejected (saved to %s) --";
  1366. Xchar txt_quit_edit_post[] = "q)uit, e)dit, p)ost: ";
  1367. Xchar txt_help_4[] = "4$       Goto spooldir 4 ($=goto last spooldir)\r\n";
  1368. Xchar txt_help_i_4[] = "4$       Goto article 4 ($=goto last article)\r\n";
  1369. Xchar txt_help_ctrl_k[] = "^K       Kill / Auto select (hot) current article\r\n";
  1370. Xchar txt_help_ctrl_l[] = "^L       Redraw page\r\n";
  1371. Xchar txt_help_ctrl_d[] = "^D^U     Down (^U=up) a page\r\n";
  1372. Xchar txt_help_i_cr[] = "<CR>     Read current article\r\n";
  1373. Xchar txt_help_cr[] = "<CR>     Read news from selected spooldir\r\n";
  1374. Xchar txt_help_i_tab[] = "<TAB>    Goto next unread article or group\r\n";
  1375. Xchar txt_help_d[] = "d        Toggle display of subject only & subject/author\r\n";
  1376. Xchar txt_help_l[] = "l        List articles within current thread\r\n";
  1377. Xchar txt_help_m[] = "m        Move current group within group selection list\r\n";
  1378. Xchar txt_help_M[] = "M        Menu of configurable options\r\n";
  1379. Xchar txt_help_a[] = "aA       Author forward (A=backward) search\r\n";
  1380. Xchar txt_help_sel_c[] = "cC       Mark group read (C=and goto next unread group)\r\n";
  1381. Xchar txt_help_c[] = "c        Mark all articles as read and goto group selection menu\r\n";
  1382. Xchar txt_help_g[] = "g        Choose a new group by name\r\n";
  1383. Xchar txt_help_I[] = "I        Toggle inverse video\r\n";
  1384. Xchar txt_help_K[] = "K        Mark article/thread as read & goto next unread\r\n";
  1385. Xchar txt_help_j[] = "jk       Down (k=up) a line\r\n";
  1386. Xchar txt_help_i_n[] = "np       Goto next (p=previous) group\r\n";
  1387. Xchar txt_help_i_p[] = "NP       Goto next (P=previous) unread article\r\n";
  1388. Xchar txt_help_q[] = "Q        Quit\r\n";
  1389. Xchar txt_help_r[] = "r        Toggle display to show all / only unread articles\r\n";
  1390. Xchar txt_help_s[] = "su       Subscribe (u=unsubscribe) to current group\r\n";
  1391. Xchar txt_help_S[] = "SU       Subscribe (U=unsubscribe) to groups that match pattern\r\n";
  1392. Xchar txt_help_t[] = "t        Return to group selection level\r\n";
  1393. Xchar txt_help_T[] = "T        Tag current article for crossposting/mailing/piping/printing/saving\r\n";
  1394. Xchar txt_help_u[] = "u        Toggle display of unthreaded & threaded articles\r\n";
  1395. Xchar txt_help_U[] = "U        Untag all tagged articles\r\n";
  1396. Xchar txt_help_v[] = "v        Show version information\r\n";
  1397. Xchar txt_help_w[] = "w        Post an article to current group\r\n";
  1398. Xchar txt_help_x[] = "x        Crosspost current article to another group\r\n";
  1399. Xchar txt_help_i_search[] = "/?       Subject forward (?=backward) search\r\n";
  1400. Xchar txt_help_thread[] = "<>       Goto first (>=last) article in current thread";
  1401. X#ifndef NO_SHELL_ESCAPE
  1402. Xchar txt_help_shell[] = "!        Shell escape\r\n";
  1403. X#endif
  1404. Xchar txt_help_dash[] = "-        Show last message\r\n";
  1405. X#ifdef NO_REGEX 
  1406. Xchar txt_save_pattern[] = "Enter save pattern [%s]> ";
  1407. X#else
  1408. Xchar txt_save_pattern[] = "Enter regex save pattern [%s]> ";
  1409. X#endif
  1410. Xchar txt_saved_pattern_to[] = "-- Saved pattern to %s - %s --";
  1411. Xchar txt_saved_to_mailbox[] = "-- Saved to mailbox %s --";
  1412. Xchar txt_threading_arts[] = "Threading articles...";
  1413. Xchar txt_unthreading_arts[] = "Unthreading articles...";
  1414. X
  1415. X/* 
  1416. X *  help.c:
  1417. X */
  1418. X
  1419. Xchar txt_group_select_com[] = "Group Selection Commands (page %d of %d)";
  1420. Xchar txt_spooldir_com[] = "Spooldir Selection Commands (page %d of %d)";
  1421. Xchar txt_index_page_com[] = "Index Page Commands (page %d of %d)";
  1422. Xchar txt_thread_com[] = "Thread Commands (page %d of %d)";
  1423. Xchar txt_art_pager_com[] = "Article Pager Commands (page %d of %d)";
  1424. Xchar txt_hit_space_for_more[] = "PgDn,End,<SPACE>,^D - page down. PgUp,Home,b,^U - page up. <CR>,q - quit";
  1425. Xchar txt_post_history_menu[] = "Posted articles history (page %d of %d)";
  1426. X
  1427. X/* 
  1428. X *  kill.c:
  1429. X */
  1430. X
  1431. Xchar txt_corrupt_kill_file[] = "Corrupt kill file %s";
  1432. Xchar txt_kill_menu[] = "Kill Article Menu";
  1433. Xchar txt_kill_how[] = "Kill type : ";
  1434. Xchar txt_kill_subject[] = "Kill Subject [%-*.*s] (y/n): ";
  1435. Xchar txt_kill_from[] =    "Kill From    [%-*.*s] (y/n): ";
  1436. Xchar txt_kill_text[] = "Kill text pattern : ";
  1437. Xchar txt_kill_text_type[] = "Apply pattern to  : ";
  1438. Xchar txt_kill_group[] =     "Kill pattern scope: ";
  1439. Xchar txt_help_kill_how[] = "Choose kill or auto select. <SPACE> toggles & <CR> sets.";
  1440. Xchar txt_help_kill_subject[] = "Subject: line to add to kill file. <SPACE> toggles & <CR> sets.";
  1441. Xchar txt_help_kill_from[] = "From: line to add to kill file. <SPACE> toggles & <CR> sets.";
  1442. Xchar txt_help_kill_text[] = "Enter text pattern to kill if Subject: & From: lines are not what you want.";
  1443. Xchar txt_help_kill_text_type[] = "Select where text pattern should be applied. <SPACE> toggles & <CR> sets.";
  1444. Xchar txt_help_kill_group[] = "Kill/auto-select only current group or all groups. <SPACE> toggles & <CR> sets.";
  1445. Xchar txt_quit_edit_save_killfile[] = "q)uit e)dit s)ave kill/hot description: ";
  1446. X
  1447. X
  1448. X/* 
  1449. X *  main.c:
  1450. X */
  1451. X
  1452. Xchar txt_option_not_enabled[] = "Option not enabled. Recompile with %s.";
  1453. Xchar txt_not_in_active_file[] = "Group %s not found in active file";
  1454. Xchar txt_screen_init_failed[] = "%s: Screen initialization failed";
  1455. Xchar txt_bad_active_file[] = "Active file corrupt - %s";
  1456. X
  1457. X/*
  1458. X *  misc.c
  1459. X */
  1460. X
  1461. Xchar txt_cannot_open_active_file[] = "Cannot open %s. Try %s -r to read news via NNTP.\n";
  1462. Xchar txt_reading_active_file[] = "Reading active file...";
  1463. Xchar txt_active_file_is_empty[] = "%s contains no newsgroups. Exiting.";
  1464. Xchar txt_checking_active_file[] = "Checking for new newsgroups...";
  1465. Xchar txt_checking[] = "Checking...";
  1466. Xchar txt_cannot_find_base_art[] = "Cannot find base article %s";
  1467. Xchar txt_out_of_memory[] = "%s: out of memory";
  1468. Xchar txt_rename_error[] = "Error: rename %s to %s";
  1469. Xchar txt_shell_escape[] = "Enter shell command [%s]> ";
  1470. X
  1471. X/*
  1472. X *  newsrc.c
  1473. X */
  1474. X
  1475. Xchar txt_creating_newsrc[] = "Creating .newsrc...\n";
  1476. Xchar txt_deleting_from_newsrc[] = "Group %s not in active file. Deleting.";
  1477. X
  1478. X/*
  1479. X *  open.c
  1480. X */
  1481. Xchar txt_connecting[] = "Connecting to %s...";
  1482. Xchar txt_cannot_get_nntp_server_name[] = "Cannot find NNTP server name";
  1483. Xchar txt_server_name_in_file_env_var[] = "Put the server name in the file %s,\nor set the environment variable NNTPSERVER";
  1484. Xchar txt_failed_to_connect_to_server[] = "Failed to connect to (%s) server";
  1485. Xchar txt_rejected_by_nntpserver[] = "Rejected by server, nntp error %d";
  1486. Xchar txt_connection_to_server_broken[] = "Connection to server broken";
  1487. Xchar txt_stuff_nntp_cannot_open[] = "stuff_nntp: can't open %s: ";
  1488. Xchar txt_nntp_to_fp_cannot_reopen[] = "nntp_to_fp: can't reopen %s: ";
  1489. Xchar txt_nntp_to_fd_cannot_reopen[] = "nntp_to_fd: can't reopen %s: ";
  1490. X
  1491. X/*
  1492. X *  page.c
  1493. X */
  1494. X
  1495. Xchar txt_quit[] = "Do you really want to quit? (y/n): ";
  1496. Xchar txt_art_unavailable[] = "Article %ld unavailable";
  1497. Xchar txt_art_marked_as_unread[] = "Article marked as unread";
  1498. Xchar txt_thread_marked_as_unread[] = "Thread marked as unread";
  1499. Xchar txt_begin_of_art[] = "*** Beginning of article ***";
  1500. Xchar txt_next_resp[] = "-- Next response --";
  1501. Xchar txt_last_resp[] = "-- Last response --";
  1502. Xchar txt_more[] = "--More--";
  1503. Xchar txt_more_percent[] = "--More--(%d%%) [%ld/%ld]";
  1504. Xchar txt_thread_x_of_n[] = "%sThread %4d of %4d\r\n";
  1505. Xchar txt_art[] = "Article %ld  ";
  1506. Xchar txt_resp_x_of_n[] = "Respno %3d of %3d\r\n";
  1507. Xchar txt_no_resp[] = "No responses\r\n";
  1508. Xchar txt_1_resp[] = "1 Response\r\n";
  1509. Xchar txt_x_resp[] = "%d Responses\r\n";
  1510. Xchar txt_s_at_s[] = "%s at %s";
  1511. Xchar txt_thread_resp_page[] = "Thread %d of %d, Resp %d (page %d):  %s";
  1512. Xchar txt_thread_page[] = "Thread %d of %d (page %d):  %s";
  1513. Xchar txt_read_resp[] = "Read response> ";
  1514. Xchar txt_help_p_0[] = "0        Read the base article in current thread\r\n";
  1515. Xchar txt_help_p_4[] = "4        Read response 4 in current thread\r\n";
  1516. Xchar txt_help_p_cr[] = "<CR>     Goto to next thread\r\n";
  1517. Xchar txt_help_p_tab[] = "<TAB>    Goto next unread article\r\n";
  1518. Xchar txt_help_b[] = "b<SPACE> Back (<SPACE>=forward) a page\r\n";
  1519. Xchar txt_help_bug[] = "B        Mail bug/comment to %s\r\n";
  1520. Xchar txt_help_p_f[] = "fF       Post (F=copy text) a followup\r\n";
  1521. Xchar txt_help_C[] = "C        Cancel current article that must have been posted by you\r\n";
  1522. Xchar txt_help_ctrl_h[] = "^H       Show articles header\r\n";
  1523. Xchar txt_help_h[] = "h        Command help\r\n";
  1524. Xchar txt_help_i[] = "q        Return to previous level\r\n";
  1525. Xchar txt_help_ck[] = "ck       Mark thread as read & return to previous level\r\n";
  1526. Xchar txt_help_p_k[] = "kK       Mark article (K=thread) as read & advance to next unread\r\n";
  1527. Xchar txt_help_p_m[] = "m        Mail article/thread/hot/pattern/tagged articles to someone\r\n";
  1528. Xchar txt_help_p_n[] = "nN       Goto to the next (N=unread) article\r\n";
  1529. Xchar txt_help_o[] = "o        Output article/thread/hot/pattern/tagged articles to printer\r\n";
  1530. Xchar txt_help_p_p[] = "pP       Goto the previous (P=unread) article\r\n";
  1531. Xchar txt_help_p_r[] = "rR       Reply through mail (R=copy text) to author\r\n";
  1532. Xchar txt_help_p_s[] = "s        Save article/thread/hot/pattern/tagged articles to file\r\n";
  1533. Xchar txt_help_p_z[] = "zZ       Mark article (Z=thread) as unread\r\n";
  1534. Xchar txt_help_p_ctrl_r[] = "^R$      Redisplay first ($=last) page of article\r\n";
  1535. Xchar txt_help_p_g[] = "gG       Goto first (G=last) page of article\r\n";
  1536. Xchar txt_help_p_d[] = "d        Toggle rot-13 decoding for current article\r\n";
  1537. Xchar txt_help_pipe[] = "|        Pipe article/thread/hot/pattern/tagged articles into command\r\n";
  1538. Xchar txt_help_p_search[] = "/        Article forward search\r\n";
  1539. Xchar txt_mail_art_to[] = "Mail article to [%.*s]> ";
  1540. Xchar txt_no_mail_address[] = "No mail address";
  1541. Xchar txt_quit_edit_send[] = "q)uit, e)dit, s)end";
  1542. Xchar txt_quit_edit_cancel[] = "q)uit, e)dit, c)ancel";
  1543. Xchar txt_mailing_to[] = "Mailing to %s...";
  1544. Xchar txt_mailed[] = "-- %d Article(s) mailed --";
  1545. Xchar txt_command_failed_s[] = "Command failed: %s\n";
  1546. Xchar txt_in_art_you_write[] = "In article %s you write:\n";
  1547. Xchar txt_resp_to_poster[] = "Responses have been directed to the poster. Post anyway? (y/n): ";
  1548. Xchar txt_resp_redirect[] = "Responses have been directed to the following newsgroups";
  1549. Xchar txt_continue[] = "Continue? (y/n): ";
  1550. Xchar txt_writes[] = "%s writes:\n";
  1551. Xchar txt_writes_name[] = "%s (%s) writes:\n";
  1552. Xchar txt_save_filename[] = "Save filename [%s]> ";
  1553. Xchar txt_art_not_saved[] = "-- Article not saved --";
  1554. Xchar txt_no_filename[] = "No filename";
  1555. Xchar txt_saving[] = "Saving...";
  1556. Xchar txt_art_saved_to[] = "-- Article saved to %s --";
  1557. Xchar txt_thread_not_saved[] = "-- Thread not saved --";
  1558. Xchar txt_thread_saved_to_many[] = "-- Thread saved to %s - %s --";
  1559. Xchar txt_thread_saved_to[] = "-- Thread saved to %s --";
  1560. Xchar txt_pipe_to_command[] = "Pipe to command [%.*s]> ";
  1561. Xchar txt_printing[] = "Printing...";
  1562. Xchar txt_printed[] = "-- %d Article(s) printed --";
  1563. Xchar txt_append_to_file[] = "File %s exists. Append? (y/n): ";
  1564. Xchar txt_toggled_rot13[] = "Toggled rot13 encoding";
  1565. X
  1566. X/*
  1567. X *  post.c
  1568. X */
  1569. X
  1570. Xchar txt_no_arts_posted[] = "No articles have been posted";
  1571. Xchar txt_post_an_article[] = "Post an article...";
  1572. Xchar txt_post_a_followup[] = "Post a followup...";
  1573. Xchar txt_mail_bug_report[] = "Mail bug report...";
  1574. Xchar txt_crosspost_group[] = "Crosspost article to group(s) [%s]> ";
  1575. Xchar txt_no_group[] = "No group";
  1576. Xchar txt_crosspost_an_article[] = "Crossposting article...";
  1577. Xchar txt_mail_bug_report_confirm[] = "Mail bug report to %s? (y/n): ";
  1578. Xchar txt_reply_to_author[] = "Reply to author...";
  1579. Xchar txt_no_blank_line[] = "No blank line found after header information. q)uit, e)dit: ";
  1580. Xchar txt_cancelling[] = "Cancelling article...";
  1581. Xchar txt_art_cancelled[] = "Article cancelled";
  1582. Xchar txt_art_cannot_cancel[] = "Article cannot be cancelled";
  1583. Xchar txt_quit_edit_xpost[] = "q)uit, e)dit, p)ost [%.*s]: %c";
  1584. X
  1585. X/*
  1586. X *  prompt.c
  1587. X */
  1588. X
  1589. Xchar txt_hit_any_key[] = "-- Press any key to continue --";
  1590. X
  1591. X/*
  1592. X *  rcfile.c
  1593. X */
  1594. Xchar txt_opt_autosave[] = "1. Auto save       : ";
  1595. Xchar txt_opt_start_editor_offset[] = "2. Editor Offset   : ";
  1596. Xchar txt_opt_mark_saved_read[] = "3. Mark saved read : ";
  1597. Xchar txt_opt_confirm_action[] =  "4. Confirm command : ";
  1598. Xchar txt_opt_draw_arrow[] = "5. Draw arrow      : ";
  1599. Xchar txt_opt_print_header[] = "6. Print header    : ";
  1600. Xchar txt_opt_pos_first_unread[] = "7. Goto 1st unread : ";
  1601. Xchar txt_opt_page_scroll[] = "8. Scroll full page: ";
  1602. Xchar txt_opt_catchup_groups[] = "9. Catchup on quit : ";
  1603. Xchar txt_opt_thread_arts[] =   "10 Thread articles : ";
  1604. Xchar txt_opt_show_only_unread[] = "11 Show only unread: ";
  1605. Xchar txt_opt_show_author[] = "13 Show author     : ";
  1606. Xchar txt_opt_process_type[] = "14 Process type    : ";
  1607. Xchar txt_opt_sort_type[] = "15 Sort article by : ";
  1608. Xchar txt_opt_savedir[] = "16 Save directory  : ";
  1609. Xchar txt_opt_maildir[] = "17 Mail directory  : ";
  1610. Xchar txt_opt_printer[] = "18 Printer         : ";
  1611. Xchar txt_options_menu[] = "Options Menu";
  1612. Xchar txt_show_from_none[] = "None";
  1613. Xchar txt_show_from_addr[] = "Addr";
  1614. Xchar txt_show_from_name[] = "Name";
  1615. Xchar txt_show_from_both[] = "Both";
  1616. Xchar txt_post_process_none[] = "None";
  1617. Xchar txt_post_process_sh[] = "Shell archive";
  1618. Xchar txt_post_process_uudecode[] = "Uudecode";
  1619. Xchar txt_post_process_uud_lst_zoo[] = "Uudecode & list zoo archive";
  1620. Xchar txt_post_process_uud_ext_zoo[] = "Uudecode & extract zoo archive";
  1621. Xchar txt_sort_by_nothing[] = "Nothing";
  1622. Xchar txt_sort_by_subj_descend[] = "Subject: field (descending)";
  1623. Xchar txt_sort_by_subj_ascend[] = "Subject: field (ascending)";
  1624. Xchar txt_sort_by_from_descend[] = "From: field (descending)";
  1625. Xchar txt_sort_by_from_ascend[] = "From: field (ascending)";
  1626. Xchar txt_sort_by_date_descend[] = "Date: field (descending)";
  1627. Xchar txt_sort_by_date_ascend[] = "Date: field (ascending)";
  1628. Xchar txt_help_autosave[] = "Auto save article/thread by Archive-name: header. <SPACE> toggles & <CR> sets.";
  1629. Xchar txt_help_start_editor_offset[] = "Start editor with line offset. <SPACE> toggles & <CR> sets.";
  1630. Xchar txt_help_confirm_action[] = "Ask for command confirmation. <SPACE> toggles & <CR> sets.";
  1631. Xchar txt_help_print_header[] = "By printing print all/part of header. <SPACE> toggles & <CR> sets.";
  1632. Xchar txt_help_pos_first_unread[] = "Put cursor at first/last unread art in groups. <SPACE> toggles & <CR> sets.";
  1633. Xchar txt_help_show_author[] = "Show Subject & From (author) fields in group menu. <SPACE> toggles & <CR> sets.";
  1634. Xchar txt_help_draw_arrow[] = "Draw -> or highlighted bar for selection. <SPACE> toggles & <CR> sets.";
  1635. Xchar txt_help_mark_saved_read[] = "Mark saved articles/threads as read. <SPACE> toggles & <CR> sets."; 
  1636. Xchar txt_help_page_scroll[] = "Scroll half/full page of groups/articles. <SPACE> toggles & <CR> sets."; 
  1637. Xchar txt_help_catchup_groups[] = "Ask to mark groups read when quiting. <SPACE> toggles & <CR> sets."; 
  1638. Xchar txt_help_thread_arts[] = "Enable/disable threading of articles in all groups. <SPACE> toggles & <CR> sets."; 
  1639. Xchar txt_help_show_only_unread[] = "Show all articles or only unread articles. <SPACE> toggles & <CR> sets."; 
  1640. Xchar txt_help_post_proc_type[] = "Post process (ie. unshar) saved article/thread. <SPACE> toggles & <CR> sets."; 
  1641. Xchar txt_help_sort_type[] = "Sort articles by Subject, From or Date fields. <SPACE> toggles & <CR> sets.";
  1642. Xchar txt_help_savedir[] = "The directory where you want articles/threads saved.";
  1643. Xchar txt_help_maildir[] = "The directory where articles/threads are to be saved in mailbox format.";
  1644. Xchar txt_help_printer[] = "The printer program with options that is to be used to print articles/threads.";
  1645. Xchar txt_select_rcfile_option[] = "Select option by entering number before text. Any other key to save.";
  1646. X
  1647. X/*
  1648. X *  save.c
  1649. X */
  1650. X
  1651. Xchar txt_post_processing[] = "Post processing...";
  1652. Xchar txt_post_processing_finished[] = "-- post processing completed --";
  1653. Xchar txt_deleting[] = "Deleting...";
  1654. Xchar txt_uudecoding[] = "Uudecoding...";
  1655. Xchar txt_extracting_shar[] ="\r\nExtracting %s...\r\n";
  1656. Xchar txt_delete_processed_files[] = "Delete saved files that have been post processed? (y/n): ";
  1657. Xchar txt_post_processing_failed[] = "Post processing failed";
  1658. Xchar txt_listing_archive[] = "\r\n\r\nListing %s archive...\r\n"; 
  1659. Xchar txt_extracting_archive[] = "\r\n\r\nExtracting %s archive...\r\n";
  1660. Xchar txt_checksum_of_file[] = "\r\n\r\nChecksum of %s...\r\n\r\n"; 
  1661. X
  1662. X/*
  1663. X *  search.c
  1664. X */
  1665. X
  1666. Xchar txt_searching[] = "Searching...";
  1667. X
  1668. X/*
  1669. X *  select.c
  1670. X */
  1671. X
  1672. Xchar txt_moving[] = "Moving %s...";
  1673. X#ifdef NO_REGEX
  1674. Xchar txt_subscribe_pattern[] = "Enter subscribe pattern> ";
  1675. Xchar txt_unsubscribe_pattern[] = "Enter unsubscribe pattern> ";
  1676. X#else
  1677. Xchar txt_subscribe_pattern[] = "Enter regex subscribe pattern> ";
  1678. Xchar txt_unsubscribe_pattern[] = "Enter regex unsubscribe pattern> ";
  1679. X#endif
  1680. Xchar txt_subscribing[] = "Subscribing...";
  1681. Xchar txt_subscribing_to[] = "Subscribing to %s...";
  1682. Xchar txt_unsubscribing[] = "Unsubscribing...";
  1683. Xchar txt_unsubscribing_from[] = "Unsubscribing from %s...";
  1684. Xchar txt_subscribed_num_groups[] = "subscribed to %d groups";
  1685. Xchar txt_unsubscribed_num_groups[] = "unsubscribed from %d groups";
  1686. Xchar txt_del_group_in_newsrc[] = "Delete %s from .newsrc? (y/n): ";
  1687. Xchar txt_group_deleted[] = "Group %s deleted";
  1688. Xchar txt_group_undeleted[] = "Group undeleted";
  1689. Xchar txt_mark_group_read[] = "Mark group %s as read? (y/n): ";
  1690. Xchar txt_no_groups_to_delete[] = "No groups to delete";
  1691. Xchar txt_reset_newsrc[] = "Reset newsrc? (y/n): ";
  1692. Xchar txt_post_newsgroup[] = "Post newsgroup> ";
  1693. Xchar txt_yanking_all_groups[] = "Yanking in all groups...";
  1694. Xchar txt_yanking_sub_groups[] = "Yanking in subscribed to groups...";
  1695. Xchar txt_no_groups_to_read[] = "No more groups to read";
  1696. Xchar txt_added_groups[] = "Added %d group%s";
  1697. Xchar txt_plural[] = "s";
  1698. Xchar txt_no_groups_to_yank_in[] = "No more groups to yank in";
  1699. Xchar txt_group_selection[] = "Group Selection";
  1700. Xchar txt_spooldir_selection[] = "Spooldir Selection (%d)";
  1701. Xchar txt_select_group[] = "Select group> ";
  1702. Xchar txt_select_spooldir[] = "Select spooldir> ";
  1703. Xchar txt_help_g_4[] = "4$       Select group 4 ($=select last group)\r\n";
  1704. Xchar txt_help_g_ctrl_r[] = "^R       Reset .newsrc\r\n";
  1705. Xchar txt_help_g_ctrl_k[] = "^KZ      Delete (Z=undelete) group from .newsrc\r\n";
  1706. Xchar txt_help_g_cr[] = "<CR>     Read current group\r\n";
  1707. Xchar txt_help_g_c[] = "c        Mark group as all read\r\n";
  1708. Xchar txt_help_g_l[] = "l        List & select another spooldir\r\n";
  1709. Xchar txt_help_g_tab[] =   "n<TAB>   Goto next group with unread news and enter it\r\n";
  1710. Xchar txt_help_n[] = "N        Goto next group with unread news\r\n";
  1711. Xchar txt_help_g_q[] = "qQ       Quit\r\n";
  1712. Xchar txt_help_W[] = "W        List articles posted by user\r\n";
  1713. Xchar txt_help_g_y[] = "y        Yank in subscribed/unsubscribed from .newsrc\r\n";
  1714. Xchar txt_help_g_z[] = "z        Mark current group as unread\r\n";
  1715. Xchar txt_help_y[] = "Y        Yank in active file to see any new news\r\n";
  1716. Xchar txt_help_g_search[] = "/?       Group forward (?=backward) search\r\n";
  1717. Xchar txt_newsgroup[] = "Goto newsgroup [%s]> ";
  1718. Xchar txt_newsgroup_position[] = "Position %s in group list (1,2,..,$) [%d]> ";
  1719. X
  1720. X/*
  1721. X *  signal.c
  1722. X */
  1723. X
  1724. Xchar txt_resizing_window[] = "resizing window";
  1725. Xchar txt_suspended_message[] = "\nStopped. Type 'fg' to restart TIN\n";
  1726. X
  1727. X/*
  1728. X *  thread.c
  1729. X */
  1730. X
  1731. Xchar txt_no_resps_in_thread[] = "No responses to list in current thread";
  1732. Xchar txt_help_t_0[] = "0        Goto the base article in current thread\r\n";
  1733. Xchar txt_help_t_4[] = "4$       Goto response 4 ($=goto last response) in current thread\r\n";
  1734. Xchar txt_help_t_cr[] = "<CR>     Read current response\r\n";
  1735. Xchar txt_help_t_tab[] = "<TAB>    Goto next unread response\r\n";
  1736. Xchar txt_help_t_K[] =   "K        Mark thread as read & return\r\n";
  1737. END_OF_FILE
  1738.   if test 22813 -ne `wc -c <'lang.c'`; then
  1739.     echo shar: \"'lang.c'\" unpacked with wrong size!
  1740.   fi
  1741.   # end of 'lang.c'
  1742. fi
  1743. echo shar: End of archive 8 \(of 14\).
  1744. cp /dev/null ark8isdone
  1745. MISSING=""
  1746. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1747.     if test ! -f ark${I}isdone ; then
  1748.     MISSING="${MISSING} ${I}"
  1749.     fi
  1750. done
  1751. if test "${MISSING}" = "" ; then
  1752.     echo You have unpacked all 14 archives.
  1753.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1754. else
  1755.     echo You still must unpack the following archives:
  1756.     echo "        " ${MISSING}
  1757. fi
  1758. exit 0
  1759. exit 0 # Just in case...
  1760.