mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-22 22:48:08 +03:00
SDL: Implement inline text input (for MJ command)
Very few games use it (Mamorigami-sama and Les Chairs Cruelles), but this could be reused when we add a pure SDL implementation of input dialogs.
This commit is contained in:
+1
-1
@@ -104,7 +104,7 @@ elseif (GTK2_FOUND)
|
||||
link_libraries(${Intl_LIBRARIES})
|
||||
endif()
|
||||
else()
|
||||
set(SRC_MENU menu_null.c)
|
||||
set(SRC_MENU menu_null.c sdl_input.c)
|
||||
endif()
|
||||
|
||||
# Graphics
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
#include "portab.h"
|
||||
|
||||
/* 文字列入力のパラメータ */
|
||||
typedef struct {
|
||||
typedef struct inputstring_param {
|
||||
char *title;
|
||||
char *oldstring;
|
||||
const char *newstring;
|
||||
|
||||
+2
-2
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "portab.h"
|
||||
#include "menu.h"
|
||||
#include "sdl_core.h"
|
||||
|
||||
void menu_open(void) {
|
||||
return;
|
||||
@@ -41,8 +42,7 @@ boolean menu_inputstring(INPUTSTRING_PARAM *p) {
|
||||
}
|
||||
|
||||
boolean menu_inputstring2(INPUTSTRING_PARAM *p) {
|
||||
p->newstring = p->oldstring;
|
||||
return TRUE;
|
||||
return sdl_inputString(p);
|
||||
}
|
||||
|
||||
boolean menu_inputnumber(INPUTNUM_PARAM *p) {
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#include "ags.h"
|
||||
#include "cursor.h"
|
||||
|
||||
struct inputstring_param;
|
||||
|
||||
/* 初期化関係 */
|
||||
extern int sdl_Initilize(void);
|
||||
extern void sdl_Remove(void);
|
||||
@@ -102,6 +104,7 @@ extern void sdl_mainIteration();
|
||||
extern boolean RawKeyInfo[];
|
||||
extern void sdl_sleep(int msec);
|
||||
extern void sdl_wait_vsync();
|
||||
extern boolean sdl_inputString(struct inputstring_param *);
|
||||
|
||||
/* 初期化関係 */
|
||||
#define GraphicsInitilize() sdl_Initilize()
|
||||
|
||||
@@ -96,6 +96,10 @@ static void sdl_getEvent(void) {
|
||||
|
||||
while (SDL_PollEvent(&e)) {
|
||||
had_input = true;
|
||||
|
||||
if (sdl_custom_event_handler && sdl_custom_event_handler(&e))
|
||||
continue;
|
||||
|
||||
switch (e.type) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
case SDL_QUIT:
|
||||
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2020 <KichikuouChrome@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#include "sdl_core.h"
|
||||
#include "sdl_private.h"
|
||||
#include "menu.h"
|
||||
#include "nact.h"
|
||||
|
||||
#define XMARGIN 3
|
||||
#define YMARGIN 2
|
||||
|
||||
struct EditorState {
|
||||
INPUTSTRING_PARAM *params;
|
||||
SDL_Rect rect;
|
||||
char *text;
|
||||
char composingText[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
|
||||
int cursor;
|
||||
boolean done;
|
||||
};
|
||||
static struct EditorState *input;
|
||||
|
||||
static void redraw() {
|
||||
const int bgcolor = nact->msg.WinBackgroundColor;
|
||||
const int fgcolor = nact->msg.MsgFontColor;
|
||||
|
||||
ags_fillRectangle(input->rect.x, input->rect.y, input->rect.w, input->rect.h, bgcolor);
|
||||
|
||||
SDL_Rect r = {
|
||||
.x = input->rect.x + XMARGIN,
|
||||
.y = input->rect.y + YMARGIN,
|
||||
.w = input->rect.w - XMARGIN * 2,
|
||||
.h = input->rect.h - YMARGIN * 2,
|
||||
};
|
||||
|
||||
if (*input->text) {
|
||||
int w = sdl_drawString(r.x, r.y, input->text, fgcolor);
|
||||
r.x += w;
|
||||
r.w -= w;
|
||||
}
|
||||
|
||||
if (*input->composingText) {
|
||||
int w = sdl_drawString(r.x, r.y, input->composingText, fgcolor);
|
||||
ags_fillRectangle(r.x, r.y + r.h, w, 2, fgcolor); // underline
|
||||
}
|
||||
|
||||
// FIXME: This doesn't work with propotional fonts!
|
||||
int cursor_x = r.x + r.h * input->cursor;
|
||||
ags_fillRectangle(cursor_x, r.y, 2, r.h, fgcolor); // cursor
|
||||
|
||||
// Dib geometry -> window geometry
|
||||
r.x -= nact->sys_view_area.x;
|
||||
r.y -= nact->sys_view_area.y;
|
||||
SDL_SetTextInputRect(&r);
|
||||
|
||||
ags_updateArea(input->rect.x, input->rect.y, input->rect.w, input->rect.h);
|
||||
}
|
||||
|
||||
static boolean handle_event(const SDL_Event *e) {
|
||||
switch (e->type) {
|
||||
case SDL_KEYDOWN:
|
||||
if (*input->composingText)
|
||||
break; // Let the IME handle this event.
|
||||
switch (e->key.keysym.sym) {
|
||||
case SDLK_RETURN:
|
||||
input->params->newstring = input->text;
|
||||
input->done = TRUE;
|
||||
return TRUE;
|
||||
case SDLK_ESCAPE:
|
||||
input->params->newstring = NULL;
|
||||
input->done = TRUE;
|
||||
return TRUE;
|
||||
case SDLK_BACKSPACE:
|
||||
{
|
||||
char *p = input->text + strlen(input->text) - 1;
|
||||
while (p >= input->text && UTF8_TRAIL_BYTE(*p))
|
||||
p--;
|
||||
if (p >= input->text)
|
||||
*p = '\0';
|
||||
redraw();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
int chars = input->params->max;
|
||||
for (const char *p = input->text; *p; p = advance_char(p, UTF8))
|
||||
chars--;
|
||||
const char *end = e->text.text;
|
||||
while (chars > 0 && *end) {
|
||||
end = advance_char(end, UTF8);
|
||||
chars--;
|
||||
}
|
||||
strncat(input->text, e->text.text, end - e->text.text);
|
||||
|
||||
input->composingText[0] = '\0';
|
||||
input->cursor = 0;
|
||||
redraw();
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case SDL_TEXTEDITING:
|
||||
strncpy(input->composingText, e->edit.text, SDL_TEXTEDITINGEVENT_TEXT_SIZE);
|
||||
input->cursor = e->edit.start;
|
||||
redraw();
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
boolean sdl_inputString(INPUTSTRING_PARAM *p) {
|
||||
static char *buf;
|
||||
free(buf);
|
||||
buf = malloc(p->max * MAX_UTF8_BYTES_PAR_CHAR + 1);
|
||||
|
||||
struct EditorState s = {
|
||||
.params = p,
|
||||
.rect = {
|
||||
.x = p->x + nact->sys_view_area.x, // window geometry -> dib geometry
|
||||
.y = p->y + nact->sys_view_area.y,
|
||||
.w = p->h * p->max + XMARGIN * 2,
|
||||
.h = p->h + YMARGIN * 2
|
||||
},
|
||||
.text = buf,
|
||||
};
|
||||
strcpy(s.text, p->oldstring);
|
||||
input = &s;
|
||||
|
||||
SDL_StartTextInput();
|
||||
|
||||
void *saved_region = ags_saveRegion(s.rect.x, s.rect.y, s.rect.w, s.rect.h);
|
||||
ags_setFont(FONT_GOTHIC, p->h);
|
||||
redraw();
|
||||
|
||||
sdl_custom_event_handler = handle_event;
|
||||
while (!input->done) {
|
||||
sdl_getKeyInfo(); // message pump
|
||||
nact->callback();
|
||||
sdl_wait_vsync();
|
||||
}
|
||||
SDL_StopTextInput();
|
||||
sdl_custom_event_handler = NULL;
|
||||
|
||||
ags_restoreRegion(saved_region, s.rect.x, s.rect.y);
|
||||
ags_updateArea(s.rect.x, s.rect.y, s.rect.w, s.rect.h);
|
||||
|
||||
input = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -59,6 +59,7 @@ struct sdl_private_data {
|
||||
int winoffset_x; /* draw offset in Window x */
|
||||
int winoffset_y; /* y */
|
||||
|
||||
boolean (*custom_event_handler)(const SDL_Event *);
|
||||
};
|
||||
|
||||
extern void sdl_cursor_init(void);
|
||||
@@ -88,6 +89,7 @@ extern struct sdl_private_data *sdl_videodev;
|
||||
#define sdl_fs_on (sdl_videodev->fs_on)
|
||||
#define winoffset_x (sdl_videodev->winoffset_x)
|
||||
#define winoffset_y (sdl_videodev->winoffset_y)
|
||||
#define sdl_custom_event_handler (sdl_videodev->custom_event_handler)
|
||||
|
||||
#define setRect(r,xx,yy,ww,hh) (r).x=(xx),(r).y=(yy),(r).w=(ww),(r).h=(hh)
|
||||
#define setOffset(s,x,y) (s->pixels) + (x) * (s->format->BytesPerPixel) + (y) * s->pitch
|
||||
|
||||
Reference in New Issue
Block a user