Re: Patch

Dirk Nimmich <[email protected]>
Newsgroups gmane.network.tin.devel
Message-ID <[email protected]>
Dirk Nimmich wrote:
> Urs Janßen wrote:
> > On Sun, Sep 17, 2006 at 01:19:10AM +0200, Dirk Nimmich wrote:
> > > Attached another patch for two other bugs mentioned in TODO.
> > 
> > if you are in group level and directly enter an article via
> > GroupNextUnreadArtOrGrp ('TAB') and then press Quit ('q') in the pager
> > and press GroupNextUnreadArtOrGrp again you are back at the same article
> > instead of the next article in the thread/group.
> 
> Ok, it seems that thread.c:451 is the crucial line.

It wasn't. :-) Instead the page struct hasn't been updated
accordingly in group.c.

See attached patch which also addresses some other things in TODO.

Side note: Regarding the return value of change_config_file() I did
some archaeological ;-) research to find out its original meaning. I
had to go back to tin 1.1 PL2 only to find that it had been used to
indicate a change of the tinrc variable that switched the kill file
on or off. In tin 1.1 PL3 or PL4 (I didn't find a PL3) the variable
was dropped and the kill (now: filter) file has always been used
since, but the return value and related code remained until now ...

Dirk
192-4.diff (text/plain, 32 KB)
diff -Nur tin-1.9.2/doc/CHANGES tin-1.9.2-dn/doc/CHANGES
--- tin-1.9.2/doc/CHANGES	2006-09-06 16:39:19.000000000 +0200
+++ tin-1.9.2-dn/doc/CHANGES	2006-10-08 15:59:00.000000000 +0200
@@ -2,8 +2,16 @@
 
 U005) Dirk Nimmich <[email protected]>
       BUG. raw-mode didn't allow rot13
-      BUG. can't 'V'iew mime-parts with (illegal) encoded filename
-      FIX. proto.h, feed.c, page.c, save.c
+      BUG. can't 'V'iew mime-parts with (illegally) encoded filename
+      BUG. CatchupNextUnread in page level didn't always work
+      BUG. 'C'atchup in pager was still not correct (we didn't ever enter the
+           next group)
+      BUG. fast/endless reconecction loop after a "200\n\r400\n\r" greeting
+      BUG. resent command on 503 error
+      ADD. rewrote NGLIMIT handling
+      REM. return value of change_config_file()
+      FIX. proto.h, tin.h, feed.c, group.c, nntplib.c, options_menu.c, page.c
+           post.c, save.c, select.c
 
  015) Michael Bienia <[email protected]>
       BUG. 'l' from the pager doesn't reposition cursor to last viewed
diff -Nur tin-1.9.2/doc/TODO tin-1.9.2-dn/doc/TODO
--- tin-1.9.2/doc/TODO	2006-09-03 03:55:06.000000000 +0200
+++ tin-1.9.2-dn/doc/TODO	2006-10-08 15:52:51.000000000 +0200
@@ -4,11 +4,6 @@
 
 Bugs
 ----
-o  CatchupNextUnread in pagelevel doesn't always work (if commeing directly
-   from group level (via GroupNextUnreadArtOrGrp)): instead of leaving the
-   thread and entering the next one it stays at the current article.
-   [20060515 Urs Janssen <[email protected]>]
-
 o  a wrong usename in ~/.newsauth can't be corrected in the first
    pass
    [20050816 Urs Janssen <[email protected]>]
@@ -19,15 +14,6 @@
    (the servers response should be a single line (INN 2.2))
    [20050207 Urs Janssen <[email protected]>]
 
-o  fast/endless reconecction loop after a "200\n\r400\n\r" greeting,
-   see
-   <nntp://news.tin.org/[email protected]>
-
-o  AFAICS change_config_file() currently has a static return value,
-   but some callers do check the return value and in case we did
-   change something we should update (global) attributes accordingly.
-   [20030511 Urs Janssen <[email protected]>]
-
 o  Changes to int/bool tinrc variables in the Option Menu don't propagate
    back to the attributes, not even groups with global attributes.
    This is because the Option-Menu in {group,page}.c doesn't reread the
@@ -35,9 +21,6 @@
    flashing changes to all affected groups and remove the reread of the
    attributes file from select.c
 
