Index: xvnews/CHANGES diff -c xvnews/CHANGES:1.21 xvnews/CHANGES:1.21.2.1 *** xvnews/CHANGES:1.21 Sat Dec 31 14:44:28 1994 --- xvnews/CHANGES Wed Jun 7 14:00:10 1995 *************** *** 1,6 **** --- 1,34 ---- This is a list of changes to each version of xvnews. Most recent changes are listed first: + Changes 2.3 -> 2.3.1 + -------------------- + + 2.3.1 is a bug-fix release only. No new features have been added. Here + is a list of problems which should be fixed in this release. + + o When talking to the NNTP server, take into account that the + connection may be lost (e.g. because of timeouts). + + o If xvnews uses the POSIX regular expression routines, xvnews should + also free used expressions, otherwise memory will leak this way. + (With big KILL files this can be quite a leak!) + + o When reading an article with a line starting with a dot xvnews + would stop reading the rest of the article, and then become confused + by it. + + o With many subscribed groups xvnews could get into memory problems, + because no additional memory would be allocated. + + o If a server has more than 5000 groups, and xvnews would have to + "view all groups", it would crash because of a hard-coded limit on the + number of groups. + + o Subjects not starting with a letter would be sorted in the wrong + order. + + Changes 2.2.1 -> 2.3 -------------------- Index: xvnews/Makefile.dist diff -c xvnews/Makefile.dist:1.14 xvnews/Makefile.dist:1.14.2.1 *** xvnews/Makefile.dist:1.14 Sat Dec 3 17:30:55 1994 --- xvnews/Makefile.dist Wed Jun 7 14:05:22 1995 *************** *** 113,119 **** @echo "Making all in guide/libguide..." @cd guide/libguide; ${MAKE} -f Makefile.dist "CC=${CC}" "RANLIB=ranlib" ${MAKE} -f Makefile.dist xvnews "CFLAGS=-DDEBUG -Wall -g ${CFLAGS}" \ ! "LDFLAGS=-Lguide -Lguide/libguide -L/usr/X11R6/xview/lib -L/usr/X11R6/lib" objects: $(SOURCES.c) $(SOURCES.h) $(SOURCES.y) $(TARGETS.c) $(TARGETS.h) $(OBJECTS) --- 113,119 ---- @echo "Making all in guide/libguide..." @cd guide/libguide; ${MAKE} -f Makefile.dist "CC=${CC}" "RANLIB=ranlib" ${MAKE} -f Makefile.dist xvnews "CFLAGS=-DDEBUG -Wall -g ${CFLAGS}" \ ! "LDFLAGS=-Lguide -Lguide/libguide -L/usr/openwin/lib -L/usr/X11R6/lib" objects: $(SOURCES.c) $(SOURCES.h) $(SOURCES.y) $(TARGETS.c) $(TARGETS.h) $(OBJECTS) Index: xvnews/README diff -c xvnews/README:1.5 xvnews/README:1.5.2.1 *** xvnews/README:1.5 Sat Oct 1 20:48:36 1994 --- xvnews/README Wed Jun 7 14:06:12 1995 *************** *** 1,11 **** xvnews -- an openlook newsreader xvnews is an openlook newsreader that uses the XView 3 toolkit. It has ! been tested using Sun OpenWindows version 2 and version 3 xnews servers ! along with olvwm, olwm, and twm. I see no reason that xvnews shouldn't run on ! any X windowing system that has access to the XView libraries. The ! current version of xvnews is tested on both Solaris 1.x and Solaris ! 2.x platforms. How to build xvnews: --- 1,11 ---- xvnews -- an openlook newsreader xvnews is an openlook newsreader that uses the XView 3 toolkit. It has ! been tested using Sun OpenWindows version 2 and version 3 xnews ! servers along with olvwm, olwm, and twm. I see no reason that xvnews ! shouldn't run on any X windowing system that has access to the XView ! libraries. The current version of xvnews is tested on both Solaris 1.x ! and Solaris 2.x platforms, and on Linux. How to build xvnews: *************** *** 45,50 **** --- 45,54 ---- You can then use this target to build xvnews. (e.g. 'make -f Makefile.dist sunos5' will build xvnews for Solaris 2.x) + Note: you will see a number of warnings during compilation. These + are harmless, and mostly caused by problems within the XView + include files. + 6. If you want a version of xvnews to run on OpenWindowsV2 as well as OpenWindowsV3, statically link in libxview and libolgx. However, this is no longer the default. *************** *** 56,60 **** 9. If you have problems with xvnews, feel free to mail J.J.deGraaff@twi.tudelft.nl xvnews is compliant with items 1-9 of the "Good Net-Keeping Seal of ! Approval, release 1.1" by Ron Newman. \ No newline at end of file --- 60,74 ---- 9. If you have problems with xvnews, feel free to mail J.J.deGraaff@twi.tudelft.nl + + Updates and new versions of xvnews will be available at: + + ftp.twi.tudelft.nl:/pub/news/ + ftp.uu.net:/networking/news/readers/xvnews/ + xvnews is compliant with items 1-9 of the "Good Net-Keeping Seal of ! Approval, release 1.1" by Ron Newman. ! ! I hope you have a good time reading news with xvnews, ! ! Hans de Graaff Index: xvnews/patchlevel.h diff -c xvnews/patchlevel.h:1.11 xvnews/patchlevel.h:1.11.2.2 *** xvnews/patchlevel.h:1.11 Sat Dec 31 14:50:01 1994 --- xvnews/patchlevel.h Sat Jun 10 12:11:05 1995 *************** *** 28,32 **** */ #define VERSION 2.3 ! #define PATCHLEVEL 0 #undef BETA --- 28,32 ---- */ #define VERSION 2.3 ! #define PATCHLEVEL 2 #undef BETA Index: xvnews/server.c diff -c xvnews/server.c:1.11 xvnews/server.c:1.11.2.2 *** xvnews/server.c:1.11 Mon Dec 19 13:40:37 1994 --- xvnews/server.c Fri Jun 9 14:40:44 1995 *************** *** 194,202 **** #else va_start(args); #endif ! vfprintf(ser_wr_fp, formatstr, args); ! fprintf(ser_wr_fp, "\r\n"); ! fflush(ser_wr_fp); va_end(args); } --- 194,218 ---- #else va_start(args); #endif ! if (vfprintf(ser_wr_fp, formatstr, args) == EOF) { ! #ifdef DEBUG ! fprintf(stderr, "Couldn't write to NNTP server, trying to reconnect\n"); ! #endif ! reconnect_server(); ! /* Try to write again, we should be connected again */ ! if (vfprintf(ser_wr_fp, formatstr, args) == EOF) { ! fprintf(stderr, "Agian couldn't write to NNTP server, giving up"); ! save_newsrc(); ! exit(1); ! } ! } ! ! if (fprintf(ser_wr_fp, "\r\n") == EOF) { ! fprintf(stderr, "Couldn't write end of line to NNTP server\n"); ! } ! if (fflush(ser_wr_fp) == EOF) { ! fprintf(stderr, "Couldn't flush connection with NNTP server\n"); ! } va_end(args); } *************** *** 338,342 **** } } } ! return "No description available"; } --- 354,358 ---- } } } ! return "(No description available)"; } Index: xvnews/textsw_regexp.c diff -c xvnews/textsw_regexp.c:1.5 xvnews/textsw_regexp.c:1.5.2.1 *** xvnews/textsw_regexp.c:1.5 Sun Sep 4 20:52:47 1994 --- xvnews/textsw_regexp.c Wed Jun 7 14:07:54 1995 *************** *** 86,91 **** --- 86,92 ---- } } free(ptr); + xvnews_free(); return 1; } Index: xvnews/xv_init_newsrc.c diff -c xvnews/xv_init_newsrc.c:1.10 xvnews/xv_init_newsrc.c:1.10.2.1 *** xvnews/xv_init_newsrc.c:1.10 Mon Dec 19 13:39:21 1994 --- xvnews/xv_init_newsrc.c Wed Jun 7 14:08:33 1995 *************** *** 28,37 **** */ #include #include #include #include - #include #include #include #include --- 28,37 ---- */ #include + #include #include #include #include #include #include #include *************** *** 75,81 **** put_server("LIST"); get_server(aline, sizeof(aline)); get_server(aline, sizeof(aline)); ! while (*aline != '.') { sscanf(aline, "%s%d%d%*c%c", group, &first, &last, &status); #ifdef CNEWS_DONT_SHOW if (status == '=' || status == 'x') { --- 75,81 ---- put_server("LIST"); get_server(aline, sizeof(aline)); get_server(aline, sizeof(aline)); ! while (*aline != '.' || strlen(aline) != 1) { sscanf(aline, "%s%d%d%*c%c", group, &first, &last, &status); #ifdef CNEWS_DONT_SHOW if (status == '=' || status == 'x') { *************** *** 141,147 **** } } if (done == 0) ! printf("Invalid newsgroup %s, line %d of %s\n", sgroup, count, Global->newsrc); else ++active; --- 141,147 ---- } } if (done == 0) ! fprintf(stderr, "xvnews: Invalid newsgroup %s, line %d of %s\n", sgroup, count, Global->newsrc); else ++active; *************** *** 234,240 **** sscanf(aline, "%s", group); Global->subslist[Global->num_subs] = strdup(group); if (++Global->num_subs >= l_max) { ! Global->subslist = (char **)realloc(Global->subslist, l_max * sizeof(char *)); } } } --- 234,242 ---- sscanf(aline, "%s", group); Global->subslist[Global->num_subs] = strdup(group); if (++Global->num_subs >= l_max) { ! Global->subslist = (char **)realloc(Global->subslist, ! 2 * l_max * sizeof(char *)); ! l_max *= 2; } } } Index: xvnews/xv_kill.c diff -c xvnews/xv_kill.c:1.13 xvnews/xv_kill.c:1.13.2.1 *** xvnews/xv_kill.c:1.13 Mon Dec 19 13:38:31 1994 --- xvnews/xv_kill.c Wed Jun 7 14:09:12 1995 *************** *** 32,38 **** #include #include #include - #include #include #include #include --- 32,37 ---- *************** *** 51,56 **** --- 50,56 ---- STATIC_FUNCTION( void makeKillFile, (char *)); STATIC_FUNCTION( void parseKillFiles, (struct newsrc_node *)); STATIC_FUNCTION( int processKill, (char *, struct kill_node *, int *)); + STATIC_FUNCTION( char *messageId, (int)); STATIC_FUNCTION( char *strlower, (char *)); STATIC_FUNCTION( int confirmKillAll, (kill_popup_objects *)); STATIC_FUNCTION( int countKills, (struct kill_list *)); *************** *** 100,105 **** --- 100,106 ---- dead = kill->junk; *place = kill->place; } + xvnews_free(); kill = kill->next; if (newc) { *************** *** 153,160 **** c++; a = strchr(c, '/'); if (a == NULL) { ! printf("Malformed entry %s in kill file %s!\n", ! aline, file); continue; } while (*(a - 1) == '\\') --- 154,162 ---- c++; a = strchr(c, '/'); if (a == NULL) { ! fprintf(stderr, ! "Malformed entry %s in kill file %s!\n", ! aline, file); continue; } while (*(a - 1) == '\\') *************** *** 162,171 **** *a = '\0'; err = xvnews_comp(c); if (err != NULL) { ! printf("\nExpression error: %s!\nLine \"%s\" in file %s\n", ! err, aline, file); ! continue; } kill = (struct kill_node *)malloc(sizeof(struct kill_node)); kill->string = strdup(c); /* By default, kill by subject, unless header is --- 164,175 ---- *a = '\0'; err = xvnews_comp(c); if (err != NULL) { ! fprintf(stderr, "Expression error: %s!\n", err); ! fprintf(stderr, "Line \"%s\" in file %s\n", aline, file); ! xvnews_free(); ! continue; } + xvnews_free(); kill = (struct kill_node *)malloc(sizeof(struct kill_node)); kill->string = strdup(c); /* By default, kill by subject, unless header is *************** *** 498,503 **** --- 502,508 ---- dead = kill->junk; *place = kill->place; } + xvnews_free(); kill = kill->next; } return dead; *************** *** 946,953 **** extern void genMessage(art) int art; { ! char *c, *messageId(); ! struct message *list = Global->messages, *new = NULL; if (Global->mode != ARTICLE_MODE || Global->single != NULL) return; --- 951,961 ---- extern void genMessage(art) int art; { ! char *c; ! struct message *list = Global->messages, *new = NULL; ! ! if (Global->mode != ARTICLE_MODE || Global->single != NULL) ! return; if (Global->mode != ARTICLE_MODE || Global->single != NULL) return; *************** *** 990,998 **** } } ! char * messageId(art) ! int art; { static char command[MAX_COMMAND_LEN], message[MAX_MESSAGE_LEN]; int status; --- 998,1006 ---- } } ! STATIC char * messageId(art) ! int art; { static char command[MAX_COMMAND_LEN], message[MAX_MESSAGE_LEN]; int status; Index: xvnews/xv_newsrc.c diff -c xvnews/xv_newsrc.c:1.7 xvnews/xv_newsrc.c:1.7.2.1 *** xvnews/xv_newsrc.c:1.7 Sat Dec 31 14:47:21 1994 --- xvnews/xv_newsrc.c Wed Jun 7 14:09:50 1995 *************** *** 168,269 **** xvnews_xvnews_window_objects *ip; int flg; { ! char mode[32], *str, *err; ! static char *list[5000]; ! int count=0; ! int row = xv_get(ip->groups_list, PANEL_LIST_FIRST_SELECTED); ! struct newsrc_node *curr; ! xvnews_search_popup_objects *srp = (xvnews_search_popup_objects *) xv_get(ip->xvnews_window, XV_KEY_DATA, SEARCH_POPUP, NULL); ! ! if (row != -1) { ! str = (char *)xv_get(ip->groups_list, PANEL_LIST_STRING, row); ! sscanf(str, "%s", Global->old_group); ! } else ! memset(Global->old_group, '\0', 64); ! ! switch (flg) { ! case 0: ! strcpy(mode, ""); ! Global->mode = ALL_GROUPS; ! break; ! case 1: ! strcpy(mode, "subscribed"); ! Global->mode = SUB_GROUPS; ! break; ! case 2: ! strcpy(mode, "unsubscribed"); ! Global->mode = UNSUB_GROUPS; ! break; ! case 3: ! str =(char *)xv_get(srp->search_text,PANEL_VALUE,NULL); ! err = xvnews_comp(str); ! if (err != NULL) { ! xv_set(srp->search_popup, FRAME_LEFT_FOOTER, ! err, NULL); ! xvnews_err(ip, "Expression error: %s!\n", err); ! return -1; ! } ! strcpy(mode, "matching"); ! Global->mode = MATCH_GROUPS; ! break; ! } ! xvnews_err(ip, "Retrieving all %s groups...\n", mode); ! xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL); ! for (curr = Global->head; curr != NULL; curr = curr->nextgroup) { ! switch (flg) { ! case 0: ! list[count] = (char *)malloc(80); ! sprintf(list[count], ! curr->subscribed == SUBSCRIBED ? ! "%-64.64ssubscribed":"%-64.64sunsubscribed", ! curr->newsgroup); ! count++; ! break; ! case 1: ! if (curr->subscribed == SUBSCRIBED) { ! list[count] = (char *)malloc(80); ! sprintf(list[count],"%-64.64ssubscribed", ! curr->newsgroup); ! count++; ! } ! break; ! case 2: ! if (curr->subscribed == UNSUBSCRIBED) { ! list[count] = (char *)malloc(80); ! sprintf(list[count], "%-64.64sunsubscribed", ! curr->newsgroup); ! count++; ! } ! break; ! case 3: ! if (xvnews_exec(curr->newsgroup)) { ! list[count] = (char *)malloc(80); ! sprintf(list[count], ! (curr->subscribed == SUBSCRIBED) ? "%-64.64ssubscribed":"%-64.64sunsubscribed", ! curr->newsgroup); ! count++; ! } ! break; ! } ! } ! list[count] = NULL; ! xv_set(ip->groups_list, PANEL_LIST_DELETE_ROWS, 0, ! xv_get(ip->groups_list, PANEL_LIST_NROWS, NULL), NULL); ! xv_set(ip->groups_list, ! PANEL_LIST_INSERT_STRINGS, 0, list, NULL); ! if (xv_get(ip->groups_list, PANEL_LIST_NROWS, NULL)) ! xv_set(ip->groups_list, PANEL_LIST_FONTS, ! Global->listfont, NULL, NULL); ! while(count) ! free(list[--count]); ! new_group_set(ip); ! if (xv_get(ip->groups_list, PANEL_LIST_NROWS) > 1) ! xv_set(ip->groups_list, PANEL_LIST_SELECT, 0, FALSE, NULL); ! if (Global->mode == MATCH_GROUPS) ! xv_set(ip->sort_newsrc_butt, XV_SHOW, FALSE, NULL); ! xvnews_err(ip, "All %s groups displayed\n", mode); ! xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL); ! return 1; } extern void group_change(ip, flg) --- 168,293 ---- xvnews_xvnews_window_objects *ip; int flg; { ! char mode[32], *str, *err; ! char **list = (char **)NULL; ! int count=0, l_max = INIT_NUM_GROUPS; ! int row = xv_get(ip->groups_list, PANEL_LIST_FIRST_SELECTED); ! struct newsrc_node *curr; ! xvnews_search_popup_objects *srp = (xvnews_search_popup_objects *) ! xv_get(ip->xvnews_window, XV_KEY_DATA, SEARCH_POPUP, NULL); ! ! list = (char **)malloc(INIT_NUM_GROUPS * sizeof(char *)); ! memset(list, '\0', INIT_NUM_GROUPS * sizeof(char *)); ! ! /* If a group is currently selected, save it */ ! if (row != -1) { ! str = (char *)xv_get(ip->groups_list, PANEL_LIST_STRING, row); ! sscanf(str, "%s", Global->old_group); ! } else { ! memset(Global->old_group, '\0', 64); ! } ! ! /* Set correct mode and text, depending on the selected menuitem */ ! ! switch (flg) { ! case 0: ! strcpy(mode, ""); ! Global->mode = ALL_GROUPS; ! break; ! case 1: ! strcpy(mode, "subscribed"); ! Global->mode = SUB_GROUPS; ! break; ! case 2: ! strcpy(mode, "unsubscribed"); ! Global->mode = UNSUB_GROUPS; ! break; ! case 3: ! str =(char *)xv_get(srp->search_text,PANEL_VALUE,NULL); ! err = xvnews_comp(str); ! if (err != NULL) { ! xv_set(srp->search_popup, FRAME_LEFT_FOOTER, err, NULL); ! xvnews_err(ip, "Expression error: %s!\n", err); ! return -1; ! } ! strcpy(mode, "matching"); ! Global->mode = MATCH_GROUPS; ! break; ! } ! ! /* Go create the groups, based on the current active list */ ! xvnews_err(ip, "Retrieving all %s groups...\n", mode); ! xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL); ! ! for (curr = Global->head; curr; curr = curr->nextgroup) { ! switch (flg) { ! case 0: ! list[count] = (char *)malloc(80); ! sprintf(list[count], curr->subscribed == SUBSCRIBED ! ? "%-64.64ssubscribed":"%-64.64sunsubscribed", ! curr->newsgroup); ! count++; ! break; ! case 1: ! if (curr->subscribed == SUBSCRIBED) { ! list[count] = (char *)malloc(80); ! sprintf(list[count],"%-64.64ssubscribed", curr->newsgroup); ! count++; ! } ! break; ! case 2: ! if (curr->subscribed == UNSUBSCRIBED) { ! list[count] = (char *)malloc(80); ! sprintf(list[count], "%-64.64sunsubscribed", curr->newsgroup); ! count++; ! } ! break; ! case 3: ! if (xvnews_exec(curr->newsgroup)) { ! list[count] = (char *)malloc(80); ! sprintf(list[count], (curr->subscribed == SUBSCRIBED) ! ? "%-64.64ssubscribed":"%-64.64sunsubscribed", ! curr->newsgroup); ! count++; ! } ! break; ! } ! ! if (count >= l_max) { ! l_max += INIT_NUM_GROUPS; ! list = (char **)realloc(list, l_max *sizeof(char *)); ! } ! } ! ! if (flg == 3) { ! xvnews_free(); ! } ! ! list[count] = NULL; ! xv_set(ip->groups_list, PANEL_LIST_DELETE_ROWS, 0, ! xv_get(ip->groups_list, PANEL_LIST_NROWS, NULL), NULL); ! xv_set(ip->groups_list, PANEL_LIST_INSERT_STRINGS, 0, list, NULL); ! if (xv_get(ip->groups_list, PANEL_LIST_NROWS, NULL)) { ! xv_set(ip->groups_list, PANEL_LIST_FONTS, Global->listfont, NULL, NULL); ! } ! ! while(count) { ! free(list[--count]); ! } ! free(list); ! ! new_group_set(ip); ! if (xv_get(ip->groups_list, PANEL_LIST_NROWS) > 1) { ! xv_set(ip->groups_list, PANEL_LIST_SELECT, 0, FALSE, NULL); ! } ! ! if (Global->mode == MATCH_GROUPS) { ! xv_set(ip->sort_newsrc_butt, XV_SHOW, FALSE, NULL); ! } ! ! xvnews_err(ip, "All %s groups displayed\n", mode); ! xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL); ! return 1; } extern void group_change(ip, flg) *************** *** 369,379 **** /* We only need to remove the group when there are articles left. So check the name of the group first, and if it matches, remove it. Otherwise it was removed ! already, and we don't need to bother */ old = (char *)xv_get(ip->groups_list, PANEL_LIST_STRING, row, NULL); ! if (!strncmp(group, old, strlen(group))) { ! xv_set(ip->groups_list, PANEL_LIST_DELETE, row, NULL); ! xv_set(ip->groups_list, PANEL_LIST_SELECT, row, TRUE, NULL); } if (Global->mode == GROUP_MODE) --- 393,407 ---- /* We only need to remove the group when there are articles left. So check the name of the group first, and if it matches, remove it. Otherwise it was removed ! already, and we don't need to bother. ! In some cases old equals one, meaning? that there ! was no string, or something. */ old = (char *)xv_get(ip->groups_list, PANEL_LIST_STRING, row, NULL); ! if (old && (int)old != 1) { ! if (!strncmp(group, old, strlen(group))) { ! xv_set(ip->groups_list, PANEL_LIST_DELETE, row, NULL); ! xv_set(ip->groups_list, PANEL_LIST_SELECT, row, TRUE, NULL); ! } } if (Global->mode == GROUP_MODE) Index: xvnews/xv_regex.c diff -c xvnews/xv_regex.c:1.5 xvnews/xv_regex.c:1.5.2.1 *** xvnews/xv_regex.c:1.5 Sat Oct 1 20:55:11 1994 --- xvnews/xv_regex.c Wed Jun 7 14:10:23 1995 *************** *** 37,46 **** causing the greatest portability problems for xvnews. Essentially, there are three types of routines: BSD, featuring re_comp and re_exec, AT&T, featuring compile and step, and ! the new POSIX.2 routines regcomp and regexec. ! To keep xvnews portable I'm wrapping these functions into two ! functions: xv_comp and xv_step. */ #if defined(SVR4_REGEX) --- 37,46 ---- causing the greatest portability problems for xvnews. Essentially, there are three types of routines: BSD, featuring re_comp and re_exec, AT&T, featuring compile and step, and ! the new POSIX.2 routines regcomp, regexec, and regfree. ! To keep xvnews portable I'm wrapping these functions into three ! functions: xvnews_comp and xvnews_step, and xvnews_free. */ #if defined(SVR4_REGEX) *************** *** 61,66 **** --- 61,72 ---- #include #endif + #ifdef DEBUG + /* This global variable knows whether a compiled expression + is valid. I can use this for additional error-checking */ + static int xv_regex_current = 0; + #endif + #ifdef POSIX_REGEX static regex_t xv_regex_local; #endif *************** *** 69,80 **** char *regex_str; { #ifdef POSIX_REGEX ! regcomp(&xv_regex_local, regex_str, REG_NOSUB|REG_ICASE); return (char *)NULL; #endif #ifdef SVR4_REGEX ! compile(regex_str, regex_buf, ®ex_buf[MAXPATHLEN], '\0'); return (char *)NULL; #endif --- 75,122 ---- char *regex_str; { #ifdef POSIX_REGEX ! int result; ! static char regex_error[MAX_COMMAND_LEN]; ! #endif ! ! #ifdef SVR4_REGEX ! char *result; ! static char regex_error[MAX_COMMAND_LEN]; ! #endif ! ! ! #ifdef DEBUG ! if (xv_regex_current) { ! fprintf(stderr, "xv_regex: compiling regex when another is still compiled!\n"); ! } ! xv_regex_current = 1; ! #endif ! ! #ifdef POSIX_REGEX ! result = regcomp(&xv_regex_local, regex_str, REG_NOSUB|REG_ICASE); ! if (result != REG_NOERROR) { ! sprintf(regex_error, ! "Regular expression could not be compiled: %s\n", ! regex_str); ! #ifdef DEBUG ! fprintf(stderr, regex_error); ! #endif ! return regex_error; ! } return (char *)NULL; #endif #ifdef SVR4_REGEX ! result = compile(regex_str, regex_buf, ®ex_buf[MAXPATHLEN], '\0'); ! if (!result) { ! sprintf(regex_error, ! "Regular expression could not be compiled: %s\n", ! regex_str); ! #ifdef DEBUG ! fprintf(stderr, regex_error); ! #endif ! return regex_error; ! } return (char *)NULL; #endif *************** *** 87,92 **** --- 129,140 ---- char *s; { int result = -1; + + #ifdef DEBUG + if (xv_regex_current == 0) { + fprintf(stderr, "xv_regex: execution regex, but no current expression!\n"); + } + #endif #ifdef POSIX_REGEX result = !regexec(&xv_regex_local, s, (size_t)0, NULL, 0); *************** *** 105,110 **** --- 153,165 ---- extern void xvnews_free() { + #ifdef DEBUG + if (xv_regex_current == 0) { + fprintf(stderr, "xv_regex: freeing regex, but no current regex compiled\n"); + } + xv_regex_current = 0; + #endif + #ifdef POSIX_REGEX regfree(&xv_regex_local); #endif Index: xvnews/xv_sort.c diff -c xvnews/xv_sort.c:1.11 xvnews/xv_sort.c:1.11.2.1 *** xvnews/xv_sort.c:1.11 Mon Dec 19 13:34:47 1994 --- xvnews/xv_sort.c Wed Jun 7 14:11:00 1995 *************** *** 34,41 **** #include "xvnews_ui.h" #include "xvnews.h" ! STATIC_FUNCTION( int compareFieldArtnum, (void *, void *)); ! STATIC_FUNCTION( int compareFieldSubject, (void *, void *)); STATIC_FUNCTION( void createSortList, ()); STATIC_FUNCTION( void loadList, ()); STATIC_FUNCTION( char *getSubject, ()); --- 34,41 ---- #include "xvnews_ui.h" #include "xvnews.h" ! STATIC_FUNCTION( int compareFieldArtnum, (const void *, const void *)); ! STATIC_FUNCTION( int compareFieldSubject, (const void *, const void *)); STATIC_FUNCTION( void createSortList, ()); STATIC_FUNCTION( void loadList, ()); STATIC_FUNCTION( char *getSubject, ()); *************** *** 52,58 **** static s_node **sort_list; static l_max = 0; char *old = NULL; ! int i=0, nrows = xv_get(ip->articles_list, PANEL_LIST_NROWS), nrow = nrows; assert( flg == XV_SORT_ARTNUM || flg == XV_SORT_SUBJECT ); --- 52,59 ---- static s_node **sort_list; static l_max = 0; char *old = NULL; ! int i=0, nrow; ! int nrows = xv_get(ip->articles_list, PANEL_LIST_NROWS); assert( flg == XV_SORT_ARTNUM || flg == XV_SORT_SUBJECT ); *************** *** 83,88 **** --- 84,90 ---- } /* Add all rows to the sortlist */ + nrow = nrows; while (nrow) { old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, --nrow); createSortList(sort_list, old, flg, i++); *************** *** 95,100 **** --- 97,109 ---- } sort_list[i] = NULL; + /* If everything went right we should have created a correct + number of records, test with assert(). + Note: if this doesn't match it might point us to the empty + lines problem, because we would be feeding qsort wrong + information */ + assert( i == nrows ); + switch(flg) { case XV_SORT_ARTNUM: qsort(sort_list, nrows, sizeof(s_node *), compareFieldArtnum); *************** *** 106,116 **** loadList(list, sort_list); - /* - if (flg == 2) - xv_set(ip->articles_list, XV_SHOW, FALSE, NULL); - */ - xv_set(ip->articles_list, PANEL_LIST_DELETE_ROWS, 0, nrows, NULL); xv_set(ip->articles_list, PANEL_LIST_INSERT_STRINGS, 0, list, NULL); --- 115,120 ---- *************** *** 140,162 **** char *old; int flg, i; { ! if (!sort_list[i]) ! { ! sort_list[i] = (s_node *)malloc(sizeof(s_node)); ! sort_list[i]->string = ! (char *)malloc(SUBJECT_LENGTH + AUTHOR_LENGTH + 20); ! } ! strcpy(sort_list[i]->string, old); ! sort_list[i]->len = SUBJECT_LENGTH; ! switch(flg) { ! case XV_SORT_ARTNUM: ! sort_list[i]->subject = sort_list[i]->string; ! break; ! case XV_SORT_SUBJECT: ! sort_list[i]->subject = ! getSubject(sort_list[i]->string, &(sort_list[i]->len)); ! break; } } --- 144,164 ---- char *old; int flg, i; { ! if (!sort_list[i]) { ! sort_list[i] = (s_node *)malloc(sizeof(s_node)); ! sort_list[i]->string = (char *)malloc(SUBJECT_LENGTH + AUTHOR_LENGTH + 20); ! } ! strcpy(sort_list[i]->string, old); ! sort_list[i]->len = SUBJECT_LENGTH; ! switch(flg) { ! case XV_SORT_ARTNUM: ! sort_list[i]->subject = sort_list[i]->string; ! break; ! case XV_SORT_SUBJECT: ! sort_list[i]->subject = ! getSubject(sort_list[i]->string, &(sort_list[i]->len)); ! break; } } *************** *** 177,183 **** if (!strncasecmp(c, "re:", 3)) { c += 3, (*i) -= 3; ! while (!isalpha(*c) && *i) c++, (*i)--; } --- 179,185 ---- if (!strncasecmp(c, "re:", 3)) { c += 3, (*i) -= 3; ! while (*c == ' ' && *i) c++, (*i)--; } *************** *** 186,197 **** /* * Compare Subjects for subject-sorted order. If the subjects ! * are identical, compare again for article numver. ! * TODO: should eally be done using References header... */ static int compareFieldSubject(a, b) ! void *a, *b; { int result; s_node *aa = *((s_node **)a); --- 188,198 ---- /* * Compare Subjects for subject-sorted order. If the subjects ! * are identical, compare again using the References */ static int compareFieldSubject(a, b) ! const void *a, *b; { int result; s_node *aa = *((s_node **)a); *************** *** 201,214 **** aa->len < bb->len ? aa->len:bb->len); if (result == 0) { ! result = compareFieldArtnum(a, b); } return result; } static int compareFieldArtnum(a, b) ! void *a, *b; { s_node *aa = *((s_node **)a); s_node *bb = *((s_node **)b); --- 202,215 ---- aa->len < bb->len ? aa->len:bb->len); if (result == 0) { ! result = compareFieldArtnum(a, b); } return result; } static int compareFieldArtnum(a, b) ! const void *a, *b; { s_node *aa = *((s_node **)a); s_node *bb = *((s_node **)b); Index: xvnews/xvnews.1 diff -c xvnews/xvnews.1:1.7 xvnews/xvnews.1:1.7.2.2 *** xvnews/xvnews.1:1.7 Sun Nov 13 21:26:59 1994 --- xvnews/xvnews.1 Sat Jun 10 12:11:08 1995 *************** *** 1,4 **** ! .TH XVNEWS 1 "July 1994" .SH NAME xvnews \- an OPEN LOOK news reader --- 1,4 ---- ! .TH XVNEWS 1 "June 1995" .SH NAME xvnews \- an OPEN LOOK news reader *************** *** 29,35 **** ] .SH DESCRIPTION ! .B xvnews 2.3 is an OpenLook interface for reading Usenet news. It provides a menu-driven facility for reading, storing and sending news articles. It also provides mail functionality to reply to or forward --- 29,35 ---- ] .SH DESCRIPTION ! .B xvnews 2.3.2 is an OpenLook interface for reading Usenet news. It provides a menu-driven facility for reading, storing and sending news articles. It also provides mail functionality to reply to or forward Index: xvnews/xvnews.h diff -c xvnews/xvnews.h:1.17 xvnews/xvnews.h:1.17.2.1 *** xvnews/xvnews.h:1.17 Sat Dec 31 14:46:29 1994 --- xvnews/xvnews.h Wed Jun 7 14:12:08 1995 *************** *** 61,66 **** --- 61,67 ---- extern Attr_attribute LOAD_POPUP; #define BUFFERLEN 8192 + #define NNTP_HEADER_LENGTH 1024 /* Maximum length of nntp header */ #define GROUP_MODE 1 #define SUBSCRIBED 1 #define UNSUBSCRIBED 0 *************** *** 76,82 **** #define ALL_ARTICLES 4 #define MAX_COMMAND_LEN 128 #define MAX_MESSAGE_LEN 512 ! #define MAX_ARTICLE_LEN 1024 #define POSTED_OK 240 #define NEWS_REPLY 1 #define NEWS_POST 4 --- 77,83 ---- #define ALL_ARTICLES 4 #define MAX_COMMAND_LEN 128 #define MAX_MESSAGE_LEN 512 ! #define MAX_ARTICLE_LEN 2048 #define POSTED_OK 240 #define NEWS_REPLY 1 #define NEWS_POST 4 Index: xvnews/xvnews_stubs.c diff -c xvnews/xvnews_stubs.c:1.15 xvnews/xvnews_stubs.c:1.15.2.1 *** xvnews/xvnews_stubs.c:1.15 Sun Nov 13 21:28:02 1994 --- xvnews/xvnews_stubs.c Wed Jun 7 14:12:50 1995 *************** *** 66,72 **** (xvnews_xvnews_window_objects *) xv_get(item, XV_KEY_DATA, INSTANCE); char *select = (char *)xv_get(item, MENU_STRING); ! xvnews_err(ip, "Quitting %s...\n", Global->group); if (!strcmp(select, "update newsrc")) { if (Global->mode == ARTICLE_MODE) update_newsrc(ip, 0); --- 66,72 ---- (xvnews_xvnews_window_objects *) xv_get(item, XV_KEY_DATA, INSTANCE); char *select = (char *)xv_get(item, MENU_STRING); ! xvnews_err(ip, "Quitting %s...\n", Global->group->newsgroup); if (!strcmp(select, "update newsrc")) { if (Global->mode == ARTICLE_MODE) update_newsrc(ip, 0); *************** *** 1932,1937 **** --- 1932,1938 ---- else sessionHeaderKill(ip, kp, kill); + xvnews_free(); free(kill->string); free(kill); xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL); *************** *** 1975,1980 **** --- 1976,1982 ---- else sessionHeaderKill(ip, kp, kill); + xvnews_free(); free(kill->string); free(kill); xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);