This is options.c in view mode; [Download] [Up]
static char rcsid[] = "@(#)$Id: options.c,v 5.3 1992/11/07 19:37:21 syd Exp $"; /******************************************************************************* * The Elm Mail System - $Revision: 5.3 $ $State: Exp $ * * Copyright (c) 1986,1987 Dave Taylor * Copyright (c) 1988-1992 USENET Community Trust ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * Syd Weinstein, Elm Coordinator * elm@DSI.COM dsinc!elm * ******************************************************************************* * $Log: options.c,v $ * Revision 5.3 1992/11/07 19:37:21 syd * Enhanced printing support. Added "-I" to readmsg to * suppress spurious diagnostic messages. * From: chip@chinacat.unicom.com (Chip Rosenthal) * * Revision 5.2 1992/10/24 13:35:39 syd * changes found by using codecenter on Elm 2.4.3 * From: Graham Hudspith <gwh@inmos.co.uk> * * Revision 5.1 1992/10/03 22:58:40 syd * Initial checkin as of 2.4 Release at PL0 * * ******************************************************************************/ /** This set of routines allows the alteration of a number of paramaters in the Elm mailer, including the following; a) arrow-cursor <on or off> b) border for copy <string for left margin> c) calendar-file <where to put calendar entries> d) display pager <how to page messages> e) editor <name of primary editor or "builtin"> f) folder-dir <folder directory> h) hold sent msgs <on or off> * i) (internal: quit to index screen) j) reply editor <name of editor for replies> k) pause pager <on or off> l) alias sort <how to sort the alias display> m) menu-display <on or off> n) names-only <on or off> o) sent-mail <file to save outbound message copies to> p) printmail <how to print messages> * q) (internal: quit to previous screen) r) reply copy <on or off> s) sort-by <how to sort folders> t) text editor <name of ~e editor> u) user-level <BEGINNER|INTERMEDIATE|EXPERT> v) visual editor <name of ~v editor> w) want CC prompt <on or off> * x) (internal: exit ELM now) y) full_username <your full user name for outgoing mail> z) zap sign dashes <on or off> And others as they seem useful. Formatting parameters: _) Add a blank line ^) Put the title on this line A subset of the above parameters may be selected as the o)ptions screen using the parameter "configoptions" which is a string of letters representing the "key" letter for each item as listed above. The current default is "^_cdefsopyv_am_un". The order of the options displayed is as listed in the string. **/ #include "headers.h" #include "save_opts.h" #include "s_elm.h" #ifdef BSD #undef tolower #endif #undef onoff #define onoff(n) (n == 1? on_name : off_name) extern char *alias_sort_name(), *sort_name(); char *index(); char *level_name(); static char *on_name = NULL; static char *off_name = NULL; unsigned long sleep(); static int resort = 0; static char temp[SLEN]; /* needed when an option is run through * expand_env(), because that function * is destructive of the original */ static post_cal(f) int f; {strcpy(temp,raw_calendar_file); expand_env(calendar_file,temp);} static post_pager(f) int f; { strcpy(temp, raw_pager); expand_env(pager, temp); clear_pages=(equal(pager,"builtin+")||equal(pager,"internal+")); } static post_folder(f) int f; {strcpy(temp,raw_folders); expand_env(folders,temp);} static post_sort(f) int f; {if (f) resort++;} static post_sent(f) int f; {strcpy(temp,raw_sentmail); expand_env(sent_mail,temp);} static post_print(f) int f; {strcpy(temp,raw_printout); expand_env(printout,temp);} static post_menu(f) int f; {headers_per_page=LINES-(mini_menu?13:8);} opts_menu cfg_opts[] = { {'a', "A)rrow cursor", ElmOptionArrowMenu, "arrow", NULL, "This defines whether the ELM cursor is an arrow or a highlight bar.", ElmOptionArrowHelp}, {'b', "B)order on copy", ElmOptionBorderMenu, "prefix", NULL, "Left margin string (prefix) for reply and forward", ElmOptionBorderMenu}, #ifdef ENABLE_CALENDAR {'c', "C)alendar file", ElmOptionCalendarMenu, "calendar", post_cal, "This is the file where calendar entries from messages are saved.", ElmOptionCalendarHelp}, #endif {'d', "D)isplay mail using", ElmOptionDisplayMenu, "pager", post_pager, "This is the program invoked to display individual messages (try 'builtin')", ElmOptionDisplayHelp}, {'e', "E)ditor (primary)", ElmOptionEditorMenu, "editor", NULL, "This is the editor used for all outbound messages (may be 'builtin').", ElmOptionEditorHelp}, {'f', "F)older directory", ElmOptionFolderMenu, "maildir", post_folder, "This is the folders directory used when '=' (etc) is used in filenames", ElmOptionFolderHelp}, {'h', "H)old sent message", ElmOptionHoldMenu, "copy", NULL, "Whether to save a copy of outbound messages in O)utbound folder", ElmOptionHoldHelp}, {'j', "J) reply editor", ElmOptionJreplyMenu, "alteditor", NULL, "This is the editor that will be used for replies (Editor=\"builtin\").", ElmOptionJreplyHelp}, {'k', "K) pause after pager", ElmOptionKpauseMenu, "promptafter", NULL, "Whether to pause (prompt) at end of message with display message pager.", ElmOptionKpauseHelp}, {'l', "A(l)ias Sorting", ElmOptionaLiasHelp, "aliassortby", post_sort, "This is used to specify the sorting criteria for the alias display.", ElmOptionaLiasHelp}, {'m', "M)enu display", ElmOptionMenuMenu, "menu", post_menu, "This determines if you have the mini-menu displayed or not.", ElmOptionMenuHelp}, {'n', "N)ames only", ElmOptionNameMenu, "names", NULL, "Whether to display the names and addresses on mail, or names only.", ElmOptionNameHelp}, {'o', "O)utbound mail saved", ElmOptionOutboundMenu, "sentmail", post_sent, "This is where copies of outbound messages are saved automatically.", ElmOptionOutboundHelp}, {'p', "P)rint mail using", ElmOptionPrintMenu, "print", post_print, "This is the command used to print mail messages.", ElmOptionPrintHelp}, {'r', "R)eply copies msg", ElmOptionReplyMenu, "autocopy", NULL, "Whether to copy the message being replied to into the reply.", ElmOptionReplyHelp}, {'s', "S)orting criteria", ElmOptionSortMenu, "sortby", post_sort, "This is used to specify the sorting criteria for the folders.", ElmOptionSortHelp}, {'t', "T)ext editor (~e)", ElmOptionTextMenu, "easyeditor", NULL, "This is the editor that will be used by the ~e command (Editor=\"builtin\").", ElmOptionTextHelp}, {'u', "U)ser level", ElmOptionUserMenu, "userlevel", NULL, "The level of knowledge you have about the ELM mail system.", ElmOptionUserHelp}, {'v', "V)isual Editor (~v)", ElmOptionVisualMenu, "visualeditor", NULL, "This is the editor that will be used by the ~v command (Editor=\"builtin\").", ElmOptionVisualHelp}, {'w', "W)ant Cc: prompt", ElmOptionWantMenu, "askcc", NULL, "Whether to ask for \"Copies to:\" list when sending messages.", ElmOptionWantHelp}, {'y', "Y)our full name", ElmOptionYourMenu, "fullname", NULL, "When mail is sent out, this is what your full name will be recorded as.", ElmOptionYourHelp}, {'z', "Z) signature dashes", ElmOptionZdashMenu, "sigdashes", NULL, "Whether to print dashes before including signature on outbound messages.", ElmOptionZdashHelp}, { 0 } }; void init_opts_menu() { register char *c; register opts_menu *o; for (o = cfg_opts; o->parm; o++) { c = catgets(elm_msg_cat, ElmSet, o->menu_msg, "~"); if (*c != '~') o->menu = c; c = catgets(elm_msg_cat, ElmSet, o->one_liner_msg, "~"); if (*c != '~') o->one_liner = c; } } opts_menu * find_cfg_opts(c) int c; { register opts_menu *o; for (o = cfg_opts; o->parm; o++) { if (c == o->letter) break; } return(o->parm ? o : NULL); } char * one_liner_for(c) char c; { opts_menu *o; o = find_cfg_opts(c); if (o) return(o->one_liner); else return(NULL); } void display_options() { /** Display all the available options.. **/ int printed_title = FALSE; register int y; register opts_menu *o; register char *s; char buf[SLEN]; extern char *str_opt_nam(); ClearScreen(); for (s = config_options, y = 0; *s; s++, y++) { if (*s == '^') { printed_title = TRUE; Centerline(y, catgets(elm_msg_cat, ElmSet, ElmOptionsEditor, "-- ELM Options Editor --")); continue; } if (*s == '_') { continue; } o = find_cfg_opts(*s); if (o != NULL && y<LINES-5) { sprintf(buf,"%-20.20s : %%s", o->menu); PutLine1(y, 0, buf, str_opt_nam(o->parm, FULL)); } } if (!printed_title) { Centerline(LINES-5, catgets(elm_msg_cat, ElmSet, ElmOptionsEditor, "-- ELM Options Editor --")); } } void options_help() { /** help menu for the options screen... **/ char c, *ptr, *prompt; Centerline(LINES-3, catgets(elm_msg_cat, ElmSet, ElmPressKeyHelp, "Press the key you want help for, '?' for a key list, or '.' to exit help")); lower_prompt(prompt = catgets(elm_msg_cat, ElmSet, ElmKeyPrompt, "Key : ")); while ((c = ReadCh()) != '.') { c = tolower(c); if (c == '?') { display_helpfile(OPTIONS_HELP); display_options(); return; } if ((ptr = one_liner_for(c)) != NULL) error2("%c = %s.", c, ptr); else error1(catgets(elm_msg_cat, ElmSet, ElmKeyIsntUsed, "%c isn't used in this section."), c); lower_prompt(prompt); } ClearLine(LINES-3); /* clear Press help key message */ ClearLine(LINES-1); /* clear lower prompt message */ } char * level_name(n) int n; { /** return the 'name' of the level... **/ switch (n) { case 0 : return(catgets(elm_msg_cat, ElmSet, ElmBeginningUser, "Beginning User ")); case 1 : return(catgets(elm_msg_cat, ElmSet, ElmIntermediateUser, "Intermediate User")); default: return(catgets(elm_msg_cat, ElmSet, ElmExpertUser, "Expert User ")); } } int options() { /** change options... **/ /* return: * > 0 if resort was done - to indicate we might need to * change the page of our headers as a consequence * of the new sort order * < 0 if user entered 'X' to quit elm immediately * 0 otherwise */ int ch, y; opts_menu *o; char *strcpy(), *prompt; if (on_name == NULL) { on_name = catgets(elm_msg_cat, ElmSet, ElmOn, "ON "); off_name = catgets(elm_msg_cat, ElmSet, ElmOff, "OFF"); } if (!config_options[0]) { #ifdef ENABLE_CALENDAR strcpy(config_options,"^_cdefsopyv_am_un"); #else strcpy(config_options,"^_defsopyv_am_un"); #endif } resort = 0; prompt = catgets(elm_msg_cat, ElmSet, ElmPrompt, "Command: "); display_options(); clearerr(stdin); while(1) { ClearLine(LINES-4); Centerline(LINES-4, catgets(elm_msg_cat, ElmSet, ElmSelectOptionLetter, "Select letter of option line, '>' to save, or 'i' to return to index.")); PutLine0(LINES-2, 0, prompt); ch = ReadCh(); ch = tolower(ch); clear_error(); /* remove possible "sorting" message etc... */ if (index(config_options, ch)) { y = index(config_options,ch) - config_options; o = find_cfg_opts(ch); if (o != NULL && y < LINES-5) { one_liner(o->one_liner); y = info_enter(o->parm, y, 23, FALSE, FALSE); if (o->post) (o->post)(y); } else error(catgets(elm_msg_cat, ElmSet, ElmCommandUnknown, "Command unknown!")); } else { one_liner(NULL); switch (ch) { case '?' : options_help(); PutLine0(LINES-2,0, prompt); break; case '>' : printf(catgets(elm_msg_cat, ElmSet, ElmSaveOptions, "Save options in .elm/elmrc...")); fflush(stdout); save_options(); break; case 'x' : return(-1); /* exit elm */ case 'q' : /* pop back up to previous level, in this case == 'i' */ case 'i' : /* return to index screen */ return(resort ? 1 : 0); case ctrl('L'): display_options(); break; default: error(catgets(elm_msg_cat, ElmSet, ElmCommandUnknown, "Command unknown!")); } } } } on_or_off(var, x, y) int *var, x,y; { /** 'var' field at x.y toggles between on and off... **/ char ch; PutLine0(x, y+6, catgets(elm_msg_cat, ElmSet, ElmUseSpaceToToggle, "(use <space> to toggle, any other key to leave)")); MoveCursor(x,y+3); /* at end of value... */ do { ch = ReadCh(); if (ch == SPACE) { *var = ! *var; PutLine0(x,y, onoff(*var)); } } while (ch == SPACE); MoveCursor(x,y+4); CleartoEOLN(); /* remove help prompt */ } switch_user_level(ulevel, x, y) int *ulevel, x, y; { /** step through possible user levels... **/ PutLine0(x, y+20, catgets(elm_msg_cat, ElmSet, ElmSpaceToChange, "<space> to change")); MoveCursor(x,y); /* at end of value... */ while (ReadCh() == ' ') { *ulevel = (*ulevel >= 2? 0 : *ulevel + 1); PutLine1(x,y, "%s", level_name(*ulevel)); } MoveCursor(x,y+20); CleartoEOLN(); /* remove help prompt */ } change_sort(var, x, y) int *var; int x,y; { /** change the sorting scheme... **/ /** return !0 if new sort order, else 0 **/ int last_sortby, /* so we know if it changes... */ sign = 1; /* are we reverse sorting?? */ int ch; /* character typed in ... */ /* *var = sortby; or... *var == sortby; */ last_sortby = sortby; /* remember current ordering */ PutLine0(x, COLUMNS-29, catgets(elm_msg_cat, ElmSet, ElmSpaceForNext, "(SPACE for next, or R)everse)")); sort_one_liner(sortby); MoveCursor(x, y); do { ch = ReadCh(); ch = tolower(ch); switch (ch) { case SPACE : if (sortby < 0) { sign = -1; sortby = - sortby; } else sign = 1; /* insurance! */ sortby = sign * ((sortby + 1) % (STATUS+2)); if (sortby == 0) sortby = sign; /* snicker */ PutLine0(x, y, sort_name(PAD)); sort_one_liner(sortby); MoveCursor(x, y); break; case 'r' : sortby = - sortby; PutLine0(x, y, sort_name(PAD)); sort_one_liner(sortby); MoveCursor(x, y); } } while (ch == SPACE || ch == 'r'); MoveCursor(x, COLUMNS-30); CleartoEOLN(); if (sortby != last_sortby) { error(catgets(elm_msg_cat, ElmSet, ElmResortingFolder, "Resorting folder...")); sleep(1); sort_mailbox(message_count, 0); } ClearLine(LINES-2); /* clear sort_one_liner()! */ *var=sortby; sortby=last_sortby; return(*var-sortby); } one_liner(string) char *string; { /** A single-line description of the selected item... **/ ClearLine(LINES-4); if (string) Centerline(LINES-4, string); } sort_one_liner(sorting_by) int sorting_by; { /** A one line summary of the particular sorting scheme... **/ ClearLine(LINES-2); switch (sorting_by) { case REVERSE SENT_DATE: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortRSentDate, "This sort will order most-recently-sent to least-recently-sent")); break; case REVERSE RECEIVED_DATE: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortRRecvDate, "This sort will order most-recently-received to least-recently-received")); break; case REVERSE MAILBOX_ORDER: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortRMailbox, "This sort will order most-recently-added-to-folder to least-recently")); break; case REVERSE SENDER: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortRSender, "This sort will order by sender name, in reverse alphabetical order")); break; case REVERSE SIZE: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortRSize, "This sort will order messages by longest to shortest")); break; case REVERSE SUBJECT: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortRSubject, "This sort will order by subject, in reverse alphabetical order")); break; case REVERSE STATUS: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortRStatus, "This sort will order by reverse status - Deleted through Tagged...")); break; case SENT_DATE: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortSentDate, "This sort will order least-recently-sent to most-recently-sent")); break; case RECEIVED_DATE: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortRecvDate, "This sort will order least-recently-received to most-recently-received")); break; case MAILBOX_ORDER: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortMailbox, "This sort will order least-recently-added-to-folder to most-recently")); break; case SENDER: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortSender, "This sort will order by sender name")); break; case SIZE: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortSize, "This sort will order messages by shortest to longest")); break; case SUBJECT: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortSubject, "This sort will order messages by subject")); break; case STATUS: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmSortStatus, "This sort will order by status - Tagged through Deleted...")); break; } } change_alias_sort(var, x, y) int *var; int x,y; { /** change the sorting scheme... **/ /** return !0 if new sort order, else 0 **/ int last_sortby, /* so we know if it changes... */ sign = 1; /* are we reverse sorting?? */ int ch; /* character typed in ... */ /* *var = alias_sortby; or... *var == alias_sortby; */ last_sortby = alias_sortby; /* remember current ordering */ PutLine0(x, COLUMNS-29, catgets(elm_msg_cat, ElmSet, ElmSpaceForNext, "(SPACE for next, or R)everse)")); alias_sort_one_liner(alias_sortby); MoveCursor(x, y); do { ch = ReadCh(); ch = tolower(ch); switch (ch) { case SPACE : if (alias_sortby < 0) { sign = -1; alias_sortby = - alias_sortby; } else sign = 1; /* insurance! */ alias_sortby = sign * ((alias_sortby + 1) % (LAST_ALIAS_SORT+1)); if (alias_sortby == 0) alias_sortby = sign; PutLine0(x, y, alias_sort_name(PAD)); alias_sort_one_liner(alias_sortby); MoveCursor(x, y); break; case 'r' : alias_sortby = - alias_sortby; PutLine0(x, y, alias_sort_name(PAD)); alias_sort_one_liner(alias_sortby); MoveCursor(x, y); } } while (ch == SPACE || ch == 'r'); MoveCursor(x, COLUMNS-30); CleartoEOLN(); if (alias_sortby != last_sortby) { error(catgets(elm_msg_cat, ElmSet, ElmResortingAliases, "Resorting aliases...")); sleep(1); main_state(); sort_aliases(message_count, FALSE); main_state(); } ClearLine(LINES-2); /* clear alias_sort_one_liner()! */ *var=alias_sortby; alias_sortby=last_sortby; return(*var-alias_sortby); } alias_sort_one_liner(sorting_by) int sorting_by; { /** A one line summary of the particular sorting scheme... **/ ClearLine(LINES-2); switch (sorting_by) { case REVERSE ALIAS_SORT: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmASortRAlias, "This sort will order by alias name, in reverse alphabetical order")); break; case REVERSE NAME_SORT: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmASortRName, "This sort will order by user (real) name, in reverse alphabetical order")); break; case REVERSE TEXT_SORT: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmASortRText, "This sort will order aliases in the reverse order as listed in aliases.text")); break; case ALIAS_SORT: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmASortAlias, "This sort will order by alias name")); break; case NAME_SORT: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmASortName, "This sort will order by user (real) name")); break; case TEXT_SORT: Centerline(LINES-2, catgets(elm_msg_cat, ElmSet, ElmASortText, "This sort will order aliases in the order as listed in aliases.text")); break; } } /* * This routine is a "shell" to optionally_enter(), etc. so that * we can use save_info structure and tag the param as being changed * locally (so we know to save it to the .elm/elmrc file). */ info_enter(name, ypos, xpos, append_current, passwd) char *name; int ypos, xpos, append_current, passwd; { register int x,q; char buffer[SLEN]; int number; for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) { q = strcmp(name, save_info[x].name); if (q <= 0) break; } if (q) return(1); switch(save_info[x].flags & DT_MASK) { case DT_STR: strcpy(buffer, SAVE_INFO_STR(x)); if (save_info[x].flags & FL_NOSPC) { register char *s; for (s = buffer; *s; ++s) if (*s==' ') *s='_'; } optionally_enter(buffer, ypos, xpos, append_current, passwd); if (save_info[x].flags & FL_NOSPC) { register char *s; for (s=buffer; *s; ++s) if (*s=='_') *s=' '; } if (equal(buffer, SAVE_INFO_STR(x))) break; strcpy(SAVE_INFO_STR(x), buffer); q++; break; case DT_SRT: number = *SAVE_INFO_SRT(x); if (change_sort(&number, ypos, xpos) != 0) { *SAVE_INFO_SRT(x) = number; ++q; } break; case DT_ASR: number = *SAVE_INFO_ASR(x); if (change_alias_sort(&number, ypos, xpos) != 0) { *SAVE_INFO_ASR(x) = number; ++q; } break; case DT_NUM: number = *SAVE_INFO_NUM(x); if (equal(name, "userlevel")) { switch_user_level(&number, ypos, xpos); } if (number == *SAVE_INFO_NUM(x)) break; *SAVE_INFO_NUM(x) = number; ++q; break; case DT_BOL: number = *SAVE_INFO_BOL(x); on_or_off(&number, ypos, xpos); if (number == *SAVE_INFO_BOL(x)) break; *SAVE_INFO_BOL(x) = number; ++q; break; default: break; } if (q) save_info[x].flags |= FL_LOCAL; return(q != 0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.