Skip to content

Commit

Permalink
game: Convert textinput to use str over char *buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
mrannanj committed Nov 3, 2024
1 parent f9c329d commit 618b4aa
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 72 deletions.
104 changes: 49 additions & 55 deletions src/game/gui/textinput.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ typedef struct {
int ticks;
int dir;
surface sur;
char *buf;
str text;
int max_chars;
int pos;
int bg_enabled;
Expand Down Expand Up @@ -48,7 +48,7 @@ static void textinput_render(component *c) {

int start_x = c->x + tb->tconf.padding.left;
if(tb->tconf.halign == TEXT_CENTER) {
int tmp_s = text_width(&tb->tconf, tb->buf); // Total W minus last spacing
int tmp_s = text_width(&tb->tconf, str_c(&tb->text)); // Total W minus last spacing
int xspace = c->w - tb->tconf.padding.left - tb->tconf.padding.right;
start_x += ceilf((xspace - tmp_s) / 2.0f);
tb->tconf.halign = TEXT_LEFT;
Expand All @@ -61,7 +61,7 @@ static void textinput_render(component *c) {
mode = TEXT_DISABLED;
}

text_render(&tb->tconf, mode, c->x, c->y, c->w, c->h, tb->buf);
text_render_str(&tb->tconf, mode, c->x, c->y, c->w, c->h, &tb->text);
}

// Start from ' '. Support 0-9, ' ', and A-Z.
Expand Down Expand Up @@ -102,28 +102,39 @@ static char textinput_scroll_character(char cur, bool down) {

static int textinput_action(component *c, int action) {
textinput *tb = widget_get_obj(c);
DEBUG("action %d", action);
char cursor_char = str_at(&tb->text, tb->pos);
char new_char;
switch(action) {
case ACT_RIGHT:
if(tb->buf[tb->pos] == '\0') {
tb->buf[tb->pos] = ' ';
if(cursor_char == '\0' && tb->pos >= (int)str_size(&tb->text)) {
str_append_c(&tb->text, " ");
}
tb->pos = min2(tb->max_chars - 1, tb->pos + 1);
if(tb->buf[tb->pos] == '\0') {
tb->buf[tb->pos] = ' ';
}
str_truncate(&tb->text, tb->max_chars);
return 0;
break;
case ACT_LEFT:
tb->pos = max2(0, tb->pos - 1);
return 0;
break;
case ACT_UP:
tb->buf[tb->pos] = textinput_scroll_character(tb->buf[tb->pos], false);
new_char = textinput_scroll_character(cursor_char, false);
if(tb->pos >= (int)str_size(&tb->text)) {
str_append_buf(&tb->text, &new_char, 1);
} else {
str_set_at(&tb->text, tb->pos, new_char);
}
str_truncate(&tb->text, tb->max_chars);
return 0;
break;
case ACT_DOWN:
tb->buf[tb->pos] = textinput_scroll_character(tb->buf[tb->pos], true);
new_char = textinput_scroll_character(cursor_char, true);
if(tb->pos >= (int)str_size(&tb->text)) {
str_append_buf(&tb->text, &new_char, 1);
} else {
str_set_at(&tb->text, tb->pos, new_char);
}
str_truncate(&tb->text, tb->max_chars);
return 0;
break;
case ACT_PUNCH:
Expand All @@ -140,28 +151,27 @@ static int textinput_event(component *c, SDL_Event *e) {
// Handle selection
if(e->type == SDL_TEXTINPUT) {
textinput *tb = widget_get_obj(c);
tb->buf[tb->pos] = e->text.text[0];
str_insert_at(&tb->text, tb->pos, e->text.text[0]);
str_truncate(&tb->text, tb->max_chars);
tb->pos = min2(tb->max_chars - 1, tb->pos + 1);
// strncat(tb->buf, e->text.text, tb->max_chars - strlen(tb->buf));
return 0;
} else if(e->type == SDL_KEYDOWN) {
textinput *tb = widget_get_obj(c);
size_t len = strlen(tb->buf);
const unsigned char *state = SDL_GetKeyboardState(NULL);
if(state[SDL_SCANCODE_BACKSPACE] || state[SDL_SCANCODE_DELETE]) {
if(len > 1) {
memmove(tb->buf + max2(tb->pos - 1, 0), tb->buf + max2(tb->pos, 1),
min2(tb->max_chars, tb->max_chars - tb->pos + 1));
tb->pos = max2(0, tb->pos - 1);
} else if(len == 1) {
tb->buf[0] = 0;
tb->pos = 0;
if(state[SDL_SCANCODE_BACKSPACE]) {
tb->pos = max2(0, tb->pos - 1);
str_delete_at(&tb->text, tb->pos);
} else if(state[SDL_SCANCODE_DELETE]) {
if(str_delete_at(&tb->text, tb->pos)) {
tb->pos = max2(0, tb->pos);
}
} else if(state[SDL_SCANCODE_V] && state[SDL_SCANCODE_LCTRL]) {
if(SDL_HasClipboardText()) {
char *clip = SDL_GetClipboardText();
strncat(tb->buf + tb->pos, clip, tb->max_chars - tb->pos);
tb->pos = min2(tb->max_chars, tb->pos + strlen(clip));
str_insert_c_at(&tb->text, tb->pos, clip);
str_truncate(&tb->text, tb->max_chars);
tb->pos = min2(tb->max_chars - 1, tb->pos + strlen(clip));
SDL_free(clip);
}
}
return 0;
Expand All @@ -184,38 +194,27 @@ static void textinput_tick(component *c) {
}
}

char *textinput_value(const component *c) {
const char *textinput_value(const component *c) {
textinput *tb = widget_get_obj(c);
// Trim trailing whitespace
for(int i = strlen(tb->buf) - 1; i >= 0 && isspace(tb->buf[i]); --i) {
tb->buf[i] = '\0';
}
return tb->buf;
// Trim whitespace
str_strip(&tb->text);
tb->pos = 0;
return str_c(&tb->text);
}

void textinput_clear(component *c) {
textinput *tb = widget_get_obj(c);
memset(tb->buf, 0, tb->max_chars + 1);
str_truncate(&tb->text, 0);
tb->pos = 0;
}

static void textinput_free(component *c) {
textinput *tb = widget_get_obj(c);
surface_free(&tb->sur);
omf_free(tb->buf);
str_free(&tb->text);
omf_free(tb);
}

void textinput_set_max_chars(component *c, int max_chars) {
textinput *tb = widget_get_obj(c);
tb->buf = omf_realloc(tb->buf, max_chars + 1);
tb->buf[max_chars] = 0;

tb->max_chars = max_chars;

component_set_size_hints(c, text_char_width(&tb->tconf) * tb->max_chars, 10);
}

void textinput_enable_background(component *c, int enabled) {
textinput *tb = widget_get_obj(c);
tb->bg_enabled = enabled;
Expand All @@ -227,40 +226,35 @@ void textinput_set_done_cb(component *c, textinput_done_cb done_cb, void *userda
tb->userdata = userdata;
}

component *textinput_create(const text_settings *tconf, const char *help, const char *initialvalue) {
component *textinput_create(const text_settings *tconf, int max_chars, const char *help, const char *initialvalue) {
component *c = widget_create();

textinput *tb = omf_calloc(1, sizeof(textinput));
memcpy(&tb->tconf, tconf, sizeof(text_settings));
tb->tconf.max_lines = 1;
tb->bg_enabled = 1;
tb->max_chars = 15;
tb->max_chars = max_chars;
tb->pos = 0;

component_set_help_text(c, help);

// Background for field
int tsize = text_char_width(&tb->tconf);
image img;
image_create(&img, 15 * tsize + 2, tsize + 3);
image_create(&img, tb->max_chars * tsize + 2, tsize + 3);
image_clear(&img, COLOR_MENU_BG);
image_rect(&img, 0, 0, 15 * tsize + 1, tsize + 2, COLOR_MENU_BORDER);
image_rect(&img, 0, 0, tb->max_chars * tsize + 1, tsize + 2, COLOR_MENU_BORDER);
surface_create_from_image(&tb->sur, &img);
image_free(&img);

// Copy over the initial value
tb->buf = omf_calloc(tb->max_chars + 1, 1);
strncpy(tb->buf, initialvalue, tb->max_chars);
tb->pos = min2(strlen(initialvalue), tb->max_chars);
str_from_c(&tb->text, initialvalue);
str_truncate(&tb->text, tb->max_chars);
tb->pos = min2(str_size(&tb->text), tb->max_chars);

component_set_size_hints(c, text_char_width(&tb->tconf) * tb->max_chars, 10);
component_set_size_hints(c, tb->max_chars * tsize + 2, tsize + 3);

component_set_size_hints(c, 15 * tsize + 2, tsize + 3);

if(initialvalue && strlen(initialvalue)) {
// Copy over the initial value
strncpy(tb->buf, initialvalue, tb->max_chars);
}
// Widget stuff
widget_set_obj(c, tb);
widget_set_render_cb(c, textinput_render);
Expand Down
5 changes: 2 additions & 3 deletions src/game/gui/textinput.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

typedef void (*textinput_done_cb)(component *c, void *userdata);

component *textinput_create(const text_settings *tconf, const char *help, const char *initialvalue);
char *textinput_value(const component *c);
component *textinput_create(const text_settings *tconf, int max_chars, const char *help, const char *initialvalue);
const char *textinput_value(const component *c);
void textinput_clear(component *c);
void textinput_enable_background(component *c, int enabled);
void textinput_set_max_chars(component *c, int max_chars);
void textinput_set_done_cb(component *c, textinput_done_cb done_cb, void *userdata);

#endif // TEXTINPUT_H
15 changes: 6 additions & 9 deletions src/game/scenes/lobby.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ void lobby_do_yell(component *c, void *userdata) {
lobby_local *local = scene_get_userdata(scene);

// menu *m = sizer_get_obj(c->parent);
char *yell = textinput_value(c);
const char *yell = textinput_value(c);

if(strlen(yell) > 0) {
DEBUG("yelled %s", textinput_value(c));
Expand Down Expand Up @@ -364,10 +364,9 @@ component *lobby_yell_create(scene *s) {

menu_attach(menu, label_create(&tconf, "Yell:"));
component *yell_input =
textinput_create(&tconf, "Yell:",
textinput_create(&tconf, 36, "Yell:",
"Yell a message to everybody in the challenge arena.\n\n\n\n\nTo whisper to one player, type "
"their name, a ':', and your message.\nPress 'esc' to return to the challenge arena menu.");
textinput_set_max_chars(yell_input, 36);
menu_attach(menu, yell_input);
textinput_enable_background(yell_input, 0);
textinput_set_done_cb(yell_input, lobby_do_yell, s);
Expand All @@ -379,7 +378,7 @@ void lobby_do_whisper(component *c, void *userdata) {
menu *m = sizer_get_obj(c->parent);
scene *s = userdata;

char *whisper = textinput_value(c);
const char *whisper = textinput_value(c);

if(strlen(whisper) > 0) {
DEBUG("whispered %s", whisper);
Expand Down Expand Up @@ -441,8 +440,7 @@ component *lobby_whisper_create(scene *s) {
lobby_user *user = list_get(&local->users, local->active_user);
snprintf(local->helptext, sizeof(local->helptext), "Whisper a message to %s. Press enter when done, esc to abort.",
user->name);
component *whisper_input = textinput_create(&tconf, "Whisper:", local->helptext);
textinput_set_max_chars(whisper_input, 36);
component *whisper_input = textinput_create(&tconf, 36, "Whisper:", local->helptext);
menu_attach(menu, whisper_input);
textinput_enable_background(whisper_input, 0);
textinput_set_done_cb(whisper_input, lobby_do_whisper, s);
Expand Down Expand Up @@ -584,7 +582,7 @@ void lobby_entered_name(component *c, void *userdata) {
}
serial_write_int8(&ser, strlen(version));
serial_write(&ser, version, strlen(version));
char *name = textinput_value(c);
const char *name = textinput_value(c);
serial_write(&ser, name, strlen(name));

settings_get()->net.net_username = strdup(name);
Expand Down Expand Up @@ -1187,9 +1185,8 @@ int lobby_create(scene *scene) {

menu_attach(name_menu, label_create(&tconf, "Enter your name:"));
// TODO pull the last used name from settings
component *name_input = textinput_create(&tconf, "", settings_get()->net.net_username);
component *name_input = textinput_create(&tconf, 14, "", settings_get()->net.net_username);
textinput_enable_background(name_input, 0);
textinput_set_max_chars(name_input, 14);
textinput_set_done_cb(name_input, lobby_entered_name, scene);
menu_attach(name_menu, name_input);

Expand Down
2 changes: 1 addition & 1 deletion src/game/scenes/mainmenu/menu_connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ component *menu_connect_create(scene *s) {
local->controllers_created = 0;
local->connect_start = 0;
local->addr_input =
textinput_create(&tconf, "Enter an IP address you wish to connect to.", settings_get()->net.net_connect_ip);
textinput_create(&tconf, 15, "Enter an IP address you wish to connect to.", settings_get()->net.net_connect_ip);
local->connect_button =
textbutton_create(&tconf, "CONNECT", "Connect to the provided IP address.", COM_ENABLED, menu_connect_start, s);
local->cancel_button =
Expand Down
3 changes: 1 addition & 2 deletions src/game/scenes/mechlab/lab_dash_newplayer.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ component *lab_dash_newplayer_create(scene *s, newplayer_widgets *nw) {
// Input field
tconf.cselected = TEXT_BRIGHT_GREEN;
tconf.halign = TEXT_LEFT;
nw->input = textinput_create(&tconf, "Name", "");
nw->input = textinput_create(&tconf, 16, "Name", "");
component_select(nw->input, 1);
textinput_enable_background(nw->input, 0);
textinput_set_max_chars(nw->input, 16);
xysizer_attach(xy, nw->input, 114, 62, 120, 8);

return xy;
Expand Down
4 changes: 2 additions & 2 deletions src/game/scenes/scoreboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void scoreboard_free(scene *scene) {
void handle_scoreboard_save(scoreboard_local *local) {
int slot = 0;

char *name = textinput_value(local->ti);
const char *name = textinput_value(local->ti);
if(!strlen(name)) {
return;
}
Expand Down Expand Up @@ -237,7 +237,7 @@ int scoreboard_create(scene *scene) {
if(local->has_pending_data && score < local->pending_data.score && !found_slot) {
found_slot = 1;
local->frame = guiframe_create(20, 30 + r * 8, 20, 10);
local->ti = textinput_create(&small_text, "", "");
local->ti = textinput_create(&small_text, 16, "", "");
textinput_enable_background(local->ti, 0);
guiframe_set_root(local->frame, local->ti);
guiframe_layout(local->frame);
Expand Down

0 comments on commit 618b4aa

Please sign in to comment.