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

  1. Path: wupost!uunet!mcsun!unido!estevax!norisc!iain
  2. From: iain@norisc.UUCP (Iain Lea)
  3. Newsgroups: alt.sources
  4. Subject: tin v1.00 - YAN (Yet Another Newsreader) Part 06/08
  5. Message-ID: <587@norisc.UUCP>
  6. Date: 23 Aug 91 13:55:57 GMT
  7. Sender: iain@norisc.UUCP (Iain Lea)
  8. Organization: What organization?
  9. Lines: 2232
  10.  
  11. Submitted-by: iain@estevax.uucp
  12. Archive-name: tin/part06
  13.  
  14. #!/bin/sh
  15. # this is tin.shar.06 (part 6 of tin)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file rcfile.c continued
  18. #
  19. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  20.  then TOUCH=touch
  21.  else TOUCH=true
  22. fi
  23. if test ! -r shar3_seq_.tmp; then
  24.     echo "Please unpack part 1 first!"
  25.     exit 1
  26. fi
  27. (read Scheck
  28.  if test "$Scheck" != 6; then
  29.     echo "Please unpack part $Scheck next!"
  30.     exit 1
  31.  else
  32.     exit 0
  33.  fi
  34. ) < shar3_seq_.tmp || exit 1
  35. echo "x - Continuing file rcfile.c"
  36. sed 's/^X//' << 'SHAR_EOF' >> rcfile.c &&
  37. X                }
  38. X            }
  39. X        }
  40. X        fclose (fp);
  41. X        return TRUE;        
  42. X    }
  43. X    return FALSE;        
  44. X}
  45. X
  46. X/*
  47. X *  write_rcfile - write defaults to ~/.tin/tinrc
  48. X */
  49. X
  50. Xvoid write_rcfile ()
  51. X{
  52. X    FILE *fp;
  53. X
  54. X    if ((fp = fopen (rcfile, "w")) != NULL) {
  55. X        wait_message (txt_saving);
  56. X
  57. X        fprintf (fp, "# (-a) if ON articles/threads with Archive-name: in mail header will\n");
  58. X        fprintf (fp, "# be automatically saved with the Archive-name & part/patch no.\n");
  59. X        fprintf (fp, "save_archive=%s\n\n", (save_archive_name ? "ON" : "OFF"));
  60. X        fprintf (fp, "# (-s) if ON articles of a threads will be saved to separate files\n");
  61. X        fprintf (fp, "# otherwise the whole thread will be saved to one file\n");
  62. X        fprintf (fp, "save_separate=%s\n\n", (save_separate ? "ON" : "OFF"));
  63. X        fprintf (fp, "# if ON mark articles that are saved as read\n");
  64. X        fprintf (fp, "mark_saved_read=%s\n\n", (mark_saved_read ? "ON" : "OFF"));
  65. X        fprintf (fp, "# if ON show Subject & From otherwise just Subject\n");
  66. X        fprintf (fp, "show_author=%s\n\n", (show_author ? "ON" : "OFF"));
  67. X        fprintf (fp, "# if ON use -> otherwise highlighted bar for selection\n");
  68. X        fprintf (fp, "draw_arrow=%s\n\n", (draw_arrow_mark ? "ON" : "OFF"));
  69. X        fprintf (fp, "# if ON kill articles that match kill file\n");
  70. X        fprintf (fp, "kill_articles=%s\n\n", (kill_articles ? "ON" : "OFF"));
  71. X        fprintf (fp, "# if ON save articles/threads to subdir with Archive-name: under -d directory\n");
  72. X        fprintf (fp, "print_header=%s\n\n", (print_header ? "ON" : "OFF"));
  73. X        fprintf (fp, "# if ON post process saved articles/threads\n");
  74. X        fprintf (fp, "post_process=%s\n\n", (post_process ? "ON" : "OFF"));
  75. X        fprintf (fp, "# type of post processing to perform\n");
  76. X        fprintf (fp, "post_process_type=%d\n\n", post_proc_type);
  77. X        fprintf (fp, "# sort articles by 0) nothing 1) subject 2) from or 3) date field\n");
  78. X        fprintf (fp, "sort_article_type=%d\n\n", sort_art_type);
  79. X        fprintf (fp, "# (-d) directory where articles/threads are saved\n");
  80. X        fprintf (fp, "savedir=%s\n\n", savedir);
  81. X        fprintf (fp, "# (-M) directory where articles/threads are saved in mailbox format\n");    
  82. X        fprintf (fp, "maildir=%s\n\n", maildir);    
  83. X        fprintf (fp, "# (-p) print program with parameters used to print articles/threads\n");
  84. X        fprintf (fp, "printer=%s\n\n", printer);
  85. X        fprintf (fp, "# (-S) directory where news is spooled\n");
  86. X        fprintf (fp, "spooldir=%s\n\n", spooldir);
  87. X
  88. X        fprintf (fp, "# .signature file used for replies, followups\n");
  89. X        fprintf (fp, "signature=%s\n\n", signature);
  90. X        fprintf (fp, "# .Sig file used for postings\n");
  91. X        fprintf (fp, "sig=%s\n\n", sig);
  92. X
  93. X        fclose (fp);
  94. X        chmod (rcfile, 0600);
  95. X    }
  96. X}
  97. X
  98. X/*
  99. X *  options menu so that the user can dynamically change parameters
  100. X */
  101. Xint change_rcfile (group, kill_at_once)
  102. X    char *group;
  103. X    int kill_at_once;
  104. X{
  105. X    char *str;
  106. X    int ch;
  107. X    int kill_changed = FALSE;
  108. X    int orig_kill_state;
  109. X    int option;
  110. X    int ret_code = NO_KILLING;
  111. X    
  112. X    ClearScreen ();
  113. X    printf("%s\r\n", nice_time());    /* time in upper left */
  114. X
  115. X    StartInverse ();
  116. X    center_line (1, txt_options_menu);
  117. X    EndInverse ();
  118. X    
  119. X    MoveCursor(INDEX_TOP, 0);
  120. X    printf ("%s%s\r\n\r\n", txt_opt_autosave, (save_archive_name ? "ON " : "OFF"));
  121. X    printf ("%s%s\r\n\r\n", txt_opt_mark_saved_read, (mark_saved_read ? "ON " : "OFF"));
  122. X    printf ("%s%s\r\n\r\n", txt_opt_show_author, (show_author ? "ON " : "OFF"));
  123. X    printf ("%s%s", txt_opt_post_process, (post_process ? "ON " : "OFF"));
  124. X
  125. X    MoveCursor(INDEX_TOP, COL2);
  126. X    printf ("%s%s", txt_opt_save_separate, (save_separate ? "ON " : "OFF"));
  127. X    MoveCursor(INDEX_TOP+2, COL2);
  128. X    printf ("%s%s", txt_opt_kill_articles, (kill_articles ? "ON " : "OFF"));
  129. X    MoveCursor(INDEX_TOP+4, COL2);
  130. X    printf ("%s%s", txt_opt_draw_arrow, (draw_arrow_mark ? "ON " : "OFF"));
  131. X    MoveCursor(INDEX_TOP+6, COL2);
  132. X    printf ("%s%s", txt_opt_print_header, (print_header ? "ON " : "OFF"));
  133. X
  134. X
  135. X    MoveCursor(INDEX_TOP+8, 0);
  136. X    switch (post_proc_type) {
  137. X        case POST_PROC_SH:
  138. X            str = txt_post_process_sh;
  139. X            break;
  140. X        case POST_PROC_UUD:
  141. X            str = txt_post_process_uud;
  142. X            break;
  143. X        case POST_PROC_UUD_ZOO:
  144. X            str = txt_post_process_uud_zoo;
  145. X            break;
  146. X        case POST_PROC_UUD_LZH:
  147. X            str = txt_post_process_uud_lzh;
  148. X            break;
  149. X        case POST_PROC_UUD_ARC:
  150. X            str = txt_post_process_uud_arc;
  151. X            break;
  152. X        case POST_PROC_UUD_ZIP:
  153. X            str = txt_post_process_uud_zip;
  154. X            break;
  155. X        case POST_PROC_PATCH:
  156. X            str = txt_post_process_patch;
  157. X            break;
  158. X    }
  159. X    printf ("%s%s\r\n\r\n", txt_opt_process_type, str);
  160. X    
  161. X    MoveCursor(INDEX_TOP+10, 0);
  162. X    switch (sort_art_type) {
  163. X        case SORT_BY_NONE:
  164. X            str = txt_sort_by_none;
  165. X            break;
  166. X        case SORT_BY_SUBJ:
  167. X            str = txt_sort_by_subj;
  168. X            break;
  169. X        case SORT_BY_FROM:
  170. X            str = txt_sort_by_from;
  171. X            break;
  172. X        case SORT_BY_DATE:
  173. X            str = txt_sort_by_date;
  174. X            break;
  175. X    }
  176. X    printf ("%s%s\r\n\r\n", txt_opt_sort_type, str);
  177. X
  178. X    printf ("%s%s\r\n\r\n", txt_opt_savedir, savedir);
  179. X    printf ("%s%s\r\n\r\n", txt_opt_maildir, maildir);
  180. X    printf ("%s%s\r\n\r\n", txt_opt_printer, printer);
  181. X    fflush(stdout);
  182. X
  183. X    while (1) {
  184. X        show_menu_help ("Select option by entering number before text. Enter '0' to save/quit.");
  185. X        MoveCursor (LINES, 0);
  186. X        ch = ReadCh ();
  187. X        if (ch == '0') {
  188. X            option = 0;
  189. X        } else {
  190. X            option = parse_num (ch, "Enter option number> ");
  191. X        }
  192. X    switch (option) {
  193. X        case 0:
  194. X            write_rcfile ();
  195. X            if (kill_changed) {
  196. X                if (kill_at_once) {
  197. X                    if (kill_articles) {
  198. X                        read_kill_file ();
  199. X                        if (kill_any_articles (group)) {
  200. X                            reload_index_file (group, TRUE);    /* kill arts */
  201. X                        }
  202. X                    } else {
  203. X                        reload_index_file (group, FALSE);    /* add killed arts */
  204. X                    }
  205. X                }
  206. X                ret_code = KILLING;
  207. X            }
  208. X            clear_note_area ();
  209. X            return ret_code;
  210. X            
  211. X        case 1:        /* auto save */
  212. X            show_menu_help (txt_help_autosave);
  213. X            do {
  214. X                MoveCursor (INDEX_TOP, strlen (txt_opt_autosave));
  215. X                if ((ch = ReadCh()) == ' ') {
  216. X                    save_archive_name = !save_archive_name;
  217. X                    printf ("%s", (save_archive_name ? "ON " : "OFF"));
  218. X                    fflush(stdout);
  219. X                }
  220. X            } while (ch != CR);
  221. X            break;
  222. X
  223. X        case 2:        /* save sperate */
  224. X            show_menu_help (txt_help_save_separate);
  225. X            do {
  226. X                MoveCursor (INDEX_TOP, COL2 + (int) strlen (txt_opt_save_separate));
  227. X                if ((ch = ReadCh()) == ' ') {
  228. X                    save_separate = !save_separate;
  229. X                    printf ("%s", (save_separate ? "ON " : "OFF"));
  230. X                    fflush(stdout);
  231. X                }
  232. X            } while (ch != CR);
  233. X            break;
  234. X            
  235. X        case 3:        /* mark saved articles read */
  236. X            show_menu_help (txt_help_mark_saved_read);
  237. X            do {
  238. X                MoveCursor (INDEX_TOP+2, strlen (txt_opt_mark_saved_read));
  239. X                if ((ch = ReadCh()) == ' ') {
  240. X                    mark_saved_read = !mark_saved_read;
  241. X                    printf ("%s", (mark_saved_read ? "ON " : "OFF"));
  242. X                    fflush(stdout);
  243. X                }
  244. X            } while (ch != CR);
  245. X            break;
  246. X
  247. X        case 4:        /* kill articles */
  248. X            orig_kill_state = kill_articles;
  249. X            show_menu_help (txt_help_kill_articles);
  250. X            do {
  251. X                MoveCursor (INDEX_TOP+2, COL2 + (int) strlen (txt_opt_kill_articles));
  252. X                if ((ch = ReadCh()) == ' ') {
  253. X                    kill_articles = !kill_articles;
  254. X                    kill_changed = (kill_articles != orig_kill_state ? TRUE : FALSE);
  255. X                    printf ("%s", (kill_articles ? "ON " : "OFF"));
  256. X                    fflush(stdout);
  257. X                }
  258. X            } while (ch != CR);
  259. X            break;
  260. X
  261. X        case 5:        /* show subject & author / subject only */
  262. X            show_menu_help (txt_help_show_author);
  263. X            do {
  264. X                MoveCursor (INDEX_TOP+4, strlen (txt_opt_show_author));
  265. X                if ((ch = ReadCh()) == ' ') {
  266. X                    show_author = !show_author;
  267. X                    printf ("%s", (show_author ? "ON " : "OFF"));
  268. X                    fflush(stdout);    
  269. X                }
  270. X            } while (ch != CR);
  271. X            break;
  272. X            
  273. X        case 6:        /* draw -> / highlighted bar */
  274. X            show_menu_help (txt_help_draw_arrow);
  275. X            do {
  276. X                MoveCursor (INDEX_TOP+4, COL2 + (int) strlen (txt_opt_draw_arrow));
  277. X                if ((ch = ReadCh()) == ' ') {
  278. X                    draw_arrow_mark = !draw_arrow_mark;
  279. X                    printf ("%s", (draw_arrow_mark ? "ON " : "OFF"));
  280. X                    fflush(stdout);
  281. X                }
  282. X            } while (ch != CR);
  283. X            break;
  284. X
  285. X        case 7:        /* post process saved files */
  286. X            show_menu_help (txt_help_post_process);
  287. X            do {
  288. X                MoveCursor (INDEX_TOP+6, strlen (txt_opt_post_process));
  289. X                if ((ch = ReadCh()) == ' ') {
  290. X                    post_process = !post_process;
  291. X                    printf ("%s", (post_process ? "ON " : "OFF"));
  292. X                    fflush(stdout);
  293. X                }
  294. X            } while (ch != CR);
  295. X            break;
  296. X            
  297. X        case 8:        /* print header */
  298. X            show_menu_help (txt_help_print_header);
  299. X            do {
  300. X                MoveCursor (INDEX_TOP+6, COL2 + (int) strlen (txt_opt_print_header));
  301. X                if ((ch = ReadCh()) == ' ') {
  302. X                    print_header = !print_header;
  303. X                    printf ("%s", (print_header ? "ON " : "OFF"));
  304. X                    fflush(stdout);
  305. X                }
  306. X            } while (ch != CR);
  307. X            break;
  308. X            
  309. X        case 9:
  310. X            show_menu_help (txt_help_post_proc_type);
  311. X            do {
  312. X                MoveCursor (INDEX_TOP+8, strlen (txt_opt_process_type));
  313. X                if ((ch    = ReadCh()) == ' ') {
  314. X                    if (post_proc_type + 1 > POST_PROC_PATCH) {
  315. X                        post_proc_type = POST_PROC_SH;
  316. X                    } else {
  317. X                        post_proc_type++;
  318. X                    }
  319. X                    switch (post_proc_type) {
  320. X                        case POST_PROC_SH:
  321. X                            str = txt_post_process_sh;
  322. X                            break;
  323. X                        case POST_PROC_UUD:
  324. X                            str = txt_post_process_uud;
  325. X                            break;
  326. X                        case POST_PROC_UUD_ZOO:
  327. X                            str = txt_post_process_uud_zoo;
  328. X                            break;
  329. X                        case POST_PROC_UUD_LZH:
  330. X                            str = txt_post_process_uud_lzh;
  331. X                            break;
  332. X                        case POST_PROC_UUD_ARC:
  333. X                            str = txt_post_process_uud_arc;
  334. X                            break;
  335. X                        case POST_PROC_UUD_ZIP:
  336. X                            str = txt_post_process_uud_zip;
  337. X                            break;
  338. X                        case POST_PROC_PATCH:
  339. X                            str = txt_post_process_patch;
  340. X                            break;
  341. X                    }
  342. X                    CleartoEOLN (); 
  343. X                    printf ("%s", str);
  344. X                    fflush(stdout);
  345. X                }
  346. X            } while (ch != CR);
  347. X            break;
  348. X        case 10:
  349. X            show_menu_help (txt_help_sort_type);
  350. X            do {
  351. X                MoveCursor (INDEX_TOP+10, strlen (txt_opt_sort_type));
  352. X                if ((ch    = ReadCh()) == ' ') {
  353. X                    if (sort_art_type + 1 > SORT_BY_DATE) {
  354. X                        sort_art_type = SORT_BY_NONE;
  355. X                    } else {
  356. X                        sort_art_type++;
  357. X                    }
  358. X                    switch (sort_art_type) {
  359. X                        case SORT_BY_NONE:
  360. X                            str = txt_sort_by_none;
  361. X                            break;
  362. X                        case SORT_BY_SUBJ:
  363. X                            str = txt_sort_by_subj;
  364. X                            break;
  365. X                        case SORT_BY_FROM:
  366. X                            str = txt_sort_by_from;
  367. X                            break;
  368. X                        case SORT_BY_DATE:
  369. X                            str = txt_sort_by_date;
  370. X                            break;
  371. X                    }
  372. X                    CleartoEOLN (); 
  373. X                    printf ("%s", str);
  374. X                    fflush(stdout);
  375. X                }
  376. X            } while (ch != CR);
  377. X            break;
  378. X        case 11:
  379. X            show_menu_help (txt_help_savedir);
  380. X            parse_menu_string (INDEX_TOP+12, strlen (txt_opt_savedir), savedir);
  381. X            expand_rel_abs_pathname (INDEX_TOP+12, strlen (txt_opt_savedir), savedir);
  382. X            break;
  383. X        case 12:
  384. X            show_menu_help (txt_help_maildir);
  385. X            parse_menu_string (INDEX_TOP+14, strlen (txt_opt_maildir), maildir);
  386. X            expand_rel_abs_pathname (INDEX_TOP+14, strlen (txt_opt_maildir), maildir);
  387. X            break;
  388. X        case 13:
  389. X            show_menu_help (txt_help_printer);
  390. X            parse_menu_string (INDEX_TOP+16, strlen (txt_opt_printer), printer);
  391. X            expand_rel_abs_pathname (INDEX_TOP+16, strlen (txt_opt_printer), printer);
  392. X            break;
  393. X    }
  394. X    }
  395. X}
  396. X
  397. X/*
  398. X *  parse_menu_string
  399. X *  get a string from the user
  400. X *  Return TRUE if a valid string was typed, FALSE otherwise
  401. X */
  402. X
  403. Xvoid parse_menu_string (line, col, var)
  404. X    int line;
  405. X    int col;
  406. X    char *var;
  407. X{
  408. X    char buf[LEN+1];
  409. X    char ch;
  410. X    int len;
  411. X    int i;
  412. X
  413. X    MoveCursor (line, col);
  414. X    buf[0] = '\0';
  415. X    len = 0;
  416. X    ch = ReadCh();
  417. X    while (ch != '\n' && ch != '\r') {
  418. X        if (ch == 8 || ch == 127) {
  419. X            if (len) {
  420. X                len--;
  421. X                buf[len] = '\0';
  422. X                putchar('\b');
  423. X                putchar(' ');
  424. X                putchar('\b');
  425. X            } else {
  426. X                strcpy (var, buf);
  427. X                MoveCursor(line, col);
  428. X                CleartoEOLN();
  429. X            }
  430. X        } else if (ch == 21) {    /* control-U    */
  431. X            for (i = len;i>0;i--) {
  432. X                putchar('\b');
  433. X                putchar(' ');
  434. X                putchar('\b');
  435. X            }
  436. X            buf[0] = '\0';
  437. X            len = 0;
  438. X        } else if (ch >= ' ' && len < 60) {
  439. X            buf[len++] = ch;
  440. X            buf[len] = '\0';
  441. X            putchar (ch);
  442. X        } else
  443. X            putchar(7);
  444. X        fflush(stdout);
  445. X        ch = ReadCh();
  446. X    }
  447. X
  448. X    if (buf[0]) {
  449. X        strcpy (var, buf);
  450. X    }
  451. X}
  452. X
  453. X/*
  454. X *  expand ~/News to /usr/username/News and print to screen
  455. X */
  456. Xvoid expand_rel_abs_pathname (line, col, str)
  457. X    int line;
  458. X    int col;
  459. X    char *str;
  460. X{
  461. X    char buf[LEN+1];
  462. X    
  463. X    if (str[0] == '~') {
  464. X        if (strlen (str) == 1) {
  465. X            strcpy (str, homedir);
  466. X        } else {
  467. X            sprintf (buf, "%s%s", homedir, str+1);
  468. X            strcpy (str, buf);
  469. X        }
  470. X    }
  471. X    MoveCursor (line, col);
  472. X    CleartoEOLN ();
  473. X    puts (str);
  474. X    fflush (stdout);
  475. X}
  476. X
  477. X/*
  478. X *  show_menu_help
  479. X */
  480. Xvoid show_menu_help (help_message)
  481. X    char *help_message;
  482. X{
  483. X     MoveCursor (INDEX_TOP+18, 0);
  484. X     CleartoEOLN ();
  485. X     center_line (INDEX_TOP+18, help_message);
  486. X}
  487. SHAR_EOF
  488. echo "File rcfile.c is complete" &&
  489. $TOUCH -am 0819090991 rcfile.c &&
  490. chmod 0600 rcfile.c ||
  491. echo "restore of rcfile.c failed"
  492. set `wc -c rcfile.c`;Wc_c=$1
  493. if test "$Wc_c" != "15340"; then
  494.     echo original size 15340, current size $Wc_c
  495. fi
  496. # ============= save.c ==============
  497. echo "x - extracting save.c (Text)"
  498. sed 's/^X//' << 'SHAR_EOF' > save.c &&
  499. X/*
  500. X *  Project   : tin - a visual threaded usenet newsreader
  501. X *  Module    : save.c
  502. X *  Author    : R.Skrenta / I.Lea
  503. X *  Created   : 01-04-91
  504. X *  Updated   : 23-08-91
  505. X *  Release   : 1.0
  506. X *  Notes     :
  507. X *  Copyright : (c) Copyright 1991 by Rich Skrenta, Iain Lea & Wayne Brandt
  508. X *                You may  freely  copy or  redistribute  this software,
  509. X *              so  long as there is no profit made from its use, sale
  510. X *              trade or  reproduction.  You may not change this copy-
  511. X *              right notice, and it must be included in any copy made
  512. X */
  513. X
  514. X#include    "tin.h"
  515. X
  516. X#define    INITIAL        1
  517. X#define MIDDLE        2
  518. X#define OFF            3
  519. X#define END            4
  520. X
  521. Xint create_subdir = TRUE;
  522. X
  523. Xstruct save_t *save;
  524. Xint save_num=0;
  525. Xint max_save;
  526. X
  527. X/*
  528. X * types of archive programs
  529. X * 0=archiver, 1=extension, 2=extract option, 3=list option
  530. X */
  531. Xstruct archiver_t { 
  532. X    char *name;
  533. X    char *ext;
  534. X    char *extract;
  535. X    char *list;
  536. X};
  537. X
  538. Xstruct archiver_t archiver[] = {
  539. X    { "",      "",    "",         "" },
  540. X    { "",      "",    "",         "" },
  541. X    { "",      "",    "",         "" },
  542. X    { "zoo",   "zoo", "-extract", "-list" },
  543. X    { "lharc", "lzh", "x",        "l" },
  544. X    { "arc",   "arc", "x",        "l" },
  545. X    { "zip",   "zip", "-x",       "-l" },
  546. X    { "",      "",    "",         "" }
  547. X};
  548. X
  549. Xextern char *glob_page_group;
  550. Xextern char note_h_path[LEN+1];    /* Path:    */
  551. Xextern char note_h_date[LEN+1];    /* Date:    */
  552. Xextern FILE    *note_fp;            /* the body of the current article */
  553. Xextern int index_point;
  554. Xextern int note_end;
  555. Xextern int note_page;
  556. Xextern long note_mark[MAX_PAGES];
  557. X
  558. Xchar default_regex_pattern[LEN+1];
  559. X
  560. X
  561. Xvoid save_art_to_file (respnum, index, mailbox, filename)
  562. X    int respnum;
  563. X    int index;
  564. X    int mailbox;
  565. X    char *filename;
  566. X{
  567. X    char file[LEN+1], *p;
  568. X    char save_art_info[LEN+1];
  569. X    FILE *fp;
  570. X    int is_mailbox = FALSE;
  571. X    int i = 0;
  572. X    
  573. X    file[0] = '\0';
  574. X    
  575. X    if (filename) {
  576. X        my_strncpy (file, filename, LEN);
  577. X        is_mailbox = mailbox;
  578. X        i = index;
  579. X    } else {
  580. X        if (save_archive_name && arts[respnum].archive) {
  581. X            my_strncpy (file, arts[respnum].archive, LEN);
  582. X        } else {
  583. X            if (! parse_string(txt_save_art_to_file, file)) {
  584. X                return;
  585. X            }
  586. X            if (file[0] == '\0') {
  587. X                info_message (txt_no_filename);
  588. X                return;
  589. X            }
  590. X
  591. X            for (p = file; *p && (*p == ' ' || *p == '\t'); p++) {
  592. X                ;
  593. X            }
  594. X            if (! *p) {
  595. X                return;
  596. X            }
  597. X
  598. X            is_mailbox = create_path (file);
  599. X        }
  600. X        free_save_array ();
  601. X        add_to_save_list (save_num, &arts[respnum], is_mailbox, file);
  602. X    }
  603. X
  604. X    if (! append_to_existing_file (i)) {
  605. X        info_message(txt_art_not_saved);
  606. X        sleep (1);
  607. X        return;
  608. X    }
  609. X
  610. X    setuid(real_uid);
  611. X    setgid(real_gid);
  612. X
  613. X    if ((fp = fopen(save_filename (i), "a+")) == NULL) {
  614. X        info_message(txt_art_not_saved);
  615. X        setuid(real_uid);
  616. X        setgid(real_gid);
  617. X        return;
  618. X    }
  619. X
  620. X    if (! filename) {
  621. X        wait_message (txt_saving);
  622. X    }
  623. X    
  624. X    fprintf(fp, "From %s %s\n", note_h_path, note_h_date);
  625. X
  626. X    if (fseek(note_fp, 0L, 0) == -1) {
  627. X        error_message ("fseek error on \"%s\"", arts[respnum].subject);
  628. X    }
  629. X    copy_fp(note_fp, fp, "");
  630. X    fputs("\n", fp);
  631. X    fclose(fp);
  632. X    fseek(note_fp, note_mark[note_page], 0);
  633. X
  634. X    save[i].saved = TRUE;
  635. X
  636. X    if (mark_saved_read) {
  637. X        arts[respnum].unread = ART_READ;
  638. X    }
  639. X    
  640. X    setuid(real_uid);
  641. X    setgid(real_gid);
  642. X
  643. X    if (! filename) {
  644. X        if (is_mailbox) {
  645. X            sprintf (save_art_info, txt_saved_to_mailbox, get_first_savefile ());
  646. X        } else {
  647. X            sprintf (save_art_info, txt_art_saved_to, get_first_savefile ());
  648. X        }
  649. X        info_message(save_art_info);
  650. X    }
  651. X}
  652. X
  653. X
  654. Xvoid save_thread_to_file (respnum, group_path)
  655. X    int respnum;
  656. X    char *group_path;
  657. X{
  658. X    char *p;
  659. X    char file[LEN+1];
  660. X    char save_thread_info[LEN+1];
  661. X    char *first_savefile;
  662. X    FILE *fp;
  663. X    int count = 0;
  664. X    int is_mailbox = FALSE;
  665. X    int b, i;
  666. X    int orig_note_end;
  667. X    int orig_note_page;
  668. X
  669. X    file[0] = '\0';
  670. X    free_save_array ();
  671. X
  672. X    b = which_base (respnum);
  673. X    
  674. X    if (! save_archive_name || ! arts[base[b]].archive) {
  675. X        if (! parse_string(txt_save_thread_to, file)) {
  676. X            return;
  677. X        }
  678. X        if (file[0] == '\0') {
  679. X            info_message (txt_no_filename);
  680. X            return;
  681. X        }
  682. X
  683. X        for (p = file; *p && (*p == ' ' || *p == '\t'); p++) {
  684. X            ;
  685. X        }
  686. X        if (! *p) {
  687. X            return;
  688. X        }
  689. X
  690. X        is_mailbox = create_path (file);
  691. X    }
  692. X    
  693. X    setuid (real_uid);
  694. X    setgid (real_gid);
  695. X
  696. X    for (i = base[b] ; i >= 0 ; i = arts[i].thread) {
  697. X        add_to_save_list (i, &arts[i], is_mailbox, file);
  698. X    }
  699. X    sort_save_list ();
  700. X
  701. X    wait_message (txt_saving);
  702. X    
  703. X    orig_note_end = note_end;
  704. X    orig_note_page = note_page;
  705. X    note_cleanup ();        /* close currently opened article */
  706. X
  707. X    for (i=0 ; i < save_num ; i++) {
  708. X        if (! append_to_existing_file (i)) {
  709. X            info_message(txt_art_not_saved);
  710. X            sleep (1);
  711. X            setuid(real_uid);
  712. X            setgid(real_gid);
  713. X            continue;
  714. X        } else {
  715. X            wait_message (txt_saving);
  716. X        }
  717. X
  718. X        if ((fp = fopen (save_filename (i), "a+")) == NULL) {
  719. X            info_message(txt_thread_not_saved);
  720. X            goto reopen_article;
  721. X        }    
  722. X
  723. X        open_note (arts[save[i].index].artnum, group_path);
  724. X        fprintf (fp, "From %s %s\n", note_h_path, note_h_date);
  725. X        fseek (note_fp, 0L, 0);
  726. X        copy_fp (note_fp, fp, "");
  727. X        note_cleanup ();
  728. X        save[i].saved = TRUE;
  729. X
  730. X        if (mark_saved_read) {
  731. X            arts[save[i].index].unread = ART_READ;
  732. X        }
  733. X
  734. X        printf("\b\b\b\b%4d", ++count);
  735. X        fflush(stdout);
  736. X        fclose(fp);
  737. X    }
  738. X    
  739. X    if (! (first_savefile = get_first_savefile ())) {
  740. X        info_message(txt_thread_not_saved);
  741. X    } else {
  742. X        if (is_mailbox) {
  743. X            sprintf (save_thread_info, txt_saved_to_mailbox, first_savefile);
  744. X        } else {
  745. X            if (save_num == 1) {
  746. X                sprintf (save_thread_info, txt_art_saved_to, first_savefile);
  747. X            } else {
  748. X                if (save_separate) {
  749. X                    sprintf (save_thread_info, txt_thread_saved_to_many,
  750. X                        first_savefile, get_last_savefile ());
  751. X                } else {
  752. X                    sprintf (save_thread_info, txt_thread_saved_to,
  753. X                        first_savefile);
  754. X                }
  755. X            }
  756. X            free (first_savefile);
  757. X            first_savefile = '\0';
  758. X        }
  759. X        info_message(save_thread_info);
  760. X    }
  761. X    
  762. Xreopen_article:
  763. X    setuid(real_uid);
  764. X    setgid(real_gid);
  765. X    open_note(arts[respnum].artnum, group_path);
  766. X    note_end = orig_note_end;
  767. X    note_page = orig_note_page;
  768. X    fseek (note_fp, note_mark[note_page], 0);
  769. X}
  770. X
  771. X
  772. Xint save_regex_arts (group_path, group)
  773. X    char *group_path;
  774. X    char *group;
  775. X{
  776. X    char buf[LEN+1];
  777. X    char buf2[LEN+1];
  778. X    char dir[LEN+1];
  779. X    char file[LEN+1];
  780. X    char mailbox[LEN+1];
  781. X    int i, j;    
  782. X    int    is_mailbox = FALSE;
  783. X    int save_tagged_files = FALSE;
  784. X    
  785. X    if (index_point < 0) {
  786. X        info_message (txt_no_match);
  787. X        return FALSE; 
  788. X    }
  789. X    
  790. X    free_save_array ();
  791. X    clear_message ();
  792. X    
  793. X    /*
  794. X     *  check if tagged files and if not ask user for subject pattern
  795. X     */
  796. X    if (num_of_tagged_files) {
  797. X        if (prompt_yn (LINES, "Enter 'y' to save tagged files or 'n' to enter regex pattern? (y/n): ", 'y')) {
  798. X            save_tagged_files = TRUE;
  799. X        }
  800. X    }
  801. X
  802. X    if (! save_tagged_files) {
  803. X        sprintf (buf2, txt_save_pattern, default_regex_pattern);
  804. X    
  805. X        if (! parse_string (buf2, buf)) {
  806. X            return FALSE;
  807. X        }
  808. X        if (strlen (buf)) {
  809. X            my_strncpy (default_regex_pattern, buf, LEN);
  810. X        } else {
  811. X            if (default_regex_pattern[0]) {
  812. X                my_strncpy (buf, default_regex_pattern, LEN);
  813. X            } else {
  814. X                info_message (txt_no_search_string);
  815. X                return FALSE;
  816. X            }
  817. X        }
  818. X    }
  819. X
  820. X    /*
  821. X     *  ask user for filename
  822. X     */
  823. X    if (! parse_string (txt_base_file_name, file)) {
  824. X        return FALSE;
  825. X    }
  826. X
  827. X    if (file[0] == '\0') {
  828. X        info_message (txt_no_filename);
  829. X        return FALSE;
  830. X    }
  831. X
  832. X    if (is_mailbox = create_path (file)) {
  833. X        if ((int) strlen (file) > 1) {
  834. X            my_strncpy (mailbox, file, LEN);
  835. X        } else {
  836. X            my_strncpy (mailbox, group, LEN);
  837. X        }
  838. X        my_strncpy (file, mailbox, LEN);
  839. X    }
  840. X
  841. X    if (save_tagged_files) {
  842. X        for (i=1 ; i <= num_of_tagged_files ; i++) {
  843. X            for (j=0 ; j < top ; j++) {
  844. X                if (arts[j].tagged && arts[j].tagged == i) { 
  845. X                    add_to_save_list (j, &arts[j], is_mailbox, file);
  846. X                }
  847. X            }
  848. X        }
  849. X    } else {
  850. X        for (i=0 ; i < top ; i++) {
  851. X#ifdef DONT_USE_REGEX 
  852. X            if (str_str (arts[i].subject, buf) != 0) {
  853. X#else        
  854. X            if (wildmat (arts[i].subject, buf)) {
  855. X#endif        
  856. X                add_to_save_list (i, &arts[i], is_mailbox, file);
  857. X            }
  858. X        }
  859. X        sort_save_list ();
  860. X    }
  861. X
  862. X    for (i=0 ; i < save_num ; i++) {
  863. X        MoveCursor(LINES, 0);
  864. X        fputs(txt_saving, stdout);
  865. X        printf("\b\b\b\b%4d", i+1);
  866. X        fflush(stdout);
  867. X
  868. X        if (is_mailbox) {
  869. X            strcpy (file, mailbox);
  870. X        }else {
  871. X            sprintf (file, "%s.%02d", save[i].file, i+1);
  872. X        }
  873. X
  874. X        open_note (arts[save[i].index].artnum, group_path);
  875. X        save_art_to_file (save[i].index, i, is_mailbox, file);
  876. X        note_cleanup ();            
  877. X        save[i].saved = TRUE;
  878. X    }
  879. X
  880. X    if (! save_num) {    
  881. X        info_message(txt_no_match);
  882. X    } else {
  883. X        if (is_mailbox) {
  884. X            sprintf (buf, txt_saved_to_mailbox, get_first_savefile ());
  885. X        } else {
  886. X            sprintf (buf,txt_saved_pattern_to,
  887. X                get_first_savefile (), get_last_savefile ());
  888. X        }
  889. X        info_message(buf);
  890. X    }
  891. X    
  892. X    return (mark_saved_read ? TRUE : FALSE);
  893. X}
  894. X
  895. X
  896. Xint append_to_existing_file (i)
  897. X    int i;
  898. X{
  899. X    char buf[LEN+1];
  900. X    char *file;
  901. X    struct stat st;
  902. X
  903. X    if (! save[i].is_mailbox && save_separate) {
  904. X        file = save_filename (i);
  905. X        if (stat(file, &st) != -1) {    
  906. X            sprintf (buf, txt_append_to_file, file); 
  907. X            if (! prompt_yn (LINES, buf, 'n')) {
  908. X                free (file);
  909. X                file = NULL;
  910. X                return FALSE;
  911. X            }
  912. X        }
  913. X        free (file);
  914. X        file = NULL;
  915. X    }
  916. X    
  917. X    return TRUE;
  918. X}
  919. X
  920. X
  921. Xint create_path (path)
  922. X    char *path;
  923. X{
  924. X    char buf [LEN];
  925. X    int i, j, len;
  926. X    struct stat st;
  927. X    
  928. X    /*
  929. X     * save in mailbox format to ~/Mail/<group.name>
  930. X     */
  931. X    if (path[0] == '=') {
  932. X        return TRUE;
  933. X    }
  934. X
  935. X    /*
  936. X     * if ~/file expand (ie. /usr/homedir/file)
  937. X     */
  938. X    if (path[0] == '~') {
  939. X        strcpy (buf, path+1);
  940. X        sprintf (path, "%s%s", homedir, buf);
  941. X    }
  942. X
  943. X    /*
  944. X     *  create any directories, otherwise check
  945. X     *  errno and give appropiate error message
  946. X     */
  947. X    len = (int) strlen (path);
  948. X    
  949. X    for (i=0, j=0 ; i < len ; i++, j++) {
  950. X        buf[j] = path[i];
  951. X        if (i+1 < len && path[i+1] == '/') {
  952. X            buf[j+1] = '\0';
  953. X            if (stat (buf, &st) == -1) {
  954. X                if (mkdir (buf, 0755) == -1) {
  955. X                    error_message ("Cannot create ", buf);
  956. X                    return FALSE;
  957. X                }
  958. X            }
  959. X        }
  960. X    }
  961. X    return FALSE;
  962. X}
  963. X
  964. X
  965. Xint create_sub_dir (i)
  966. X    int i;
  967. X{
  968. X    char dir[LEN+1];
  969. X    struct stat st;
  970. X
  971. X    if (! save[i].is_mailbox && save[i].archive) {
  972. X        sprintf (dir, "%s/%s", save[i].dir, save[i].archive);
  973. X        if (stat (dir, &st) == -1) {
  974. X            mkdir (dir, 0755);
  975. X            return TRUE;
  976. X        }
  977. X        if ((st.st_mode & S_IFMT) == S_IFDIR) {
  978. X            return TRUE;
  979. X        } else {
  980. X            return FALSE;
  981. X        }
  982. X    }
  983. X    return FALSE;
  984. X}
  985. X
  986. X/*
  987. X *  add files to be saved to save array
  988. X */
  989. X
  990. Xvoid add_to_save_list (index, article, is_mailbox, path)
  991. X    int index;
  992. X    struct header *article;
  993. X    int is_mailbox;
  994. X    char *path;
  995. X{
  996. X    char dir[LEN+1];
  997. X    char file[LEN+1];
  998. X    int i;
  999. X    
  1000. X    dir[0] = '\0';
  1001. X    file[0] = '\0';
  1002. X
  1003. X    if (save_num == max_save-1) {
  1004. X        expand_save ();
  1005. X    }
  1006. X
  1007. X    save[save_num].index   = index;
  1008. X    save[save_num].saved   = FALSE;
  1009. X    save[save_num].is_mailbox = is_mailbox;
  1010. X    save[save_num].dir     = (char *) 0;
  1011. X    save[save_num].file    = (char *) 0;
  1012. X    save[save_num].archive = (char *) 0;
  1013. X    save[save_num].part    = (char *) 0;
  1014. X    save[save_num].patch   = (char *) 0;
  1015. X
  1016. X    save[save_num].subject = str_dup (article->subject);
  1017. X    if (article->archive) {
  1018. X        save[save_num].archive = str_dup (article->archive);
  1019. X    }
  1020. X    if (article->part) {
  1021. X        save[save_num].part = str_dup (article->part);
  1022. X    }
  1023. X    if (article->patch) {
  1024. X        save[save_num].patch = str_dup (article->patch);
  1025. X    }
  1026. X
  1027. X    if (is_mailbox) {
  1028. X        if ((int) strlen (path) > 1) {
  1029. X            if (path[0] == '=') {
  1030. X                strcpy (file, path+1);
  1031. X            } else {
  1032. X                strcpy (file, path);
  1033. X            }
  1034. X        } else {
  1035. X            strcpy (file, glob_page_group);
  1036. X        }
  1037. X        /*
  1038. X         *  convert 1st letter to uppercase
  1039. X         */
  1040. X        if (file[0] >= 'a' && file[0] <= 'z') {
  1041. X            file[0] = file[0] - 32;
  1042. X        }
  1043. X        save[save_num].dir = maildir;
  1044. X        save[save_num].file = str_dup (file);
  1045. X    } else {
  1046. X        if (path[0]) {
  1047. X            for (i=strlen (path) ; i ; i--) {
  1048. X                if (path[i] == '/') {
  1049. X                    strncpy (dir, path, i);
  1050. X                    dir[i] = '\0';
  1051. X                    strcpy (file, path+i+1);
  1052. X                    break;
  1053. X                }
  1054. X            }
  1055. X        }
  1056. X        
  1057. X        if (dir[0]) {
  1058. X            save[save_num].dir = str_dup (dir);
  1059. X        } else {
  1060. X            save[save_num].dir = str_dup (savedir);
  1061. X        }
  1062. X
  1063. X        if (file[0]) {
  1064. X            save[save_num].file = str_dup (file);
  1065. X        } else {
  1066. X            if (path[0]) {
  1067. X                save[save_num].file = str_dup (path);
  1068. X            } else {
  1069. X                save[save_num].file = save[save_num].archive;
  1070. X            }
  1071. X        }
  1072. X    }
  1073. X    save_num++;
  1074. X}
  1075. X
  1076. X/*
  1077. X *  print save array of files to be saved
  1078. X */
  1079. X
  1080. Xvoid sort_save_list ()
  1081. X{
  1082. X    qsort (save, save_num, sizeof (struct save_t), save_comp);
  1083. X}
  1084. X
  1085. X/*
  1086. X *  string comparison routine for the qsort()
  1087. X *  ie. qsort(array, 5, 32, save_comp);
  1088. X */
  1089. X
  1090. Xint save_comp (s1, s2)
  1091. X    struct save_t *s1;
  1092. X    struct save_t *s2;
  1093. X{
  1094. X    /* s1->subject less than s2->subject */
  1095. X    if (strcmp (s1->subject, s2->subject) < 0) {
  1096. X        return -1;
  1097. X    }
  1098. X    /* s1->subject greater than s2->subject */
  1099. X    if (strcmp (s1->subject, s2->subject) > 0) {
  1100. X        return 1;
  1101. X    }
  1102. X    return 0;
  1103. X}
  1104. X
  1105. X
  1106. Xchar *save_filename (i)
  1107. X    int i;
  1108. X{
  1109. X    char *filename;
  1110. X
  1111. X    filename = (char *) my_malloc (LEN);
  1112. X
  1113. X    if (save[i].is_mailbox) {
  1114. X        sprintf (filename, "%s/%s", save[i].dir, save[i].file);
  1115. X        return (filename);
  1116. X    }
  1117. X    
  1118. X    if (! save_separate || ! save_archive_name || (! save[i].part && ! save[i].patch)) {
  1119. X        if (! save_separate || save_num == 1) {
  1120. X            sprintf (filename, "%s/%s", save[i].dir, save[i].file);
  1121. X        } else {
  1122. X            sprintf (filename, "%s/%s.%02d", save[i].dir, save[i].file, i+1);
  1123. X        }
  1124. X    } else {
  1125. X        if (save[i].part) {
  1126. X            if (create_sub_dir (i)) {
  1127. X                sprintf (filename, "%s/%s/%s.%s%s", save[i].dir, save[i].archive, save[i].archive, LONG_PATH_PART, save[i].part);
  1128. X            } else {
  1129. X                sprintf (filename, "%s/%s.%s%s", save[i].dir, save[i].archive, LONG_PATH_PART, save[i].part);
  1130. X            }
  1131. X        } else {
  1132. X            if (save[i].patch) {
  1133. X                if (create_sub_dir (i)) {
  1134. X                    sprintf (filename, "%s/%s/%s.%s%s", save[i].dir, save[i].archive, save[i].archive, LONG_PATH_PATCH, save[i].patch);
  1135. X                } else {
  1136. X                    sprintf (filename, "%s/%s.%s%s", save[i].dir, save[i].archive, LONG_PATH_PATCH, save[i].patch);
  1137. X                }
  1138. X            } else {
  1139. X                  sprintf (filename, "%s/%s", save[i].dir, save[i].file);
  1140. X            }
  1141. X        }
  1142. X    }
  1143. X
  1144. X    return (filename);
  1145. X}
  1146. X
  1147. X
  1148. Xchar *get_first_savefile ()
  1149. X{
  1150. X    char *file;
  1151. X    int i;
  1152. X
  1153. X    for (i=0 ; i < save_num ; i++) {
  1154. X        if (save[i].saved) {
  1155. X            file = (char *) my_malloc (LEN);
  1156. X            if (save[i].is_mailbox) {
  1157. X                sprintf (file, "%s/%s", save[i].dir, save[i].file);
  1158. X                return (file);
  1159. X            } else {
  1160. X                if (save[i].archive && save_archive_name) {
  1161. X                    if (save[i].part) {
  1162. X                        if (create_subdir) {
  1163. X                            sprintf (file, "%s/%s.%s%s", save[i].archive, save[i].archive, LONG_PATH_PART, save[i].part);
  1164. X                        } else {
  1165. X                            sprintf (file, "%s.%s%s", save[i].archive, LONG_PATH_PART, save[i].part);
  1166. X                        }
  1167. X                    } else {
  1168. X                        if (create_subdir) {
  1169. X                            sprintf (file, "%s/%s.%s%s", save[i].archive, save[i].archive, LONG_PATH_PATCH, save[i].patch);
  1170. X                        } else {
  1171. X                            sprintf (file, "%s.%s%s", save[i].archive, LONG_PATH_PATCH, save[i].patch);
  1172. X                        }
  1173. X                    }
  1174. X                } else {
  1175. X                    if (! save_separate || save_num == 1) {
  1176. X                        sprintf (file, "%s", save[i].file);
  1177. X                    } else {
  1178. X                        sprintf (file, "%s.%02d", save[i].file, i+1);
  1179. X                    }
  1180. X                }
  1181. X                return (file);
  1182. X            }
  1183. X        }
  1184. X    }
  1185. X    return ((char *) 0);
  1186. X}
  1187. X
  1188. X
  1189. Xchar *get_last_savefile ()
  1190. X{
  1191. X    char *file;
  1192. X    int i;
  1193. X    
  1194. X    for (i=save_num-1 ; i >= 0 ; i--) {
  1195. X        if (save[i].saved) {
  1196. X            file = (char *) my_malloc (LEN);
  1197. X            if (save[i].is_mailbox) {
  1198. X                sprintf (file, "%s/%s", save[i].dir, save[i].file);
  1199. X                return (file);
  1200. X            } else {
  1201. X                if (save[i].archive && save_archive_name) {
  1202. X                    if (save[i].part) {
  1203. X                        if (create_subdir) {
  1204. X                            sprintf (file, "%s/%s.%s%s", save[i].archive, save[i].archive, LONG_PATH_PART, save[i].part);
  1205. X                        } else {
  1206. X                            sprintf (file, "%s.%s%s", save[i].archive, LONG_PATH_PART, save[i].part);
  1207. X                        }
  1208. X                    } else {
  1209. X                        if (create_subdir) {
  1210. X                            sprintf (file, "%s/%s.%s%s", save[i].archive, save[i].archive, LONG_PATH_PATCH, save[i].patch);
  1211. X                        } else {
  1212. X                            sprintf (file, "%s.%s%s", save[i].archive, LONG_PATH_PATCH, save[i].patch);
  1213. X                        }
  1214. X                    }
  1215. X                } else {
  1216. X                    if (! save_separate || save_num == 1) {
  1217. X                        sprintf (file, "%s", save[i].file);
  1218. X                    } else {
  1219. X                        sprintf (file, "%s.%02d", save[i].file, i+1);
  1220. X                    }
  1221. X                }
  1222. X                return (file);
  1223. X            }
  1224. X        }
  1225. X    }
  1226. X    return ((char *) 0);
  1227. X}
  1228. X
  1229. X
  1230. Xint post_process_files ()
  1231. X{
  1232. X    if (post_process && save_num && ! save[save_num-1].is_mailbox) {
  1233. X        wait_message (txt_post_processing);
  1234. X
  1235. X        switch (post_proc_type) {
  1236. X            case POST_PROC_SH:
  1237. X                post_process_sh ();
  1238. X                break;
  1239. X                
  1240. X            case POST_PROC_UUD:
  1241. X                post_process_uud (POST_PROC_UUD);
  1242. X                break;
  1243. X
  1244. X            case POST_PROC_UUD_ZOO:
  1245. X                post_process_uud (POST_PROC_UUD_ZOO);
  1246. X                break;
  1247. X
  1248. X            case POST_PROC_UUD_LZH:
  1249. X                post_process_uud (POST_PROC_UUD_LZH);
  1250. X                break;
  1251. X                
  1252. X            case POST_PROC_UUD_ARC:
  1253. X                post_process_uud (POST_PROC_UUD_ARC);
  1254. X                break;
  1255. X                
  1256. X            case POST_PROC_UUD_ZIP:
  1257. X                post_process_uud (POST_PROC_UUD_ZIP);
  1258. X                break;
  1259. X
  1260. X            case POST_PROC_PATCH:
  1261. X                post_process_patch ();
  1262. X                break;
  1263. X        }
  1264. X        info_message ("-- post processing completed --");
  1265. X        sleep (1);
  1266. X        return TRUE;
  1267. X    }
  1268. X    return FALSE;
  1269. X}
  1270. X
  1271. X
  1272. Xvoid post_process_uud (pp)
  1273. X    int pp;
  1274. X{
  1275. X    char s[LEN+1], t[LEN+1], u[LEN+1];
  1276. X    char buf[LEN+1], *file;
  1277. X    char file_out[LEN+1];
  1278. X    char file_out_dir[LEN+1];
  1279. X    FILE *fp_in, *fp_out;
  1280. X    int i, state = INITIAL;
  1281. X    int file_size = 0;
  1282. X    struct stat st;
  1283. X    
  1284. X    t[0] = '\0';
  1285. X    u[0] = '\0';
  1286. X
  1287. X    my_strncpy (file_out_dir, save_filename (0), LEN);
  1288. X    for (i=strlen(file_out_dir) ; i > 0 ; i--) {
  1289. X        if (file_out_dir[i] == '/') {
  1290. X            file_out_dir[i] = '\0';
  1291. X            break;
  1292. X        }
  1293. X    }
  1294. X
  1295. X    sprintf (file_out, "%s/tin.%05d", file_out_dir, getpid ());
  1296. X    
  1297. X    if ((fp_out = fopen (file_out, "a+")) == NULL) {
  1298. X        error_message (txt_cannot_open, file_out);
  1299. X    }
  1300. X
  1301. X
  1302. X    for (i=0 ; i < save_num ; i++) {
  1303. X        my_strncpy (buf, save_filename (i), LEN);
  1304. X/*
  1305. X        sprintf (buf, "%s%d", txt_post_processing, i);
  1306. X        wait_message (buf);
  1307. X*/
  1308. X        if ((fp_in = fopen (buf, "r")) != NULL) {
  1309. X            if (fgets (s, LEN, fp_in) == NULL) {
  1310. X                fclose (fp_in);
  1311. X                continue;
  1312. X            }
  1313. X            while (state != END) { 
  1314. X                switch (state) {
  1315. X                    case INITIAL:
  1316. X                        if (! strncmp ("begin", s, 5)) {
  1317. X                            state = MIDDLE;
  1318. X                            fprintf (fp_out, "%s", s);
  1319. X                        }
  1320. X                        break;
  1321. X
  1322. X                    case MIDDLE:
  1323. X                        if (s[0] == 'M') {
  1324. X                            fprintf (fp_out, "%s", s);
  1325. X                        } else if (strncmp("end", s, 3)) {
  1326. X                            state = OFF;
  1327. X                        } else { /* end */
  1328. X                            state = END;
  1329. X                            if (u[0] != 'M') {
  1330. X                                fprintf (fp_out, "%s", u);
  1331. X                            }
  1332. X                            if (t[0] != 'M') {
  1333. X                                fprintf (fp_out, "%s", t);
  1334. X                            }
  1335. X                            fprintf (fp_out, "%s\n", s);
  1336. X                        }
  1337. X                        break;
  1338. X
  1339. X                    case OFF:
  1340. X                        if ((s[0] == 'M') && (t[0] == 'M') && (u[0] == 'M')) {
  1341. X                            fprintf (fp_out, "%s", u);
  1342. X                            fprintf (fp_out, "%s", t);
  1343. X                            fprintf (fp_out, "%s", s);
  1344. X                            state = MIDDLE;
  1345. X                        } else if (! strncmp ("end", s, 3)) {
  1346. X                            state = END;
  1347. X                            if (u[0] != 'M') {
  1348. X                                fprintf (fp_out, "%s", u);
  1349. X                            }
  1350. X                            if (t[0] != 'M') {
  1351. X                                fprintf (fp_out, "%s", t);
  1352. X                            }
  1353. X                            fprintf (fp_out, "%s\n", s);
  1354. X                        }
  1355. X                        break;
  1356. X
  1357. X                    case END:
  1358. X                        break;
  1359. X
  1360. X                    default:
  1361. X                        fprintf (stderr, "\r\nerror: ASSERT - default state\n");
  1362. X                        fclose (fp_in);
  1363. X                        fclose (fp_out);
  1364. X                        unlink (file_out);
  1365. X                        return;
  1366. X                }
  1367. X                strcpy (u,t);
  1368. X                strcpy (t,s);
  1369. X                /*
  1370. X                 *  read next line & if error goto next file in save array
  1371. X                 */
  1372. X                if (fgets (s, LEN, fp_in) == NULL) {
  1373. X                    break;
  1374. X                }
  1375. X            }
  1376. X            fclose (fp_in);
  1377. X        }
  1378. X    }
  1379. X    fclose (fp_out);
  1380. X
  1381. X    /*
  1382. X     *  uudecode file
  1383. X     */
  1384. X    wait_message ("Uudecoding...");
  1385. X/*
  1386. X    printf ("\r\nUudecoding...\r\n"); 
  1387. X*/
  1388. X    
  1389. X    sprintf (buf, "cd %s; uudecode %s", file_out_dir, file_out); 
  1390. X    if (invoke_cmd (buf)) {
  1391. X        /*
  1392. X         *  sum file
  1393. X         */
  1394. X        if (file = get_archive_file (file_out_dir, "*")) { 
  1395. X            sprintf (buf, "%s %s", DEFAULT_SUM, file); 
  1396. X            printf ("\r\n\r\nChecksum of %s...\r\n\r\n", file); 
  1397. X            fflush (stdout);
  1398. X            if ((fp_in = popen (buf, "r")) == NULL) {
  1399. X                printf ("Cannot execute %s\r\n", buf); 
  1400. X                fflush (stdout);
  1401. X            } else {
  1402. X                if (stat (file, &st) != -1) {
  1403. X                    file_size = (int) st.st_size;
  1404. X                }
  1405. X                if (fgets (buf, LEN, fp_in) != NULL) {
  1406. X                    buf[strlen (buf)-1] = '\0';
  1407. X                }
  1408. X                fclose (fp_in);
  1409. X                printf ("%s  %8d bytes\r\n", buf, file_size); 
  1410. X                fflush (stdout);
  1411. X            }
  1412. X            free (file);
  1413. X            file = (char *) 0;
  1414. X            delete_processed_files ();
  1415. X        }
  1416. X    }
  1417. X
  1418. X    if (pp > POST_PROC_UUD) {
  1419. X        sprintf (buf, "*.%s", archiver[pp].ext); 
  1420. X        if (file = get_archive_file (file_out_dir, buf)) {
  1421. X#ifdef EXTRACT_ARCHIVED_FILES
  1422. X            sprintf (buf, "cd %s; %s %s %s", file_out_dir,
  1423. X                archiver[pp].name, archiver[pp].list, file);
  1424. X            printf ("\r\n\r\nListing %s archive...\r\n", file); 
  1425. X#else
  1426. X            sprintf (buf, "cd %s; %s %s %s", file_out_dir,
  1427. X                archiver[pp].name, archiver[pp].extract, file);
  1428. X            printf ("\r\n\r\nExtracting %s archive...\r\n", file); 
  1429. X#endif
  1430. X            fflush (stdout);
  1431. X            free (file);
  1432. X            file = NULL;
  1433. X            if (! invoke_cmd (buf)) {
  1434. X                error_message ("post processing failed", NULL);
  1435. X            } else {
  1436. X                continue_prompt ();
  1437. X            }
  1438. X        }
  1439. X    }
  1440. X
  1441. X    unlink (file_out);
  1442. X}
  1443. X
  1444. X/*
  1445. X *  Unpack /bin/sh archives
  1446. X */
  1447. Xvoid post_process_sh ()
  1448. X{
  1449. X    char buf[LEN+1];
  1450. X    char file_in[LEN+1];
  1451. X    char file_out[LEN+1];
  1452. X    char file_out_dir[LEN+1];
  1453. X    char *ptr1, *ptr2;
  1454. X    FILE *fp_in, *fp_out;
  1455. X    int found_header;
  1456. X    int i, j;
  1457. X    int lineno;
  1458. X    char sh_pattern_1[16];
  1459. X    char sh_pattern_2[16];
  1460. X
  1461. X    strcpy (sh_pattern_1, "#! /bin/sh");
  1462. X    strcpy (sh_pattern_2, "#!/bin/sh");
  1463. X
  1464. X    my_strncpy (file_out_dir, save_filename (0), LEN);
  1465. X    for (i=strlen(file_out_dir) ; i > 0 ; i--) {
  1466. X        if (file_out_dir[i] == '/') {
  1467. X            file_out_dir[i] = '\0';
  1468. X            break;
  1469. X        }
  1470. X    }
  1471. X
  1472. X    sprintf (file_out, "%s/tin.%05d", file_out_dir, getpid ());
  1473. X
  1474. X    for (j=0 ; j < save_num ; j++) {
  1475. X        my_strncpy (file_in, save_filename (j), LEN);
  1476. X
  1477. X        printf ("\r\nExtracting %s...\r\n", file_in);
  1478. X        fflush (stdout);
  1479. X
  1480. X        found_header = FALSE;
  1481. X        lineno = 1;
  1482. X        
  1483. X        if ((fp_out = fopen (file_out, "w")) != NULL) {
  1484. X            if ((fp_in = fopen (file_in, "r")) != NULL) {
  1485. X                while (! feof (fp_in)) {
  1486. X                    if (fgets (buf, LEN, fp_in)) {
  1487. X                        /*
  1488. X                         *  find #!/bin/sh or #! /bin/sh pattern
  1489. X                         */
  1490. X                        if (!found_header) {
  1491. X                            ptr1 = sh_pattern_1;
  1492. X                            ptr2 = sh_pattern_2;
  1493. X                            if (str_str (buf, ptr1) != 0 ||
  1494. X                                str_str (buf, ptr2) != 0) {
  1495. X/*
  1496. Xprintf ("\r\n[%16s] [%04d] FOUND #/bin/sh\r\n", file_in, lineno); 
  1497. X*/
  1498. X                                found_header = TRUE;
  1499. X                            }
  1500. X                        }
  1501. X                    
  1502. X                        /*
  1503. X                         *  Write to temp file
  1504. X                         */
  1505. X                        if (found_header) {
  1506. X                            fputs (buf, fp_out);
  1507. X                        }
  1508. X                        lineno++;
  1509. X                    }
  1510. X                }
  1511. X                fclose (fp_in);
  1512. X            }
  1513. X            fclose (fp_out);
  1514. X
  1515. X            sprintf (buf, "cd %s; sh %s", file_out_dir, file_out); 
  1516. X            printf ("\r\n");
  1517. X            fflush (stdout);
  1518. X            Raw (FALSE);
  1519. X            invoke_cmd (buf);
  1520. X            Raw (TRUE);
  1521. X            unlink (file_out);
  1522. X        }
  1523. X    }
  1524. X    delete_processed_files ();
  1525. X}
  1526. X
  1527. X
  1528. Xchar *get_archive_file (dir, ext)
  1529. X    char *dir;
  1530. X    char *ext;
  1531. X{
  1532. X    char buf[LEN+1];
  1533. X    char *file = NULL;
  1534. X    FILE *fp;
  1535. X    
  1536. X    sprintf (buf, "ls -t %s/%s", dir, ext);
  1537. X
  1538. X    if ((fp = popen (buf, "r")) == NULL) {
  1539. X        return NULL;
  1540. X    }
  1541. X
  1542. X    if (fgets (buf, LEN, fp) != NULL) {
  1543. X        file = str_dup (buf);
  1544. X        file[strlen (file)-1] = '\0';
  1545. X    }
  1546. X    
  1547. X    fclose (fp);
  1548. X
  1549. X    return (file);
  1550. X}
  1551. X
  1552. X
  1553. Xvoid delete_processed_files ()
  1554. X{
  1555. X    int i;
  1556. X
  1557. X    printf ("\r\n");
  1558. X    fflush (stdout);
  1559. X    
  1560. X    if (prompt_yn (LINES, "Delete saved files that have been post processed? (y/n): ", 'y')) {
  1561. X        wait_message (txt_deleting);
  1562. X
  1563. X        for (i=0 ; i < save_num ; i++) {
  1564. X            unlink (save_filename (i));
  1565. X        }
  1566. X    }
  1567. X}
  1568. X
  1569. X
  1570. Xvoid post_process_patch ()
  1571. X{
  1572. X}
  1573. SHAR_EOF
  1574. $TOUCH -am 0823151891 save.c &&
  1575. chmod 0600 save.c ||
  1576. echo "restore of save.c failed"
  1577. set `wc -c save.c`;Wc_c=$1
  1578. if test "$Wc_c" != "22644"; then
  1579.     echo original size 22644, current size $Wc_c
  1580. fi
  1581. # ============= screen.c ==============
  1582. echo "x - extracting screen.c (Text)"
  1583. sed 's/^X//' << 'SHAR_EOF' > screen.c &&
  1584. X/*
  1585. X *  Project   : tin - a visual threaded usenet newsreader
  1586. X *  Module    : screen.c
  1587. X *  Author    : R.Skrenta / I.Lea
  1588. X *  Created   : 01-04-91
  1589. X *  Updated   : 10-08-91
  1590. X *  Release   : 1.0
  1591. X *  Notes     :
  1592. X *  Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
  1593. X *                You may  freely  copy or  redistribute  this software,
  1594. X *              so  long as there is no profit made from its use, sale
  1595. X *              trade or  reproduction.  You may not change this copy-
  1596. X *              right notice, and it must be included in any copy made
  1597. X */
  1598. X
  1599. X#include    "tin.h"
  1600. X
  1601. Xextern int errno;
  1602. X
  1603. Xchar msg[LEN+1];
  1604. Xstruct screen_t *screen;
  1605. X
  1606. X
  1607. Xvoid info_message (msg)
  1608. X    char *msg;
  1609. X{
  1610. X    clear_message();      /* Clear any old messages hanging around */
  1611. X    center_line(LINES, msg);  /* center the message at screen bottom  */
  1612. X    MoveCursor(LINES, 0);
  1613. X}
  1614. X
  1615. X
  1616. Xvoid wait_message (msg)
  1617. X    char *msg;
  1618. X{
  1619. X    clear_message();      /* Clear any old messages hanging around */
  1620. X    printf (msg);
  1621. X    fflush (stdout);
  1622. X}
  1623. X
  1624. X
  1625. Xvoid error_message (template, msg)
  1626. X    char *template;
  1627. X    char *msg;
  1628. X{
  1629. X    errno = 0;
  1630. X
  1631. X    if (! update) {
  1632. X        clear_message();      /* Clear any old messages hanging around */
  1633. X    }
  1634. X    fprintf (stderr, template, msg);
  1635. X    fflush (stderr);
  1636. X
  1637. X    /*    perror (""); */
  1638. X
  1639. X    if (! update) {
  1640. X        MoveCursor(LINES, 0);
  1641. X    }
  1642. X    sleep (1);
  1643. X}
  1644. X
  1645. X
  1646. Xvoid clear_message ()
  1647. X{
  1648. X    MoveCursor(LINES, 0);
  1649. X    CleartoEOLN();
  1650. X}
  1651. X
  1652. X
  1653. Xvoid center_line (line, str)
  1654. X    int line;
  1655. X    char *str;
  1656. X{
  1657. X    int pos;
  1658. X
  1659. X    pos = (COLS - (int) strlen (str)) / 2;
  1660. X    MoveCursor (line, pos);
  1661. X    printf ("%s", str);
  1662. X    fflush (stdout);
  1663. X}
  1664. X
  1665. X
  1666. Xvoid draw_arrow (line)
  1667. X    int line;
  1668. X{
  1669. X    MoveCursor (line, 0);
  1670. X
  1671. X    if (draw_arrow_mark) {
  1672. X        printf ("->");
  1673. X    } else {
  1674. X        StartInverse ();
  1675. X        printf ("%s", screen[line-INDEX_TOP].col);
  1676. X        EndInverse ();
  1677. X    }
  1678. X
  1679. X    fflush (stdout);
  1680. X    MoveCursor (LINES, 0);
  1681. X}
  1682. X
  1683. X
  1684. Xvoid erase_arrow (line)
  1685. X    int line;
  1686. X{
  1687. X    MoveCursor (line, 0);
  1688. X
  1689. X    if (draw_arrow_mark) {
  1690. X        printf ("  ");
  1691. X    } else {
  1692. X        printf ("%s", screen[line-INDEX_TOP].col);
  1693. X    }
  1694. X
  1695. X    fflush (stdout);
  1696. X}
  1697. SHAR_EOF
  1698. $TOUCH -am 0819091091 screen.c &&
  1699. chmod 0600 screen.c ||
  1700. echo "restore of screen.c failed"
  1701. set `wc -c screen.c`;Wc_c=$1
  1702. if test "$Wc_c" != "1936"; then
  1703.     echo original size 1936, current size $Wc_c
  1704. fi
  1705. # ============= search.c ==============
  1706. echo "x - extracting search.c (Text)"
  1707. sed 's/^X//' << 'SHAR_EOF' > search.c &&
  1708. X/*
  1709. X *  Project   : tin - a visual threaded usenet newsreader
  1710. X *  Module    : search.c
  1711. X *  Author    : R.Skrenta / I.Lea
  1712. X *  Created   : 01-04-91
  1713. X *  Updated   : 22-08-91
  1714. X *  Release   : 1.0
  1715. X *  Notes     :
  1716. X *  Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
  1717. X *                You may  freely  copy or  redistribute  this software,
  1718. X *              so  long as there is no profit made from its use, sale
  1719. X *              trade or  reproduction.  You may not change this copy-
  1720. X *              right notice, and it must be included in any copy made
  1721. X */
  1722. X
  1723. X#include    "tin.h"
  1724. X
  1725. Xextern FILE *note_fp;
  1726. Xextern int cur_groupnum;
  1727. Xextern int first_group_on_screen;
  1728. Xextern int last_group_on_screen;
  1729. Xextern int first_subj_on_screen;
  1730. Xextern int last_subj_on_screen;
  1731. Xextern int index_point;
  1732. Xextern int note_line;
  1733. Xextern int note_page;
  1734. Xextern int note_end;
  1735. Xextern long note_mark[MAX_PAGES];
  1736. X
  1737. X/*
  1738. X * last search patterns
  1739. X */
  1740. X
  1741. Xchar author_search_string[LEN+1];
  1742. Xchar group_search_string[LEN+1];
  1743. Xchar subject_search_string[LEN+1];
  1744. Xchar art_search_string[LEN+1];
  1745. X
  1746. X
  1747. X/*
  1748. X *  group.c & page.c
  1749. X */
  1750. Xint search_author (current_art, forward)
  1751. X    int current_art;
  1752. X    int forward;
  1753. X{
  1754. X    char buf[LEN+1];
  1755. X    char buf2[LEN+1];
  1756. X    int i;
  1757. X
  1758. X    clear_message();
  1759. X
  1760. X    if (forward) {
  1761. X        sprintf (buf2, txt_author_search_forwards, author_search_string);
  1762. X    } else {
  1763. X        sprintf (buf2, txt_author_search_backwards, author_search_string);
  1764. X    }
  1765. X
  1766. X    
  1767. X    if (! parse_string (buf2, buf)) {
  1768. X        return -1;
  1769. X    }
  1770. X    
  1771. X    if (strlen (buf)) {
  1772. X        strcpy (author_search_string, buf);
  1773. X    } else {
  1774. X        if (author_search_string[0]) {
  1775. X            strcpy (buf, author_search_string);
  1776. X        } else {
  1777. X            info_message (txt_no_search_string);    
  1778. X            return -1;
  1779. X        }
  1780. X    }
  1781. X
  1782. X    make_lower(author_search_string, buf);
  1783. X
  1784. X    i = current_art;
  1785. X
  1786. X    do {
  1787. X        if (forward) {
  1788. X            i = next_response(i);
  1789. X            if (i < 0)
  1790. X                i = 0;
  1791. X        } else {
  1792. X            i = prev_response(i);
  1793. X            if (i < 0)
  1794. X                i = top - 1;
  1795. X        }
  1796. X
  1797. X        make_lower(arts[i].from, buf2);
  1798. X        if (str_str (buf2, buf) != 0)
  1799. X            return i;
  1800. X    } while (i != current_art);
  1801. X
  1802. X    info_message(txt_no_match);
  1803. X    return -1;
  1804. X}
  1805. X
  1806. X/*
  1807. X * select.c
  1808. X */
  1809. Xvoid search_group (forward)
  1810. X    int forward;
  1811. X{
  1812. X    char buf[LEN+1];
  1813. X    char buf2[LEN+1];
  1814. X    int i;
  1815. X
  1816. X    clear_message();
  1817. X
  1818. X    if (forward) {
  1819. X        sprintf (buf2, txt_search_forwards, group_search_string);
  1820. X    } else {
  1821. X        sprintf (buf2, txt_search_backwards, group_search_string);
  1822. X    }
  1823. X
  1824. X    if (! parse_string (buf2, buf)) {
  1825. X        return;
  1826. X    }
  1827. X
  1828. X    if (strlen (buf)) {
  1829. X        strcpy (group_search_string, buf);
  1830. X    } else {
  1831. X        if (group_search_string[0]) {
  1832. X            strcpy (buf, group_search_string);
  1833. X        } else {
  1834. X            info_message (txt_no_search_string);    
  1835. X            return;
  1836. X        }
  1837. X    }
  1838. X
  1839. X    i = cur_groupnum;
  1840. X
  1841. X    make_lower(group_search_string, buf);
  1842. X
  1843. X    do {
  1844. X        if (forward)
  1845. X            i++;
  1846. X        else
  1847. X            i--;
  1848. X
  1849. X        if (i >= local_top)
  1850. X            i = 0;
  1851. X        if (i < 0)
  1852. X            i = local_top - 1;
  1853. X
  1854. X        make_lower(active[my_group[i]].name, buf2);
  1855. X        if (str_str (buf2, buf) != 0) {
  1856. X            if (i >= first_group_on_screen
  1857. X            &&  i < last_group_on_screen) {
  1858. X                erase_group_arrow();
  1859. X                cur_groupnum = i;
  1860. X                draw_group_arrow();
  1861. X            } else {
  1862. X                cur_groupnum = i;
  1863. X                group_selection_page();
  1864. X            }
  1865. X            return;
  1866. X        }
  1867. X    } while (i != cur_groupnum);
  1868. X
  1869. X    info_message(txt_no_match);
  1870. X}
  1871. X
  1872. X/*
  1873. X * group.c
  1874. X */
  1875. X
  1876. Xvoid search_subject (forward, group)
  1877. X    int forward;
  1878. X    char *group;
  1879. X{
  1880. X    char buf[LEN+1];
  1881. X    char buf2[LEN+1];
  1882. X    int i, j;
  1883. X
  1884. X    if (index_point < 0) {
  1885. X        info_message (txt_no_arts);
  1886. X        return;
  1887. X    }
  1888. X    
  1889. X    clear_message();
  1890. X
  1891. X    if (forward) {
  1892. X        sprintf (buf2, txt_search_forwards, subject_search_string);
  1893. X    } else {
  1894. X        sprintf (buf2, txt_search_backwards, subject_search_string);
  1895. X    }
  1896. X
  1897. X    if (! parse_string (buf2, buf)) {
  1898. X        return;
  1899. X    }
  1900. X
  1901. X    if (strlen (buf)) {
  1902. X        strcpy (subject_search_string, buf);
  1903. X    } else {
  1904. X        if (subject_search_string[0]) {
  1905. X            strcpy (buf, subject_search_string);
  1906. X        } else {
  1907. X            info_message (txt_no_search_string);    
  1908. X            return;
  1909. X        }
  1910. X    }
  1911. X
  1912. X    i = index_point;
  1913. X
  1914. X    make_lower(subject_search_string, buf);
  1915. X
  1916. X    do {
  1917. X        if (forward)
  1918. X            i++;
  1919. X        else
  1920. X            i--;
  1921. X
  1922. X        if (i >= top_base)
  1923. X            i = 0;
  1924. X        if (i < 0)
  1925. X            i = top_base - 1;
  1926. X
  1927. X        j = base[i];
  1928. X        make_lower(arts[j].subject, buf2);
  1929. X        if (str_str (buf2, buf) != 0) {
  1930. X            if (i >= first_subj_on_screen
  1931. X                &&  i < last_subj_on_screen) {
  1932. X                erase_subject_arrow();
  1933. X                index_point = i;
  1934. X                draw_subject_arrow();
  1935. X            } else {
  1936. X                index_point = i;
  1937. X                show_group_page(group);
  1938. X            }
  1939. X            return;
  1940. X        }
  1941. X    } while (i != index_point);
  1942. X
  1943. X    info_message(txt_no_match);
  1944. X}
  1945. X
  1946. X/*
  1947. X *  page.c (search article body)
  1948. X */
  1949. X
  1950. Xint search_article (forward)
  1951. X    int forward;
  1952. X{
  1953. X    char buf[LEN+1];
  1954. X    char buf2[LEN+1];
  1955. X    char string[LEN+1];
  1956. X    char pattern[LEN+1];
  1957. X    char *p, *q;
  1958. X    int ctrl_L;
  1959. X    int i, j;
  1960. X    int orig_note_end;
  1961. X    int orig_note_page;
  1962. X
  1963. X    clear_message ();
  1964. X
  1965. X    if (forward) {
  1966. X        sprintf (buf2, txt_search_forwards, art_search_string);
  1967. X    } else {
  1968. X        sprintf (buf2, txt_search_backwards, art_search_string);
  1969. X    }
  1970. X
  1971. X    if (! parse_string (buf2, buf)) {
  1972. X        return FALSE;
  1973. X    }
  1974. X
  1975. X    if (strlen (buf)) {
  1976. X        strcpy (art_search_string, buf);
  1977. X    } else {
  1978. X        if (art_search_string[0]) {
  1979. X            strcpy (buf, art_search_string);
  1980. X        } else {
  1981. X            info_message (txt_no_search_string);    
  1982. X            return FALSE;
  1983. X        }
  1984. X    }
  1985. X
  1986. X    make_lower (art_search_string, pattern);
  1987. X    /*
  1988. X     *  save current position in article
  1989. X     */
  1990. X    orig_note_end = note_end;
  1991. X    orig_note_page = note_page;
  1992. X
  1993. X    wait_message (txt_searching);
  1994. X    
  1995. X    while (! note_end) {
  1996. X        note_line = 1;
  1997. X        ctrl_L = FALSE;
  1998. X
  1999. X        if (note_page == 0) {
  2000. X            note_line += 4;
  2001. X        } else {
  2002. X            note_line += 2;
  2003. X        }
  2004. X        while (note_line < LINES) {
  2005. X            if (fgets(buf, LEN, note_fp) == NULL) {
  2006. X                note_end = TRUE;
  2007. X                break;
  2008. X            }
  2009. X            buf[LEN-1] = '\0';
  2010. X            for (p = buf, q = buf2;    *p && *p != '\n' && q<&buf2[LEN]; p++) {
  2011. X                if (*p == '\b' && q > buf2) {
  2012. X                    q--;
  2013. X                } else if (*p == 12) {        /* ^L */
  2014. X                    *q++ = '^';
  2015. X                    *q++ = 'L';
  2016. X                    ctrl_L = TRUE;
  2017. X                } else if (*p == '\t') {
  2018. X                    i = q - buf2;
  2019. X                    j = (i|7) + 1;
  2020. X
  2021. X                    while (i++ < j) {
  2022. X                        *q++ = ' ';
  2023. X                    }
  2024. X                } else if (((*p) & 0x7F) < 32) {
  2025. X                    *q++ = '^';
  2026. X                    *q++ = ((*p) & 0x7F) + '@';
  2027. X                } else {
  2028. X                    *q++ = *p;
  2029. X                }
  2030. X            }
  2031. X            *q = '\0';
  2032. X
  2033. X            make_lower(buf2, string);
  2034. X
  2035. X            if (str_str (string, pattern) != 0) {
  2036. X                fseek (note_fp, note_mark[note_page], 0);
  2037. X                return TRUE;
  2038. X            }
  2039. X
  2040. X            note_line += ((int) strlen(buf2) / COLS) + 1;
  2041. X
  2042. X            if (ctrl_L) {
  2043. X                break;
  2044. X            }
  2045. X        }
  2046. X        if (! note_end) {
  2047. X            note_mark[++note_page] = ftell(note_fp);
  2048. X        }
  2049. X    }
  2050. X
  2051. X    note_end = orig_note_end;
  2052. X    note_page = orig_note_page;
  2053. X    fseek (note_fp, note_mark[note_page], 0);
  2054. X    info_message (txt_no_match);
  2055. X    return FALSE;
  2056. X}
  2057. X
  2058. X/*
  2059. X * ANSI C strstr () - Use Boyer-Moore algorithm. Downloaded from net.
  2060. X */
  2061. Xchar *str_str (text, pattern)
  2062. X    char *text;
  2063. X    char *pattern;
  2064. X{
  2065. X    register unsigned char *p, *t;
  2066. X    register int i, p1, j, *delta;
  2067. X    int deltaspace[256];
  2068. X    int patlen;
  2069. X    int textlen;
  2070. X
  2071. X    textlen= strlen (text);
  2072. X    patlen = strlen (pattern);
  2073. X
  2074. X    /* algorithm fails if pattern is empty */
  2075. X    if ((p1 = patlen) == 0)
  2076. X        return (text);
  2077. X
  2078. X    /* code below fails (whenever i is unsigned) if pattern too long */
  2079. X    if (p1 > textlen)
  2080. X        return (NULL);
  2081. X
  2082. X    /* set up deltas */
  2083. X    delta = deltaspace;
  2084. X    for (i = 0; i <= 255; i++)
  2085. X        delta[i] = p1;
  2086. X    for (p = (unsigned char *) pattern, i = p1; --i > 0;)
  2087. X        delta[*p++] = i;
  2088. X
  2089. X    /*
  2090. X     * From now on, we want patlen - 1.
  2091. X     * In the loop below, p points to the end of the pattern,
  2092. X     * t points to the end of the text to be tested against the
  2093. X     * pattern, and i counts the amount of text remaining, not
  2094. X     * including the part to be tested.
  2095. X     */
  2096. X    p1--;
  2097. X    p = (unsigned char *) pattern + p1;
  2098. X    t = (unsigned char *) text + p1;
  2099. X    i = textlen - patlen;
  2100. X    for (;;) {
  2101. X        if (*p == *t && memcmp((p - p1), (t - p1), p1) == 0)
  2102. X            return ((char *)t - p1);
  2103. X        j = delta[*t];
  2104. X        if (i < j)
  2105. X            break;
  2106. X        i -= j;
  2107. X        t += j;
  2108. X    }
  2109. X    return (NULL);
  2110. X}
  2111. X
  2112. X
  2113. Xvoid make_lower (s, t)
  2114. X    char *s;
  2115. X    char *t;
  2116. X{
  2117. X
  2118. X    while (*s) {
  2119. X        if (isupper(*s))
  2120. X            *t = tolower(*s);
  2121. X        else
  2122. X            *t = *s;
  2123. X        s++;
  2124. X        t++;
  2125. X    }
  2126. X    *t = 0;
  2127. X}
  2128. SHAR_EOF
  2129. $TOUCH -am 0822103791 search.c &&
  2130. chmod 0600 search.c ||
  2131. echo "restore of search.c failed"
  2132. set `wc -c search.c`;Wc_c=$1
  2133. if test "$Wc_c" != "7656"; then
  2134.     echo original size 7656, current size $Wc_c
  2135. fi
  2136. # ============= select.c ==============
  2137. echo "x - extracting select.c (Text)"
  2138. sed 's/^X//' << 'SHAR_EOF' > select.c &&
  2139. X/*
  2140. X *  Project   : tin - a visual threaded usenet newsreader
  2141. X *  Module    : select.c
  2142. X *  Author    : R.Skrenta / I.Lea
  2143. X *  Created   : 01-04-91
  2144. X *  Updated   : 20-08-91
  2145. X *  Release   : 1.0
  2146. X *  Notes     :
  2147. X *  Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
  2148. X *                You may  freely  copy or  redistribute  this software,
  2149. X *              so  long as there is no profit made from its use, sale
  2150. X *              trade or  reproduction.  You may not change this copy-
  2151. X *              right notice, and it must be included in any copy made
  2152. X */
  2153. X
  2154. X#include    "tin.h"
  2155. X
  2156. X
  2157. Xint first_group_on_screen;
  2158. Xint last_group_on_screen;
  2159. Xint cur_groupnum = 0;
  2160. Xint reread_active_file = TRUE;
  2161. Xextern int index_point;
  2162. Xint space_mode;
  2163. Xextern char cvers[LEN+1];
  2164. X
  2165. X
  2166. X#ifdef SIGTSTP
  2167. Xvoid select_susp (sig)
  2168. X    int sig;
  2169. X{
  2170. X
  2171. X    Raw(FALSE);
  2172. X    putchar('\n');
  2173. X    signal(SIGTSTP, SIG_DFL);
  2174. X#ifdef BSD
  2175. X    sigsetmask(sigblock(0) & ~(1 << (SIGTSTP -1)));
  2176. X#endif
  2177. X    kill(0, SIGTSTP);
  2178. X
  2179. X    signal(SIGTSTP, select_susp);
  2180. X
  2181. X    if (! update) {
  2182. X        Raw(TRUE);
  2183. X    }
  2184. X
  2185. X#ifndef USE_CLEARSCREEN
  2186. X    ClearScreen ();
  2187. X#endif
  2188. X    mail_setup();
  2189. X    group_selection_page();
  2190. X}
  2191. X#endif
  2192. X
  2193. X
  2194. Xvoid selection_index()
  2195. X{
  2196. X    char ch;
  2197. X    int i, n;
  2198. X    int subscribe_num;
  2199. X    char buf[LEN+1];
  2200. X
  2201. X    group_selection_page ();        /* display group selection page */
  2202. X
  2203. X    while (1) {
  2204. X        ch = ReadCh();
  2205. X
  2206. X        if (ch > '0' && ch <= '9') {
  2207. X            prompt_group_num(ch);
  2208. X        } else switch (ch) {
  2209. X            case '!':
  2210. X                shell_escape();
  2211. X                group_selection_page();
  2212. X                break;
  2213. X
  2214. X            case '$':    /* show last page of groups */
  2215. Xend_of_list:            
  2216. X                cur_groupnum = local_top - 1;
  2217. X                group_selection_page();
  2218. X                break;
  2219. X
  2220. X            case '/':    /* search forward */
  2221. X            case '?':    /* search backward */
  2222. X                i = (ch == '/');
  2223. X                search_group (i);
  2224. SHAR_EOF
  2225. echo "End of tin part 6"
  2226. echo "File select.c is continued in part 7"
  2227. echo "7" > shar3_seq_.tmp
  2228. exit 0
  2229.  
  2230. --
  2231. NAME   Iain Lea
  2232. EMAIL  norisc!iain@estevax.UUCP  ...!unido!estevax!norisc!iain
  2233. SNAIL  Siemens AG, AUT 922C, Postfach 4848, Nuernberg, Germany
  2234. PHONE  +49-911-895-3853, +49-911-895-3877, +49-911-331963
  2235.