Changeset 16

Show
Ignore:
Timestamp:
03/27/07 13:06:31 (1 year ago)
Author:
pmac
Message:

Initial add of menu feature.
- Cleaned up z-file.h inclusion.
- Added new menu interface (ui.h, ui.c)
- Added "knowledge menu" to cmd4.c

  • Added support for knowledge (tables.c, wizard1.c)

- Removed massive redundancy from cmd4.c
- Replaced (most) menus in cmd4.c with new interface.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/Makefile.inc

    r15 r16  
    3939  store \ 
    4040  tables \ 
     41  ui \ 
    4142  use-obj \ 
    4243  util \ 
  • trunk/src/Makefile.osx

    r12 r16  
    3535 
    3636CFLAGS = \ 
    37         -Wall -std=gnu99 $(OPT) -DMACH_O_CARBON
     37        -Wall -std=gnu99 $(OPT) -DMACH_O_CARBON -DHAVE_MKSTEMP
    3838        -DPRIVATE_USER_PATH=\"~/Library/Preferences\" -DUSE_PRIVATE_PATHS 
    3939LIBS = -framework CoreFoundation -framework QuickTime -framework Carbon 
  • trunk/src/Makefile.std

    r14 r16  
    174174        @-cp ../lib/xtra/sound/*.wav $(TMPDIR)/lib/xtra/sound 
    175175        @-cp ../lib/xtra/graf/*.bmp $(TMPDIR)/lib/xtra/graf 
     176        @cp ../changes.txt ../readme.txt $(TMPDIR) 
    176177        @cp $(EXE) $(TMPDIR) 
    177178        tar czf ../$(EXE)-$(VERSION).tar.gz $(TMPDIR) 
  • trunk/src/angband.h

    r1 r16  
    2020 * Include the mid-level includes. 
    2121 */ 
     22#include "z-file.h" 
     23#include "z-form.h" 
    2224#include "z-util.h" 
    2325#include "z-virt.h" 
    24 #include "z-form.h" 
    2526#include "z-rand.h" 
    2627#include "z-term.h" 
     
    3233#include "defines.h" 
    3334#include "types.h" 
     35#include "ui.h" 
    3436#include "externs.h" 
    3537 
  • trunk/src/cave.c

    r1 r16  
    10111011                /* Get the "player" char */ 
    10121012                c = r_ptr->x_char; 
    1013         } 
    1014  
    1015         /* Result */ 
    1016         (*ap) = a; 
    1017         (*cp) = c; 
    1018 } 
    1019  
    1020 /* 
    1021  * HACK - duplicated code 
    1022  * 
    1023  * Same as map_info, but always return the char/attr specified by the 
    1024  * info files. 
    1025  */ 
    1026 void map_info_default(int y, int x, byte *ap, char *cp) 
    1027 { 
    1028         byte a; 
    1029         char c; 
    1030  
    1031         byte feat; 
    1032         byte info; 
    1033  
    1034         feature_type *f_ptr; 
    1035  
    1036         s16b this_o_idx, next_o_idx = 0; 
    1037  
    1038         s16b m_idx; 
    1039  
    1040         s16b image = p_ptr->image; 
    1041  
    1042         int floor_num = 0; 
    1043  
    1044         /* Monster/Player */ 
    1045         m_idx = cave_m_idx[y][x]; 
    1046  
    1047         /* Feature */ 
    1048         feat = cave_feat[y][x]; 
    1049  
    1050         /* Cave flags */ 
    1051         info = cave_info[y][x]; 
    1052  
    1053         /* Hack -- rare random hallucination on non-outer walls */ 
    1054         if (image && (!rand_int(256)) && (feat < FEAT_PERM_SOLID)) 
    1055         { 
    1056                 int i = image_random(); 
    1057  
    1058                 a = PICT_A(i); 
    1059                 c = PICT_C(i); 
    1060         } 
    1061  
    1062         /* Boring grids (floors, etc) */ 
    1063         else if (feat <= FEAT_INVIS) 
    1064         { 
    1065                 /* Memorized (or seen) floor */ 
    1066                 if ((info & (CAVE_MARK)) || 
    1067                     (info & (CAVE_SEEN))) 
    1068                 { 
    1069                         /* Get the floor feature */ 
    1070                         f_ptr = &f_info[FEAT_FLOOR]; 
    1071  
    1072                         /* Normal attr */ 
    1073                         a = f_ptr->d_attr; 
    1074  
    1075                         /* Normal char */ 
    1076                         c = f_ptr->d_char; 
    1077  
    1078                         /* Special lighting effects */ 
    1079                         if (view_special_lite && (a == TERM_WHITE)) 
    1080                         { 
    1081                                 /* Handle "seen" grids */ 
    1082                                 if (info & (CAVE_SEEN)) 
    1083                                 { 
    1084                                         /* Only lit by "torch" lite */ 
    1085                                         if (view_yellow_lite && !(info & (CAVE_GLOW))) 
    1086                                         { 
    1087                                                 /* Use "yellow" */ 
    1088                                                 a = TERM_YELLOW; 
    1089                                         } 
    1090                                 } 
    1091  
    1092                                 /* Handle "blind" */ 
    1093                                 else if (p_ptr->blind) 
    1094                                 { 
    1095                                         /* Use "dark gray" */ 
    1096                                         a = TERM_L_DARK; 
    1097                                 } 
    1098  
    1099                                 /* Handle "dark" grids */ 
    1100                                 else if (!(info & (CAVE_GLOW))) 
    1101                                 { 
    1102                                         /* Use "dark gray" */ 
    1103                                         a = TERM_L_DARK; 
    1104                                 } 
    1105  
    1106                                 /* Handle "view_bright_lite" */ 
    1107                                 else if (view_bright_lite) 
    1108                                 { 
    1109                                         /* Use "gray" */ 
    1110                                         a = TERM_SLATE; 
    1111                                 } 
    1112                         } 
    1113                 } 
    1114  
    1115                 /* Unknown */ 
    1116                 else 
    1117                 { 
    1118                         /* Get the darkness feature */ 
    1119                         f_ptr = &f_info[FEAT_NONE]; 
    1120  
    1121                         /* Normal attr */ 
    1122                         a = f_ptr->d_attr; 
    1123  
    1124                         /* Normal char */ 
    1125                         c = f_ptr->d_char; 
    1126                 } 
    1127         } 
    1128  
    1129         /* Interesting grids (non-floors) */ 
    1130         else 
    1131         { 
    1132                 /* Memorized grids */ 
    1133                 if (info & (CAVE_MARK)) 
    1134                 { 
    1135                         /* Apply "mimic" field */ 
    1136                         feat = f_info[feat].mimic; 
    1137  
    1138                         /* Get the feature */ 
    1139                         f_ptr = &f_info[feat]; 
    1140  
    1141                         /* Normal attr */ 
    1142                         a = f_ptr->d_attr; 
    1143  
    1144                         /* Normal char */ 
    1145                         c = f_ptr->d_char; 
    1146  
    1147                         /* Special lighting effects (walls only) */ 
    1148                         if (view_granite_lite && 
    1149                             (((a == TERM_WHITE) && (feat >= FEAT_SECRET)) || 
    1150                              (feat_supports_lighting(feat)))) 
    1151                         { 
    1152                                 /* Handle "seen" grids */ 
    1153                                 if (info & (CAVE_SEEN)) 
    1154                                 { 
    1155                                         /* Use "white" */ 
    1156                                 } 
    1157  
    1158                                 /* Handle "blind" */ 
    1159                                 else if (p_ptr->blind) 
    1160                                 { 
    1161                                         /* Use "dark gray" */ 
    1162                                         a = TERM_L_DARK; 
    1163                                 } 
    1164  
    1165                                 /* Handle "view_bright_lite" */ 
    1166                                 else if (view_bright_lite) 
    1167                                 { 
    1168                                         /* Use "gray" */ 
    1169                                         a = TERM_SLATE; 
    1170                                 } 
    1171                                 else 
    1172                                 { 
    1173                                         /* Use "white" */ 
    1174                                 } 
    1175                         } 
    1176                 } 
    1177  
    1178                 /* Unknown */ 
    1179                 else 
    1180                 { 
    1181                         /* Get the darkness feature */ 
    1182                         f_ptr = &f_info[FEAT_NONE]; 
    1183  
    1184                         /* Normal attr */ 
    1185                         a = f_ptr->d_attr; 
    1186  
    1187                         /* Normal char */ 
    1188                         c = f_ptr->d_char; 
    1189                 } 
    1190         } 
    1191  
    1192         /* Objects */ 
    1193         for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx) 
    1194         { 
    1195                 object_type *o_ptr; 
    1196  
    1197                 /* Get the object */ 
    1198                 o_ptr = &o_list[this_o_idx]; 
    1199  
    1200                 /* Get the next object */ 
    1201                 next_o_idx = o_ptr->next_o_idx; 
    1202  
    1203                 /* Memorized objects */ 
    1204                 if (o_ptr->marked) 
    1205                 { 
    1206                         /* Hack -- object hallucination */ 
    1207                         if (image) 
    1208                         { 
    1209                                 int i = image_object(); 
    1210  
    1211                                 a = PICT_A(i); 
    1212                                 c = PICT_C(i); 
    1213  
    1214                                 break; 
    1215                         } 
    1216  
    1217                         /* Normal attr */ 
    1218                         a = object_attr_default(o_ptr); 
    1219  
    1220                         /* Normal char */ 
    1221                         c = object_char_default(o_ptr); 
    1222  
    1223                         /* First marked object */ 
    1224                         if (!show_piles) break; 
    1225  
    1226                         /* Special stack symbol */ 
    1227                         if (++floor_num > 1) 
    1228                         { 
    1229                                 object_kind *k_ptr; 
    1230  
    1231                                 /* Get the "pile" feature */ 
    1232                                 k_ptr = &k_info[0]; 
    1233  
    1234                                 /* Normal attr */ 
    1235                                 a = k_ptr->d_attr; 
    1236  
    1237                                 /* Normal char */ 
    1238                                 c = k_ptr->d_char; 
    1239  
    1240                                 break; 
    1241                         } 
    1242                 } 
    1243         } 
    1244  
    1245  
    1246         /* Monsters */ 
    1247         if (m_idx > 0) 
    1248         { 
    1249                 monster_type *m_ptr = &mon_list[m_idx]; 
    1250  
    1251                 /* Visible monster */ 
    1252                 if (m_ptr->ml) 
    1253                 { 
    1254                         monster_race *r_ptr = &r_info[m_ptr->r_idx]; 
    1255  
    1256                         byte da; 
    1257                         char dc; 
    1258  
    1259                         /* Desired attr */ 
    1260                         da = r_ptr->d_attr; 
    1261  
    1262                         /* Desired char */ 
    1263                         dc = r_ptr->d_char; 
    1264  
    1265                         /* Hack -- monster hallucination */ 
    1266                         if (image) 
    1267                         { 
    1268                                 int i = image_monster(); 
    1269  
    1270                                 a = PICT_A(i); 
    1271                                 c = PICT_C(i); 
    1272                         } 
    1273  
    1274                         /* Ignore weird codes */ 
    1275                         else if (avoid_other) 
    1276                         { 
    1277                                 /* Use attr */ 
    1278                                 a = da; 
    1279  
    1280                                 /* Use char */ 
    1281                                 c = dc; 
    1282                         } 
    1283  
    1284                         /* Special attr/char codes */ 
    1285                         else if ((da & 0x80) && (dc & 0x80)) 
    1286                         { 
    1287                                 /* Use attr */ 
    1288                                 a = da; 
    1289  
    1290                                 /* Use char */ 
    1291                                 c = dc; 
    1292                         } 
    1293  
    1294                         /* Multi-hued monster */ 
    1295                         else if (r_ptr->flags1 & (RF1_ATTR_MULTI)) 
    1296                         { 
    1297                                 /* Multi-hued attr */ 
    1298                                 a = randint(15); 
    1299  
    1300                                 /* Normal char */ 
    1301                                 c = dc; 
    1302                         } 
    1303  
    1304                         /* Normal monster (not "clear" in any way) */ 
    1305                         else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR))) 
    1306                         { 
    1307                                 /* Use attr */ 
    1308                                 a = da; 
    1309  
    1310                                 /* Use char */ 
    1311                                 c = dc; 
    1312                         } 
    1313  
    1314                         /* Hack -- Bizarre grid under monster */ 
    1315                         else if ((a & 0x80) || (c & 0x80)) 
    1316                         { 
    1317                                 /* Use attr */ 
    1318                                 a = da; 
    1319  
    1320                                 /* Use char */ 
    1321                                 c = dc; 
    1322                         } 
    1323  
    1324                         /* Normal char, Clear attr, monster */ 
    1325                         else if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR))) 
    1326                         { 
    1327                                 /* Normal char */ 
    1328                                 c = dc; 
    1329                         } 
    1330  
    1331                         /* Normal attr, Clear char, monster */ 
    1332                         else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR))) 
    1333                         { 
    1334                                 /* Normal attr */ 
    1335                                 a = da; 
    1336                         } 
    1337                 } 
    1338         } 
    1339  
    1340         /* Handle "player" */ 
    1341         else if ((m_idx < 0) && !(p_ptr->running && hidden_player)) 
    1342         { 
    1343                 monster_race *r_ptr = &r_info[0]; 
    1344  
    1345                 /* Get the "player" attr */ 
    1346                 a = r_ptr->d_attr; 
    1347  
    1348                 /* Get the "player" char */ 
    1349                 c = r_ptr->d_char; 
    1350         } 
    1351  
    1352 #ifdef MAP_INFO_MULTIPLE_PLAYERS 
    1353         /* Players */ 
    1354         else if (m_idx < 0) 
    1355 #else /* MAP_INFO_MULTIPLE_PLAYERS */ 
    1356         /* Handle "player" */ 
    1357         else if ((m_idx < 0) && !(p_ptr->running && hidden_player)) 
    1358 #endif /* MAP_INFO_MULTIPLE_PLAYERS */ 
    1359         { 
    1360                 monster_race *r_ptr = &r_info[0]; 
    1361  
    1362                 /* Get the "player" attr */ 
    1363                 a = r_ptr->d_attr; 
    1364  
    1365                 /* Get the "player" char */ 
    1366                 c = r_ptr->d_char; 
    13671013        } 
    13681014 
  • trunk/src/cmd4.c

    r15 r16  
    1 /* File: cmd4.c */ 
    2  
    31/* 
    42 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke 
     
    75 * and not for profit purposes provided that this copyright and statement 
    86 * are included in all such copies.  Other copyrights may also apply. 
     7 * 
     8 * UnAngband (c) 2001-6 Andrew Doull. Modifications to the Angband 2.9.1 
     9 * source code are released under the Gnu Public License. See www.fsf.org 
     10 * for current GPL license details. Addition permission granted to 
     11 * incorporate modifications in all Angband variants as defined in the 
     12 * Angband variants FAQ. See rec.games.roguelike.angband for FAQ. 
     13 * 
     14 */ 
     15 
     16/* 
     17 * Code cleanup -- Pete Mack 02/2007 (No copyright)  
     18 * Use proper function tables and database methodology. 
     19 * Tables are now tables, not multiline conditionals. 
     20 * Joins are now relational, not ad hoc. 
     21 * Function tables are used for iteration where reasonable. (C-style class model) 
    922 */ 
    1023 
    1124#include "angband.h" 
    12 #include "z-file.h" 
     25#include "ui.h" 
     26 
     27 
     28 
     29typedef struct { 
     30                int maxnum; /* Maximum possible item count for this class */ 
     31                bool easy_know; /* Items don't need to be IDed to recognize membership */ 
     32 
     33                const char *(*name)(int gid); /* name of this group */ 
     34 
     35                /* Compare, in group and display order */ 
     36                /* Optional, if already sorted */ 
     37                int (*gcomp)(const void *, const void *); /* Compare GroupIDs of two oids */ 
     38                int (*group)(int oid); /* Group ID for of an oid */ 
     39                bool (*aware)(object_type *obj); /* Object is known sufficiently for group */ 
     40 
     41} group_funcs; 
     42 
     43typedef struct { 
     44 
     45                /* Display object label (possibly with cursor) at given screen location. */ 
     46                void (*display_label)(int col, int row, bool cursor, int oid); 
     47 
     48                void (*lore)(int oid); /* Dump known lore to screen*/ 
     49 
     50                /* Required only for objects with modifiable display attributes */ 
     51                /* Unknown 'flavors' return flavor attributes */ 
     52                char *(*xchar)(int oid); /* get character attr for OID (by address) */ 
     53                byte *(*xattr)(int oid); /* get color attr for OID (by address) */ 
     54 
     55                /* Required only for manipulable (ordinary) objects */ 
     56                /* Address of inscription.  Unknown 'flavors' return null  */ 
     57                u16b *(*note)(int oid); 
     58 
     59} member_funcs; 
     60 
     61 
     62/* Helper class for generating joins */ 
     63typedef struct join { 
     64                int oid; 
     65                int gid; 
     66} join_t; 
     67 
     68/* A default group-by */ 
     69static join_t *default_join; 
     70static int default_join_cmp(const void *a, const void *b) 
     71
     72                join_t *ja = &default_join[*(int*)a]; 
     73                join_t *jb = &default_join[*(int*)b]; 
     74                int c = ja->gid - jb->gid; 
     75                if (c) return c; 
     76                return ja->oid - jb->oid; 
     77
     78static int default_group(int oid) { return default_join[oid].gid; } 
     79 
     80 
     81static int *obj_group_order; 
     82/* 
     83 * Description of each monster group. 
     84 */ 
     85static struct { 
     86                cptr chars; 
     87                cptr name; 
     88} monster_group[] = 
     89
     90        { (cptr)-1,     "Uniques" }, 
     91        { "A",          "Angels" }, 
     92        { "a",          "Ants" }, 
     93        { "b",          "Bats" }, 
     94        { "B",          "Birds" }, 
     95        { "C",          "Canines" }, 
     96        { "c",          "Centipedes" }, 
     97        { "uU",         "Demons" }, 
     98        { "dD",         "Dragons" }, 
     99        { "vE",         "Elementals/Vortices" }, 
     100        { "e",          "Eyes/Beholders" }, 
     101        { "f",          "Felines" }, 
     102        { "G",          "Ghosts" }, 
     103        { "OP",         "Giants/Ogres" }, 
     104        { "g",          "Golems" }, 
     105        { "H",          "Harpies/Hybrids" }, 
     106        { "h",          "Hominids (Elves, Dwarves)" }, 
     107        { "H",          "Hydras" }, 
     108        { "i",          "Icky Things" }, 
     109        { "FI",         "Insects" }, 
     110        { "j",          "Jellies" }, 
     111        { "K",          "Killer Beetles" }, 
     112        { "k",          "Kobolds" }, 
     113        { "L",          "Lichs" }, 
     114        { "$?!_",       "Mimics" }, 
     115        { "m",          "Molds" }, 
     116        { ",",          "Mushroom Patches" }, 
     117        { "n",          "Nagas" }, 
     118        { "o",          "Orcs" }, 
     119        { "tp",         "Humans" }, 
     120        { "q",          "Quadrupeds" }, 
     121        { "Q",          "Quylthulgs" }, 
     122        { "R",          "Reptiles/Amphibians" }, 
     123        { "r",          "Rodents" }, 
     124        { "S",          "Scorpions/Spiders" }, 
     125        { "s",          "Skeletons/Drujs" }, 
     126        { "J",          "Snakes" }, 
     127        { "T",          "Trolls" }, 
     128        { "V",          "Vampires" }, 
     129        { "W",          "Wights/Wraiths" }, 
     130        { "w",          "Worms/Worm Masses" }, 
     131        { "X",          "Xorns/Xarens" }, 
     132        { "Y",          "Yeti" }, 
     133        { "Z",          "Zephyr Hounds" }, 
     134        { "z",          "Zombies" }, 
     135        { NULL,         NULL } 
     136}; 
     137 
     138/* 
     139 * Description of each feature group. 
     140 */ 
     141const char *feature_group_text[] =  
     142
     143                "Floors", 
     144                "Traps", 
     145                "Doors", 
     146                "Stairs", 
     147                "Walls", 
     148                "Streamers", 
     149                "Obstructions", 
     150                "Stores", 
     151                "Other", 
     152                NULL 
     153}; 
     154 
     155 
     156 
     157/* Useful method declarations */ 
     158static void display_visual_list(int col, int row, int height, int width, 
     159                                byte attr_top, char char_left); 
     160 
     161static void browser_mouse(key_event ke, int *column, int *grp_cur, int grp_cnt,  
     162                                int *list_cur, int list_cnt, int col0, int row0, 
     163                                int grp0, int list0, int *delay); 
     164 
     165static void browser_cursor(char ch, int *column, int *grp_cur, int grp_cnt,  
     166                                int *list_cur, int list_cnt); 
     167 
     168static bool visual_mode_command(key_event ke, bool *visual_list_ptr,  
     169                                int height, int width,  
     170                                byte *attr_top_ptr, char *char_left_ptr,  
     171                                byte *cur_attr_ptr, char *cur_char_ptr, 
     172                                int col, int row, int *delay); 
     173 
     174static void place_visual_list_cursor(int col, int row, byte a, 
     175                                byte c, byte attr_top, byte char_left); 
     176 
     177static void dump_pref_file(void (*dump)(FILE*), const char *title); 
     178 
     179/* 
     180 *  Clipboard variables for copy&paste in visual mode 
     181 */ 
     182static byte attr_idx = 0; 
     183static byte char_idx = 0; 
     184 
     185/* 
     186 * Return a specific ordering for the features 
     187 */ 
     188int feat_order(int feat) 
     189
     190                feature_type *f_ptr = &f_info[feat]; 
     191                switch(f_ptr->d_char) { 
     192                                case '.':                               return 0; 
     193                                case '^':                               return 1; 
     194                                case '\'': case '+':    return 2; 
     195                                case '<': case '>':             return 3; 
     196                                case '#':                               return 4; 
     197                                case '*': case '%' :    return 5; 
     198                                case ';': case ':' :    return 6; 
     199                                default: 
     200                                        if(isdigit(f_ptr->d_char)) return 7; 
     201                                        return 8; 
     202                } 
     203}; 
     204 
     205 
     206/* HACK */ 
     207static const int use_dbltile = 0; 
     208static const int use_trptile = 0; 
     209 
     210/* Emit a 'graphical' symbol and a padding character if appropriate */ 
     211static void big_pad(int col, int row, byte a, byte c) 
     212
     213                Term_putch(col, row, a, c); 
     214                if(!use_bigtile) return; 
     215                if (a &0x80) Term_putch(col+1, row, 255, -1); 
     216                else Term_putch(col+1, row, 1, ' '); 
     217
     218 
     219static int actual_width(int width) { 
     220                if (use_trptile) width = width * 3; 
     221                else if(use_dbltile) width *= 2; 
     222                if(use_bigtile) width *= 2; 
     223                return width; 
     224
     225static int actual_height(int height) { 
     226                if(use_bigtile) height *= 2; 
     227                if (use_trptile) height = height * 3 / 2; 
     228                else if(use_dbltile) height *= 2; 
     229                return height; 
     230
     231 
     232static int logical_width(int width) 
     233
     234                int div = 1; 
     235                if(use_trptile) div = 3; 
     236                else if(use_dbltile) div *= 2; 
     237                if(use_bigtile) div *= 2; 
     238                return width / div; 
     239
     240 
     241static int logical_height(int height) 
     242
     243                int div = 1; 
     244                if(use_trptile) { 
     245                                height *= 2; 
     246                                div = 3; 
     247                } 
     248                else if(use_dbltile) div = 2; 
     249                if(use_bigtile) div *= 2; 
     250                return height / div; 
     251
     252 
     253/* 
     254 * Interact with inscriptions. 
     255 * Create a copy of an existing quark, except if the quark has '=x' in it,  
     256 * If an quark has '=x' in it remove it from the copied string, otherwise append it where 'x' is ch. 
     257 * Return the new quark location. 
     258 */ 
     259static int auto_note_modify(int note, char ch) 
     260
     261                char tmp[80]; 
     262 
     263                cptr s; 
     264 
     265                /* Paranoia */ 
     266                if (!ch) return(note); 
     267 
     268                /* Null length string to start */ 
     269                tmp[0] = '\0'; 
     270 
     271                /* Inscription */ 
     272                if (note) 
     273                { 
     274 
     275                                /* Get the inscription */ 
     276                                s = quark_str(note); 
     277 
     278                                /* Temporary copy */ 
     279                                my_strcpy(tmp,s,80); 
     280 
     281                                /* Process inscription */ 
     282                                while (s) 
     283                                { 
     284 
     285                                                /* Auto-pickup on "=g" */ 
     286                                                if (s[1] == ch) 
     287                                                { 
     288 
     289                                                                /* Truncate string */ 
     290                                                                tmp[strlen(tmp)-strlen(s)] = '\0'; 
     291 
     292                                                                /* Overwrite shorter string */ 
     293                                                                my_strcat(tmp,s+2,80); 
     294 
     295                                                                /* Create quark */ 
     296                                                                return(quark_add(tmp)); 
     297                                                } 
     298 
     299                                                /* Find another '=' */ 
     300                                                s = strchr(s + 1, '='); 
     301                                } 
     302                } 
     303 
     304                /* Append note */ 
     305                my_strcat(tmp,format("=%c",ch),80); 
     306 
     307                /* Create quark */ 
     308                return(quark_add(tmp)); 
     309
     310 
     311/* 
     312 * Display a list with a cursor 
     313 */ 
     314static void display_group_list(int col, int row, int wid, int per_page, 
     315                                int start, int max, int cursor, const cptr group_text[]) 
     316
     317                int i, pos; 
     318 
     319                /* Display lines until done */ 
     320                for (i = 0, pos = start; i < per_page && pos < max; i++, pos++) 
     321                { 
     322                                char buffer[21]; 
     323                                byte attr = curs_attrs[CURS_KNOWN][cursor == pos]; 
     324 
     325                                /* Erase the line */ 
     326                                Term_erase(col, row + i, wid); 
     327 
     328                                /* Display it (width should not exceed 20) */ 
     329                                strncpy(buffer, group_text[pos], 20); 
     330                                buffer[20] = 0; 
     331                                c_put_str(attr, buffer, row + i, col); 
     332                } 
     333                /* Wipe the rest? */ 
     334
     335 
     336/* 
     337 * Display the members of a list. 
     338 * Aware of inscriptions, wizard information, and string-formatted visual data. 
     339 * label function must display actual visuals, to handle illumination, etc 
     340 */ 
     341static void display_member_list(int col, int row, int wid, int per_page, 
     342                                int start, int o_count, int cursor, int object_idx [], 
     343                                member_funcs o_funcs) 
     344
     345                int i, pos; 
     346 
     347                for(i = 0, pos = start; i < per_page && pos < o_count; i++, pos++) { 
     348                                int oid = object_idx[pos]; 
     349                                byte attr = curs_attrs[CURS_KNOWN][cursor == oid]; 
     350 
     351                                /* Print basic label */ 
     352                                o_funcs.display_label(col, row + i, pos == cursor, oid); 
     353 
     354                                /* Show inscription, if applicable, aware and existing */ 
     355                                if(o_funcs.note && o_funcs.note(oid) && *o_funcs.note(oid)) { 
     356                                                c_put_str(TERM_YELLOW,quark_str(*o_funcs.note(oid)), row+i, 65); 
     357                                } 
     358 
     359                                if (p_ptr->wizard) 
     360                                                c_put_str(attr, format("%d", oid), row, 60); 
     361 
     362                                /* Do visual mode */ 
     363                                if(per_page == 1 && o_funcs.xattr) { 
     364                                                char c = *o_funcs.xchar(oid); 
     365                                                byte a = *o_funcs.xattr(oid); 
     366                                                c_put_str(attr, format((c & 0x80) ? "%02x/%02x" : "%02x/%d", a, c), row + i, 60); 
     367                                } 
     368                } 
     369 
     370                /* Clear remaining lines */ 
     371                for (; i < per_page; i++) 
     372                { 
     373                                Term_erase(col, row + i, 255); 
     374                } 
     375
     376 
     377 
     378/* 
     379 * Interactive group by.  
     380 * Recognises inscriptions, graphical symbols, lore 
     381 */ 
     382static void display_knowledge(const char *title, int *obj_list, int o_count, 
     383                                group_funcs g_funcs, member_funcs o_funcs, 
     384                                const char *otherfields) 
     385
     386        /* maximum number of groups to display */ 
     387        int max_group = g_funcs.maxnum < o_count ? g_funcs.maxnum : o_count ; 
     388 
     389        /* This could (should?) be (void **) */ 
     390        int *g_list, *g_offset; 
     391 
     392        const char **g_names; 
     393 
     394        int g_name_len = 8;  /* group name length, minumum is 8 */ 
     395 
     396        int grp_cnt = 0; /* total number groups */ 
     397 
     398        int g_cur = 0, grp_old = -1, grp_top = 0; /* group list positions */ 
     399        int o_cur = 0, object_top = 0; /* object list positions */ 
     400        int g_o_count = 0; /* object count for group */ 
     401        int o_first = 0, g_o_max = 0; /* group limits in object list */ 
     402        int oid = -1, old_oid = -1;  /* object identifiers */ 
     403 
     404        /* display state variables */ 
     405        bool visual_list = FALSE; 
     406        byte attr_top = 0; 
     407        char char_left = 0; 
     408        int note_idx = 0; 
     409 
     410        int delay = 0; 
     411        int column = 0; 
     412 
     413        bool flag = FALSE; 
     414        bool redraw = TRUE; 
     415 
     416        int browser_rows; 
     417        int wid, hgt; 
     418        int i; 
     419        int prev_g = -1; 
     420 
     421        /* Get size */ 
     422        Term_get_size(&wid, &hgt); 
     423        browser_rows = hgt - 8; 
     424 
     425        /* Do the group by. ang_sort only works on (void **) */ 
     426        /* Maybe should make this a precondition? */ 
     427        if(g_funcs.gcomp) 
     428                        qsort(obj_list, o_count, sizeof(*obj_list), g_funcs.gcomp); 
     429 
     430        C_MAKE(g_list, max_group+1, int); 
     431        C_MAKE(g_offset, max_group+1, int); 
     432 
     433        for(i = 0; i < o_count; i++) { 
     434                if(prev_g != g_funcs.group(obj_list[i])) { 
     435                        prev_g = g_funcs.group(obj_list[i]); 
     436                        g_offset[grp_cnt] = i; 
     437                        g_list[grp_cnt++] = prev_g; 
     438                } 
     439        } 
     440        g_offset[grp_cnt] = o_count; 
     441        g_list[grp_cnt] = -1; 
     442 
     443 
     444        /* The compact set of group names, in display order */ 
     445        C_MAKE(g_names, grp_cnt, const char **); 
     446        for (i = 0; i < grp_cnt; i++) { 
     447                int len; 
     448                g_names[i] = g_funcs.name(g_list[i]); 
     449                len = strlen(g_names[i]); 
     450                if(len > g_name_len) g_name_len = len; 
     451        } 
     452        if(g_name_len >= 20) g_name_len = 20; 
     453 
     454  &n