PageRenderTime 68ms CodeModel.GetById 30ms app.highlight 32ms RepoModel.GetById 0ms app.codeStats 0ms

/src/object/obj-ui.c

https://bitbucket.org/ekolis/jackband
C | 1306 lines | 731 code | 262 blank | 313 comment | 205 complexity | e59b1cfaa897335b4064b1f11ec643e7 MD5 | raw file
   1/*
   2 * File: object1.c
   3 * Purpose: Mainly object descriptions and generic UI functions
   4 *
   5 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
   6 *
   7 * This work is free software; you can redistribute it and/or modify it
   8 * under the terms of either:
   9 *
  10 * a) the GNU General Public License as published by the Free Software
  11 *    Foundation, version 2, or
  12 *
  13 * b) the "Angband licence":
  14 *    This software may be copied and distributed for educational, research,
  15 *    and not for profit purposes provided that this copyright and statement
  16 *    are included in all such copies.  Other copyrights may also apply.
  17 */
  18#include "angband.h"
  19#include "tvalsval.h"
  20
  21
  22/*
  23 * Display a list of objects.  Each object may be prefixed with a label.
  24 * Used by show_inven(), show_equip(), and show_floor().  Mode flags are
  25 * documented in object.h
  26 */
  27static void show_obj_list(int num_obj, char labels[50][80], object_type *objects[50], olist_detail_t mode)
  28{
  29	int i, row = 0, col = 0;
  30	size_t max_len = 0;
  31	int ex_width = 0, ex_offset, ex_offset_ctr;
  32
  33	object_type *o_ptr;
  34	char o_name[50][80];
  35	char tmp_val[80];
  36	
  37	bool in_term;
  38	
  39	in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE;
  40
  41	if (in_term) max_len = 40;
  42
  43	/* Calculate name offset and max name length */
  44	for (i = 0; i < num_obj; i++)
  45	{
  46		o_ptr = objects[i];
  47
  48		/* Null objects are used to skip lines, or display only a label */		
  49		if (o_ptr == NULL) continue;
  50
  51		/* Max length of label + object name */
  52		object_desc(o_name[i], sizeof(o_name[i]), o_ptr, ODESC_PREFIX | ODESC_FULL);
  53		max_len = MAX(max_len, strlen(labels[i]) + strlen(o_name[i]));
  54	}
  55
  56	/* Width of extra fields */
  57	if (mode & OLIST_WEIGHT) ex_width += 9;
  58	if (mode & OLIST_PRICE) ex_width += 9;
  59	if (mode & OLIST_FAIL) ex_width += 10;
  60
  61	/* Determine beginning row and column */
  62	if (in_term)
  63	{
  64		/* Term window */
  65		row = 0;
  66		col = 0;
  67	}
  68	else
  69	{
  70		/* Main window */
  71		row = 1;
  72		col = Term->wid - 1 - max_len - ex_width;
  73
  74		if (col < 3) col = 0;
  75	}
  76
  77	/* Column offset of the first extra field */
  78	ex_offset = MIN(max_len, (size_t)(Term->wid - 1 - ex_width - col));
  79
  80	/* Output the list */
  81	for (i = 0; i < num_obj; i++)
  82	{
  83		o_ptr = objects[i];
  84		
  85		/* Clear the line */
  86		prt("", row + i, MAX(col - 2, 0));
  87
  88		/* Print the label */
  89		put_str(labels[i], row + i, col);
  90
  91		/* Print the object */
  92		if (o_ptr != NULL)
  93		{
  94			/* Limit object name */
  95			if (strlen(labels[i]) + strlen(o_name[i]) > (size_t)ex_offset)
  96			{
  97				int truncate = ex_offset - strlen(labels[i]);
  98				
  99				if (truncate < 0) truncate = 0;
 100				if ((size_t)truncate > sizeof(o_name[i]) - 1) truncate = sizeof(o_name[i]) - 1;
 101
 102				o_name[i][truncate] = '\0';
 103			}
 104
 105			/* Object name */
 106			c_put_str(tval_to_attr[o_ptr->tval % N_ELEMENTS(tval_to_attr)], o_name[i],
 107			          row + i, col + strlen(labels[i]));
 108
 109			/* Extra fields */
 110			ex_offset_ctr = ex_offset;
 111			
 112			if (mode & OLIST_PRICE)
 113			{
 114				int price = price_item(o_ptr, TRUE, o_ptr->number);
 115				strnfmt(tmp_val, sizeof(tmp_val), "%6d au", price);
 116				put_str(tmp_val, row + i, col + ex_offset_ctr);
 117				ex_offset_ctr += 9;
 118			}
 119
 120			if (mode & OLIST_FAIL)
 121			{
 122				int fail = (9 + get_use_device_chance(o_ptr)) / 10;
 123				if (object_effect_is_known(o_ptr))
 124					strnfmt(tmp_val, sizeof(tmp_val), "%4d%% fail", fail);
 125				else
 126					my_strcpy(tmp_val, "    ? fail", sizeof(tmp_val));
 127				put_str(tmp_val, row + i, col + ex_offset_ctr);
 128				ex_offset_ctr += 10;
 129			}
 130
 131			if (mode & OLIST_WEIGHT)
 132			{
 133				int weight = o_ptr->weight * o_ptr->number;
 134				strnfmt(tmp_val, sizeof(tmp_val), "%4d.%1d lb", weight / 10, weight % 10);
 135				put_str(tmp_val, row + i, col + ex_offset_ctr);
 136				ex_offset_ctr += 9;
 137			}
 138		}
 139	}
 140
 141	/* For the inventory: print the quiver count */
 142	if (mode & OLIST_QUIVER)
 143	{
 144		int count, j;
 145
 146		/* Quiver may take multiple lines */
 147		for(j = 0; j < p_ptr->quiver_slots; j++, i++)
 148		{
 149			/* Number of missiles in this "slot" */
 150			if (j == p_ptr->quiver_slots - 1 && p_ptr->quiver_remainder > 0)
 151				count = p_ptr->quiver_remainder;
 152			else
 153				count = 99;
 154
 155			/* Clear the line */
 156			prt("", row + i, MAX(col - 2, 0));
 157
 158			/* Print the (disabled) label */
 159			strnfmt(tmp_val, sizeof(tmp_val), "%c) ", index_to_label(i));
 160			c_put_str(TERM_SLATE, tmp_val, row + i, col);
 161
 162			/* Print the count */
 163			strnfmt(tmp_val, sizeof(tmp_val), "in Quiver: %d missile%s", count,
 164					count == 1 ? "" : "s");
 165			c_put_str(TERM_L_UMBER, tmp_val, row + i, col + 3);
 166		}
 167	}
 168
 169	/* Clear term windows */
 170	if (in_term)
 171	{
 172		for (; i < Term->hgt; i++)
 173		{
 174			prt("", row + i, MAX(col - 2, 0));
 175		}
 176	}
 177	
 178	/* Print a drop shadow for the main window if necessary */
 179	else if (i > 0 && row + i < 24)
 180	{
 181		prt("", row + i, MAX(col - 2, 0));
 182	}
 183}
 184
 185
 186/*
 187 * Display the inventory.  Builds a list of objects and passes them
 188 * off to show_obj_list() for display.  Mode flags documented in
 189 * object.h
 190 */
 191void show_inven(olist_detail_t mode)
 192{
 193	int i, last_slot = 0;
 194	int diff = weight_remaining();
 195
 196	object_type *o_ptr;
 197
 198   int num_obj = 0;
 199   char labels[50][80];
 200   object_type *objects[50];
 201
 202   bool in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE;
 203
 204	/* Include burden for term windows */
 205	if (in_term)
 206	{
 207		strnfmt(labels[num_obj], sizeof(labels[num_obj]),
 208		        "Burden %d.%d lb (%d.%d lb %s) ",
 209		        p_ptr->total_weight / 10, p_ptr->total_weight % 10,
 210		        abs(diff) / 10, abs(diff) % 10,
 211		        (diff < 0 ? "overweight" : "remaining"));
 212
 213		objects[num_obj] = NULL;
 214		num_obj++;
 215	}
 216
 217	/* Find the last occupied inventory slot */
 218	for (i = 0; i < INVEN_PACK; i++)
 219	{
 220		o_ptr = &inventory[i];
 221		if (o_ptr->k_idx) last_slot = i;
 222	}
 223
 224	/* Build the object list */
 225	for (i = 0; i <= last_slot; i++)
 226	{
 227		o_ptr = &inventory[i];
 228
 229		/* Acceptable items get a label */
 230		if (item_tester_okay(o_ptr))
 231			strnfmt(labels[num_obj], sizeof(labels[num_obj]), "%c) ", index_to_label(i));
 232
 233		/* Unacceptable items are still displayed in term windows */
 234		else if (in_term)
 235			my_strcpy(labels[num_obj], "   ", sizeof(labels[num_obj]));
 236
 237		/* Unacceptable items are skipped in the main window */
 238		else continue;
 239
 240		/* Save the object */
 241		objects[num_obj] = o_ptr;
 242		num_obj++;
 243	}
 244
 245	/* Display the object list */
 246	show_obj_list(num_obj, labels, objects, mode);
 247}
 248
 249
 250/*
 251 * Display the equipment.  Builds a list of objects and passes them
 252 * off to show_obj_list() for display.  Mode flags documented in
 253 * object.h
 254 */
 255void show_equip(olist_detail_t mode)
 256{
 257	int i, last_slot = 0;
 258
 259	object_type *o_ptr;
 260
 261   int num_obj = 0;
 262   char labels[50][80];
 263   object_type *objects[50];
 264
 265	char tmp_val[80];
 266
 267   bool in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE;
 268
 269	/* Find the last equipment slot to display */
 270	for (i = INVEN_WIELD; i < ALL_INVEN_TOTAL; i++)
 271	{
 272		o_ptr = &inventory[i];
 273		if (i < INVEN_TOTAL || o_ptr->k_idx) last_slot = i;
 274	}
 275
 276	/* Build the object list */
 277	for (i = INVEN_WIELD; i <= last_slot; i++)
 278	{
 279		o_ptr = &inventory[i];
 280
 281		/* May need a blank line to separate the quiver */
 282		if (i == INVEN_TOTAL)
 283		{
 284			int j;
 285			bool need_spacer = FALSE;
 286			
 287			/* Scan the rest of the items for acceptable entries */
 288			for (j = i; j < last_slot; j++)
 289			{
 290				o_ptr = &inventory[j];
 291				if (item_tester_okay(o_ptr)) need_spacer = TRUE;
 292			}
 293
 294			/* Add a spacer between equipment and quiver */
 295			if (num_obj > 0 && need_spacer)
 296			{
 297				my_strcpy(labels[num_obj], "", sizeof(labels[num_obj]));
 298				objects[num_obj] = NULL;
 299				num_obj++;
 300			}
 301
 302			continue;
 303		}
 304
 305		/* Acceptable items get a label */
 306		if (item_tester_okay(o_ptr))
 307			strnfmt(labels[num_obj], sizeof(labels[num_obj]), "%c) ", index_to_label(i));
 308
 309		/* Unacceptable items are still displayed in term windows */
 310		else if (in_term)
 311			my_strcpy(labels[num_obj], "   ", sizeof(labels[num_obj]));
 312
 313		/* Unacceptable items are skipped in the main window */
 314		else continue;
 315
 316		/* Show full slot labels */
 317		if (OPT(show_labels))
 318		{
 319			strnfmt(tmp_val, sizeof(tmp_val), "%-14s: ", mention_use(i));
 320			my_strcat(labels[num_obj], tmp_val, sizeof(labels[num_obj]));
 321		}
 322
 323		/* Otherwise only show short quiver labels */
 324		else if (i >= QUIVER_START)
 325		{
 326			strnfmt(tmp_val, sizeof(tmp_val), "[f%d]: ", i - QUIVER_START);
 327			my_strcat(labels[num_obj], tmp_val, sizeof(labels[num_obj]));
 328		}
 329
 330		/* Save the object */
 331		objects[num_obj] = o_ptr;
 332		num_obj++;
 333	}
 334
 335	/* Display the object list */
 336	show_obj_list(num_obj, labels, objects, mode);
 337}
 338
 339
 340/*
 341 * Display the floor.  Builds a list of objects and passes them
 342 * off to show_obj_list() for display.  Mode flags documented in
 343 * object.h
 344 */
 345void show_floor(const int *floor_list, int floor_num, olist_detail_t mode)
 346{
 347	int i;
 348
 349	object_type *o_ptr;
 350
 351   int num_obj = 0;
 352   char labels[50][80];
 353   object_type *objects[50];
 354
 355	if (floor_num > MAX_FLOOR_STACK) floor_num = MAX_FLOOR_STACK;
 356
 357	/* Build the object list */
 358	for (i = 0; i < floor_num; i++)
 359	{
 360		o_ptr = &o_list[floor_list[i]];
 361
 362		/* Tester always skips gold. When gold should be displayed,
 363		 * only test items that are not gold.
 364		 */
 365		if ((o_ptr->tval != TV_GOLD || !(mode & OLIST_GOLD)) &&
 366		    !item_tester_okay(o_ptr))
 367			continue;
 368
 369		strnfmt(labels[num_obj], sizeof(labels[num_obj]),
 370		        "%c) ", index_to_label(i));
 371
 372		/* Save the object */
 373		objects[num_obj] = o_ptr;
 374		num_obj++;
 375	}
 376
 377	/* Display the object list */
 378	show_obj_list(num_obj, labels, objects, mode);
 379}
 380
 381
 382/*
 383 * Verify the choice of an item.
 384 *
 385 * The item can be negative to mean "item on floor".
 386 */
 387bool verify_item(cptr prompt, int item)
 388{
 389	char o_name[80];
 390
 391	char out_val[160];
 392
 393	object_type *o_ptr;
 394
 395	/* Inventory */
 396	if (item >= 0)
 397	{
 398		o_ptr = &inventory[item];
 399	}
 400
 401	/* Floor */
 402	else
 403	{
 404		o_ptr = &o_list[0 - item];
 405	}
 406
 407	/* Describe */
 408	object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);
 409
 410	/* Prompt */
 411	strnfmt(out_val, sizeof(out_val), "%s %s? ", prompt, o_name);
 412
 413	/* Query */
 414	return (get_check(out_val));
 415}
 416
 417
 418/*
 419 * Hack -- allow user to "prevent" certain choices.
 420 *
 421 * The item can be negative to mean "item on floor".
 422 */
 423static bool get_item_allow(int item, bool is_harmless)
 424{
 425	object_type *o_ptr;
 426	char verify_inscrip[] = "!*";
 427
 428	unsigned n;
 429
 430	/* Inventory or floor */
 431	if (item >= 0)
 432		o_ptr = &inventory[item];
 433	else
 434		o_ptr = &o_list[0 - item];
 435
 436	/* Check for a "prevention" inscription */
 437	verify_inscrip[1] = p_ptr->command_cmd;
 438
 439	/* Find both sets of inscriptions, add togther, and prompt that number of times */
 440	n = check_for_inscrip(o_ptr, verify_inscrip);
 441
 442	if (!is_harmless)
 443		n += check_for_inscrip(o_ptr, "!*");
 444
 445	while (n--)
 446	{
 447		if (!verify_item("Really try", item))
 448			return (FALSE);
 449	}
 450
 451	/* Allow it */
 452	return (TRUE);
 453}
 454
 455
 456
 457/*
 458 * Find the "first" inventory object with the given "tag".
 459 *
 460 * A "tag" is a char "n" appearing as "@n" anywhere in the
 461 * inscription of an object.
 462 *
 463 * Also, the tag "@xn" will work as well, where "n" is a tag-char,
 464 * and "x" is the "current" p_ptr->command_cmd code.
 465 */
 466static int get_tag(int *cp, char tag)
 467{
 468	int i;
 469	cptr s;
 470
 471	/* (f)ire is handled differently from all others, due to the quiver */
 472	if (p_ptr->command_cmd == 'f')
 473	{
 474		i = QUIVER_START + tag - '0';
 475		if (inventory[i].k_idx)
 476		{
 477			*cp = i;
 478			return (TRUE);
 479		}
 480		return (FALSE);
 481	}
 482
 483	/* Check every object */
 484	for (i = 0; i < ALL_INVEN_TOTAL; ++i)
 485	{
 486		object_type *o_ptr = &inventory[i];
 487
 488		/* Skip non-objects */
 489		if (!o_ptr->k_idx) continue;
 490
 491		/* Skip empty inscriptions */
 492		if (!o_ptr->note) continue;
 493
 494		/* Find a '@' */
 495		s = strchr(quark_str(o_ptr->note), '@');
 496
 497		/* Process all tags */
 498		while (s)
 499		{
 500			/* Check the normal tags */
 501			if (s[1] == tag)
 502			{
 503				/* Save the actual inventory ID */
 504				*cp = i;
 505
 506				/* Success */
 507				return (TRUE);
 508			}
 509
 510			/* Check the special tags */
 511			if ((s[1] == p_ptr->command_cmd) && (s[2] == tag))
 512			{
 513				/* Save the actual inventory ID */
 514				*cp = i;
 515
 516				/* Success */
 517				return (TRUE);
 518			}
 519
 520			/* Find another '@' */
 521			s = strchr(s + 1, '@');
 522		}
 523	}
 524
 525	/* No such tag */
 526	return (FALSE);
 527}
 528
 529
 530
 531/*
 532 * Let the user select an item, save its "index"
 533 *
 534 * Return TRUE only if an acceptable item was chosen by the user.
 535 *
 536 * The selected item must satisfy the "item_tester_hook()" function,
 537 * if that hook is set, and the "item_tester_tval", if that value is set.
 538 *
 539 * All "item_tester" restrictions are cleared before this function returns.
 540 *
 541 * The user is allowed to choose acceptable items from the equipment,
 542 * inventory, or floor, respectively, if the proper flag was given,
 543 * and there are any acceptable items in that location.
 544 *
 545 * The equipment or inventory are displayed (even if no acceptable
 546 * items are in that location) if the proper flag was given.
 547 *
 548 * If there are no acceptable items available anywhere, and "str" is
 549 * not NULL, then it will be used as the text of a warning message
 550 * before the function returns.
 551 *
 552 * Note that the user must press "-" to specify the item on the floor,
 553 * and there is no way to "examine" the item on the floor, while the
 554 * use of "capital" letters will "examine" an inventory/equipment item,
 555 * and prompt for its use.
 556 *
 557 * If a legal item is selected from the inventory, we save it in "cp"
 558 * directly (0 to 35), and return TRUE.
 559 *
 560 * If a legal item is selected from the floor, we save it in "cp" as
 561 * a negative (-1 to -511), and return TRUE.
 562 *
 563 * If no item is available, we do nothing to "cp", and we display a
 564 * warning message, using "str" if available, and return FALSE.
 565 *
 566 * If no item is selected, we do nothing to "cp", and return FALSE.
 567 *
 568 * Global "p_ptr->command_new" is used when viewing the inventory or equipment
 569 * to allow the user to enter a command while viewing those screens, and
 570 * also to induce "auto-enter" of stores, and other such stuff.
 571 *
 572 * Global "p_ptr->command_wrk" is used to choose between equip/inven/floor
 573 * listings.  It is equal to USE_INVEN or USE_EQUIP or USE_FLOOR, except
 574 * when this function is first called, when it is equal to zero, which will
 575 * cause it to be set to USE_INVEN.
 576 *
 577 * We always erase the prompt when we are done, leaving a blank line,
 578 * or a warning message, if appropriate, if no items are available.
 579 *
 580 * Note that only "acceptable" floor objects get indexes, so between two
 581 * commands, the indexes of floor objects may change.  XXX XXX XXX
 582 */
 583bool get_item(int *cp, cptr pmt, cptr str, int mode)
 584{
 585	int py = p_ptr->py;
 586	int px = p_ptr->px;
 587
 588	ui_event_data which;
 589
 590	int j, k;
 591
 592	int i1, i2;
 593	int e1, e2;
 594	int f1, f2;
 595
 596	bool done, item;
 597
 598	bool oops = FALSE;
 599
 600	bool use_inven = ((mode & USE_INVEN) ? TRUE : FALSE);
 601	bool use_equip = ((mode & USE_EQUIP) ? TRUE : FALSE);
 602	bool use_floor = ((mode & USE_FLOOR) ? TRUE : FALSE);
 603	bool can_squelch = ((mode & CAN_SQUELCH) ? TRUE : FALSE);
 604	bool is_harmless = ((mode & IS_HARMLESS) ? TRUE : FALSE);
 605
 606	olist_detail_t olist_mode = 0;
 607
 608	bool allow_inven = FALSE;
 609	bool allow_equip = FALSE;
 610	bool allow_floor = FALSE;
 611
 612	bool toggle = FALSE;
 613
 614	char tmp_val[160];
 615	char out_val[160];
 616
 617	int floor_list[MAX_FLOOR_STACK];
 618	int floor_num;
 619
 620	bool show_list = OPT(show_lists) ? TRUE : FALSE;
 621
 622
 623	/* Object list display modes */
 624	if (mode & SHOW_FAIL)
 625		olist_mode |= (OLIST_FAIL);
 626	else
 627		olist_mode |= (OLIST_WEIGHT);
 628	if (mode & SHOW_PRICES)
 629		olist_mode |= (OLIST_PRICE);
 630
 631	/* Paranoia XXX XXX XXX */
 632	message_flush();
 633
 634
 635	/* Not done */
 636	done = FALSE;
 637
 638	/* No item selected */
 639	item = FALSE;
 640
 641
 642	/* Full inventory */
 643	i1 = 0;
 644	i2 = INVEN_PACK - 1;
 645
 646	/* Forbid inventory */
 647	if (!use_inven) i2 = -1;
 648
 649	/* Restrict inventory indexes */
 650	while ((i1 <= i2) && (!get_item_okay(i1))) i1++;
 651	while ((i1 <= i2) && (!get_item_okay(i2))) i2--;
 652
 653	/* Accept inventory */
 654	if (i1 <= i2) allow_inven = TRUE;
 655
 656
 657	/* Full equipment */
 658	e1 = INVEN_WIELD;
 659	e2 = ALL_INVEN_TOTAL - 1;
 660
 661	/* Forbid equipment */
 662	if (!use_equip) e2 = -1;
 663
 664	/* Restrict equipment indexes */
 665	while ((e1 <= e2) && (!get_item_okay(e1))) e1++;
 666	while ((e1 <= e2) && (!get_item_okay(e2))) e2--;
 667
 668	/* Accept equipment */
 669	if (e1 <= e2) allow_equip = TRUE;
 670
 671
 672	/* Scan all non-gold objects in the grid */
 673	floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), py, px, 0x03);
 674
 675	/* Full floor */
 676	f1 = 0;
 677	f2 = floor_num - 1;
 678
 679	/* Forbid floor */
 680	if (!use_floor) f2 = -1;
 681
 682	/* Restrict floor indexes */
 683	while ((f1 <= f2) && (!get_item_okay(0 - floor_list[f1]))) f1++;
 684	while ((f1 <= f2) && (!get_item_okay(0 - floor_list[f2]))) f2--;
 685
 686	/* Accept floor */
 687	if (f1 <= f2) allow_floor = TRUE;
 688
 689
 690	/* Require at least one legal choice */
 691	if (!allow_inven && !allow_equip && !allow_floor)
 692	{
 693		/* Oops */
 694		oops = TRUE;
 695		done = TRUE;
 696	}
 697
 698	/* Analyze choices */
 699	else
 700	{
 701		/* Hack -- Start on equipment if requested */
 702		if ((p_ptr->command_wrk == USE_EQUIP) && use_equip)
 703			p_ptr->command_wrk = USE_EQUIP;
 704
 705		/* Use inventory if allowed */
 706		else if (use_inven)
 707			p_ptr->command_wrk = USE_INVEN;
 708
 709		/* Use equipment if allowed */
 710		else if (use_equip)
 711			p_ptr->command_wrk = USE_EQUIP;
 712
 713		/* Use floor if allowed */
 714		else if (use_floor)
 715			p_ptr->command_wrk = USE_FLOOR;
 716
 717		/* Hack -- Use (empty) inventory */
 718		else
 719			p_ptr->command_wrk = USE_INVEN;
 720	}
 721
 722
 723	/* Start out in "display" mode */
 724	if (show_list)
 725	{
 726		/* Save screen */
 727		screen_save();
 728	}
 729
 730
 731	/* Repeat until done */
 732	while (!done)
 733	{
 734		int ni = 0;
 735		int ne = 0;
 736
 737		/* Scan windows */
 738		for (j = 0; j < ANGBAND_TERM_MAX; j++)
 739		{
 740			/* Unused */
 741			if (!angband_term[j]) continue;
 742
 743			/* Count windows displaying inven */
 744			if (op_ptr->window_flag[j] & (PW_INVEN)) ni++;
 745
 746			/* Count windows displaying equip */
 747			if (op_ptr->window_flag[j] & (PW_EQUIP)) ne++;
 748		}
 749
 750		/* Toggle if needed */
 751		if (((p_ptr->command_wrk == USE_EQUIP) && ni && !ne) ||
 752		    ((p_ptr->command_wrk == USE_INVEN) && !ni && ne))
 753		{
 754			/* Toggle */
 755			toggle_inven_equip();
 756
 757			/* Track toggles */
 758			toggle = !toggle;
 759		}
 760
 761		/* Redraw */
 762		p_ptr->redraw |= (PR_INVEN | PR_EQUIP);
 763
 764		/* Redraw windows */
 765		redraw_stuff();
 766
 767		/* Viewing inventory */
 768		if (p_ptr->command_wrk == USE_INVEN)
 769		{
 770			/* Redraw if needed */
 771			if (show_list) show_inven(olist_mode);
 772
 773			/* Begin the prompt */
 774			strnfmt(out_val, sizeof(out_val), "Inven:");
 775
 776			/* List choices */
 777			if (i1 <= i2)
 778			{
 779				/* Build the prompt */
 780				strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,",
 781				        index_to_label(i1), index_to_label(i2));
 782
 783				/* Append */
 784				my_strcat(out_val, tmp_val, sizeof(out_val));
 785			}
 786
 787			/* Indicate ability to "view" */
 788			if (!show_list)
 789			{
 790				my_strcat(out_val, " * to see,", sizeof(out_val));
 791				button_add("[*]", '*');
 792			}
 793
 794			/* Indicate legality of "toggle" */
 795			if (use_equip)
 796			{
 797				my_strcat(out_val, " / for Equip,", sizeof(out_val));
 798				button_add("[/]", '/');
 799			}
 800
 801			/* Indicate legality of the "floor" */
 802			if (allow_floor)
 803			{
 804				my_strcat(out_val, " - for floor,", sizeof(out_val));
 805				button_add("[-]", '-');
 806			}
 807
 808			/* Indicate that squelched items can be selected */
 809			if (can_squelch)
 810			{
 811				my_strcat(out_val, " ! for squelched,", sizeof(out_val));
 812				button_add("[!]", '!');
 813			}
 814		}
 815
 816		/* Viewing equipment */
 817		else if (p_ptr->command_wrk == USE_EQUIP)
 818		{
 819			/* Redraw if needed */
 820			if (show_list) show_equip(olist_mode);
 821
 822			/* Begin the prompt */
 823			strnfmt(out_val, sizeof(out_val), "Equip:");
 824
 825			/* List choices */
 826			if (e1 <= e2)
 827			{
 828				/* Build the prompt */
 829				strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,",
 830				        index_to_label(e1), index_to_label(e2));
 831
 832				/* Append */
 833				my_strcat(out_val, tmp_val, sizeof(out_val));
 834			}
 835
 836			/* Indicate ability to "view" */
 837			if (!show_list)
 838			{
 839				my_strcat(out_val, " * to see,", sizeof(out_val));
 840				button_add("[*]", '*');
 841			}
 842
 843			/* Indicate legality of "toggle" */
 844			if (use_inven)
 845			{
 846				my_strcat(out_val, " / for Inven,", sizeof(out_val));
 847				button_add("[/]", '/');
 848			}
 849
 850			/* Indicate legality of the "floor" */
 851			if (allow_floor)
 852			{
 853				my_strcat(out_val, " - for floor,", sizeof(out_val));
 854				button_add("[!]", '!');
 855			}
 856		}
 857
 858		/* Viewing floor */
 859		else
 860		{
 861			/* Redraw if needed */
 862			if (show_list) show_floor(floor_list, floor_num, olist_mode);
 863
 864			/* Begin the prompt */
 865			strnfmt(out_val, sizeof(out_val), "Floor:");
 866
 867			/* List choices */
 868			if (f1 <= f2)
 869			{
 870				/* Build the prompt */
 871				strnfmt(tmp_val, sizeof(tmp_val), " %c-%c,", I2A(f1), I2A(f2));
 872
 873				/* Append */
 874				my_strcat(out_val, tmp_val, sizeof(out_val));
 875			}
 876
 877			/* Indicate ability to "view" */
 878			if (!show_list)
 879			{
 880				my_strcat(out_val, " * to see,", sizeof(out_val));
 881				button_add("[*]", '*');
 882			}
 883
 884			/* Append */
 885			if (use_inven)
 886			{
 887				my_strcat(out_val, " / for Inven,", sizeof(out_val));
 888				button_add("[/]", '/');
 889			}
 890
 891			/* Append */
 892			else if (use_equip)
 893			{
 894				my_strcat(out_val, " / for Equip,", sizeof(out_val));
 895				button_add("[/]", '/');
 896			}
 897
 898			/* Indicate that squelched items can be selected */
 899			if (can_squelch)
 900			{
 901				my_strcat(out_val, " ! for squelched,", sizeof(out_val));
 902				button_add("[!]", '!');
 903			}
 904		}
 905
 906		redraw_stuff();
 907
 908		/* Finish the prompt */
 909		my_strcat(out_val, " ESC", sizeof(out_val));
 910
 911		/* Build the prompt */
 912		strnfmt(tmp_val, sizeof(tmp_val), "(%s) %s", out_val, pmt);
 913
 914		/* Show the prompt */
 915		prt(tmp_val, 0, 0);
 916
 917
 918		/* Get a key */
 919		which = inkey_ex();
 920
 921		/* Parse it */
 922		switch (which.key)
 923		{
 924			case ESCAPE:
 925			{
 926				done = TRUE;
 927				break;
 928			}
 929
 930			case '*':
 931			case '?':
 932			case ' ':
 933			{
 934				if (!OPT(show_lists))
 935				{
 936					/* Hide the list */
 937					if (show_list)
 938					{
 939						/* Flip flag */
 940						show_list = FALSE;
 941
 942						/* Load screen */
 943						screen_load();
 944					}
 945
 946					/* Show the list */
 947					else
 948					{
 949						/* Save screen */
 950						screen_save();
 951
 952						/* Flip flag */
 953						show_list = TRUE;
 954					}
 955				}
 956
 957				break;
 958			}
 959
 960			case '/':
 961			{
 962				/* Toggle to inventory */
 963				if (use_inven && (p_ptr->command_wrk != USE_INVEN))
 964				{
 965					p_ptr->command_wrk = USE_INVEN;
 966				}
 967
 968				/* Toggle to equipment */
 969				else if (use_equip && (p_ptr->command_wrk != USE_EQUIP))
 970				{
 971					p_ptr->command_wrk = USE_EQUIP;
 972				}
 973
 974				/* No toggle allowed */
 975				else
 976				{
 977					bell("Cannot switch item selector!");
 978					break;
 979				}
 980
 981
 982				/* Hack -- Fix screen */
 983				if (show_list)
 984				{
 985					/* Load screen */
 986					screen_load();
 987
 988					/* Save screen */
 989					screen_save();
 990				}
 991
 992				/* Need to redraw */
 993				break;
 994			}
 995
 996			case '-':
 997			{
 998				/* Paranoia */
 999				if (!allow_floor)
1000				{
1001					bell("Cannot select floor!");
1002					break;
1003				}
1004
1005				/* There is only one item */
1006				if (floor_num == 1)
1007				{
1008					/* Auto-select */
1009					if (p_ptr->command_wrk == (USE_FLOOR))
1010					{
1011						/* Special index */
1012						k = 0 - floor_list[0];
1013
1014						/* Allow player to "refuse" certain actions */
1015						if (!get_item_allow(k, is_harmless))
1016						{
1017							done = TRUE;
1018							break;
1019						}
1020
1021						/* Accept that choice */
1022						(*cp) = k;
1023						item = TRUE;
1024						done = TRUE;
1025
1026						break;
1027					}
1028				}
1029
1030				/* Hack -- Fix screen */
1031				if (show_list)
1032				{
1033					/* Load screen */
1034					screen_load();
1035
1036					/* Save screen */
1037					screen_save();
1038				}
1039
1040				p_ptr->command_wrk = (USE_FLOOR);
1041
1042#if 0
1043				/* Check each legal object */
1044				for (i = 0; i < floor_num; ++i)
1045				{
1046					/* Special index */
1047					k = 0 - floor_list[i];
1048
1049					/* Skip non-okay objects */
1050					if (!get_item_okay(k)) continue;
1051
1052					/* Allow player to "refuse" certain actions */
1053					if (!get_item_allow(k)) continue;
1054
1055					/* Accept that choice */
1056					(*cp) = k;
1057					item = TRUE;
1058					done = TRUE;
1059					break;
1060				}
1061#endif
1062
1063				break;
1064			}
1065
1066			case '0':
1067			case '1': case '2': case '3':
1068			case '4': case '5': case '6':
1069			case '7': case '8': case '9':
1070			{
1071				/* Look up the tag */
1072				if (!get_tag(&k, which.key))
1073				{
1074					bell("Illegal object choice (tag)!");
1075					break;
1076				}
1077
1078				/* Hack -- Validate the item */
1079				if ((k < INVEN_WIELD) ? !allow_inven : !allow_equip)
1080				{
1081					bell("Illegal object choice (tag)!");
1082					break;
1083				}
1084
1085				/* Validate the item */
1086				if (!get_item_okay(k))
1087				{
1088					bell("Illegal object choice (tag)!");
1089					break;
1090				}
1091
1092				/* Allow player to "refuse" certain actions */
1093				if (!get_item_allow(k, is_harmless))
1094				{
1095					done = TRUE;
1096					break;
1097				}
1098
1099				/* Accept that choice */
1100				(*cp) = k;
1101				item = TRUE;
1102				done = TRUE;
1103				break;
1104			}
1105
1106			case '\n':
1107			case '\r':
1108			{
1109				/* Choose "default" inventory item */
1110				if (p_ptr->command_wrk == USE_INVEN)
1111				{
1112					if (i1 != i2)
1113					{
1114						bell("Illegal object choice (default)!");
1115						break;
1116					}
1117
1118					k = i1;
1119				}
1120
1121				/* Choose the "default" slot (0) of the quiver */
1122				else if(p_ptr->command_cmd == 'f')
1123					k = e1;
1124
1125				/* Choose "default" equipment item */
1126				else if (p_ptr->command_wrk == USE_EQUIP)
1127				{
1128					if (e1 != e2)
1129					{
1130						bell("Illegal object choice (default)!");
1131						break;
1132					}
1133
1134					k = e1;
1135				}
1136
1137				/* Choose "default" floor item */
1138				else
1139				{
1140					if (f1 != f2)
1141					{
1142						bell("Illegal object choice (default)!");
1143						break;
1144					}
1145
1146					k = 0 - floor_list[f1];
1147				}
1148
1149				/* Validate the item */
1150				if (!get_item_okay(k))
1151				{
1152					bell("Illegal object choice (default)!");
1153					break;
1154				}
1155
1156				/* Allow player to "refuse" certain actions */
1157				if (!get_item_allow(k, is_harmless))
1158				{
1159					done = TRUE;
1160					break;
1161				}
1162
1163				/* Accept that choice */
1164				(*cp) = k;
1165				item = TRUE;
1166				done = TRUE;
1167				break;
1168			}
1169
1170			case '!':
1171			{
1172				/* Try squelched items */
1173				if (can_squelch)
1174				{
1175					(*cp) = ALL_SQUELCHED;
1176					item = TRUE;
1177					done = TRUE;
1178					break;
1179				}
1180
1181				/* Just fall through */
1182			}
1183
1184			default:
1185			{
1186				bool verify;
1187
1188				/* Note verify */
1189				verify = (isupper((unsigned char)which.key) ? TRUE : FALSE);
1190
1191				/* Lowercase */
1192				which.key = tolower((unsigned char)which.key);
1193
1194				/* Convert letter to inventory index */
1195				if (p_ptr->command_wrk == USE_INVEN)
1196				{
1197					k = label_to_inven(which.key);
1198
1199					if (k < 0)
1200					{
1201						bell("Illegal object choice (inven)!");
1202						break;
1203					}
1204				}
1205
1206				/* Convert letter to equipment index */
1207				else if (p_ptr->command_wrk == USE_EQUIP)
1208				{
1209					k = label_to_equip(which.key);
1210
1211					if (k < 0)
1212					{
1213						bell("Illegal object choice (equip)!");
1214						break;
1215					}
1216				}
1217
1218				/* Convert letter to floor index */
1219				else
1220				{
1221					k = (islower((unsigned char)which.key) ? A2I(which.key) : -1);
1222
1223					if (k < 0 || k >= floor_num)
1224					{
1225						bell("Illegal object choice (floor)!");
1226						break;
1227					}
1228
1229					/* Special index */
1230					k = 0 - floor_list[k];
1231				}
1232
1233				/* Validate the item */
1234				if (!get_item_okay(k))
1235				{
1236					bell("Illegal object choice (normal)!");
1237					break;
1238				}
1239
1240				/* Verify the item */
1241				if (verify && !verify_item("Try", k))
1242				{
1243					done = TRUE;
1244					break;
1245				}
1246
1247				/* Allow player to "refuse" certain actions */
1248				if (!get_item_allow(k, is_harmless))
1249				{
1250					done = TRUE;
1251					break;
1252				}
1253
1254				/* Accept that choice */
1255				(*cp) = k;
1256				item = TRUE;
1257				done = TRUE;
1258				break;
1259			}
1260		}
1261	}
1262
1263
1264	/* Fix the screen if necessary */
1265	if (show_list)
1266	{
1267		/* Load screen */
1268		screen_load();
1269
1270		/* Hack -- Cancel "display" */
1271		show_list = FALSE;
1272	}
1273
1274
1275	/* Kill buttons */
1276	button_kill('*');
1277	button_kill('/');
1278	button_kill('-');
1279	button_kill('!');
1280	redraw_stuff();
1281 
1282	/* Forget the item_tester_tval restriction */
1283	item_tester_tval = 0;
1284
1285	/* Forget the item_tester_hook restriction */
1286	item_tester_hook = NULL;
1287
1288
1289	/* Toggle again if needed */
1290	if (toggle) toggle_inven_equip();
1291
1292	/* Update */
1293	p_ptr->redraw |= (PR_INVEN | PR_EQUIP);
1294	redraw_stuff();
1295
1296
1297	/* Clear the prompt line */
1298	prt("", 0, 0);
1299
1300	/* Warning if needed */
1301	if (oops && str) msg_print(str);
1302
1303	/* Result */
1304	return (item);
1305}
1306