home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / tin / part05 < prev    next >
Encoding:
Text File  |  1992-03-27  |  50.4 KB  |  2,146 lines

  1. Newsgroups: comp.sources.misc
  2. From: iain%anl433.uucp@germany.eu.net (Iain J. Lea)
  3. Subject:  v29i023:  tin - threaded full screen newsreader v1.1P1, Part05/12
  4. Message-ID: <1992Mar27.033145.2338@sparky.imd.sterling.com>
  5. X-Md4-Signature: 40b631f0902878291c8bb52f24069683
  6. Date: Fri, 27 Mar 1992 03:31:45 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: iain%anl433.uucp@germany.eu.net (Iain J. Lea)
  10. Posting-number: Volume 29, Issue 23
  11. Archive-name: tin/part05
  12. Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
  13. Supersedes: tin: Volume 28, Issue 45-55
  14.  
  15. #!/bin/sh
  16. # this is tin.shar.05 (part 5 of tin1.1)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file group.c continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 5; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping group.c'
  34. else
  35. echo 'x - continuing file group.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'group.c' &&
  37. X                    break;
  38. X                }
  39. X                index_point = show_page (this_resp, group, group_path);
  40. X                if (index_point < 0) {
  41. X                    space_mode = FALSE;
  42. X                    goto group_done;
  43. X                }
  44. X                clear_note_area ();
  45. X                show_group_page (group);
  46. X                break;
  47. X
  48. X            case '|':    /* pipe article/thread/tagged arts to command */
  49. X                if (index_point >= 0) {
  50. X                    set_real_uid_gid ();
  51. X                    feed_articles (FEED_PIPE, GROUP_LEVEL, "Pipe",
  52. X                        (int) base[index_point], group_path);
  53. X                    set_tin_uid_gid ();
  54. X                }
  55. X                break;
  56. X
  57. X            case '/':    /* forward/backward search */
  58. X            case '?':
  59. X                i = (ch == '/');
  60. X                search_subject (i, group);
  61. X                break;
  62. X
  63. X            case '\r':
  64. X            case '\n':    /* read current basenote */
  65. X                if (index_point < 0) {
  66. X                    info_message(txt_no_arts);
  67. X                    break;
  68. X                }
  69. X                i = (int) base[index_point];
  70. X                index_point = show_page (i, group, group_path);
  71. X                if (index_point < 0) {
  72. X                    space_mode = FALSE;
  73. X                    goto group_done;
  74. X                }
  75. X                clear_note_area ();
  76. X                show_group_page (group);
  77. X                break;
  78. X
  79. X            case '\t':
  80. X                 space_mode = TRUE;
  81. X
  82. X                if (index_point < 0
  83. X                || (n=next_unread((int) base[index_point]))<0) {
  84. X                    for (i = cur_groupnum+1 ; i < group_top ; i++)
  85. X                        if (unread[i] > 0)
  86. X                            break;
  87. X                    if (i >= group_top)
  88. X                        goto group_done;
  89. X
  90. X                    cur_groupnum = i;
  91. X                    index_point = -3;
  92. X                    goto group_done;
  93. X                }
  94. X                index_point = show_page(n, group, group_path);
  95. X                if (index_point < 0)
  96. X                    goto group_done;
  97. X                clear_note_area ();
  98. X                show_group_page(group);
  99. X                break;
  100. X    
  101. X            case ' ':            /* page down */
  102. X            case ctrl('D'):        /* vi style */
  103. X            case ctrl('V'):        /* emacs style */
  104. group_page_down:
  105. X                if (! top_base || index_point == top_base - 1)
  106. X                    break;
  107. X
  108. X                erase_subject_arrow ();
  109. X                scroll_lines = (full_page_scroll ? NOTESLINES : NOTESLINES / 2);
  110. X                index_point = ((index_point + scroll_lines) / scroll_lines) * scroll_lines;
  111. X                if (index_point >= top_base) {
  112. X                    index_point = (top_base / scroll_lines) * scroll_lines;
  113. X                    if (index_point < top_base - 1) {
  114. X                        index_point = top_base - 1;
  115. X                    }
  116. X                }
  117. X                if (index_point < first_subj_on_screen
  118. X                || index_point >= last_subj_on_screen)
  119. X                    show_group_page (group);
  120. X                else
  121. X                    draw_subject_arrow ();
  122. X                break;
  123. X
  124. X            case ctrl('K'):        /* kill article */
  125. X                 if (index_point < 0) {
  126. X                     info_message (txt_no_arts);
  127. X                    break;
  128. X                }
  129. X                if (kill_articles) {
  130. X                    old_top = top;
  131. X                    n = (int) base[index_point];
  132. X                    old_artnum = arts[n].artnum;
  133. X                    if (kill_art_menu (group, (int) base[index_point])) {
  134. X                        kill_any_articles (group);
  135. X                        reload_index_file (group, TRUE);
  136. X                        index_point = find_new_pos (old_top, old_artnum, index_point);
  137. X                    }
  138. X                    show_group_page (group);
  139. X                } else {
  140. X                    info_message (txt_switch_on_kill_art_menu);
  141. X                }
  142. X                break;
  143. X
  144. X            case ctrl('L'):        /* redraw screen */
  145. X            case ctrl('R'):
  146. X            case ctrl('W'):
  147. #ifndef USE_CLEARSCREEN
  148. X                ClearScreen ();
  149. #endif
  150. X                show_group_page (group);
  151. X                break;
  152. X
  153. X            case ctrl('N'):
  154. X            case 'j':        /* line down */
  155. group_down:
  156. X                if (! top_base || index_point + 1 >= top_base)
  157. X                    break;
  158. X
  159. X                if (index_point + 1 >= last_subj_on_screen) {
  160. #ifndef USE_CLEARSCREEN
  161. X                    erase_subject_arrow();
  162. #endif                    
  163. X                    index_point++;
  164. X                    show_group_page(group);
  165. X                } else {
  166. X                    erase_subject_arrow();
  167. X                    index_point++;
  168. X                    draw_subject_arrow();
  169. X                }
  170. X                break;
  171. X
  172. X            case ctrl('P'):
  173. X            case 'k':        /* line up */
  174. group_up:
  175. X                if (!top_base || !index_point)
  176. X                    break;
  177. X
  178. X                if (index_point <= first_subj_on_screen) {
  179. X                    index_point--;
  180. X                    show_group_page(group);
  181. X                } else {
  182. X                    erase_subject_arrow();
  183. X                    index_point--;
  184. X                    draw_subject_arrow();
  185. X                }
  186. X                break;
  187. X
  188. X            case ctrl('U'):        /* page up */
  189. X            case 'b':
  190. group_page_up:
  191. X                if (! top_base)
  192. X                    break;
  193. X
  194. #ifndef USE_CLEARSCREEN
  195. X                clear_message ();
  196. #endif
  197. X                erase_subject_arrow ();
  198. X                scroll_lines = (full_page_scroll ? NOTESLINES : NOTESLINES / 2);
  199. X                if ((n = index_point % scroll_lines) > 0) {
  200. X                    index_point = index_point - n;
  201. X                } else {
  202. X                    index_point = ((index_point - scroll_lines) / scroll_lines) * scroll_lines;
  203. X                }
  204. X                if (index_point < 0) {
  205. X                    index_point = 0;
  206. X                }
  207. X                if (index_point < first_subj_on_screen
  208. X                || index_point >= last_subj_on_screen)
  209. X                    show_group_page (group);
  210. X                else
  211. X                    draw_subject_arrow ();
  212. X                break;
  213. X
  214. X            case 'a':    /* author search forward */
  215. X            case 'A':    /* author search backward */
  216. X                if (index_point < 0) {
  217. X                    info_message (txt_no_arts);
  218. X                    break;
  219. X                }
  220. X
  221. X                i = (ch == 'a');
  222. X
  223. X                n = search_author(show_only_unread, (int) base[index_point], i);
  224. X                if (n < 0)
  225. X                    break;
  226. X
  227. X                index_point = show_page(n, group, group_path);
  228. X                if (index_point < 0) {
  229. X                    space_mode = FALSE;
  230. X                    goto group_done;
  231. X                }
  232. X                clear_note_area ();
  233. X                show_group_page (group);
  234. X                break;
  235. X
  236. X            case 'B':    /* bug/gripe/comment mailed to author */
  237. X                mail_bug_report ();
  238. #ifndef USE_CLEARSCREEN
  239. X                ClearScreen ();
  240. #endif
  241. X                show_group_page (group);
  242. X                break;
  243. X                
  244. X            case 'c':    /* catchup - mark all articles as read */
  245. X                if (prompt_yn (LINES, txt_mark_all_read, 'y')) {
  246. X                    for (n = 0; n < top; n++) {
  247. X                        arts[n].unread = ART_READ;
  248. X                    }
  249. X                    if (cur_groupnum + 1 < group_top) {
  250. X                        cur_groupnum++;
  251. X                    }
  252. X                    goto group_done;
  253. X                }
  254. X                break;
  255. X
  256. X            case 'd':    /* toggle display of subject & subj/author */
  257. X                if (show_author + 1 > SHOW_FROM_BOTH) {
  258. X                    show_author = SHOW_FROM_NONE;
  259. X                } else {
  260. X                    show_author++;
  261. X                }
  262. X                if (show_author == SHOW_FROM_BOTH) {
  263. X                    max_subj = (COLS / 2) - 2;
  264. X                } else {
  265. X                    max_subj = (COLS / 2) + 5;
  266. X                }
  267. X                max_from = (COLS - max_subj) - 17;
  268. X                show_group_page (group);
  269. X                break;
  270. X
  271. X            case 'g':    /* choose a new group by name */
  272. X                n = choose_new_group ();
  273. X                if (n >= 0 && n != cur_groupnum) {
  274. X                    cur_groupnum = n;
  275. X                    index_point = -3;
  276. X                    goto group_done;
  277. X                }
  278. X                break;
  279. X
  280. X            case 'h':    /* help */
  281. X                show_info_page (HELP_INFO, help_group, txt_index_page_com);
  282. X                show_group_page (group);
  283. X                break;
  284. X
  285. X            case 'I':    /* toggle inverse video */
  286. X                toggle_inverse_video ();
  287. X                show_group_page (group);
  288. X                break;
  289. X
  290. X            case 'K':    /* mark rest of thread as read */
  291. X                if (index_point < 0) {
  292. X                    info_message (txt_no_next_unread_art);
  293. X                    break;
  294. X                }
  295. X                if (new_responses (index_point)) {
  296. X                    n = (int) base[index_point];
  297. X                    for (i = (int) base[index_point]; i >= 0; i = arts[i].thread) {
  298. X                        arts[i].unread = ART_READ;
  299. X                    }    
  300. X                    if (arts[n].tagged) {
  301. X                        sprintf (msg, "%3d", arts[n].tagged);
  302. X                    } else {
  303. X                        sprintf (msg, "   ");
  304. X                    }
  305. X                    if (show_only_unread) {
  306. X                        strcat (msg, "   ");
  307. X                    }                    
  308. X                    mark_screen (SCREEN_READ_UNREAD, msg);    
  309. X                    flag = FALSE;
  310. X                } else {
  311. X                    flag = TRUE;
  312. X                }
  313. X                n = next_unread (next_response ((int) base[index_point]));
  314. X                if (n < 0) {
  315. X                    if (flag)
  316. X                        info_message (txt_no_next_unread_art);
  317. X                    else
  318. X                        MoveCursor (LINES, 0);
  319. X                    break;
  320. X                }
  321. X
  322. X                if ((n = which_thread (n)) < 0) {
  323. X                    error_message("Internal error: K which_thread < 0", "");
  324. X                    break;
  325. X                }
  326. X
  327. X                if (n >= last_subj_on_screen) {
  328. X                    index_point = n;
  329. X                    show_group_page (group);
  330. X                } else {
  331. X                    erase_subject_arrow ();
  332. X                    index_point = n;
  333. X                    draw_subject_arrow ();
  334. X                }
  335. X                break;
  336. X
  337. X            case 'l':    /* list articles within current thread */
  338. X                 space_mode = TRUE;
  339. X                if (show_thread ((int) base[index_point], group, group_path)) {
  340. X                    if (index_point < 0) {
  341. X                        space_mode = FALSE;
  342. X                        goto group_done;
  343. X                    }
  344. X                    clear_note_area ();
  345. X                    show_group_page (group);
  346. X                }
  347. X                break;    
  348. X
  349. X            case 'm':    /* mail article to somebody */
  350. X                if (index_point >= 0) {
  351. X                    set_real_uid_gid ();
  352. X                    feed_articles (FEED_MAIL, GROUP_LEVEL, "Mail",
  353. X                        (int) base[index_point], group_path);
  354. X                    set_tin_uid_gid ();
  355. X                }
  356. X                break;
  357. X
  358. X            case 'M':    /* options menu */
  359. X                if (top_base > 0) {
  360. X                    old_top = top;
  361. X                    n = (int) base[index_point];
  362. X                    old_artnum = arts[n].artnum;
  363. X                }
  364. X                n = sort_art_type;
  365. X                kill_state = change_rcfile (group, TRUE);
  366. X                if (kill_state == NO_KILLING && n != sort_art_type) {
  367. X                    make_threads (TRUE);
  368. X                    find_base (show_only_unread);
  369. X                }
  370. X                index_point = find_new_pos (old_top, old_artnum, index_point);
  371. X                show_group_page (group);
  372. X                break;
  373. X
  374. X            case 'n':    /* next group */
  375. X                clear_message();
  376. X                if (cur_groupnum + 1 >= group_top)
  377. X                    info_message(txt_no_more_groups);
  378. X                else {
  379. X                    cur_groupnum++;
  380. X                    index_point = -3;
  381. X                    space_mode = pos_first_unread;
  382. X                    goto group_done;
  383. X                }
  384. X                break;
  385. X
  386. X            case 'N':    /* go to next unread article */
  387. X                if (index_point < 0) {
  388. X                    info_message(txt_no_next_unread_art);
  389. X                    break;
  390. X                }
  391. X
  392. X                n = next_unread ((int) base[index_point]);
  393. X                if (n == -1)
  394. X                    info_message (txt_no_next_unread_art);
  395. X                else {
  396. X                    index_point = show_page (n, group, group_path);
  397. X                    if (index_point < 0) {
  398. X                        space_mode = pos_first_unread;
  399. X                        goto group_done;
  400. X                    }
  401. X                    clear_note_area ();
  402. X                    show_group_page (group);
  403. X                }
  404. X                break;
  405. X
  406. X            case 'o':    /* output art/thread/tagged arts to printer */
  407. X                if (index_point >= 0) {
  408. X                    set_real_uid_gid ();
  409. X                    feed_articles (FEED_PRINT, GROUP_LEVEL, "Print",
  410. X                        (int) base[index_point], group_path);
  411. X                    set_tin_uid_gid ();
  412. X                }
  413. X                break;
  414. X
  415. X            case 'p':    /* previous group */
  416. X                clear_message();
  417. X                if (cur_groupnum <= 0)
  418. X                    info_message(txt_no_prev_group);
  419. X                else {
  420. X                    cur_groupnum--;
  421. X                    index_point = -3;
  422. X                    space_mode = pos_first_unread;
  423. X                    goto group_done;
  424. X                }
  425. X                break;
  426. X
  427. X            case 'P':    /* go to previous unread article */
  428. X                if (index_point < 0) {
  429. X                    info_message(txt_no_prev_unread_art);
  430. X                    break;
  431. X                }
  432. X                n = prev_response ((int) base[index_point]);
  433. X                n = prev_unread (n);
  434. X                if (n == -1)
  435. X                    info_message(txt_no_prev_unread_art);
  436. X                else {
  437. X                    index_point = show_page (n, group, group_path);
  438. X                    if (index_point < 0) {
  439. X                        space_mode = pos_first_unread;
  440. X                        goto group_done;
  441. X                    }
  442. X                    clear_note_area ();
  443. X                    show_group_page (group);
  444. X                }
  445. X                break;
  446. X
  447. X            case 'q':        /* quit */
  448. X                index_point = -2;
  449. X                space_mode = FALSE;
  450. X                goto group_done;
  451. X
  452. X             case 'r':        
  453. X                 /* If in show_only_unread mode or there are unread 
  454. X                articles we know this thread will exist after 
  455. X                toggle. Otherwise we find the next closest */
  456. X                 i = -1;
  457. X                 if (index_point >= 0) {
  458. X                     if (show_only_unread || new_responses(index_point))
  459. X                         i = base[index_point];
  460. X                     else if ((n = prev_unread(base[index_point])) >= 0)
  461. X                         i = n;
  462. X                     else if ((n = next_unread(base[index_point])) >= 0)
  463. X                         i = n;
  464. X                 }
  465. X                 show_only_unread = (show_only_unread ? FALSE : TRUE);
  466. X                 make_threads (TRUE);
  467. X                 find_base (show_only_unread);
  468. X                 if (i >= 0 && (n = which_thread(i)) >= 0)
  469. X                     index_point = n;
  470. X                 else if (top_base > 0)
  471. X                     index_point = top_base -1;
  472. X                 show_group_page (group);
  473. X                 break;
  474. X
  475. X            case 's':    /* save regex pattern to file/s */
  476. X                if (index_point >= 0) {
  477. X                    set_real_uid_gid ();
  478. X                    feed_articles (FEED_SAVE, GROUP_LEVEL, "Save",
  479. X                        (int) base[index_point], group_path);
  480. X                    set_tin_uid_gid ();
  481. X                }
  482. X                break;
  483. X            
  484. X            case 't':
  485. X            case 'i':    /* return to group selection page */
  486. X                goto group_done;
  487. X
  488. X            case 'T':    /* tag/untag art for mailing/piping/printing/saving */
  489. X                 if (index_point >= 0) {
  490. X                    n = (int) base[index_point];
  491. X                    if (arts[n].tagged) {
  492. X                        arts[n].tagged = 0;
  493. X                        sprintf (msg, "%3s", (arts[n].unread ? "  +" : "   "));
  494. X                        info_message (txt_untagged_art);
  495. X                    } else {
  496. X                        arts[n].tagged = ++num_of_tagged_files;
  497. X                        sprintf (msg, "%3d", arts[n].tagged);
  498. X                        info_message (txt_tagged_art);
  499. X                    }
  500. X                    mark_screen (SCREEN_READ_UNREAD, msg);
  501. X                    goto group_down;    /* advance an article */
  502. X                }
  503. X                break;
  504. X
  505. X            case 'u':    /* unthread/thread articles */
  506. X                 if (index_point >= 0) {
  507. X                    thread_arts = !thread_arts;
  508. X                    make_threads (TRUE);
  509. X                    find_base (show_only_unread);
  510. X                    show_group_page (group);
  511. X                }
  512. X                break;
  513. X
  514. X            case 'U':    /* untag all articles */
  515. X                 if (index_point >= 0) {
  516. X                    untag_all_articles ();
  517. X                    show_group_page (group);
  518. X                }
  519. X                break;
  520. X
  521. X            case 'v':
  522. X                info_message (cvers);
  523. X                break;
  524. X
  525. X            case 'w':    /* post a basenote */
  526. X                if (! can_post) {
  527. X                    info_message (txt_cannot_post);
  528. X                    break;
  529. X                }
  530. X                if (post_base (group, &posted)) {
  531. X                    show_group_page (group);
  532. X                }
  533. X                break;
  534. X
  535. X            case 'W':    /* display messages posted by user */
  536. X                if (user_posted_messages ()) {
  537. X                    show_group_page(group);
  538. X                }
  539. X                break;
  540. X
  541. X            case 'z':    /* mark article as unread */
  542. X                 if (index_point < 0) {
  543. X                     info_message (txt_no_arts);
  544. X                    break;
  545. X                }
  546. X                i = (int) base[index_point];
  547. X                arts[i].unread = ART_UNREAD;
  548. X                if (show_only_unread) {
  549. X                    n = new_responses (index_point);
  550. X                    sprintf (buf, "  %c %d", UNREAD_ART_MARK, n);
  551. X                } else {
  552. X                    sprintf (buf, "  %c", UNREAD_ART_MARK);
  553. X                }
  554. X                mark_screen (SCREEN_READ_UNREAD, buf);    
  555. X                info_message (txt_art_marked_as_unread);
  556. X                break;
  557. X
  558. X            case 'Z':    /* mark thread as unread */
  559. X                 if (index_point < 0) {
  560. X                     info_message (txt_no_arts);
  561. X                    break;
  562. X                }
  563. X                n = 0;
  564. X                for (i = (int) base[index_point] ; i != -1 ; i = arts[i].thread) {
  565. X                    arts[i].unread = ART_UNREAD;
  566. X                    ++n;
  567. X                }
  568. X                assert (n > 0);
  569. X                if (show_only_unread) {
  570. X                    sprintf (buf, "  %c %d", UNREAD_ART_MARK, n);
  571. X                } else {
  572. X                    sprintf (buf, "  %c", UNREAD_ART_MARK);
  573. X                }
  574. X                mark_screen (SCREEN_READ_UNREAD, buf);    
  575. X                info_message (txt_thread_marked_as_unread);
  576. X                break;
  577. X
  578. X            default:
  579. X                info_message (txt_bad_command);
  580. X        }
  581. X    }
  582. X
  583. group_done:
  584. X    fix_new_highest (sav_groupnum);
  585. X    update_newsrc (group, my_group[sav_groupnum], FALSE);
  586. X
  587. X    if (index_point == -2) {
  588. X        tin_done (0);
  589. X    }    
  590. X    clear_note_area ();
  591. X
  592. #endif /* INDEX_DAEMON */
  593. }
  594. X
  595. X
  596. /*
  597. X *  Correct highest[] for the group selection page display since
  598. X *  new articles may have been read or marked unread
  599. X */
  600. X
  601. void fix_new_highest (groupnum)
  602. X    int groupnum;
  603. {
  604. X    register int i;
  605. X    int sum = 0;
  606. X
  607. X    for (i = 0; i < top; i++) {
  608. X        if (arts[i].unread) {
  609. X            sum++;
  610. X        }
  611. X    }
  612. X    
  613. X    unread[groupnum] = sum;
  614. }
  615. X
  616. X
  617. void show_group_page (group)
  618. X    char *group;
  619. {
  620. #ifndef INDEX_DAEMON
  621. X
  622. X    char buf[LEN];
  623. X    char new_resps[8];
  624. X    char resps[8];
  625. X    char from[LEN];
  626. X    char subject[LEN];
  627. X    int i, j, n;
  628. X    int len_from;
  629. X    int len_subj;
  630. X    int respnum;
  631. X    int art_cnt = 0;
  632. X
  633. X    set_signals_group ();
  634. X    
  635. #ifdef USE_CLEARSCREEN
  636. X    ClearScreen ();
  637. #else
  638. X    MoveCursor (0, 0);
  639. X    CleartoEOLN ();
  640. #endif
  641. X
  642. X    if (show_only_unread) {
  643. X        for (i = 0 ; i < top_base ; i++) {
  644. X            art_cnt += new_responses (i);
  645. X        }    
  646. X    } else {
  647. X        art_cnt = top;
  648. X    }
  649. X
  650. X    if (active[my_group[cur_groupnum]].thread && thread_arts) {
  651. X        sprintf (buf, "%s (%d %d)", group, top_base, art_cnt);
  652. X    } else {
  653. X        sprintf (buf, "%s (U %d)", group, art_cnt);
  654. X    }
  655. X    show_title (buf);
  656. X
  657. #ifndef USE_CLEARSCREEN
  658. X    MoveCursor (1, 0);
  659. X    CleartoEOLN ();
  660. #endif
  661. X
  662. X    MoveCursor (INDEX_TOP, 0);
  663. X
  664. X    if (index_point >= top_base) {
  665. X        index_point = top_base - 1;
  666. X    }
  667. X
  668. X    if (NOTESLINES <= 0) {
  669. X        first_subj_on_screen = 0;
  670. X    } else {
  671. X        first_subj_on_screen = (index_point / NOTESLINES) * NOTESLINES;
  672. X        if (first_subj_on_screen < 0) {
  673. X            first_subj_on_screen = 0;
  674. X        }
  675. X    }
  676. X
  677. X    last_subj_on_screen = first_subj_on_screen + NOTESLINES;
  678. X
  679. X    if (last_subj_on_screen >= top_base) {
  680. X        last_subj_on_screen = top_base;
  681. X        first_subj_on_screen = (top_base / NOTESLINES) * NOTESLINES;
  682. X
  683. X        if (first_subj_on_screen == last_subj_on_screen ||
  684. X            first_subj_on_screen < 0) {
  685. X            if (first_subj_on_screen < 0) {
  686. X                first_subj_on_screen = 0;
  687. X            } else {
  688. X                first_subj_on_screen = last_subj_on_screen - NOTESLINES;
  689. X            }
  690. X        }
  691. X    }
  692. X
  693. X    if (top_base == 0) {
  694. X        first_subj_on_screen = 0;
  695. X        last_subj_on_screen = 0;
  696. X    }
  697. X
  698. X    if (show_author != SHOW_FROM_NONE) {
  699. X        len_from = max_from-BLANK_GROUP_COLS;
  700. X    } else {
  701. X        len_subj = (max_subj+max_from+3)-BLANK_GROUP_COLS;
  702. X    }
  703. X
  704. X    if (draw_arrow_mark) {
  705. X        CleartoEOS ();
  706. X    }
  707. X
  708. X    for (j=0, i = first_subj_on_screen; i < last_subj_on_screen; i++, j++) {
  709. X        respnum = (int) base[i];
  710. X
  711. X        if (arts[respnum].tagged) {
  712. X            sprintf (new_resps, "%3d", arts[respnum].tagged);
  713. X        } else if (new_responses(i)) {
  714. X            sprintf (new_resps, "  %c", UNREAD_ART_MARK);
  715. X        } else {
  716. X            strcpy (new_resps, "   ");
  717. X        }
  718. X
  719. X        if (show_only_unread) {
  720. X            n = new_responses (i);
  721. X            if (n > 0) {
  722. X                n = n - 1;
  723. X            }    
  724. X        } else {
  725. X            n = num_of_responses (i);
  726. X        }
  727. X        
  728. X        if (n) {
  729. X            sprintf (resps, "%-3d", n); 
  730. X        } else {
  731. X            strcpy (resps, "   ");
  732. X        }
  733. X
  734. X        get_author (FALSE, respnum, from);
  735. X
  736. X        if (draw_arrow_mark) {
  737. X            if (show_author != SHOW_FROM_NONE) {
  738. X                my_strncpy (subject, arts[respnum].subject, max_subj);
  739. X                printf ("  %4d%3s %s%-*s   %-s\r\n",
  740. X                       i+1, new_resps, resps, max_subj, subject, from);
  741. X            } else {
  742. X                my_strncpy (subject, arts[respnum].subject, max_subj+max_from+3);
  743. X                printf ("  %4d%3s %s%-s\r\n",
  744. X                       i+1, new_resps, resps, subject);
  745. X            }
  746. X        } else {
  747. X            if (show_author != SHOW_FROM_NONE) {
  748. X                my_strncpy (subject, arts[respnum].subject, max_subj);
  749. X                sprintf (screen[j].col, "  %4d%3s %s%-*s   %-*s\r\n",
  750. X                       i+1, new_resps, resps, max_subj, subject, len_from, from);
  751. X            } else {
  752. X                my_strncpy (subject, arts[respnum].subject, max_subj+max_from+3);
  753. X                sprintf (screen[j].col, "  %4d%3s %s%-*s\r\n",
  754. X                       i+1, new_resps, resps, len_subj, subject);
  755. X            }
  756. X            printf ("%s", screen[j].col);
  757. X        }
  758. X    }
  759. X
  760. #ifndef USE_CLEARSCREEN
  761. X    CleartoEOS ();
  762. #endif
  763. X
  764. X    if (top_base <= 0) {
  765. X        info_message(txt_no_arts);
  766. X        return;
  767. X    } else if (last_subj_on_screen == top_base) {
  768. X        info_message(txt_end_of_arts);
  769. X    }
  770. X
  771. X    draw_subject_arrow();
  772. X
  773. #endif /* INDEX_DAEMON */
  774. }
  775. X
  776. X
  777. void draw_subject_arrow()
  778. {
  779. X    draw_arrow (INDEX_TOP + (index_point-first_subj_on_screen));
  780. }
  781. X
  782. void erase_subject_arrow()
  783. {
  784. X    erase_arrow (INDEX_TOP + (index_point-first_subj_on_screen));
  785. }
  786. X
  787. X
  788. int prompt_subject_num (ch, group)
  789. X    char ch;
  790. X    char *group;
  791. {
  792. X    int num;
  793. X
  794. X    clear_message ();
  795. X
  796. X    if ((num = prompt_num (ch, txt_read_art)) == -1) {
  797. X        clear_message ();
  798. X        return FALSE;
  799. X    }
  800. X    num--;        /* index from 0 (internal) vs. 1 (user) */
  801. X
  802. X    if (num < 0) {
  803. X        num = 0;
  804. X    }
  805. X    if (num >= top_base) {
  806. X        num = top_base - 1;
  807. X    }
  808. X
  809. X    if (num >= first_subj_on_screen
  810. X    &&  num < last_subj_on_screen) {
  811. X        erase_subject_arrow();
  812. X        index_point = num;
  813. X        draw_subject_arrow();
  814. X    } else {
  815. #ifndef USE_CLEARSCREEN
  816. X        erase_subject_arrow();
  817. #endif        
  818. X        index_point = num;
  819. X        show_group_page(group);
  820. X    }
  821. X    return TRUE;
  822. }
  823. X
  824. X
  825. void clear_note_area ()
  826. {
  827. #ifndef USE_CLEARSCREEN
  828. X    MoveCursor (INDEX_TOP, 0);
  829. X    CleartoEOS ();
  830. #endif
  831. }
  832. X
  833. /*
  834. X * Find new index position after a kill or unkill. Because
  835. X * kill can work on author it is impossible to know which,
  836. X * if any, articles will be left afterwards. So we make a
  837. X * "best attempt" to find a new index point.
  838. X */
  839. X
  840. int find_new_pos (old_top, old_artnum, cur_pos)
  841. X    int old_top;
  842. X    long old_artnum;
  843. X    int cur_pos;
  844. {
  845. X    int pos;
  846. X    
  847. X     if (top == old_top) {
  848. X         return (cur_pos);
  849. X     }    
  850. X  
  851. X     if ((pos = valid_artnum (old_artnum)) >= 0) {
  852. X         if ((pos = which_thread (pos)) >= 0){
  853. X             return pos;
  854. X         }
  855. X     }        
  856. X     
  857. X     if (cur_pos < top_base) {
  858. X         return cur_pos;
  859. X     } else {
  860. X         return (top_base - 1);
  861. X     }    
  862. }
  863. X
  864. X
  865. void mark_screen (col, value)
  866. X    int col;
  867. X    char *value;
  868. {
  869. X    int i, len;
  870. X
  871. X    len = strlen (value);
  872. X    
  873. X    if (draw_arrow_mark) {
  874. X        MoveCursor(INDEX_TOP + (index_point - first_subj_on_screen), col);
  875. X        printf ("%s", value);
  876. X        MoveCursor (LINES, 0);
  877. X        fflush(stdout);
  878. X    } else {
  879. X        for (i=0 ; i < len ; i++) {
  880. X            screen[index_point-first_subj_on_screen].col[col+i] = value[i];
  881. X        }
  882. X        draw_subject_arrow();
  883. X    }
  884. }
  885. SHAR_EOF
  886. echo 'File group.c is complete' &&
  887. chmod 0600 group.c ||
  888. echo 'restore of group.c failed'
  889. Wc_c="`wc -c < 'group.c'`"
  890. test 22085 -eq "$Wc_c" ||
  891.     echo 'group.c: original size 22085, current size' "$Wc_c"
  892. rm -f _shar_wnt_.tmp
  893. fi
  894. # ============= hashstr.c ==============
  895. if test -f 'hashstr.c' -a X"$1" != X"-c"; then
  896.     echo 'x - skipping hashstr.c (File already exists)'
  897.     rm -f _shar_wnt_.tmp
  898. else
  899. > _shar_wnt_.tmp
  900. echo 'x - extracting hashstr.c (Text)'
  901. sed 's/^X//' << 'SHAR_EOF' > 'hashstr.c' &&
  902. /*
  903. X *  Project   : tin - a threaded Netnews reader
  904. X *  Module    : hashstr.c
  905. X *  Author    : I.Lea & R.Skrenta
  906. X *  Created   : 01-04-91
  907. X *  Updated   : 21-03-92
  908. X *  Notes     :
  909. X *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  910. X *              You may  freely  copy or  redistribute  this software,
  911. X *              so  long as there is no profit made from its use, sale
  912. X *              trade or  reproduction.  You may not change this copy-
  913. X *              right notice, and it must be included in any copy made
  914. X */
  915. X
  916. #include    "tin.h"
  917. X
  918. /*
  919. X *  Maintain a table of all strings we have seen.
  920. X *  If a new string comes in, add it to the table and return a pointer
  921. X *  to it.  If we've seen it before, just return the pointer to it.
  922. X *
  923. X *  Usage:  hash_str("some string") returns char *
  924. X *
  925. X *  Spillovers are chained on the end
  926. X */
  927. X
  928. /*
  929. X *  Arbitrary table size, but make sure it's prime!
  930. X */
  931. X
  932. #define        HASHNODE_TABLE_SIZE    2411
  933. X
  934. struct hashnode *table[HASHNODE_TABLE_SIZE];
  935. X
  936. X
  937. char *hash_str (s)
  938. X    char *s;
  939. {
  940. X    long h;                /* result of hash:  index into hash table */
  941. X    struct hashnode *p;    /* used to descend the spillover structs */
  942. X
  943. X    if (s == (char *) 0) {
  944. X        return ((char *) 0);
  945. X    }
  946. X
  947. X    {
  948. X        unsigned char *t = (unsigned char *) s;
  949. X
  950. X        h = *t++;
  951. X        while (*t)
  952. X            h = ((h << 1) ^ *t++) % (long) HASHNODE_TABLE_SIZE;
  953. X    }
  954. X
  955. X    p = table[h];
  956. X
  957. X    if (p == (struct hashnode *) 0) {
  958. X        table[h] = add_string (s);
  959. X        return table[h]->s;
  960. X    }
  961. X
  962. X    while (1) {
  963. X        if (strcmp (s, p->s) == 0) {
  964. X            return (p->s);
  965. X        }
  966. X
  967. X        if (p->next == (struct hashnode *) 0) {
  968. X            p->next = add_string (s);
  969. X            return p->next->s;
  970. X        } else {
  971. X            p = p->next;
  972. X        }
  973. X    }
  974. X    /* NOTREACHED */
  975. }
  976. X
  977. X
  978. struct hashnode *add_string (s)
  979. X    char *s;
  980. {
  981. X    int *iptr;
  982. X    struct hashnode *p;
  983. X
  984. X    p = (struct hashnode *) my_malloc ((unsigned) sizeof (struct hashnode));
  985. X
  986. X    p->next = (struct hashnode *) 0;
  987. X    iptr = (int *) my_malloc ((unsigned) strlen (s) + sizeof (int) + 1);
  988. X    *iptr++ = -1;
  989. X    p->s = (char *) iptr;
  990. X    strcpy (p->s, s);
  991. X    return (p);
  992. }
  993. X
  994. X
  995. void hash_init ()
  996. {
  997. X    int i;
  998. X
  999. X    for (i = 0; i < HASHNODE_TABLE_SIZE; i++) {
  1000. X        table[i] = (struct hashnode *) 0;
  1001. X    }
  1002. }
  1003. X
  1004. X
  1005. void hash_reclaim ()
  1006. {
  1007. X    int i;
  1008. X    int *iptr;
  1009. X    struct hashnode *p, *next;
  1010. X
  1011. X    for (i = 0; i < HASHNODE_TABLE_SIZE; i++)
  1012. X        if (table[i] != (struct hashnode *) 0) {
  1013. X            p = table[i];
  1014. X            while (p != (struct hashnode *) 0) {
  1015. X                next = p->next;
  1016. X                if (p->s != (char *) 0) {
  1017. X                    iptr = (int *) p->s;
  1018. X                    iptr--;
  1019. X                    free ((char *) iptr);
  1020. X                }
  1021. X                free ((char *) p);
  1022. X                p = next;
  1023. X            }
  1024. X            table[i] = (struct hashnode *) 0;
  1025. X        }
  1026. }
  1027. SHAR_EOF
  1028. chmod 0600 hashstr.c ||
  1029. echo 'restore of hashstr.c failed'
  1030. Wc_c="`wc -c < 'hashstr.c'`"
  1031. test 2510 -eq "$Wc_c" ||
  1032.     echo 'hashstr.c: original size 2510, current size' "$Wc_c"
  1033. rm -f _shar_wnt_.tmp
  1034. fi
  1035. # ============= help.c ==============
  1036. if test -f 'help.c' -a X"$1" != X"-c"; then
  1037.     echo 'x - skipping help.c (File already exists)'
  1038.     rm -f _shar_wnt_.tmp
  1039. else
  1040. > _shar_wnt_.tmp
  1041. echo 'x - extracting help.c (Text)'
  1042. sed 's/^X//' << 'SHAR_EOF' > 'help.c' &&
  1043. /*
  1044. X *  Project   : tin - a threaded Netnews reader
  1045. X *  Module    : help.c
  1046. X *  Author    : I.Lea
  1047. X *  Created   : 01-04-91
  1048. X *  Updated   : 12-02-92
  1049. X *  Notes     :
  1050. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  1051. X *              You may  freely  copy or  redistribute  this software,
  1052. X *              so  long as there is no profit made from its use, sale
  1053. X *              trade or  reproduction.  You may not change this copy-
  1054. X *              right notice, and it must be included in any copy made
  1055. X */
  1056. X
  1057. #include    "tin.h"
  1058. #include    "nntp.h"
  1059. X
  1060. char *help_select[] = {
  1061. X    txt_help_g_4,
  1062. X    txt_help_ctrl_d,
  1063. X    txt_help_ctrl_l,
  1064. X    txt_help_g_ctrl_k,
  1065. X    txt_help_g_ctrl_r,
  1066. X    txt_help_g_cr,
  1067. X    txt_help_g_tab,
  1068. X    txt_help_b,
  1069. X    txt_help_bug_report,
  1070. X    txt_help_sel_c,
  1071. X    txt_help_g,
  1072. X    txt_help_j,
  1073. X    txt_help_h,
  1074. X    txt_help_I,
  1075. X    txt_help_m,
  1076. X    txt_help_M,
  1077. X    txt_help_n,
  1078. X    txt_help_q,
  1079. X    txt_help_s,
  1080. X    txt_help_S,
  1081. X    txt_help_v,
  1082. X    txt_help_w,
  1083. X    txt_help_W,
  1084. X    txt_help_g_y,
  1085. X    txt_help_g_dollar,
  1086. X    txt_help_g_z,
  1087. X    txt_help_g_search,
  1088. #ifndef NO_SHELL_ESCAPE
  1089. X    txt_help_shell,
  1090. #endif
  1091. X    (char *) 0
  1092. };
  1093. X
  1094. char *help_group[] = {
  1095. X    txt_help_i_4,
  1096. X    txt_help_ctrl_d,
  1097. X    txt_help_ctrl_k,
  1098. X    txt_help_ctrl_l,
  1099. X    txt_help_i_cr,
  1100. X    txt_help_i_tab,
  1101. X    txt_help_a,
  1102. X    txt_help_b,
  1103. X    txt_help_bug_report,
  1104. X    txt_help_c,
  1105. X    txt_help_d,
  1106. X    txt_help_g,
  1107. X    txt_help_h,
  1108. X    txt_help_I,
  1109. X    txt_help_j,
  1110. X    txt_help_K,
  1111. X    txt_help_l,
  1112. X    txt_help_p_m,
  1113. X    txt_help_M,
  1114. X    txt_help_o,
  1115. X    txt_help_i_n,
  1116. X    txt_help_i_p,
  1117. X    txt_help_q,
  1118. X    txt_help_r,
  1119. X    txt_help_p_s,
  1120. X    txt_help_t,
  1121. X    txt_help_T,
  1122. X    txt_help_u,
  1123. X    txt_help_U,
  1124. X    txt_help_v,
  1125. X    txt_help_w,
  1126. X    txt_help_W,
  1127. X    txt_help_p_z,
  1128. X    txt_help_i_search,
  1129. #ifndef NO_SHELL_ESCAPE
  1130. X    txt_help_shell,
  1131. #endif
  1132. X    txt_help_dash,
  1133. X    txt_help_pipe,
  1134. X    (char *) 0
  1135. };
  1136. X
  1137. char *help_thread[] = {
  1138. X    txt_help_t_0,
  1139. X    txt_help_t_4,
  1140. X    txt_help_ctrl_d,
  1141. X    txt_help_ctrl_l,
  1142. X    txt_help_t_cr,
  1143. X    txt_help_p_tab,
  1144. X    txt_help_b,
  1145. X    txt_help_h,
  1146. X    txt_help_I,
  1147. X    txt_help_j,
  1148. X    txt_help_p_k,
  1149. X    txt_help_q,
  1150. X    txt_help_T,
  1151. X    txt_help_T,
  1152. X    txt_help_v,
  1153. X    txt_help_p_z,
  1154. X    (char *) 0
  1155. };
  1156. X
  1157. char *help_page[] = {
  1158. X    txt_help_p_0,
  1159. X    txt_help_p_4,
  1160. X    txt_help_ctrl_h,
  1161. X    txt_help_ctrl_k,
  1162. X    txt_help_ctrl_l,
  1163. X    txt_help_p_ctrl_r,
  1164. X    txt_help_p_cr,
  1165. X    txt_help_p_tab,
  1166. X    txt_help_b,
  1167. X    txt_help_a,
  1168. X    txt_help_bug_report,
  1169. X    txt_help_c,
  1170. X    txt_help_C,
  1171. X    txt_help_p_d,
  1172. X    txt_help_p_f,
  1173. X    txt_help_p_g,
  1174. X    txt_help_h,
  1175. X    txt_help_p_i,
  1176. X    txt_help_I,
  1177. X    txt_help_p_k,
  1178. X    txt_help_p_m,
  1179. X    txt_help_M,
  1180. X    txt_help_p_n,
  1181. X    txt_help_o,
  1182. X    txt_help_p_p,
  1183. X    txt_help_q,
  1184. X    txt_help_p_r,
  1185. X    txt_help_p_s,
  1186. X    txt_help_t,
  1187. X    txt_help_T,
  1188. X    txt_help_v,
  1189. X    txt_help_w,
  1190. X    txt_help_W,
  1191. X    txt_help_p_z,
  1192. X    txt_help_p_search,
  1193. #ifndef NO_SHELL_ESCAPE
  1194. X    txt_help_shell,
  1195. #endif
  1196. X    txt_help_dash,
  1197. X    txt_help_pipe,
  1198. X    txt_help_thread,
  1199. X    (char *) 0
  1200. };
  1201. X
  1202. X
  1203. void show_info_page (type, help, title)
  1204. X    int type; 
  1205. X    char *help[];
  1206. X    char *title;
  1207. {
  1208. X    char buf[LEN];
  1209. X    char ch;
  1210. X    int i, len;
  1211. X    int group_len = 0;
  1212. X    int old_page = 0;
  1213. X    int cur_page = 1;
  1214. X    int max_page = 1;
  1215. X    int pos_help = 0;
  1216. X
  1217. X    if (NOTESLINES <= 0) {
  1218. X        return;
  1219. X    }
  1220. X
  1221. X    /*
  1222. X     *  find how many elements in array
  1223. X     */
  1224. X    if (type == HELP_INFO) {
  1225. X        for (i=0 ; help[i] ; i++) {
  1226. X            continue;
  1227. X        }
  1228. X    } else {
  1229. X        for (i=0 ; posted[i].date[0] ; i++) {
  1230. X            len = strlen (posted[i].group);
  1231. X            if (len > group_len) {
  1232. X                 group_len = len;
  1233. X            }
  1234. X         }
  1235. X    }
  1236. X    
  1237. X    max_page = i / NOTESLINES;
  1238. X    if (i % NOTESLINES) {
  1239. X        max_page++;
  1240. X    }
  1241. X
  1242. X    while (1) {
  1243. X        if (cur_page != old_page) {
  1244. X            ClearScreen ();
  1245. X            sprintf (buf, title, cur_page, max_page);
  1246. X            center_line (0, TRUE, buf);
  1247. X            MoveCursor (INDEX_TOP, 0);
  1248. X
  1249. X            if (type == HELP_INFO) { 
  1250. X                for (i=pos_help ; i < (pos_help + NOTESLINES) && help[i] ; i++) {
  1251. X                    printf ("%s", help[i]);
  1252. X                }
  1253. X            } else {
  1254. X                for (i=pos_help ; i < (pos_help + NOTESLINES) && posted[i].date[0] ; i++) {
  1255. X                    sprintf (msg, "%8s  %-*s  %s", posted[i].date,
  1256. X                        group_len, posted[i].group, posted[i].subj);
  1257. X                        msg[COLS-2] = '\0';
  1258. X                    printf ("%s\r\n", msg);
  1259. X                }
  1260. X            }
  1261. X        }
  1262. X
  1263. X        if (cur_page != old_page) {
  1264. X            center_line (LINES, FALSE, txt_hit_space_for_more);
  1265. X        }
  1266. X
  1267. X        old_page = cur_page;
  1268. X        
  1269. X        ch = (char) ReadCh ();
  1270. X        switch (ch) {
  1271. X            case ESC:    /* common arrow keys */
  1272. X                switch (get_arrow_key ()) {
  1273. X                    case KEYMAP_UP:
  1274. X                    case KEYMAP_PAGE_UP:
  1275. X                        if (cur_page > 1) {
  1276. X                            cur_page--;
  1277. X                            pos_help = (cur_page-1)*NOTESLINES;
  1278. X                        }
  1279. X                        break;
  1280. X
  1281. X                    case KEYMAP_DOWN:
  1282. X                    case KEYMAP_PAGE_DOWN:
  1283. X                        if (cur_page < max_page) {
  1284. X                            pos_help = cur_page*NOTESLINES;
  1285. X                            cur_page++;
  1286. X                        }
  1287. X                        break;
  1288. X
  1289. X                    case KEYMAP_HOME:
  1290. X                        if (cur_page != 1) {
  1291. X                            cur_page = 1;
  1292. X                            pos_help = 0;
  1293. X                        }
  1294. X                        break;
  1295. X                    
  1296. X                    case KEYMAP_END:
  1297. X                        if (cur_page != max_page) {
  1298. X                            cur_page = max_page;
  1299. X                            pos_help = (max_page-1) * NOTESLINES;
  1300. X                        }
  1301. X                        break;
  1302. X                }
  1303. X                break;
  1304. X
  1305. X            case ctrl('D'):            /* page down */
  1306. X            case ' ':
  1307. X                if (cur_page < max_page) {
  1308. X                    pos_help = cur_page*NOTESLINES;
  1309. X                    cur_page++;
  1310. X                }
  1311. X                break;
  1312. X            
  1313. X            case ctrl('U'):            /* page up */
  1314. X            case 'b':
  1315. X                if (cur_page > 1) {
  1316. X                    cur_page--;
  1317. X                    pos_help = (cur_page-1)*NOTESLINES;
  1318. X                }
  1319. X                break;
  1320. X
  1321. X            case ctrl('R'):            /* Home */
  1322. X            case 'g':
  1323. X                if (cur_page != 1) {
  1324. X                    cur_page = 1;
  1325. X                    pos_help = 0;
  1326. X                }
  1327. X                break;
  1328. X
  1329. X            case '$':                /* End */
  1330. X            case 'G':
  1331. X                if (cur_page != max_page) {
  1332. X                    cur_page = max_page;
  1333. X                    pos_help = (max_page-1) * NOTESLINES;
  1334. X                }
  1335. X                break;
  1336. X
  1337. X            default:
  1338. #ifndef USE_CLEARSCREEN
  1339. X                ClearScreen ();
  1340. #endif    
  1341. X                return;
  1342. X        }    
  1343. X    }
  1344. }
  1345. SHAR_EOF
  1346. chmod 0600 help.c ||
  1347. echo 'restore of help.c failed'
  1348. Wc_c="`wc -c < 'help.c'`"
  1349. test 5257 -eq "$Wc_c" ||
  1350.     echo 'help.c: original size 5257, current size' "$Wc_c"
  1351. rm -f _shar_wnt_.tmp
  1352. fi
  1353. # ============= inews.c ==============
  1354. if test -f 'inews.c' -a X"$1" != X"-c"; then
  1355.     echo 'x - skipping inews.c (File already exists)'
  1356.     rm -f _shar_wnt_.tmp
  1357. else
  1358. > _shar_wnt_.tmp
  1359. echo 'x - extracting inews.c (Text)'
  1360. sed 's/^X//' << 'SHAR_EOF' > 'inews.c' &&
  1361. /*
  1362. X *  Project   : tin - a threaded Netnews reader
  1363. X *  Module    : inews.c
  1364. X *  Author    : I.Lea
  1365. X *  Created   : 17-03-92
  1366. X *  Updated   : 19-03-92
  1367. X *  Notes     : NNTP builtin version of inews
  1368. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  1369. X *              You may  freely  copy or  redistribute  this software,
  1370. X *              so  long as there is no profit made from its use, sale
  1371. X *              trade or  reproduction.  You may not change this copy-
  1372. X *              right notice, and it must be included in any copy made
  1373. X */
  1374. X
  1375. #include    "tin.h"
  1376. #include    "nntp.h"
  1377. X
  1378. X
  1379. int submit_inews (name)
  1380. X    char *name;
  1381. {    
  1382. X    int    ret_code = FALSE;
  1383. X
  1384. #ifdef NNTP_INEWS
  1385. X    char    *ptr;
  1386. X    char    full_name[128];
  1387. X    char    host_name[128];
  1388. X    char    line[NNTP_STRLEN];
  1389. X    FILE    *fp;
  1390. X    int    respcode;
  1391. X
  1392. X    if ((fp = fopen (name, "r")) == NULL) {
  1393. X        return (ret_code);
  1394. X    }
  1395. X
  1396. X    /*
  1397. X     * Send POST command to NNTP server
  1398. X     */
  1399. X    put_server ("post");
  1400. X
  1401. X    /*
  1402. X     * Receive CONT_POST or ERROR response code from NNTP server
  1403. X     */
  1404. X    if ((respcode = get_respcode ()) != CONT_POST) {
  1405. X        error_message ("%s", nntp_respcode (respcode));
  1406. X        debug_nntp ("submit_inews", nntp_respcode (respcode));
  1407. X        return (ret_code);
  1408. X    }
  1409. X
  1410. X    /*
  1411. X     * Find users name and hosts name
  1412. X     */
  1413. X    if ((ptr = (char *) getenv ("NAME")) != (char *) 0) {
  1414. X        strcpy (full_name, ptr);
  1415. X    } else {    
  1416. X        strcpy (full_name, myentry->pw_gecos);
  1417. X        if ((ptr = (char *) strchr (full_name, ','))) {
  1418. X            *ptr = '\0';            
  1419. X        }
  1420. X    }
  1421. X
  1422. #if defined(BSD) || defined(sinix)
  1423. X    gethostname (host_name, sizeof (host_name)); 
  1424. #else    
  1425. X    uname (host_name);
  1426. #endif
  1427. X    
  1428. X    if (debug == 2) {
  1429. X        sprintf (msg, "NAME=[%s] HOST=[%s]", full_name, host_name);
  1430. X        wait_message (msg);
  1431. X        sleep (2);
  1432. X    }    
  1433. X     
  1434. X    /*
  1435. X     * Send Path: and From: article headers
  1436. X     */
  1437. X    sprintf (line, "Path: %s!%s", host_name, userid);
  1438. X    put_server (line);
  1439. X    sprintf (line, "From: %s@%s (%s)", userid, host_name, full_name);
  1440. X    put_server (line);
  1441. X
  1442. X    /*
  1443. X     * Send article 1 line at a time ending with "."
  1444. X     */
  1445. X    while (fgets (line, sizeof (line), fp) != NULL) {
  1446. X        if (line[strlen (line)-1] == '\n') {
  1447. X            line[strlen (line)-1] = '\0';
  1448. X        }
  1449. X        put_server (line);    
  1450. X    }
  1451. X    
  1452. X    put_server (".");
  1453. X
  1454. X    /*
  1455. X     * Receive OK_POSTED or ERROR response code from NNTP server
  1456. X     */
  1457. X    if ((respcode = get_respcode ()) != OK_POSTED) {
  1458. X        error_message ("%s", nntp_respcode (respcode));
  1459. X        debug_nntp ("submit_inews", nntp_respcode (respcode));
  1460. X        return (ret_code);
  1461. X      }
  1462. X      
  1463. X    ret_code = TRUE;
  1464. X
  1465. #endif /* NNTP_ABLE */
  1466. X
  1467. X    return (ret_code);
  1468. }
  1469. X
  1470. SHAR_EOF
  1471. chmod 0600 inews.c ||
  1472. echo 'restore of inews.c failed'
  1473. Wc_c="`wc -c < 'inews.c'`"
  1474. test 2409 -eq "$Wc_c" ||
  1475.     echo 'inews.c: original size 2409, current size' "$Wc_c"
  1476. rm -f _shar_wnt_.tmp
  1477. fi
  1478. # ============= init.c ==============
  1479. if test -f 'init.c' -a X"$1" != X"-c"; then
  1480.     echo 'x - skipping init.c (File already exists)'
  1481.     rm -f _shar_wnt_.tmp
  1482. else
  1483. > _shar_wnt_.tmp
  1484. echo 'x - extracting init.c (Text)'
  1485. sed 's/^X//' << 'SHAR_EOF' > 'init.c' &&
  1486. /*
  1487. X *  Project   : tin - a threaded Netnews reader
  1488. X *  Module    : init.c
  1489. X *  Author    : I.Lea
  1490. X *  Created   : 01-04-91
  1491. X *  Updated   : 21-03-92
  1492. X *  Notes     :
  1493. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  1494. X *              You may  freely  copy or  redistribute  this software,
  1495. X *              so  long as there is no profit made from its use, sale
  1496. X *              trade or  reproduction.  You may not change this copy-
  1497. X *              right notice, and it must be included in any copy made
  1498. X */
  1499. X
  1500. #include    "tin.h"
  1501. X
  1502. X
  1503. char rcdir[LEN];
  1504. char rcfile[LEN];
  1505. char indexdir[LEN];
  1506. char killfile[LEN];
  1507. char postfile[LEN];
  1508. char unthreadfile[LEN];
  1509. char cvers[LEN];
  1510. char nntp_server[LEN];
  1511. char active_file[LEN];
  1512. char subscriptions_file[LEN];
  1513. char homedir[LEN];
  1514. char userid[LEN];
  1515. char delgroups[LEN];
  1516. char newsrc[LEN];
  1517. char newnewsrc[LEN];
  1518. char add_addr[LEN];            /* address to add to rR reply to author with mail */
  1519. char bug_addr[LEN];            /* address to add send bug reports to */
  1520. char txt_help_bug_report[LEN];    /* address to add send bug reports to */
  1521. char reply_to[LEN];            /* reply-to address */
  1522. char my_org[LEN];            /* organization */
  1523. char sig[LEN];
  1524. char signature[LEN];
  1525. char default_shell_command[LEN];    /* offers user default choice */
  1526. char killsubj[LEN];            /* contains Subject:'s not to be shown */
  1527. char killfrom[LEN];            /* conatins From:'s not to be shown */
  1528. char page_header[LEN];        /* page header of pgm name and version */
  1529. char savedir[LEN];            /* directory to save articles to */
  1530. char spooldir[LEN];            /* directory where new is */
  1531. char mail_news_user[LEN];    /* mail new news to this user address */
  1532. char mailer[LEN];            /* mail program */
  1533. char maildir[LEN];            /* mailbox dir where = saves are stored */
  1534. char mailbox[LEN];            /* system mailbox for each user */
  1535. char printer[LEN];            /* printer program specified from tinrc */
  1536. char cmd_line_printer[LEN];    /* printer program specified on cmd line */
  1537. char article[LEN];            /* ~/.article file */
  1538. char dead_article[LEN];        /* ~/dead.article file */
  1539. char progname[LEN];            /* program name */
  1540. char redirect_output[LEN];    /* /dev/null or nothing if -D option */
  1541. X
  1542. int NOTESLINES;                        /* set in set_win_size () */
  1543. int RIGHT_POS;                        /* set in set_win_size () */
  1544. int MORE_POS;                        /* set in set_win_size () */
  1545. int max_subj = 0;
  1546. int max_from = 0;
  1547. int max_active;
  1548. int num_active;                        /* one past top of active */
  1549. int group_top;                        /* one past top of my_group */
  1550. int catchup = FALSE;                /* mark all arts read in all subscribed groups */
  1551. int update_fork = FALSE;            /* update index files by forked tin -u */
  1552. int verbose = FALSE;                /* update index files only mode */
  1553. int start_line_offset;                /* used by invoke_editor for line no. */
  1554. int read_news_via_nntp = FALSE;        /* read news locally or via NNTP */
  1555. int local_index;                    /* do private indexing? */
  1556. int max_art;
  1557. int real_uid;
  1558. int real_gid;
  1559. int tin_uid;
  1560. int tin_gid;
  1561. int top = 0;
  1562. int top_base;
  1563. int check_any_unread = FALSE;
  1564. int notify_new_groups = FALSE;
  1565. int start_any_unread = FALSE;
  1566. X
  1567. int catchup_read_groups;    /* ask if read groups are to be marked read */
  1568. int cmd_line;                /* batch / interactive mode */
  1569. int created_rcdir;            /* checks if first time tin is started */
  1570. int default_printer;        /* set to false if user give a printer with -p switch */
  1571. int default_show_author;    /* show_author value from 'M' menu in tinrc */
  1572. int draw_arrow_mark;        /* draw -> or highlighted bar */
  1573. int full_page_scroll;        /* page half/full screen of articles/groups */
  1574. int kill_articles;            /* kill articles matching kill file contents */
  1575. int mark_saved_read;        /* mark saved article/thread as read */
  1576. int num_of_killed_files;
  1577. int num_of_tagged_files;
  1578. int process_id;
  1579. int pos_first_unread;        /* position cursor at first/last unread article */
  1580. int post_proc_type;            /* type of post processing to be performed */
  1581. int print_header;            /* print all of mail header or just Subject: & From lines */
  1582. int save_archive_name;        /* save thread with name from Archive-name: field */
  1583. int mail_news;                /* mail all arts to specified user */
  1584. int save_news;                /* save all arts to savedir structure */
  1585. int save_separate;            /* save a each part of a thread to a separate file */
  1586. int show_author;            /* show Subject & From or only Subject in group menu */
  1587. int show_only_unread;        /* show only new/unread arts or all arts */
  1588. int sort_art_type;            /* sort arts[] array by subject,from or date field */
  1589. int thread_arts;            /* thread/unthread articles for viewing */
  1590. X
  1591. #ifdef INDEX_DAEMON
  1592. int update = TRUE;                    /* update index files only mode */
  1593. #else
  1594. int update = FALSE;                    /* update index files only mode */
  1595. #endif
  1596. X
  1597. struct passwd *myentry;
  1598. X
  1599. X
  1600. /*
  1601. X * Get users home directory, userid, and a bunch of other stuff!
  1602. X */
  1603. X
  1604. void init_selfinfo ()
  1605. {
  1606. X    extern char *getlogin ();
  1607. #ifndef __convexc__
  1608. X    extern struct passwd *getpwuid ();
  1609. #endif    
  1610. X    extern struct passwd *getpwnam ();
  1611. X    char nam[LEN];
  1612. X    char *p;
  1613. X    FILE *fp;
  1614. X    struct stat sb;
  1615. X
  1616. X    process_id = getpid ();
  1617. X    
  1618. X    myentry = (struct passwd *) 0;
  1619. X    if ((p = getlogin ()) != (char *) 0) {
  1620. X        myentry = getpwnam (p);
  1621. X    } else {
  1622. X        myentry = getpwuid (getuid ());
  1623. X    }
  1624. X
  1625. X    strcpy (userid, myentry->pw_name);
  1626. X
  1627. X    if ((p = (char *) getenv ("HOME")) != NULL) {
  1628. X        strcpy (homedir, p);
  1629. X    } else {
  1630. X        strcpy (homedir, myentry->pw_dir);
  1631. X    }
  1632. X
  1633. X    catchup_read_groups = FALSE;
  1634. X    created_rcdir = FALSE;
  1635. #ifdef USE_INVERSE_HACK
  1636. X    draw_arrow_mark = TRUE;
  1637. #else
  1638. X    draw_arrow_mark = FALSE;
  1639. #endif
  1640. #ifdef BSD
  1641. X    default_printer = TRUE;
  1642. #else    
  1643. X    default_printer = FALSE;
  1644. #endif
  1645. X    full_page_scroll = TRUE;
  1646. X    kill_articles = FALSE;
  1647. X    mark_saved_read = TRUE;
  1648. X    num_of_killed_files = 0;
  1649. X    num_of_tagged_files = 0;
  1650. X    post_proc_type = POST_PROC_NONE;
  1651. X    pos_first_unread = TRUE;
  1652. X    print_header = FALSE;
  1653. X    save_separate = TRUE;
  1654. X    save_archive_name = TRUE;
  1655. X    default_show_author = SHOW_FROM_NAME;
  1656. X    show_only_unread = FALSE;
  1657. X    sort_art_type = SORT_BY_NOTHING;
  1658. X    save_news = FALSE;
  1659. X    thread_arts = TRUE;
  1660. X    
  1661. X    killsubj[0] = '\0';
  1662. X    killfrom[0] = '\0';
  1663. X    
  1664. X    nntp_server[0] = '\0';
  1665. X    author_search_string[0] = '\0';
  1666. X    group_search_string[0] = '\0';
  1667. X    subject_search_string[0] = '\0';
  1668. X    art_search_string[0] = '\0';
  1669. X    default_mail_address[0] = '\0';
  1670. X    default_regex_pattern[0] = '\0';
  1671. X    default_save_file[0] = '\0';
  1672. X    default_shell_command[0] = '\0';
  1673. X    default_post_subject[0] = '\0';
  1674. X    cmd_line_printer[0] = '\0';
  1675. X    
  1676. X    sprintf (rcdir,  "%s/%s", get_val ("TINDIR", homedir), RCDIR);
  1677. X    sprintf (indexdir, "%s/%s", rcdir, INDEXDIR);
  1678. X    sprintf (rcfile,   "%s/%s", rcdir, RCFILE);
  1679. X    sprintf (killfile, "%s/%s", rcdir, KILLFILE);
  1680. X    sprintf (postfile, "%s/%s", rcdir, POSTFILE);
  1681. X    sprintf (unthreadfile, "%s/%s", rcdir, UNTHREADFILE);
  1682. X
  1683. X    sprintf (active_file, "%s/active", LIBDIR);
  1684. X    sprintf (article, "%s/.article", homedir);
  1685. X    sprintf (dead_article, "%s/dead.article", homedir);
  1686. X    sprintf (delgroups, "%s/.delgroups", homedir);
  1687. X    sprintf (mailbox, "%s/%s", DEFAULT_MAILBOX, userid);
  1688. X    sprintf (maildir, "%s/%s", homedir, DEFAULT_MAILDIR);
  1689. X    sprintf (newsrc, "%s/.newsrc", homedir);
  1690. X    sprintf (newnewsrc, "%s/.newnewsrc", homedir);
  1691. X    sprintf (savedir, "%s/News", homedir);
  1692. X    sprintf (sig, "%s/.Sig", homedir);
  1693. X    sprintf (signature, "%s/.signature", homedir);
  1694. X    sprintf (subscriptions_file, "%s/subscriptions", LIBDIR);
  1695. X
  1696. X    strcpy (mailer, DEFAULT_MAILER);
  1697. X    strcpy (printer, DEFAULT_PRINTER);
  1698. X    strcpy (spooldir, SPOOLDIR);
  1699. X    strcpy (bug_addr, BUG_REPORT_ADDRESS);
  1700. X    strcpy (redirect_output, "> /dev/null 2>&1");
  1701. X
  1702. X    set_real_uid_gid ();
  1703. X    
  1704. #ifdef INDEX_DAEMON
  1705. X    sprintf (indexdir, "%s/.index", SPOOLDIR);
  1706. X    strcpy (newsrc, active_file);    /* so that all groups are indexed */
  1707. X
  1708. X    if (stat (indexdir, &sb) == -1) {
  1709. X        mkdir (indexdir, 0755);
  1710. X    }
  1711. #else
  1712. X    if (stat (rcdir, &sb) == -1) {
  1713. X        created_rcdir = TRUE;
  1714. X        mkdir (rcdir, 0755);
  1715. X    }
  1716. #ifndef NNTP_XINDEX
  1717. X    if (stat (indexdir, &sb) == -1) {
  1718. X        mkdir (indexdir, 0755);
  1719. X    }
  1720. #endif /* NNTP_XINDEX */    
  1721. X    if (stat (postfile, &sb) == -1) {
  1722. X        if ((fp = fopen (postfile, "w")) != NULL) {
  1723. X            fclose (fp);
  1724. X        }
  1725. X    }
  1726. X    if (stat (unthreadfile, &sb) == -1) {
  1727. X        if ((fp = fopen (unthreadfile, "w")) != NULL) {
  1728. X            fclose (fp);
  1729. X        }
  1730. X    }
  1731. X
  1732. X    read_rcfile ();
  1733. X
  1734. X    show_author = default_show_author;
  1735. X
  1736. #endif /* INDEX_DAEMON */    
  1737. X
  1738. X    if (stat (active_file, &sb) >= 0)
  1739. X        goto got_active;
  1740. X
  1741. X    /*
  1742. X     *  I hate forgetting to define LIBDIR correctly.  Guess a couple
  1743. X     *  of the likely places if it's not where LIBDIR says it is.
  1744. X     */
  1745. X
  1746. X    strcpy (active_file, "/usr/lib/news/active");
  1747. X    if (stat (active_file, &sb) >= 0)
  1748. X        goto got_active;
  1749. X
  1750. X    strcpy (active_file, "/usr/local/lib/news/active");
  1751. X    if (stat (active_file, &sb) >= 0)
  1752. X        goto got_active;
  1753. X
  1754. X    strcpy (active_file, "/usr/public/lib/news/active");
  1755. X    if (stat (active_file, &sb) >= 0)
  1756. X        goto got_active;
  1757. X
  1758. X    /*
  1759. X     *  Oh well. Revert to what LIBDIR says it is to produce a useful
  1760. X     *  error message when read_active_file () fails later.
  1761. X     */
  1762. X
  1763. X    sprintf (active_file, "%s/active", LIBDIR);
  1764. X
  1765. got_active:
  1766. X
  1767. X    /*
  1768. X     *  check enviroment for organization
  1769. X     */
  1770. X    my_org[0] = '\0';
  1771. X    if ((p = (char *) getenv ("ORGANIZATION")) != NULL) {
  1772. X        my_strncpy (my_org, p, LEN);
  1773. X        goto got_org;
  1774. X    }
  1775. X
  1776. X    /*
  1777. X     *  check ~/.org for organization
  1778. X     */
  1779. X    sprintf (nam, "%s/organization", rcdir);
  1780. X    fp = fopen (nam, "r");
  1781. X
  1782. X    /*
  1783. X     *  check LIBDIR/organization for system wide organization
  1784. X     */
  1785. X    if (fp == NULL) {
  1786. X        sprintf (nam, "%s/organization", LIBDIR);
  1787. X        fp = fopen (nam, "r");
  1788. X    }
  1789. X
  1790. X    if (fp == NULL) {
  1791. X        sprintf (nam, "/usr/lib/news/organization");
  1792. X        fp = fopen (nam, "r");
  1793. X    }
  1794. X
  1795. X    if (fp == NULL) {
  1796. X        sprintf (nam, "/usr/local/lib/news/organization");
  1797. X        fp = fopen (nam, "r");
  1798. X    }
  1799. X
  1800. X    if (fp == NULL) {
  1801. X        sprintf (nam, "/usr/public/lib/news/organization");
  1802. X        fp = fopen (nam, "r");
  1803. X    }
  1804. X
  1805. X    if (fp == NULL) {
  1806. X        sprintf (nam, "/etc/organization");
  1807. X        fp = fopen (nam, "r");
  1808. X    }
  1809. X
  1810. X    if (fp != NULL) {
  1811. X        if (fgets (my_org, sizeof (my_org), fp) != NULL) {
  1812. X            for (p = my_org; *p && *p != '\n'; p++)
  1813. X                continue;
  1814. X            *p = '\0';
  1815. X        }
  1816. X        fclose (fp);
  1817. X    }
  1818. X
  1819. got_org:;
  1820. X
  1821. X    /*
  1822. X     *  check enviroment for REPLYTO
  1823. X     */
  1824. X    reply_to[0] = '\0';
  1825. X    if ((p = (char *) getenv ("REPLYTO")) != NULL) {
  1826. X        my_strncpy (reply_to, p, LEN);
  1827. X        goto got_reply;
  1828. X    }
  1829. X
  1830. X    sprintf (nam, "%s/replyto", rcdir);
  1831. X    if ((fp = fopen (nam, "r")) != NULL) {
  1832. X        if (fgets (reply_to, sizeof (reply_to), fp) != NULL) {
  1833. X            for (p = reply_to; *p && *p != '\n'; p++)
  1834. X                continue;
  1835. X            *p = '\0';
  1836. X        }
  1837. X        fclose (fp);
  1838. X    }
  1839. X
  1840. got_reply:;
  1841. X
  1842. X    /*
  1843. X     *  check enviroment for ADD_ADDRESS
  1844. X     */
  1845. X    add_addr[0] = '\0';
  1846. X    if ((p = (char *) getenv ("ADD_ADDRESS")) != NULL) {
  1847. X        my_strncpy (add_addr, p, LEN);
  1848. X        goto got_add_addr;
  1849. X    }
  1850. X
  1851. X    sprintf (nam, "%s/add_address", rcdir);
  1852. X    if ((fp = fopen (nam, "r")) != NULL) {
  1853. X        if (fgets (add_addr, sizeof (add_addr), fp) != NULL) {
  1854. X            for (p = add_addr; *p && *p != '\n'; p++)
  1855. X                continue;
  1856. X            *p = '\0';
  1857. X        }
  1858. X        fclose (fp);
  1859. X    }
  1860. X
  1861. got_add_addr:;
  1862. X
  1863. X    /*
  1864. X     *  check enviroment for BUG_ADDRESS
  1865. X     */
  1866. X    if ((p = (char *) getenv ("BUG_ADDRESS")) != NULL) {
  1867. X        my_strncpy (bug_addr, p, LEN);
  1868. X        goto got_bug_addr;
  1869. X    }
  1870. X
  1871. X    sprintf (nam, "%s/bug_address", rcdir);
  1872. X    if ((fp = fopen (nam, "r")) != NULL) {
  1873. X        if (fgets (bug_addr, sizeof (bug_addr), fp) != NULL) {
  1874. X            for (p = bug_addr; *p && *p != '\n'; p++)
  1875. X                continue;
  1876. X            *p = '\0';
  1877. X        }
  1878. X        fclose (fp);
  1879. X    }
  1880. X
  1881. got_bug_addr:;
  1882. X    sprintf (txt_help_bug_report, txt_help_bug, bug_addr);
  1883. X
  1884. X    set_tin_uid_gid ();
  1885. }
  1886. X
  1887. X
  1888. int create_mail_save_dirs ()
  1889. {
  1890. X    int created = FALSE;
  1891. X    struct stat sb;
  1892. X    
  1893. X    set_real_uid_gid ();
  1894. X    if (stat (maildir, &sb) == -1) {
  1895. X        mkdir (maildir, 0755);
  1896. X        created = TRUE;
  1897. X    }
  1898. X    if (stat (savedir, &sb) == -1) {
  1899. X        mkdir (savedir, 0755);
  1900. X        created = TRUE;
  1901. X    }
  1902. X    set_tin_uid_gid ();
  1903. X    
  1904. X    return (created);
  1905. }
  1906. SHAR_EOF
  1907. chmod 0600 init.c ||
  1908. echo 'restore of init.c failed'
  1909. Wc_c="`wc -c < 'init.c'`"
  1910. test 11316 -eq "$Wc_c" ||
  1911.     echo 'init.c: original size 11316, current size' "$Wc_c"
  1912. rm -f _shar_wnt_.tmp
  1913. fi
  1914. # ============= kill.c ==============
  1915. if test -f 'kill.c' -a X"$1" != X"-c"; then
  1916.     echo 'x - skipping kill.c (File already exists)'
  1917.     rm -f _shar_wnt_.tmp
  1918. else
  1919. > _shar_wnt_.tmp
  1920. echo 'x - extracting kill.c (Text)'
  1921. sed 's/^X//' << 'SHAR_EOF' > 'kill.c' &&
  1922. /*
  1923. X *  Project   : tin - a threaded Netnews reader
  1924. X *  Module    : kill.c
  1925. X *  Author    : I.Lea
  1926. X *  Created   : 01-04-91
  1927. X *  Updated   : 13-03-92
  1928. X *  Notes     : kill articles
  1929. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  1930. X *              You may  freely  copy or  redistribute  this software,
  1931. X *              so  long as there is no profit made from its use, sale
  1932. X *              trade or  reproduction.  You may not change this copy-
  1933. X *              right notice, and it must be included in any copy made
  1934. X */
  1935. X
  1936. #include    "tin.h"
  1937. X
  1938. extern char index_file[LEN];
  1939. X
  1940. struct kill_t *killf;
  1941. int kill_num = 0;
  1942. int max_kill;
  1943. X
  1944. /*
  1945. X *  read_kill_file - read ~/.tin/kill file contents into kill array
  1946. X */
  1947. X
  1948. int read_kill_file ()
  1949. {
  1950. X    char buf[LEN];
  1951. X    FILE *fp;
  1952. X
  1953. X    free_kill_array ();
  1954. X    
  1955. X    set_real_uid_gid ();
  1956. X
  1957. X    if ((fp = fopen (killfile, "r")) != NULL) {
  1958. X        kill_num=0;
  1959. X        while (fgets (buf, sizeof buf, fp) != NULL) {
  1960. X            if (buf[0] != '#') {
  1961. X                if (kill_num == max_kill-1) {
  1962. X                    expand_kill ();
  1963. X                }
  1964. X                killf[kill_num].kill_type = (int) atoi (buf);
  1965. X                if (fgets (buf, sizeof buf, fp) != NULL) {
  1966. X                    killf[kill_num].kill_group = (long) atol (buf);
  1967. X                } else {    
  1968. X                    goto corrupt_killfile;
  1969. X                }    
  1970. X                switch (killf[kill_num].kill_type) {
  1971. X                    case KILL_SUBJ:
  1972. X                        if (fgets (buf, sizeof buf, fp) != NULL) {
  1973. X                            buf[strlen (buf)-1] = '\0';
  1974. X                            killf[kill_num].kill_subj = str_dup (buf);
  1975. X                        }
  1976. X                        break;
  1977. X                    case KILL_FROM:
  1978. X                        if (fgets (buf, sizeof buf, fp) != NULL) {
  1979. X                            buf[strlen (buf)-1] = '\0';
  1980. X                            killf[kill_num].kill_from = str_dup (buf);
  1981. X                        }
  1982. X                        break;
  1983. X                    case KILL_BOTH:
  1984. X                        if (fgets (buf, sizeof buf, fp) != NULL) {
  1985. X                            buf[strlen (buf)-1] = '\0';
  1986. X                            killf[kill_num].kill_subj = str_dup (buf);
  1987. X                        }
  1988. X                        if (fgets (buf, sizeof buf, fp) != NULL) {
  1989. X                            buf[strlen (buf)-1] = '\0';
  1990. X                            killf[kill_num].kill_from = str_dup (buf);
  1991. X                        }
  1992. X                        break;
  1993. X                    default:
  1994. X                        goto corrupt_killfile;
  1995. X                }
  1996. X                kill_num++;
  1997. X            }
  1998. X        }
  1999. X        fclose (fp);
  2000. X        set_tin_uid_gid ();
  2001. X        return TRUE;        
  2002. X    } else {
  2003. X        set_tin_uid_gid ();
  2004. X        return FALSE;
  2005. X    }
  2006. X
  2007. corrupt_killfile:
  2008. X    fclose (fp);
  2009. X    killf[kill_num].kill_type = 0;
  2010. X    error_message ("corrupt kill file %s", killfile);
  2011. X    set_tin_uid_gid ();
  2012. X    return FALSE;
  2013. }
  2014. X
  2015. /*
  2016. X *  write_kill_file - write kill strings to ~/.tin/kill
  2017. X */
  2018. X
  2019. void write_kill_file ()
  2020. {
  2021. X    FILE *fp;
  2022. X    int i;
  2023. X    
  2024. X    set_real_uid_gid ();
  2025. X
  2026. X    if (kill_num && (fp = fopen (killfile, "w")) != NULL) {
  2027. X        wait_message (txt_saving);
  2028. X        fprintf (fp, "# 1st line  1=(Subject: only)  2=(From: only)  3=(Subject: & From:)\n");
  2029. X        fprintf (fp, "# 2nd line  0=(kill on all newsgroups)  >0=(kill on specific newsgroup)\n");
  2030. X        for (i=0 ; i < kill_num ; i++) {
  2031. X            if (killf[i].kill_type && (killf[i].kill_subj || killf[i].kill_from)) {
  2032. X                fprintf (fp, "#\n# kill description %d\n", i+1);
  2033. X                fprintf (fp, "%d\n", killf[i].kill_type);
  2034. X                fprintf (fp, "%ld\n", killf[i].kill_group);
  2035. X                switch (killf[i].kill_type) {
  2036. X                    case KILL_SUBJ:
  2037. X                        fprintf (fp, "%s\n", killf[i].kill_subj);
  2038. X                        break;
  2039. X                    case KILL_FROM:
  2040. X                        fprintf (fp, "%s\n", killf[i].kill_from);
  2041. X                        break;
  2042. X                    case KILL_BOTH:
  2043. X                        fprintf (fp, "%s\n", killf[i].kill_subj);
  2044. X                        fprintf (fp, "%s\n", killf[i].kill_from);
  2045. X                        break;
  2046. X                }
  2047. X            }
  2048. X        }
  2049. X        fclose (fp);
  2050. X        chmod (killfile, 0600);
  2051. X    }
  2052. X    set_tin_uid_gid ();
  2053. }
  2054. X
  2055. /*
  2056. X *  options menu so that the user can dynamically change parameters
  2057. X */
  2058. int kill_art_menu (group_name, index)
  2059. X    char *group_name;
  2060. X    int index;
  2061. {
  2062. X    char text[LEN];
  2063. X    char kill_from[LEN];
  2064. X    char kill_subj[LEN];
  2065. X    char kill_group[LEN];
  2066. X    char ch_default = 's';
  2067. X    char *str;    
  2068. X    int ch;
  2069. X    int counter;
  2070. X    int killed = TRUE;
  2071. X    int kill_from_ok = FALSE;
  2072. X    int kill_subj_ok = FALSE;
  2073. X    int kill_every_group;
  2074. X
  2075. #ifdef SIGTSTP
  2076. X    SIGTYPE (*susp)();
  2077. X
  2078. X    if (do_sigtstp) {
  2079. #ifdef POSIX_JOB_CONTROL
  2080. X        sigemptyset (&kill_act.sa_mask);
  2081. X        kill_act.sa_flags = SA_RESTART | SA_RESETHAND;
  2082. X        kill_act.sa_handler = SIG_DFL;
  2083. X        sigaction (SIGTSTP, &kill_act, &old_act);
  2084. X        kill_act.sa_handler = SIG_IGN;
  2085. X        sigaction (SIGTSTP, &kill_act, 0L);
  2086. #else
  2087. X        susp = signal (SIGTSTP, SIG_DFL);
  2088. X        signal (SIGTSTP, SIG_IGN);
  2089. #endif
  2090. X    }
  2091. #endif
  2092. X    
  2093. X    sprintf (kill_group, "%s only", group_name);
  2094. X    my_strncpy (text, arts[index].subject, COLS-35);
  2095. X    sprintf (kill_subj, txt_kill_subject, text);
  2096. X    if (arts[index].name != (char *) 0) {
  2097. X        sprintf (msg, "%s (%s)", arts[index].from, arts[index].name);
  2098. X        my_strncpy (text, msg, COLS-35);
  2099. X    } else {
  2100. X        my_strncpy (text, arts[index].from, COLS-35);
  2101. X    }
  2102. X    sprintf (kill_from, txt_kill_from, text);
  2103. X    text[0] = '\0';
  2104. X    
  2105. X    ClearScreen ();
  2106. X
  2107. X    center_line (0, TRUE, txt_kill_menu);
  2108. X    
  2109. X    MoveCursor(INDEX_TOP, 0);
  2110. X    printf ("%s\r\n\r\n", txt_kill_text);
  2111. X    printf ("%s\r\n\r\n\r\n", txt_kill_text_type);
  2112. X    printf ("%s\r\n\r\n", kill_subj);
  2113. X    printf ("%s\r\n\r\n\r\n", kill_from);
  2114. X    printf ("%s%s", txt_kill_group, kill_group);
  2115. X    fflush(stdout);
  2116. X
  2117. X    show_menu_help (txt_help_kill_text);
  2118. X    if (! prompt_menu_string (INDEX_TOP, (int) strlen (txt_kill_text), text)) {
  2119. X        return FALSE;
  2120. X    }
  2121. X
  2122. X    if (text[0]) {
  2123. X        show_menu_help (txt_help_kill_text_type);
  2124. X        counter = 1;
  2125. X        MoveCursor (INDEX_TOP+2, (int) strlen (txt_kill_text_type));
  2126. SHAR_EOF
  2127. true || echo 'restore of kill.c failed'
  2128. fi
  2129. echo 'End of tin1.1 part 5'
  2130. echo 'File kill.c is continued in part 6'
  2131. echo 6 > _shar_seq_.tmp
  2132. exit 0
  2133.  
  2134. --
  2135. NAME   Iain Lea 
  2136. EMAIL  iain%anl433.uucp@germany.eu.net
  2137. SNAIL  Siemens AG, ANL A433SZ, Gruendlacher Str. 248, 8510 Fuerth, Germany.
  2138. PHONE  +49-911-3089-407 (work) +49-911-331963 (home) +49-911-3089-290 (FAX)  
  2139. -- 
  2140.  Dr. med. dipl.-math Dieter Becker           Tel.: (0 / +49) 6841 - 16 3046
  2141.  Medizinische Universitaets- und Poliklinik  Fax.: (0 / +49) 6841 - 16 3369
  2142.  Innere Medizin III                         
  2143.  D - 6650 Homburg / Saar                     Email: becker@med-in.uni-sb.de
  2144. exit 0 # Just in case...
  2145.