home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume23 / tin / part07 < prev    next >
Text File  |  1991-09-25  |  51KB  |  2,230 lines

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