/* * Copyright (c) 2002-2008 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Basic keyboard input processing in ASCII mode. */ #include #include #include "widget.h" #include "editable.h" #include "keymap.h" #include "text.h" #include #include /* Emulate "shift" key for US keyboard layout. */ /* XXX move to keymap */ static Uint32 EmulateShiftUSKBD(Uint32 key) { if (isalpha(key)) { return (toupper(key)); } else { switch (key) { case SDLK_1: return ('!'); case SDLK_2: return ('@'); case SDLK_3: return ('#'); case SDLK_4: return ('$'); case SDLK_5: return ('%'); case SDLK_6: return ('^'); case SDLK_7: return ('&'); case SDLK_8: return ('*'); case SDLK_9: return ('('); case SDLK_0: return (')'); case SDLK_BACKQUOTE: return ('~'); case SDLK_MINUS: return ('_'); case SDLK_EQUALS: return ('+'); case SDLK_LEFTBRACKET: return ('{'); case SDLK_RIGHTBRACKET: return ('}'); case SDLK_BACKSLASH: return ('|'); case SDLK_SEMICOLON: return (':'); case SDLK_QUOTE: return ('"'); case SDLK_COMMA: return ('<'); case SDLK_PERIOD: return ('>'); case SDLK_SLASH: return ('?'); } } return ('?'); } /* Apply modifiers (when not using Unicode keyboard translation). */ Uint32 AG_ApplyModifiersASCII(Uint32 key, int kmod) { if (kmod & KMOD_CAPS) { if (kmod & KMOD_SHIFT) { return (Uint32)tolower((int)key); } else { return (EmulateShiftUSKBD(key)); } } else { if (kmod & KMOD_SHIFT) { return (EmulateShiftUSKBD(key)); } else { return (key); } } } static int InsertASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 unicode, char *s, int len, int lenMax) { Uint32 ins[3]; int nins, i; char ch; if (AG_WidgetDisabled(ed)) return (0); if (keysym == 0 || !isascii(keysym)) return (0); ch = (char)AG_ApplyModifiersASCII((Uint32)keysym, keymod); if (ch == 0) { return (0); } if (ch == '\r') { ch = '\n'; } switch (ed->encoding) { case AG_ENCODING_UTF8: break; case AG_ENCODING_ASCII: if (!isascii((int)ch)) { return (0); } break; } if (AG_GetBool(agConfig,"input.composition")) { if ((nins = AG_KeyInputCompose(ed, (Uint32)ch, ins)) == 0) return (0); } else { ins[0] = (Uint32)ch; nins = 1; } if (len+nins >= lenMax) { return (0); } ins[nins] = '\0'; if (ed->pos == len) { /* Append */ for (i = 0; i < nins+1; i++) s[len+i] = ins[i]; } else { /* Insert */ char *p = &s[ed->pos]; memcpy(&p[nins], &p[0], (len - ed->pos)); for (i = 0; i < nins; i++) { p[i] = ins[i]; } s[len+1] = '\0'; } ed->pos++; return (1); } static int DeleteASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 unicode, char *s, int len, int lenMax) { char *c; if (AG_WidgetDisabled(ed)) return (0); if (len == 0) return (0); switch (keysym) { case SDLK_BACKSPACE: if (ed->pos == 0) { return (0); } if (ed->pos == len) { s[len-1] = '\0'; ed->pos--; return (1); } ed->pos--; break; case SDLK_DELETE: if (ed->pos == len) { s[len-1] = '\0'; ed->pos--; return (1); } break; default: break; } for (c = &s[ed->pos]; c[1] != '\0'; c++) { *c = c[1]; } *c = '\0'; return (1); } static int KillASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { if (AG_WidgetDisabled(ed)) return (0); /* TODO Save to a kill buffer, etc. */ s[ed->pos] = '\0'; return (1); } static int YankASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { if (AG_WidgetDisabled(ed)) return (0); /* TODO */ return (1); } static int WordBackASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { /* TODO */ ed->flags |= AG_EDITABLE_MARKPREF; return (0); } static int WordForwASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { /* TODO */ ed->flags |= AG_EDITABLE_MARKPREF; return (0); } static int CursorHomeASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { ed->pos = 0; ed->flags |= AG_EDITABLE_MARKPREF; return (0); } static int CursorEndASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { ed->pos = len; ed->flags |= AG_EDITABLE_MARKPREF; return (0); } static int CursorLeftASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { if (--ed->pos < 1) { ed->pos = 0; } ed->flags |= AG_EDITABLE_MARKPREF; return (0); } static int CursorRightASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { if (ed->pos < len) { ed->pos++; } ed->flags |= AG_EDITABLE_MARKPREF; return (0); } static int CursorUpASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { char *p; if ((p = strrchr(&s[ed->pos], '\n')) != NULL) { ed->pos -= (s - p); } return (0); } static int CursorDownASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { char *p; if ((p = strchr(&s[ed->pos], '\n')) != NULL) { ed->pos -= (p - s); } return (0); } static int PageUpASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { AG_EditableMoveCursor(ed, ed->xCurs, (ed->yCurs - ed->y - ed->yVis*2 + 2)*agTextFontLineSkip + 1, 1); return (0); } static int PageDownASCII(AG_Editable *ed, SDLKey keysym, int keymod, Uint32 uch, char *s, int len, int lenMax) { AG_EditableMoveCursor(ed, ed->xCurs, (ed->yCurs - ed->y + ed->yVis*2 - 2)*agTextFontLineSkip + 1, 1); return (0); } const struct ag_keycode_ascii agKeymapASCII[] = { { SDLK_HOME, 0, CursorHomeASCII }, { SDLK_a, KMOD_CTRL, CursorHomeASCII }, { SDLK_END, 0, CursorEndASCII }, { SDLK_e, KMOD_CTRL, CursorEndASCII }, { SDLK_LEFT, 0, CursorLeftASCII }, { SDLK_RIGHT, 0, CursorRightASCII }, { SDLK_UP, 0, CursorUpASCII }, { SDLK_DOWN, 0, CursorDownASCII }, { SDLK_PAGEUP, 0, PageUpASCII }, { SDLK_PAGEDOWN, 0, PageDownASCII }, { SDLK_BACKSPACE, 0, DeleteASCII }, { SDLK_DELETE, 0, DeleteASCII }, { SDLK_k, KMOD_CTRL, KillASCII }, { SDLK_y, KMOD_CTRL, YankASCII }, { SDLK_b, KMOD_ALT, WordBackASCII }, { SDLK_f, KMOD_ALT, WordForwASCII }, { SDLK_LAST, 0, InsertASCII }, };