diff --git a/src/base/system.c b/src/base/system.c index 40d53e8ac..c94e4cf95 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1188,6 +1188,139 @@ void gui_messagebox(const char *title, const char *message) int str_isspace(char c) { return c == ' ' || c == '\n' || c == '\t'; } + +static int str_utf8_isstart(char c) +{ + if((c&0xC0) == 0x80) /* 10xxxxxx */ + return 0; + return 1; +} + +int str_utf8_rewind(const char *str, int cursor) +{ + while(cursor) + { + cursor--; + if(str_utf8_isstart(*(str + cursor))) + break; + } + return cursor; +} + +int str_utf8_forward(const char *str, int cursor) +{ + const char *buf = str + cursor; + if(!buf[0]) + return cursor; + + if((*buf&0x80) == 0x0) /* 0xxxxxxx */ + return cursor+1; + else if((*buf&0xE0) == 0xC0) /* 110xxxxx */ + { + if(!buf[1]) return cursor+1; + return cursor+2; + } + else if((*buf & 0xF0) == 0xE0) /* 1110xxxx */ + { + if(!buf[1]) return cursor+1; + if(!buf[2]) return cursor+2; + return cursor+2; + } + else if((*buf & 0xF8) == 0xF0) /* 11110xxx */ + { + if(!buf[1]) return cursor+1; + if(!buf[2]) return cursor+2; + if(!buf[3]) return cursor+3; + return cursor+3; + } + + /* invalid */ + return cursor+1; +} + +int str_utf8_encode(char *ptr, int chr) +{ + /* encode */ + if(chr <= 0x7F) + { + ptr[0] = (char)chr; + return 1; + } + else if(chr <= 0x7FF) + { + ptr[0] = 0xC0|((chr>>6)&0x1F); + ptr[1] = 0x80|(chr&0x3F); + return 2; + } + else if(chr <= 0xFFFF) + { + ptr[0] = 0xE0|((chr>>12)&0x0F); + ptr[1] = 0xC0|((chr>>6)&0x3F); + ptr[2] = 0xC0|(chr&0x3F); + return 3; + } + else if(chr <= 0x10FFFF) + { + ptr[0] = 0xF0|((chr>>18)&0x07); + ptr[1] = 0xC0|((chr>>12)&0x3F); + ptr[2] = 0xC0|((chr>>6)&0x3F); + ptr[3] = 0xC0|(chr&0x3F); + return 4; + } + + return 0; +} + +int str_utf8_decode(const char **ptr) +{ + const char *buf = *ptr; + int ch = 0; + + do + { + if((*buf&0x80) == 0x0) /* 0xxxxxxx */ + { + ch = *buf; + buf++; + } + else if((*buf&0xE0) == 0xC0) /* 110xxxxx */ + { + ch = (*buf++ & 0x3F) << 6; if(!(*buf)) break; + ch += (*buf++ & 0x3F); + if(ch == 0) ch = -1; + } + else if((*buf & 0xF0) == 0xE0) /* 1110xxxx */ + { + ch = (*buf++ & 0x1F) << 12; if(!(*buf)) break; + ch += (*buf++ & 0x3F) << 6; if(!(*buf)) break; + ch += (*buf++ & 0x3F); + if(ch == 0) ch = -1; + } + else if((*buf & 0xF8) == 0xF0) /* 11110xxx */ + { + ch = (*buf++ & 0x0F) << 18; if(!(*buf)) break; + ch += (*buf++ & 0x3F) << 12; if(!(*buf)) break; + ch += (*buf++ & 0x3F) << 6; if(!(*buf)) break; + ch += (*buf++ & 0x3F); + if(ch == 0) ch = -1; + } + else + { + /* invalid */ + buf++; + break; + } + + *ptr = buf; + return ch; + } while(0); + + /* out of bounds */ + *ptr = buf; + return -1; + +} + #if defined(__cplusplus) } #endif diff --git a/src/base/system.h b/src/base/system.h index 3aa01cab6..87cae4a02 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -947,6 +947,69 @@ int str_isspace(char c); */ void gui_messagebox(const char *title, const char *message); + +/* + Function: str_utf8_rewind + Moves a cursor backwards in an utf8 string + + Parameters: + str - utf8 string + cursor - position in the string + + Returns: + New cursor position. + + Remarks: + - Won't move the cursor less then 0 +*/ +int str_utf8_rewind(const char *str, int cursor); + +/* + Function: str_utf8_forward + Moves a cursor forwards in an utf8 string + + Parameters: + str - utf8 string + cursor - position in the string + + Returns: + New cursor position. + + Remarks: + - Won't move the cursor beyond the zero termination marker +*/ +int str_utf8_forward(const char *str, int cursor); + +/* + Function: str_utf8_decode + Decodes an utf8 character + + Parameters: + ptr - pointer to an utf8 string. this pointer will be moved forward + + Returns: + Unicode value for the character. -1 for invalid characters and 0 for end of string. + + Remarks: + - This function will also move the pointer forward. +*/ +int str_utf8_decode(const char **ptr); + +/* + Function: str_utf8_encode + Encode an utf8 character + + Parameters: + ptr - Pointer to a buffer that should recive the data. Should be able to hold at least 4 bytes. + + Returns: + Number of bytes put into the buffer. + + Remarks: + - Does not do zero termination of the string. +*/ +int str_utf8_encode(char *ptr, int chr); + #ifdef __cplusplus } #endif diff --git a/src/engine/client/ec_gfx_text.c b/src/engine/client/ec_gfx_text.c index 2dedd032d..a38e800bc 100644 --- a/src/engine/client/ec_gfx_text.c +++ b/src/engine/client/ec_gfx_text.c @@ -121,6 +121,9 @@ typedef struct FONTSIZEDATA int num_x_chars; int num_y_chars; + int char_max_width; + int char_max_height; + FONTCHAR characters[MAX_CHARACTERS*MAX_CHARACTERS]; int current_character; @@ -198,38 +201,90 @@ static void grow(unsigned char *in, unsigned char *out, int w, int h) } out[y*w+x] = c; - } + } } -static void font_init_texture(FONTSIZEDATA *font, int width, int height) +static void font_init_texture(FONTSIZEDATA *sizedata, int charwidth, int charheight, int xchars, int ychars) { + static int font_memory_usage = 0; int i; + int width = charwidth*xchars; + int height = charheight*ychars; void *mem = mem_alloc(width*height, 1); mem_zero(mem, width*height); - font->texture_width = width; - font->texture_height = height; - font->num_x_chars = 32; - font->num_y_chars = 32; - font->current_character = 0; - glGenTextures(2, font->textures); + if(sizedata->textures[0] == 0) + glGenTextures(2, sizedata->textures); + else + font_memory_usage -= sizedata->texture_width*sizedata->texture_height*2; + + sizedata->num_x_chars = xchars; + sizedata->num_y_chars = ychars; + sizedata->texture_width = width; + sizedata->texture_height = height; + sizedata->current_character = 0; for(i = 0; i < 2; i++) { - glBindTexture(GL_TEXTURE_2D, font->textures[i]); + glBindTexture(GL_TEXTURE_2D, sizedata->textures[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, font_texture_format, width, height, 0, font_texture_format, GL_UNSIGNED_BYTE, mem); + font_memory_usage += width*height; } + dbg_msg("", "font memory usage: %d", font_memory_usage); + mem_free(mem); } +static void font_increase_texture_size(FONTSIZEDATA *sizedata) +{ + if(sizedata->texture_width < sizedata->texture_height) + sizedata->num_x_chars <<= 1; + else + sizedata->num_y_chars <<= 1; + font_init_texture(sizedata, sizedata->char_max_width, sizedata->char_max_height, sizedata->num_x_chars, sizedata->num_y_chars); +} + static void font_init_index(FONT *font, int index) { - font->sizes[index].font_size = font_sizes[index]; + int outline_thickness = 1; + FONTSIZEDATA *sizedata = &font->sizes[index]; + + sizedata->font_size = font_sizes[index]; + FT_Set_Pixel_Sizes(font->ft_face, 0, sizedata->font_size); + + if(sizedata->font_size >= 18) + outline_thickness = 2; + + { + unsigned glyph_index; + int charcode; + int max_h = 0; + int max_w = 0; + + charcode = FT_Get_First_Char(font->ft_face, &glyph_index); + while(glyph_index != 0) + { + /* do stuff */ + FT_Load_Glyph(font->ft_face, glyph_index, FT_LOAD_DEFAULT); + + if(font->ft_face->glyph->metrics.width > max_w) max_w = font->ft_face->glyph->metrics.width; + if(font->ft_face->glyph->metrics.height > max_h) max_h = font->ft_face->glyph->metrics.height; + charcode = FT_Get_Next_Char(font->ft_face, charcode, &glyph_index); + } + + max_w = (max_w>>6)+2+outline_thickness*2; + max_h = (max_h>>6)+2+outline_thickness*2; + + for(sizedata->char_max_width = 1; sizedata->char_max_width < max_w; sizedata->char_max_width <<= 1); + for(sizedata->char_max_height = 1; sizedata->char_max_height < max_h; sizedata->char_max_height <<= 1); + } + + //dbg_msg("font", "init size %d, texture size %d %d", font->sizes[index].font_size, w, h); //FT_New_Face(ft_library, "data/fonts/vera.ttf", 0, &font->ft_face); - font_init_texture(&font->sizes[index], 1024*2, 1024*2); + font_init_texture(sizedata, sizedata->char_max_width, sizedata->char_max_height, 8, 8); } static FONTSIZEDATA *font_get_size(FONT *font, int pixelsize) @@ -279,6 +334,13 @@ static int font_get_slot(FONTSIZEDATA *sizedata) if(sizedata->characters[i].touch_time < sizedata->characters[oldest].touch_time) oldest = i; } + + if(time_get()-sizedata->characters[oldest].touch_time < time_freq()) + { + font_increase_texture_size(sizedata); + return font_get_slot(sizedata); + } + return oldest; } } @@ -286,7 +348,7 @@ static int font_get_slot(FONTSIZEDATA *sizedata) static int font_render_glyph(FONT *font, FONTSIZEDATA *sizedata, int chr) { FT_Bitmap *bitmap; - int slot_id = sizedata->current_character; + int slot_id = 0; int slot_w = sizedata->texture_width / sizedata->num_x_chars; int slot_h = sizedata->texture_height / sizedata->num_y_chars; int slot_size = slot_w*slot_h; @@ -297,7 +359,7 @@ static int font_render_glyph(FONT *font, FONTSIZEDATA *sizedata, int chr) FT_Set_Pixel_Sizes(font->ft_face, 0, sizedata->font_size); - if(FT_Load_Char(font->ft_face, chr, FT_LOAD_RENDER)) + if(FT_Load_Char(font->ft_face, chr, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP)) { dbg_msg("font", "error loading glyph %d", chr); return -1; @@ -412,7 +474,7 @@ static FONTCHAR *font_get_char(FONT *font, FONTSIZEDATA *sizedata, int chr) } /* must only be called from the rendering function as the font must be set to the correct size */ -static void font_setsize(FONT *font, int size) +static void font_render_setup(FONT *font, int size) { FT_Set_Pixel_Sizes(font->ft_face, 0, size); } @@ -420,57 +482,10 @@ static void font_setsize(FONT *font, int size) static float font_kerning(FONT *font, int left, int right) { FT_Vector kerning = {0,0}; - FT_Get_Kerning(font->ft_face, left, right, FT_KERNING_DEFAULT, &kerning ); + FT_Get_Kerning(font->ft_face, left, right, FT_KERNING_DEFAULT, &kerning); return (kerning.x>>6); } -static int utf8_decode(const unsigned char **ptr) -{ - const unsigned char *buf = *ptr; - int ch = 0; - - do - { - if((*buf&0x80) == 0x0) /* 0xxxxxxx */ - { - ch = *buf; - buf++; - } - else if((*buf&0xE0) == 0xC0) /* 110xxxxx */ - { - ch = (*buf++ & 0x3F) << 6; if(!(*buf)) break; - ch += (*buf++ & 0x3F); - if(ch == 0) ch = -1; - } - else if((*buf & 0xF0) == 0xE0) /* 1110xxxx */ - { - ch = (*buf++ & 0x1F) << 12; if(!(*buf)) break; - ch += (*buf++ & 0x3F) << 6; if(!(*buf)) break; - ch += (*buf++ & 0x3F); - if(ch == 0) ch = -1; - } - else if((*buf & 0xF8) == 0xF0) /* 11110xxx */ - { - ch = (*buf++ & 0x0F) << 18; if(!(*buf)) break; - ch += (*buf++ & 0x3F) << 12; if(!(*buf)) break; - ch += (*buf++ & 0x3F) << 6; if(!(*buf)) break; - ch += (*buf++ & 0x3F); - if(ch == 0) ch = -1; - } - else - break; - - /* valid */ - *ptr = buf; - return ch; - } while(0); - - /* invalid */ - *ptr = buf; - return -1; - -} - void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length) { FONT *font = cursor->font; @@ -512,7 +527,7 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length) return; sizedata = font_get_size(font, actual_size); - font_setsize(font, actual_size); + font_render_setup(font, actual_size); /* set length */ if(length < 0) @@ -527,8 +542,8 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length) for(;i < 2; i++) { - const unsigned char *current = (unsigned char *)text; - const unsigned char *end = current+length; + const char *current = (char *)text; + const char *end = current+length; //int to_render = length; draw_x = cursor_x; draw_y = cursor_y; @@ -553,7 +568,7 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length) { int new_line = 0; //int this_batch = (int)(end-current); - const unsigned char *batch_end = end; + const char *batch_end = end; if(cursor->line_width > 0 && !(cursor->flags&TEXTFLAG_STOP_AT_END)) { int wlen = word_length((char *)current); @@ -599,19 +614,23 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length) while(current < batch_end) { + const char *tmp; float advance = 0; int character = 0; + int nextcharacter = 0; FONTCHAR *chr; // TODO: UTF-8 decode - character = utf8_decode(¤t); + character = str_utf8_decode(¤t); + tmp = current; + nextcharacter = str_utf8_decode(&tmp); + if(character == '\n') { draw_x = cursor->start_x; draw_y += size; draw_x = (int)(draw_x * fake_to_screen_x) / fake_to_screen_x; /* realign */ draw_y = (int)(draw_y * fake_to_screen_y) / fake_to_screen_y; - /* current++; */ continue; } @@ -625,7 +644,7 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length) gfx_quads_drawTL(draw_x+chr->offset_x*size, draw_y+chr->offset_y*size, chr->width*size, chr->height*size); } - advance = chr->advance_x; /* + font_kerning(font, character, *(current+1));*/ + advance = chr->advance_x + font_kerning(font, character, nextcharacter)/size; } if(cursor->flags&TEXTFLAG_STOP_AT_END && draw_x+advance*size-cursor->start_x > cursor->line_width) diff --git a/src/engine/client/ec_inp.c b/src/engine/client/ec_inp.c index 4aea840ab..495614d67 100644 --- a/src/engine/client/ec_inp.c +++ b/src/engine/client/ec_inp.c @@ -49,11 +49,11 @@ enum static INPUT_EVENT input_events[INPUT_BUFFER_SIZE]; static int num_events = 0; -static void add_event(char c, int key, int flags) +static void add_event(int unicode, int key, int flags) { if(num_events != INPUT_BUFFER_SIZE) { - input_events[num_events].ch = c; + input_events[num_events].unicode = unicode; input_events[num_events].key = key; input_events[num_events].flags = flags; num_events++; @@ -178,8 +178,8 @@ void inp_update() { /* handle keys */ case SDL_KEYDOWN: - if(event.key.keysym.unicode < 255) - add_event(event.key.keysym.unicode, 0, 0); + /*if(event.key.keysym.unicode < 255) */ + add_event(event.key.keysym.unicode, 0, 0); key = event.key.keysym.sym; break; case SDL_KEYUP: diff --git a/src/engine/e_if_gfx.h b/src/engine/e_if_gfx.h index 61a76bad9..3d048e853 100644 --- a/src/engine/e_if_gfx.h +++ b/src/engine/e_if_gfx.h @@ -671,5 +671,4 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length); struct FONT *gfx_font_load(const char *filename); void gfx_font_destroy(struct FONT *font); - #endif diff --git a/src/engine/e_if_inp.h b/src/engine/e_if_inp.h index 00f44ba1a..919ac0eb7 100644 --- a/src/engine/e_if_inp.h +++ b/src/engine/e_if_inp.h @@ -20,7 +20,7 @@ enum typedef struct { int flags; - unsigned char ch; + int unicode; int key; } INPUT_EVENT; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 050c70564..0fd024c30 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -18,6 +18,7 @@ #include #include +#include #include vec4 MENUS::gui_color; @@ -199,7 +200,7 @@ void MENUS::ui_draw_checkbox_number(const void *id, const char *text, int checke ui_draw_checkbox_common(id, text, buf, r); } -int MENUS::ui_do_edit_box(void *id, const RECT *rect, char *str, int str_size, float font_size, bool hidden) +int MENUS::ui_do_edit_box(void *id, const RECT *rect, char *str, unsigned str_size, float font_size, bool hidden) { int inside = ui_mouse_inside(rect); int r = 0; @@ -229,48 +230,7 @@ int MENUS::ui_do_edit_box(void *id, const RECT *rect, char *str, int str_size, f for(int i = 0; i < num_inputevents; i++) { len = strlen(str); - INPUT_EVENT e = inputevents[i]; - char c = e.ch; - int k = e.key; - - if (at_index > len) - at_index = len; - - if (!(c >= 0 && c < 32) && c != 127) - { - if (len < str_size - 1 && at_index < str_size - 1) - { - memmove(str + at_index + 1, str + at_index, len - at_index + 1); - str[at_index] = c; - at_index++; - r = 1; - } - } - - if(e.flags&INPFLAG_PRESS) - { - if (k == KEY_BACKSPACE && at_index > 0) - { - memmove(str + at_index - 1, str + at_index, len - at_index + 1); - at_index--; - r = 1; - } - else if (k == KEY_DELETE && at_index < len) - { - memmove(str + at_index, str + at_index + 1, len - at_index); - r = 1; - } - else if (k == KEY_RETURN) - ui_clear_last_active_item(); - else if (k == KEY_LEFT && at_index > 0) - at_index--; - else if (k == KEY_RIGHT && at_index < len) - at_index++; - else if (k == KEY_HOME) - at_index = 0; - else if (k == KEY_END) - at_index = len; - } + LINEINPUT::manipulate(inputevents[i], str, str_size, &len, &at_index); } } diff --git a/src/game/client/components/menus.hpp b/src/game/client/components/menus.hpp index 8a50c1227..27423490b 100644 --- a/src/game/client/components/menus.hpp +++ b/src/game/client/components/menus.hpp @@ -40,7 +40,7 @@ class MENUS : public COMPONENT static void ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const RECT *r); static void ui_draw_checkbox(const void *id, const char *text, int checked, const RECT *r, const void *extra); static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const RECT *r, const void *extra); - static int ui_do_edit_box(void *id, const RECT *rect, char *str, int str_size, float font_size, bool hidden=false); + static int ui_do_edit_box(void *id, const RECT *rect, char *str, unsigned str_size, float font_size, bool hidden=false); static float ui_do_scrollbar_v(const void *id, const RECT *rect, float current); static float ui_do_scrollbar_h(const void *id, const RECT *rect, float current); diff --git a/src/game/client/lineinput.cpp b/src/game/client/lineinput.cpp index 40c47d411..f8c9d7e78 100644 --- a/src/game/client/lineinput.cpp +++ b/src/game/client/lineinput.cpp @@ -21,23 +21,30 @@ void LINEINPUT::set(const char *string) cursor_pos = len; } -void LINEINPUT::process_input(INPUT_EVENT e) +void LINEINPUT::manipulate(INPUT_EVENT e, char *str, int str_max_size, int *str_len_ptr, int *cursor_pos_ptr) { + int cursor_pos = *cursor_pos_ptr; + int len = *str_len_ptr; + if(cursor_pos > len) cursor_pos = len; - char c = e.ch; + int code = e.unicode; int k = e.key; // 127 is produced on Mac OS X and corresponds to the delete key - if (!(c >= 0 && c < 32) && c != 127) + if (!(code >= 0 && code < 32) && code != 127) { - if (len < sizeof(str) - 1 && cursor_pos < sizeof(str) - 1) + char tmp[8]; + int charsize = str_utf8_encode(tmp, code); + + if (len < str_max_size - charsize && cursor_pos < str_max_size - charsize) { - memmove(str + cursor_pos + 1, str + cursor_pos, len - cursor_pos + 1); - str[cursor_pos] = c; - cursor_pos++; - len++; + memmove(str + cursor_pos + charsize, str + cursor_pos, len - cursor_pos + charsize); + for(int i = 0; i < charsize; i++) + str[cursor_pos+i] = tmp[i]; + cursor_pos += charsize; + len += charsize; } } @@ -45,22 +52,34 @@ void LINEINPUT::process_input(INPUT_EVENT e) { if (k == KEY_BACKSPACE && cursor_pos > 0) { - memmove(str + cursor_pos - 1, str + cursor_pos, len - cursor_pos + 1); - cursor_pos--; - len--; + int new_cursor_pos = str_utf8_rewind(str, cursor_pos); + int charsize = cursor_pos-new_cursor_pos; + memmove(str+new_cursor_pos, str+cursor_pos, len - charsize + 1); // +1 == null term + cursor_pos = new_cursor_pos; + len -= charsize; } else if (k == KEY_DELETE && cursor_pos < len) { - memmove(str + cursor_pos, str + cursor_pos + 1, len - cursor_pos); - len--; + int p = str_utf8_forward(str, cursor_pos); + int charsize = p-cursor_pos; + memmove(str + cursor_pos, str + cursor_pos + charsize, len - cursor_pos - charsize + 1); // +1 == null term + len -= charsize; } else if (k == KEY_LEFT && cursor_pos > 0) - cursor_pos--; + cursor_pos = str_utf8_rewind(str, cursor_pos); else if (k == KEY_RIGHT && cursor_pos < len) - cursor_pos++; + cursor_pos = str_utf8_forward(str, cursor_pos); else if (k == KEY_HOME) cursor_pos = 0; else if (k == KEY_END) cursor_pos = len; } + + *cursor_pos_ptr = cursor_pos; + *str_len_ptr = len; +} + +void LINEINPUT::process_input(INPUT_EVENT e) +{ + manipulate(e, str, sizeof(str), &len, &cursor_pos); } diff --git a/src/game/client/lineinput.hpp b/src/game/client/lineinput.hpp index 80ef3c521..75b2bd1d2 100644 --- a/src/game/client/lineinput.hpp +++ b/src/game/client/lineinput.hpp @@ -5,9 +5,11 @@ class LINEINPUT { char str[256]; - unsigned len; - unsigned cursor_pos; + int len; + int cursor_pos; public: + static void manipulate(INPUT_EVENT e, char *str, int str_max_size, int *str_len, int *cursor_pos); + class CALLBACK { public: diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp index 7a8a1ae7f..d56a05061 100644 --- a/src/game/editor/ed_editor.cpp +++ b/src/game/editor/ed_editor.cpp @@ -18,6 +18,7 @@ extern "C" { #include #include "ed_editor.hpp" +#include static int checker_texture = 0; static int background_texture = 0; @@ -209,44 +210,7 @@ int ui_do_edit_box(void *id, const RECT *rect, char *str, int str_size, float fo for(int i = 0; i < inp_num_events(); i++) { len = strlen(str); - - INPUT_EVENT e = inp_get_event(i); - char c = e.ch; - int k = e.key; - - if (at_index > len) - at_index = len; - - if (!(c >= 0 && c < 32) && c != 127) - { - if (len < str_size - 1 && at_index < str_size - 1) - { - memmove(str + at_index + 1, str + at_index, len - at_index + 1); - str[at_index] = c; - at_index++; - } - } - - if(e.flags&INPFLAG_PRESS) - { - if (k == KEY_BACKSPACE && at_index > 0) - { - memmove(str + at_index - 1, str + at_index, len - at_index + 1); - at_index--; - } - else if (k == KEY_DELETE && at_index < len) - memmove(str + at_index, str + at_index + 1, len - at_index); - else if (k == KEY_RETURN) - ui_clear_last_active_item(); - else if (k == KEY_LEFT && at_index > 0) - at_index--; - else if (k == KEY_RIGHT && at_index < len) - at_index++; - else if (k == KEY_HOME) - at_index = 0; - else if (k == KEY_END) - at_index = len; - } + LINEINPUT::manipulate(inp_get_event(i), str, str_size, &len, &at_index); } r = 1;