diff --git a/dat/opthelp b/dat/opthelp index f3debdc5d..c752a8d2e 100644 --- a/dat/opthelp +++ b/dat/opthelp @@ -205,6 +205,15 @@ scores the parts of the score list you wish [!own/3 top/2 around] to see when the game ends. You choose a combination of top scores, scores around the top scores, and all of your own scores. +sortdiscoveries preferred order when viewing list of discovered objects [o] + o -- in order of discovery within each class + s -- sortloot's "loot" order + c -- alphabetized within each class + a -- alphabetized across all classes +sortloot preferred order when examining a set of objects [n] + none -- no sorting + loot -- sort piles of objects on floor and in containers + full -- 'loot' plus objects in inventory statushilites whether to display status highlights (when non-zero) and [0] also how many turns to display temporary highlights (for 'up', 'down', and 'changed' hilite_status rules) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 4fab00cd7..dab9e06da 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -35,7 +35,7 @@ .ds vr "NetHack 3.7 .ds f0 "\*(vr .ds f1 -.ds f2 "December 16, 2020 +.ds f2 "December 19, 2020 . .\" A note on some special characters: .\" \(lq = left double quote @@ -1055,8 +1055,12 @@ be added to the end of the list rather than be inserted into the sorted ordering.) .lp \\\\ Show what types of objects have been discovered. +.lp "" +May be preceded by \(oq\f(CRm\fP\(cq to select preferred display order. .lp \` Show discovered types for one class of objects. +.lp "" +May be preceded by \(oq\f(CRm\fP\(cq to select preferred display order. .lp ! Escape to a shell. See \(lq#shell\(rq below for more details. @@ -1258,10 +1262,16 @@ Default key is \(oq\(haD\(cq, and \(oqk\(cq if is on. .lp "#known " Show what object types have been discovered. -Default key is \(oq\\\(cq. +Default key is \(oq\f(CR\\\fP\(cq. +.lp "" +The \(oq\f(CRm\fP\(cq prefix allows assigning a new value to the +.op sortdiscoveries +option to control the order in which the discoveries are displayed. .lp #knownclass Show discovered types for one class of objects. -Default key is \(oq\`\(cq. +Default key is \(oq\f(CR\`\fP\(cq. +.lp "" +The \(oq\f(CRm\fP\(cq prefix operates the same as for \(lq#known\(rq. .lp #levelchange Change your experience level. Autocompletes. @@ -4109,19 +4119,47 @@ Persistent. Show your approximate accumulated score on bottom line (default off). Persistent. .lp "silent " -Suppress terminal beeps (default on). Persistent. +Suppress terminal beeps (default on). +Persistent. +.lp sortdiscoveries +Controls the sorting behavior for the output of the \(oq\f(CR\\\fP\(cq +and \(oq\f(CR\`\fP\(cq commands. +Persistent. +.lp "" +The possible values are: +.PS o +.PL o +list object types by class, in discovery order within each class; +default; +.PL s +list object types by +.op sortloot +classification: by class, by sub-class within class for classes which +have substantial groupings (like helmets, boots, gloves, and so forth +for armor), with object types partly-discovered via assigned name coming +before fully identified types; +.PL c +list by class, alphabetically within each class; +.PL a +list alphabetically across all classes. +.PE +Can be interactively set via the \(oq\f(CRO\fP\(cq command or via using +the \(oq\f(CRm\fP\(cq prefix before the \(oq\f(CR\\\fP\(cq +or \(oq\f(CR\`\fP\(cq command. .lp sortloot Controls the sorting behavior of the pickup lists for inventory and #loot commands and some others. Persistent. +.lp "" The possible values are: -.PS full +.PS none \" note: with proportional font, "none" is wider than "full" or "loot" .PL full always sort the lists; .PL loot only sort the lists that don't use inventory letters, like with the #loot and pickup commands; .PL none -show lists the traditional way without sorting. +show lists the traditional way without sorting; +default. .PE .lp sortpack Sort the pack contents by type when displaying inventory (default on). diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index a3dd3fecc..b1606a34c 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -45,7 +45,7 @@ %.au \author{Original version - Eric S. Raymond\\ (Edited and expanded for 3.7 by Mike Stephenson and others)} -\date{December 16, 2020} +\date{December 19, 2020} \maketitle @@ -1154,9 +1154,15 @@ ordering.) %.lp \item[\tb{$\backslash$}] Show what types of objects have been discovered. +\\ +%.lp "" +May be preceded by `{\tt m}' to select preferred display order. %.lp \item[\tb{\`}] Show discovered types for one class of objects. +\\ +.lp "" +May be preceded by `{\tt m}' to select preferred display order. %.lp \item[\tb{!}] Escape to a shell. @@ -1340,10 +1346,18 @@ and also `{\tt k}' if {\it number\verb+_+pad\/} is on. \item[\tb{\#known}] Show what object types have been discovered. Default key is `{\tt $\backslash$}'. +\\ +%.lp "" +The `{\tt m}' prefix allows assigning a new value to the +{\it sortdiscoveries\/} +option to control the order in which the discoveries are displayed. %.lp \item[\tb{\#knownclass}] Show discovered types for one class of objects. Default key is `{\tt `}'. +\\ +%.lp "" +The `{\tt m}' prefix operates the same as for \(lq#known\(rq. %.lp \item[\tb{\#levelchange}] Change your experience level. @@ -4450,17 +4464,44 @@ Persistent. \item[\ib{silent}] Suppress terminal beeps (default on). Persistent. %.lp +\item[\ib{sortdiscoveries}] +Controls the sorting behavior for the output of the `{\tt $\backslash$}' +and `{\tt \`}' commands. +Persistent. +\\ +%.lp "" +The possible values are: +%.PS o +%.PL o +(\tt o} --- list object types by class, in discovery order within each class; +default; +%.PL s +{\tt s} --- list object types by {\it sortloot\/} +classification: by class, by sub-class within class for classes which +have substantial groupings (like helmets, boots, gloves, and so forth +for armor), with object types partly-discovered via assigned name coming +before fully identified types; +\\ +%.PL c +{\tt c} --- list by class, alphabetically within each class;\\ +%.PL a +{\tt a} --- list alphabetically across all classes.\\ +%.PE +Can be interactively set via the `{\tt O}' command or via using +the `{\tt m}' prefix before the `{\tt $\backslash$}' +or `{\tt \`}' command. +%.lp \item[\ib{sortloot}] Controls the sorting behavior of pickup lists for inventory and \#loot commands and some others. Persistent. - +\\ The possible values are: %.sd %.si {\tt full} --- always sort the lists;\\ {\tt loot} --- only sort the lists that don't use inventory letters, like with the \#loot and pickup commands;\\ -{\tt none} --- show lists the traditional way without sorting. +{\tt none} --- show lists the traditional way without sorting; default. %.ei %.ed %.lp diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 9b619329b..23868980b 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -681,6 +681,7 @@ when "?i" (show key bindings) displays commands and their keys, also show assign default key binding for or to execute #terrain assign M-X to #exploremode make #herecmdmenu and #therecmdmenu autocomplete +add 'sortdiscoveries' option to control output of '\' and '`' commands Platform- and/or Interface-Specific New Features diff --git a/include/extern.h b/include/extern.h index f771e0766..cc7fd8be9 100644 --- a/include/extern.h +++ b/include/extern.h @@ -972,6 +972,7 @@ E void NDECL(ustatusline); /* ### invent.c ### */ +E void FDECL(loot_classify, (Loot *, struct obj *)); E Loot *FDECL(sortloot, (struct obj **, unsigned, BOOLEAN_P, boolean (*)(OBJ_P))); E void FDECL(unsortloot, (Loot **)); @@ -1743,6 +1744,7 @@ E void FDECL(savenames, (NHFILE *)); E void FDECL(restnames, (NHFILE *)); E void FDECL(discover_object, (int, BOOLEAN_P, BOOLEAN_P)); E void FDECL(undiscover_object, (int)); +E int FDECL(choose_disco_sort, (int)); E int NDECL(dodiscovered); E int NDECL(doclassdisco); E void NDECL(rename_disco); diff --git a/include/flag.h b/include/flag.h index 5a0f0213e..4122dd046 100644 --- a/include/flag.h +++ b/include/flag.h @@ -80,6 +80,7 @@ struct flag { #define PARANOID_EATING 0x0200 int pickup_burden; /* maximum burden before prompt */ int pile_limit; /* controls feedback when walking over objects */ + char discosort; /* order of dodiscovery/doclassdisco output: o,s,c,a */ char sortloot; /* 'n'=none, 'l'=loot (pickup), 'f'=full ('l'+invent) */ char inv_order[MAXOCLASSES]; char pickup_types[MAXOCLASSES]; @@ -93,8 +94,7 @@ struct flag { char end_disclose[NUM_DISCLOSURE_OPTIONS + 1]; /* disclose various info upon exit */ char menu_style; /* User interface style setting */ - boolean made_fruit; /* don't easily let the user overflow the number of - fruits */ + boolean made_fruit; /* don't easily let user overflow fruit limit */ /* KMH, role patch -- Variables used during startup. * diff --git a/include/optlist.h b/include/optlist.h index 7ae20db6e..9bf4a057d 100644 --- a/include/optlist.h +++ b/include/optlist.h @@ -406,6 +406,8 @@ pfx_##a, &flags.silent) NHOPTB(softkeyboard, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias, &iflags.wc2_softkeyboard) + NHOPTC(sortdiscoveries, 0, opt_in, set_in_game, Yes, Yes, No, Yes, + NoAlias, "preferred order when displaying discovered objects") NHOPTC(sortloot, 4, opt_in, set_in_game, No, Yes, No, Yes, NoAlias, "sort object selection lists by description") NHOPTB(sortpack, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias, diff --git a/include/patchlevel.h b/include/patchlevel.h index 47f5d5235..d6969198b 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 28 +#define EDITLEVEL 29 /* * Development status possibilities. diff --git a/src/cmd.c b/src/cmd.c index 65c05546b..94f5a0068 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -3236,6 +3236,8 @@ int NDECL((*cmd_func)); /* 'm' for removing saddle from adjacent monster without checking for containers at */ || cmd_func == doloot + /* offer menu to choose discoveries sort order */ + || cmd_func == dodiscovered || cmd_func == doclassdisco /* travel: pop up a menu of interesting targets in view */ || cmd_func == dotravel /* wait and search: allow even if next to a hostile monster */ diff --git a/src/invent.c b/src/invent.c index f7be4f669..63f7904a9 100644 --- a/src/invent.c +++ b/src/invent.c @@ -13,7 +13,6 @@ #define CONTAINED_SYM '>' /* designator for inside a container */ #define HANDS_SYM '-' -static void FDECL(loot_classify, (Loot *, struct obj *)); static char *FDECL(loot_xname, (struct obj *)); static int FDECL(invletter_value, (CHAR_P)); static int FDECL(CFDECLSPEC sortloot_cmp, (const genericptr, @@ -54,7 +53,7 @@ static char FDECL(obj_to_let, (struct obj *)); static const char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */ /* sortloot() classification; called at most once [per sort] for each object */ -static void +void loot_classify(sort_item, obj) Loot *sort_item; struct obj *obj; diff --git a/src/o_init.c b/src/o_init.c index 0ef30c222..5806e9ee3 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -9,6 +9,8 @@ static void FDECL(setgemprobs, (d_level *)); static void FDECL(shuffle, (int, int, BOOLEAN_P)); static void NDECL(shuffle_all); static boolean FDECL(interesting_to_discover, (int)); +static int FDECL(CFDECLSPEC discovered_cmp, (const genericptr, + const genericptr)); static char *FDECL(oclass_to_name, (CHAR_P, char *)); #ifdef USE_TILES @@ -465,37 +467,167 @@ static const short uniq_objs[] = { BELL_OF_OPENING, }; +/* discoveries qsort comparison function */ +static int CFDECLSPEC +discovered_cmp(v1, v2) +const genericptr v1; +const genericptr v2; +{ + const char *s1 = *(const char **) v1; + const char *s2 = *(const char **) v2; + /* each element starts with "* " or " " but we don't sort by those */ + int res = strcmpi(s1 + 2, s2 + 2); + + if (res == 0) { + ; /* no tie-breaker needed */ + } + return res; +} + +static char * +sortloot_descr(otyp, outbuf) +int otyp; +char *outbuf; +{ + Loot sl_cookie; + struct obj o; + + o = cg.zeroobj; + o.otyp = otyp; + o.oclass = objects[otyp].oc_class; + o.dknown = 1; + o.known = (objects[otyp].oc_name_known || !objects[otyp].oc_uses_known) + ? 1 : 0; + o.corpsenm = NON_PM; /* suppress statue and figurine details */ + /* but suppressing fruit details leads to "bad fruit #0" */ + if (otyp == SLIME_MOLD) + o.spe = g.context.current_fruit; + + (void) memset((genericptr_t) &sl_cookie, 0, sizeof sl_cookie); + sl_cookie.obj = (struct obj *) 0; + sl_cookie.str = (char *) 0; + + loot_classify(&sl_cookie, &o); + Sprintf(outbuf, "%02d%02d%1d ", + sl_cookie.orderclass, sl_cookie.subclass, sl_cookie.disco); + return outbuf; +} + +#define DISCO_BYCLASS 0 /* by discovery order within each class */ +#define DISCO_SORTLOOT 1 /* by discovery order within each subclass */ +#define DISCO_ALPHABYCLASS 2 /* alphabetized within each class */ +#define DISCO_ALPHABETIZED 3 /* alphabetized across all classes */ +/* also used in options.c (optfn_sortdiscoveries) */ +const char disco_order_let[] = "osca"; +const char *const disco_orders_descr[] = { + "by order of discovery within each class", + "sortloot order (by class with some sub-class groupings)", + "alphabetical within each class", + "alphabetical across all classes", + (char *) 0 +}; + +int +choose_disco_sort(mode) +int mode; /* 0 => 'O' cmd, 1 => full discoveries; 2 => class discoveries */ +{ + winid tmpwin; + menu_item *selected; + anything any; + int i, n, choice; + + tmpwin = create_nhwindow(NHW_MENU); + start_menu(tmpwin, MENU_BEHAVE_STANDARD); + any = cg.zeroany; /* zero out all bits */ + for (i = 0; disco_orders_descr[i]; ++i) { + any.a_int = disco_order_let[i]; + add_menu(tmpwin, NO_GLYPH, &any, (char) any.a_int, 0, ATR_NONE, + disco_orders_descr[i], + (disco_order_let[i] == flags.discosort) + ? MENU_ITEMFLAGS_SELECTED + : MENU_ITEMFLAGS_NONE); + } + if (mode == 2) { + /* called via 'm `' where full alphabetize doesn't make sense + (only showing one class so can't span all classes) but the + chosen sort will stick and also apply to '\' usage */ + any = cg.zeroany; + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, + "", MENU_ITEMFLAGS_NONE); + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, + "Note: full alphabetical and alphabetical within class", + MENU_ITEMFLAGS_NONE); + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, + " are equivalent for single class discovery, but", + MENU_ITEMFLAGS_NONE); + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, + " will matter for future use of total discoveries.", + MENU_ITEMFLAGS_NONE); + } + end_menu(tmpwin, "Ordering of discoveries"); + + n = select_menu(tmpwin, PICK_ONE, &selected); + destroy_nhwindow(tmpwin); + if (n > 0) { + choice = selected[0].item.a_int; + /* skip preselected entry if we have more than one item chosen */ + if (n > 1 && choice == (int) flags.discosort) + choice = selected[1].item.a_int; + free((genericptr_t) selected); + flags.discosort = choice; + } + return n; +} + /* the '\' command - show discovered object types */ int dodiscovered() /* free after Robert Viduya */ { - register int i, dis; - int ct = 0; - char *s, oclass, prev_class, classes[MAXOCLASSES], buf[BUFSZ]; winid tmpwin; + char *s, *p, oclass, prev_class, + classes[MAXOCLASSES], buf[BUFSZ], + *sorted_lines[NUM_OBJECTS]; /* overkill */ + int i, j, sortindx, dis, ct, uniq_ct, arti_ct, sorted_ct; + boolean alphabetized, alphabyclass, lootsort; + + if (!flags.discosort || !(p = index(disco_order_let, flags.discosort))) + flags.discosort = 'o'; + + if (iflags.menu_requested) { + if (choose_disco_sort(1) < 0) + return 0; + } + alphabyclass = (flags.discosort == 'c'); + alphabetized = (flags.discosort == 'a' || alphabyclass); + lootsort = (flags.discosort == 's'); + sortindx = index(disco_order_let, flags.discosort) - disco_order_let; tmpwin = create_nhwindow(NHW_MENU); - putstr(tmpwin, 0, "Discoveries"); + Sprintf(buf, "Discoveries, %s", disco_orders_descr[sortindx]); + putstr(tmpwin, 0, buf); putstr(tmpwin, 0, ""); /* gather "unique objects" into a pseudo-class; note that they'll also be displayed individually within their regular class */ + uniq_ct = 0; for (i = dis = 0; i < SIZE(uniq_objs); i++) if (objects[uniq_objs[i]].oc_name_known) { if (!dis++) putstr(tmpwin, iflags.menu_headings, "Unique items"); + ++uniq_ct; Sprintf(buf, " %s", OBJ_NAME(objects[uniq_objs[i]])); putstr(tmpwin, 0, buf); - ++ct; } /* display any known artifacts as another pseudo-class */ - ct += disp_artifact_discoveries(tmpwin); + arti_ct = disp_artifact_discoveries(tmpwin); /* several classes are omitted from packorder; one is of interest here */ Strcpy(classes, flags.inv_order); if (!index(classes, VENOM_CLASS)) (void) strkitten(classes, VENOM_CLASS); /* append char to string */ + ct = uniq_ct + arti_ct; + sorted_ct = 0; for (s = classes; *s; s++) { oclass = *s; prev_class = oclass + 1; /* forced different from oclass */ @@ -504,21 +636,63 @@ dodiscovered() /* free after Robert Viduya */ if ((dis = g.disco[i]) != 0 && interesting_to_discover(dis)) { ct++; if (oclass != prev_class) { - putstr(tmpwin, iflags.menu_headings, - let_to_name(oclass, FALSE, FALSE)); - prev_class = oclass; + if ((alphabyclass || lootsort) && sorted_ct) { + /* output previous class */ + qsort(sorted_lines, sorted_ct, sizeof (char *), + discovered_cmp); + for (j = 0; j < sorted_ct; ++j) { + p = sorted_lines[j]; + if (lootsort) { + p[6] = p[0]; /* '*' or ' ' */ + p += 6; + } + putstr(tmpwin, 0, p); + free(sorted_lines[j]), sorted_lines[j] = 0; + } + sorted_ct = 0; + } + if (!alphabetized || alphabyclass) { + /* header for new class */ + putstr(tmpwin, iflags.menu_headings, + let_to_name(oclass, FALSE, FALSE)); + prev_class = oclass; + } } - Sprintf(buf, "%s %s", - (objects[dis].oc_pre_discovered ? "*" : " "), - obj_typename(dis)); - putstr(tmpwin, 0, buf); + Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " "); + if (lootsort) + (void) sortloot_descr(dis, &buf[2]); + Strcat(buf, obj_typename(dis)); + + if (!alphabetized && !lootsort) + putstr(tmpwin, 0, buf); + else + sorted_lines[sorted_ct++] = dupstr(buf); } } } if (ct == 0) { You("haven't discovered anything yet..."); - } else + } else { + if (sorted_ct) { + /* if we're alphabetizing by class, we've already shown the + relevant header above; if we're alphabetizing across all + classes, we normally don't need a header; but it we showed + any unique items or any artifacts then we do need one */ + if ((uniq_ct || arti_ct) && !alphabyclass) + putstr(tmpwin, iflags.menu_headings, "Discovered items"); + qsort(sorted_lines, sorted_ct, sizeof (char *), discovered_cmp); + for (j = 0; j < sorted_ct; ++j) { + p = sorted_lines[j]; + if (lootsort) { + p[6] = p[0]; /* '*' or ' ' */ + p += 6; + } + putstr(tmpwin, 0, p); + free(sorted_lines[j]), sorted_lines[j] = 0; + } + } display_nhwindow(tmpwin, TRUE); + } destroy_nhwindow(tmpwin); return 0; @@ -547,13 +721,24 @@ doclassdisco() havent_discovered_any[] = "haven't discovered any %s yet.", unique_items[] = "unique items", artifact_items[] = "artifacts"; - char *s, c, oclass, menulet, allclasses[MAXOCLASSES], - discosyms[2 + MAXOCLASSES + 1], buf[BUFSZ]; - int i, ct, dis, xtras; - boolean traditional; winid tmpwin = WIN_ERR; - anything any; menu_item *pick_list = 0; + anything any; + char *p, *s, c, oclass, menulet, allclasses[MAXOCLASSES], + discosyms[2 + MAXOCLASSES + 1], buf[BUFSZ], + *sorted_lines[NUM_OBJECTS]; /* overkill */ + int i, ct, dis, xtras, sorted_ct; + boolean traditional, alphabetized, lootsort; + + if (!flags.discosort || !(p = index(disco_order_let, flags.discosort))) + flags.discosort = 'o'; + + if (iflags.menu_requested) { + if (choose_disco_sort(2) < 0) + return 0; + } + alphabetized = (flags.discosort == 'a' || flags.discosort == 'c'); + lootsort = (flags.discosort == 's'); discosyms[0] = '\0'; traditional = (flags.menu_style == MENU_TRADITIONAL @@ -670,9 +855,9 @@ doclassdisco() upstart(strcpy(buf, unique_items))); for (i = 0; i < SIZE(uniq_objs); i++) if (objects[uniq_objs[i]].oc_name_known) { + ++ct; Sprintf(buf, " %s", OBJ_NAME(objects[uniq_objs[i]])); putstr(tmpwin, 0, buf); - ++ct; } if (!ct) You(havent_discovered_any, unique_items); @@ -685,20 +870,40 @@ doclassdisco() break; default: oclass = def_char_to_objclass(c); - Sprintf(buf, "Discovered %s", let_to_name(oclass, FALSE, FALSE)); - putstr(tmpwin, iflags.menu_headings, buf); - for (i = g.bases[(int) oclass]; - i < NUM_OBJECTS && objects[i].oc_class == oclass; ++i) { + Sprintf(buf, "Discovered %s in %s", let_to_name(oclass, FALSE, FALSE), + (flags.discosort == 'o') ? "order of discovery" + : (flags.discosort == 's') ? "'sortloot' order" + : "alphabetical order"); + putstr(tmpwin, 0, buf); /* skip iflags.menu_headings */ + sorted_ct = 0; + for (i = g.bases[(int) oclass]; i < g.bases[oclass + 1] - 1; ++i) { if ((dis = g.disco[i]) != 0 && interesting_to_discover(dis)) { - Sprintf(buf, "%s %s", - objects[dis].oc_pre_discovered ? "*" : " ", - obj_typename(dis)); - putstr(tmpwin, 0, buf); ++ct; + Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " "); + if (lootsort) + (void) sortloot_descr(dis, &buf[2]); + Strcat(buf, obj_typename(dis)); + + if (!alphabetized && !lootsort) + putstr(tmpwin, 0, buf); + else + sorted_lines[sorted_ct++] = dupstr(buf); } } - if (!ct) + if (!ct) { You(havent_discovered_any, oclass_to_name(oclass, buf)); + } else if (sorted_ct) { + qsort(sorted_lines, sorted_ct, sizeof (char *), discovered_cmp); + for (i = 0; i < sorted_ct; ++i) { + p = sorted_lines[i]; + if (lootsort) { + p[6] = p[0]; /* '*' or ' ' */ + p += 6; + } + putstr(tmpwin, 0, p); + free(sorted_lines[i]), sorted_lines[i] = 0; + } + } break; } if (ct) diff --git a/src/options.c b/src/options.c index 90d2c5b97..c1ce9eefb 100644 --- a/src/options.c +++ b/src/options.c @@ -3256,6 +3256,66 @@ char *op; return optn_ok; } +int +optfn_sortdiscoveries(optidx, req, negated, opts, op) +int optidx; +int req; +boolean negated; +char *opts; +char *op; +{ + if (req == do_init) { + flags.discosort = 'o'; + return optn_ok; + } + if (req == do_set) { + op = string_for_env_opt(allopt[optidx].name, opts, FALSE); + if (negated) { + flags.discosort = 'o'; + } else if (op != empty_optstr) { + switch (lowc(*op)) { + case '0': + case 'o': /* order of discovery */ + flags.discosort = 'o'; + break; + case '1': + case 's': /* sortloot order (subclasses for some classes) */ + flags.discosort = 's'; + break; + case '2': + case 'c': /* alphabetical within each class */ + flags.discosort = 'c'; + break; + case '3': + case 'a': /* alphabetical across all classes */ + flags.discosort = 'a'; + break; + default: + config_error_add("Unknown %s parameter '%s'", + allopt[optidx].name, op); + return optn_silenterr; + } + } else + return optn_err; + return optn_ok; + } + if (req == get_val) { + extern const char *const disco_orders_descr[]; /* o_init.c */ + extern const char disco_order_let[]; + const char *p = index(disco_order_let, flags.discosort); + + if (!p) + flags.discosort = 'o', p = disco_order_let; + Strcpy(opts, disco_orders_descr[p - disco_order_let]); + return optn_ok; + } + if (req == do_handler) { + /* return handler_sortdiscoveries(); */ + (void) choose_disco_sort(0); /* o_init.c */ + } + return optn_ok; +} + int optfn_sortloot(optidx, req, negated, opts, op) int optidx;