summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/gui.cpp8
-rw-r--r--src/gui/gui.h3
-rw-r--r--src/gui/sdlinput.cpp429
-rw-r--r--src/gui/sdlinput.h188
-rw-r--r--src/gui/textfield.cpp129
-rw-r--r--src/gui/textfield.h2
-rw-r--r--src/gui/viewport.cpp2
7 files changed, 724 insertions, 37 deletions
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index f33d9495..7cf1881c 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -24,11 +24,9 @@
#include <guichan/imagefont.hpp>
#include <SDL/SDL_ttf.h>
-// Should stay here because of Guichan being sensitive to headers order
-#include <guichan/sdl/sdlinput.hpp>
-
#include "focushandler.h"
#include "gui.h"
+#include "sdlinput.h"
#include "truetypefont.h"
#include "viewport.h"
#include "window.h"
@@ -47,7 +45,7 @@
// Guichan stuff
Gui *gui;
Viewport *viewport; /**< Viewport on the map. */
-gcn::SDLInput *guiInput; /**< GUI input. */
+SDLInput *guiInput; /**< GUI input. */
// Fonts used in showing hits
gcn::Font *hitRedFont;
@@ -97,7 +95,7 @@ Gui::Gui(Graphics *graphics):
gcn::Image::setImageLoader(&imageLoader);
// Set input
- guiInput = new gcn::SDLInput();
+ guiInput = new SDLInput;
setInput(guiInput);
// Set focus handler
diff --git a/src/gui/gui.h b/src/gui/gui.h
index f56b1dbf..eb81b87c 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -29,6 +29,7 @@
class Graphics;
class GuiConfigListener;
class ImageSet;
+class SDLInput;
class Viewport;
/**
@@ -115,7 +116,7 @@ class Gui : public gcn::Gui
extern Gui *gui; /**< The GUI system */
extern Viewport *viewport; /**< The viewport */
-extern gcn::SDLInput *guiInput; /**< GUI input */
+extern SDLInput *guiInput; /**< GUI input */
/**
* Fonts used in showing hits
diff --git a/src/gui/sdlinput.cpp b/src/gui/sdlinput.cpp
new file mode 100644
index 00000000..ee94b2c6
--- /dev/null
+++ b/src/gui/sdlinput.cpp
@@ -0,0 +1,429 @@
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson
+ * Copyright 2007 The Mana World Development Team
+ *
+ * Js_./
+ * Per Larsson a.k.a finalman _RqZ{a<^_aa
+ * Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
+ * _Qhm`] _f "'c 1!5m
+ * Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
+ * .)j(] .d_/ '-( P . S
+ * License: (BSD) <Td/Z <fP"5(\"??"\a. .L
+ * Redistribution and use in source and _dV>ws?a-?' ._/L #'
+ * binary forms, with or without )4d[#7r, . ' )d`)[
+ * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam'
+ * that the following conditions are met: j<<WP+k/);. _W=j f
+ * 1. Redistributions of source code must .$%w\/]Q . ."' . mj$
+ * retain the above copyright notice, ]E.pYY(Q]>. a J@\
+ * this list of conditions and the j(]1u<sE"L,. . ./^ ]{a
+ * following disclaimer. 4'_uomm\. )L);-4 (3=
+ * 2. Redistributions in binary form must )_]X{Z('a_"a7'<a"a, ]"[
+ * reproduce the above copyright notice, #}<]m7`Za??4,P-"'7. ).m
+ * this list of conditions and the ]d2e)Q(<Q( ?94 b- LQ/
+ * following disclaimer in the <B!</]C)d_, '(<' .f. =C+m
+ * documentation and/or other materials .Z!=J ]e []('-4f _ ) -.)m]'
+ * provided with the distribution. .w[5]' _[ /.)_-"+? _/ <W"
+ * 3. Neither the name of Guichan nor the :$we` _! + _/ . j?
+ * names of its contributors may be used =3)= _f (_yQmWW$#( "
+ * to endorse or promote products derived - W, sQQQQmZQ#Wwa]..
+ * from this software without specific (js, \[QQW$QWW#?!V"".
+ * prior written permission. ]y:.<\.. .
+ * -]n w/ ' [.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT )/ )/ !
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY < (; sac , '
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, ]^ .- %
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF c < r
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR aga< <La
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 5% )P'-3L
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR _bQf` y`..)a
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ,J?4P'.P"_(\?d'.,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES _Pa,)!f/<[]/ ?"
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT _2-..:. .r+_,.. .
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ?a.<%"' " -'.a_ _,
+ * 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.
+ */
+
+#include "sdlinput.h"
+
+#include <guichan/exception.hpp>
+
+SDLInput::SDLInput()
+{
+ mMouseInWindow = true;
+ mMouseDown = false;
+}
+
+bool SDLInput::isKeyQueueEmpty()
+{
+ return mKeyInputQueue.empty();
+}
+
+gcn::KeyInput SDLInput::dequeueKeyInput()
+{
+ gcn::KeyInput keyInput;
+
+ if (mKeyInputQueue.empty())
+ {
+ throw GCN_EXCEPTION("The queue is empty.");
+ }
+
+ keyInput = mKeyInputQueue.front();
+ mKeyInputQueue.pop();
+
+ return keyInput;
+}
+
+bool SDLInput::isMouseQueueEmpty()
+{
+ return mMouseInputQueue.empty();
+}
+
+gcn::MouseInput SDLInput::dequeueMouseInput()
+{
+ gcn::MouseInput mouseInput;
+
+ if (mMouseInputQueue.empty())
+ {
+ throw GCN_EXCEPTION("The queue is empty.");
+ }
+
+ mouseInput = mMouseInputQueue.front();
+ mMouseInputQueue.pop();
+
+ return mouseInput;
+}
+
+void SDLInput::pushInput(SDL_Event event)
+{
+ gcn::KeyInput keyInput;
+ gcn::MouseInput mouseInput;
+
+ switch (event.type)
+ {
+ case SDL_KEYDOWN:
+ keyInput.setKey(gcn::Key(convertKeyCharacter(event)));
+ keyInput.setType(gcn::KeyInput::PRESSED);
+ keyInput.setShiftPressed(event.key.keysym.mod & KMOD_SHIFT);
+ keyInput.setControlPressed(event.key.keysym.mod & KMOD_CTRL);
+ keyInput.setAltPressed(event.key.keysym.mod & KMOD_ALT);
+ keyInput.setMetaPressed(event.key.keysym.mod & KMOD_META);
+ keyInput.setNumericPad(event.key.keysym.sym >= SDLK_KP0
+ && event.key.keysym.sym <= SDLK_KP_EQUALS);
+
+ mKeyInputQueue.push(keyInput);
+ break;
+
+ case SDL_KEYUP:
+ keyInput.setKey(gcn::Key(convertKeyCharacter(event)));
+ keyInput.setType(gcn::KeyInput::RELEASED);
+ keyInput.setShiftPressed(event.key.keysym.mod & KMOD_SHIFT);
+ keyInput.setControlPressed(event.key.keysym.mod & KMOD_CTRL);
+ keyInput.setAltPressed(event.key.keysym.mod & KMOD_ALT);
+ keyInput.setMetaPressed(event.key.keysym.mod & KMOD_META);
+ keyInput.setNumericPad(event.key.keysym.sym >= SDLK_KP0
+ && event.key.keysym.sym <= SDLK_KP_EQUALS);
+
+ mKeyInputQueue.push(keyInput);
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ mMouseDown = true;
+ mouseInput.setX(event.button.x);
+ mouseInput.setY(event.button.y);
+ mouseInput.setButton(convertMouseButton(event.button.button));
+
+ if (event.button.button == SDL_BUTTON_WHEELDOWN)
+ {
+ mouseInput.setType(gcn::MouseInput::WHEEL_MOVED_DOWN);
+ }
+ else if (event.button.button == SDL_BUTTON_WHEELUP)
+ {
+ mouseInput.setType(gcn::MouseInput::WHEEL_MOVED_UP);
+ }
+ else
+ {
+ mouseInput.setType(gcn::MouseInput::PRESSED);
+ }
+ mouseInput.setTimeStamp(SDL_GetTicks());
+ mMouseInputQueue.push(mouseInput);
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ mMouseDown = false;
+ mouseInput.setX(event.button.x);
+ mouseInput.setY(event.button.y);
+ mouseInput.setButton(convertMouseButton(event.button.button));
+ mouseInput.setType(gcn::MouseInput::RELEASED);
+ mouseInput.setTimeStamp(SDL_GetTicks());
+ mMouseInputQueue.push(mouseInput);
+ break;
+
+ case SDL_MOUSEMOTION:
+ mouseInput.setX(event.button.x);
+ mouseInput.setY(event.button.y);
+ mouseInput.setButton(gcn::MouseInput::EMPTY);
+ mouseInput.setType(gcn::MouseInput::MOVED);
+ mouseInput.setTimeStamp(SDL_GetTicks());
+ mMouseInputQueue.push(mouseInput);
+ break;
+
+ case SDL_ACTIVEEVENT:
+ /*
+ * This occurs when the mouse leaves the window and the Gui-chan
+ * application loses its mousefocus.
+ */
+ if ((event.active.state & SDL_APPMOUSEFOCUS)
+ && !event.active.gain)
+ {
+ mMouseInWindow = false;
+
+ if (!mMouseDown)
+ {
+ mouseInput.setX(-1);
+ mouseInput.setY(-1);
+ mouseInput.setButton(gcn::MouseInput::EMPTY);
+ mouseInput.setType(gcn::MouseInput::MOVED);
+ mMouseInputQueue.push(mouseInput);
+ }
+ }
+
+ if ((event.active.state & SDL_APPMOUSEFOCUS)
+ && event.active.gain)
+ {
+ mMouseInWindow = true;
+ }
+ break;
+
+ } // end switch
+}
+
+int SDLInput::convertMouseButton(int button)
+{
+ switch (button)
+ {
+ case SDL_BUTTON_LEFT:
+ return gcn::MouseInput::LEFT;
+ case SDL_BUTTON_RIGHT:
+ return gcn::MouseInput::RIGHT;
+ case SDL_BUTTON_MIDDLE:
+ return gcn::MouseInput::MIDDLE;
+ default:
+ // We have an unknown mouse type which is ignored.
+ return button;
+ }
+}
+
+int SDLInput::convertKeyCharacter(SDL_Event event)
+{
+ SDL_keysym keysym = event.key.keysym;
+
+ int value = keysym.unicode;
+
+ switch (keysym.sym)
+ {
+ case SDLK_TAB:
+ value = Key::TAB;
+ break;
+ case SDLK_LALT:
+ value = Key::LEFT_ALT;
+ break;
+ case SDLK_RALT:
+ value = Key::RIGHT_ALT;
+ break;
+ case SDLK_LSHIFT:
+ value = Key::LEFT_SHIFT;
+ break;
+ case SDLK_RSHIFT:
+ value = Key::RIGHT_SHIFT;
+ break;
+ case SDLK_LCTRL:
+ value = Key::LEFT_CONTROL;
+ break;
+ case SDLK_RCTRL:
+ value = Key::RIGHT_CONTROL;
+ break;
+ case SDLK_BACKSPACE:
+ value = Key::BACKSPACE;
+ break;
+ case SDLK_PAUSE:
+ value = Key::PAUSE;
+ break;
+ case SDLK_SPACE:
+ // Special characters like ~ (tilde) ends up
+ // with the keysym.sym SDLK_SPACE which
+ // without this check would be lost. The check
+ // is only valid on key down events in SDL.
+ if (event.type == SDL_KEYUP || keysym.unicode == ' ')
+ {
+ value = Key::SPACE;
+ }
+ break;
+ case SDLK_ESCAPE:
+ value = Key::ESCAPE;
+ break;
+ case SDLK_DELETE:
+ value = Key::DELETE;
+ break;
+ case SDLK_INSERT:
+ value = Key::INSERT;
+ break;
+ case SDLK_HOME:
+ value = Key::HOME;
+ break;
+ case SDLK_END:
+ value = Key::END;
+ break;
+ case SDLK_PAGEUP:
+ value = Key::PAGE_UP;
+ break;
+ case SDLK_PRINT:
+ value = Key::PRINT_SCREEN;
+ break;
+ case SDLK_PAGEDOWN:
+ value = Key::PAGE_DOWN;
+ break;
+ case SDLK_F1:
+ value = Key::F1;
+ break;
+ case SDLK_F2:
+ value = Key::F2;
+ break;
+ case SDLK_F3:
+ value = Key::F3;
+ break;
+ case SDLK_F4:
+ value = Key::F4;
+ break;
+ case SDLK_F5:
+ value = Key::F5;
+ break;
+ case SDLK_F6:
+ value = Key::F6;
+ break;
+ case SDLK_F7:
+ value = Key::F7;
+ break;
+ case SDLK_F8:
+ value = Key::F8;
+ break;
+ case SDLK_F9:
+ value = Key::F9;
+ break;
+ case SDLK_F10:
+ value = Key::F10;
+ break;
+ case SDLK_F11:
+ value = Key::F11;
+ break;
+ case SDLK_F12:
+ value = Key::F12;
+ break;
+ case SDLK_F13:
+ value = Key::F13;
+ break;
+ case SDLK_F14:
+ value = Key::F14;
+ break;
+ case SDLK_F15:
+ value = Key::F15;
+ break;
+ case SDLK_NUMLOCK:
+ value = Key::NUM_LOCK;
+ break;
+ case SDLK_CAPSLOCK:
+ value = Key::CAPS_LOCK;
+ break;
+ case SDLK_SCROLLOCK:
+ value = Key::SCROLL_LOCK;
+ break;
+ case SDLK_RMETA:
+ value = Key::RIGHT_META;
+ break;
+ case SDLK_LMETA:
+ value = Key::LEFT_META;
+ break;
+ case SDLK_LSUPER:
+ value = Key::LEFT_SUPER;
+ break;
+ case SDLK_RSUPER:
+ value = Key::RIGHT_SUPER;
+ break;
+ case SDLK_MODE:
+ value = Key::ALT_GR;
+ break;
+ case SDLK_UP:
+ value = Key::UP;
+ break;
+ case SDLK_DOWN:
+ value = Key::DOWN;
+ break;
+ case SDLK_LEFT:
+ value = Key::LEFT;
+ break;
+ case SDLK_RIGHT:
+ value = Key::RIGHT;
+ break;
+ case SDLK_RETURN:
+ value = Key::ENTER;
+ break;
+ case SDLK_KP_ENTER:
+ value = Key::ENTER;
+ break;
+
+ default:
+ break;
+ }
+
+ if (!(keysym.mod & KMOD_NUM))
+ {
+ switch (keysym.sym)
+ {
+ case SDLK_KP0:
+ value = Key::INSERT;
+ break;
+ case SDLK_KP1:
+ value = Key::END;
+ break;
+ case SDLK_KP2:
+ value = Key::DOWN;
+ break;
+ case SDLK_KP3:
+ value = Key::PAGE_DOWN;
+ break;
+ case SDLK_KP4:
+ value = Key::LEFT;
+ break;
+ case SDLK_KP5:
+ value = 0;
+ break;
+ case SDLK_KP6:
+ value = Key::RIGHT;
+ break;
+ case SDLK_KP7:
+ value = Key::HOME;
+ break;
+ case SDLK_KP8:
+ value = Key::UP;
+ break;
+ case SDLK_KP9:
+ value = Key::PAGE_UP;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return value;
+}
diff --git a/src/gui/sdlinput.h b/src/gui/sdlinput.h
new file mode 100644
index 00000000..72d949e1
--- /dev/null
+++ b/src/gui/sdlinput.h
@@ -0,0 +1,188 @@
+/* _______ __ __ __ ______ __ __ _______ __ __
+ * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
+ * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
+ * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson
+ * Copyright 2007 The Mana World Development Team
+ *
+ * Js_./
+ * Per Larsson a.k.a finalman _RqZ{a<^_aa
+ * Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
+ * _Qhm`] _f "'c 1!5m
+ * Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
+ * .)j(] .d_/ '-( P . S
+ * License: (BSD) <Td/Z <fP"5(\"??"\a. .L
+ * Redistribution and use in source and _dV>ws?a-?' ._/L #'
+ * binary forms, with or without )4d[#7r, . ' )d`)[
+ * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam'
+ * that the following conditions are met: j<<WP+k/);. _W=j f
+ * 1. Redistributions of source code must .$%w\/]Q . ."' . mj$
+ * retain the above copyright notice, ]E.pYY(Q]>. a J@\
+ * this list of conditions and the j(]1u<sE"L,. . ./^ ]{a
+ * following disclaimer. 4'_uomm\. )L);-4 (3=
+ * 2. Redistributions in binary form must )_]X{Z('a_"a7'<a"a, ]"[
+ * reproduce the above copyright notice, #}<]m7`Za??4,P-"'7. ).m
+ * this list of conditions and the ]d2e)Q(<Q( ?94 b- LQ/
+ * following disclaimer in the <B!</]C)d_, '(<' .f. =C+m
+ * documentation and/or other materials .Z!=J ]e []('-4f _ ) -.)m]'
+ * provided with the distribution. .w[5]' _[ /.)_-"+? _/ <W"
+ * 3. Neither the name of Guichan nor the :$we` _! + _/ . j?
+ * names of its contributors may be used =3)= _f (_yQmWW$#( "
+ * to endorse or promote products derived - W, sQQQQmZQ#Wwa]..
+ * from this software without specific (js, \[QQW$QWW#?!V"".
+ * prior written permission. ]y:.<\.. .
+ * -]n w/ ' [.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT )/ )/ !
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY < (; sac , '
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, ]^ .- %
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF c < r
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR aga< <La
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 5% )P'-3L
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR _bQf` y`..)a
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ,J?4P'.P"_(\?d'.,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES _Pa,)!f/<[]/ ?"
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT _2-..:. .r+_,.. .
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ?a.<%"' " -'.a_ _,
+ * 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.
+ */
+
+#ifndef _TMW_SDLINPUT_
+#define _TMW_SDLINPUT_
+
+#include <queue>
+
+#include <SDL/SDL.h>
+
+#include <guichan/input.hpp>
+#include <guichan/keyinput.hpp>
+#include <guichan/mouseinput.hpp>
+#include <guichan/platform.hpp>
+
+namespace Key
+{
+ enum
+ {
+ SPACE = ' ',
+ TAB = '\t',
+ ENTER = '\n',
+ // Negative values, to avoid conflicts with higher character codes.
+ LEFT_ALT = -1000,
+ RIGHT_ALT,
+ LEFT_SHIFT,
+ RIGHT_SHIFT,
+ LEFT_CONTROL,
+ RIGHT_CONTROL,
+ LEFT_META,
+ RIGHT_META,
+ LEFT_SUPER,
+ RIGHT_SUPER,
+ INSERT,
+ HOME,
+ PAGE_UP,
+ DELETE,
+ END,
+ PAGE_DOWN,
+ ESCAPE,
+ CAPS_LOCK,
+ BACKSPACE,
+ F1,
+ F2,
+ F3,
+ F4,
+ F5,
+ F6,
+ F7,
+ F8,
+ F9,
+ F10,
+ F11,
+ F12,
+ F13,
+ F14,
+ F15,
+ PRINT_SCREEN,
+ SCROLL_LOCK,
+ PAUSE,
+ NUM_LOCK,
+ ALT_GR,
+ LEFT,
+ RIGHT,
+ UP,
+ DOWN
+ };
+}
+
+/**
+ * SDL implementation of Input.
+ */
+class SDLInput : public gcn::Input
+{
+public:
+
+ /**
+ * Constructor.
+ */
+ SDLInput();
+
+ /**
+ * Pushes an SDL event. It should be called at least once per frame to
+ * update input with user input.
+ *
+ * @param event an event from SDL.
+ */
+ virtual void pushInput(SDL_Event event);
+
+ /**
+ * Polls all input. It exists for input driver compatibility. If you
+ * only use SDL and plan sticking with SDL you can safely ignore this
+ * function as it in the SDL case does nothing.
+ */
+ virtual void _pollInput() { }
+
+
+ // Inherited from Input
+
+ virtual bool isKeyQueueEmpty();
+
+ virtual gcn::KeyInput dequeueKeyInput();
+
+ virtual bool isMouseQueueEmpty();
+
+ virtual gcn::MouseInput dequeueMouseInput();
+
+protected:
+ /**
+ * Converts a mouse button from SDL to a Guichan mouse button
+ * representation.
+ *
+ * @param button an SDL mouse button.
+ * @return a Guichan mouse button.
+ */
+ int convertMouseButton(int button);
+
+ /**
+ * Converts an SDL event key to a key value.
+ *
+ * @param event an SDL event with a key to convert.
+ * @return a key value.
+ * @see Key
+ */
+ int convertKeyCharacter(SDL_Event event);
+
+ std::queue<gcn::KeyInput> mKeyInputQueue;
+ std::queue<gcn::MouseInput> mMouseInputQueue;
+
+ bool mMouseDown;
+ bool mMouseInWindow;
+};
+
+#endif
diff --git a/src/gui/textfield.cpp b/src/gui/textfield.cpp
index bd016a8d..d4709d3f 100644
--- a/src/gui/textfield.cpp
+++ b/src/gui/textfield.cpp
@@ -19,12 +19,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "textfield.h"
+
#include <algorithm>
#include <guichan/font.hpp>
#include <guichan/sdl/sdlinput.hpp>
+#include "sdlinput.h"
#include "textfield.h"
#include "../graphics.h"
@@ -34,6 +37,8 @@
#include "../utils/dtor.h"
+#undef DELETE //Win32 compatibility hack
+
int TextField::instances = 0;
ImageRect TextField::skin;
@@ -123,34 +128,6 @@ void TextField::setNumeric(bool numeric)
}
}
-void TextField::keyPressed(gcn::KeyEvent &keyEvent)
-{
- if (mNumeric)
- {
- while (true)
- {
- const gcn::Key &key = keyEvent.getKey();
- if (key.isNumber())
- {
- break;
- }
- int value = key.getValue();
- if (value == SDLK_LEFT || value == SDLK_RIGHT ||
- value == SDLK_HOME || value == SDLK_END ||
- value == SDLK_BACKSPACE || value == SDLK_DELETE)
- {
- break;
- }
- return;
- }
- }
- gcn::TextField::keyPressed(keyEvent);
- if (mListener)
- {
- mListener->listen(this);
- }
-}
-
int TextField::getValue() const
{
if (!mNumeric)
@@ -168,3 +145,99 @@ int TextField::getValue() const
}
return value;
}
+
+void TextField::keyPressed(gcn::KeyEvent &keyEvent)
+{
+ int val = keyEvent.getKey().getValue();
+
+ if (val >= 32)
+ {
+ int l;
+ if (val < 128) l = 1; // 0xxxxxxx
+ else if (val < 0x800) l = 2; // 110xxxxx 10xxxxxx
+ else if (val < 0x10000) l = 3; // 1110xxxx 10xxxxxx 10xxxxxx
+ else l = 4; // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+ char buf[4];
+ for (int i = 0; i < l; ++i)
+ {
+ buf[i] = val >> (6 * (l - i - 1));
+ if (i > 0) buf[i] = (buf[i] & 63) | 128;
+ }
+
+ if (l > 1) buf[0] |= 255 << (8 - l);
+
+ mText.insert(mCaretPosition, std::string(buf, buf + l));
+ mCaretPosition += l;
+ }
+
+ /* In UTF-8, 10xxxxxx is only used for inner parts of characters. So skip
+ them when processing key presses. */
+
+ switch (val)
+ {
+ case Key::LEFT:
+ {
+ while (mCaretPosition > 0)
+ {
+ --mCaretPosition;
+ if ((mText[mCaretPosition] & 192) != 128)
+ break;
+ }
+ } break;
+
+ case Key::RIGHT:
+ {
+ unsigned sz = mText.size();
+ while (mCaretPosition < sz)
+ {
+ ++mCaretPosition;
+ if (mCaretPosition == sz ||
+ (mText[mCaretPosition] & 192) != 128)
+ break;
+ }
+ } break;
+
+ case Key::DELETE:
+ {
+ unsigned sz = mText.size();
+ while (mCaretPosition < sz)
+ {
+ --sz;
+ mText.erase(mCaretPosition, 1);
+ if (mCaretPosition == sz ||
+ (mText[mCaretPosition] & 192) != 128)
+ break;
+ }
+ } break;
+
+ case Key::BACKSPACE:
+ {
+ while (mCaretPosition > 0)
+ {
+ --mCaretPosition;
+ int v = mText[mCaretPosition];
+ mText.erase(mCaretPosition, 1);
+ if ((v & 192) != 128) break;
+ }
+ } break;
+
+ case Key::ENTER:
+ distributeActionEvent();
+ break;
+
+ case Key::HOME:
+ mCaretPosition = 0;
+ break;
+
+ case Key::END:
+ mCaretPosition = mText.size();
+ break;
+
+ case Key::TAB:
+ return;
+ }
+
+ keyEvent.consume();
+ fixScroll();
+}
diff --git a/src/gui/textfield.h b/src/gui/textfield.h
index 6def784d..38150b83 100644
--- a/src/gui/textfield.h
+++ b/src/gui/textfield.h
@@ -74,7 +74,7 @@ class TextField : public gcn::TextField {
void setRange(int min, int max) {mMinimum = min; mMaximum = max; }
/**
- * Restrict keyboard input if numeric
+ * Processes one keypress.
*/
void keyPressed(gcn::KeyEvent &keyEvent);
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index f6f9bb42..080ebddc 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -21,8 +21,6 @@
#include <cassert>
-#include <guichan/sdl/sdlinput.hpp>
-
#include "gui.h"
#include "popupmenu.h"
#include "viewport.h"