tin  2.4.4
About: TIN is a threaded NNTP and spool based UseNet newsreader.
  Fossies Dox: tin-2.4.4.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

select.c
Go to the documentation of this file.
1 /*
2  * Project : tin - a Usenet reader
3  * Module : select.c
4  * Author : I. Lea & R. Skrenta
5  * Created : 1991-04-01
6  * Updated : 2019-09-16
7  * Notes :
8  *
9  * Copyright (c) 1991-2020 Iain Lea <iain@bricbrac.de>, Rich Skrenta <skrenta@pbm.com>
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  * this list of conditions and the following disclaimer.
18  *
19  * 2. Redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in the
21  * documentation and/or other materials provided with the distribution.
22  *
23  * 3. Neither the name of the copyright holder nor the names of its
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 
41 #ifndef TIN_H
42 # include "tin.h"
43 #endif /* !TIN_H */
44 #ifndef TCURSES_H
45 # include "tcurses.h"
46 #endif /* !TCURSES_H */
47 
48 
49 static struct t_fmt sel_fmt;
50 
51 /*
52  * Local prototypes
53  */
54 static t_function select_left(void);
55 static t_function select_right(void);
56 static int active_comp(t_comptype p1, t_comptype p2);
57 static int reposition_group(struct t_group *group, int default_num);
58 static int save_restore_curr_group(t_bool saving);
59 static t_bool pos_next_unread_group(t_bool redraw);
61 static void build_gline(int i);
62 static void catchup_group(struct t_group *group, t_bool goto_next_unread_group);
63 static void draw_group_arrow(void);
64 static void read_groups(void);
65 static void select_done(void);
66 static void select_quit(void);
67 static void select_read_group(void);
68 static void sort_active_file(void);
69 static void subscribe_pattern(const char *prompt, const char *message, const char *result, t_bool state);
70 static void sync_active_file(void);
71 static void yank_active_file(void);
72 #ifdef NNTP_ABLE
73  static char *lookup_msgid(char *msgid);
74  static int show_article_by_msgid(void);
75  static struct t_group *get_group_from_list(char *newsgroups);
76 #endif /* NNTP_ABLE */
77 
78 
79 /*
80  * selmenu.curr = index (start at 0) of cursor position on menu,
81  * or -1 when no groups visible on screen
82  * selmenu.max = Total # of groups in my_group[]
83  * selmenu.first is static here
84  */
86 
87 static int groupname_len; /* max. group name length */
88 static int flags_offset;
89 static int ucnt_offset;
90 
91 
92 static t_function
94  void)
95 {
96  return GLOBAL_QUIT;
97 }
98 
99 
100 static t_function
102  void)
103 {
104  return SELECT_ENTER_GROUP;
105 }
106 
107 
108 void
110  int start_groupnum,
111  int num_cmd_line_groups)
112 {
113  char buf[LEN];
114  char key[MAXKEYLEN];
115  int i, n;
116  t_function func;
117 
118  selmenu.curr = start_groupnum;
119 
120 #ifdef READ_CHAR_HACK
121  setbuf(stdin, 0);
122 #endif /* READ_CHAR_HACK */
123 
124  Raw(TRUE);
125  ClearScreen();
126 
127  /*
128  * If user specified only 1 cmd line groupname (eg. tin -r alt.sources)
129  * then go there immediately.
130  */
131  if (num_cmd_line_groups == 1)
133 
134  cursoroff();
135  show_selection_page(); /* display group selection page */
136 
137  forever {
138  if (!resync_active_file()) {
139  if (reread_active_after_posting()) /* reread active file if necessary */
141  } else {
142  if (!yanked_out)
143  yanked_out = bool_not(yanked_out); /* yank out if yanked in */
144  }
145 
146  set_xclick_on();
147 
149  case GLOBAL_ABORT: /* Abort */
150  break;
151 
152  case DIGIT_1:
153  case DIGIT_2:
154  case DIGIT_3:
155  case DIGIT_4:
156  case DIGIT_5:
157  case DIGIT_6:
158  case DIGIT_7:
159  case DIGIT_8:
160  case DIGIT_9:
161  if (selmenu.max)
163  else
165  break;
166 
167 #ifndef NO_SHELL_ESCAPE
168  case GLOBAL_SHELL_ESCAPE:
169  do_shell_escape();
170  break;
171 #endif /* !NO_SHELL_ESCAPE */
172 
173  case GLOBAL_FIRST_PAGE: /* show first page of groups */
174  top_of_list();
175  break;
176 
177  case GLOBAL_LAST_PAGE: /* show last page of groups */
178  end_of_list();
179  break;
180 
181  case GLOBAL_PAGE_UP:
182  page_up();
183  break;
184 
185  case GLOBAL_PAGE_DOWN:
186  page_down();
187  break;
188 
189  case GLOBAL_LINE_UP:
190  move_up();
191  break;
192 
193  case GLOBAL_LINE_DOWN:
194  move_down();
195  break;
196 
197  case GLOBAL_SCROLL_DOWN:
198  scroll_down();
199  break;
200 
201  case GLOBAL_SCROLL_UP:
202  scroll_up();
203  break;
204 
205  case SELECT_SORT_ACTIVE: /* sort active groups */
207  break;
208 
209  case GLOBAL_SET_RANGE:
210  if (selmenu.max) {
213  } else
215  break;
216 
222  else {
223  if ((i = search_active((func == GLOBAL_SEARCH_SUBJECT_FORWARD), (func == GLOBAL_SEARCH_REPEAT))) != -1) {
224  move_to_item(i);
225  clear_message();
226  }
227  }
228  break;
229 
230  case SELECT_ENTER_GROUP: /* go into group */
232  break;
233 
234  case SELECT_ENTER_NEXT_UNREAD_GROUP: /* enter next group containing unread articles */
236  read_groups();
237  break; /* Nothing more to do at the moment */
238 
240  my_retouch(); /* TODO: not done elsewhere, maybe should be in show_selection_page */
241  set_xclick_off();
243  break;
244 
245  case SELECT_RESET_NEWSRC: /* reset .newsrc */
246  if (no_write) {
248  break;
249  }
250  if (prompt_yn(_(txt_reset_newsrc), FALSE) == 1) {
251  reset_newsrc();
253  selmenu.curr = 0;
255  }
256  break;
257 
258  case CATCHUP: /* catchup - mark all articles as read */
259  case CATCHUP_NEXT_UNREAD: /* and goto next unread group */
260  if (selmenu.max)
262  else
264  break;
265 
266  case GLOBAL_EDIT_FILTER:
270  break;
271 
272  case SELECT_TOGGLE_DESCRIPTIONS: /* toggle newsgroup descriptions */
273  if (sel_fmt.show_grpdesc) {
275  if (show_description)
278  } else
280  break;
281 
282  case SELECT_GOTO: /* prompt for a new group name */
283  {
284  int oldmax = selmenu.max;
285 
286  if ((n = choose_new_group()) >= 0) {
287  /*
288  * If a new group was added and it is on the actual screen
289  * draw it. If it is off screen the redraw will handle it.
290  */
291  if (oldmax != selmenu.max && n >= selmenu.first && n < selmenu.first + NOTESLINES)
292  build_gline(n);
293  move_to_item(n);
294  }
295  }
296  break;
297 
298  case GLOBAL_HELP:
301  break;
302 
303 #ifdef NNTP_ABLE
305  switch (show_article_by_msgid()) {
306  case 0:
308  break;
309 
310  case GRP_QUIT:
311  select_quit();
312  break;
313 
314  default:
315  break;
316  }
317  break;
318 #endif /* NNTP_ABLE */
319 
320  case GLOBAL_TOGGLE_HELP_DISPLAY: /* toggle mini help menu */
323  break;
324 
329  break;
330 
331 #ifdef HAVE_COLOR
332  case GLOBAL_TOGGLE_COLOR:
333  if (toggle_color()) {
335  show_color_status();
336  }
337  break;
338 #endif /* HAVE_COLOR */
339 
340  case GLOBAL_TOGGLE_INFO_LAST_LINE: /* display group description */
343  break;
344 
345  case SELECT_MOVE_GROUP: /* reposition group within group list */
346  /* TODO: move all this to reposition_group() */
347  if (!selmenu.max) {
349  break;
350  }
351 
352  if (!CURR_GROUP.subscribed) {
354  break;
355  }
356 
357  if (no_write) {
359  break;
360  }
361 
362  n = selmenu.curr;
367  else {
368  i = selmenu.curr;
369  selmenu.curr = n;
370  erase_arrow();
371  selmenu.curr = i;
372  clear_message();
374  }
375  break;
376 
377  case GLOBAL_OPTION_MENU:
380  break;
381 
382  case SELECT_NEXT_UNREAD_GROUP: /* goto next unread group */
384  break;
385 
386  case GLOBAL_QUIT: /* quit */
387  select_done();
388  break;
389 
390  case GLOBAL_QUIT_TIN: /* quit, no ask */
391  select_quit();
392  break;
393 
394  case SELECT_QUIT_NO_WRITE: /* quit, but don't save configuration */
395  if (prompt_yn(_(txt_quit_no_write), TRUE) == 1)
396  tin_done(EXIT_SUCCESS, NULL);
398  break;
399 
401  /*
402  * If in tinrc.show_only_unread_groups mode toggle all
403  * subscribed to groups and only groups that contain unread
404  * articles
405  */
407  /*
408  * as we effectively do a yank out on each change, set yanked_out accordingly
409  */
410  yanked_out = TRUE;
411  wait_message(0, _(txt_reading_groups), (tinrc.show_only_unread_groups) ? _("unread") : _("all"));
412 
413  toggle_my_groups(NULL);
417  else
418  clear_message();
419  break;
420 
421  case GLOBAL_BUGREPORT:
422  bug_report();
423  break;
424 
425  case SELECT_SUBSCRIBE: /* subscribe to current group */
426  if (!selmenu.max) {
428  break;
429  }
430  if (no_write) {
432  break;
433  }
434  if (!CURR_GROUP.subscribed && !CURR_GROUP.bogus) {
438  move_down();
439  }
440  break;
441 
442  case SELECT_SUBSCRIBE_PATTERN: /* subscribe to groups matching pattern */
443  if (no_write) {
445  break;
446  }
448  break;
449 
450  case SELECT_UNSUBSCRIBE: /* unsubscribe to current group */
451  if (!selmenu.max) {
453  break;
454  }
455  if (no_write) {
457  break;
458  }
459  if (CURR_GROUP.subscribed) {
460  mark_screen(selmenu.curr, flags_offset, CURR_GROUP.newgroup ? "N" : "u");
463  move_down();
464  } else if (CURR_GROUP.bogus && tinrc.strip_bogus == BOGUS_SHOW) {
465  /* Bogus groups aren't subscribed to avoid confusion */
466  /* Note that there is no way to remove the group from active[] */
467  snprintf(buf, sizeof(buf), _(txt_remove_bogus), CURR_GROUP.name);
468  write_newsrc(); /* save current newsrc */
469  delete_group(CURR_GROUP.name); /* remove bogus group */
470  read_newsrc(newsrc, TRUE); /* reload newsrc */
471  toggle_my_groups(NULL); /* keep current display-state */
472  show_selection_page(); /* redraw screen */
473  info_message(buf);
474  }
475  break;
476 
477  case SELECT_UNSUBSCRIBE_PATTERN: /* unsubscribe to groups matching pattern */
478  if (no_write) {
480  break;
481  }
484  break;
485 
486  case GLOBAL_VERSION: /* show tin version */
488  break;
489 
490  case GLOBAL_POST: /* post a basenote */
491  if (!selmenu.max) {
492  if (!can_post) {
494  break;
495  }
498  break;
501  break;
502  } else {
504 #if 1 /* TODO: fix the rest of the code so we don't need this anymore */
505  /*
506  * this is a gross hack to avoid a crash in the
507  * CHARSET_CONVERSION conversion case in new_part()
508  * which currently relies on CURR_GROUP
509  */
511  /*
512  * and the next hack to avoid a grabbled selection
513  * screen after the posting
514  */
515  toggle_my_groups(NULL);
516  toggle_my_groups(NULL);
517 #endif /* 1 */
518  }
519  } else
520  STRCPY(buf, CURR_GROUP.name);
521  if (!can_post && !CURR_GROUP.bogus && !CURR_GROUP.attribute->mailing_list) {
523  break;
524  }
525  if (post_article(buf))
527  break;
528 
529  case GLOBAL_POSTPONED: /* post postponed article */
530  if (can_post) {
533  } else
535  break;
536 
537  case GLOBAL_DISPLAY_POST_HISTORY: /* display messages posted by user */
538  if (user_posted_messages())
540  break;
541 
542  case SELECT_YANK_ACTIVE: /* yank in/out rest of groups from active */
544  break;
545 
546  case SELECT_SYNC_WITH_ACTIVE: /* Re-read active file to see if any new news */
548  if (!yanked_out)
549  yank_active_file(); /* yank out if yanked in */
550  break;
551 
553  if (!selmenu.max) {
555  break;
556  }
558  if (CURR_GROUP.newsrc.num_unread)
559  STRCPY(buf, tin_ltoa(CURR_GROUP.newsrc.num_unread, sel_fmt.len_ucnt));
560  else {
561  size_t j = 0;
562 
563  while (j < sel_fmt.len_ucnt)
564  buf[j++] = ' ';
565  buf[j] = '\0';
566  }
568  break;
569 
570  default:
572  }
573  }
574 }
575 
576 
577 void
579  void)
580 {
581  char buf[LEN];
582  int i;
583  size_t len;
584 
586  currmenu = &selmenu;
588  groupname_len = 0;
589  flags_offset = 0;
590  mark_offset = 0;
591  ucnt_offset = 0;
592 
593  if (read_news_via_nntp)
594  snprintf(buf, sizeof(buf), "%s (%s %d%s)", _(txt_group_selection), nntp_server, selmenu.max, (tinrc.show_only_unread_groups ? _(" R") : ""));
595  else
596  snprintf(buf, sizeof(buf), "%s (%d%s)", _(txt_group_selection), selmenu.max, (tinrc.show_only_unread_groups ? _(" R") : ""));
597 
598  if (selmenu.curr < 0)
599  selmenu.curr = 0;
600 
601  ClearScreen();
603  show_title(buf);
604 
606  /*
607  * calculate max length of groupname field
608  * if yanked in (yanked_out == FALSE) check all groups in active file
609  * otherwise just subscribed to groups
610  */
611  if (yanked_out) {
612  for (i = 0; i < selmenu.max; i++) {
613  if ((len = strwidth(active[my_group[i]].name)) > sel_fmt.len_grpname)
614  sel_fmt.len_grpname = len;
615  }
616  } else {
617  for_each_group(i) {
618  if ((len = strwidth(active[i].name)) > sel_fmt.len_grpname)
619  sel_fmt.len_grpname = len;
620  }
621  }
622  }
623 
625 
628  if (groupname_len < 0)
629  groupname_len = 0;
630 
631  if (!sel_fmt.len_grpdesc)
633  else {
636  }
637 
640 
641  for (i = selmenu.first; i < selmenu.first + NOTESLINES && i < selmenu.max; i++)
642  build_gline(i);
643 
645 
646 #ifdef NNTP_ABLE
647  did_reconnect = FALSE;
648 #endif /* NNTP_ABLE */
649 
650  if (selmenu.max <= 0) {
652  return;
653  }
654 
656 }
657 
658 
659 static void
661  int i)
662 {
663  char *sptr, *fmt, *buf;
664  char subs;
665  int n;
666  size_t j;
667 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
668  char *name_buf = NULL;
669  char *desc_buf = NULL;
670  wchar_t *active_name, *active_name2, *active_desc, *active_desc2;
671 #else
672  char *active_name, *active_name2;
673  size_t fill, len_start;
674 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
675 
676 #ifdef USE_CURSES
677  /*
678  * Allocate line buffer
679  * make it the same size like in !USE_CURSES case to simplify the code
680  */
681 # if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
682  sptr = my_malloc(cCOLS * MB_CUR_MAX + 2);
683 # else
684  sptr = my_malloc(cCOLS + 2);
685 # endif /* MULTIBYTE_ABLE && !NO_LOCALE */
686 #else
687  sptr = screen[INDEX2SNUM(i)].col;
688 #endif /* USE_CURSES */
689 
690  sptr[0] = '\0';
691  fmt = sel_fmt.str;
692  n = my_group[i];
693 
694  if (tinrc.draw_arrow)
695  strcat(sptr, " ");
696 
697  for (; *fmt; fmt++) {
698  if (*fmt != '%') {
699  strncat(sptr, fmt, 1);
700  continue;
701  }
702  switch (*++fmt) {
703  case '\0':
704  break;
705 
706  case '%':
707  strncat(sptr, fmt, 1);
708  break;
709 
710  case 'd':
711 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
712  if (show_description && active[n].description) {
713  active_desc = char2wchar_t(active[n].description);
714  if (active_desc) {
715  if ((active_desc2 = wcspart(active_desc, sel_fmt.len_grpdesc, TRUE)) != NULL) {
716  desc_buf = wchar_t2char(active_desc2);
717  free(active_desc);
718  free(active_desc2);
719  }
720  }
721  if (desc_buf) {
722  strcat(sptr, desc_buf);
723  FreeAndNull(desc_buf);
724  }
725  } else {
726  buf = sptr + strlen(sptr);
727  for (j = 0; j < sel_fmt.len_grpdesc; ++j)
728  *buf++ = ' ';
729  *buf = '\0';
730  }
731 #else
732  if (show_description && active[n].description) {
733  len_start = strwidth(sptr);
734  strncat(sptr, active[n].description, sel_fmt.len_grpdesc);
735  fill = sel_fmt.len_grpdesc - (strwidth(sptr) - len_start);
736  } else
737  fill = sel_fmt.len_grpdesc;
738  buf = sptr + strlen(sptr);
739  for (j = 0; j < fill; ++j)
740  *buf++ = ' ';
741  *buf = '\0';
742 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
743  break;
744 
745  case 'f':
746  /*
747  * Display a flag for this group if needed
748  * . Bogus groups are dumped immediately
749  * . Normal subscribed groups may be
750  * ' ' normal, 'X' not postable, 'M' moderated, '=' renamed
751  * . Newgroups are 'N'
752  * . Unsubscribed groups are 'u'
753  *
754  * TODO: make flags configurable via tinrc?
755  */
756  if (active[n].bogus) /* Group is not in active list */
757  subs = 'D';
758  else if (active[n].subscribed) /* Important that this precedes Newgroup */
759  subs = group_flag(active[n].moderated);
760  else
761  subs = ((active[n].newgroup) ? 'N' : 'u'); /* New (but unsubscribed) group or unsubscribed group */
762  buf = sptr + strlen(sptr);
763  *buf++ = subs;
764  *buf = '\0';
765  break;
766 
767  case 'G':
768 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
769  if ((active_name = char2wchar_t(active[n].name)) == NULL) /* If char2wchar_t() fails try again after replacing unprintable characters */
770  active_name = char2wchar_t(convert_to_printable(active[n].name, FALSE));
771 
772  if (active_name && tinrc.abbreviate_groupname) {
773  active_name2 = abbr_wcsgroupname(active_name, groupname_len);
774  free(active_name);
775  } else
776  active_name2 = active_name;
777 
778  if (active_name2 && (active_name = wcspart(active_name2, groupname_len, TRUE)) != NULL) {
779  free(active_name2);
780  name_buf = wchar_t2char(active_name);
781  free(active_name);
782  }
783  if (name_buf) {
784  strcat(sptr, name_buf);
785  FreeAndNull(name_buf);
786  }
787 #else
789  active_name = abbr_groupname(active[n].name, groupname_len);
790  else
791  active_name = my_strdup(active[n].name);
792 
793  active_name2 = my_malloc(groupname_len + 1);
794  snprintf(active_name2, groupname_len + 1, "%-*s", groupname_len, active_name);
795  strcat(sptr, active_name2);
796  free(active_name);
797  free(active_name2);
798 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
799  break;
800 
801  case 'n':
802  strcat(sptr, tin_ltoa(i + 1, sel_fmt.len_linenumber));
803  break;
804 
805  case 'U':
806  if (active[my_group[i]].inrange) {
807  buf = sptr + strlen(sptr);
808  for (j = 1; j < sel_fmt.len_ucnt; ++j)
809  *buf++ = ' ';
811  *buf = '\0';
812  } else if (active[my_group[i]].newsrc.num_unread) {
813  int getart_limit;
814  t_artnum num_unread;
815 
817  num_unread = active[my_group[i]].newsrc.num_unread;
818  if (getart_limit > 0 && getart_limit < num_unread)
819  num_unread = getart_limit;
820  strcat(sptr, tin_ltoa(num_unread, sel_fmt.len_ucnt));
821  } else {
822  buf = sptr + strlen(sptr);
823  for (j = 0; j < sel_fmt.len_ucnt; ++j)
824  *buf++ = ' ';
825  *buf = '\0';
826  }
827  break;
828 
829  default:
830  break;
831  }
832  }
833 #ifndef USE_CURSES
834  if (tinrc.strip_blanks)
835  strcat(strip_line(sptr), cCRLF);
836 #endif /* !USE_CURSES */
837 
838  WriteLine(INDEX2LNUM(i), sptr);
839 
840 #ifdef USE_CURSES
841  free(sptr);
842 #endif /* USE_CURSES */
843 }
844 
845 
846 static void
848  void)
849 {
850  if (!selmenu.max)
852  else {
854  if (CURR_GROUP.aliasedto)
856  else if (tinrc.info_in_last_line)
857  info_message("%s", CURR_GROUP.description ? CURR_GROUP.description : _(txt_no_description));
858  else if (selmenu.curr == selmenu.max - 1)
860  }
861 }
862 
863 
864 static void
866  void)
867 {
871 }
872 
873 
874 static void
876  void)
877 {
878  if (yanked_out && selmenu.max == num_active) { /* All groups currently present? */
880  return;
881  }
882 
883  if (yanked_out) { /* Yank in */
884  int i;
885  int prevmax = selmenu.max;
886 
887  save_restore_curr_group(TRUE); /* Save group position */
888 
889  /*
890  * Reset counter and load all the groups in active[] into my_group[]
891  */
892  selmenu.max = 0;
893  for_each_group(i)
894  my_group[selmenu.max++] = i;
895 
896  selmenu.curr = save_restore_curr_group(FALSE); /* Restore previous group position */
900  } else { /* Yank out */
901  toggle_my_groups(NULL);
906  }
907 }
908 
909 
910 /*
911  * Sort active[] and associated tin_sort() helper function
912  */
913 static int
915  t_comptype p1,
916  t_comptype p2)
917 {
918  const struct t_group *s1 = (const struct t_group *) p1;
919  const struct t_group *s2 = (const struct t_group *) p2;
920 
921  return strcasecmp(s1->name, s2->name);
922 }
923 
924 
925 /*
926  * Call with TRUE to file away the current cursor position
927  * Call again with FALSE to return a suggested value to restore the
928  * current cursor (selmenu.curr) position
929  */
930 static int
932  t_bool saving)
933 {
934  static char *oldgroup;
935  static int oldmax = 0;
936  int ret;
937 
938  /*
939  * Take a copy of the current groupname, if present
940  */
941  if (saving) {
942  oldmax = selmenu.max;
943  if (oldmax)
944  oldgroup = my_strdup(CURR_GROUP.name);
945  return 0;
946  }
947 
948  /*
949  * Find & return the new screen position of the group
950  */
951  ret = -1;
952 
953  if (oldmax) {
954  ret = my_group_find(oldgroup);
955  FreeAndNull(oldgroup);
956  }
957 
958  if (ret == -1) { /* Group not present, return something semi-useful */
959  if (selmenu.max > 0)
960  ret = selmenu.max - 1;
961  else
962  ret = 0;
963  }
964  return ret;
965 }
966 
967 
968 static void
970  void)
971 {
973 
974  tin_sort(active, (size_t) num_active, sizeof(struct t_group), active_comp);
976 
978 
980 }
981 
982 
983 int
985  void)
986 {
987  char *prompt;
988  int idx;
989 
991 
993  free(prompt);
994  return -1;
995  }
996  free(prompt);
997 
999 
1000  if (tinrc.default_goto_group[0] == '\0')
1001  return -1;
1002 
1003  clear_message();
1004 
1005  if ((idx = my_group_add(tinrc.default_goto_group, TRUE)) == -1)
1007 
1008  return idx;
1009 }
1010 
1011 
1012 /*
1013  * Return new value for selmenu.max, skipping any new newsgroups that have been
1014  * found
1015  */
1016 int
1018  void)
1019 {
1020  int i = 0;
1021 
1022  if (selmenu.max) {
1023  while (i < selmenu.max && active[my_group[i]].newgroup)
1024  i++;
1025  }
1026 
1027  return i;
1028 }
1029 
1030 
1031 /*
1032  * Find a group in the users selection list, my_group[].
1033  * If 'add' is TRUE, then add the supplied group return the index into
1034  * my_group[] if group is added or was already there. Return -1 if group
1035  * is not in active[]
1036  *
1037  * NOTE: can't be static due to my_group_add() macro
1038  */
1039 int
1041  const char *group,
1042  t_bool add,
1043  t_bool ignore_case)
1044 {
1045  int i, j;
1046 
1047  if ((i = find_group_index(group, ignore_case)) < 0)
1048  return -1;
1049 
1050  for (j = 0; j < selmenu.max; j++) {
1051  if (my_group[j] == i)
1052  return j;
1053  }
1054 
1055  if (add) {
1056  my_group[selmenu.max++] = i;
1057  return (selmenu.max - 1);
1058  }
1059 
1060  return -1;
1061 }
1062 
1063 
1064 static int
1066  struct t_group *group,
1067  int default_num)
1068 {
1069  char buf[LEN];
1070  char pos[LEN];
1071  int pos_num, newgroups;
1072 
1073  /* Have already trapped no_write at this point */
1074 
1075  snprintf(buf, sizeof(buf), _(txt_newsgroup_position), group->name,
1076  (tinrc.default_move_group ? tinrc.default_move_group : default_num + 1));
1077 
1078  if (!prompt_string(buf, pos, HIST_MOVE_GROUP))
1079  return default_num;
1080 
1081  if (strlen(pos))
1082  pos_num = ((pos[0] == '$') ? selmenu.max : atoi(pos));
1083  else {
1085  pos_num = tinrc.default_move_group;
1086  else
1087  return default_num;
1088  }
1089 
1090  if (pos_num > selmenu.max)
1091  pos_num = selmenu.max;
1092  else if (pos_num <= 0)
1093  pos_num = 1;
1094 
1095  newgroups = skip_newgroups();
1096 
1097  /*
1098  * Can't move into newgroups, they aren't in .newsrc
1099  */
1100  if (pos_num <= newgroups) {
1102  return default_num;
1103  }
1104 
1105  wait_message(0, _(txt_moving), group->name);
1106 
1107  /*
1108  * seems to have the side effect of rearranging
1109  * my_groups, so tinrc.show_only_unread_groups has to be updated
1110  */
1112 
1113  /*
1114  * New newgroups aren't in .newsrc so we need to offset to
1115  * get the right position
1116  */
1117  if (pos_group_in_newsrc(group, pos_num - newgroups)) {
1119  tinrc.default_move_group = pos_num;
1120  return (pos_num - 1);
1121  } else {
1122  tinrc.default_move_group = default_num + 1;
1123  return default_num;
1124  }
1125 }
1126 
1127 
1128 static void
1130  struct t_group *group,
1131  t_bool goto_next_unread_group)
1132 {
1133  char *smsg = NULL;
1134 
1135  if ((!TINRC_CONFIRM_ACTION) || prompt_yn(sized_message(&smsg, _(txt_mark_group_read), group->name), TRUE) == 1) {
1136  grp_mark_read(group, NULL);
1137  {
1138  char buf[LEN];
1139  size_t i = 0;
1140 
1141  while (i < sel_fmt.len_ucnt)
1142  buf[i++] = ' ';
1143  buf[i] = '\0';
1145  }
1146 
1147  if (goto_next_unread_group)
1149  else
1150  move_down();
1151  }
1152  FreeIfNeeded(smsg);
1153 }
1154 
1155 
1156 /*
1157  * Set selmenu.curr to next group with unread arts
1158  * If the current group has unread arts, it will be found first !
1159  * If redraw is set, update the selection menu appropriately
1160  * Return FALSE if no groups left to read
1161  * TRUE at all other times
1162  */
1163 static t_bool
1165  t_bool redraw)
1166 {
1167  int i;
1168  t_bool all_groups_read = TRUE;
1169 
1170  if (!selmenu.max)
1171  return FALSE;
1172 
1173  for (i = selmenu.curr; i < selmenu.max; i++) {
1174  if (UNREAD_GROUP(i)) {
1175  all_groups_read = FALSE;
1176  break;
1177  }
1178  }
1179 
1180  if (all_groups_read) {
1181  for (i = 0; i < selmenu.curr; i++) {
1182  if (UNREAD_GROUP(i)) {
1183  all_groups_read = FALSE;
1184  break;
1185  }
1186  }
1187  }
1188 
1189  if (all_groups_read) {
1191  return FALSE;
1192  }
1193 
1194  if (redraw)
1195  move_to_item(i);
1196  else
1197  selmenu.curr = i;
1198 
1199  return TRUE;
1200 }
1201 
1202 
1203 /*
1204  * This is the main loop that cycles through, reading groups.
1205  * We keep going until we return to the selection screen or exit tin
1206  */
1207 static void
1209  void)
1210 {
1211  t_bool done = FALSE;
1212 
1213  clear_message();
1214 
1215  while (!done) { /* if xmin > xmax the newsservers active is broken */
1216  switch (group_page(&CURR_GROUP)) {
1217  case GRP_QUIT:
1218  select_quit();
1219  break;
1220 
1221  case GRP_NEXT:
1222  if (selmenu.curr + 1 < selmenu.max)
1223  selmenu.curr++;
1224  done = TRUE;
1225  break;
1226 
1227  case GRP_NEXTUNREAD:
1229  done = TRUE;
1230  break;
1231 
1232  case GRP_ENTER: /* group_page() has already set selmenu.curr */
1233  break;
1234 
1235  case GRP_RETSELECT:
1236  case GRP_EXIT:
1237  default:
1238  done = TRUE;
1239  break;
1240  }
1241  }
1242 
1243  if (!need_reread_active_file())
1245 }
1246 
1247 
1248 /*
1249  * Toggle my_group[] between all groups / only unread groups
1250  * We make a special case for Newgroups (always appear, at the top)
1251  * and Bogus groups if tinrc.strip_bogus = BOGUS_SHOW
1252  */
1253 void
1255  const char *group)
1256 {
1257 #if 1
1258  FILE *fp;
1259  char buf[NEWSRC_LINE];
1260  char *ptr;
1261 #endif /* 1 */
1262  int i;
1263 
1264  /*
1265  * Save current or next group with unread arts for later use
1266  */
1267  if (selmenu.max) {
1268  int old_curr_group_idx = 0;
1269 
1270  if (group != NULL) {
1271  if ((i = my_group_find(group)) >= 0)
1272  old_curr_group_idx = i;
1273  } else
1274  old_curr_group_idx = (selmenu.curr == -1) ? 0 : selmenu.curr;
1275 
1277  for (i = old_curr_group_idx; i < selmenu.max; i++) {
1278  if (UNREAD_GROUP(i) || active[my_group[i]].newgroup) {
1279  old_curr_group_idx = i;
1280  break;
1281  }
1282  }
1283  }
1284  selmenu.curr = old_curr_group_idx; /* Set current group to save */
1285  } else
1286  selmenu.curr = 0;
1287 
1289 
1290  selmenu.max = skip_newgroups(); /* Reposition after any newgroups */
1291 
1292  /* TODO: why re-read .newsrc here, instead of something like this... */
1293 #if 0
1294  for_each_group(i) {
1295  if (active[i].subscribed) {
1297  if (active[i].newsrc.num_unread > 0 || (active[i].bogus && tinrc.strip_bogus == BOGUS_SHOW))
1298  my_group[selmenu.max++] = i;
1299  } else
1300  my_group[selmenu.max++] = i;
1301  }
1302  }
1303 #else
1304  /* preserve group ordering based on newsrc */
1305  if ((fp = fopen(newsrc, "r")) == NULL)
1306  return;
1307 
1308  while (fgets(buf, (int) sizeof(buf), fp) != NULL) {
1309  if ((ptr = strchr(buf, SUBSCRIBED)) != NULL) {
1310  *ptr = '\0';
1311 
1312  if ((i = find_group_index(buf, FALSE)) < 0)
1313  continue;
1314 
1316  if (active[i].newsrc.num_unread || (active[i].bogus && tinrc.strip_bogus == BOGUS_SHOW))
1318  } else
1320  }
1321  }
1322  fclose(fp);
1323 #endif /* 0 */
1324  selmenu.curr = save_restore_curr_group(FALSE); /* Restore saved group position */
1325 }
1326 
1327 
1328 /*
1329  * Subscribe or unsubscribe from a list of groups. List can be full list as
1330  * supported by match_group_list()
1331  */
1332 static void
1334  const char *prompt,
1335  const char *message,
1336  const char *result,
1337  t_bool state)
1338 {
1339  char buf[LEN];
1340  int i, subscribe_num = 0;
1341 
1342  if (!num_active || no_write)
1343  return;
1344 
1345  if (!prompt_string(prompt, buf, HIST_OTHER) || !*buf) {
1346  clear_message();
1347  return;
1348  }
1349 
1350  wait_message(0, "%s", message);
1351 
1352  for_each_group(i) {
1353  if (match_group_list(active[i].name, buf)) {
1354  if (active[i].subscribed != (state != FALSE)) {
1355  spin_cursor();
1356  /* If found and group is not subscribed add it to end of my_group[]. */
1358  if (state) {
1360  grp_mark_unread(&active[i]);
1361  }
1362  subscribe_num++;
1363  }
1364  }
1365  }
1366 
1367  if (subscribe_num) {
1368  toggle_my_groups(NULL);
1370  info_message(result, subscribe_num);
1371  } else
1373 }
1374 
1375 
1376 /*
1377  * Does NOT return
1378  */
1379 static void
1381  void)
1382 {
1384  ClearScreen();
1385  tin_done(EXIT_SUCCESS, NULL); /* Tin END */
1386 }
1387 
1388 
1389 static void
1391  void)
1392 {
1393  if (!TINRC_CONFIRM_TO_QUIT || prompt_yn(_(txt_quit), TRUE) == 1)
1394  select_quit();
1395  if (!no_write && prompt_yn(_(txt_save_config), TRUE) == 1) {
1397  write_newsrc();
1398  }
1400 }
1401 
1402 
1403 static void
1405  void)
1406 {
1407  struct t_group *currgrp;
1408 
1409  if (!selmenu.max || selmenu.curr == -1) {
1411  return;
1412  }
1413 
1414  currgrp = &CURR_GROUP;
1415 
1416  if (currgrp->bogus) {
1418  return;
1419  }
1420 
1421  if (currgrp->xmax > 0 && (currgrp->xmin <= currgrp->xmax))
1422  read_groups();
1423  else
1425 }
1426 
1427 
1428 #ifdef NNTP_ABLE
1429 /*
1430  * Try to fetch articles Nesgroups-header via [X]HDR or XPAT.
1431  */
1432 static char *
1433 lookup_msgid(
1434  char *msgid)
1435 {
1437  if (!nntp_caps.hdr_cmd && !nntp_caps.xpat) {
1438  info_message(_(txt_lookup_func_not_available));
1439  return NULL;
1440  }
1441  if (msgid) {
1442  char *ptr, *r = NULL;
1443  static char *x = NULL;
1444  char buf[NNTP_STRLEN];
1445  int ret;
1446 
1447  if (nntp_caps.hdr_cmd) {
1448  snprintf(buf, sizeof(buf), "%s Newsgroups %s", nntp_caps.hdr_cmd, msgid);
1449  ret = new_nntp_command(buf, (nntp_caps.type == CAPABILITIES) ? OK_HDR : OK_HEAD, NULL, 0);
1450 
1451  switch (ret) {
1452  case OK_HEAD:
1453  case OK_HDR:
1454  while ((ptr = tin_fgets(FAKE_NNTP_FP, FALSE)) != NULL) {
1455 # ifdef DEBUG
1456  if (debug & DEBUG_NNTP)
1457  debug_print_file("NNTP", "<<<%s%s", logtime(), ptr);
1458 # endif /* DEBUG */
1459 
1460  if (ret == OK_HEAD) { /* RFC 2980 ("%s %s", id, grp) */
1461  if (!strncmp(ptr, msgid, strlen(msgid))) { /* INN, MPNews, Leafnode, Cnews nntpd */
1462  r = ptr + strlen(msgid) + 1;
1463  } else { /* DNEWS ("%d %s", num, grp) */
1464  r = ptr;
1465  while (*r && *r != ' ' && *r != '\t')
1466  r++;
1467  while (*r && (*r == ' ' || *r == '\t'))
1468  r++;
1469  }
1470  }
1471 
1472  if (ret == OK_HDR) { /* RFC 3977 ("0 %s", grp) */
1473  if (*ptr == '0' && (*(ptr + 1) == ' ' || *(ptr + 1) == '\t'))
1474  r = ptr + 2;
1475  }
1476 
1477  if (r)
1478  x = my_strdup(r);
1479  }
1480 
1481  if (x)
1482  return x;
1483 
1484  if (!r) {
1485 # ifdef DEBUG
1486  if ((debug & DEBUG_NNTP) && verbose > 1)
1487  debug_print_file("NNTP", "lookup_msgid(%s) response empty or not recognized", buf);
1488 # endif /* DEBUG */
1489  if (!nntp_caps.xpat)
1490  info_message(_(txt_lookup_func_not_available));
1491  }
1492  if (r || !nntp_caps.xpat)
1493  return NULL;
1494  break;
1495 
1496  case ERR_NOART:
1498  return NULL;
1499 
1500  default:
1501  if (!nntp_caps.xpat) { /* try only once */
1502  info_message(_(txt_lookup_func_not_available));
1503  return NULL;
1504  }
1505  break;
1506  }
1507  }
1508 
1509  if (nntp_caps.xpat) {
1510  snprintf(buf, sizeof(buf), "XPAT Newsgroups %s *", msgid);
1511  ret = new_nntp_command(buf, OK_HEAD, NULL, 0);
1512  r = NULL;
1513  switch (ret) {
1514  case OK_HEAD:
1515  while ((ptr = tin_fgets(FAKE_NNTP_FP, FALSE)) != NULL) {
1516 # ifdef DEBUG
1517  if (debug & DEBUG_NNTP)
1518  debug_print_file("NNTP", "<<<%s%s", logtime(), ptr);
1519 # endif /* DEBUG */
1520  if (!strncmp(ptr, msgid, strlen(msgid)))
1521  r = ptr + strlen(msgid) + 1;
1522 
1523  if (r)
1524  x = my_strdup(r);
1525  }
1526 
1527  if (x)
1528  return x;
1529 
1530  if (!r) {
1531 # ifdef DEBUG
1532  if ((debug & DEBUG_NNTP) && verbose > 1)
1533  debug_print_file("NNTP", "lookup_msgid(%s) response empty or not recognized", buf);
1534 # endif /* DEBUG */
1535  info_message(_(txt_lookup_func_not_available));
1536  /* nntp_caps.xpat = FALSE; */ /* ? */
1537  }
1538  return NULL;
1539 
1540  case ERR_NOART:
1542  return NULL;
1543 
1544  default:
1545  nntp_caps.xpat = FALSE;
1546  break;
1547  }
1548  }
1549  info_message(_(txt_lookup_func_not_available));
1550  }
1551  } else
1552  info_message("%s %s", _(txt_lookup_func_not_available), _(txt_lookup_func_not_nntp));
1553 
1554  return NULL;
1555 }
1556 
1557 
1558 /*
1559  * Get a message ID for the 'L' command. Add <> if needed.
1560  * Try to enter an appropriate group and display the referenced article.
1561  * If no group from the Newsgroups:-header is available, display the
1562  * contents of the header.
1563  */
1564 static int
1565 show_article_by_msgid(
1566  void)
1567 {
1568  char id[NNTP_STRLEN]; /* still way too big; RFC 3977 3.6 & RFC 5536 3.1.3 limit Message-ID to max 250 octets */
1569  char *idptr;
1570  char *newsgroups = NULL;
1571  int i, ret = 0;
1572  struct t_article *art;
1573  struct t_group *group = NULL;
1574  struct t_msgid *msgid = NULL;
1575  t_bool tmp_cache_overview_files;
1576  t_bool tmp_show_only_unread_arts;
1577 
1578  if (!(read_news_via_nntp && !read_saved_news)) {
1579  info_message("%s %s", _(txt_lookup_func_not_available), _(txt_lookup_func_not_nntp));
1580  return -1;
1581  }
1582 
1583  if (prompt_string(_(txt_enter_message_id), id + 1, HIST_MESSAGE_ID) && id[1]) {
1584  idptr = str_trim(id + 1);
1585  if (id[1] != '<') {
1586  id[0] = '<';
1587  strcat(id, ">");
1588  idptr = id;
1589  }
1590  newsgroups = lookup_msgid(idptr);
1591  }
1592 
1593  if (!newsgroups)
1594  return -1;
1595 
1596  if ((group = get_group_from_list(newsgroups)) == NULL) {
1597  info_message(strchr(newsgroups, ',') ? _(txt_lookup_show_groups) : _(txt_lookup_show_group), newsgroups);
1598  free(newsgroups);
1599  return -1;
1600  }
1601 
1602  curr_group = group;
1603  num_of_tagged_arts = 0;
1604  range_active = FALSE;
1605  last_resp = -1;
1606  this_resp = -1;
1607  tmp_cache_overview_files = tinrc.cache_overview_files;
1609  tmp_show_only_unread_arts = curr_group->attribute->show_only_unread_arts;
1611 
1612  if (!index_group(group)) {
1613  for_each_art(i) {
1614  art = &arts[i];
1615  FreeAndNull(art->refs);
1616  FreeAndNull(art->msgid);
1617  }
1618  tin_errno = 0;
1619  ret = -1;
1620  }
1621 
1622  if (!ret) {
1623  grpmenu.first = 0;
1624 
1625  if ((msgid = find_msgid(idptr)) == NULL) {
1627  ret = -1;
1628  }
1629 
1630  if (!ret && msgid->article == ART_UNAVAILABLE) {
1632  ret = -1;
1633  }
1634 
1635  if (!ret && which_thread(msgid->article) == -1) {
1637  ret = -1;
1638  }
1639  }
1640 
1641  if (!ret) {
1642  switch (show_page(group, msgid->article, NULL)) {
1643  case GRP_QUIT:
1644  ret = GRP_QUIT;
1645  break;
1646 
1647  default:
1648  break;
1649  }
1650  }
1651 
1652  free(newsgroups);
1653  art_close(&pgart);
1654  tinrc.cache_overview_files = tmp_cache_overview_files;
1655  curr_group->attribute->show_only_unread_arts = tmp_show_only_unread_arts;
1656  curr_group = NULL;
1657 
1658  return ret;
1659 }
1660 
1661 
1662 /*
1663  * Takes a list of newsgroups and determines if one of them is available.
1664  */
1665 static struct t_group *
1666 get_group_from_list(
1667  char *newsgroups)
1668 {
1669  char *ptr, *tr;
1670  t_bool found = FALSE;
1671  struct t_group *group = NULL;
1672 
1673  if (!newsgroups || (ptr = strtok(newsgroups, ",")) == NULL)
1674  return NULL;
1675 
1676  /* find first available group of type news */
1677  do {
1678  tr = str_trim(ptr);
1679  group = group_find(tr, TRUE);
1680  if (group && group->type == GROUP_TYPE_NEWS)
1681  found = TRUE;
1682  } while (!found && (ptr = strtok(NULL, ",")) != NULL);
1683 
1684  return found ? group : NULL;
1685 }
1686 #endif /* NNTP_ABLE */
txt_grpdesc_disabled
constext txt_grpdesc_disabled[]
Definition: lang.c:324
OK_HDR
#define OK_HDR
Definition: nntplib.h:106
name
const char * name
Definition: signal.c:117
DEBUG_NNTP
#define DEBUG_NNTP
Definition: debug.h:47
t_fmt::len_grpname
size_t len_grpname
Definition: tin.h:1816
flags_offset
static int flags_offset
Definition: select.c:88
t_article
Definition: tin.h:1510
abbr_groupname
char * abbr_groupname(const char *grpname, size_t len)
Definition: string.c:990
NNTP_STRLEN
#define NNTP_STRLEN
Definition: nntplib.h:155
groupname_len
static int groupname_len
Definition: select.c:87
erase_arrow
void erase_arrow(void)
Definition: screen.c:352
CAPABILITIES
@ CAPABILITIES
Definition: nntplib.h:171
t_fmt::d_before_u
t_bool d_before_u
Definition: tin.h:1833
strcasecmp
int strcasecmp(const char *p, const char *q)
Definition: string.c:468
EXIT_SUCCESS
#define EXIT_SUCCESS
Definition: tin.h:1273
pos_group_in_newsrc
t_bool pos_group_in_newsrc(struct t_group *group, int pos)
Definition: newsrc.c:1181
read_groups
static void read_groups(void)
Definition: select.c:1208
t_config::strip_blanks
t_bool strip_blanks
Definition: tinrc.h:239
GLOBAL_PAGE_DOWN
@ GLOBAL_PAGE_DOWN
Definition: keymap.h:200
_
#define _(Text)
Definition: tin.h:94
GLOBAL_SHELL_ESCAPE
@ GLOBAL_SHELL_ESCAPE
Definition: keymap.h:223
UNSUBSCRIBED
#define UNSUBSCRIBED
Definition: tin.h:1340
SELECT_ENTER_GROUP
@ SELECT_ENTER_GROUP
Definition: keymap.h:340
txt_quit
constext txt_quit[]
Definition: lang.c:745
active_comp
static int active_comp(t_comptype p1, t_comptype p2)
Definition: select.c:914
INDEX_TOP
#define INDEX_TOP
Definition: tin.h:1008
txt_quit_no_write
constext txt_quit_no_write[]
Definition: lang.c:751
invoke_editor
t_bool invoke_editor(const char *filename, int lineno, struct t_group *group)
Definition: misc.c:372
txt_no_prev_search
constext txt_no_prev_search[]
Definition: lang.c:683
my_strdup
char * my_strdup(const char *str)
Definition: string.c:133
txt_cannot_post
constext txt_cannot_post[]
Definition: lang.c:130
t_group
Definition: tin.h:1772
parse_format_string
void parse_format_string(const char *fmtstr, struct t_fmt *fmt)
Definition: string.c:1430
CATCHUP
@ CATCHUP
Definition: keymap.h:169
DIGIT_8
@ DIGIT_8
Definition: keymap.h:158
catchup_group
static void catchup_group(struct t_group *group, t_bool goto_next_unread_group)
Definition: select.c:1129
bug_report
void bug_report(void)
Definition: global.c:430
t_config::select_format
char select_format[LEN]
Definition: tinrc.h:272
GLOBAL_TOGGLE_INFO_LAST_LINE
@ GLOBAL_TOGGLE_INFO_LAST_LINE
Definition: keymap.h:229
GLOBAL_DISPLAY_POST_HISTORY
@ GLOBAL_DISPLAY_POST_HISTORY
Definition: keymap.h:188
tin_sort
#define tin_sort
Definition: tin.h:2098
str_trim
char * str_trim(char *string)
Definition: string.c:532
t_fmt::d_before_f
t_bool d_before_f
Definition: tin.h:1831
txt_subscribing
constext txt_subscribing[]
Definition: lang.c:851
txt_bad_command
constext txt_bad_command[]
Definition: lang.c:112
txt_unsubscribe_pattern
constext txt_unsubscribe_pattern[]
Definition: lang.c:898
GLOBAL_SEARCH_SUBJECT_FORWARD
@ GLOBAL_SEARCH_SUBJECT_FORWARD
Definition: keymap.h:220
show_title
void show_title(const char *title)
Definition: screen.c:405
t_capabilities::type
enum extension_type type
Definition: nntplib.h:187
GROUP_TYPE_NEWS
#define GROUP_TYPE_NEWS
Definition: tin.h:1059
t_msgid
Definition: tin.h:1486
t_config::strip_bogus
int strip_bogus
Definition: tinrc.h:151
move_down
void move_down(void)
Definition: global.c:110
read_news_via_nntp
t_bool read_news_via_nntp
Definition: init.c:150
DIGIT_5
@ DIGIT_5
Definition: keymap.h:155
last_search
t_function last_search
Definition: init.c:117
screen
struct t_screen * screen
Definition: screen.c:51
txt_group
constext txt_group[]
Definition: lang.c:1217
txt_no_description
constext txt_no_description[]
Definition: lang.c:670
build_gline
static void build_gline(int i)
Definition: select.c:660
txt_group_selection
constext txt_group_selection[]
Definition: lang.c:322
ClearScreen
void ClearScreen(void)
Definition: curses.c:410
GLOBAL_LOOKUP_MESSAGEID
@ GLOBAL_LOOKUP_MESSAGEID
Definition: keymap.h:196
reread_active_after_posting
t_bool reread_active_after_posting(void)
Definition: post.c:4644
GLOBAL_OPTION_MENU
@ GLOBAL_OPTION_MENU
Definition: keymap.h:199
scroll_up
void scroll_up(void)
Definition: global.c:278
cCRLF
#define cCRLF
Definition: tcurses.h:150
grpmenu
t_menu grpmenu
Definition: group.c:83
t_fmt::len_grpdesc
size_t len_grpdesc
Definition: tin.h:1814
SELECT_MARK_GROUP_UNREAD
@ SELECT_MARK_GROUP_UNREAD
Definition: keymap.h:343
art
static t_openartinfo * art
Definition: cook.c:78
t_config::default_goto_group
char default_goto_group[HEADER_LEN]
Definition: tinrc.h:69
yank_active_file
static void yank_active_file(void)
Definition: select.c:875
DIGIT_3
@ DIGIT_3
Definition: keymap.h:153
select_keys
struct keylist select_keys
Definition: keymap.c:88
show_description
t_bool show_description
Definition: init.c:152
t_fmt::flags_offset
size_t flags_offset
Definition: tin.h:1827
tinrc
struct t_config tinrc
Definition: init.c:191
wait_message
void wait_message(unsigned int sdelay, const char *fmt,...)
Definition: screen.c:133
HIST_OTHER
@ HIST_OTHER
Definition: extern.h:1538
FreeAndNull
#define FreeAndNull(p)
Definition: tin.h:2204
curr_group
struct t_group * curr_group
Definition: group.c:55
select_done
static void select_done(void)
Definition: select.c:1390
read_saved_news
t_bool read_saved_news
Definition: init.c:151
t_group::xmin
t_artnum xmin
Definition: tin.h:1780
txt_moving
constext txt_moving[]
Definition: lang.c:652
write_config_file
void write_config_file(char *file)
Definition: config.c:913
filter_file_offset
int filter_file_offset
Definition: filter.c:93
t_fmt::g_before_u
t_bool g_before_u
Definition: tin.h:1834
signal_context
int signal_context
Definition: signal.c:105
t_fmt::len_grpname_max
size_t len_grpname_max
Definition: tin.h:1818
ART_UNAVAILABLE
#define ART_UNAVAILABLE
Definition: tin.h:1323
add_my_group
int add_my_group(const char *group, t_bool add, t_bool ignore_case)
Definition: select.c:1040
CATCHUP_NEXT_UNREAD
@ CATCHUP_NEXT_UNREAD
Definition: keymap.h:170
GLOBAL_POSTPONED
@ GLOBAL_POSTPONED
Definition: keymap.h:204
txt_end_of_groups
constext txt_end_of_groups[]
Definition: lang.c:168
GLOBAL_SCROLL_DOWN
@ GLOBAL_SCROLL_DOWN
Definition: keymap.h:213
t_fmt::show_grpdesc
t_bool show_grpdesc
Definition: tin.h:1830
txt_newsgroup
constext txt_newsgroup[]
Definition: lang.c:658
fmt_string
char * fmt_string(const char *fmt,...)
Definition: string.c:1379
skip_newgroups
int skip_newgroups(void)
Definition: select.c:1017
SELECT_SUBSCRIBE_PATTERN
@ SELECT_SUBSCRIBE_PATTERN
Definition: keymap.h:349
pickup_postponed_articles
t_bool pickup_postponed_articles(t_bool ask, t_bool all)
Definition: post.c:2462
TINRC_CONFIRM_ACTION
#define TINRC_CONFIRM_ACTION
Definition: tin.h:947
t_group::type
unsigned int type
Definition: tin.h:1781
prompt_item_num
void prompt_item_num(int ch, const char *prompt)
Definition: global.c:200
HIST_GOTO_GROUP
@ HIST_GOTO_GROUP
Definition: extern.h:1541
GRP_NEXTUNREAD
@ GRP_NEXTUNREAD
Definition: tin.h:1262
CMDLINE_GETART_LIMIT
#define CMDLINE_GETART_LIMIT
Definition: tin.h:1091
state
state
Definition: save.c:56
tcurses.h
selection_page
void selection_page(int start_groupnum, int num_cmd_line_groups)
Definition: select.c:109
t_fmt::g_before_f
t_bool g_before_f
Definition: tin.h:1832
GLOBAL_SCROLL_UP
@ GLOBAL_SCROLL_UP
Definition: keymap.h:214
t_menu::max
int max
Definition: tin.h:2007
info_message
void info_message(const char *fmt,...)
Definition: screen.c:102
SELECT_SORT_ACTIVE
@ SELECT_SORT_ACTIVE
Definition: keymap.h:347
tin.h
tin_done
void tin_done(int ret, const char *fmt,...)
Definition: misc.c:557
GLOBAL_LAST_PAGE
@ GLOBAL_LAST_PAGE
Definition: keymap.h:192
find_msgid
struct t_msgid * find_msgid(const char *msgid)
Definition: refs.c:351
read_filter_file
t_bool read_filter_file(const char *file)
Definition: filter.c:308
need_reread_active_file
t_bool need_reread_active_file(void)
Definition: active.c:88
draw_group_arrow
static void draw_group_arrow(void)
Definition: select.c:847
DIGIT_4
@ DIGIT_4
Definition: keymap.h:154
GRP_EXIT
@ GRP_EXIT
Definition: tin.h:1269
can_post
t_bool can_post
Definition: nntplib.c:32
cmdline
struct t_cmdlineopts cmdline
Definition: init.c:189
select_quit
static void select_quit(void)
Definition: select.c:1380
strip_line
char * strip_line(char *line)
Definition: misc.c:3599
t_fmt::len_ucnt
size_t len_ucnt
Definition: tin.h:1826
t_fmt
Definition: tin.h:1809
GLOBAL_TOGGLE_HELP_DISPLAY
@ GLOBAL_TOGGLE_HELP_DISPLAY
Definition: keymap.h:228
group_find
struct t_group * group_find(const char *group_name, t_bool ignore_case)
Definition: list.c:154
txt_unsubscribed_to
constext txt_unsubscribed_to[]
Definition: lang.c:905
cSelect
@ cSelect
Definition: tin.h:107
prompt_string_default
char * prompt_string_default(const char *prompt, char *def, const char *failtext, int history)
Definition: prompt.c:558
page_up
void page_up(void)
Definition: global.c:130
filter_file
char filter_file[PATH_LEN]
Definition: init.c:89
save_restore_curr_group
static int save_restore_curr_group(t_bool saving)
Definition: select.c:931
txt_select_group
constext txt_select_group[]
Definition: lang.c:838
forever
#define forever
Definition: tin.h:810
t_capabilities::hdr_cmd
const char * hdr_cmd
Definition: nntplib.h:207
t_msgid::article
int article
Definition: tin.h:1491
active
struct t_group * active
Definition: memory.c:66
show_help_page
void show_help_page(const int level, const char *title)
Definition: help.c:694
tin_fgets
char * tin_fgets(FILE *fp, t_bool header)
Definition: read.c:320
force_reread_active_file
t_bool force_reread_active_file
Definition: active.c:62
Raw
void Raw(int state)
Definition: curses.c:624
txt_remove_bogus
constext txt_remove_bogus[]
Definition: lang.c:775
txt_no_groups
constext txt_no_groups[]
Definition: lang.c:673
txt_yanked_groups
constext txt_yanked_groups[]
Definition: lang.c:988
HIST_POST_NEWSGROUPS
@ HIST_POST_NEWSGROUPS
Definition: extern.h:1547
strwidth
int strwidth(const char *str)
Definition: string.c:1043
sized_message
char * sized_message(char **result, const char *format, const char *subject)
Definition: prompt.c:646
mark_offset
int mark_offset
Definition: screen.c:48
nntp_caps
struct t_capabilities nntp_caps
Definition: init.c:516
txt_save_config
constext txt_save_config[]
Definition: lang.c:807
GLOBAL_VERSION
@ GLOBAL_VERSION
Definition: keymap.h:231
SELECT_QUIT_NO_WRITE
@ SELECT_QUIT_NO_WRITE
Definition: keymap.h:355
txt_no_groups_to_read
constext txt_no_groups_to_read[]
Definition: lang.c:674
GLOBAL_EDIT_FILTER
@ GLOBAL_EDIT_FILTER
Definition: keymap.h:189
txt_newsgroup_position
constext txt_newsgroup_position[]
Definition: lang.c:660
SUB_CHAR
#define SUB_CHAR(x)
Definition: tin.h:1344
draw_arrow_mark
void draw_arrow_mark(int line)
Definition: screen.c:300
WriteLine
#define WriteLine(row, buffer)
Definition: tcurses.h:174
PLURAL
#define PLURAL(x, y)
Definition: tin.h:1053
SELECT_TOGGLE_READ_DISPLAY
@ SELECT_TOGGLE_READ_DISPLAY
Definition: keymap.h:352
index_group
t_bool index_group(struct t_group *group)
Definition: art.c:396
DIGIT_7
@ DIGIT_7
Definition: keymap.h:157
toggle_mini_help
void toggle_mini_help(int level)
Definition: help.c:1020
GLOBAL_BUGREPORT
@ GLOBAL_BUGREPORT
Definition: keymap.h:187
handle_keypad
t_function handle_keypad(t_function(*left_action)(void), t_function(*right_action)(void), t_function(*mouse_action)(t_function(*left_action)(void), t_function(*right_action)(void)), const struct keylist keys)
Definition: global.c:355
t_fmt::str
char str[1024]
Definition: tin.h:1810
t_group::description
char * description
Definition: tin.h:1775
t_config::info_in_last_line
t_bool info_in_last_line
Definition: tinrc.h:215
read_descriptions
void read_descriptions(t_bool verb)
Definition: mail.c:441
buf
static char buf[16]
Definition: langinfo.c:50
convert_to_printable
char * convert_to_printable(char *buf, t_bool keep_tab)
Definition: charset.c:385
t_menu
Definition: tin.h:2005
GLOBAL_LINE_DOWN
@ GLOBAL_LINE_DOWN
Definition: keymap.h:194
HpGlitch
#define HpGlitch(func)
Definition: tcurses.h:176
FreeIfNeeded
#define FreeIfNeeded(p)
Definition: tin.h:2203
set_xclick_on
void set_xclick_on(void)
Definition: curses.c:691
show_mini_help
void show_mini_help(int level)
Definition: help.c:754
post_article
t_bool post_article(const char *groupname)
Definition: post.c:2554
txt_art_unavailable
constext txt_art_unavailable[]
Definition: lang.c:69
t_group::moderated
char moderated
Definition: tin.h:1777
config_page
void config_page(const char *grpname, enum context level)
Definition: options_menu.c:921
txt_not_exist
constext txt_not_exist[]
Definition: lang.c:698
t_attribute::show_only_unread_arts
unsigned show_only_unread_arts
Definition: tin.h:1627
HIST_MESSAGE_ID
@ HIST_MESSAGE_ID
Definition: extern.h:1544
SELECT_TOGGLE_DESCRIPTIONS
@ SELECT_TOGGLE_DESCRIPTIONS
Definition: keymap.h:351
SELECT_SUBSCRIBE
@ SELECT_SUBSCRIBE
Definition: keymap.h:348
GLOBAL_LINE_UP
@ GLOBAL_LINE_UP
Definition: keymap.h:195
t_fmt::ucnt_offset
size_t ucnt_offset
Definition: tin.h:1829
subscribe_pattern
static void subscribe_pattern(const char *prompt, const char *message, const char *result, t_bool state)
Definition: select.c:1333
top_of_list
void top_of_list(void)
Definition: global.c:182
read_newsrc
signed long int read_newsrc(char *newsrc_file, t_bool allgroups)
Definition: newsrc.c:83
GLOBAL_SEARCH_SUBJECT_BACKWARD
@ GLOBAL_SEARCH_SUBJECT_BACKWARD
Definition: keymap.h:219
txt_not_in_active_file
constext txt_not_in_active_file[]
Definition: lang.c:699
selmenu
t_menu selmenu
Definition: select.c:85
DIGIT_9
@ DIGIT_9
Definition: keymap.h:159
cCOLS
int cCOLS
Definition: curses.c:53
t_config::default_move_group
int default_move_group
Definition: tinrc.h:133
grp_mark_unread
void grp_mark_unread(struct t_group *group)
Definition: newsrc.c:716
yanked_out
static t_bool yanked_out
Definition: select.c:60
LEN
#define LEN
Definition: tin.h:854
last_resp
int last_resp
Definition: page.c:70
for_each_group
#define for_each_group(x)
Definition: tin.h:2210
t_function
enum defined_functions t_function
Definition: keymap.h:373
find_group_index
int find_group_index(const char *group, t_bool ignore_case)
Definition: list.c:106
toggle_inverse_video
void toggle_inverse_video(void)
Definition: misc.c:1058
reset_newsrc
void reset_newsrc(void)
Definition: newsrc.c:605
select_left
static t_function select_left(void)
Definition: select.c:93
t_config::default_post_newsgroups
char default_post_newsgroups[HEADER_LEN]
Definition: tinrc.h:75
t_fmt::len_grpname_dsc
size_t len_grpname_dsc
Definition: tin.h:1817
currmenu
t_menu * currmenu
Definition: init.c:165
write_newsrc
signed long int write_newsrc(void)
Definition: newsrc.c:197
which_thread
int which_thread(int n)
Definition: thread.c:1003
sync_active_file
static void sync_active_file(void)
Definition: select.c:865
cursoroff
void cursoroff(void)
Definition: curses.c:721
GLOBAL_FIRST_PAGE
@ GLOBAL_FIRST_PAGE
Definition: keymap.h:190
GLOBAL_POST
@ GLOBAL_POST
Definition: keymap.h:203
SELECT_UNSUBSCRIBE_PATTERN
@ SELECT_UNSUBSCRIBE_PATTERN
Definition: keymap.h:354
FAKE_NNTP_FP
#define FAKE_NNTP_FP
Definition: tin.h:455
GRP_NEXT
@ GRP_NEXT
Definition: tin.h:1263
set_xclick_off
void set_xclick_off(void)
Definition: curses.c:703
txt_unsubscribed_num_groups
constext txt_unsubscribed_num_groups[]
Definition: lang.c:904
func_to_key
char func_to_key(t_function func, const struct keylist keys)
Definition: keymap.c:124
my_retouch
#define my_retouch()
Definition: tcurses.h:173
txt_no_last_message
constext txt_no_last_message[]
Definition: lang.c:675
choose_new_group
int choose_new_group(void)
Definition: select.c:984
txt_unsubscribing
constext txt_unsubscribing[]
Definition: lang.c:906
txt_info_no_write
constext txt_info_no_write[]
Definition: lang.c:549
txt_no_newsgroups
constext txt_no_newsgroups[]
Definition: lang.c:680
txt_group_aliased
constext txt_group_aliased[]
Definition: lang.c:316
bool_not
#define bool_not(b)
Definition: bool.h:81
t_group::xmax
t_artnum xmax
Definition: tin.h:1779
t_group::inrange
t_bool inrange
Definition: tin.h:1782
SELECT_ENTER_NEXT_UNREAD_GROUP
@ SELECT_ENTER_NEXT_UNREAD_GROUP
Definition: keymap.h:341
UNREAD_GROUP
#define UNREAD_GROUP(i)
Definition: tin.h:1048
sort_active_file
static void sort_active_file(void)
Definition: select.c:969
t_group::bogus
t_bool bogus
Definition: tin.h:1787
scroll_down
void scroll_down(void)
Definition: global.c:252
t_capabilities::xpat
t_bool xpat
Definition: nntplib.h:205
ERR_NOART
#define ERR_NOART
Definition: nntplib.h:133
MAXKEYLEN
#define MAXKEYLEN
Definition: keymap.h:136
SELECT_GOTO
@ SELECT_GOTO
Definition: keymap.h:342
t_cmdlineopts::args
unsigned int args
Definition: tin.h:1471
t_menu::curr
int curr
Definition: tin.h:2006
show_page
int show_page(struct t_group *group, int start_respnum, int *threadnum)
Definition: page.c:305
atoi
int atoi(const char *s)
INDEX2LNUM
#define INDEX2LNUM(i)
Definition: tin.h:1009
t_group::name
char * name
Definition: tin.h:1773
t_group::newsrc
struct t_newsrc newsrc
Definition: tin.h:1789
my_group_find
#define my_group_find(x)
Definition: tin.h:2208
t_screen::col
char * col
Definition: tin.h:1930
GLOBAL_SET_RANGE
@ GLOBAL_SET_RANGE
Definition: keymap.h:221
toggle_my_groups
void toggle_my_groups(const char *group)
Definition: select.c:1254
SELECT_NEXT_UNREAD_GROUP
@ SELECT_NEXT_UNREAD_GROUP
Definition: keymap.h:345
FALSE
#define FALSE
Definition: bool.h:70
SELECT_MOVE_GROUP
@ SELECT_MOVE_GROUP
Definition: keymap.h:344
STRCPY
#define STRCPY(dst, src)
Definition: tin.h:814
select_right
static t_function select_right(void)
Definition: select.c:101
num_of_tagged_arts
int num_of_tagged_arts
Definition: tags.c:50
debug
unsigned short debug
Definition: debug.c:51
GLOBAL_QUIT_TIN
@ GLOBAL_QUIT_TIN
Definition: keymap.h:211
SELECT_SYNC_WITH_ACTIVE
@ SELECT_SYNC_WITH_ACTIVE
Definition: keymap.h:350
local_config_file
char local_config_file[PATH_LEN]
Definition: init.c:84
GLOBAL_PAGE_UP
@ GLOBAL_PAGE_UP
Definition: keymap.h:201
txt_no_match
constext txt_no_match[]
Definition: lang.c:678
this_resp
int this_resp
Definition: page.c:71
verbose
int verbose
Definition: init.c:153
tin_ltoa
char * tin_ltoa(t_artnum value, int digits)
Definition: string.c:80
end_of_list
void end_of_list(void)
Definition: global.c:191
no_write
t_bool no_write
Definition: init.c:144
grp_mark_read
void grp_mark_read(struct t_group *group, struct t_article *art)
Definition: newsrc.c:690
txt_reading_groups
constext txt_reading_groups[]
Definition: lang.c:764
t_cmdlineopts::getart_limit
int getart_limit
Definition: tin.h:1467
newsrc
char newsrc[PATH_LEN]
Definition: init.c:96
OK_HEAD
#define OK_HEAD
Definition: nntplib.h:100
snprintf
#define snprintf
Definition: tin.h:2417
resync_active_file
t_bool resync_active_file(void)
Definition: active.c:102
GLOBAL_SEARCH_REPEAT
@ GLOBAL_SEARCH_REPEAT
Definition: keymap.h:216
move_to_item
void move_to_item(int n)
Definition: global.c:227
DIGIT_2
@ DIGIT_2
Definition: keymap.h:152
t_fmt::len_linenumber
size_t len_linenumber
Definition: tin.h:1820
txt_subscribed_num_groups
constext txt_subscribed_num_groups[]
Definition: lang.c:849
NEWSRC_LINE
#define NEWSRC_LINE
Definition: tin.h:856
my_group
int * my_group
Definition: memory.c:64
reposition_group
static int reposition_group(struct t_group *group, int default_num)
Definition: select.c:1065
t_artnum
long t_artnum
Definition: tin.h:226
error_message
void error_message(unsigned int sdelay, const char *fmt,...)
Definition: screen.c:184
txt_show_unread
constext txt_show_unread[]
Definition: lang.c:802
GRP_QUIT
@ GRP_QUIT
Definition: tin.h:1261
txt_reading_news_newsrc_file
constext txt_reading_news_newsrc_file[]
Definition: lang.c:768
txt_mark_group_read
constext txt_mark_group_read[]
Definition: lang.c:626
t_group::attribute
struct t_attribute * attribute
Definition: tin.h:1790
subscribe
void subscribe(struct t_group *group, int sub_state, t_bool get_info)
Definition: newsrc.c:537
show_selection_page
void show_selection_page(void)
Definition: select.c:578
GLOBAL_HELP
@ GLOBAL_HELP
Definition: keymap.h:191
t_menu::first
int first
Definition: tin.h:2008
GLOBAL_ABORT
@ GLOBAL_ABORT
Definition: keymap.h:186
BOGUS_SHOW
#define BOGUS_SHOW
Definition: tin.h:1200
t_config::show_only_unread_groups
t_bool show_only_unread_groups
Definition: tinrc.h:233
txt_info_not_subscribed
constext txt_info_not_subscribed[]
Definition: lang.c:547
txt_enter_message_id
constext txt_enter_message_id[]
Definition: lang.c:174
t_config::art_marked_inrange
char art_marked_inrange
Definition: tinrc.h:60
SELECT_UNSUBSCRIBE
@ SELECT_UNSUBSCRIBE
Definition: keymap.h:353
GRP_RETSELECT
@ GRP_RETSELECT
Definition: tin.h:1260
art_close
void art_close(t_openartinfo *artinfo)
Definition: rfc2046.c:1604
move_up
void move_up(void)
Definition: global.c:81
DIGIT_6
@ DIGIT_6
Definition: keymap.h:156
search_active
int search_active(t_bool forward, t_bool repeat)
Definition: search.c:272
txt_skipping_newgroups
constext txt_skipping_newgroups[]
Definition: lang.c:843
range_active
t_bool range_active
Definition: init.c:147
sel_fmt
static struct t_fmt sel_fmt
Definition: select.c:49
delete_group
void delete_group(char *group)
Definition: newsrc.c:644
t_config::cache_overview_files
t_bool cache_overview_files
Definition: tinrc.h:209
ucnt_offset
static int ucnt_offset
Definition: select.c:89
group_page
int group_page(struct t_group *group)
Definition: group.c:142
HIST_MOVE_GROUP
@ HIST_MOVE_GROUP
Definition: extern.h:1545
pos_next_unread_group
static t_bool pos_next_unread_group(t_bool redraw)
Definition: select.c:1164
CURR_GROUP
#define CURR_GROUP
Definition: tin.h:1043
mark_screen
void mark_screen(int screen_row, int screen_col, const char *value)
Definition: group.c:1084
t_bool
unsigned t_bool
Definition: bool.h:77
group_flag
char group_flag(char ch)
Definition: active.c:1248
txt_reset_newsrc
constext txt_reset_newsrc[]
Definition: lang.c:782
txt_subscribed_to
constext txt_subscribed_to[]
Definition: lang.c:850
printascii
char * printascii(char *buf, int ch)
Definition: keymap.c:271
txt_yanked_none
constext txt_yanked_none[]
Definition: lang.c:989
prompt_yn
int prompt_yn(const char *prompt, t_bool default_answer)
Definition: prompt.c:165
match_group_list
t_bool match_group_list(const char *group, const char *group_list)
Definition: active.c:1118
TRUE
#define TRUE
Definition: bool.h:74
global_mouse_action
t_function global_mouse_action(t_function(*left_action)(void), t_function(*right_action)(void))
Definition: global.c:321
for_each_art
#define for_each_art(x)
Definition: tin.h:2211
t_newsrc::num_unread
t_artnum num_unread
Definition: tin.h:1762
select_read_group
static void select_read_group(void)
Definition: select.c:1404
txt_post_newsgroups
constext txt_post_newsgroups[]
Definition: lang.c:724
GRP_ENTER
@ GRP_ENTER
Definition: tin.h:1268
SELECT_YANK_ACTIVE
@ SELECT_YANK_ACTIVE
Definition: keymap.h:356
tin_errno
int tin_errno
Definition: read.c:59
GLOBAL_REDRAW_SCREEN
@ GLOBAL_REDRAW_SCREEN
Definition: keymap.h:212
GLOBAL_TOGGLE_INVERSE_VIDEO
@ GLOBAL_TOGGLE_INVERSE_VIDEO
Definition: keymap.h:230
nntp_server
char * nntp_server
Definition: nntplib.c:28
show_inverse_video_status
void show_inverse_video_status(void)
Definition: misc.c:1073
arts
struct t_article * arts
Definition: memory.c:69
TINRC_CONFIRM_TO_QUIT
#define TINRC_CONFIRM_TO_QUIT
Definition: tin.h:948
t_group::subscribed
t_bool subscribed
Definition: tin.h:1785
txt_group_select_com
constext txt_group_select_com[]
Definition: lang.c:321
set_range
t_bool set_range(int level, int min, int max, int curr)
Definition: tags.c:353
SUBSCRIBED
#define SUBSCRIBED
Definition: tin.h:1341
t_config::getart_limit
int getart_limit
Definition: tinrc.h:135
t_config::abbreviate_groupname
t_bool abbreviate_groupname
Definition: tinrc.h:199
SELECT_LEVEL
#define SELECT_LEVEL
Definition: tin.h:1101
DIGIT_1
@ DIGIT_1
Definition: keymap.h:151
GLOBAL_QUIT
@ GLOBAL_QUIT
Definition: keymap.h:210
t_group::newgroup
t_bool newgroup
Definition: tin.h:1786
num_active
int num_active
Definition: memory.c:51
group_rehash
void group_rehash(t_bool yanked_out)
Definition: list.c:232
cvers
char cvers[LEN]
Definition: init.c:70
NOTESLINES
int NOTESLINES
Definition: signal.c:111
do_shell_escape
void do_shell_escape(void)
Definition: misc.c:542
SELECT_RESET_NEWSRC
@ SELECT_RESET_NEWSRC
Definition: keymap.h:346
INDEX2SNUM
#define INDEX2SNUM(i)
Definition: tin.h:1011
txt_yanked_sub_groups
constext txt_yanked_sub_groups[]
Definition: lang.c:990
my_group_add
#define my_group_add(x, y)
Definition: tin.h:2209
pgart
t_openartinfo pgart
Definition: page.c:63
txt_subscribe_pattern
constext txt_subscribe_pattern[]
Definition: lang.c:848
page_down
void page_down(void)
Definition: global.c:155
clear_message
void clear_message(void)
Definition: screen.c:243
txt_no_arts
constext txt_no_arts[]
Definition: lang.c:667
spin_cursor
void spin_cursor(void)
Definition: screen.c:445
t_config::draw_arrow
t_bool draw_arrow
Definition: tinrc.h:212
prompt_string
t_bool prompt_string(const char *prompt, char *buf, int which_hist)
Definition: prompt.c:93
my_malloc
#define my_malloc(size)
Definition: tin.h:2196
user_posted_messages
t_bool user_posted_messages(void)
Definition: post.c:466
set_first_screen_item
void set_first_screen_item(void)
Definition: global.c:61