/*************************************************************************** file : guiedit.cpp created : Mon Apr 24 10:23:28 CEST 2000 copyright : (C) 2000 by Eric Espie email : torcs@free.fr version : $Id: guiedit.cpp,v 1.2 2003/06/24 21:02:25 torcs Exp $ ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** @file GUI Edit Box Management. @author Eric Espie @version $Id: guiedit.cpp,v 1.2 2003/06/24 21:02:25 torcs Exp $ @ingroup gui */ #include #include #ifdef WIN32 #include #endif #include #include "gui.h" #include "guifont.h" void gfuiEditboxInit(void) { } /** Add a editbox to a screen. @ingroup gui @param scr Screen @param text Editbox start text @param font Font id @param x X position on screen @param y Y position on screen (0 = bottom) @param width width of the editbox (0 = text size) @param maxlen Max lenght of text (0 = text size) @param userDataOnFocus Parameter to the Focus (and lost) callback @param onFocus Focus callback function @param onFocusLost Focus Lost callback function @return Editbox Id
-1 Error */ int GfuiEditboxCreate(void *scr, char *text, int font, int x, int y, int width, int maxlen, void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost) { tGfuiEditbox *editbox; tGfuiLabel *label; tGfuiObject *object; tGfuiScreen *screen = (tGfuiScreen*)scr; object = (tGfuiObject*)calloc(1, sizeof(tGfuiObject)); object->widget = GFUI_EDITBOX; object->focusMode = GFUI_FOCUS_MOUSE_CLICK; object->id = screen->curId++; object->visible = 1; editbox = &(object->u.editbox); editbox->state = GFUI_BTN_RELEASED; editbox->userDataOnFocus = userDataOnFocus; editbox->onFocus = onFocus; editbox->onFocusLost = onFocusLost; editbox->bgColor[0] = &(GfuiColor[GFUI_BGBTNDISABLED][0]); editbox->bgColor[1] = &(GfuiColor[GFUI_BGBTNENABLED][0]); editbox->bgColor[2] = &(GfuiColor[GFUI_BGBTNCLICK][0]); editbox->bgFocusColor[0] = &(GfuiColor[GFUI_BGBTNDISABLED][0]); editbox->bgFocusColor[1] = &(GfuiColor[GFUI_BGBTNFOCUS][0]); editbox->bgFocusColor[2] = &(GfuiColor[GFUI_BGBTNCLICK][0]); editbox->fgColor[0] = &(GfuiColor[GFUI_BTNDISABLED][0]); editbox->fgColor[1] = &(GfuiColor[GFUI_BTNENABLED][0]); editbox->fgColor[2] = &(GfuiColor[GFUI_BTNCLICK][0]); editbox->fgFocusColor[0] = &(GfuiColor[GFUI_BTNDISABLED][0]); editbox->fgFocusColor[1] = &(GfuiColor[GFUI_BTNFOCUS][0]); editbox->fgFocusColor[2] = &(GfuiColor[GFUI_BTNCLICK][0]); editbox->cursorColor[0] = &(GfuiColor[GFUI_EDITCURSORCLR][0]); editbox->cursorColor[1] = &(GfuiColor[GFUI_EDITCURSORCLR][1]); editbox->cursorColor[2] = &(GfuiColor[GFUI_EDITCURSORCLR][2]); label = &(editbox->label); if (maxlen == 0) maxlen = strlen(text); label->text = (char*)calloc(1, maxlen+1); strncpy(label->text, text, maxlen+1); label->font = gfuiFont[font]; label->maxlen = maxlen; if (width == 0) { char *buf; int i; buf = (char*)malloc(maxlen+1); if (buf == NULL) return -1; for (i = 0; i < maxlen; i++) buf[i] = 'W'; buf[i] = '\0'; width = gfuiFont[font]->getWidth((const char *)buf); free(buf); } label->align = GFUI_ALIGN_HL_VC; label->x = object->xmin = x; label->y = y - 2 * gfuiFont[font]->getDescender(); object->ymin = y; object->xmax = x + width; object->ymax = y + gfuiFont[font]->getHeight() - gfuiFont[font]->getDescender(); editbox->cursory1 = object->ymin + 2; editbox->cursory2 = object->ymax - 2; editbox->cursorx = label->x; #define HORIZ_MARGIN 10 object->xmin -= HORIZ_MARGIN; object->xmax += HORIZ_MARGIN; gfuiAddObject(screen, object); return object->id; } /** Get the Id of the editbox focused in the current screen. @ingroup gui @return Editbox Id
-1 if no editbox or no screen or the focus is not on a editbox */ int GfuiEditboxGetFocused(void) { tGfuiObject *curObject; if (GfuiScreen != NULL) { curObject = GfuiScreen->objects; if (curObject != NULL) { do { curObject = curObject->next; if (curObject->focus) { if (curObject->widget == GFUI_EDITBOX) { return curObject->id; } return -1; } } while (curObject != GfuiScreen->objects); } } return -1; } void gfuiDrawEditbox(tGfuiObject *obj) { tGfuiLabel *label; tGfuiEditbox *editbox; float *fgColor; float *bgColor; editbox = &(obj->u.editbox); if (obj->state == GFUI_DISABLE) { editbox->state = GFUI_BTN_DISABLE; } else { editbox->state = GFUI_BTN_RELEASED; } if (obj->focus) { fgColor = editbox->fgFocusColor[editbox->state]; bgColor = editbox->bgFocusColor[editbox->state]; } else { fgColor = editbox->fgColor[editbox->state]; bgColor = editbox->bgColor[editbox->state]; } glColor4fv(bgColor); glBegin(GL_QUADS); glVertex2i(obj->xmin, obj->ymin); glVertex2i(obj->xmin, obj->ymax); glVertex2i(obj->xmax, obj->ymax); glVertex2i(obj->xmax, obj->ymin); glEnd(); glColor4fv(fgColor); glBegin(GL_LINE_STRIP); glVertex2i(obj->xmin, obj->ymin); glVertex2i(obj->xmin, obj->ymax); glVertex2i(obj->xmax, obj->ymax); glVertex2i(obj->xmax, obj->ymin); glVertex2i(obj->xmin, obj->ymin); glEnd(); label = &(editbox->label); glColor4fv(fgColor); gfuiPrintString(label->x, label->y, label->font, label->text); if ((obj->state != GFUI_DISABLE) && (obj->focus)) { /* draw cursor */ glColor3fv(editbox->cursorColor[editbox->state]); glBegin(GL_LINES); glVertex2i(editbox->cursorx, editbox->cursory1); glVertex2i(editbox->cursorx, editbox->cursory2); glEnd(); } } void gfuiEditboxAction(int mouse) { tGfuiObject *object; tGfuiLabel *label; tGfuiEditbox *editbox; int relX; char buf[256]; uint i; object = GfuiScreen->hasFocus; if (object->state == GFUI_DISABLE) { return; } if (mouse == 2) { /* enter key */ gfuiSelectNext(GfuiScreen); } else if (mouse == 0) { /* mouse down */ editbox = &(object->u.editbox); label = &(editbox->label); /* Set the cursor position */ relX = GfuiMouse.X - label->x; for (i = 0; i < strlen(label->text); i++){ buf[i] = label->text[i]; buf[i+1] = '\0'; if (relX < label->font->getWidth((const char *)buf)) { break; } } editbox->cursorIdx = i; if (i == 0) { editbox->cursorx = label->x; } else { buf[i] = '\0'; editbox->cursorx = label->x + label->font->getWidth((const char *)buf); } } } /* recalc cursorx with cursorIdx */ static void gfuiEditboxRecalcCursor(tGfuiObject *obj) { char buf[256]; tGfuiEditbox *editbox; tGfuiLabel *label; editbox = &(obj->u.editbox); label = &(editbox->label); strncpy(buf, label->text, editbox->cursorIdx); buf[editbox->cursorIdx] = '\0'; editbox->cursorx = label->x + label->font->getWidth((const char *)buf); } void gfuiEditboxKey(tGfuiObject *obj, int key, int modifier) { tGfuiEditbox *editbox; tGfuiLabel *label; char *p1, *p2; int i1, i2; if (obj->state == GFUI_DISABLE) { return; } editbox = &(obj->u.editbox); label = &(editbox->label); switch (modifier) { case 0: case GLUT_ACTIVE_SHIFT: switch (key) { case 256 + GLUT_KEY_RIGHT: editbox->cursorIdx++; if (editbox->cursorIdx > (int)strlen(label->text)) { editbox->cursorIdx--; } break; case 256 + GLUT_KEY_LEFT: editbox->cursorIdx--; if (editbox->cursorIdx < 0) { editbox->cursorIdx = 0; } break; case 256 + GLUT_KEY_HOME: editbox->cursorIdx = 0; break; case 256 + GLUT_KEY_END: editbox->cursorIdx = (int)strlen(label->text); break; case 0x7F : /* DEL */ if (editbox->cursorIdx < (int)strlen(label->text)) { p1 = &(label->text[editbox->cursorIdx]); p2 = &(label->text[editbox->cursorIdx+1]); while ( *p1 != '\0' ) { *p1++ = *p2++; } } break; case '\b' : /* Backspace */ if (editbox->cursorIdx > 0) { p1 = &(label->text[editbox->cursorIdx-1]); p2 = &(label->text[editbox->cursorIdx]); while ( *p1 != '\0' ) { *p1++ = *p2++; } editbox->cursorIdx--; } break; } if (key >= ' ' && key < 127) { if ((int)strlen(label->text) < label->maxlen) { i2 = (int)strlen(label->text) + 1; i1 = i2 - 1; while (i2 > editbox->cursorIdx) { label->text[i2] = label->text[i1]; i1--; i2--; } label->text[editbox->cursorIdx] = key; editbox->cursorIdx++; } } break; case GLUT_ACTIVE_CTRL: break; case GLUT_ACTIVE_ALT: break; } gfuiEditboxRecalcCursor(obj); } /** Get the string @ingroup gui @param scr Screen @param id Edit box Id @return Corresponding string. */ char * GfuiEditboxGetString(void *scr, int id) { tGfuiObject *curObject; tGfuiEditbox *editbox; tGfuiLabel *label; curObject = gfuiGetObject(scr, id); if ((curObject == NULL) || (curObject->widget != GFUI_EDITBOX)) { return (char*)NULL; } editbox = &(curObject->u.editbox); label = &(editbox->label); return label->text; } /** Set a new string. @ingroup gui @param scr Screen @param id Edit box Id @param text text to set @return none */ void GfuiEditboxSetString(void *scr, int id, char *text) { tGfuiObject *curObject; tGfuiEditbox *editbox; tGfuiLabel *label; curObject = gfuiGetObject(scr, id); if ((curObject == NULL) || (curObject->widget != GFUI_EDITBOX)) { return; } editbox = &(curObject->u.editbox); label = &(editbox->label); strncpy(label->text, text, label->maxlen); } void gfuiReleaseEditbox(tGfuiObject *curObject) { tGfuiEditbox *editbox; tGfuiLabel *label; editbox = &(curObject->u.editbox); label = &(editbox->label); free(label->text); free(curObject); }