/src/button.c

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