/src/button.c
C | 280 lines | 127 code | 57 blank | 96 comment | 20 complexity | 2c87b08343840a2e06ba82f05ff5e320 MD5 | raw file
1/* 2 * File: mouse.c 3 * Purpose: Mousebutton handling code 4 * 5 * Copyright (c) 2007 Nick McConnell 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 20 21/*** Constants ***/ 22 23/** 24 * Maximum number of mouse buttons 25 */ 26#define MAX_MOUSE_BUTTONS 20 27 28/** 29 * Maximum length of a mouse button label 30 */ 31#define MAX_MOUSE_LABEL 10 32 33 34/*** Types ***/ 35 36/** 37 * Mouse button structure 38 */ 39typedef struct 40{ 41 char label[MAX_MOUSE_LABEL]; /*!< Label on the button */ 42 int left; /*!< Column containing the left edge of the button */ 43 int right; /*!< Column containing the right edge of the button */ 44 unsigned char key; /*!< Keypress corresponding to the button */ 45} button_mouse; 46 47 48 49/*** Variables ***/ 50 51static button_mouse *button_mse; 52static button_mouse *button_backup; 53 54static int button_start; 55static int button_length; 56static int button_num; 57 58 59/* 60 * Hooks for making and unmaking buttons 61 */ 62button_add_f button_add_hook; 63button_kill_f button_kill_hook; 64 65 66 67/*** Code ***/ 68 69/* 70 * The mousebutton code. Buttons should be created when neccessary and 71 * destroyed when no longer necessary. By default, buttons occupy the section 72 * of the bottom line between the status display and the location display 73 * in normal screen mode, and the bottom line after any prompt in alternate 74 * screen mode. 75 * 76 * Individual ports may (and preferably will) handle this differently using 77 * button_add_gui and button_kill_gui. 78 */ 79 80/* 81 * Add a button 82 */ 83int button_add_text(const char *label, unsigned char keypress) 84{ 85 int i; 86 int length = strlen(label); 87 88 /* Check the label length */ 89 if (length > MAX_MOUSE_LABEL) 90 { 91 bell("Label too long - button abandoned!"); 92 return 0; 93 } 94 95 /* Check we haven't already got a button for this keypress */ 96 for (i = 0; i < button_num; i++) 97 if (button_mse[i].key == keypress) 98 return 0; 99 100 /* Make the button */ 101 button_length += length; 102 my_strcpy(button_mse[button_num].label, label, MAX_MOUSE_LABEL); 103 button_mse[button_num].left = button_length - length + 1; 104 button_mse[button_num].right = button_length; 105 button_mse[button_num++].key = keypress; 106 107 /* Redraw */ 108 p_ptr->redraw |= (PR_BUTTONS); 109 110 /* Return the size of the button */ 111 return (length); 112} 113 114/* 115 * Add a button 116 */ 117int button_add(const char *label, unsigned char keypress) 118{ 119 if (!button_add_hook) 120 return 0; 121 else 122 return (*button_add_hook) (label, keypress); 123} 124 125/* 126 * Make a backup of the current buttons 127 */ 128void button_backup_all(void) 129{ 130 /* Check we haven't already done this */ 131 if (button_backup[0].key) return; 132 133 /* Straight memory copy */ 134 (void)C_COPY(button_backup, button_mse, MAX_MOUSE_BUTTONS, button_mouse); 135} 136 137 138/* 139 * Restore the buttons from backup 140 */ 141void button_restore(void) 142{ 143 int i = 0; 144 145 /* Remove the current lot */ 146 button_kill_all(); 147 148 /* Get all the previous buttons, copy them back */ 149 while (button_backup[i].key) 150 { 151 /* Add them all back, forget the backups */ 152 button_add(button_backup[i].label, button_backup[i].key); 153 button_backup[i].key = '\0'; 154 i++; 155 } 156} 157 158 159/* 160 * Remove a button 161 */ 162int button_kill_text(unsigned char keypress) 163{ 164 int i, j, length; 165 166 /* Find the button */ 167 for (i = 0; i < button_num; i++) 168 if (button_mse[i].key == keypress) break; 169 170 /* No such button */ 171 if (i == button_num) 172 { 173 return 0; 174 } 175 176 /* Find the length */ 177 length = button_mse[i].right - button_mse[i].left + 1; 178 button_length -= length; 179 180 /* Move each button up one */ 181 for (j = i; j < button_num - 1; j++) 182 { 183 button_mse[j] = button_mse[j + 1]; 184 185 /* Adjust length */ 186 button_mse[j].left -= length; 187 button_mse[j].right -= length; 188 } 189 190 /* Wipe the data */ 191 button_mse[button_num].label[0] = '\0'; 192 button_mse[button_num].left = 0; 193 button_mse[button_num].right = 0; 194 button_mse[button_num--].key = 0; 195 196 /* Redraw */ 197 p_ptr->redraw |= (PR_BUTTONS); 198 redraw_stuff(); 199 200 /* Return the size of the button */ 201 return (length); 202} 203 204/* 205 * Kill a button 206 */ 207int button_kill(unsigned char keypress) 208{ 209 if (!button_kill_hook) return 0; 210 else 211 return (*button_kill_hook) (keypress); 212} 213 214/* 215 * Kill all buttons 216 */ 217void button_kill_all(void) 218{ 219 int i; 220 221 /* Paranoia */ 222 if (!button_kill_hook) return; 223 224 /* One by one */ 225 for (i = button_num - 1; i >= 0; i--) 226 (void)(*button_kill_hook) (button_mse[i].key); 227} 228 229 230/* 231 * Initialise buttons. 232 */ 233void button_init(button_add_f add, button_kill_f kill) 234{ 235 /* Prepare mouse button arrays */ 236 button_mse = C_ZNEW(MAX_MOUSE_BUTTONS, button_mouse); 237 button_backup = C_ZNEW(MAX_MOUSE_BUTTONS, button_mouse); 238 239 /* Initialise the hooks */ 240 button_add_hook = add; 241 button_kill_hook = kill; 242} 243 244 245/** 246 * Return the character represented by a button at screen position (x, y), 247 * or 0. 248 */ 249char button_get_key(int x, int y) 250{ 251 int i; 252 253 for (i = 0; i < button_num; i++) 254 { 255 if ((y == Term->hgt - 1) && 256 (x >= button_start + button_mse[i].left) && 257 (x <= button_start + button_mse[i].right)) 258 { 259 return button_mse[i].key; 260 } 261 } 262 263 return 0; 264} 265 266/** 267 * Print the current button list at the specified `row` and `col`umn. 268 */ 269size_t button_print(int row, int col) 270{ 271 int j; 272 273 button_start = col; 274 275 for (j = 0; j < button_num; j++) 276 c_put_str(TERM_SLATE, button_mse[j].label, row, col + button_mse[j].left); 277 278 return button_length; 279} 280