Quake II RTX doxygen  1.0 dev
field.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2003-2006 Andrey Nazarov
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 //
20 // field.c
21 //
22 
23 #include "shared/shared.h"
24 #include "common/common.h"
25 #include "common/field.h"
26 #include "client/client.h"
27 #include "client/keys.h"
28 #include "client/video.h"
29 #include "refresh/refresh.h"
30 
31 /*
32 ================
33 IF_Init
34 ================
35 */
36 void IF_Init(inputField_t *field, size_t visibleChars, size_t maxChars)
37 {
38  memset(field, 0, sizeof(*field));
39 
40  if (maxChars >= sizeof(field->text)) {
41  maxChars = sizeof(field->text) - 1;
42  }
43  if (visibleChars > maxChars) {
44  visibleChars = maxChars;
45  }
46 
47  field->maxChars = maxChars;
48  field->visibleChars = visibleChars;
49 }
50 
51 /*
52 ================
53 IF_Clear
54 ================
55 */
56 void IF_Clear(inputField_t *field)
57 {
58  memset(field->text, 0, sizeof(field->text));
59  field->cursorPos = 0;
60 }
61 
62 /*
63 ================
64 IF_Replace
65 ================
66 */
67 void IF_Replace(inputField_t *field, const char *text)
68 {
69  if (field->maxChars && text) {
70  size_t len = Q_strlcpy(field->text, text, field->maxChars + 1);
71  field->cursorPos = len >= field->maxChars ? field->maxChars - 1 : len;
72  } else {
73  field->text[0] = 0;
74  field->cursorPos = 0;
75  }
76 }
77 
78 #if USE_CLIENT
79 
80 /*
81 ================
82 IF_KeyEvent
83 ================
84 */
85 qboolean IF_KeyEvent(inputField_t *field, int key)
86 {
87  if (!field->maxChars) {
88  return qfalse;
89  }
90  if (field->cursorPos >= field->maxChars) {
91  Com_Error(ERR_FATAL, "%s: bad cursorPos", __func__);
92  }
93 
94  if (key == K_DEL) {
95  if (field->text[field->cursorPos]) {
96  memmove(field->text + field->cursorPos,
97  field->text + field->cursorPos + 1,
98  sizeof(field->text) - field->cursorPos);
99  }
100  return qtrue;
101  }
102 
103  if (key == K_BACKSPACE || (key == 'h' && Key_IsDown(K_CTRL))) {
104  if (field->cursorPos > 0) {
105  memmove(field->text + field->cursorPos - 1,
106  field->text + field->cursorPos,
107  sizeof(field->text) - field->cursorPos);
108  field->cursorPos--;
109  }
110  return qtrue;
111  }
112 
113  if (key == 'w' && Key_IsDown(K_CTRL)) {
114  size_t oldpos = field->cursorPos;
115 
116  // kill trailing whitespace
117  while (field->cursorPos > 0 && field->text[field->cursorPos] <= 32) {
118  field->cursorPos--;
119  }
120 
121  // kill this word
122  while (field->cursorPos > 0 && field->text[field->cursorPos - 1] > 32) {
123  field->cursorPos--;
124  }
125  memmove(field->text + field->cursorPos, field->text + oldpos,
126  sizeof(field->text) - oldpos);
127  return qtrue;
128  }
129 
130  if (key == 'u' && Key_IsDown(K_CTRL)) {
131  memmove(field->text, field->text + field->cursorPos,
132  sizeof(field->text) - field->cursorPos);
133  field->cursorPos = 0;
134  return qtrue;
135  }
136 
137  if (key == 'k' && Key_IsDown(K_CTRL)) {
138  field->text[field->cursorPos] = 0;
139  return qtrue;
140  }
141 
142  if (key == 'c' && Key_IsDown(K_CTRL)) {
143  VID_SetClipboardData(field->text);
144  return qtrue;
145  }
146 
147  if (key == K_LEFTARROW || (key == 'b' && Key_IsDown(K_CTRL))) {
148  if (field->cursorPos > 0) {
149  field->cursorPos--;
150  }
151  return qtrue;
152  }
153 
154  if (key == K_RIGHTARROW || (key == 'f' && Key_IsDown(K_CTRL))) {
155  if (field->text[field->cursorPos]) {
156  field->cursorPos++;
157  }
158  goto check;
159  }
160 
161  if (key == 'b' && Key_IsDown(K_ALT)) {
162  if (field->cursorPos > 0 && field->text[field->cursorPos - 1] <= 32) {
163  field->cursorPos--;
164  }
165  while (field->cursorPos > 0 && field->text[field->cursorPos] <= 32) {
166  field->cursorPos--;
167  }
168  while (field->cursorPos > 0 && field->text[field->cursorPos - 1] > 32) {
169  field->cursorPos--;
170  }
171  return qtrue;
172  }
173 
174  if (key == 'f' && Key_IsDown(K_ALT)) {
175  while (field->text[field->cursorPos] && field->text[field->cursorPos] <= 32) {
176  field->cursorPos++;
177  }
178  while (field->text[field->cursorPos] > 32) {
179  field->cursorPos++;
180  }
181  goto check;
182  }
183 
184  if (key == K_HOME || (key == 'a' && Key_IsDown(K_CTRL))) {
185  field->cursorPos = 0;
186  return qtrue;
187  }
188 
189  if (key == K_END || (key == 'e' && Key_IsDown(K_CTRL))) {
190  field->cursorPos = strlen(field->text);
191  goto check;
192  }
193 
194  if (key == K_INS) {
196  return qtrue;
197  }
198 
199  return qfalse;
200 
201 check:
202  if (field->cursorPos >= field->maxChars) {
203  field->cursorPos = field->maxChars - 1;
204  }
205 
206  return qtrue;
207 }
208 
209 /*
210 ================
211 IF_CharEvent
212 ================
213 */
214 qboolean IF_CharEvent(inputField_t *field, int key)
215 {
216  if (!field->maxChars) {
217  return qfalse;
218  }
219  if (field->cursorPos >= field->maxChars) {
220  Com_Error(ERR_FATAL, "%s: bad cursorPos", __func__);
221  }
222 
223  if (key < 32 || key > 127) {
224  return qfalse; // non printable
225  }
226 
227  if (field->cursorPos == field->maxChars - 1) {
228  // buffer limit was reached, just replace the last character
229  field->text[field->cursorPos] = key;
230  return qtrue;
231  }
232 
233  if (Key_GetOverstrikeMode()) {
234  // replace the character at cursor and advance
235  field->text[field->cursorPos++] = key;
236  return qtrue;
237  }
238 
239  // insert new character at cursor position
240  memmove(field->text + field->cursorPos + 1,
241  field->text + field->cursorPos,
242  sizeof(field->text) - field->cursorPos - 1);
243  field->text[field->cursorPos++] = key;
244 
245  return qtrue;
246 }
247 
248 /*
249 ================
250 IF_Draw
251 
252 The input line scrolls horizontally if typing goes beyond the right edge.
253 Returns x offset of the rightmost character drawn.
254 ================
255 */
256 int IF_Draw(inputField_t *field, int x, int y, int flags, qhandle_t font)
257 {
258  char *text = field->text;
259  size_t cursorPos = field->cursorPos;
260  size_t offset = 0;
261  int ret;
262 
263  if (!field->maxChars || !field->visibleChars) {
264  return 0;
265  }
266 
267  if (cursorPos >= field->maxChars) {
268  Com_Error(ERR_FATAL, "%s: bad cursorPos", __func__);
269  }
270 
271  // scroll horizontally
272  if (cursorPos >= field->visibleChars) {
273  cursorPos = field->visibleChars - 1;
274  offset = field->cursorPos - cursorPos;
275  }
276 
277  // draw text
278  ret = R_DrawString(x, y, flags, field->visibleChars, text + offset, font);
279 
280  if (flags & UI_DRAWCURSOR) {
281  // draw blinking cursor
282  if ((com_localTime >> 8) & 1) {
283  int c = Key_GetOverstrikeMode() ? 11 : '_';
284  R_DrawChar(x + cursorPos * CHAR_WIDTH, y, flags, c, font);
285  }
286  }
287 
288  return ret;
289 }
290 
291 #endif
Key_SetOverstrikeMode
void Key_SetOverstrikeMode(qboolean overstrike)
Definition: keys.c:158
Key_GetOverstrikeMode
qboolean Key_GetOverstrikeMode(void)
Definition: keys.c:148
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
Key_IsDown
int Key_IsDown(int key)
Definition: keys.c:204
R_DrawString
int(* R_DrawString)(int x, int y, int flags, size_t maxChars, const char *string, qhandle_t font)
Definition: refresh.c:417
Q_strlcpy
size_t Q_strlcpy(char *dst, const char *src, size_t size)
Definition: shared.c:715
IF_Replace
void IF_Replace(inputField_t *field, const char *text)
Definition: field.c:67
com_localTime
unsigned com_localTime
Definition: common.c:123
c
statCounters_t c
Definition: main.c:30
IF_Clear
void IF_Clear(inputField_t *field)
Definition: field.c:56
client.h
VID_SetClipboardData
void VID_SetClipboardData(const char *data)
Definition: client.c:1354
R_DrawChar
void(* R_DrawChar)(int x, int y, int flags, int ch, qhandle_t font)
Definition: refresh.c:416
IF_Init
void IF_Init(inputField_t *field, size_t visibleChars, size_t maxChars)
Definition: field.c:36