diff --git a/demo/src/common.c b/demo/src/common.c index ffb12e0..7d14f6a 100644 --- a/demo/src/common.c +++ b/demo/src/common.c @@ -84,7 +84,7 @@ void commonDraw() { if (mouseWentDown("left")) soundPlay(beep, FALSE); - if (mouseWentDown("middle")) { + if (mouseWentDown("left")) { if (keyDown("any alt")) { answer = askTextf("Test\nformatted text input.\nEnter two numbers: int and double", "%d%lg", &intAnswer, &doubleAnswer); } else { diff --git a/src/font.c b/src/font.c index 23913a9..9702371 100644 --- a/src/font.c +++ b/src/font.c @@ -376,10 +376,12 @@ static void expand(double *min, double *max, double x) { } -TextLayout createTextLayout(const char *text) { +TextLayout createTextLayoutEx(const char *text, int length) { TextLayout layout = calloc(1, sizeof(*layout)); - if (!text) return layout; + int len = 0; + while(len < length && text[len]) ++len; + if (!text || !len) return layout; HeliDrawingState *drawingState = heliDrawingGetState(); @@ -414,7 +416,7 @@ TextLayout createTextLayout(const char *text) { line->xheight = fonts[0]->xheight; line->ascender = fonts[0]->ascender; line->descender = fonts[0]->descender; - layout->chars = calloc(strlen(text) + 1, sizeof(HeliCharDesc)); + layout->chars = calloc(len + 1, sizeof(HeliCharDesc)); if ( drawingState->font && drawingState->font != defaultFont && drawingState->font != unicodeFont @@ -422,27 +424,31 @@ TextLayout createTextLayout(const char *text) { layout->font = fontClone(drawingState->font); // gather glyphs - const char *c = text; + const char *c = text, *e = c + len, *e1 = e - 1, *e2 = e - 2; while(1) { - const char *charpos = c; int code = FONT_BADCHAR_CODE; - while((*c & 0xC0) == 0x80) ++c; - if ((*c & 0x80) == 0x00) { - code = *c; - } else - if ((*c & 0xE0) == 0xC0) { - if ((c[1] & 0xC0) == 0x80) { - code = ((c[0] & 0x1F) << 6) | (c[1] & 0x3F); - c += 1; - } - } else - if ((*c & 0xF0) == 0xE0) { - if ((c[1] & 0xC0) == 0x80 && (c[2] & 0xC0) == 0x80) { - code = ((c[0] & 0x0F) << 12) | ((c[1] & 0x3F) << 6) | (c[2] & 0x3F); - c += 2; + while(c < e && (*c & 0xC0) == 0x80) ++c; + const char *charpos = c; + if (c < e) { + if ((*c & 0x80) == 0x00) { + code = *c; + } else + if ((*c & 0xE0) == 0xC0) { + if (c < e1 && (c[1] & 0xC0) == 0x80) { + code = ((c[0] & 0x1F) << 6) | (c[1] & 0x3F); + c += 1; + } + } else + if ((*c & 0xF0) == 0xE0) { + if (c < e2 && (c[1] & 0xC0) == 0x80 && (c[2] & 0xC0) == 0x80) { + code = ((c[0] & 0x0F) << 12) | ((c[1] & 0x3F) << 6) | (c[2] & 0x3F); + c += 2; + } } + ++c; + } else { + code = 0; } - ++c; HeliGlyph *glyph = &blankGlyph; int code2 = (code == 0 || code == 10 || code == 13) ? 32 : code; @@ -589,6 +595,10 @@ TextLayout createTextLayout(const char *text) { } +TextLayout createTextLayout(const char *text) + { return createTextLayoutEx(text, strlen(text)); } + + TextLayout createTextLayoutf(const char *format, ...) { va_list args; va_start(args, format); diff --git a/src/font.h b/src/font.h index 61d59b7..ec24459 100644 --- a/src/font.h +++ b/src/font.h @@ -37,6 +37,7 @@ void textSize(double size); TextLayout createTextLayout(const char *text); +TextLayout createTextLayoutEx(const char *text, int length); TextLayout createTextLayoutf(const char *format, ...); void textLayoutDestroy(TextLayout layout); void textLayoutDraw(TextLayout layout, double x, double y); diff --git a/src/private.h b/src/private.h index 7907119..7fcfa66 100644 --- a/src/private.h +++ b/src/private.h @@ -298,7 +298,6 @@ typedef struct _HeliDialog { double scrollX; double scrollY; int success; - char newText[4096]; } HeliDialog; void heliDialogDraw(HeliDialog *dialog); diff --git a/src/window.c b/src/window.c index d2fc879..333d4cf 100644 --- a/src/window.c +++ b/src/window.c @@ -1,5 +1,6 @@ #include +#include #include @@ -44,6 +45,10 @@ static double frameTime = 1.0/HELI_DEFAULT_FPS; static HeliArray keyEvents[6]; static int keyEventsCount = (int)(sizeof(keyEvents)/sizeof(*keyEvents)); +static int textInputActive; +static char *textInput; +static int textInputSize; + static int mouseMovedInFrame; static double _mouseX; static double _mouseY; @@ -194,6 +199,17 @@ int keyWentDown(const char *code) int keyWentUp(const char *code) { return keyEventAliasesCheck(KEYEVENT_KEY_WENTUP, code); } + +const char* textInputGet() + { return textInput ? textInput : ""; } +void textInputClear() + { if (textInput) *textInput = 0; } +void textInputBegin() + { if (!textInputActive) { SDL_StartTextInput(); textInputActive = TRUE; } } +void textInputEnd() + { if (textInputActive) { SDL_StopTextInput(); textInputActive = FALSE; } } + + int mouseDidMove() { return mouseMovedInFrame; } int mouseDown(const char *code) @@ -234,6 +250,20 @@ static void resize(int w, int h) { } } + +const char* windowGetClipboardText() + { const char *t = SDL_GetClipboardText(); return t ? t : ""; } +void windowSetClipboardText(const char *text) + { SDL_SetClipboardText(text); } +void windowSetClipboardTextEx(const char *text, int len) { + if (len <= 0) return; + char *t = malloc(len + 1); + memcpy(t, text, len); + t[len] = 0; + windowSetClipboardText(t); + free(t); +} + int windowGetWidth() { return width; } void windowSetWidth(int w) @@ -395,7 +425,6 @@ int askTextf(const char *question, const char *format, ...) { static void resetEvents() { - dialog.newText[0] = 0; _mouseScrolledX = _mouseScrolledY = 0; heliArrayClear(&keyEvents[KEYEVENT_KEY_WENTDOWN]); heliArrayClear(&keyEvents[KEYEVENT_KEY_WENTUP]); @@ -602,14 +631,24 @@ static void handleEvent(SDL_Event *e) { _mouseScrolledY += e->wheel.y; } else if (e->type == SDL_TEXTINPUT) { - if (dialog.shown) { - int len = strlen(dialog.newText); + if (*e->text.text) { + int oldlen = textInput ? strlen(textInput) : 0; int newlen = strlen(e->text.text); - int dl = len + newlen + 1 - sizeof(dialog.newText); - if (dl > 0) newlen -= dl; - if (newlen > 0) { - memcpy(dialog.newText + len, e->text.text, newlen); - dialog.newText[len + newlen] = 0; + int size = oldlen + newlen + 1; + if (size > 0) { + if (size > textInputSize) { + int newsize = ((size + size/16 - 1)/1024 + 1)*1024; + if (newsize < 0) newsize = INT_MAX; + if (newsize > textInputSize) { + textInput = realloc(textInput, newsize); + textInputSize = newsize; + textInput[textInputSize - 1] = 0; + } + } + if (size <= textInputSize) { + memcpy(textInput + oldlen, e->text.text, newlen); + textInput[oldlen + newlen] = 0; + } } } } @@ -631,14 +670,15 @@ int askTextEx(const char *question, char *answer, int maxAnswerSize, int multili dialog.pos = dialog.selPos = strlen(dialog.answer); dialog.success = FALSE; - SDL_StartTextInput(); + int tiActive = textInputActive; + textInputBegin(); while(dialog.shown && !stopped) { SDL_Event event; while (SDL_PollEvent(&event)) handleEvent(&event); draw(); } - SDL_StopTextInput(); + if (!tiActive) textInputEnd(); int success = dialog.success; if (dialog.success && maxAnswerSize > 0) strcpy(answer, dialog.answer); @@ -700,6 +740,9 @@ void windowRun() { heliSoundFinish(); heliArrayDestroy(&heliObjectsSet); + free(textInput); + textInputSize = 0; + heliInitialized = FALSE; deinit(); diff --git a/src/window.h b/src/window.h index d80a170..ec90965 100644 --- a/src/window.h +++ b/src/window.h @@ -24,7 +24,12 @@ int keyWentDown(const char *code); int keyWentUp(const char *code); int keyEventGetCount(KeyEvent mode); -const char *keyEventGet(KeyEvent mode, int i); +const char* keyEventGet(KeyEvent mode, int i); + +const char* textInputGet(); +void textInputClear(); +void textInputBegin(); +void textInputEnd(); int mouseDidMove(); int mouseDown(const char *code); @@ -45,6 +50,10 @@ int askText(const char *question, char *answer, int maxAnswerSize); int askTextf(const char *question, const char *format, ...); int askTextEx(const char *question, char *answer, int maxAnswerSize, int multiline, int password); +const char* windowGetClipboardText(); +void windowSetClipboardText(const char *text); +void windowSetClipboardTextEx(const char *text, int len); + int windowGetWidth(); void windowSetWidth(int width); diff --git a/src/windowui.c b/src/windowui.c index 6c72775..ba872fe 100644 --- a/src/windowui.c +++ b/src/windowui.c @@ -276,7 +276,8 @@ static void draw(HeliDialog *dialog) { void heliDialogDraw(HeliDialog *dialog) { - if (dialog->newText[0]) insert(dialog, dialog->newText); + if (*textInputGet()) insert(dialog, textInputGet()); + textInputClear(); int shift = keyDown("any shift"); int ctrl = keyDown("any ctrl");