rayfract

annotate src/imtk/textbox.c @ 10:1496aae2e7d4

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