-o  'C'atchup in pager is still not correct (we don't ever enter the next group)
-   [20030515 Urs Janssen <[email protected]>]
-
 o  piping/printing articles grabbles screen
    [20030501 Urs Janssen <[email protected]>]
 
@@ -350,7 +333,7 @@
      'h'  (GLOBAL_HELP)
      'R'  (GLOBAL_BUGREPORT)
      '!'  (GLOBAL_SHELL_ESCAPE)
-     and maybe a way to changed built in path like DEFAULT_MAILER, PATH_PGP, ...
+     and maybe a way to change built in path like DEFAULT_MAILER, PATH_PGP, ...
 
 o  Add to the POST_INFO-level:
      '?','/','\' search (partly done, currently only the displayed page is
@@ -429,11 +412,6 @@
 o  bring up a warning on a long Newsgroups: (>=5) line and
    force the user to confirm every single group he wants to post (or
    redirect followups to) in. (N/y)
-   rewrite NGLIMIT handling (post.c) ulBuildArgv() would replace a lot of
-   the current code
-   (not just truncate Newsgroups:-line after the NGLIMITth newsgroup -
-    or if we do so - give an extra warning to the user and give him the
-    chance to reedit the Newsgroups:-line)
 
 o  bring up a warning when trying to f'up into a binary group
    (use a regexp to detect binary groups e.g.:
diff -Nur tin-1.9.2/include/proto.h tin-1.9.2-dn/include/proto.h
--- tin-1.9.2/include/proto.h	2006-09-03 03:50:53.000000000 +0200
+++ tin-1.9.2-dn/include/proto.h	2006-10-08 13:43:31.000000000 +0200
@@ -3,7 +3,7 @@
  *  Module    : proto.h
  *  Author    : Urs Janssen <[email protected]>
  *  Created   :
- *  Updated   : 2006-09-02
+ *  Updated   : 2006-10-01
  *  Notes     :
  *
  * Copyright (c) 1997-2006 Urs Janssen <[email protected]>
@@ -435,7 +435,7 @@
 
 /* options_menu.c */
 extern char *fmt_option_prompt(char *dst, size_t len, t_bool editing, enum option_enum option);
-extern int change_config_file(struct t_group *group);
+extern void change_config_file(struct t_group *group);
 extern int option_row(enum option_enum option);
 extern t_bool option_is_visible(enum option_enum option);
 extern void check_score_defaults(void);
diff -Nur tin-1.9.2/include/tin.h tin-1.9.2-dn/include/tin.h
--- tin-1.9.2/include/tin.h	2006-06-28 14:18:00.000000000 +0200
+++ tin-1.9.2-dn/include/tin.h	2006-10-08 13:43:16.000000000 +0200
@@ -3,7 +3,7 @@
  *  Module    : tin.h
  *  Author    : I. Lea & R. Skrenta
  *  Created   : 1991-04-01
- *  Updated   : 2006-06-28
+ *  Updated   : 2006-10-01
  *  Notes     : #include files, #defines & struct's
  *
  * Copyright (c) 1997-2006 Iain Lea <[email protected]>, Rich Skrenta <[email protected]>
@@ -1200,8 +1200,6 @@
 /*
  * return codes for change_config_file ()
  */
-#define NO_FILTERING		0
-#define FILTERING		1
 #define DEFAULT_FILTER_DAYS		28
 
 
diff -Nur tin-1.9.2/src/group.c tin-1.9.2-dn/src/group.c
--- tin-1.9.2/src/group.c	2006-02-15 19:44:38.000000000 +0100
+++ tin-1.9.2-dn/src/group.c	2006-10-06 22:44:17.000000000 +0200
@@ -3,7 +3,7 @@
  *  Module    : group.c
  *  Author    : I. Lea & R. Skrenta
  *  Created   : 1991-04-01
- *  Updated   : 2005-07-02
+ *  Updated   : 2006-10-06
  *  Notes     :
  *
  * Copyright (c) 1991-2006 Iain Lea <[email protected]>, Rich Skrenta <[email protected]>
@@ -455,7 +455,8 @@
 					old_artnum = arts[(int) base[grpmenu.curr]].artnum;
 				}
 				n = tinrc.sort_article_type;
-				if ((change_config_file(group) == NO_FILTERING) && n != tinrc.sort_article_type)
+				change_config_file(group);
+				if (n != tinrc.sort_article_type)
 					make_threads(group, TRUE);
 				grpmenu.curr = find_new_pos(old_top, old_artnum, grpmenu.curr);
 				show_group_page();
@@ -1567,14 +1568,19 @@
 
 			case GRP_NEXTUNREAD:				/* 'C'atchup */
 				if ((n = next_unread((int) base[grpmenu.curr])) >= 0) {
+					if (page)
+						page->art = n;
 					if ((n = which_thread(n)) >= 0) {
 						grpmenu.curr = n;
 						depth = 0;
 						break;		/* Drop into next thread with unread */
 					}
 				}
-				/* No more unread threads in this group */
-				/* FALLTHROUGH */
+				/* No more unread threads in this group, enter next group */
+				grpmenu.curr = 0;
+				return GRP_NEXTUNREAD;
+				/* NOTREACHED */
+				break;
 
 			case GRP_KILLED:
 				grpmenu.curr = 0;
diff -Nur tin-1.9.2/src/nntplib.c tin-1.9.2-dn/src/nntplib.c
--- tin-1.9.2/src/nntplib.c	2006-03-06 18:42:45.000000000 +0100
+++ tin-1.9.2-dn/src/nntplib.c	2006-10-04 00:09:19.000000000 +0200
@@ -3,7 +3,7 @@
  *  Module    : nntplib.c
  *  Author    : S. Barber & I. Lea
  *  Created   : 1991-01-12
- *  Updated   : 2006-03-05
+ *  Updated   : 2006-10-03
  *  Notes     : NNTP client routines taken from clientlib.c 1.5.11 (1991-02-10)
  *  Copyright : (c) Copyright 1991-99 by Stan Barber & Iain Lea
  *              Permission is hereby granted to copy, reproduce, redistribute
@@ -957,125 +957,138 @@
 	char *ptr;
 	int ret = 0;
 #	if 0 /* "CAPABILITIES" will replace "LIST EXTENSIONS" */
-	FILE *fp;
+	char buf[NNTP_STRLEN];
 	char *d;
+	int i;
 
-	if ((fp = nntp_command("CAPABILITIES", INF_CAPABILITIES, NULL, 0)) != NULL) {
-		nntp_caps.type = CAPABILITIES;
-		while ((ptr = tin_fgets(fp, FALSE)) != NULL) {
+	buf[0] = '\0';
+	i = new_nntp_command("CAPABILITIES", INF_CAPABILITIES, buf, sizeof(buf));
+	switch (i) {
+		case INF_CAPABILITIES:
+			nntp_caps.type = CAPABILITIES;
+			while ((ptr = tin_fgets(FAKE_NNTP_FP, FALSE)) != NULL) {
 #		ifdef DEBUG
-			debug_nntp("<<<", ptr);
+				debug_nntp("<<<", ptr);
 #		endif /* DEBUG */
-			/* look for version number(s) */
-			if (!nntp_caps.version && nntp_caps.type == CAPABILITIES) {
-				if (!strcasecmp(ptr, "VERSION")) {
-					d = ptr + 7;
-					d = strpbrk(d, " \t");
-					while (d != NULL && (d + 1 < (ptr + strlen(ptr)))) {
-						d++;
-						nntp_caps.version = MAX(nntp_caps.version, (unsigned int) atoi(d));
+				/* look for version number(s) */
+				if (!nntp_caps.version && nntp_caps.type == CAPABILITIES) {
+					if (!strcasecmp(ptr, "VERSION")) {
+						d = ptr + 7;
 						d = strpbrk(d, " \t");
+						while (d != NULL && (d + 1 < (ptr + strlen(ptr)))) {
+							d++;
+							nntp_caps.version = MAX(nntp_caps.version, (unsigned int) atoi(d));
+							d = strpbrk(d, " \t");
+						}
 					}
 				}
-			}
-			/* we currently only support CAPABILITIES VERSION 2 */
-			if (nntp_caps.version == 2) {
-				/*
-				 * check for LIST variants - this code is untested
-				 */
-				if (!strcasecmp(ptr, "LIST")) {
-					d = ptr + 4;
-					d = strpbrk(d, " \t");
-					while (d != NULL && (d + 1 < (ptr + strlen(ptr)))) {
-						d++;
-						if (!strcasecmp(d, "ACTIVE.TIMES"))
-							nntp_caps.list_active_times = TRUE;
-						else if (!strcasecmp(d, "ACTIVE"))
-							nntp_caps.list_active_times = TRUE;
-						else if (!strcasecmp(d, "DISTRIB.PATS"))
-							nntp_caps.list_distrib_pats = TRUE;
-						else if (!strcasecmp(d, "DISTRIBUTIONS")) /* LIST DISTRIBUTIONS, "private" extension, RFC 2980 */
-							nntp_caps.list_distributions = TRUE;
-						else if (!strcasecmp(d, "HEADERS"))
-							nntp_caps.list_headers = TRUE; /* HDR requires LIST HEADERS, but not vice versa */
-						else if (!strcasecmp(d, "NEWSGROUPS"))
-							nntp_caps.list_newsgroups = TRUE;
-						else if (!strcasecmp(d, "OVERVIEW.FMT")) /* OVER requires OVERVIEW.FMT, but not vice versa */
-							nntp_caps.list_overview_fmt = TRUE;
-						else if (!strcasecmp(d, "MOTD")) /* "private" extension */
-							nntp_caps.list_motd = TRUE;
-						else if (!strcasecmp(d, "SUBSCRIPTIONS")) /* "private" extension, RFC 2980 */
-							nntp_caps.list_subscriptions = TRUE;
-						else if (!strcasecmp(d, "MODERATORS")) /* "private" extension */
-							nntp_caps.list_moderators = TRUE;
+				/* we currently only support CAPABILITIES VERSION 2 */
+				if (nntp_caps.version == 2) {
+					/*
+					 * check for LIST variants - this code is untested
+					 */
+					if (!strcasecmp(ptr, "LIST")) {
+						d = ptr + 4;
 						d = strpbrk(d, " \t");
-					}
-				} else if (!strcasecmp(ptr, "IMPLEMENTATION"))
-					nntp_caps.implementation = my_strdup(ptr + 14);
-				else if (!strcasecmp(ptr, "MODE-READER")) {
-					if (!nntp_caps.reader)
-						nntp_caps.mode_reader = TRUE;
-				} else if (!strcasecmp(ptr, "READER")) {
-					nntp_caps.reader = TRUE;
-					nntp_caps.mode_reader = FALSE;
-				} else if (!strcasecmp(d, "POST"))
-					nntp_caps.post = TRUE;
-				else if (!strcasecmp(ptr, "NEWNEWS"))
-					nntp_caps.newnews = TRUE;
-				else if (!strcasecmp(ptr, "XPAT")) /* extension, RFC 2980 */
-					nntp_caps.xpat = TRUE;
-				else if (!strcasecmp(ptr, "STARTTLS"))
-					nntp_caps.starttls = TRUE;
-				/*
-				 * NOTE: if we saw OVER, LIST OVERVIEW.FMT _must_ be implemented
-				 */
-				else if (!strcasecmp(ptr, &xover_cmds[1])) {
-					nntp_caps.over = TRUE;
-					nntp_caps.list_overview_fmt = TRUE;
-					nntp_caps.over_cmd = &xover_cmds[1];
-					d = ptr + strlen(&xover_cmds[1]);
-					d = strpbrk(d, " \t");
-					while (d != NULL && (d + 1 < (ptr + strlen(ptr)))) {
-						d++;
-						if (!strcasecmp(d, "MSGID"))
-							nntp_caps.over_msgid = TRUE;
+						while (d != NULL && (d + 1 < (ptr + strlen(ptr)))) {
+							d++;
+							if (!strcasecmp(d, "ACTIVE.TIMES"))
+								nntp_caps.list_active_times = TRUE;
+							else if (!strcasecmp(d, "ACTIVE"))
+								nntp_caps.list_active_times = TRUE;
+							else if (!strcasecmp(d, "DISTRIB.PATS"))
+								nntp_caps.list_distrib_pats = TRUE;
+							else if (!strcasecmp(d, "DISTRIBUTIONS")) /* LIST DISTRIBUTIONS, "private" extension, RFC 2980 */
+								nntp_caps.list_distributions = TRUE;
+							else if (!strcasecmp(d, "HEADERS"))
+								nntp_caps.list_headers = TRUE; /* HDR requires LIST HEADERS, but not vice versa */
+							else if (!strcasecmp(d, "NEWSGROUPS"))
+								nntp_caps.list_newsgroups = TRUE;
+							else if (!strcasecmp(d, "OVERVIEW.FMT")) /* OVER requires OVERVIEW.FMT, but not vice versa */
+								nntp_caps.list_overview_fmt = TRUE;
+							else if (!strcasecmp(d, "MOTD")) /* "private" extension */
+								nntp_caps.list_motd = TRUE;
+							else if (!strcasecmp(d, "SUBSCRIPTIONS")) /* "private" extension, RFC 2980 */
+								nntp_caps.list_subscriptions = TRUE;
+							else if (!strcasecmp(d, "MODERATORS")) /* "private" extension */
+								nntp_caps.list_moderators = TRUE;
+							d = strpbrk(d, " \t");
+						}
+					} else if (!strcasecmp(ptr, "IMPLEMENTATION"))
+						nntp_caps.implementation = my_strdup(ptr + 14);
+					else if (!strcasecmp(ptr, "MODE-READER")) {
+						if (!nntp_caps.reader)
+							nntp_caps.mode_reader = TRUE;
+					} else if (!strcasecmp(ptr, "READER")) {
+						nntp_caps.reader = TRUE;
+						nntp_caps.mode_reader = FALSE;
+					} else if (!strcasecmp(d, "POST"))
+						nntp_caps.post = TRUE;
+					else if (!strcasecmp(ptr, "NEWNEWS"))
+						nntp_caps.newnews = TRUE;
+					else if (!strcasecmp(ptr, "XPAT")) /* extension, RFC 2980 */
+						nntp_caps.xpat = TRUE;
+					else if (!strcasecmp(ptr, "STARTTLS"))
+						nntp_caps.starttls = TRUE;
+					/*
+					 * NOTE: if we saw OVER, LIST OVERVIEW.FMT _must_ be implemented
+					 */
+					else if (!strcasecmp(ptr, &xover_cmds[1])) {
+						nntp_caps.over = TRUE;
+						nntp_caps.list_overview_fmt = TRUE;
+						nntp_caps.over_cmd = &xover_cmds[1];
+						d = ptr + strlen(&xover_cmds[1]);
 						d = strpbrk(d, " \t");
-					}
-				} else if (!strcasecmp(ptr, "AUTHINFO")) {
-					d = ptr + 8;
-					d = strpbrk(d, " \t");
-					while (d != NULL && (d + 1 < (ptr + strlen(ptr)))) {
-						d++;
-						if (!strcasecmp(d, "USER"))
-							nntp_caps.authinfo_user = TRUE;
-						if (!strcasecmp(d, "SASL"))
-							nntp_caps.authinfo_sasl = TRUE;
+						while (d != NULL && (d + 1 < (ptr + strlen(ptr)))) {
+							d++;
+							if (!strcasecmp(d, "MSGID"))
+								nntp_caps.over_msgid = TRUE;
+							d = strpbrk(d, " \t");
+						}
+					} else if (!strcasecmp(ptr, "AUTHINFO")) {
+						d = ptr + 8;
 						d = strpbrk(d, " \t");
+						while (d != NULL && (d + 1 < (ptr + strlen(ptr)))) {
+							d++;
+							if (!strcasecmp(d, "USER"))
+								nntp_caps.authinfo_user = TRUE;
+							if (!strcasecmp(d, "SASL"))
+								nntp_caps.authinfo_sasl = TRUE;
+							d = strpbrk(d, " \t");
+						}
 					}
-				}
 #		if 0
-				/*
-				 * NOTE: if we saw HDR, LIST HEADERS _must_ be implemented
-				 */
-				else if (!strcasecmp(ptr, &xhdr_cmds[1])) {
+					/*
+					 * NOTE: if we saw HDR, LIST HEADERS _must_ be implemented
+					 */
+					else if (!strcasecmp(ptr, &xhdr_cmds[1])) {
 						nntp_caps.hdr_cmd = &xhdr_cmds[1];
 						nntp_caps.hdr = TRUE;
 						nntp_caps.list_headers = TRUE;
-				}
-				else if (!strcasecmp(ptr, "IHAVE"))
+					}
+					else if (!strcasecmp(ptr, "IHAVE"))
 						nntp_caps.ihave = TRUE;
 #		endif /* 0 */
-				/*
-				 * TODO: SASL, STREAMING
-				 */
-			} else
-				nntp_caps.type = NO;
-		}
+					/*
+					 * TODO: SASL, STREAMING
+					 */
+				} else
+					nntp_caps.type = NO;
+			}
+			break;
+
+		case ERR_GOODBYE:
+			ret = i;
+			error_message(buf);
+			break;
+
+		default:
+			break;
 	}
 #		ifdef DEBUG
 	debug_print_nntp_extensions();
 #		endif /* DEBUG */
-	if (!*sec && !nntp_caps.reader) {
+	if ((ret != ERR_GOODBYE) && !*sec && !nntp_caps.reader) {
 		if (nntp_caps.type == CAPABILITIES && !nntp_caps.mode_reader)
 			return -1; /* no mode-switching and no reader mode, give up */
 		if ((ret = mode_reader(&*sec)) != 0)
@@ -1136,20 +1149,25 @@
 				/*
 				 * as the server did support LIST EXTENSIONS it's likely that it
 				 * also can do LIST MOTD (we don't bother to parse the LIST
-				 * EXTENSIONS output for MOTD as it never was standartizised;
+				 * EXTENSIONS output for MOTD as it never was standardized;
 				 * draft-ietf-nntpext-base-24.txt only described OVER, HDR and
 				 * LISTGROUP).
 				 */
 				nntp_caps.list_motd = TRUE;
 				break;
 
+			case ERR_GOODBYE:
+				ret = i;
+				error_message(buf);
+				break;
+
 			default:
 				break;
 		}
 #		ifdef DEBUG
 		debug_print_nntp_extensions();
 #		endif /* DEBUG */
-		if (!*sec)
+		if ((ret != ERR_GOODBYE) && !*sec)
 			ret = mode_reader(&*sec);
 	}
 #	endif /* 0 */
@@ -1553,8 +1571,7 @@
 	respcode = (int) strtol(ptr, &end, 10);
 	DEBUG_IO((stderr, "get_only_respcode(%d)\n", respcode));
 
-	/* TODO: reconnect on ERR_FAULT? */
-	if ((respcode == ERR_FAULT || respcode == ERR_GOODBYE || respcode == OK_GOODBYE) && last_put[0] != '\0' && strcmp(last_put, "QUIT")) {
+	if ((respcode == ERR_GOODBYE || respcode == OK_GOODBYE) && last_put[0] != '\0' && strcmp(last_put, "QUIT")) {
 		/*
 		 * Maybe server timed out.
 		 * If so, retrying will force a reconnect.
diff -Nur tin-1.9.2/src/options_menu.c tin-1.9.2-dn/src/options_menu.c
--- tin-1.9.2/src/options_menu.c	2006-06-28 14:21:33.000000000 +0200
+++ tin-1.9.2-dn/src/options_menu.c	2006-10-08 13:42:34.000000000 +0200
@@ -3,7 +3,7 @@
  *  Module    : options_menu.c
  *  Author    : Michael Bienia <[email protected]>
  *  Created   : 2004-09-05
- *  Updated   : 2006-06-28
+ *  Updated   : 2006-10-01
  *  Notes     : Split from config.c
  *
  * Copyright (c) 2004-2006 Michael Bienia <[email protected]>
@@ -696,17 +696,14 @@
 /*
  * options menu so that the user can dynamically change parameters
  *
- * TODO: - why do we use ret_code when we never modify it?  what about calling
- *         code which checks the return value?
- *       - when we change something we need to update the related attributes
+ * TODO: - when we change something we need to update the related attributes
  *         as well (see line 2009).
  */
-int
+void
 change_config_file(
 	struct t_group *group)
 {
 	enum option_enum option, old_option;
-	int ret_code = NO_FILTERING;
 	int mime_encoding = MIME_ENCODING_7BIT;
 	t_bool change_option = FALSE;
 	t_function func;
@@ -725,7 +722,7 @@
 				/* FALLTHROUGH */
 			case CONFIG_NO_SAVE:
 				clear_note_area();
-				return ret_code;
+				return;
 
 			case GLOBAL_LINE_UP:
 				unhighlight_option(option);
@@ -1517,5 +1514,5 @@
 		} /* if (change_option) */
 	} /* forever */
 	/* NOTREACHED */
-	return ret_code;
+	return; 
 }
diff -Nur tin-1.9.2/src/page.c tin-1.9.2-dn/src/page.c
--- tin-1.9.2/src/page.c	2006-09-03 03:48:07.000000000 +0200
+++ tin-1.9.2-dn/src/page.c	2006-10-08 13:42:07.000000000 +0200
@@ -3,7 +3,7 @@
  *  Module    : page.c
  *  Author    : I. Lea & R. Skrenta
  *  Created   : 1991-04-01
- *  Updated   : 2006-06-28
+ *  Updated   : 2006-10-01
  *  Notes     :
  *
  * Copyright (c) 1991-2006 Iain Lea <[email protected]>, Rich Skrenta <[email protected]>
@@ -300,7 +300,6 @@
 	char buf[LEN];
 	char key[MAXKEYLEN];
 	int i, n = 0;
-	int filter_state = NO_FILTERING;
 	int old_sort_art_type = tinrc.sort_article_type;
 	int art_type = GROUP_TYPE_NEWS;
 	t_bool mouse_click_on = TRUE;
@@ -791,14 +790,14 @@
 			case GLOBAL_QUIT:	/* return to index page */
 return_to_index:
 				XFACE_CLEAR();
-				if (filter_state == NO_FILTERING && tinrc.sort_article_type != old_sort_art_type)
+				if (tinrc.sort_article_type != old_sort_art_type)
 					make_threads(group, TRUE);
 
 				i = which_thread(this_resp);
 				if (threadnum)
 					*threadnum = which_response(this_resp);
 
-				if (filter_state == FILTERING || filtered_articles) {
+				if (filtered_articles) {
 					int old_top = top_art;
 					long old_artnum = arts[this_resp].artnum;
 
@@ -830,8 +829,7 @@
 
 			case GLOBAL_OPTION_MENU:	/* option menu */
 				XFACE_CLEAR();
-				if (change_config_file(group) == FILTERING)
-					filter_state = FILTERING;
+				change_config_file(group);
 				draw_page(group->name, 0);
 				break;
 
@@ -894,10 +892,13 @@
 				break;
 
 			case PAGE_GROUP_SELECT:	/* return to group selection page */
+#if 0
+				/* Hasn't been used since tin 1.1 PL4 */
 				if (filter_state == FILTERING) {
 					filter_articles(group);
 					make_threads(group, FALSE);
 				}
+#endif /* 0 */
 				XFACE_CLEAR();
 				return GRP_RETSELECT;
 
diff -Nur tin-1.9.2/src/post.c tin-1.9.2-dn/src/post.c
--- tin-1.9.2/src/post.c	2006-06-16 16:58:52.000000000 +0200
+++ tin-1.9.2-dn/src/post.c	2006-10-08 13:41:23.000000000 +0200
@@ -3,7 +3,7 @@
  *  Module    : post.c
  *  Author    : I. Lea
  *  Created   : 1991-04-01
- *  Updated   : 2006-02-15
+ *  Updated   : 2006-10-01
  *  Notes     : mail/post/replyto/followup/repost & cancel articles
  *
  * Copyright (c) 1991-2006 Iain Lea <[email protected]>
@@ -125,6 +125,7 @@
  * Local prototypes
  */
 static FILE *create_mail_headers(char *filename, const char *suffix, const char *to, const char *subject, struct t_header *extra_hdrs);
+static char **build_nglist(char *ngs_list, int *ngcnt);
 static char **split_address_list(const char *addresses, unsigned int *cnt);
 static char *backup_article_name(const char *the_article);
 static int add_mail_quote(FILE *fp, int respnum);
@@ -147,6 +148,7 @@
 static t_bool is_crosspost(const char *xref);
 static t_bool must_include(const char *id);
 static t_bool repair_article(t_function *result, struct t_group *group);
+static t_bool stripped_double_ngs(char **newsgroups, int *ngcnt);
 static t_bool submit_mail_file(const char *file, struct t_group *group, FILE *articlefp, t_bool include_text);
 static t_function prompt_rejected(void);
 static t_function prompt_to_send(const char *subject);
@@ -279,7 +281,7 @@
 		if (invoke_editor(article_name, start_line_offset))
 			return TRUE;
 	} else if (func == GLOBAL_OPTION_MENU) {
-		(void) change_config_file(group); /*OD:*/
+		change_config_file(group); /*OD:*/
 		return TRUE;
 	}
 	return FALSE;
@@ -724,7 +726,8 @@
 	t_bool art_unchanged)
 {
 	FILE *fp;
-	char *ngptrs[NGLIMIT], *ftngptrs[NGLIMIT];
+	char **newsgroups;
+	char **followupto;
 	char *line, *cp, *cp2;
 	char references[HEADER_LEN];
 	char subject[HEADER_LEN];
@@ -743,7 +746,6 @@
 	int found_subject_lines = 0;
 	int errors_catbp = 0; /* sum of error-codes */
 	int warnings_catbp = 0; /* sum of warning-codes */
-	size_t nglens[NGLIMIT], ftnglens[NGLIMIT];
 	struct t_group *psGrp;
 	t_bool end_of_header = FALSE;
 	t_bool got_long_line = FALSE;
@@ -956,28 +958,10 @@
 				unfold_header(line);
 			}
 
-			strip_double_ngs(cp);
-			while (*cp) {
-				if (!(cp2 = strchr(cp, ',')))
-					cp2 = cp + strlen(cp);
-				else
-					*cp2++ = '\0';
-				if (ngcnt < NGLIMIT) {
-					nglens[ngcnt] = strlen(cp);
-					ngptrs[ngcnt] = my_malloc(nglens[ngcnt] + 1);
-					if (!ngptrs[ngcnt]) {
-						for (i = 0; i < ngcnt; i++)
-							FreeIfNeeded(ngptrs[i]);
-						for (i = 0; i < ftngcnt; i++)
-							FreeIfNeeded(ftngptrs[i]);
-						Raw(oldraw);
-						return 1;
-					}
-					strcpy(ngptrs[ngcnt], cp);
-					ngcnt++;
-				}
-				cp = cp2;
-			}
+			newsgroups = build_nglist(cp, &ngcnt);
+			if (newsgroups && ngcnt)
+				(void) stripped_double_ngs(newsgroups, &ngcnt);
+
 			if (!ngcnt)
 				errors_catbp |= CA_ERROR_EMPTY_NEWSGROUPS;
 		}
@@ -987,7 +971,6 @@
 				;
 			if (strlen(cp)) /* Followup-To not empty */
 				found_followup_to_lines++;
-			strip_double_ngs(cp);
 			if (strchr(cp, ' ') || strchr(cp, '\t')) {
 #ifdef FOLLOW_USEFOR_DRAFT
 				warnings_catbp |= CA_WARNING_SPACE_IN_FOLLOWUP_TO;
@@ -1003,28 +986,10 @@
 #endif /* FOLLOW_USEFOR_DRAFT */
 				unfold_header(line);
 			}
-			while (*cp) {
-				if (!(cp2 = strchr(cp, ',')))
-					cp2 = cp + strlen(cp);
-				else
-					*cp2++ = '\0';
-				if (ftngcnt < NGLIMIT) {
-					ftnglens[ftngcnt] = strlen(cp);
-					ftngptrs[ftngcnt] = my_malloc(ftnglens[ftngcnt] + 1);
-					if (!ftngptrs[ftngcnt]) {
-						/* out of memory? */
-						for (i = 0; i < ftngcnt; i++)
-							FreeIfNeeded(ftngptrs[i]);
-						for (i = 0; i < ngcnt; i++)
-							FreeIfNeeded(ngptrs[i]);
-						Raw(oldraw);
-						return 1;
-					}
-					strcpy(ftngptrs[ftngcnt], cp);
-					ftngcnt++;
-				}
-				cp = cp2;
-			}
+			
+			followupto = build_nglist(cp, &ftngcnt);
+			if (followupto && ftngcnt)
+				(void) stripped_double_ngs(followupto, &ftngcnt);
 		}
 	}
 
@@ -1215,7 +1180,7 @@
 	 * Is this correct for crosspostings?
 	 */
 	if (ngcnt)
-		*group = group_find(ngptrs[0]);
+		*group = group_find(newsgroups[0]);
 
 	/*
 	 * check for known 7bit charsets
@@ -1269,7 +1234,7 @@
 		if (errors_catbp & CA_ERROR_MISSING_NEWSGROUPS)
 			my_fprintf(stderr, _(txt_error_header_line_missing), "Newsgroups");
 
-		/* dublicated headers */
+		/* duplicated headers */
 		if (errors_catbp & CA_ERROR_DUPLICATED_FROM)
 			my_fprintf(stderr, _(txt_error_header_duplicate), found_from_lines, "From");
 		if (errors_catbp & CA_ERROR_DUPLICATED_SUBJECT)
@@ -1360,17 +1325,17 @@
 			my_fprintf(stderr, _(txt_warn_article_unchanged));
 		my_fprintf(stderr, _(txt_art_newsgroups), subject, PLURAL(ngcnt, txt_newsgroup));
 		for (i = 0; i < ngcnt; i++) {
-			if ((psGrp = group_find(ngptrs[i])))
-				my_fprintf(stderr, "  %s\t %s\n", ngptrs[i], BlankIfNull(psGrp->description));
+			if ((psGrp = group_find(newsgroups[i])))
+				my_fprintf(stderr, "  %s\t %s\n", newsgroups[i], BlankIfNull(psGrp->description));
 			else {
 #ifdef HAVE_FASCIST_NEWSADMIN
 				StartInverse();
 				errors++;
-				my_fprintf(stderr, _(txt_error_not_valid_newsgroup), ngptrs[i]);
+				my_fprintf(stderr, _(txt_error_not_valid_newsgroup), newsgroups[i]);
 				my_fflush(stderr);
 				EndInverse();
 #else
-				my_fprintf(stderr, (!list_active ? /* did we read the whole active file? */ _(txt_warn_not_in_newsrc) : _(txt_warn_not_valid_newsgroup)), ngptrs[i]);
+				my_fprintf(stderr, (!list_active ? /* did we read the whole active file? */ _(txt_warn_not_in_newsrc) : _(txt_warn_not_valid_newsgroup)), newsgroups[i]);
 				warnings++;
 #endif /* HAVE_FASCIST_NEWSADMIN */
 			}
@@ -1406,20 +1371,20 @@
 #endif /* HAVE_FASCIST_NEWSADMIN */
 				my_fprintf(stderr, _(txt_followup_newsgroups), PLURAL(ftngcnt, txt_newsgroup));
 				for (i = 0; i < ftngcnt; i++) {
-					if ((psGrp = group_find(ftngptrs[i])))
-						my_fprintf(stderr, "  %s\t %s\n", ftngptrs[i], BlankIfNull(psGrp->description));
+					if ((psGrp = group_find(followupto[i])))
+						my_fprintf(stderr, "  %s\t %s\n", followupto[i], BlankIfNull(psGrp->description));
 					else {
-						if (STRCMPEQ("poster", ftngptrs[i]))
-							my_fprintf(stderr, _(txt_followup_poster), ftngptrs[i]);
+						if (STRCMPEQ("poster", followupto[i]))
+							my_fprintf(stderr, _(txt_followup_poster), followupto[i]);
 						else {
 #ifdef HAVE_FASCIST_NEWSADMIN
 							StartInverse();
-							my_fprintf(stderr, _(txt_error_not_valid_newsgroup), ftngptrs[i]);
+							my_fprintf(stderr, _(txt_error_not_valid_newsgroup), followupto[i]);
 							my_fflush(stderr);
 							EndInverse();
 							errors++;
 #else
-							my_fprintf(stderr, (!list_active ? /* did we read the whole active file? */ _(txt_warn_not_in_newsrc) : _(txt_warn_not_valid_newsgroup)), ftngptrs[i]);
+							my_fprintf(stderr, (!list_active ? /* did we read the whole active file? */ _(txt_warn_not_in_newsrc) : _(txt_warn_not_valid_newsgroup)), followupto[i]);
 							warnings++;
 #endif /* HAVE_FASCIST_NEWSADMIN */
 						}
@@ -1441,10 +1406,14 @@
 	Raw(oldraw);		/* restore raw/unraw state */
 
 	/* free memory */
-	for (i = 0; i < ngcnt; i++)
-		FreeIfNeeded(ngptrs[i]);
-	for (i = 0; i < ftngcnt; i++)
-		FreeIfNeeded(ftngptrs[i]);
+	if (newsgroups) {
+		FreeIfNeeded(*newsgroups);
+		FreeIfNeeded(newsgroups);
+	}
+	if (followupto) {
+		FreeIfNeeded(*followupto);
+		FreeIfNeeded(followupto);
+	}
 
 	return (errors ? 1 : warnings ? 2 : 0);
 }
@@ -1533,7 +1502,7 @@
 				return ret_code;
 
 			case GLOBAL_OPTION_MENU:
-				(void) change_config_file(group);
+				change_config_file(group);
 				while ((i = check_article_to_be_posted(article_name, art_type, &group, art_unchanged) == 1) && repair_article(&func, group))
 					;
 				break;
@@ -4833,73 +4802,95 @@
 }
 #endif /* EVIL_INSIDE */
 
+static char **
+build_nglist(
+	char *ngs_list,
+	int *ngcnt)
+{
+	char **newsgroups;
+	char *dst;
+	char *my_list;
+	char *src;
+	char cp;
+
+	/* ulBuildArgv likes to have spaces, not commas */
+	my_list = my_malloc(strlen(ngs_list) + 1);
+	src = ngs_list;
+	dst = my_list;
+	while (cp = *src++) {
+		if (cp == ',') cp = ' ';
+		*dst++ = cp;
+	}
+	*dst = cp;
+
+	/* now build the list of newsgroups */
+	newsgroups = ulBuildArgv(my_list, ngcnt);
+	free(my_list);
+	return newsgroups;
+}
+
+static t_bool
+stripped_double_ngs(
+	char **newsgroups,
+	int *ngcnt)
+{
+	char *that_group;
+	char *this_group;
+	unsigned int i = 0;
+	unsigned int j;
+	unsigned int k;
+	t_bool changed = FALSE;
+
+	if (*ngcnt < 2)
+		/* no need to do anything with no or just one group */
+		return FALSE;
+	
+	while (this_group = newsgroups[i++]) {
+		j = i;
+		while (that_group = newsgroups[j]) {
+			if (strcasecmp(this_group, that_group) == 0) {
+				/* Double newsgroup. Move all following newsgroups downwards */
+				k = j + 1;
+				do {
+					newsgroups[k-1] = newsgroups[k];
+				} while (newsgroups[k++]);
+				changed = TRUE;
+				(*ngcnt)--;
+			} else
+				j++;
+		}
+	}
+	return changed;
+}
 
-/*
- * Strip duplicate newsgroups from within a given list of comma separated
- * groups
- * 14-Jun-'96 Sven Paulus <[email protected]>
- */
 static void
 strip_double_ngs(
 	char *ngs_list)
 {
-	char *ptr;			/* start of next (outer) newsgroup */
-	char *ptr2;			/* temporary pointer */
-	char ngroup1[HEADER_LEN];	/* outer newsgroup to compare */
-	char ngroup2[HEADER_LEN];	/* inner newsgroup to compare */
-	char cmplist[HEADER_LEN];	/* last loops output */
-	char newlist[HEADER_LEN];	/* the newly generated list without */
-										/* any duplicates of the first nwsg */
-	int ncnt1;			/* counter for the first newsgroup */
-	int ncnt2;			/* counter for the second newsgroup */
-	t_bool over1;		/* TRUE when the outer loop is over */
-	t_bool over2;		/* TRUE when the inner loop is over */
-
-	/* shortcut, check if there is only 1 group */
-	if (strchr(ngs_list, ',') != NULL) {
-		over1 = FALSE;
-		ncnt1 = 0;
-		strcpy(newlist, ngs_list);		/* make a "working copy" */
-		ptr = newlist;						/* the next outer newsg. is the 1st */
-
-		while (!over1) {
-			ncnt1++;							/* inc. outer counter */
-			strcpy(cmplist, newlist);	/* duplicate groups for inner loop */
-			ptr2 = strchr(ptr, ',');	/* search "," ... */
-			if (ptr2 != NULL) {	/* if found ... */
-				*ptr2 = '\0';
-				strcpy(ngroup1, ptr);	/* chop off first outer newsgroup */
-				ptr = ptr2 + 1;			/* pointer points to next newsgr. */
-			} else {							/* ... if not: last group */
-				over1 = TRUE;				/* wow, everything is done after . */
-				strcpy(ngroup1, ptr);	/* ... this last outer newsgroup */
-			}
+	char **newsgroups;
+	int ngcnt;
 
-			over2 = FALSE;
-			ncnt2 = 0;
+	/* shortcut, only one newsgroup */
+	if (strchr(ngs_list, ',') == NULL)
+		return;
 
-			/*
-			 * now compare with each inner newsgroup on the list,
-			 * which is behind the momentary outer newsgroup
-			 * if it is different from the outer newsgroup, append
-			 * to list, strip double-commas
-			 */
-			while (!over2) {
-				ncnt2++;
-				strcpy(ngroup2, cmplist);
-				ptr2 = strchr(ngroup2, ',');
-				if (ptr2 != NULL) {
-					strcpy(cmplist, ptr2 + 1);
-					*ptr2 = '\0';
-				} else
-					over2 = TRUE;
+	if ((newsgroups = build_nglist(ngs_list, &ngcnt)) == NULL)
+		/* something went wrong */
+		return;
 
-				if ((ncnt2 > ncnt1) && (strcasecmp(ngroup1, ngroup2)) && (strlen(ngroup2) != 0)) {
-					strcat(newlist, ",");
-					strcat(newlist, ngroup2);
-				}
-			}
+	if (stripped_double_ngs(newsgroups, &ngcnt)) {
+		/* something has changed, rebuild newsgroups list */
+		char *this_group;
+		unsigned int i = 0;
+
+		this_group = newsgroups[i++];
+		strcpy(ngs_list, this_group);
+		while (this_group = newsgroups[i++]) {
+			strcat(ngs_list, ",");
+			strcat(ngs_list, this_group);
 		}
-		strcpy(ngs_list, newlist);	/* move string to its real location */
 	}
+	free(*newsgroups);
+	free(newsgroups);
 }
+
diff -Nur tin-1.9.2/src/select.c tin-1.9.2-dn/src/select.c
--- tin-1.9.2/src/select.c	2006-02-15 19:44:38.000000000 +0100
+++ tin-1.9.2-dn/src/select.c	2006-10-08 13:40:43.000000000 +0200
@@ -3,7 +3,7 @@
  *  Module    : select.c
  *  Author    : I. Lea & R. Skrenta
  *  Created   : 1991-04-01
- *  Updated   : 2005-07-02
+ *  Updated   : 2006-10-01
  *  Notes     :
  *
  * Copyright (c) 1991-2006 Iain Lea <[email protected]>, Rich Skrenta <[email protected]>
@@ -342,7 +342,7 @@
 				break;
 
 			case GLOBAL_OPTION_MENU:
-				(void) change_config_file(NULL);
+				change_config_file(NULL);
 				read_attributes_files();
 				show_selection_page();
 				break;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.