home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- *
- * News group access.
- */
-
- #include "config.h"
- #include "articles.h"
- #include "db.h"
- #include "term.h"
- #include "menu.h"
- #include "keymap.h"
- #ifdef HAVE_SYSLOG
- #include <syslog.h>
- #endif
-
- export int dont_split_digests = 0;
- export int dont_sort_articles = 0;
- export int also_cross_postings = 0;
- export int also_unsub_groups = 0;
- export int entry_message_limit = 400;
-
- import int article_limit, also_read_articles;
- import int no_update, novice, case_fold_search;
- import int merged_menu, keep_unsubscribed, keep_unsub_long;
- import int killed_articles;
- import int seq_cross_filtering;
- import char *default_save_file;
-
- import char delayed_msg[];
- import int32 db_read_counter;
-
- /*
- * completion of group name
- */
-
- group_completion(hbuf, ix)
- char *hbuf;
- int ix;
- {
- static group_number next_group, n1, n2;
- static char *head, *tail, *last;
- static int tail_offset, prev_lgt, l1, l2;
- static group_header *prev_group, *p1, *p2;
- register group_header *gh;
- register char *t1, *t2;
- int order;
-
- if (ix < 0) return 0;
-
- if (hbuf) {
- n2 = next_group = 0;
- p2 = prev_group = NULL;
- l2 = 0;
-
- if (head = strrchr(hbuf, ','))
- head++;
- else
- head = hbuf;
- tail = hbuf + ix;
- tail_offset = ix - (head - hbuf);
- if (last = strrchr(head, '.')) last++; else last = head;
- return 1;
- }
-
- if (ix) {
- n1 = next_group, p1 = prev_group, l1 = prev_lgt;
- next_group = n2, prev_group = p2, prev_lgt = l2;
- list_completion((char *)NULL);
- }
-
- *tail = NUL;
-
- while (next_group < master.number_of_groups) {
- gh = sorted_groups[next_group++];
- if (gh->master_flag & M_IGNORE_GROUP) continue;
- if (gh->group_name_length <= tail_offset) continue;
-
- if (prev_group &&
- strncmp(prev_group->group_name, gh->group_name, prev_lgt) == 0)
- continue;
-
- order = strncmp(gh->group_name, head, tail_offset);
- if (order < 0) continue;
- if (order > 0) break;
-
- t1 = gh->group_name + tail_offset;
- if (t2 = strchr(t1, '.')) {
- strncpy(tail, t1, t2 - t1 + 1);
- tail[t2 - t1 + 1] = NUL;
- } else
- strcpy(tail, t1);
-
- prev_group = gh;
- prev_lgt = tail_offset + strlen(tail);
- if (ix) {
- if (list_completion(last) == 0) break;
- } else
- return 1;
- }
-
- if (ix) {
- n2 = next_group, p2 = prev_group, l2 = prev_lgt;
- if (n2 > master.number_of_groups)
- n2 = 0, p2 = NULL, l2 = 0;
- next_group = n1, prev_group = p1, prev_lgt = l1;
- return 1;
- }
-
- next_group = 0;
- prev_group = NULL;
- return 0;
- }
-
- static int group_level = 0;
-
- static print_header()
- {
- extern long unread_articles;
- extern int unread_groups;
-
- so_printxy(0, 0, "Newsgroup: %s", current_group->group_name);
-
- if (current_group->group_flag & G_MERGED) printf(" MERGED");
-
- clrline();
-
- so_gotoxy(-1, 0, 0);
-
- so_printf("Articles: %d", n_articles);
-
- if (no_update) {
- so_printf(" NO UPDATE");
- } else {
- if (current_group->current_first > current_group->first_article + 1)
- so_printf((killed_articles > 0) ? "(L-%ld,K-%d)" : "(L-%ld)",
- current_group->current_first - current_group->first_article - 1,
- killed_articles);
- else
- if (killed_articles > 0)
- so_printf(" (K-%d)", killed_articles);
-
- if (unread_articles > 0) {
- so_printf(" of %ld", unread_articles);
- if (unread_groups > 0)
- so_printf("/%d", unread_groups);
- }
-
- if (current_group->group_flag & G_UNSUBSCRIBED)
- so_printf(" UNSUB");
- else if (current_group->group_flag & G_NEW)
- so_printf(" NEW");
-
- if (current_group->unread_count <= 0)
- so_printf(" READ");
-
- if (group_level > 1)
- so_printf(" *NO*UPDATE*");
- }
-
- so_end();
-
- return 1; /* number of lines in header */
- }
-
- /*
- * interpretation of first_art:
- * >0 Read articles first_art..last_db_article (also read)
- * -1 Read unread or read articles accoring to -x and -aN flags
- */
-
- group_menu(gh, first_art, access_mode, mask, menu)
- register group_header *gh;
- article_number first_art;
- register flag_type access_mode;
- char *mask;
- fct_type menu;
- {
- int status, was_unread, unread_at_reentry = 0;
- int menu_cmd, o_killed;
- article_number prev_last, n;
- register group_header *mg_head;
-
- #define menu_return(cmd) { menu_cmd = (cmd); goto menu_exit; }
-
- o_killed = killed_articles;
- mark_var_stack();
-
- mg_head = (group_level == 0 && gh->group_flag & G_MERGE_HEAD) ? gh : NULL;
- group_level++;
-
- reenter:
- for (; gh; gh = gh->merge_with) {
- if (init_group(gh) <= 0) {
- if (mg_head != NULL) continue;
- menu_return( ME_NEXT );
- }
-
- if (unread_at_reentry) restore_unread(gh);
-
- m_invoke(-1);
-
- killed_articles = 0;
-
- /* don't lose (a few) new articles when reentering a read group */
- /* (the user will expect the menu to be the same, and may overlook */
- /* the new articles) */
- if (gh->group_flag & G_READ) goto update_unsafe;
-
- #ifdef RENUMBER_DANGER
- prev_last = gh->last_db_article;
- #endif
- was_unread = add_unread(gh, -1);
-
- switch (update_group(gh)) {
- case -1:
- status = -1;
- goto access_exception;
- case -3:
- return ME_QUIT;
- }
-
- #ifdef RENUMBER_DANGER
- if (gh->last_db_article < prev_last) {
- /* expire + renumbering */
- flag_type updflag;
-
- if ((gh->last_article = gh->first_db_article - 1) < 0)
- gh->last_article = 0;
- gh->first_article = gh->last_article;
- updflag = gh->group_flag & G_READ;
- gh->group_flag &= ~G_READ;
- update_rc_all(gh, 0);
- gh->group_flag &= ~G_READ;
- gh->group_flag |= updflag;
- }
- #endif
-
- if (was_unread)
- add_unread(gh, 1);
-
- update_unsafe:
- if ((gh->current_first = first_art) < 0) {
- if (access_mode & ACC_ORIG_NEWSRC)
- gh->current_first = gh->first_article + 1;
- else if (access_mode & ACC_ALSO_READ_ARTICLES)
- gh->current_first = gh->first_db_article;
- else
- gh->current_first = gh->last_article + 1;
- }
-
- if (gh->current_first <= 0) gh->current_first = 1;
-
- if (article_limit > 0) {
- n = gh->last_db_article - article_limit + 1;
- if (gh->current_first < n) gh->current_first = n;
- }
-
- if (mg_head != NULL) {
- access_mode |= ACC_MERGED_MENU | ACC_DONT_SORT_ARTICLES;
- if (mg_head != gh) access_mode |= ACC_EXTRA_ARTICLES;
- }
-
- if (entry_message_limit &&
- (n = gh->last_db_article - gh->current_first) >= entry_message_limit) {
- clrdisp();
- printf("Reading %s: %ld articles...", gh->group_name, (long)n);
- } else
- home();
- fl;
-
- status = access_group(gh, gh->current_first, gh->last_db_article,
- access_mode, mask);
-
- access_exception:
-
- if (status < 0) {
- if (status == -2) {
- clrdisp();
- printf("Read error on group %s (NFS timeout?)\n\r",
- current_group->group_name);
- printf("Skipping to next group.... (interrupt to quit)\n\r");
- if (any_key(0) == K_interrupt) nn_exit(0);
- }
-
- if (status <= -10) {
- clrdisp();
- msg("DATABASE CORRUPTED FOR GROUP %s", gh->group_name);
- #ifdef HAVE_SYSLOG
- openlog("nn", LOG_CONS, LOG_DAEMON);
- syslog(LOG_ALERT, "database corrupted for newsgroup %s.",
- gh->group_name);
- closelog();
- #endif
- user_delay(5);
- }
- if (mg_head != NULL) continue;
- menu_return( ME_NEXT );
- }
-
- if (mg_head == NULL) break;
- }
-
- if (n_articles == 0) {
- m_break_entry();
- menu_return( ME_NO_ARTICLES );
- }
-
- if (mg_head != NULL) {
- if (!dont_sort_articles) sort_articles(-1);
- init_group(mg_head);
- }
-
- samemenu:
- menu_cmd = CALL(menu)(print_header);
-
- if (menu_cmd == ME_REENTER_GROUP) {
- if (group_level != 1) {
- strcpy(delayed_msg, "can only unread groups at topmost level");
- goto samemenu;
- }
- free_memory();
- if (mg_head) gh = mg_head;
- unread_at_reentry = 1;
- goto reenter;
- }
-
- menu_exit:
-
- n = 1; /* must unsort articles */
- if (mg_head != NULL) gh = mg_head;
-
- if (!no_update) {
- do {
- if (mask == NULL && (access_mode & ACC_ALSO_READ_ARTICLES) == 0
- && first_art < 0) {
- if (menu_cmd != ME_NO_ARTICLES) gh->group_flag &= ~G_NEW;
- if ((gh->group_flag & G_UNSUBSCRIBED) == 0 || keep_unsub_long) {
- if (n) sort_articles(0);
- n = 0;
- update_rc(gh);
- }
- }
- gh->current_first = 0;
- } while (mg_head != NULL && (gh = gh->merge_with) != NULL);
- }
-
- killed_articles = o_killed;
- restore_variables();
- group_level--;
-
- return menu_cmd;
- }
-
-
- goto_group(command, ah, access_mode)
- int command;
- article_header *ah;
- flag_type access_mode;
- {
- register group_header *gh;
- char ans1, *answer, *mask, buffer[FILENAME], fbuffer[FILENAME];
- article_number first;
- memory_marker mem_marker;
- group_header *orig_group;
- int menu_cmd;
- extern int menu(), file_completion();
- extern article_header *get_menu_article();
- extern int get_from_macro;
- extern group_header *jump_to_group;
-
- #define goto_return( cmd ) \
- { menu_cmd = cmd; goto goto_exit; }
-
- m_startinput();
-
- gh = orig_group = current_group;
-
- mask = NULL;
-
- if (command == K_GOTO_GROUP)
- goto get_group_name;
-
- if (command == K_ADVANCE_GROUP)
- gh = gh->next_group;
- else
- gh = gh->prev_group;
-
- for (;;) {
- if (gh == NULL)
- goto_return(ME_NO_REDRAW);
-
- if (gh->first_db_article < gh->last_db_article && gh->current_first <= 0) {
- sprintf(buffer, "%s%s%s) ",
- (gh->group_flag & G_UNSUBSCRIBED) ? " UNSUB" : "",
- (gh->group_flag & G_MERGE_HEAD) ? " MERGED" : "",
- gh->unread_count <= 0 ? " READ" : "" );
- buffer[0] = buffer[0] == ')' ? NUL : '(';
-
- prompt("\1Enter\1 %s %s? (ABGNPy) ", gh->group_name, buffer);
-
- command = get_c();
- if (command & GETC_COMMAND) goto_return(ME_REDRAW);
- if (command == 'y') break;
- command = menu_key_map[command];
- }
-
- switch (command) {
- case K_CONTINUE:
- case K_CONTINUE_NO_MARK:
- break;
-
- case K_ADVANCE_GROUP:
- gh = gh->next_group;
- continue;
-
- case K_BACK_GROUP:
- gh = gh->prev_group;
- continue;
-
- case K_GOTO_GROUP:
- goto get_group_name;
-
- case K_PREVIOUS:
- while (gh = gh->prev_group) {
- if (gh->group_flag & G_MERGE_SUB) continue;
- if (gh->group_flag & G_COUNTED) break;
- if (gh->newsrc_line != gh->newsrc_orig) break;
- }
- continue;
-
- case K_NEXT_GROUP_NO_UPDATE:
- while (gh = gh->next_group) {
- if (gh->group_flag & G_MERGE_SUB) continue;
- if (gh->group_flag & G_COUNTED) break;
- if (gh->newsrc_line != gh->newsrc_orig) break;
- }
- continue;
-
- default:
- goto_return(ME_NO_REDRAW);
- }
- break;
- }
-
- if (gh == orig_group) goto_return(ME_NO_REDRAW);
-
- goto get_first;
-
- get_group_name:
-
- if (current_group == NULL) {
- prompt("\1Enter Group or Folder\1 (+./~) ");
- answer = get_s(NONE, NONE, "+./~", group_completion);
- } else {
- prompt("\1Group or Folder\1 (+./~ %%%s=sneN) ",
- (gh->master_flag & M_AUTO_ARCHIVE) ? "@" : "");
- strcpy(buffer, "++./0123456789~=% ");
- if (gh->master_flag & M_AUTO_ARCHIVE) buffer[0] = '@';
- answer = get_s(NONE, NONE, buffer, group_completion);
- }
-
- if (answer == NULL) goto_return(ME_NO_REDRAW);
-
- if ((ans1 = *answer) == NUL || ans1 == SP) {
- if (current_group == NULL) goto_return(ME_NO_REDRAW);
- goto get_first;
- }
-
- sprintf(buffer, "%c", ans1);
-
- switch (ans1) {
-
- case '@':
- if (current_group == NULL ||
- (current_group->master_flag & M_AUTO_ARCHIVE) == 0)
- goto_return(ME_NO_REDRAW);
- answer = current_group->archive_file;
- goto get_folder;
-
- case '%':
- if (current_group == NULL) goto_return(ME_NO_REDRAW);
- if ((current_group->group_flag & G_FOLDER) == 0) {
- if (!ah) {
- prompt("\1READ\1");
- if ((ah = get_menu_article()) == NULL)
- goto_return(ME_NO_REDRAW);
- }
- if ((ah->flag & A_DIGEST) == 0) {
- *group_file_name = NUL;
- sprintf(fbuffer, "%s%ld", group_path_name, ah->a_number);
- answer = fbuffer;
- goto get_folder;
- }
- }
-
- msg("cannot split articles inside a folder or digest");
- goto_return(ME_NO_REDRAW);
-
- case '.':
- case '~':
- strcat(buffer, "/");
- case '+':
- case '/':
- if (!get_from_macro) {
- prompt("\1Folder\1 ");
- answer = get_s(NONE, buffer, NONE, file_completion);
- if (answer == NULL || answer[0] == NUL) goto_return(ME_NO_REDRAW);
- }
- goto get_folder;
-
- case 'a':
- if (answer[1] != NUL && strcmp(answer, "all")) break;
- if (current_group == NULL) goto_return(ME_NO_REDRAW);
- access_mode |= ACC_ALSO_READ_ARTICLES | ACC_ALSO_CROSS_POSTINGS;
- first = 0;
- goto more_articles;
-
- case 'u':
- if (answer[1] != NUL && strcmp(answer, "unread")) break;
- if (current_group == NULL) goto_return(ME_NO_REDRAW);
- access_mode |= ACC_ORIG_NEWSRC;
- first = gh->first_article + 1;
- goto enter_new_level;
-
- case 'e':
- case 'n':
- case 's':
- if (answer[1] != NUL && answer[1] != '=') break;
- /* fall thru */
- case '=':
- if (current_group == NULL) goto_return(ME_NO_REDRAW);
- goto get_mask;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (current_group == NULL) goto_return(ME_NO_REDRAW);
- if (gh->current_first <= gh->first_db_article) {
- msg("No extra articles");
- flush_input();
- goto_return(ME_NO_REDRAW);
- }
- if (!get_from_macro) {
- prompt("\1Number of extra articles\1 max %ld: ",
- gh->current_first - gh->first_db_article);
- sprintf(buffer, "%c", ans1);
- answer = get_s(NONE, buffer, NONE, NULL_FCT);
- if (answer == NULL || *answer == NUL) goto_return(ME_NO_REDRAW);
- }
- first = gh->current_first - atol(answer);
- goto more_articles;
-
- default:
- break;
- }
-
- if ((gh = lookup(answer)) == NULL) {
- msg("No group named %s", answer);
- goto_return(ME_NO_REDRAW);
- }
-
-
- get_first:
-
- m_advinput();
-
- if (gh->master_flag & M_BLOCKED ||
- gh->last_db_article == 0 ||
- gh->last_db_article < gh->first_db_article) {
- msg("Group %s is %s", gh->group_name,
- (gh->master_flag & M_BLOCKED) ? "blocked" : "empty");
- goto_return(ME_NO_REDRAW);
- }
-
- if (gh != orig_group) {
- if (gh->current_first > 0) {
- msg("Group %s already active", gh->group_name);
- goto_return(ME_NO_REDRAW);
- }
- gh->current_first = gh->last_db_article + 1;
- }
-
- ans1 = ah ? 's' : 'a';
- if (gh != orig_group) {
- if (gh->unread_count > 0) ans1 = 'j';
- } else {
- if (gh->unread_count > 0 && gh->current_first > (gh->first_article + 1))
- ans1 = 'u';
- else if (gh->current_first <= gh->first_db_article)
- ans1 = 's'; /* no more articles to read */
- }
-
- prompt("\1Number of%s articles\1 (%sua%ssne) (%c) ",
- gh == orig_group ? " extra" : "",
- (gh->unread_count > 0) ? "j" : "",
- (gh->master_flag & M_AUTO_ARCHIVE) ? "@" : "",
- ans1);
-
- if (novice)
- msg("Use: j)ump u)nread a)ll @)archive s)ubject n)ame e)ither or number");
-
- answer = get_s(NONE, NONE, " jua@s=ne", NULL_FCT);
- if (answer == NULL) goto_return(ME_NO_REDRAW);
- if (*answer == NUL || *answer == SP) answer = &ans1;
-
- switch (*answer) {
- case '@':
- if ((gh->master_flag & M_AUTO_ARCHIVE) == 0) {
- msg("No archive");
- goto_return(ME_NO_REDRAW);
- }
- answer = gh->archive_file;
- goto get_folder;
-
- case 'u':
- access_mode |= ACC_ORIG_NEWSRC;
- first = gh->first_article + 1;
- goto enter_new_level;
-
- case 'j':
- if (gh == orig_group || gh->unread_count <= 0) {
- msg("Cannot jump - no unread articles");
- goto_return(ME_NO_REDRAW);
- }
- jump_to_group = gh;
- goto_return(ME_QUIT);
-
- case 'a':
- first = 0;
- access_mode |= ACC_ALSO_READ_ARTICLES | ACC_ALSO_CROSS_POSTINGS;
- goto more_articles;
-
- case '=':
- case 's':
- case 'n':
- case 'e':
- goto get_mask;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- first = gh->current_first - atol(answer);
- goto more_articles;
-
- default:
- ding();
- goto_return(ME_NO_REDRAW);
- }
-
-
- more_articles:
- if (first > gh->last_db_article) goto_return(ME_NO_REDRAW);
-
- if (gh != orig_group) goto enter_new_level;
-
- if (gh->current_first <= gh->first_db_article) {
- msg("No extra articles");
- goto_return(ME_NO_REDRAW);
- }
-
- if (access_group(gh, first, gh->current_first == gh->first_article + 1 ?
- gh->last_db_article : gh->current_first - 1,
- ACC_EXTRA_ARTICLES | ACC_ALSO_CROSS_POSTINGS |
- ACC_ALSO_READ_ARTICLES | ACC_ONLY_READ_ARTICLES,
- (char *)NULL) < 0) {
- msg("Cannot read extra articles (now)");
- goto_return(ME_NO_REDRAW);
- }
-
- gh->current_first = first;
- goto_return(ME_REDRAW);
-
- get_folder:
- m_endinput();
- if (strcmp(answer, "+") == 0)
- answer = (gh->save_file != NULL) ? gh->save_file : default_save_file;
- if (!expand_file_name(buffer, answer, 1)) goto_return (ME_NO_REDRAW);
- menu_cmd = folder_menu(buffer);
- gh = NULL;
- goto goto_exit;
-
- get_mask:
- first = 0;
- access_mode |= ACC_ALSO_READ_ARTICLES | ACC_ALSO_CROSS_POSTINGS;
- switch (*answer) {
- case '=':
- *answer = 's';
- case 's':
- access_mode |= ACC_ON_SUBJECT;
- break;
- case 'n':
- access_mode |= ACC_ON_SENDER;
- break;
- case 'e':
- access_mode |= ACC_ON_SUBJECT | ACC_ON_SENDER;
- break;
- }
-
- if (get_from_macro || answer[1] == '=') {
- mask = answer + 1;
- if (*mask == '=') mask++;
- } else {
- prompt("%c=", *answer);
- mask = get_s(ah == NULL ? NONE :
- (access_mode & ACC_ON_SUBJECT ? ah->subject : ah->sender),
- NONE, ah ? NONE : "%=", NULL_FCT);
- if (mask == NULL) goto_return(ME_NO_REDRAW);
- if (*mask == '%' || *mask == '=') {
- if ((ah = get_menu_article()) == 0) goto_return(ME_NO_REDRAW);
- *mask = NUL;
- }
- }
-
- if (*mask == NUL) {
- if (ah == NULL) goto_return(ME_NO_REDRAW);
- strncpy(mask, (access_mode & ACC_ON_SUBJECT) ? ah->subject : ah->sender, GET_S_BUFFER);
- mask[GET_S_BUFFER-1] = NUL;
- }
-
- if (*mask) {
- if (case_fold_search) fold_string(mask);
- } else
- mask = NULL;
-
- enter_new_level:
- mark_memory(&mem_marker);
- m_endinput();
- menu_cmd = group_menu(gh, first, access_mode, mask, menu);
- release_memory(&mem_marker);
-
- goto_exit:
- if (gh != orig_group)
- if (orig_group) init_group(orig_group);
-
- m_endinput();
- return menu_cmd;
- }
-
- static merged_header()
- {
- so_printxy(0, 0, "MERGED NEWS GROUPS: %d ARTICLES", n_articles);
- clrline();
-
- return 1;
- }
-
- merge_and_read(access_mode, mask)
- flag_type access_mode;
- char *mask;
- {
- register group_header *gh;
- group_header dummy_group;
- time_t t1, t2;
- long kb = 0, kbleft = 0;
-
- time(&t1); t2 = 0;
-
- free_memory();
-
- access_mode |= ACC_DONT_SORT_ARTICLES | ACC_MERGED_MENU;
- if (!seq_cross_filtering)
- if (also_read_articles || mask || also_cross_postings)
- access_mode |= ACC_ALSO_CROSS_POSTINGS;
- if (dont_split_digests)
- access_mode |= ACC_DONT_SPLIT_DIGESTS;
-
- Loop_Groups_Sequence(gh) {
- if (gh->group_flag & G_FOLDER) continue;
- if (gh->master_flag & M_NO_DIRECTORY) continue;
- if ((gh->group_flag & G_UNSUBSCRIBED) && !also_unsub_groups)
- continue;
- if (!also_read_articles && gh->last_article >= gh->last_db_article)
- continue;
-
- kbleft += gh->data_write_offset;
- }
-
- Loop_Groups_Sequence(gh) {
- if (s_hangup || s_keyboard) break;
-
- if (gh->group_flag & G_FOLDER) {
- printf("\n\rIgnoring folder: %s\n\r", gh->group_name);
- continue;
- }
-
- if (gh->master_flag & M_NO_DIRECTORY) continue;
- if ((gh->group_flag & G_UNSUBSCRIBED) && !also_unsub_groups)
- continue;
-
- if (also_read_articles)
- access_mode |= ACC_ALSO_READ_ARTICLES;
- else
- if (gh->last_article >= gh->last_db_article)
- continue;
-
- if (init_group(gh) <= 0) continue;
-
- if (t2 > 2 && kb > 50000) {
- printf("\r%4lds\t%lds\t%s", kbleft/(kb/t2), (long)t2, gh->group_name);
- } else
- #ifdef KBYTE_PER_SECOND
- printf("\r%4lds\t%lds\t%s", kbleft/(KBYTE_PER_SECOND*1024)),
- (long)t2, gh->group_name);
- #else
- printf("\r\t%lds\t%s", (long)t2, gh->group_name);
- #endif
- clrline();
-
- access_group(gh, (article_number)(-1), gh->last_db_article,
- access_mode, mask);
-
- time(&t2); t2 -= t1;
- kb += gh->data_write_offset;
- kbleft -= gh->data_write_offset;
- }
- merge_memory();
- if (n_articles == 0) return;
- if (!dont_sort_articles) sort_articles(-1);
-
- dummy_group.group_flag = G_FAKED;
- dummy_group.master_flag = 0;
- dummy_group.save_file = NULL;
- dummy_group.group_name = "dummy";
- dummy_group.kill_list = NULL;
-
- current_group = &dummy_group;
-
- kb = (kb + 1023) >> 10;
- sprintf(delayed_msg, "Read %ld articles in %ld seconds (%ld kbyte/s)",
- (long)db_read_counter, (long)t2, t2 > 0 ? kb/t2 : kb);
-
- menu(merged_header);
-
- free_memory();
- }
-
- unsubscribe(gh)
- group_header *gh;
- {
- if (no_update) {
- msg("nn started in \"no update\" mode");
- return 0;
- }
-
- if (gh->group_flag & G_FOLDER) {
- msg("cannot unsubscribe to a folder");
- return 0;
- }
-
- if (gh->group_flag & G_UNSUBSCRIBED) {
- prompt("Already unsubscribed. \1Resubscribe to\1 %s ? ",
- gh->group_name);
- if (yes(0) <= 0) return 0;
-
- add_to_newsrc(gh);
- add_unread(gh, 1);
- } else {
- prompt("\1Unsubscribe to\1 %s ? ", gh->group_name);
- if (yes(0) <= 0) return 0;
-
- add_unread(gh, -1);
- update_rc_all(gh, 1);
- }
-
- return 1;
- }
-
- static disp_group(gh)
- group_header *gh;
- {
- if (pg_next() < 0) return -1;
-
- printf("%c%6ld%c%s%s%s",
- (gh->group_flag & G_MERGED) == 0 ? ' ' :
- (gh->group_flag & G_MERGE_HEAD) ? '&' : '+',
-
- (long)(gh->unread_count),
-
- (gh == current_group) ? '*' : ' ',
-
- gh->group_name,
-
- (gh->group_flag & G_NEW) ? " NEW" :
- (gh->group_flag & G_UNSUBSCRIBED) ? " (!)" : "",
-
- gh->enter_macro ? " %" : "");
-
- return 0;
- }
-
- /*
- * amount interpretation:
- * -1 presentation sequence, unread,subscribed+current
- * 0 unread,subscribed
- * 1 unread,all
- * 2 all,all 3=>unsub
- */
-
- group_overview(amount)
- int amount;
- {
- register group_header *gh;
-
- clrdisp();
-
- pg_init(0, 2);
-
- if (amount < 0) {
- Loop_Groups_Sequence(gh) {
- if (gh->group_flag & G_FAKED) continue;
- if (gh->master_flag & M_NO_DIRECTORY) continue;
- if (gh != current_group)
- if ((gh->group_flag & G_COUNTED) == 0) continue;
- if (disp_group(gh) < 0) break;
- }
- } else
- Loop_Groups_Sorted(gh) {
- if (gh->master_flag & (M_NO_DIRECTORY | M_IGNORE_GROUP)) continue;
- if (amount <= 1 && gh->unread_count <= 0) continue;
- if (amount == 0 && (gh->group_flag & G_UNSUBSCRIBED)) continue;
- if (amount == 3 && (gh->group_flag & G_UNSUBSCRIBED) == 0) continue;
-
- if (disp_group(gh) < 0) break;
- }
-
- pg_end();
- }
-