Initial commit
This commit is contained in:
314
engines/ultima/nuvie/gui/gui_text_input.cpp
Normal file
314
engines/ultima/nuvie/gui/gui_text_input.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/nuvie/core/nuvie_defs.h"
|
||||
|
||||
#include "ultima/nuvie/gui/gui_text_input.h"
|
||||
#include "ultima/nuvie/gui/gui_font.h"
|
||||
#include "ultima/nuvie/keybinding/keys.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Nuvie {
|
||||
|
||||
GUI_TextInput:: GUI_TextInput(int x, int y, uint8 r, uint8 g, uint8 b, const char *str,
|
||||
GUI_Font *gui_font, uint16 width, uint16 height, GUI_CallBack *callback)
|
||||
: GUI_Text(x, y, r, g, b, gui_font, width), max_height(height), callback_object(callback),
|
||||
cursor_color(0), selected_bgcolor(0) {
|
||||
text = (char *)malloc(max_width * max_height + 1);
|
||||
if (text == nullptr)
|
||||
error("GUI_TextInput failed to allocate memory for text");
|
||||
|
||||
strncpy(text, str, max_width * max_height);
|
||||
|
||||
pos = strlen(text);
|
||||
length = pos;
|
||||
|
||||
area.setWidth(max_width * font->charWidth());
|
||||
area.setHeight(max_height * font->charHeight());
|
||||
}
|
||||
|
||||
GUI_TextInput::~GUI_TextInput() {
|
||||
return;
|
||||
}
|
||||
|
||||
void GUI_TextInput::release_focus() {
|
||||
GUI_Widget::release_focus();
|
||||
|
||||
// SDL_EnableUNICODE(0); //disable unicode.
|
||||
}
|
||||
|
||||
GUI_status GUI_TextInput::MouseUp(int x, int y, Events::MouseButton button) {
|
||||
// if(button == SDL_BUTTON_WHEELUP || button == SDL_BUTTON_WHEELDOWN)
|
||||
// return GUI_PASS;
|
||||
//release focus if we click outside the text box.
|
||||
if (focused && !HitRect(x, y))
|
||||
release_focus();
|
||||
else {
|
||||
if (!focused) {
|
||||
grab_focus();
|
||||
// FIXME SDL2 SDL_EnableUNICODE(1); //turn on unicode processing.
|
||||
}
|
||||
}
|
||||
|
||||
return GUI_PASS;
|
||||
}
|
||||
|
||||
GUI_status GUI_TextInput::KeyDown(const Common::KeyState &keyState) {
|
||||
Common::KeyState key = keyState;
|
||||
char ascii = get_ascii_char_from_keysym(key);
|
||||
|
||||
if (!focused)
|
||||
return GUI_PASS;
|
||||
|
||||
|
||||
if (!Common::isPrint(ascii) && key.keycode != Common::KEYCODE_BACKSPACE) {
|
||||
KeyBinder *keybinder = Game::get_game()->get_keybinder();
|
||||
ActionType a = keybinder->get_ActionType(key);
|
||||
switch (keybinder->GetActionKeyType(a)) {
|
||||
case NORTH_KEY:
|
||||
key.keycode = Common::KEYCODE_UP;
|
||||
break;
|
||||
case SOUTH_KEY:
|
||||
key.keycode = Common::KEYCODE_DOWN;
|
||||
break;
|
||||
case WEST_KEY:
|
||||
key.keycode = Common::KEYCODE_LEFT;
|
||||
break;
|
||||
case EAST_KEY:
|
||||
key.keycode = Common::KEYCODE_RIGHT;
|
||||
break;
|
||||
case TOGGLE_CURSOR_KEY:
|
||||
release_focus();
|
||||
return GUI_PASS; // can tab through to SaveDialog
|
||||
case DO_ACTION_KEY:
|
||||
key.keycode = Common::KEYCODE_RETURN;
|
||||
break;
|
||||
case CANCEL_ACTION_KEY:
|
||||
key.keycode = Common::KEYCODE_ESCAPE;
|
||||
break;
|
||||
case HOME_KEY:
|
||||
key.keycode = Common::KEYCODE_HOME;
|
||||
break;
|
||||
case END_KEY:
|
||||
key.keycode = Common::KEYCODE_END;
|
||||
break;
|
||||
default :
|
||||
if (keybinder->handle_always_available_keys(a)) return GUI_YUM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (key.keycode) {
|
||||
case Common::KEYCODE_LSHIFT:
|
||||
case Common::KEYCODE_RSHIFT:
|
||||
case Common::KEYCODE_LCTRL:
|
||||
case Common::KEYCODE_RCTRL:
|
||||
case Common::KEYCODE_CAPSLOCK:
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_KP_ENTER:
|
||||
case Common::KEYCODE_RETURN:
|
||||
if (callback_object)
|
||||
callback_object->callback(TEXTINPUT_CB_TEXT_READY, this, text);
|
||||
// falls through
|
||||
case Common::KEYCODE_ESCAPE :
|
||||
release_focus();
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_HOME:
|
||||
pos = 0;
|
||||
break;
|
||||
case Common::KEYCODE_END:
|
||||
pos = length;
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_KP4:
|
||||
case Common::KEYCODE_LEFT:
|
||||
if (pos > 0)
|
||||
pos--;
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_KP6:
|
||||
case Common::KEYCODE_RIGHT:
|
||||
if (pos < length)
|
||||
pos++;
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_DELETE :
|
||||
if (pos < length) { //delete the character to the right of the cursor
|
||||
pos++;
|
||||
remove_char();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_BACKSPACE :
|
||||
remove_char();
|
||||
break; //delete the character to the left of the cursor
|
||||
|
||||
case Common::KEYCODE_UP:
|
||||
case Common::KEYCODE_KP8:
|
||||
if (pos == length) {
|
||||
if (length + 1 > max_width * max_height)
|
||||
break;
|
||||
length++;
|
||||
if (pos == 0 || text[pos - 1] == ' ')
|
||||
text[pos] = 'A';
|
||||
else
|
||||
text[pos] = 'a';
|
||||
break;
|
||||
}
|
||||
text[pos]++;
|
||||
// We want alphanumeric characters or space
|
||||
if (text[pos] < ' ' || text[pos] > 'z') {
|
||||
text[pos] = ' ';
|
||||
break;
|
||||
}
|
||||
while (!Common::isAlnum(text[pos]))
|
||||
text[pos]++;
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_KP2:
|
||||
case Common::KEYCODE_DOWN:
|
||||
if (pos == length) {
|
||||
if (length + 1 > max_width * max_height)
|
||||
break;
|
||||
length++;
|
||||
if (pos == 0 || text[pos - 1] == ' ')
|
||||
text[pos] = 'Z';
|
||||
else
|
||||
text[pos] = 'z';
|
||||
break;
|
||||
}
|
||||
text[pos]--;
|
||||
// We want alphanumeric characters or space
|
||||
if (text[pos] < ' ' || text[pos] > 'z') {
|
||||
text[pos] = 'z';
|
||||
break;
|
||||
} else if (text[pos] < '0') {
|
||||
text[pos] = ' ';
|
||||
break;
|
||||
}
|
||||
while (!Common::isAlnum(text[pos]))
|
||||
text[pos]--;
|
||||
break;
|
||||
|
||||
default :
|
||||
if (Common::isPrint(ascii))
|
||||
add_char(ascii);
|
||||
break;
|
||||
}
|
||||
|
||||
return GUI_YUM;
|
||||
}
|
||||
|
||||
void GUI_TextInput::add_char(char c) {
|
||||
uint16 i;
|
||||
|
||||
if (length + 1 > max_width * max_height)
|
||||
return;
|
||||
|
||||
if (pos < length) { //shuffle chars to the right if required.
|
||||
for (i = length; i > pos; i--)
|
||||
text[i] = text[i - 1];
|
||||
}
|
||||
|
||||
length++;
|
||||
|
||||
text[pos] = c;
|
||||
pos++;
|
||||
|
||||
text[length] = '\0';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void GUI_TextInput::remove_char() {
|
||||
uint16 i;
|
||||
|
||||
if (pos == 0)
|
||||
return;
|
||||
|
||||
for (i = pos - 1; i < length; i++)
|
||||
text[i] = text[i + 1];
|
||||
|
||||
pos--;
|
||||
length--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void GUI_TextInput::set_text(const char *new_text) {
|
||||
if (new_text) {
|
||||
strncpy(text, new_text, max_width * max_height);
|
||||
|
||||
pos = strlen(text);
|
||||
length = pos;
|
||||
}
|
||||
}
|
||||
|
||||
/* Map the color to the display */
|
||||
void GUI_TextInput::SetDisplay(Screen *s) {
|
||||
GUI_Widget::SetDisplay(s);
|
||||
cursor_color = surface->format.RGBToColor(0xff, 0, 0);
|
||||
selected_bgcolor = surface->format.RGBToColor(0x5a, 0x6e, 0x91);
|
||||
}
|
||||
|
||||
|
||||
/* Show the widget */
|
||||
void GUI_TextInput:: Display(bool full_redraw) {
|
||||
Common::Rect r;
|
||||
|
||||
if (full_redraw && focused) {
|
||||
r = area;
|
||||
SDL_FillRect(surface, &r, selected_bgcolor);
|
||||
}
|
||||
|
||||
GUI_Text::Display(full_redraw);
|
||||
|
||||
if (focused)
|
||||
display_cursor();
|
||||
|
||||
}
|
||||
|
||||
void GUI_TextInput::display_cursor() {
|
||||
Common::Rect r;
|
||||
uint16 x, y;
|
||||
uint16 cw, ch;
|
||||
|
||||
x = pos % max_width;
|
||||
y = pos / max_width;
|
||||
|
||||
cw = font->charWidth();
|
||||
ch = font->charHeight();
|
||||
|
||||
r.left = area.left + x * cw;
|
||||
r.top = area.top + y * ch;
|
||||
r.setWidth(1);
|
||||
r.setHeight(ch);
|
||||
|
||||
SDL_FillRect(surface, &r, cursor_color);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} // End of namespace Nuvie
|
||||
} // End of namespace Ultima
|
||||
Reference in New Issue
Block a user