imtk

annotate src/textbox.c @ 16:1cf212375db3

textbox cursor handling
author John Tsiombikas <nuclear@siggraph.org>
date Tue, 19 Apr 2011 08:24:39 +0300
parents df2bc9406561
children c7a7ddbe7714
rev   line source
nuclear@6 1 #include <string.h>
nuclear@6 2 #include <ctype.h>
nuclear@6 3 #include <assert.h>
nuclear@6 4 #include "imtk.h"
nuclear@6 5 #include "state.h"
nuclear@6 6 #include "draw.h"
nuclear@6 7
nuclear@6 8 #define TEXTBOX_SIZE 100
nuclear@6 9
nuclear@16 10 static void draw_textbox(int id, char *text, int cursor, int x, int y, int over);
nuclear@6 11
nuclear@6 12
nuclear@6 13 void imtk_textbox(int id, char *textbuf, size_t buf_sz, int x, int y)
nuclear@6 14 {
nuclear@16 15 int key, len, cursor = 0, over = 0;
nuclear@6 16
nuclear@6 17 assert(id >= 0);
nuclear@6 18
nuclear@16 19 len = strlen(textbuf);
nuclear@16 20
nuclear@16 21 /* HACK! using last element of textbuf for saving cursor position */
nuclear@16 22 if((cursor = textbuf[buf_sz - 1]) > len || cursor < 0) {
nuclear@16 23 cursor = len;
nuclear@16 24 }
nuclear@16 25
nuclear@6 26 if(imtk_hit_test(x, y, TEXTBOX_SIZE, 20)) {
nuclear@6 27 imtk_set_hot(id);
nuclear@6 28 over = 1;
nuclear@6 29 }
nuclear@6 30
nuclear@6 31 if(imtk_button_state(IMTK_LEFT_BUTTON)) {
nuclear@6 32 if(over) {
nuclear@6 33 imtk_set_active(id);
nuclear@6 34 }
nuclear@6 35 } else {
nuclear@6 36 if(imtk_is_active(id)) {
nuclear@6 37 imtk_set_active(-1);
nuclear@6 38 if(imtk_is_hot(id) && over) {
nuclear@6 39 imtk_set_focus(id);
nuclear@6 40 }
nuclear@6 41 }
nuclear@6 42 }
nuclear@6 43
nuclear@6 44 if(imtk_has_focus(id)) {
nuclear@6 45 while((key = imtk_get_key()) != -1) {
nuclear@16 46 if(!(key & 0xff00) && isprint(key)) {
nuclear@16 47 if(len < buf_sz - 1) {
nuclear@16 48 if(cursor == len) {
nuclear@16 49 textbuf[len++] = (char)key;
nuclear@16 50 cursor = len;
nuclear@16 51 } else {
nuclear@16 52 memmove(textbuf + cursor + 1, textbuf + cursor, len - cursor);
nuclear@16 53 len++;
nuclear@16 54 textbuf[cursor++] = (char)key;
nuclear@16 55 }
nuclear@6 56 }
nuclear@6 57 } else {
nuclear@16 58 key &= 0xff;
nuclear@16 59
nuclear@6 60 switch(key) {
nuclear@6 61 case '\b':
nuclear@16 62 if(cursor > 0) {
nuclear@16 63 if(cursor == len) {
nuclear@16 64 textbuf[--cursor] = 0;
nuclear@16 65 } else {
nuclear@16 66 memmove(textbuf + cursor - 1, textbuf + cursor, len - cursor);
nuclear@16 67 textbuf[--len] = 0;
nuclear@16 68 cursor--;
nuclear@16 69 }
nuclear@16 70 }
nuclear@16 71 break;
nuclear@16 72
nuclear@16 73 case 127: /* del */
nuclear@16 74 if(cursor < len) {
nuclear@16 75 memmove(textbuf + cursor, textbuf + cursor + 1, len - cursor);
nuclear@6 76 textbuf[--len] = 0;
nuclear@6 77 }
nuclear@6 78 break;
nuclear@6 79
nuclear@16 80 case GLUT_KEY_LEFT:
nuclear@16 81 if(cursor > 0) {
nuclear@16 82 cursor--;
nuclear@16 83 }
nuclear@16 84 break;
nuclear@16 85
nuclear@16 86 case GLUT_KEY_RIGHT:
nuclear@16 87 if(cursor < len) {
nuclear@16 88 cursor++;
nuclear@16 89 }
nuclear@16 90 break;
nuclear@16 91
nuclear@16 92 case GLUT_KEY_HOME:
nuclear@16 93 cursor = 0;
nuclear@16 94 break;
nuclear@16 95
nuclear@16 96 case GLUT_KEY_END:
nuclear@16 97 cursor = len;
nuclear@16 98 break;
nuclear@16 99
nuclear@6 100 default:
nuclear@6 101 break;
nuclear@6 102 }
nuclear@6 103 }
nuclear@6 104 }
nuclear@6 105 }
nuclear@6 106
nuclear@16 107 textbuf[buf_sz - 1] = cursor;
nuclear@16 108 draw_textbox(id, textbuf, cursor, x, y, over);
nuclear@6 109 }
nuclear@6 110
nuclear@6 111
nuclear@16 112 static void draw_textbox(int id, char *text, int cursor, int x, int y, int over)
nuclear@6 113 {
nuclear@14 114 float tcol[4], bcol[4];
nuclear@14 115 unsigned int attr = 0;
nuclear@6 116
nuclear@14 117 if(over) {
nuclear@14 118 attr |= IMTK_FOCUS_BIT;
nuclear@6 119 }
nuclear@14 120 memcpy(tcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof tcol);
nuclear@14 121 memcpy(bcol, imtk_get_color(IMTK_TOP_COLOR | attr), sizeof bcol);
nuclear@6 122
nuclear@14 123 imtk_draw_rect(x, y, TEXTBOX_SIZE, 20, tcol, bcol);
nuclear@6 124
nuclear@6 125 if(imtk_has_focus(id)) {
nuclear@16 126 int strsz;
nuclear@16 127 char tmp;
nuclear@16 128
nuclear@16 129 tmp = text[cursor];
nuclear@16 130 text[cursor] = 0;
nuclear@16 131 strsz = imtk_string_size(text);
nuclear@16 132 text[cursor] = tmp;
nuclear@16 133
nuclear@16 134 glBegin(GL_QUADS);
nuclear@13 135 glColor4fv(imtk_get_color(IMTK_CURSOR_COLOR));
nuclear@16 136 glVertex2f(x + strsz + 2, y + 2);
nuclear@8 137 glVertex2f(x + strsz + 4, y + 2);
nuclear@8 138 glVertex2f(x + strsz + 4, y + 18);
nuclear@16 139 glVertex2f(x + strsz + 2, y + 18);
nuclear@6 140 glEnd();
nuclear@6 141 }
nuclear@6 142
nuclear@8 143 glColor4fv(imtk_get_color(IMTK_TEXT_COLOR));
nuclear@6 144 imtk_draw_string(x + 2, y + 15, text);
nuclear@6 145
nuclear@6 146 imtk_draw_frame(x, y, TEXTBOX_SIZE, 20, FRAME_INSET);
nuclear@6 147 }
nuclear@6 148