1 /***************************************************************************
2
3 file : guiedit.cpp
4 created : Mon Apr 24 10:23:28 CEST 2000
5 copyright : (C) 2000-2014 by Eric Espie, Bernhard Wymann
6 email : torcs@free.fr
7 version : $Id: guiedit.cpp,v 1.2.2.6 2014/04/28 10:29:39 berniw Exp $
8
9 ***************************************************************************/
10
11 /***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20 /** @file
21 GUI Edit Box Management.
22 @author <a href=mailto:torcs@free.fr>Eric Espie</a>
23 @version $Id: guiedit.cpp,v 1.2.2.6 2014/04/28 10:29:39 berniw Exp $
24 @ingroup gui
25 */
26
27 #include <stdlib.h>
28 #ifdef WIN32
29 #include <windows.h>
30 #endif
31 #include <tgfclient.h>
32 #include "gui.h"
33 #include "guifont.h"
34
35 void
gfuiEditboxInit(void)36 gfuiEditboxInit(void)
37 {
38 }
39
40 /** Add a editbox to a screen.
41 @ingroup gui
42 @param scr Screen
43 @param text Editbox start text
44 @param font Font id
45 @param x X position on screen
46 @param y Y position on screen (0 = bottom)
47 @param width width of the editbox (0 = text size)
48 @param maxlen Max lenght of text (0 = text size)
49 @param userDataOnFocus Parameter to the Focus (and lost) callback
50 @param onFocus Focus callback function
51 @param onFocusLost Focus Lost callback function
52 @param margin Margin adjustment, default is 10 pixels
53 @return Editbox Id
54 <br>-1 Error
55 */
56 int
GfuiEditboxCreate(void * scr,const char * text,int font,int x,int y,int width,int maxlen,void * userDataOnFocus,tfuiCallback onFocus,tfuiCallback onFocusLost,int margin)57 GfuiEditboxCreate(void *scr, const char *text, int font, int x, int y, int width, int maxlen,
58 void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost, int margin)
59 {
60 tGfuiEditbox *editbox;
61 tGfuiLabel *label;
62 tGfuiObject *object;
63 tGfuiScreen *screen = (tGfuiScreen*)scr;
64
65
66 object = (tGfuiObject*)calloc(1, sizeof(tGfuiObject));
67 object->widget = GFUI_EDITBOX;
68 object->focusMode = GFUI_FOCUS_MOUSE_CLICK;
69 object->id = screen->curId++;
70 object->visible = 1;
71
72 editbox = &(object->u.editbox);
73 editbox->state = GFUI_BTN_RELEASED;
74 editbox->userDataOnFocus = userDataOnFocus;
75 editbox->onFocus = onFocus;
76 editbox->onFocusLost = onFocusLost;
77
78 editbox->bgColor[0] = &(GfuiColor[GFUI_BGBTNDISABLED][0]);
79 editbox->bgColor[1] = &(GfuiColor[GFUI_BGBTNENABLED][0]);
80 editbox->bgColor[2] = &(GfuiColor[GFUI_BGBTNCLICK][0]);
81 editbox->bgFocusColor[0] = &(GfuiColor[GFUI_BGBTNDISABLED][0]);
82 editbox->bgFocusColor[1] = &(GfuiColor[GFUI_BGBTNFOCUS][0]);
83 editbox->bgFocusColor[2] = &(GfuiColor[GFUI_BGBTNCLICK][0]);
84 editbox->fgColor[0] = &(GfuiColor[GFUI_BTNDISABLED][0]);
85 editbox->fgColor[1] = &(GfuiColor[GFUI_BTNENABLED][0]);
86 editbox->fgColor[2] = &(GfuiColor[GFUI_BTNCLICK][0]);
87 editbox->fgFocusColor[0] = &(GfuiColor[GFUI_BTNDISABLED][0]);
88 editbox->fgFocusColor[1] = &(GfuiColor[GFUI_BTNFOCUS][0]);
89 editbox->fgFocusColor[2] = &(GfuiColor[GFUI_BTNCLICK][0]);
90 editbox->cursorColor[0] = &(GfuiColor[GFUI_EDITCURSORCLR][0]);
91 editbox->cursorColor[1] = &(GfuiColor[GFUI_EDITCURSORCLR][1]);
92 editbox->cursorColor[2] = &(GfuiColor[GFUI_EDITCURSORCLR][2]);
93
94
95 label = &(editbox->label);
96 if (maxlen == 0) maxlen = strlen(text);
97 label->text = (char*)calloc(1, maxlen+1);
98 strncpy(label->text, text, maxlen);
99 label->text[maxlen] = '\0';
100 label->font = gfuiFont[font];
101 label->maxlen = maxlen;
102
103 if (width == 0) {
104 char *buf;
105 int i;
106 buf = (char*)malloc(maxlen+1);
107 if (buf == NULL) return -1; // Memory leak does not matter, this must not happen
108 for (i = 0; i < maxlen; i++) buf[i] = 'W';
109 buf[i] = '\0';
110 width = gfuiFont[font]->getWidth((const char *)buf);
111 free(buf);
112 }
113
114 label->align = GFUI_ALIGN_HL_VC;
115 label->x = object->xmin = x;
116 label->y = y - 2 * gfuiFont[font]->getDescender();
117 object->ymin = y;
118 object->xmax = x + width;
119 object->ymax = y + gfuiFont[font]->getHeight() - gfuiFont[font]->getDescender();
120 editbox->cursory1 = object->ymin + 2;
121 editbox->cursory2 = object->ymax - 2;
122 editbox->cursorx = label->x;
123
124 object->xmin -= margin;
125 object->xmax += margin;
126
127 gfuiAddObject(screen, object);
128 return object->id;
129 }
130
131
132 /** Get the Id of the editbox focused in the current screen.
133 @ingroup gui
134 @return Editbox Id
135 <br>-1 if no editbox or no screen or the focus is not on a editbox
136 */
137 int
GfuiEditboxGetFocused(void)138 GfuiEditboxGetFocused(void)
139 {
140 tGfuiObject *curObject;
141
142 if (GfuiScreen != NULL) {
143 curObject = GfuiScreen->objects;
144 if (curObject != NULL) {
145 do {
146 curObject = curObject->next;
147 if (curObject->focus) {
148 if (curObject->widget == GFUI_EDITBOX) {
149 return curObject->id;
150 }
151 return -1;
152 }
153 } while (curObject != GfuiScreen->objects);
154 }
155 }
156 return -1;
157 }
158
159
160 void
gfuiDrawEditbox(tGfuiObject * obj)161 gfuiDrawEditbox(tGfuiObject *obj)
162 {
163 tGfuiLabel *label;
164 tGfuiEditbox *editbox;
165 float *fgColor;
166 float *bgColor;
167
168 editbox = &(obj->u.editbox);
169 if (obj->state == GFUI_DISABLE) {
170 editbox->state = GFUI_BTN_DISABLE;
171 } else {
172 editbox->state = GFUI_BTN_RELEASED;
173 }
174 if (obj->focus) {
175 fgColor = editbox->fgFocusColor[editbox->state];
176 bgColor = editbox->bgFocusColor[editbox->state];
177 } else {
178 fgColor = editbox->fgColor[editbox->state];
179 bgColor = editbox->bgColor[editbox->state];
180 }
181
182 glColor4fv(bgColor);
183 glBegin(GL_QUADS);
184 glVertex2i(obj->xmin, obj->ymin);
185 glVertex2i(obj->xmin, obj->ymax);
186 glVertex2i(obj->xmax, obj->ymax);
187 glVertex2i(obj->xmax, obj->ymin);
188 glEnd();
189
190 glColor4fv(fgColor);
191 glBegin(GL_LINE_STRIP);
192 glVertex2i(obj->xmin, obj->ymin);
193 glVertex2i(obj->xmin, obj->ymax);
194 glVertex2i(obj->xmax, obj->ymax);
195 glVertex2i(obj->xmax, obj->ymin);
196 glVertex2i(obj->xmin, obj->ymin);
197 glEnd();
198
199 label = &(editbox->label);
200 glColor4fv(fgColor);
201 gfuiPrintString(label->x, label->y, label->font, label->text);
202
203 if ((obj->state != GFUI_DISABLE) && (obj->focus)) {
204 /* draw cursor */
205 glColor3fv(editbox->cursorColor[editbox->state]);
206 glBegin(GL_LINES);
207 glVertex2i(editbox->cursorx, editbox->cursory1);
208 glVertex2i(editbox->cursorx, editbox->cursory2);
209 glEnd();
210 }
211 }
212
213
214 void
gfuiEditboxAction(int mouse)215 gfuiEditboxAction(int mouse)
216 {
217 tGfuiObject *object;
218 tGfuiLabel *label;
219 tGfuiEditbox *editbox;
220 int relX;
221 char buf[256];
222 uint i;
223
224 object = GfuiScreen->hasFocus;
225 if (object->state == GFUI_DISABLE) {
226 return;
227 }
228
229 if (mouse == 2) { /* enter key */
230 gfuiSelectNext(GfuiScreen);
231 } else if (mouse == 0) { /* mouse down */
232 editbox = &(object->u.editbox);
233 label = &(editbox->label);
234 /* Set the cursor position */
235 relX = GfuiMouse.X - label->x;
236 for (i = 0; i < strlen(label->text); i++){
237 buf[i] = label->text[i];
238 buf[i+1] = '\0';
239 if (relX < label->font->getWidth((const char *)buf)) {
240 break;
241 }
242 }
243 editbox->cursorIdx = i;
244 if (i == 0) {
245 editbox->cursorx = label->x;
246 } else {
247 buf[i] = '\0';
248 editbox->cursorx = label->x + label->font->getWidth((const char *)buf);
249 }
250 }
251 }
252
253 /* recalc cursorx with cursorIdx */
254 static void
gfuiEditboxRecalcCursor(tGfuiObject * obj)255 gfuiEditboxRecalcCursor(tGfuiObject *obj)
256 {
257 char buf[256];
258 tGfuiEditbox *editbox;
259 tGfuiLabel *label;
260
261 editbox = &(obj->u.editbox);
262 label = &(editbox->label);
263 strncpy(buf, label->text, editbox->cursorIdx);
264 buf[editbox->cursorIdx] = '\0';
265 editbox->cursorx = label->x + label->font->getWidth((const char *)buf);
266 }
267
268
269 void
gfuiEditboxKey(tGfuiObject * obj,int key,int modifier)270 gfuiEditboxKey(tGfuiObject *obj, int key, int modifier)
271 {
272 tGfuiEditbox *editbox;
273 tGfuiLabel *label;
274 char *p1, *p2;
275 int i1, i2;
276
277 if (obj->state == GFUI_DISABLE) {
278 return;
279 }
280
281 editbox = &(obj->u.editbox);
282 label = &(editbox->label);
283
284 switch (modifier) {
285 case 0:
286 case GLUT_ACTIVE_SHIFT:
287 switch (key) {
288 case 256 + GLUT_KEY_RIGHT:
289 editbox->cursorIdx++;
290 if (editbox->cursorIdx > (int)strlen(label->text)) {
291 editbox->cursorIdx--;
292 }
293 break;
294 case 256 + GLUT_KEY_LEFT:
295 editbox->cursorIdx--;
296 if (editbox->cursorIdx < 0) {
297 editbox->cursorIdx = 0;
298 }
299 break;
300 case 256 + GLUT_KEY_HOME:
301 editbox->cursorIdx = 0;
302 break;
303 case 256 + GLUT_KEY_END:
304 editbox->cursorIdx = (int)strlen(label->text);
305 break;
306 case 0x7F : /* DEL */
307 if (editbox->cursorIdx < (int)strlen(label->text)) {
308 p1 = &(label->text[editbox->cursorIdx]);
309 p2 = &(label->text[editbox->cursorIdx+1]);
310 while ( *p1 != '\0' ) {
311 *p1++ = *p2++;
312 }
313 }
314 break;
315 case '\b' : /* Backspace */
316 if (editbox->cursorIdx > 0) {
317 p1 = &(label->text[editbox->cursorIdx-1]);
318 p2 = &(label->text[editbox->cursorIdx]);
319 while ( *p1 != '\0' ) {
320 *p1++ = *p2++;
321 }
322 editbox->cursorIdx--;
323 }
324 break;
325 }
326 if (key >= ' ' && key < 127) {
327 if ((int)strlen(label->text) < label->maxlen) {
328 i2 = (int)strlen(label->text) + 1;
329 i1 = i2 - 1;
330 while (i2 > editbox->cursorIdx) {
331 label->text[i2] = label->text[i1];
332 i1--;
333 i2--;
334 }
335 label->text[editbox->cursorIdx] = key;
336 editbox->cursorIdx++;
337 }
338 }
339 break;
340
341 case GLUT_ACTIVE_CTRL:
342 break;
343
344 case GLUT_ACTIVE_ALT:
345 break;
346 }
347
348 gfuiEditboxRecalcCursor(obj);
349 }
350
351 /** Get the string
352 @ingroup gui
353 @param scr Screen
354 @param id Edit box Id
355 @return Corresponding string.
356 */
357 char *
GfuiEditboxGetString(void * scr,int id)358 GfuiEditboxGetString(void *scr, int id)
359 {
360 tGfuiObject *curObject;
361 tGfuiEditbox *editbox;
362 tGfuiLabel *label;
363
364 curObject = gfuiGetObject(scr, id);
365
366 if ((curObject == NULL) || (curObject->widget != GFUI_EDITBOX)) {
367 return (char*)NULL;
368 }
369
370 editbox = &(curObject->u.editbox);
371 label = &(editbox->label);
372
373 return label->text;
374 }
375
376 /** Set a new string.
377 @ingroup gui
378 @param scr Screen
379 @param id Edit box Id
380 @param text text to set
381 @return none
382 */
GfuiEditboxSetString(void * scr,int id,const char * text)383 void GfuiEditboxSetString(void *scr, int id, const char *text)
384 {
385 tGfuiObject *curObject;
386 tGfuiEditbox *editbox;
387 tGfuiLabel *label;
388
389 curObject = gfuiGetObject(scr, id);
390
391 if ((curObject == NULL) || (curObject->widget != GFUI_EDITBOX)) {
392 return;
393 }
394
395 editbox = &(curObject->u.editbox);
396 label = &(editbox->label);
397
398 strncpy(label->text, text, label->maxlen);
399 label->text[label->maxlen] = '\0';
400 }
401
402
403 void
gfuiReleaseEditbox(tGfuiObject * curObject)404 gfuiReleaseEditbox(tGfuiObject *curObject)
405 {
406 tGfuiEditbox *editbox;
407 tGfuiLabel *label;
408
409 editbox = &(curObject->u.editbox);
410 label = &(editbox->label);
411 free(label->text);
412 free(curObject);
413 }
414
415