static char rcsid[] = "@(#)$Id: elm.c,v 1.9 1996/08/08 19:49:23 wfp5p Exp $"; /******************************************************************************* * The Elm Mail System - $Revision: 1.9 $ $State: Exp $ * * This file and all associated files and documentation: * Copyright (c) 1988-1995 USENET Community Trust * Copyright (c) 1986,1987 Dave Taylor ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * Bill Pemberton, Elm Coordinator * flash@virginia.edu * ******************************************************************************* * $Log: elm.c,v $ * Revision 1.9 1996/08/08 19:49:23 wfp5p * Alpha 11 * * Revision 1.8 1996/05/09 15:51:18 wfp5p * Alpha 10 * * Revision 1.7 1996/03/14 17:27:59 wfp5p * Alpha 9 * * Revision 1.6 1996/03/13 14:37:59 wfp5p * Alpha 9 before Chip's big changes * * Revision 1.5 1995/09/29 17:42:05 wfp5p * Alpha 8 (Chip's big changes) * * Revision 1.4 1995/09/11 15:19:05 wfp5p * Alpha 7 * * Revision 1.3 1995/05/10 13:34:48 wfp5p * Added mailing list stuff by Paul Close * * Revision 1.2 1995/04/20 21:01:46 wfp5p * Added the showreply feature and emacs key bindings. * * Revision 1.1.1.1 1995/04/19 20:38:35 wfp5p * Initial import of elm 2.4 PL0 as base for elm 2.5. * ******************************************************************************/ /* Main program of the ELM mail system! */ #define INTERN #include "elm_defs.h" #include /* so that "GetKey_jmpbuf" gets defined */ #include "elm_globals.h" #include "s_elm.h" #ifdef I_TIME # include #endif #ifdef I_SYSTIME # include #endif #ifdef BSD # include #endif long bytes(); char *format_long(), *parse_arguments(); main(argc, argv) int argc; char *argv[]; { int ch; char address[SLEN], to_whom[SLEN], *req_mfile; int i,j; /** Random counting variables (etc) **/ int pageon, /** for when we receive new mail... **/ last_in_folder; /** for when we receive new mail too... **/ long num; /** another variable for fun.. **/ int err; initialize_common(); req_mfile = parse_arguments(argc, argv, to_whom); initialize(req_mfile); if (OPMODE_IS_SENDMODE(opmode)) { if (OPMODE_IS_INTERACTIVE(opmode)) { sprintf(address, catgets(elm_msg_cat, ElmSet, ElmSendOnlyMode, "Send only mode [ELM %s]"), version_buff); CenterLine(1, address); } if (to_whom && *to_whom) dprint(3, (debugfile, "Mail-only: mailing to\n-> \"%s\"\n", format_long(to_whom, 3))); else dprint(3, (debugfile, "Mail-only; no recipient specified\n")); (void) send_message(to_whom, (char *)NULL, batch_subject, SM_ORIGINAL); leave(LEAVE_NORMAL); } headers_per_page = LINES - (mini_menu ? 13 : 8); if (headers_per_page < 1) headers_per_page = 1; /* read in the folder */ newmbox(req_mfile, FALSE); redraw = 1; while (1) { if (redraw) showscreen(); redraw = 0; nufoot = 0; nucurr = 0; if (curr_folder.fp) fflush (curr_folder.fp); if ((num = bytes(curr_folder.filename)) != curr_folder.size) { dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n", num - curr_folder.size)); error(catgets(elm_msg_cat, ElmSet, ElmNewMailHangOn, "New mail has arrived! Hang on...")); last_in_folder = curr_folder.num_mssgs; pageon = header_page; newmbox(curr_folder.filename, TRUE); /* last won't be touched! */ clear_error(); header_page = pageon; if (selected) /* update count of selected messages */ selected += curr_folder.num_mssgs - last_in_folder; if (on_page(curr_folder.curr_mssg)) /* do we REALLY have to rewrite? */ showscreen(); else { update_title(); ClearLine(LINES-1); /* remove reading message... */ if ((curr_folder.num_mssgs - last_in_folder) == 1) error(catgets(elm_msg_cat, ElmSet, ElmNewMessageRecv, "1 new message received.")); else error1(catgets(elm_msg_cat, ElmSet, ElmNewMessageRecvPlural, "%d new messages received."), curr_folder.num_mssgs - last_in_folder); } } prompt(nls_Prompt); CleartoEOLN(); ch = GetKey(timeout); CleartoEOS(); if (clear_error()) MoveCursor(LINES-3, strlen(nls_Prompt)); #ifdef DEBUG dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch)); #endif switch (ch) { case KEY_TIMEOUT: break; case KEY_REDRAW: ++redraw; break; case '?' : if (help(FALSE)) redraw++; else nufoot++; break; case '$' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmResyncFolder, "Resynchronize folder")); redraw += resync(); nucurr = get_page(curr_folder.curr_mssg); break; case '|' : WriteChar('|'); if (curr_folder.num_mssgs < 1) { error(catgets(elm_msg_cat, ElmSet, ElmNoMailToPipe, "No mail to pipe!")); FlushInput(); } else { redraw += do_pipe(); } break; #ifdef ALLOW_SUBSHELL case '!' : WriteChar('!'); redraw += subshell(); break; #endif case '&' : TreatAsSpooled = !TreatAsSpooled; if (TreatAsSpooled) { error(catgets(elm_msg_cat, ElmSet, ElmMagicOn, "[Magic On]")); } else { error(catgets(elm_msg_cat, ElmSet, ElmMagicOff, "[Magic Off]")); } break; case '%' : if (curr_folder.curr_mssg > 0) { get_return(address, curr_folder.curr_mssg-1); clear_error(); PutLine1(LINES,(COLS-strlen(address))/2, "%.78s", address); } else { error(catgets(elm_msg_cat, ElmSet, ElmNoMailReturnAddress, "No mail to get return address of!")); } break; case '<' : /* scan current message for calendar information */ #ifdef ENABLE_CALENDAR if (curr_folder.num_mssgs < 1) { error(catgets(elm_msg_cat, ElmSet, ElmNoMailToScan, "No mail to scan!")); } else { PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmScanForCalendar, "Scan message for calendar entries...")); scan_calendar(); } #else error(catgets(elm_msg_cat, ElmSet, ElmSorryNoCalendar, "Sorry. Calendar function disabled.")); #endif break; case 'a' : alias(); redraw++; break; case 'b' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmBounceMessage, "Bounce message")); if (curr_folder.num_mssgs < 1) { error(catgets(elm_msg_cat, ElmSet, ElmNoMailToBounce, "No mail to bounce!")); FlushInput(); } else nufoot = remail(); break; case 'c' : define_softkeys(SOFTKEYS_CHANGE); redraw += change_file(catgets(elm_msg_cat, ElmSet, ElmChangeFolder, "Change folder")); define_softkeys(SOFTKEYS_MAIN); break; #ifdef ALLOW_MAILBOX_EDITING case 'e' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmEditFolder, "Edit folder")); if (curr_folder.curr_mssg > 0) { edit_mailbox(); } else { error(catgets(elm_msg_cat, ElmSet, ElmFolderIsEmpty, "Folder is empty!")); } break; #else case 'e' : error(catgets(elm_msg_cat, ElmSet, ElmNoFolderEdit, "Folder editing isn't configured in this version of ELM.")); break; #endif case 'f' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmForward, "Forward")); if (curr_folder.curr_mssg > 0) { if(forward()) redraw++; else nufoot++; } else { error(catgets(elm_msg_cat, ElmSet, ElmNoMailToForward, "No mail to forward!")); FlushInput(); } break; case 'g' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmGroupReply, "Group reply")); if (curr_folder.curr_mssg > 0) { if (curr_folder.headers[curr_folder.curr_mssg-1]->status & FORM_LETTER) { error(catgets(elm_msg_cat, ElmSet, ElmCantGroupReplyForm, "Can't group reply to a Form!!")); FlushInput(); } else { redraw += reply_to_everyone(); } } else { error(catgets(elm_msg_cat, ElmSet, ElmNoMailToReply, "No mail to reply to!")); FlushInput(); } break; case 'h' : if (filter) PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmMessageWithHeaders, "Message with headers...")); else PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmDisplayMessage, "Display message")); if(curr_folder.curr_mssg > 0) { j = filter; filter = FALSE; i = show_msg(curr_folder.curr_mssg); ResizeScreen(); while (i) i = process_showmsg_cmd(i); filter = j; redraw++; (void)get_page(curr_folder.curr_mssg); } else error(catgets(elm_msg_cat, ElmSet, ElmNoMailToRead, "No mail to read!")); break; case 'M' : if (show_mlists) { char buffer[SLEN]; strcpy(buffer, catgets(elm_msg_cat, ElmSet, ElmMlistOff, "[Mlists Off]")); PutLine0(LINES,(COLS-10)/2,buffer); show_mlists = 0; } else { char buffer[SLEN]; strcpy(buffer, catgets(elm_msg_cat, ElmSet, ElmMlistOn, "[Mlists On]")); PutLine0(LINES,(COLS-10)/2,buffer); show_mlists = 1; } last_header_page = -1; /* force a redraw */ show_headers(); break; case 'm' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmMail, "Mail")); redraw += send_message((char *)NULL, (char *)NULL, (char *)NULL, SM_ORIGINAL); break; case ' ' : case ctrl('J'): case ctrl('M'): PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmDisplayMessage, "Display message")); if(curr_folder.curr_mssg > 0 ) { define_softkeys(SOFTKEYS_READ); i = show_msg(curr_folder.curr_mssg); ResizeScreen(); while (i) i = process_showmsg_cmd(i); define_softkeys(SOFTKEYS_MAIN); redraw++; (void)get_page(curr_folder.curr_mssg); } else error(catgets(elm_msg_cat, ElmSet, ElmNoMailToRead, "No mail to read!")); break; case 'n' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmNextMessage, "Next Message")); if(curr_folder.curr_mssg > 0 ) { define_softkeys(SOFTKEYS_READ); i = show_msg(curr_folder.curr_mssg); ResizeScreen(); while (i) i = process_showmsg_cmd(i); define_softkeys(SOFTKEYS_MAIN); redraw++; if (++curr_folder.curr_mssg > curr_folder.num_mssgs) curr_folder.curr_mssg = curr_folder.num_mssgs; (void)get_page(curr_folder.curr_mssg); } else error(catgets(elm_msg_cat, ElmSet, ElmNoMailToRead, "No mail to read!")); break; case 'o' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmOptions, "Options")); if((i=options()) > 0) get_page(curr_folder.curr_mssg); redraw++; /* always fix da screen... */ break; case 'p' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmPrintMail, "Print mail")); if (curr_folder.num_mssgs < 1) { error(catgets(elm_msg_cat, ElmSet, ElmNoMailToPrint, "No mail to print!")); } else if (print_msg(TRUE) != 0) redraw++; break; case 'q' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmQuit, "Quit")); quit(TRUE); break; case 'Q' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmQuickQuit, "Quick quit")); quit(FALSE); break; case 'r' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmReplyToMessage, "Reply to message")); if (curr_folder.curr_mssg > 0) redraw += reply(); else { error(catgets(elm_msg_cat, ElmSet, ElmNoMailToReplyTo, "No mail to reply to!")); FlushInput(); } break; case '>' : /** backwards compatibility **/ case 'C' : case 's' : if (curr_folder.num_mssgs < 1) { if (ch != 'C') error(catgets(elm_msg_cat, ElmSet, ElmNoMailToSave, "No mail to save!")); else error(catgets(elm_msg_cat, ElmSet, ElmNoMailToCopy, "No mail to copy!")); FlushInput(); } else { if (save(&redraw, FALSE, (ch != 'C')) && resolve_mode && ch != 'C') { if((i=next_message(curr_folder.curr_mssg-1, TRUE)) != -1) { curr_folder.curr_mssg = i+1; nucurr = get_page(curr_folder.curr_mssg); } } } ClearLine(LINES-2); break; #ifdef ALLOW_STATUS_CHANGING case 'S' : PutLine0(-1, -1, "Status"); /* catgets(elm_msg_cat, ElmSet, ElmOptions, */ if((i=ch_status()) > 0) get_page(curr_folder.curr_mssg); redraw++; /* always fix da screen... */ break; #else case 'S' : error(catgets(elm_msg_cat, ElmSet, ElmNoStatusChange, "Status changing isn't configured in this version of ELM.")); break; #endif case 'X' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmQuickExit, "Quick Exit")); quit_abandon(FALSE); case ctrl('Q') : case 'x' : PutLine0(-1, -1, catgets(elm_msg_cat, ElmSet, ElmExit, "Exit")); quit_abandon(TRUE); break; case '@': case '#': for (;;) { error( "Debug: display p)age, current m)essage, t)erminal, or q)uit to return."); if ((i = ReadCh()) == 'q') break; switch (i) { case 'p': debug_page(); break; case 'm': debug_message(); break; case 't': debug_terminal(); break; default: Beep(); } } clear_error(); redraw++; break; /* None of the menu specific commands were chosen, therefore * it must be a "motion" command (or an error). */ default : motion(ch); } if (redraw) { showscreen(); redraw = 0; nucurr = 0; nufoot = 0; } check_range(); if (nucurr == NEW_PAGE) show_headers(); else if (nucurr == SAME_PAGE) show_current(); else if (nufoot) { if (mini_menu) { MoveCursor(LINES-7, 0); CleartoEOS(); show_menu(); } else { MoveCursor(LINES-4, 0); CleartoEOS(); } show_last_error(); /* for those operations that have to * clear the footer except for a message. */ } } /* the BIG while loop! */ } debug_page() { int i, first, last, line; char buffer[SLEN]; first = header_page * headers_per_page; /* starting header */ if ((last = first + (headers_per_page-1)) >= curr_folder.num_mssgs) last = curr_folder.num_mssgs-1; ClearScreen(); PutLine1(0, 0, "Current mail file = %s", curr_folder.filename); PutLine2(1, 0, "Current message number = %-8d %d message(s) total", curr_folder.curr_mssg, curr_folder.num_mssgs); PutLine2(2, 0, "Header_page = %-8d %d page(s) total", header_page+1, (int) (curr_folder.num_mssgs / headers_per_page) + 1); sprintf(buffer, "%3s %-16s %-34s %5s %8s %8s", "Num", "From", "Subject", "Lines", "Offset", "ContLen"); PutLine0(4, 0, buffer); line = 5; for (i = first ; i <= last ; ++i) { sprintf(buffer, "%3d %-16.16s %-35.35s %4d %8d %8d", i+1, curr_folder.headers[i]->from, curr_folder.headers[i]->subject, curr_folder.headers[i]->lines, curr_folder.headers[i]->offset, curr_folder.headers[i]->content_length); PutLine0(++line, 0, buffer); } } debug_message() { /**** Spit out the current message record. Include EVERYTHING in the record structure. **/ struct header_rec *hdr; char buffer[SLEN]; time_t tval; int row, i; #define ShowStr(row, name, str) PutLine2((row), 0, \ (strlen(str) > 62 ? "%-16s|%.60s..." : "%-16s|%s|"), (name), (str)) #define ShowNum(row, name, num) PutLine2((row), 0, \ "%-16s%ld", (name), (long)(num)) ClearScreen(); PutLine1(0, 24, "--- Debug Display - Message %d Header_Rec ---", curr_folder.curr_mssg); PutLine0(2, 24, "status:"); PutLine0(2, 32, "A C D E F M D N N O P T U V"); PutLine0(3, 32, "c o e x o i e p e l r a r i"); PutLine0(4, 32, "t n l p r m c l w d i g g s"); PutLine0(5, 32, "n f d d m e o a v d n i"); if (curr_folder.num_mssgs == 0) { CenterLine(8, catgets(elm_msg_cat, ElmSet, ElmNoMailToCheck, "No mail to check.")); return; } hdr = curr_folder.headers[curr_folder.curr_mssg-1]; ShowNum(2, "index_number:", hdr->index_number); ShowNum(3, "offset:", hdr->offset); ShowNum(4, "lines:", hdr->lines); ShowNum(5, "content_length:", hdr->content_length); ShowNum(6, "cc_index:", hdr->cc_index); ShowStr(7, "mailx_status:", hdr->mailx_status); #define SHOW_STATUS(hdr, FLAG) (!!((hdr)->status & (FLAG))) sprintf(buffer, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d", SHOW_STATUS(hdr, ACTION), SHOW_STATUS(hdr, CONFIDENTIAL), SHOW_STATUS(hdr, DELETED), SHOW_STATUS(hdr, EXPIRED), SHOW_STATUS(hdr, FORM_LETTER), SHOW_STATUS(hdr, MIME_MESSAGE), SHOW_STATUS(hdr, MIME_NEEDDECOD), SHOW_STATUS(hdr, MIME_NOTPLAIN), SHOW_STATUS(hdr, NEW), SHOW_STATUS(hdr, UNREAD), SHOW_STATUS(hdr, PRIVATE), SHOW_STATUS(hdr, TAGGED), SHOW_STATUS(hdr, URGENT), SHOW_STATUS(hdr, VISIBLE)); PutLine0(7, 32, buffer); row = 8; trim_trailing_spaces(strcpy(buffer, ctime(&hdr->received_time))); ShowStr(++row, "received_time:", buffer); tval = hdr->time_sent + hdr->tz_offset; trim_trailing_spaces(strcpy(buffer, ctime(&tval))); ShowStr(++row, "time_sent:", buffer); ShowStr(++row, "time_zone:", hdr->time_zone); ShowNum(++row, "tz_offset:", hdr->tz_offset); ShowStr(++row, "from:", hdr->from); ShowStr(++row, "to:", hdr->to); ShowStr(++row, "subject:", hdr->subject); ShowStr(++row, "messageid:", hdr->messageid); ShowStr(++row, "allfrom:", hdr->allfrom); ShowStr(++row, "allto:", hdr->allto); ShowNum(++row, "ml_cc_index:", hdr->ml_cc_index); ShowStr(++row, "ml_to:", ""); WriteChar('\b'); /* erase closing "|" added above */ for (i = 0; i < hdr->ml_to.len; i++) { if (i > 0) PutLine0(-1, -1, ", "); PutLine0(-1, -1, hdr->ml_to.str[i]); } WriteChar('|'); } check_range() { int count, curr, i; if (inalias) { count = num_aliases; curr = curr_alias; } else { count = curr_folder.num_mssgs; curr = curr_folder.curr_mssg; } i = compute_visible(curr); if ((curr < 1) || (selected && i < 1)) { if (count > 0) { /* We are out of range! Get to first message! */ if (selected) curr = compute_visible(1); else curr = 1; } else curr = 0; } else if ((curr > count) || (selected && i > selected)) { if (count > 0) { /* We are out of range! Get to last (visible) message! */ if (selected) curr = visible_to_index(selected)+1; else curr = count; } else curr = 0; } if (inalias) curr_alias = curr; else curr_folder.curr_mssg = curr; } static char *no_mail = NULL; static char *no_aliases = NULL; #define ifmain(a,b) (inalias ? (b) : (a)) motion(ch) int ch; { /* Consolidated the standard menu navigation and delete/tag * commands to a function. */ int key_offset; /** Position offset within keyboard string **/ int i; int count, curr; if (inalias) { count = num_aliases; curr = curr_alias; } else { count = curr_folder.num_mssgs; curr = curr_folder.curr_mssg; } if (no_mail == NULL) { no_mail = catgets(elm_msg_cat, ElmSet, ElmNoMailInFolder, "No mail in folder!"); no_aliases = catgets(elm_msg_cat, ElmSet, ElmNoAliases, "No aliases!"); } switch (ch) { case '/' : /* scan mbox or aliases for string */ if (count < 1) { error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToScan, "No %s to scan!"), nls_items); FlushInput(); } else if (pattern_match()) { if (inalias) curr = curr_alias; else curr = curr_folder.curr_mssg; nucurr = get_page(curr); } break; case KEY_NPAGE: case KEY_RIGHT: case ctrl('V'): case '+' : /* move to next page if we're not on the last */ if((selected && ((header_page+1)*headers_per_page < selected)) ||(!selected && ((header_page+1)*headers_per_page 0) { header_page--; nucurr = NEW_PAGE; if(move_when_paged) { /* move to first message of new page */ if(selected) curr = visible_to_index( header_page * headers_per_page + 1) + 1; else curr = header_page * headers_per_page + 1; } } else error(catgets(elm_msg_cat, ElmSet, ElmAlreadyOnFirstPage, "Already on first page.")); break; case KEY_HOME: case '=' : if (selected) curr = visible_to_index(1)+1; else curr = 1; nucurr = get_page(curr); break; case KEY_END: case '*' : if (selected) curr = (visible_to_index(selected)+1); else curr = count; nucurr = get_page(curr); break; /* case EOF : leave(0); break; */ case ctrl('D') : case '^' : case 'd' : if (count < 1) { error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToDelete, "No %s to delete!"), nls_item); /* fflush(stdin);*/ } else { if(ch == ctrl('D')) { /* if current item did not become deleted, * don't to move to the next undeleted item */ if(!meta_match(MATCH_DELETE)) break; } else delete_msg((ch == 'd'), TRUE); if (resolve_mode) /* move after mail resolved */ if((i=next_message(curr-1, TRUE)) != -1) { curr = i+1; nucurr = get_page(curr); } } break; case 'H' : { /* move to first line of page */ int first_on_page; if (selected) first_on_page = visible_to_index( header_page * headers_per_page + 1) + 1; else first_on_page = header_page*headers_per_page + 1; /* don't bother to redraw if you don't move */ if (curr != first_on_page) { curr = first_on_page; nucurr = SAME_PAGE; } break; } case ctrl('N'): case 'J' : if(curr > 0) { if((i=next_message(curr-1, FALSE)) != -1) { curr = i+1; nucurr = get_page(curr); } else error1(catgets(elm_msg_cat, ElmSet, ElmNoMoreItemBelow, "No more %s below."), nls_items); } else error(ifmain(no_mail, no_aliases)); break; next_undel_msg: case KEY_DOWN: case 'j' : if(curr > 0) { if((i=next_message(curr-1, TRUE)) != -1) { curr = i+1; nucurr = get_page(curr); } else error1(catgets(elm_msg_cat, ElmSet, ElmNoItemUndeletedBelow, "No more undeleted %s below."), nls_items); } else error(ifmain(no_mail, no_aliases)); break; case ctrl('P'): case 'K' : if(curr > 0) { if((i=prev_message(curr-1, FALSE)) != -1) { curr = i+1; nucurr = get_page(curr); } else error1(catgets(elm_msg_cat, ElmSet, ElmNoMoreItemAbove, "No more %s above."), nls_items); } else error(ifmain(no_mail, no_aliases)); break; case KEY_UP: case 'k' : if(curr > 0) { if((i=prev_message(curr-1, TRUE)) != -1) { curr = i+1; nucurr = get_page(curr); } else error1(catgets(elm_msg_cat, ElmSet, ElmNoMoreUndeletedAbove, "No more undeleted %s above."), nls_items); } else error(ifmain(no_mail, no_aliases)); break; case 'L' : { /* move to last line of page */ int last_on_page, last_of_all, last_line; if (selected) { last_on_page = visible_to_index( (header_page + 1) * headers_per_page) + 1; last_of_all = (visible_to_index(selected) + 1); } else { last_on_page = (header_page+1) * headers_per_page; last_of_all = count; } if (last_on_page < last_of_all) last_line = last_on_page; else last_line = last_of_all; /* don't bother to redraw if you don't move */ if (curr != last_line) { curr = last_line; nucurr = SAME_PAGE; } break; } case 'l' : PutLine1(LINES-3, strlen(nls_Prompt), catgets(elm_msg_cat, ElmSet, ElmLimitDisplayBy, "Limit displayed %s by..."), nls_items); clear_error(); if (limit() != 0) { curr = curr_folder.curr_mssg; nucurr = get_page(curr); redraw++; } else { nufoot++; } break; case ctrl('T') : case 'T' : case 't' : if (count < 1) { error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToTag, "No %s to tag!"), nls_items); } else if (ch == 't') tag_message(TRUE); else if (ch == 'T') { tag_message(TRUE); goto next_undel_msg; } else (void) meta_match(MATCH_TAG); break; case 'u' : if (count < 1) { error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToMarkUndeleted, "No %s to mark as undeleted!"), nls_items); } else { /* Overload u to have it mark unread a read * message which is not deleted. */ if ( (!inalias) && (isoff(curr_folder.headers[curr_folder.curr_mssg-1]->status, DELETED))) { setit(curr_folder.headers[curr_folder.curr_mssg-1]->status, UNREAD); curr_folder.headers[curr_folder.curr_mssg-1]->status_chgd = TRUE; } else undelete_msg(TRUE); if (resolve_mode) /* move after mail resolved */ if((i=next_message(curr-1, FALSE)) != -1) { curr = i+1; nucurr = get_page(curr); } /************************************************************************* ** What we've done here is to special case the "U)ndelete" command to ** ignore whether the next message is marked for deletion or not. The ** reason is obvious upon usage - it's a real pain to undelete a series ** of messages without this quirk. Thanks to Jim Davis @ HPLabs for ** suggesting this more intuitive behaviour. ** ** The old way, for those people that might want to see what the previous ** behaviour was to call next_message with TRUE, not FALSE. **************************************************************************/ } break; case ctrl('U') : if (count < 1) { error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToUndelete, "No %s to undelete!"), nls_items); } else (void) meta_match(MATCH_UNDELETE); break; case ctrl('L') : redraw++; break; default : if (ch > '0' && ch <= '9') { PutLine1(LINES-3, strlen(nls_Prompt), catgets(elm_msg_cat, ElmSet, ElmNewCurrentItem, "New Current %s"), nls_Item); UnreadCh(ch); i = enter_number(LINES-3, curr, nls_item); if( i > count) error1(catgets(elm_msg_cat, ElmSet, ElmNotThatMany, "Not that many %s."), nls_items); else if(selected && isoff(ifmain(curr_folder.headers[i-1]->status, aliases[i-1]->status), VISIBLE)) error1(catgets(elm_msg_cat, ElmSet, ElmNotInLimitedDisplay, "%s not in limited display."), nls_Item); else { curr = i; nucurr = get_page(curr); } } else { error(catgets(elm_msg_cat, ElmSet, ElmUnknownCommand, "Unknown command. Use '?' for help.")); FlushInput(); } } if (inalias) curr_alias = curr; else curr_folder.curr_mssg = curr; }