Ticket #8711: backends-lib.v4.2.patch

File backends-lib.v4.2.patch, 101.7 KB (added by SF/sbatyuk, 17 years ago)

key mapper tab in edit game dialog

  • backends/events/default/default-events.cpp

     
    3535
    3636DefaultEventManager::DefaultEventManager(OSystem *boss) :
    3737        _boss(boss),
     38        _keyMapper(boss->getKeyMapper()),
     39        _virtualKeyboard(boss->getVirtualKeyboard()),
    3840        _buttonState(0),
    3941        _modifierState(0),
    4042        _shouldQuit(false) {
     
    5254        result = _boss->pollEvent(event);
    5355       
    5456        if (result) {
     57                // check if we have to resolve virtual keyboard event
     58                bool lbutton = event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP;
     59                if (_boss->getFeatureState(OSystem::kFeatureVirtualKeyboard) && _virtualKeyboard && lbutton) { // possibly a virtual keyboard event
     60                        _virtualKeyboard->resolve(event); // try to resolve a virtual keyboard event
     61                }
     62
     63                // check if we have to resolve key mapping
     64                if (_keyMapper) {
     65                        _keyMapper->resolve(event);
     66                }
     67
    5568                event.synthetic = false;
    5669                switch (event.type) {
    5770                case Common::EVENT_KEYDOWN:
     
    128141        return result;
    129142}
    130143
     144KeyMapper *DefaultEventManager::getKeyMapper() {
     145        return _keyMapper;
     146}
     147
    131148#endif // !defined(DISABLE_DEFAULT_EVENTMANAGER)
  • backends/events/default/default-events.h

     
    2727#define BACKEND_EVENTS_DEFAULT_H
    2828
    2929#include "common/stdafx.h"
    30 #include "common/events.h"
     30#include "common/event-manager.h"
    3131
     32#include "backends/platform/common/key-mapper.h"
     33#include "backends/platform/common/virtual-keyboard.h"
     34
    3235/*
    3336At some point we will remove pollEvent from OSystem and change
    3437DefaultEventManager to use a "boss" derived from this class:
     
    4346
    4447class DefaultEventManager : public Common::EventManager {
    4548        OSystem *_boss;
     49        KeyMapper *_keyMapper;
     50        VirtualKeyboard *_virtualKeyboard;
    4651
    4752        Common::Point _mousePos;
    4853        int _buttonState;
     
    6772
    6873        virtual bool pollEvent(Common::Event &event);
    6974
     75        virtual KeyMapper *getKeyMapper();
     76
    7077        virtual Common::Point getMousePos() const { return _mousePos; }
    7178        virtual int getButtonState() const { return _buttonState; }
    7279        virtual int getModifierState() const { return _modifierState; }
  • backends/platform/sdl/sdl.cpp

     
    257257        memset(&_mouseCurState, 0, sizeof(_mouseCurState));
    258258
    259259        _inited = false;
     260
     261        _keyMapper = new KeyMapper();
     262        _virtualKeyboard = new VirtualKeyboard();
    260263}
    261264
    262265OSystem_SDL::~OSystem_SDL() {
     
    271274        delete _savefile;
    272275        delete _mixer;
    273276        delete _timer;
     277
     278        delete _keyMapper;
     279        delete _virtualKeyboard;
    274280}
    275281
    276282uint32 OSystem_SDL::getMillis() {
  • backends/platform/sdl/events.cpp

     
    444444        }
    445445        return false;
    446446}
     447KeyMapper *OSystem_SDL::getKeyMapper() {
     448        return _keyMapper;
     449}
    447450
     451VirtualKeyboard *OSystem_SDL::getVirtualKeyboard() {
     452        return _virtualKeyboard;
     453}
     454
    448455bool OSystem_SDL::remapKey(SDL_Event &ev, Common::Event &event) {
    449456#ifdef LINUPY
    450457        // On Yopy map the End button to quit
  • backends/platform/sdl/sdl-common.h

     
    131131        // Returns true if an event was retrieved.
    132132        virtual bool pollEvent(Common::Event &event); // overloaded by CE backend
    133133
     134        virtual KeyMapper *getKeyMapper();
     135
     136        virtual VirtualKeyboard *getVirtualKeyboard();
     137
    134138        // Set function that generates samples
    135139        typedef void (*SoundProc)(void *param, byte *buf, int len);
    136140        virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend
     
    411415        virtual bool remapKey(SDL_Event &ev, Common::Event &event);
    412416
    413417        void handleScalerHotkeys(const SDL_KeyboardEvent &key);
     418
     419private:
     420        KeyMapper *_keyMapper;
     421        VirtualKeyboard *_virtualKeyboard;
     422
    414423};
    415424
    416425#endif
  • backends/platform/common/key-mapper.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 */
     22
     23#ifndef COMMON_KEY_MAPPER_H
     24#define COMMON_KEY_MAPPER_H
     25
     26#include "common/stdafx.h"
     27#include "common/scummsys.h"
     28#include "common/keyboard.h"
     29#include "common/events.h"
     30
     31#include "common/hashmap.h"
     32
     33typedef Common::HashMap<Common::KeyState, Common::UserAction, Common::KeyState_Hash> KeyActionMap;
     34
     35/**
     36 * Default key mapper implementation, base class for custom extensions.
     37 */
     38class KeyMapper {
     39
     40public:
     41
     42        KeyMapper();
     43
     44        /**
     45         * Adds key action mapping.
     46         */
     47        virtual void addActionMapping(const Common::KeyState, const Common::UserAction);
     48
     49        /**
     50         * Maps engine and game supported actions to their defaultKey's.
     51         * This method is useful for registering a Common::ActionType to some key.
     52         */
     53        virtual void addDefaultActionMappings(const Common::ActionList);
     54
     55        /**
     56         * Clears all currently registered action mappings.
     57         */
     58        virtual void clearActionMappings();
     59
     60        /**
     61         * Returns the key currently mapped to specified user action, NULL if no key is mapped.
     62         */
     63        virtual const Common::KeyState *getMappingKey(const Common::UserAction);
     64
     65        /**
     66         * Save all currently registered action mappings.
     67         */
     68        virtual void saveActionMappings();
     69
     70        /**
     71         * Load previously saved action mappings.
     72         */
     73        virtual bool loadActionMappings();
     74
     75        /**
     76         * Tries to find a corresponding mapping for event.kbd. If successful,
     77         * replaces the event.kbd with a defaultKey from mapped action. If the actionType of
     78         * mapped action type is not Common::ACTION_INVALID, also substitutes the event.actionType.
     79         */
     80        virtual void resolve(Common::Event &event);
     81
     82private:
     83
     84        KeyActionMap _mappings; // action mappings
     85        KeyActionMap _defaultMappings; // default action mappings
     86
     87};
     88
     89#endif
     90 No newline at end of file
  • backends/platform/common/virtual-keyboard.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 */
     22
     23#include "backends/platform/common/virtual-keyboard.h"
     24
     25VirtualKeyboard::VirtualKeyboard() {
     26}
     27
     28void VirtualKeyboard::resolve(Common::Event &event) {
     29}
  • backends/platform/common/virtual-keyboard.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 */
     22
     23#ifndef COMMON_VIRTUAL_KEYBOARD_H
     24#define COMMON_VIRTUAL_KEYBOARD_H
     25
     26#include "common/stdafx.h"
     27#include "common/scummsys.h"
     28#include "common/events.h"
     29
     30/**
     31 * Default virtual keyboard implementation, base class for custom extensions.
     32 */
     33class VirtualKeyboard {
     34
     35public:
     36       
     37        VirtualKeyboard();
     38
     39        /**
     40         * For all mouse click events checks whether the click is 
     41         * in the screen range of virtual keyboard. This being true,
     42         * figures out what virtual button was clicked and substitutes
     43         * the mouse data in event with fake key data.
     44         */
     45        virtual void resolve(Common::Event &event);
     46};
     47
     48#endif
     49 No newline at end of file
  • backends/platform/common/module.mk

     
     1MODULE := backends/platform/common
     2
     3MODULE_OBJS := \
     4        key-mapper.o \
     5        virtual-keyboard.o
     6
     7MODULE_DIRS += \
     8        backends/platform/common/
     9
     10# We don't use the rules.mk here on purpose
     11OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
  • backends/platform/common/key-mapper.cpp

     
     1        /* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 */
     22
     23#include "backends/platform/common/key-mapper.h"
     24#include "common/config-manager.h"
     25
     26#define version 1 // TODO add backend identification here
     27
     28KeyMapper::KeyMapper() {
     29}
     30
     31void KeyMapper::addActionMapping(const Common::KeyState key, const Common::UserAction action) {
     32        const Common::KeyState *oldKey = getMappingKey(action);
     33        if (oldKey) {
     34                _mappings.erase(*oldKey);
     35        }
     36        _mappings[key] = action;
     37}
     38
     39void KeyMapper::addDefaultActionMappings(const Common::ActionList actions) {
     40        for (Common::ActionList::const_iterator mIt = actions.begin(); mIt != actions.end(); mIt++) {
     41                // actions are mapped to default keys to substitute later the action associated with the event
     42                addActionMapping(mIt->defaultKey, *mIt);
     43        }
     44        _defaultMappings = _mappings;
     45}
     46
     47const Common::KeyState *KeyMapper::getMappingKey(const Common::UserAction action) {
     48        const Common::KeyState *result = NULL;
     49        for (KeyActionMap::const_iterator mIt = _mappings.begin(); mIt != _mappings.end(); ++mIt) {
     50                if (mIt->_value == action) {
     51                        result = &(mIt->_key);
     52                        break;
     53                }
     54        }
     55        return result;
     56}
     57
     58void KeyMapper::clearActionMappings() {
     59        _mappings.clear();
     60}
     61
     62void KeyMapper::saveActionMappings() {
     63        char *tempo = (char *) malloc(_mappings.size() * 15 + 1); // 15 is the size required to write one mapping
     64        if (tempo == NULL) {
     65                return;
     66        }
     67        tempo[0] = '\0';
     68        ConfMan.setInt("action_mapping_version", version, ConfMan.kApplicationDomain);
     69        for (KeyActionMap::const_iterator mIt = _mappings.begin(); mIt != _mappings.end(); ++mIt) {
     70                char s[15];
     71                sprintf(s, "%.4x%.2x,%.4x%.2x;", mIt->_key.keycode, mIt->_key.flags, mIt->_value.defaultKey.keycode, mIt->_value.defaultKey.flags);
     72                strcat(tempo, s);
     73        }
     74        ConfMan.set("action_mapping", tempo, ConfMan.kApplicationDomain);
     75        free(tempo);
     76        ConfMan.flushToDisk();
     77}
     78
     79bool KeyMapper::loadActionMappings() {
     80        int current_version = ConfMan.getInt("action_mapping_version", ConfMan.kApplicationDomain);
     81        if (current_version != version) {
     82                return false;
     83        }
     84
     85        const char *tempo = ConfMan.get("action_mapping", ConfMan.kApplicationDomain).c_str();
     86        if (tempo && strlen(tempo)) {
     87                for (int i = 0, size = _mappings.size(); i < size; i++) {
     88                        char x[4];
     89                        int offset = 14 * i;
     90                        uint32 buf;
     91                        Common::KeyState key;
     92                        Common::KeyState defaultKey;
     93
     94                        memset(x, 0, sizeof(x));
     95                        memcpy(x, tempo + offset, 4);
     96                        sscanf(x, "%x", &buf);
     97                        key.keycode = (Common::KeyCode) buf;
     98
     99                        memset(x, 0, sizeof(x));
     100                        memcpy(x, tempo + offset + 4, 2);
     101                        sscanf(x, "%x", &buf);
     102                        key.flags = (byte) buf;
     103
     104                        memset(x, 0, sizeof(x));
     105                        memcpy(x, tempo + offset + 7, 4);
     106                        sscanf(x, "%x", &buf);
     107                        defaultKey.keycode = (Common::KeyCode) buf;
     108
     109                        memset(x, 0, sizeof(x));
     110                        memcpy(x, tempo + offset + 11, 2);
     111                        sscanf(x, "%x", &buf);
     112                        defaultKey.flags = (byte) buf;
     113
     114                        const Common::UserAction action = _defaultMappings[defaultKey];
     115                        const Common::KeyState *oldKey = getMappingKey(action);
     116                        _mappings.erase(*oldKey);
     117                        _mappings[key] = action;
     118                }
     119                return true;
     120        }
     121        else
     122                return false;
     123}
     124
     125void KeyMapper::resolve(Common::Event &event) {
     126        if (_mappings.empty()) {
     127                return;
     128        }
     129
     130        if (_mappings.contains(event.kbd)) {
     131                event.kbd = _mappings[event.kbd].defaultKey;
     132                if (_mappings[event.kbd].actionType != Common::ACTION_INVALID) {
     133                        event.actionType = _mappings[event.kbd].actionType;
     134                }
     135        }
     136}
     137 No newline at end of file
  • common/event-manager.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 */
     22
     23#ifndef COMMON_EVENT_MANAGER_H
     24#define COMMON_EVENT_MANAGER_H
     25
     26#include "common/events.h"
     27#include "backends/platform/common/key-mapper.h"
     28
     29namespace Common {
     30
     31/**
     32 * The EventManager provides user input events to the client code.
     33 * In addition, it keeps track of the state of various input devices,
     34 * like keys, mouse position and buttons.
     35 */
     36class EventManager : NonCopyable {
     37public:
     38        EventManager() {}
     39        virtual ~EventManager() {}
     40       
     41        enum {
     42                LBUTTON = 1 << 0,
     43                RBUTTON = 1 << 1
     44        };
     45
     46        /**
     47         * Get the next event in the event queue.
     48         * @param event point to an Event struct, which will be filled with the event data.
     49         * @return true if an event was retrieved.
     50         */
     51        virtual bool pollEvent(Common::Event &event) = 0;
     52
     53
     54        /** Return the current key state */
     55        virtual Common::Point getMousePos() const = 0;
     56       
     57        /**
     58         * Return a bitmask with the button states:
     59         * - bit 0: left button up=1, down=0
     60         * - bit 1: right button up=1, down=0
     61         */
     62        virtual int getButtonState() const = 0;
     63       
     64        /** Get a bitmask with the current modifier state */
     65        virtual int getModifierState() const = 0;
     66
     67        /**
     68         * Should the application terminate? Set to true if we
     69         * received an EVENT_QUIT.
     70         */
     71        virtual int shouldQuit() const = 0;
     72       
     73        // Optional: check whether a given key is currently pressed ????
     74        //virtual bool isKeyPressed(int keycode) = 0;
     75
     76        // TODO: Keyboard repeat support?
     77       
     78        // TODO: Consider removing OSystem::getScreenChangeID and
     79        // replacing it by a generic getScreenChaneID method here
     80
     81        virtual KeyMapper *getKeyMapper() = 0;
     82};
     83
     84} // End of namespace Common
     85
     86#endif
     87 No newline at end of file
  • common/keyboard.h

     
    259259                keycode = KEYCODE_INVALID;
    260260                ascii = flags = 0;
    261261        }
     262
     263        bool operator <(const KeyState keyState) const {
     264                bool result;
     265                if (keycode != keyState.keycode) {
     266                        result = keycode < keyState.keycode;
     267                } else {
     268                        result = flags < keyState.flags;
     269                }
     270
     271                return result;
     272        }
     273
     274        bool operator ==(const KeyState keyState) const {
     275                return (keycode == keyState.keycode) && (flags == keyState.flags);
     276        }
     277
     278        uint hash() const {
     279                return 0;
     280        }
     281
    262282};
    263283
     284struct KeyState_Hash {
     285        uint operator()(const KeyState& ks) const { return ks.hash(); }
     286};
     287
     288
    264289} // End of namespace Common
    265290
    266291#endif
  • common/system.h

     
    3131#include "common/noncopyable.h"
    3232#include "common/rect.h"
    3333
     34#include "backends/platform/common/key-mapper.h"
     35#include "backends/platform/common/virtual-keyboard.h"
     36
    3437namespace Audio {
    3538        class Mixer;
    3639}
     
    724727         */
    725728        virtual bool pollEvent(Common::Event &event) = 0;
    726729
     730        virtual KeyMapper *getKeyMapper() { return NULL; }
     731
     732        virtual VirtualKeyboard *getVirtualKeyboard() { return NULL; }
     733
    727734public:
     735
    728736        /** Get the number of milliseconds since the program was started. */
    729737        virtual uint32 getMillis() = 0;
    730738
     
    743751         */
    744752        virtual Common::EventManager *getEventManager();
    745753
     754
    746755        //@}
    747756
    748757
     
    894903         * refer to the SaveFileManager documentation.
    895904         */
    896905        virtual Common::SaveFileManager *getSavefileManager() = 0;
    897 
    898906        //@}
    899907};
    900908
  • common/events.h

     
    2828
    2929#include "common/keyboard.h"
    3030#include "common/rect.h"
    31 #include "common/system.h"
    3231#include "common/noncopyable.h"
    3332
     33#include "common/list.h"
     34
    3435namespace Common {
    3536
    3637/**
     
    4344 *       indicates which button was pressed.
    4445 */
    4546enum EventType {
     47
     48        EVENT_INVALID = 0,
    4649        /** A key was pressed, details in Event::kbd. */
    4750        EVENT_KEYDOWN = 1,
    4851        /** A key was released, details in Event::kbd. */
     
    6871        EVENT_PREDICTIVE_DIALOG = 12
    6972};
    7073
     74enum ActionType {
     75
     76        ACTION_INVALID = 0,
     77        ACTION_QUIT = 1,
     78        ACTION_SAVE = 2,
     79        ACTION_LOAD = 3
     80
     81};
     82
     83
    7184/**
    7285 * Data structure for an event. A pointer to an instance of Event
    7386 * can be passed to pollEvent.
     
    97110 *       };
    98111 */
    99112struct Event {
    100         /** The type of the event. */
     113        /** The type of the event like key down/up. */
    101114        EventType type;
     115
     116        /** The action which this event represents like quit, save, load. */
     117        ActionType actionType;
     118
    102119        /** Flag to indicate if the event is real or synthetic. E.g. keyboard
    103120          * repeat events are synthetic.
    104121          */
     
    107124          * Keyboard data; only valid for keyboard events (EVENT_KEYDOWN and
    108125          * EVENT_KEYUP). For all other event types, content is undefined.
    109126          */
    110         KeyState kbd;
     127        Common::KeyState kbd;
    111128        /**
    112129         * The mouse coordinates, in virtual screen coordinates. Only valid
    113130         * for mouse events.
     
    115132         * screen area as defined by the most recent call to initSize().
    116133         */
    117134        Common::Point mouse;
     135
     136        Event(Common::EventType et = Common::EVENT_INVALID, bool s = false,
     137                Common::KeyState ks = Common::KeyState(), Common::Point p = Common::Point()) {
     138               
     139                type = et;
     140                synthetic = s;
     141                kbd = ks;
     142                mouse = p;
     143        }
     144
     145        void reset() {
     146                type = Common::EVENT_INVALID;
     147                synthetic = false;
     148                kbd = Common::KeyState();
     149                mouse = Common::Point();
     150        }
    118151};
    119152
     153enum Priority {
     154        PRIORITY_HIGHEST = 1,
     155        PRIORITY_HIGH = 2,
     156        PRIORITY_NORMAL = 3,
     157        PRIORITY_LOW = 4,
     158        PRIORITY_LOWEST = 5
     159};
    120160
    121 /**
    122  * The EventManager provides user input events to the client code.
    123  * In addition, it keeps track of the state of various input devices,
    124  * like keys, mouse position and buttons.
    125  */
    126 class EventManager : NonCopyable {
    127 public:
    128         EventManager() {}
    129         virtual ~EventManager() {}
    130        
    131         enum {
    132                 LBUTTON = 1 << 0,
    133                 RBUTTON = 1 << 1
    134         };
    135161
     162struct UserAction {
     163
    136164        /**
    137          * Get the next event in the event queue.
    138          * @param event point to an Event struct, which will be filled with the event data.
    139          * @return true if an event was retrieved.
     165         * Default key used in the egines an games for this action.
    140166         */
    141         virtual bool pollEvent(Common::Event &event) = 0;
     167        Common::KeyState defaultKey;
    142168
     169        /**
     170         * Event type like quit, save/load, etc.
     171         */
     172        Common::ActionType actionType;
    143173
    144         /** Return the current key state */
    145         virtual Common::Point getMousePos() const = 0;
    146        
    147174        /**
    148          * Return a bitmask with the button states:
    149          * - bit 0: left button up=1, down=0
    150          * - bit 1: right button up=1, down=0
     175         * Human readable description for a GUI keymapping config dialog
    151176         */
    152         virtual int getButtonState() const = 0;
    153        
    154         /** Get a bitmask with the current modifier state */
    155         virtual int getModifierState() const = 0;
     177        String description;
    156178
    157179        /**
    158          * Should the application terminate? Set to true if we
    159          * received an EVENT_QUIT.
     180         * Mapping priority. Actions with higher priority will be given preference for mapping
     181         * in case of limited inputs.
    160182         */
    161         virtual int shouldQuit() const = 0;
    162        
    163         // Optional: check whether a given key is currently pressed ????
    164         //virtual bool isKeyPressed(int keycode) = 0;
     183        Common::Priority priority;
    165184
    166         // TODO: Keyboard repeat support?
    167        
    168         // TODO: Consider removing OSystem::getScreenChangeID and
    169         // replacing it by a generic getScreenChangeID method here
     185        UserAction(Common::KeyState ks = Common::KeyState(Common::KEYCODE_ESCAPE),
     186                Common::ActionType at = Common::ACTION_INVALID,
     187                String d = "Action name", Common::Priority p = Common::PRIORITY_NORMAL) {
     188               
     189                defaultKey = ks;
     190                actionType = at;
     191                description = d;
     192                priority = p;
     193        }
     194
     195        UserAction(Common::KeyState ks, String d, Common::Priority p = Common::PRIORITY_NORMAL) {
     196                defaultKey = ks;
     197                actionType = Common::ACTION_INVALID;
     198                description = d;
     199                priority = p;
     200        }
     201
     202        bool operator ==(const UserAction action) const {
     203                return (defaultKey == action.defaultKey) && (actionType == action.actionType) && (description == action.description);
     204        }
     205
     206        bool operator <(const UserAction action) const {
     207                return priority < action.priority;
     208        }
     209
    170210};
    171211
     212typedef Common::List<Common::UserAction> ActionList;
     213
    172214} // End of namespace Common
    173215
    174216#endif
  • engines/sword1/sword1.cpp

     
    3131#include "common/file.h"
    3232#include "common/fs.h"
    3333#include "common/timer.h"
    34 #include "common/events.h"
     34#include "common/event-manager.h"
    3535#include "common/system.h"
    3636
    3737#include "sword1/resman.h"
  • engines/sword1/credits.cpp

     
    3535
    3636#include "common/file.h"
    3737#include "common/util.h"
    38 #include "common/events.h"
     38#include "common/event-manager.h"
    3939#include "common/system.h"
    4040
    4141
  • engines/sword1/animation.cpp

     
    3434#include "common/config-manager.h"
    3535#include "common/endian.h"
    3636#include "common/str.h"
    37 #include "common/events.h"
     37#include "common/event-manager.h"
    3838#include "common/system.h"
    3939
    4040namespace Sword1 {
  • engines/sword1/control.cpp

     
    2727#include "common/file.h"
    2828#include "common/util.h"
    2929#include "common/savefile.h"
    30 #include "common/events.h"
     30#include "common/event-manager.h"
    3131#include "common/system.h"
    3232
    3333#include "gui/message.h"
  • engines/sword2/sword2.cpp

     
    3232#include "common/config-manager.h"
    3333#include "common/file.h"
    3434#include "common/fs.h"
    35 #include "common/events.h"
     35#include "common/event-manager.h"
    3636#include "common/system.h"
    3737
    3838#include "sword2/sword2.h"
  • engines/sword2/mouse.cpp

     
    2727
    2828#include "common/stdafx.h"
    2929#include "common/system.h"
    30 #include "common/events.h"
     30#include "common/event-manager.h"
    3131
    3232#include "graphics/cursorman.h"
    3333
  • engines/sword2/animation.cpp

     
    2828#include "common/stdafx.h"
    2929#include "common/config-manager.h"
    3030#include "common/file.h"
    31 #include "common/events.h"
     31#include "common/event-manager.h"
    3232#include "common/system.h"
    3333
    3434#include "sword2/sword2.h"
  • engines/scumm/input.cpp

     
    2626#include "common/stdafx.h"
    2727
    2828#include "common/config-manager.h"
    29 #include "common/events.h"
     29#include "common/event-manager.h"
    3030#include "common/system.h"
    3131
    3232#include "gui/message.h"
  • engines/scumm/scumm.cpp

     
    2727
    2828#include "common/config-manager.h"
    2929#include "common/md5.h"
    30 #include "common/events.h"
     30#include "common/event-manager.h"
    3131#include "common/system.h"
    3232
    3333#include "gui/message.h"
  • engines/touche/touche.cpp

     
    2525
    2626#include "common/stdafx.h"
    2727#include "common/config-manager.h"
    28 #include "common/events.h"
     28#include "common/event-manager.h"
    2929#include "common/system.h"
    3030
    3131#include "graphics/cursorman.h"
  • engines/touche/ui.cpp

     
    2424 */
    2525
    2626#include "common/stdafx.h"
    27 #include "common/events.h"
     27#include "common/event-manager.h"
    2828#include "common/system.h"
    2929#include "common/savefile.h"
    3030
  • engines/agos/cursor.cpp

     
    2525
    2626#include "common/stdafx.h"
    2727
    28 #include "common/events.h"
     28#include "common/event-manager.h"
    2929#include "common/system.h"
    3030
    3131#include "graphics/cursorman.h"
  • engines/agos/event.cpp

     
    2929#include "agos/debugger.h"
    3030#include "agos/intern.h"
    3131
    32 #include "common/events.h"
     32#include "common/event-manager.h"
    3333#include "common/system.h"
    3434
    3535#include "gui/about.h"
  • engines/agos/animation.cpp

     
    2626#include "common/stdafx.h"
    2727
    2828#include "common/endian.h"
    29 #include "common/events.h"
     29#include "common/event-manager.h"
    3030#include "common/system.h"
    3131
    3232#include "graphics/cursorman.h"
  • engines/cruise/cruise_main.cpp

     
    2525
    2626#include "common/stdafx.h"
    2727#include "common/endian.h"
    28 #include "common/events.h"
     28#include "common/event-manager.h"
    2929
    3030#include "cruise/cruise_main.h"
    3131#include "cruise/cell.h"
    3232
     33#include "common/system.h"
     34
    3335namespace Cruise {
    3436
    3537unsigned int timer = 0;
  • engines/drascula/drascula.cpp

     
    2525
    2626#include "common/stdafx.h"
    2727
    28 #include "common/events.h"
    2928#include "common/keyboard.h"
     29#include "common/event-manager.h"
    3030#include "common/file.h"
    3131#include "common/savefile.h"
    3232#include "common/config-manager.h"
  • engines/agi/agi.cpp

     
    2525
    2626#include "common/stdafx.h"
    2727
    28 #include "common/events.h"
     28#include "common/event-manager.h"
    2929#include "common/file.h"
    3030#include "common/savefile.h"
    3131#include "common/config-manager.h"
  • engines/sky/sky.h

     
    2727#define SKY_H
    2828
    2929#include "common/stdafx.h"
     30#include "common/keyboard.h"
    3031#include "common/events.h"
     32#include "common/system.h"
    3133#include "engines/engine.h"
    3234
    3335namespace Sky {
  • engines/sky/mouse.cpp

     
    2424 */
    2525
    2626#include "common/stdafx.h"
    27 #include "common/events.h"
     27#include "common/event-manager.h"
    2828#include "common/system.h"
    2929#include "graphics/cursorman.h"
    3030#include "sky/disk.h"
  • engines/sky/intro.cpp

     
    2626#include "common/stdafx.h"
    2727#include "common/endian.h"
    2828#include "common/util.h"
    29 #include "common/events.h"
     29#include "common/event-manager.h"
    3030#include "common/system.h"
    3131
    3232#include "sky/disk.h"
  • engines/sky/sky.cpp

     
    3030#include "common/config-manager.h"
    3131#include "common/file.h"
    3232#include "common/fs.h"
    33 #include "common/events.h"
    34 #include "common/system.h"
    3533#include "common/timer.h"
    3634
     35#include "gui/key-mapper-dialog.h"
     36
    3737#include "sky/control.h"
    3838#include "sky/debug.h"
    3939#include "sky/disk.h"
     
    182182SystemVars SkyEngine::_systemVars = {0, 0, 0, 0, 4316, 0, 0, false, false, false };
    183183
    184184SkyEngine::SkyEngine(OSystem *syst)
    185         : Engine(syst), _fastMode(0), _debugger(0) {
    186 }
     185        : Engine(syst), _fastMode(0), _debugger(0) {}
    187186
    188187SkyEngine::~SkyEngine() {
    189188
     
    463462        _skyMusic->setVolume(ConfMan.getInt("music_volume") >> 1);
    464463
    465464        _debugger = new Debugger(_skyLogic, _skyMouse, _skyScreen, _skyCompact);
     465
     466        // init key mapper, it's called here only for key mapper dialog testing purposes
     467        Common::ActionList actions;
     468
     469        Common::KeyState key = Common::KeyState(Common::KEYCODE_F5);
     470        Common::UserAction action = Common::UserAction(key, "Menu");
     471        actions.push_back(action);
     472       
     473        key = Common::KeyState(Common::KEYCODE_ESCAPE);
     474        action = Common::UserAction(key, "Esc");
     475        actions.push_back(action);
     476
     477        key = Common::KeyState(Common::KEYCODE_p);
     478        action = Common::UserAction(key, "Pause");
     479        actions.push_back(action);
     480
     481        _eventMan->getKeyMapper()->addDefaultActionMappings(actions);
     482        GUI::KeyMapperDialog::s_showKeyMapperDialog("Key mapping", _system->getEventManager(), actions);
     483
    466484        return 0;
    467485}
    468486
  • engines/sky/screen.cpp

     
    2525
    2626#include "common/stdafx.h"
    2727#include "common/endian.h"
    28 #include "common/events.h"
     28#include "common/event-manager.h"
    2929#include "common/system.h"
    3030
    3131#include "sky/disk.h"
  • engines/sky/control.cpp

     
    2727#include "common/endian.h"
    2828#include "common/config-manager.h"
    2929#include "common/file.h"
    30 #include "common/events.h"
     30#include "common/event-manager.h"
    3131#include "common/system.h"
    3232#include "common/savefile.h"
    3333#include "common/util.h"
  • engines/kyra/kyra.cpp

     
    2626#include "common/stdafx.h"
    2727
    2828#include "common/config-manager.h"
     29#include "common/event-manager.h"
    2930
    3031#include "sound/mididrv.h"
    3132#include "sound/mixer.h"
  • engines/kyra/gui.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/kyra/gui.cpp $
     22 * $Id: gui.cpp 28028 2007-07-11 13:25:21Z lordhoto $
     23 *
     24 */
     25
     26#include "kyra/kyra.h"
     27#include "kyra/screen.h"
     28#include "kyra/script.h"
     29#include "kyra/text.h"
     30#include "kyra/animator.h"
     31#include "kyra/sound.h"
     32
     33#include "common/config-manager.h"
     34#include "common/savefile.h"
     35#include "common/event-manager.h"
     36#include "common/system.h"
     37
     38namespace Kyra {
     39
     40void KyraEngine::registerDefaultSettings() {
     41        // Most settings already have sensible defaults. This one, however, is
     42        // specific to the Kyra engine.
     43        ConfMan.registerDefault("walkspeed", 2);
     44        ConfMan.registerDefault("cdaudio", _flags.platform == Common::kPlatformFMTowns);
     45}
     46
     47void KyraEngine::readSettings() {
     48        int talkspeed = ConfMan.getInt("talkspeed");
     49
     50        // The default talk speed is 60. This should be mapped to "Normal".
     51
     52        if (talkspeed == 0)
     53                _configTextspeed = 3;   // Clickable
     54        if (talkspeed <= 50)
     55                _configTextspeed = 0;   // Slow
     56        else if (talkspeed <= 150)
     57                _configTextspeed = 1;   // Normal
     58        else
     59                _configTextspeed = 2;   // Fast
     60
     61        _configWalkspeed = ConfMan.getInt("walkspeed");
     62        _configMusic = ConfMan.getBool("music_mute") ? 0 : ((ConfMan.getBool("cdaudio") && _flags.platform == Common::kPlatformFMTowns) ? 2 : 1);       
     63        _configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1;
     64
     65        _sound->enableMusic(_configMusic);
     66        _sound->enableSFX(_configSounds);
     67
     68        bool speechMute = ConfMan.getBool("speech_mute");
     69        bool subtitles = ConfMan.getBool("subtitles");
     70
     71        if (!speechMute && subtitles)
     72                _configVoice = 2;       // Voice & Text
     73        else if (!speechMute && !subtitles)
     74                _configVoice = 1;       // Voice only
     75        else
     76                _configVoice = 0;       // Text only
     77
     78        setWalkspeed(_configWalkspeed);
     79}
     80
     81void KyraEngine::writeSettings() {
     82        bool speechMute, subtitles;
     83        int talkspeed;
     84
     85        switch (_configTextspeed) {
     86        case 0:         // Slow
     87                talkspeed = 1;
     88                break;
     89        case 1:         // Normal
     90                talkspeed = 60;
     91                break;
     92        case 2:         // Fast
     93                talkspeed = 255;
     94                break;
     95        default:        // Clickable
     96                talkspeed = 0;
     97                break;
     98        }
     99
     100        ConfMan.setInt("talkspeed", talkspeed);
     101        ConfMan.setInt("walkspeed", _configWalkspeed);
     102        ConfMan.setBool("music_mute", _configMusic == 0);
     103        ConfMan.setBool("cdaudio", _configMusic == 2);
     104        ConfMan.setBool("sfx_mute", _configSounds == 0);
     105
     106        switch (_configVoice) {
     107        case 0:         // Text only
     108                speechMute = true;
     109                subtitles = true;
     110                break;
     111        case 1:         // Voice only
     112                speechMute = false;
     113                subtitles = false;
     114                break;
     115        default:        // Voice & Text
     116                speechMute = false;
     117                subtitles = true;
     118                break;
     119        }
     120
     121        if (!_configMusic)
     122                _sound->beginFadeOut();
     123
     124        _sound->enableMusic(_configMusic);
     125        _sound->enableSFX(_configSounds);
     126
     127        ConfMan.setBool("speech_mute", speechMute);
     128        ConfMan.setBool("subtitles", subtitles);
     129
     130        ConfMan.flushToDisk();
     131}
     132
     133void KyraEngine::initMainButtonList() {
     134        _haveScrollButtons = false;
     135        _buttonList = &_buttonData[0];
     136        for (int i = 0; _buttonDataListPtr[i]; ++i)
     137                _buttonList = initButton(_buttonList, _buttonDataListPtr[i]);
     138}
     139
     140Button *KyraEngine::initButton(Button *list, Button *newButton) {
     141        if (!newButton)
     142                return list;
     143        if (!list)
     144                return newButton;
     145        Button *cur = list;
     146
     147        while (true) {
     148                if (!cur->nextButton)
     149                        break;
     150                cur = cur->nextButton;
     151        }
     152
     153        cur->nextButton = newButton;
     154        return list;
     155}
     156
     157int KyraEngine::buttonInventoryCallback(Button *caller) {
     158        int itemOffset = caller->specialValue - 2;
     159        uint8 inventoryItem = _currentCharacter->inventoryItems[itemOffset];
     160        if (_itemInHand == -1) {
     161                if (inventoryItem == 0xFF) {
     162                        snd_playSoundEffect(0x36);
     163                        return 0;
     164                } else {
     165                        _screen->hideMouse();
     166                        _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12);
     167                        snd_playSoundEffect(0x35);
     168                        setMouseItem(inventoryItem);
     169                        updateSentenceCommand(_itemList[inventoryItem], _takenList[0], 179);
     170                        _itemInHand = inventoryItem;
     171                        _screen->showMouse();
     172                        _currentCharacter->inventoryItems[itemOffset] = 0xFF;
     173                }
     174        } else {
     175                if (inventoryItem != 0xFF) {
     176                        snd_playSoundEffect(0x35);
     177                        _screen->hideMouse();
     178                        _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12);
     179                        _screen->drawShape(0, _shapes[216+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0);
     180                        setMouseItem(inventoryItem);
     181                        updateSentenceCommand(_itemList[inventoryItem], _takenList[1], 179);
     182                        _screen->showMouse();
     183                        _currentCharacter->inventoryItems[itemOffset] = _itemInHand;
     184                        _itemInHand = inventoryItem;
     185                } else {
     186                        snd_playSoundEffect(0x32);
     187                        _screen->hideMouse();
     188                        _screen->drawShape(0, _shapes[216+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0);
     189                        _screen->setMouseCursor(1, 1, _shapes[0]);
     190                        updateSentenceCommand(_itemList[_itemInHand], _placedList[0], 179);
     191                        _screen->showMouse();
     192                        _currentCharacter->inventoryItems[itemOffset] = _itemInHand;
     193                        _itemInHand = -1;
     194                }
     195        }
     196        _screen->updateScreen();
     197        // XXX clearKyrandiaButtonIO
     198        return 0;
     199}
     200
     201int KyraEngine::buttonAmuletCallback(Button *caller) {
     202        if (!(_deathHandler & 8))
     203                return 1;
     204        int jewel = caller->specialValue - 0x14;
     205        if (_currentCharacter->sceneId == 210) {
     206                if (_beadStateVar == 4 || _beadStateVar == 6)
     207                        return 1;
     208        }
     209        if (!queryGameFlag(0x2D))
     210                return 1;
     211        if (_itemInHand != -1) {
     212                assert(_putDownFirst);
     213                characterSays(2000, _putDownFirst[0], 0, -2);
     214                return 1;
     215        }
     216        if (queryGameFlag(0xF1)) {
     217                assert(_waitForAmulet);
     218                characterSays(2001, _waitForAmulet[0], 0, -2); 
     219                return 1;
     220        }
     221        if (!queryGameFlag(0x55+jewel)) {
     222                assert(_blackJewel);
     223                _animator->makeBrandonFaceMouse();
     224                drawJewelPress(jewel, 1);
     225                characterSays(2002, _blackJewel[0], 0, -2);
     226                return 1;
     227        }
     228        drawJewelPress(jewel, 0);
     229        drawJewelsFadeOutStart();
     230        drawJewelsFadeOutEnd(jewel);
     231       
     232        _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
     233        _scriptClick->regs[3] = 0;
     234        _scriptClick->regs[6] = jewel;
     235        _scriptInterpreter->startScript(_scriptClick, 4);
     236       
     237        while (_scriptInterpreter->validScript(_scriptClick))
     238                _scriptInterpreter->runScript(_scriptClick);
     239       
     240        if (_scriptClick->regs[3])
     241                return 1;
     242       
     243        _unkAmuletVar = 1;
     244        switch (jewel-1) {
     245        case 0:
     246                if (_brandonStatusBit & 1) {
     247                        seq_brandonHealing2();
     248                } else if (_brandonStatusBit == 0) {
     249                        seq_brandonHealing();
     250                        assert(_healingTip);
     251                        characterSays(2003, _healingTip[0], 0, -2);
     252                }
     253                break;
     254               
     255        case 1:
     256                seq_makeBrandonInv();
     257                break;
     258
     259        case 2:
     260                if (_brandonStatusBit & 1) {
     261                        assert(_wispJewelStrings);
     262                        characterSays(2004, _wispJewelStrings[0], 0, -2);
     263                } else {
     264                        if (_brandonStatusBit & 2) {
     265                                // XXX
     266                                seq_makeBrandonNormal2();
     267                                // XXX
     268                        } else {
     269                                // do not check for item in hand again as in the original since some strings are missing
     270                                // in the cd version
     271                                if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) {
     272                                        snd_playWanderScoreViaMap(1, 0);
     273                                        seq_makeBrandonWisp();
     274                                        snd_playWanderScoreViaMap(17, 0);
     275                                } else {
     276                                        seq_makeBrandonWisp();
     277                                }
     278                                setGameFlag(0x9E);
     279                        }
     280                }
     281                break;
     282
     283        case 3:
     284                seq_dispelMagicAnimation();
     285                assert(_magicJewelString);
     286                characterSays(2007, _magicJewelString[0], 0, -2);
     287                break;
     288               
     289        default:
     290                break;
     291        }
     292        _unkAmuletVar = 0;
     293        // XXX clearKyrandiaButtonIO (!used before every return in this function!)
     294        return 1;
     295}
     296
     297void KyraEngine::processButtonList(Button *list) {
     298        if (_haveScrollButtons) {
     299                if (_mouseWheel < 0)
     300                        gui_scrollUp(&_scrollUpButton);
     301                else if (_mouseWheel > 0)
     302                        gui_scrollDown(&_scrollDownButton);
     303        }
     304        while (list) {
     305                if (list->flags & 8) {
     306                        list = list->nextButton;
     307                        continue;
     308                }
     309               
     310                int x = list->x;
     311                int y = list->y;
     312                assert(list->dimTableIndex < _screen->_screenDimTableCount);
     313                if (x < 0) {
     314                        x += _screen->_screenDimTable[list->dimTableIndex].w << 3;
     315                }
     316                x += _screen->_screenDimTable[list->dimTableIndex].sx << 3;
     317               
     318                if (y < 0) {
     319                        y += _screen->_screenDimTable[list->dimTableIndex].h;
     320                }
     321                y += _screen->_screenDimTable[list->dimTableIndex].sy;
     322               
     323                Common::Point mouse = getMousePos();
     324                if (mouse.x >= x && mouse.y >= y && x + list->width >= mouse.x && y + list->height >= mouse.y) {
     325                        int processMouseClick = 0;
     326                        if (list->flags & 0x400) {
     327                                if (_mousePressFlag) {
     328                                        if (!(list->flags2 & 1)) {
     329                                                list->flags2 |= 1;
     330                                                list->flags2 |= 4;
     331                                                processButton(list);
     332                                                _screen->updateScreen();
     333                                        }
     334                                } else {
     335                                        if (list->flags2 & 1) {
     336                                                list->flags2 &= 0xFFFE;
     337                                                processButton(list);
     338                                                processMouseClick = 1;
     339                                        }
     340                                }
     341                        } else if (_mousePressFlag) {
     342                                processMouseClick = 1;
     343                        }
     344                               
     345                        if (processMouseClick) {
     346                                if (list->buttonCallback) {
     347                                        if ((this->*(list->buttonCallback))(list)) {
     348                                                break;
     349                                        }
     350                                }
     351                        }
     352                } else {
     353                        if (list->flags2 & 1) {
     354                                list->flags2 &= 0xFFFE;
     355                                processButton(list);
     356                        }
     357                        if (list->flags2 & 4) {
     358                                list->flags2 &= 0xFFFB;
     359                                processButton(list);
     360                                _screen->updateScreen();
     361                        }
     362                        list = list->nextButton;
     363                        continue;
     364                }
     365               
     366                list = list->nextButton;
     367        }
     368}
     369
     370void KyraEngine::processButton(Button *button) {
     371        if (!button)
     372                return;
     373       
     374        int processType = 0;
     375        uint8 *shape = 0;
     376        Button::ButtonCallback callback = 0;
     377       
     378        int flags = (button->flags2 & 5);
     379        if (flags == 1) {
     380                processType = button->process2;
     381                if (processType == 1)
     382                        shape = button->process2PtrShape;
     383                else if (processType == 4)
     384                        callback = button->process2PtrCallback;
     385        } else if (flags == 4 || flags == 5) {
     386                processType = button->process1;
     387                if (processType == 1)
     388                        shape = button->process1PtrShape;
     389                else if (processType == 4)
     390                        callback = button->process1PtrCallback;
     391        } else {
     392                processType = button->process0;
     393                if (processType == 1)
     394                        shape = button->process0PtrShape;
     395                else if (processType == 4)
     396                        callback = button->process0PtrCallback;
     397        }
     398       
     399        int x = button->x;
     400        int y = button->y;
     401        assert(button->dimTableIndex < _screen->_screenDimTableCount);
     402        if (x < 0)
     403                x += _screen->_screenDimTable[button->dimTableIndex].w << 3;
     404       
     405        if (y < 0)
     406                y += _screen->_screenDimTable[button->dimTableIndex].h;
     407       
     408        if (processType == 1 && shape)
     409                _screen->drawShape(_screen->_curPage, shape, x, y, button->dimTableIndex, 0x10);
     410        else if (processType == 4 && callback)
     411                (this->*callback)(button);
     412}
     413
     414void KyraEngine::processAllMenuButtons() {
     415        if (!_menuButtonList)
     416                return;
     417
     418        Button *cur = _menuButtonList;
     419        while (true) {
     420                if (!cur->nextButton)
     421                        break;
     422                processMenuButton(cur);
     423                cur = cur->nextButton;
     424        }
     425        return;
     426}
     427
     428void KyraEngine::processMenuButton(Button *button) {
     429        if (!_displayMenu)
     430                return;
     431
     432        if (!button || (button->flags & 8))
     433                return;
     434
     435        if (button->flags2 & 1)
     436                button->flags2 &= 0xf7;
     437        else
     438                button->flags2 |= 8;
     439
     440        button->flags2 &= 0xfc;
     441
     442        if (button->flags2 & 4)
     443                button->flags2 |= 0x10;
     444        else
     445                button->flags2 &= 0xef;
     446
     447        button->flags2 &= 0xfb;
     448
     449        processButton(button);
     450}
     451
     452int KyraEngine::drawBoxCallback(Button *button) {
     453        if (!_displayMenu)
     454                return 0;
     455
     456        _screen->hideMouse();
     457        _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 0xf8);
     458        _screen->showMouse();
     459
     460        return 0;
     461}
     462
     463int KyraEngine::drawShadedBoxCallback(Button *button) {
     464        if (!_displayMenu)
     465                return 0;
     466       
     467        _screen->hideMouse();
     468        _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 0xf9, 0xfa);
     469        _screen->showMouse();
     470
     471        return 0;
     472}
     473
     474void KyraEngine::setGUILabels() {
     475        int offset = 0;
     476        int offsetOptions = 0;
     477        int offsetMainMenu = 0;
     478        int offsetOn = 0;
     479
     480        int walkspeedGarbageOffset = 36;
     481        int menuLabelGarbageOffset = 0;
     482       
     483        if (_flags.isTalkie) {
     484                if (_flags.lang == Common::EN_ANY)
     485                        offset = 52;
     486                else if (_flags.lang == Common::DE_DEU)
     487                        offset = 30;
     488                else if (_flags.lang == Common::FR_FRA || _flags.lang == Common::IT_ITA)
     489                        offset = 6;
     490                offsetOn = offsetMainMenu = offsetOptions = offset;
     491                walkspeedGarbageOffset = 48;
     492        } else if (_flags.lang == Common::ES_ESP) {
     493                offsetOn = offsetMainMenu = offsetOptions = offset = -4;
     494                menuLabelGarbageOffset = 72;
     495        } else if (_flags.lang == Common::DE_DEU) {
     496                offset = offsetMainMenu = offsetOn = offsetOptions = 24;
     497        } else if (_flags.platform == Common::kPlatformFMTowns) {
     498                offset = 1;
     499                offsetOptions = 10;
     500                offsetOn = 0;
     501                walkspeedGarbageOffset = 0;
     502        }
     503
     504        assert(offset + 27 < _guiStringsSize);
     505               
     506        // The Legend of Kyrandia
     507        _menu[0].menuName = _guiStrings[0];
     508        // Load a Game
     509        _menu[0].item[0].itemString = _guiStrings[1];
     510        // Save a Game
     511        _menu[0].item[1].itemString = _guiStrings[2];
     512        // Game controls
     513        _menu[0].item[2].itemString = _guiStrings[3];
     514        // Quit playing
     515        _menu[0].item[3].itemString = _guiStrings[4];
     516        // Resume game
     517        _menu[0].item[4].itemString = _guiStrings[5];
     518
     519        // Cancel
     520        _menu[2].item[5].itemString = _guiStrings[10];
     521       
     522        // Enter a description of your saved game:
     523        _menu[3].menuName = _guiStrings[11];
     524        // Save
     525        _menu[3].item[0].itemString = _guiStrings[12];
     526        // Cancel
     527        _menu[3].item[1].itemString = _guiStrings[10];
     528
     529        // Rest in peace, Brandon
     530        _menu[4].menuName = _guiStrings[13];
     531        // Load a game
     532        _menu[4].item[0].itemString = _guiStrings[1];
     533        // Quit playing
     534        _menu[4].item[1].itemString = _guiStrings[4];
     535       
     536        // Game Controls
     537        _menu[5].menuName = _guiStrings[6];
     538        // Yes
     539        _menu[1].item[0].itemString = _guiStrings[22 + offset];
     540        // No
     541        _menu[1].item[1].itemString = _guiStrings[23 + offset];
     542               
     543        // Music is
     544        _menu[5].item[0].labelString = _guiStrings[26 + offsetOptions];
     545        // Sounds are
     546        _menu[5].item[1].labelString = _guiStrings[27 + offsetOptions];
     547        // Walk speed
     548        _menu[5].item[2].labelString = &_guiStrings[24 + offsetOptions][walkspeedGarbageOffset];
     549        // Text speed
     550        _menu[5].item[4].labelString = _guiStrings[25 + offsetOptions];
     551        // Main Menu
     552        _menu[5].item[5].itemString = &_guiStrings[19 + offsetMainMenu][menuLabelGarbageOffset];
     553       
     554        if (_flags.isTalkie)
     555                // Text & Voice
     556                _voiceTextString = _guiStrings[28 + offset];
     557
     558        _textSpeedString = _guiStrings[25 + offsetOptions];
     559        _onString =  _guiStrings[20 + offsetOn];
     560        _offString =  _guiStrings[21 + offset];
     561        _onCDString = _guiStrings[21];
     562}
     563
     564int KyraEngine::buttonMenuCallback(Button *caller) {
     565        _displayMenu = true;
     566
     567        assert(_guiStrings);
     568        assert(_configStrings);
     569       
     570        /*
     571        for (int i = 0; i < _guiStringsSize; i++)
     572                debug("GUI string %i: %s", i, _guiStrings[i]);
     573
     574        for (int i = 0; i < _configStringsSize; i++)
     575                debug("Config string %i: %s", i, _configStrings[i]);
     576        */
     577       
     578        setGUILabels();
     579        if (_currentCharacter->sceneId == 210 && _deathHandler == 0xFF) {
     580                snd_playSoundEffect(0x36);
     581                return 0;
     582        }
     583        // XXX
     584        _screen->setPaletteIndex(0xFE, 60, 60, 0);
     585        for (int i = 0; i < 6; i++) {
     586                _menuButtonData[i].process0 = _menuButtonData[i].process1 = _menuButtonData[i].process2 = 4;
     587                _menuButtonData[i].process0PtrCallback = &KyraEngine::drawShadedBoxCallback;
     588                _menuButtonData[i].process1PtrCallback = &KyraEngine::drawBoxCallback;
     589                _menuButtonData[i].process2PtrCallback = &KyraEngine::drawShadedBoxCallback;
     590        }
     591
     592        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     593        gui_fadePalette();
     594
     595        for (int i = 0; i < 5; i++)
     596                calcCoords(_menu[i]);
     597
     598        _menuRestoreScreen = true;
     599        _keyPressed.reset();
     600        _mousePressFlag = false;
     601       
     602        _toplevelMenu = 0;
     603        if (_menuDirectlyToLoad) {
     604                gui_loadGameMenu(0);
     605        } else {
     606                if (!caller)
     607                        _toplevelMenu = 4;
     608
     609                initMenu(_menu[_toplevelMenu]);
     610                processAllMenuButtons();
     611        }
     612
     613        while (_displayMenu && !_quitFlag) {
     614                gui_processHighlights(_menu[_toplevelMenu]);
     615                processButtonList(_menuButtonList);
     616                gui_getInput();
     617        }
     618
     619        if (_menuRestoreScreen) {
     620                gui_restorePalette();
     621                _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     622                _animator->_updateScreen = true;
     623        } else {
     624                _screen->deletePageFromDisk(0);
     625        }
     626
     627        return 0;
     628}
     629
     630void KyraEngine::initMenu(Menu &menu) {
     631        _menuButtonList = 0;
     632
     633        _screen->hideMouse();
     634
     635        int textX;
     636        int textY;
     637
     638        int menu_x2 = menu.width  + menu.x - 1;
     639        int menu_y2 = menu.height + menu.y - 1;
     640
     641        _screen->fillRect(menu.x + 2, menu.y + 2, menu_x2 - 2, menu_y2 - 2, menu.bgcolor);
     642        _screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2);
     643
     644        if (menu.field_10 != -1)
     645                textX = menu.x;
     646        else
     647                textX = _text->getCenterStringX(menu.menuName, menu.x, menu_x2);
     648
     649        textY = menu.y + menu.field_12;
     650
     651        _text->printText(menu.menuName, textX - 1, textY + 1, 12, 248, 0);
     652        _text->printText(menu.menuName, textX, textY, menu.textColor, 0, 0);
     653
     654        int x1, y1, x2, y2;     
     655        for (int i = 0; i < menu.nrOfItems; i++) {
     656                if (!menu.item[i].enabled)
     657                        continue;
     658
     659                x1 = menu.x + menu.item[i].x;
     660                y1 = menu.y + menu.item[i].y;
     661
     662                x2 = x1 + menu.item[i].width - 1;
     663                y2 = y1 + menu.item[i].height - 1;
     664
     665                if (i < 6) {
     666                        _menuButtonData[i].nextButton = 0;
     667                        _menuButtonData[i].x = x1;
     668                        _menuButtonData[i].y = y1;
     669                        _menuButtonData[i].width  = menu.item[i].width  - 1;
     670                        _menuButtonData[i].height = menu.item[i].height - 1;
     671                        _menuButtonData[i].buttonCallback = menu.item[i].callback;
     672                        _menuButtonData[i].specialValue = menu.item[i].field_1b;
     673                        //_menuButtonData[i].field_6 = menu.item[i].field_25;
     674                        //_menuButtonData[i].field_8 = 0;
     675
     676                        if (!_menuButtonList)
     677                                _menuButtonList = &_menuButtonData[i];
     678                        else
     679                                _menuButtonList = initButton(_menuButtonList, &_menuButtonData[i]);
     680                }
     681                _screen->fillRect(x1, y1, x2, y2, menu.item[i].bgcolor);
     682                _screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2);
     683
     684                if (menu.item[i].itemString) {
     685                        if (menu.item[i].field_12 != -1 && _flags.lang == Common::EN_ANY)
     686                                textX = x1 + menu.item[i].field_12 + 3;
     687                        else
     688                                textX = _text->getCenterStringX(menu.item[i].itemString, x1, x2);
     689
     690                        textY = y1 + 2;
     691                        _text->printText(menu.item[i].itemString, textX - 1, textY + 1,  12, 0, 0);
     692
     693                        if (i == menu.highlightedItem)
     694                                _text->printText(menu.item[i].itemString, textX, textY, menu.item[i].highlightColor, 0, 0);
     695                        else
     696                                _text->printText(menu.item[i].itemString, textX, textY, menu.item[i].textColor, 0, 0);
     697
     698                        if (menu.item[i].labelString) {
     699                                _text->printText(menu.item[i].labelString, menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, 12, 0, 0);
     700                                _text->printText(menu.item[i].labelString, menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, 253, 0, 0);
     701                        }
     702                }
     703        }
     704
     705        if (menu.scrollUpBtnX != -1) {
     706                _haveScrollButtons = true;
     707
     708                _scrollUpButton.x = menu.scrollUpBtnX + menu.x;
     709                _scrollUpButton.y = menu.scrollUpBtnY + menu.y;
     710                _scrollUpButton.buttonCallback = &KyraEngine::gui_scrollUp;
     711                _scrollUpButton.nextButton = 0;
     712                _menuButtonList = initButton(_menuButtonList, &_scrollUpButton);
     713                processMenuButton(&_scrollUpButton);
     714               
     715                _scrollDownButton.x = menu.scrollDownBtnX + menu.x;
     716                _scrollDownButton.y = menu.scrollDownBtnY + menu.y;
     717                _scrollDownButton.buttonCallback = &KyraEngine::gui_scrollDown;
     718                _scrollDownButton.nextButton = 0;
     719                _menuButtonList = initButton(_menuButtonList, &_scrollDownButton);
     720                processMenuButton(&_scrollDownButton);
     721        } else {
     722                _haveScrollButtons = false;
     723        }
     724
     725        _screen->showMouse();
     726        _screen->updateScreen();
     727}
     728
     729void KyraEngine::calcCoords(Menu &menu) {
     730        assert(menu.nrOfItems < 7);
     731
     732        int widthBackup = _screen->_charWidth;
     733        _screen->_charWidth = -2;
     734       
     735        menu.x = (320 - menu.width)/2;
     736
     737        int menu_x2 = menu.width  + menu.x - 1;
     738        int maxOffset = 0;
     739        int x1, x2, y1, y2;     
     740
     741        for (int i = 0; i < menu.nrOfItems; i++) {
     742                if (menu.item[i].x == -1)
     743                        menu.item[i].x = (menu.width - menu.item[i].width)/2;
     744
     745                if (menu.item[i].labelString) {
     746                        x1 = menu.x + menu.item[i].x + 25;
     747                        y1 = (200 - menu.height)/2 + menu.item[i].y;
     748
     749                        x2 = x1 + menu.item[i].width;
     750                        y2 = y1 + menu.item[i].height;
     751
     752                        int textWidth = _screen->getTextWidth(menu.item[i].labelString) + 25;
     753                        int textX = menu.item[i].labelX + menu.x;
     754
     755                        if (textWidth + textX > x1) {
     756                                int offset = ((textWidth + textX) - x1);
     757                                if (maxOffset < offset)
     758                                        maxOffset = offset;
     759                        }
     760                }
     761               
     762                if (menu.item[i].itemString) {
     763                        int textWidth = _screen->getTextWidth(menu.item[i].itemString) + 15;
     764
     765                        if (menu.item[i].width < textWidth) {
     766                                menu.item[i].width = textWidth;
     767                               
     768                                if ( menu.x + menu.item[i].x + menu.item[i].width > menu_x2)
     769                                        menu.item[i].x -= (menu.x + menu.item[i].x + menu.item[i].width) - menu_x2 + 10;
     770                        }
     771                }       
     772               
     773        }
     774
     775        if (maxOffset > 0) {
     776                maxOffset = maxOffset/2;
     777                for (int i = 0; i < menu.nrOfItems; i++) {
     778                        menu.item[i].x += maxOffset + 10;
     779                        menu.item[i].labelX -= maxOffset;
     780                }
     781                menu.width += maxOffset;
     782        }
     783       
     784        if (menu.menuName != 0) {
     785                int menuNameLength = _screen->getTextWidth(menu.menuName);
     786                if (menuNameLength  > menu.width)
     787                        menu.width = menuNameLength;
     788        }
     789
     790        if (menu.width > 310)
     791                menu.width = 310;
     792
     793        menu.x = (320 - menu.width)/2;
     794                       
     795        if (menu.y == -1)
     796                menu.y = (200 - menu.height)/2;
     797               
     798        _screen->_charWidth = widthBackup;
     799}
     800
     801void KyraEngine::gui_getInput() {
     802        Common::Event event;
     803        static uint32 lastScreenUpdate = 0;
     804        uint32 now = _system->getMillis();
     805
     806        _mouseWheel = 0;
     807        while (_eventMan->pollEvent(event)) {
     808                switch (event.type) {
     809                case Common::EVENT_QUIT:
     810                        quitGame();
     811                        break;
     812                case Common::EVENT_LBUTTONDOWN:
     813                        _mousePressFlag = true;
     814                        break;
     815                case Common::EVENT_LBUTTONUP:
     816                        _mousePressFlag = false;
     817                        break;
     818                case Common::EVENT_MOUSEMOVE:
     819                        _system->updateScreen();
     820                        lastScreenUpdate = now;
     821                        break;
     822                case Common::EVENT_WHEELUP:
     823                        _mouseWheel = -1;
     824                        break;
     825                case Common::EVENT_WHEELDOWN:
     826                        _mouseWheel = 1;
     827                        break;
     828                case Common::EVENT_KEYDOWN:
     829                        _keyPressed = event.kbd;
     830                        break;
     831                default:
     832                        break;
     833                }
     834        }
     835
     836        if (now - lastScreenUpdate > 50) {
     837                _system->updateScreen();
     838                lastScreenUpdate = now;
     839        }
     840
     841        _system->delayMillis(3);
     842}
     843
     844int KyraEngine::gui_resumeGame(Button *button) {
     845        debugC(9, kDebugLevelGUI, "KyraEngine::gui_resumeGame()");
     846        processMenuButton(button);
     847        _displayMenu = false;
     848
     849        return 0;
     850}
     851
     852const char *KyraEngine::getSavegameFilename(int num) {
     853        static char saveLoadSlot[12];
     854
     855        sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), num);
     856        return saveLoadSlot;
     857}
     858
     859int KyraEngine::getNextSavegameSlot() {
     860        Common::InSaveFile *in;
     861
     862        for (int i = 1; i < 1000; i++) {
     863                if ((in = _saveFileMan->openForLoading(getSavegameFilename(i))))
     864                        delete in;
     865                else
     866                        return i;
     867        }
     868        warning("Didn't save: Ran out of savegame filenames");
     869        return 0;
     870}
     871
     872void KyraEngine::setupSavegames(Menu &menu, int num) {
     873        Common::InSaveFile *in;
     874        static char savenames[5][31];
     875        uint8 startSlot;
     876        assert(num <= 5);
     877
     878        if (_savegameOffset == 0) {
     879                menu.item[0].itemString = _specialSavegameString;
     880                menu.item[0].enabled = 1;
     881                menu.item[0].field_1b = 0;
     882                startSlot = 1;
     883        } else {
     884                startSlot = 0;
     885        }
     886
     887        for (int i = startSlot; i < num; i++) {
     888                if ((in = _saveFileMan->openForLoading(getSavegameFilename(i + _savegameOffset)))) {
     889                        in->skip(8);
     890                        in->read(savenames[i], 31);
     891                        menu.item[i].itemString = savenames[i];
     892                        menu.item[i].enabled = 1;
     893                        menu.item[i].field_1b = i + _savegameOffset;
     894                        delete in;
     895                } else {
     896                        menu.item[i].enabled = 0;
     897                        //menu.item[i].itemString = "";
     898                        //menu.item[i].field_1b = -1;
     899                }
     900        }
     901}
     902
     903int KyraEngine::gui_saveGameMenu(Button *button) {
     904        debugC(9, kDebugLevelGUI, "KyraEngine::gui_saveGameMenu()");
     905        processMenuButton(button);
     906        _menu[2].item[5].enabled = true;
     907
     908        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     909        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     910
     911        _menu[2].menuName = _guiStrings[8]; // Select a position to save to:
     912        _specialSavegameString = _guiStrings[9]; // [ EMPTY SLOT ]
     913        for (int i = 0; i < 5; i++)
     914                _menu[2].item[i].callback = &KyraEngine::gui_saveGame;
     915
     916        _savegameOffset = 0;
     917        setupSavegames(_menu[2], 5);
     918
     919        initMenu(_menu[2]);
     920        processAllMenuButtons();
     921
     922        _displaySubMenu = true;
     923        _cancelSubMenu = false;
     924
     925        while (_displaySubMenu && !_quitFlag) {
     926                gui_getInput();
     927                gui_processHighlights(_menu[2]);
     928                processButtonList(_menuButtonList);
     929        }
     930
     931        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     932        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     933
     934        if (_cancelSubMenu) {
     935                initMenu(_menu[0]);
     936                processAllMenuButtons();
     937        } else {
     938                _displayMenu = false;
     939        }
     940        return 0;
     941}
     942
     943int KyraEngine::gui_loadGameMenu(Button *button) {
     944        debugC(9, kDebugLevelGUI, "KyraEngine::gui_loadGameMenu()");
     945        if (_menuDirectlyToLoad) {
     946                _menu[2].item[5].enabled = false;
     947        } else {
     948                processMenuButton(button);
     949                _menu[2].item[5].enabled = true;
     950        }
     951
     952        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     953        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     954
     955        _specialSavegameString = _newGameString[0]; //[ START A NEW GAME ]
     956        _menu[2].menuName = _guiStrings[7]; // Which game would you like to reload?
     957        for (int i = 0; i < 5; i++)
     958                _menu[2].item[i].callback = &KyraEngine::gui_loadGame;
     959
     960        _savegameOffset = 0;
     961        setupSavegames(_menu[2], 5);
     962
     963        initMenu(_menu[2]);
     964        processAllMenuButtons();
     965
     966        _displaySubMenu = true;
     967        _cancelSubMenu = false;
     968
     969        while (_displaySubMenu && !_quitFlag) {
     970                gui_getInput();
     971                gui_processHighlights(_menu[2]);
     972                processButtonList(_menuButtonList);
     973        }
     974
     975        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     976        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     977
     978        if (_cancelSubMenu) {
     979                initMenu(_menu[_toplevelMenu]);
     980                processAllMenuButtons();
     981        } else {
     982                gui_restorePalette();
     983                loadGame(getSavegameFilename(_gameToLoad));
     984                _displayMenu = false;
     985                _menuRestoreScreen = false;
     986        }
     987        return 0;
     988}
     989
     990void KyraEngine::gui_redrawTextfield() {
     991        _screen->fillRect(38, 91, 287, 102, 250);
     992        _text->printText(_savegameName, 38, 92, 253, 0, 0);
     993
     994        _screen->_charWidth = -2;
     995        int width = _screen->getTextWidth(_savegameName);
     996        _screen->fillRect(39 + width, 93, 45 + width, 100, 254);
     997        _screen->_charWidth = 0;
     998
     999        _screen->updateScreen();
     1000}
     1001
     1002void KyraEngine::gui_updateSavegameString() {
     1003        int length;
     1004
     1005        if (_keyPressed.keycode) {
     1006                length = strlen(_savegameName);
     1007
     1008                if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127) {
     1009                        if (length < 31) {
     1010                                _savegameName[length] = _keyPressed.ascii;
     1011                                _savegameName[length+1] = 0;
     1012                                gui_redrawTextfield();
     1013                        }
     1014                } else if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE ||
     1015                           _keyPressed.keycode == Common::KEYCODE_DELETE) {
     1016                        if (length > 0) {
     1017                                _savegameName[length-1] = 0;
     1018                                gui_redrawTextfield();
     1019                        }
     1020                } else if (_keyPressed.keycode == Common::KEYCODE_RETURN ||
     1021                           _keyPressed.keycode == Common::KEYCODE_KP_ENTER) {
     1022                        _displaySubMenu = false;
     1023                }
     1024        }
     1025
     1026        _keyPressed.reset();
     1027}
     1028
     1029int KyraEngine::gui_saveGame(Button *button) {
     1030        debugC(9, kDebugLevelGUI, "KyraEngine::gui_saveGame()");
     1031        processMenuButton(button);
     1032        _gameToLoad = button->specialValue;
     1033
     1034        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     1035        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     1036
     1037        initMenu(_menu[3]);
     1038        processAllMenuButtons();
     1039
     1040        _displaySubMenu = true;
     1041        _cancelSubMenu = false;
     1042
     1043        if (_savegameOffset == 0 && _gameToLoad == 0) {
     1044                _savegameName[0] = 0;
     1045        } else {
     1046                for (int i = 0; i < 5; i++) {
     1047                        if (_menu[2].item[i].field_1b == _gameToLoad) {
     1048                                strncpy(_savegameName, _menu[2].item[i].itemString, 31);
     1049                                break;
     1050                        }
     1051                }
     1052        }
     1053        gui_redrawTextfield();
     1054
     1055        while (_displaySubMenu && !_quitFlag) {
     1056                gui_getInput();
     1057                gui_updateSavegameString();
     1058                gui_processHighlights(_menu[3]);
     1059                processButtonList(_menuButtonList);
     1060        }
     1061
     1062        if (_cancelSubMenu) {
     1063                _displaySubMenu = true;
     1064                _cancelSubMenu = false;
     1065                initMenu(_menu[2]);
     1066                processAllMenuButtons();
     1067        } else {
     1068                if (_savegameOffset == 0 && _gameToLoad == 0)
     1069                        _gameToLoad = getNextSavegameSlot();
     1070                if (_gameToLoad > 0)
     1071                        saveGame(getSavegameFilename(_gameToLoad), _savegameName);
     1072        }
     1073
     1074        return 0;
     1075}
     1076
     1077int KyraEngine::gui_savegameConfirm(Button *button) {
     1078        debugC(9, kDebugLevelGUI, "KyraEngine::gui_savegameConfirm()");
     1079        processMenuButton(button);
     1080        _displaySubMenu = false;
     1081
     1082        return 0;
     1083}
     1084
     1085int KyraEngine::gui_loadGame(Button *button) {
     1086        debugC(9, kDebugLevelGUI, "KyraEngine::gui_loadGame()");
     1087        processMenuButton(button);
     1088        _displaySubMenu = false;
     1089        _gameToLoad = button->specialValue;
     1090
     1091        return 0;
     1092}
     1093
     1094int KyraEngine::gui_cancelSubMenu(Button *button) {
     1095        debugC(9, kDebugLevelGUI, "KyraEngine::gui_cancelLoadGameMenu()");
     1096        processMenuButton(button);
     1097        _displaySubMenu = false;
     1098        _cancelSubMenu = true;
     1099
     1100        return 0;
     1101}
     1102
     1103int KyraEngine::gui_quitPlaying(Button *button) {
     1104        debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitPlaying()");
     1105        processMenuButton(button);
     1106
     1107        if (gui_quitConfirm(_guiStrings[14])) { // Are you sure you want to quit playing?
     1108                quitGame();
     1109        } else {
     1110                initMenu(_menu[_toplevelMenu]);
     1111                processAllMenuButtons();
     1112        }
     1113
     1114        return 0;
     1115}
     1116
     1117bool KyraEngine::gui_quitConfirm(const char *str) {
     1118        debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirm()");
     1119
     1120        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     1121        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     1122
     1123        _menu[1].menuName = str;
     1124        calcCoords(_menu[1]);
     1125        initMenu(_menu[1]);
     1126       
     1127        _displaySubMenu = true;
     1128        _cancelSubMenu = true;
     1129
     1130        while (_displaySubMenu && !_quitFlag) {
     1131                gui_getInput();
     1132                gui_processHighlights(_menu[1]);
     1133                processButtonList(_menuButtonList);
     1134        }
     1135
     1136        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     1137        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     1138
     1139        return !_cancelSubMenu;
     1140}
     1141
     1142int KyraEngine::gui_quitConfirmYes(Button *button) {
     1143        debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirmYes()");
     1144        processMenuButton(button);
     1145        _displaySubMenu = false;
     1146        _cancelSubMenu = false;
     1147
     1148        return 0;
     1149}
     1150
     1151int KyraEngine::gui_quitConfirmNo(Button *button) {
     1152        debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirmNo()");
     1153        processMenuButton(button);
     1154        _displaySubMenu = false;
     1155        _cancelSubMenu = true;
     1156
     1157        return 0;
     1158}
     1159
     1160int KyraEngine::gui_gameControlsMenu(Button *button) {
     1161        debugC(9, kDebugLevelGUI, "KyraEngine::gui_gameControlsMenu()");
     1162
     1163        readSettings();
     1164
     1165        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     1166        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     1167
     1168        if (_flags.isTalkie) {
     1169                //_menu[5].width = 230;
     1170
     1171                for (int i = 0; i < 5; i++) {
     1172                        //_menu[5].item[i].labelX = 24;
     1173                        //_menu[5].item[i].x = 115;
     1174                        //_menu[5].item[i].width = 94;
     1175                }
     1176
     1177                _menu[5].item[3].labelString = _voiceTextString; //"Voice / Text "
     1178                _menu[5].item[3].callback = &KyraEngine::gui_controlsChangeVoice;
     1179
     1180        } else {
     1181                //_menu[5].height = 136;
     1182                //_menu[5].item[5].y = 110;
     1183                _menu[5].item[4].enabled = 0;
     1184                _menu[5].item[3].labelString = _textSpeedString; // "Text speed "
     1185                _menu[5].item[3].callback = &KyraEngine::gui_controlsChangeText;
     1186        }
     1187
     1188        gui_setupControls(_menu[5]);
     1189
     1190        processAllMenuButtons();
     1191
     1192        _displaySubMenu = true;
     1193        _cancelSubMenu = false;
     1194
     1195        while (_displaySubMenu && !_quitFlag) {
     1196                gui_getInput();
     1197                gui_processHighlights(_menu[5]);
     1198                processButtonList(_menuButtonList);
     1199        }
     1200
     1201        _screen->loadPageFromDisk("SEENPAGE.TMP", 0);
     1202        _screen->savePageToDisk("SEENPAGE.TMP", 0);
     1203
     1204        if (_cancelSubMenu) {
     1205                initMenu(_menu[_toplevelMenu]);
     1206                processAllMenuButtons();
     1207        }
     1208        return 0;
     1209}
     1210
     1211void KyraEngine::gui_setupControls(Menu &menu) {
     1212        debugC(9, kDebugLevelGUI, "KyraEngine::gui_setupControls()");
     1213
     1214        switch (_configMusic) {
     1215                case 0:
     1216                        menu.item[0].itemString = _offString; //"Off"
     1217                        break;
     1218                case 1:
     1219                        menu.item[0].itemString = _onString; //"On"
     1220                        break;
     1221                case 2:
     1222                        menu.item[0].itemString = _onCDString; //"On + CD"
     1223                        break;
     1224        }
     1225
     1226        if (_configSounds)
     1227                menu.item[1].itemString = _onString; //"On"
     1228        else
     1229                menu.item[1].itemString = _offString; //"Off"
     1230
     1231
     1232        switch (_configWalkspeed) {
     1233        case 0:
     1234                menu.item[2].itemString = _configStrings[0]; //"Slowest"
     1235                break;
     1236        case 1:
     1237                menu.item[2].itemString = _configStrings[1]; //"Slow"
     1238                break;
     1239        case 2:
     1240                menu.item[2].itemString = _configStrings[2]; //"Normal"
     1241                break;
     1242        case 3:
     1243                menu.item[2].itemString = _configStrings[3]; //"Fast"
     1244                break;
     1245        case 4:
     1246                menu.item[2].itemString = _configStrings[4]; //"Fastest"
     1247                break;
     1248        default:
     1249                menu.item[2].itemString = "ERROR";
     1250                break;
     1251        }
     1252
     1253        int textControl = 3;
     1254        int clickableOffset = 8;
     1255        if (_flags.isTalkie) {
     1256                textControl = 4;
     1257                clickableOffset = 11;
     1258               
     1259                if (_configVoice == 0)
     1260                        _menu[5].item[4].enabled = 1;
     1261                else
     1262                        _menu[5].item[4].enabled = 0;
     1263
     1264                switch (_configVoice) {
     1265                case 0:
     1266                        menu.item[3].itemString = _configStrings[5]; //"Text only"
     1267                        break;
     1268                case 1:
     1269                        menu.item[3].itemString = _configStrings[6]; //"Voice only"
     1270                        break;
     1271                case 2:
     1272                        menu.item[3].itemString = _configStrings[7]; //"Voice & Text"
     1273                        break;
     1274                default:
     1275                        menu.item[3].itemString = "ERROR";
     1276                        break;
     1277                }
     1278        }
     1279
     1280        switch (_configTextspeed) {
     1281        case 0:
     1282                menu.item[textControl].itemString = _configStrings[1]; //"Slow"
     1283                break;
     1284        case 1:
     1285                menu.item[textControl].itemString = _configStrings[2]; //"Normal"
     1286                break;
     1287        case 2:
     1288                menu.item[textControl].itemString = _configStrings[3]; //"Fast"
     1289                break;
     1290        case 3:
     1291                menu.item[textControl].itemString = _configStrings[clickableOffset]; //"Clickable"
     1292                break;
     1293        default:
     1294                menu.item[textControl].itemString = "ERROR";
     1295                break;
     1296        }
     1297
     1298        calcCoords(menu);
     1299        initMenu(menu);
     1300}
     1301
     1302int KyraEngine::gui_controlsChangeMusic(Button *button) {
     1303        debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeMusic()");
     1304        processMenuButton(button);
     1305
     1306        _configMusic = ++_configMusic % (_flags.platform == Common::kPlatformFMTowns ? 3 : 2);
     1307        gui_setupControls(_menu[5]);
     1308        return 0;
     1309}
     1310
     1311int KyraEngine::gui_controlsChangeSounds(Button *button) {
     1312        debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeSounds()");
     1313        processMenuButton(button);
     1314
     1315        _configSounds = !_configSounds;
     1316        gui_setupControls(_menu[5]);
     1317        return 0;
     1318}
     1319
     1320int KyraEngine::gui_controlsChangeWalk(Button *button) {
     1321        debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeWalk()");
     1322        processMenuButton(button);
     1323
     1324        _configWalkspeed = ++_configWalkspeed % 5;
     1325        setWalkspeed(_configWalkspeed);
     1326        gui_setupControls(_menu[5]);
     1327        return 0;
     1328}
     1329
     1330int KyraEngine::gui_controlsChangeText(Button *button) {
     1331        debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeText()");
     1332        processMenuButton(button);
     1333
     1334        _configTextspeed = ++_configTextspeed % 4;
     1335        gui_setupControls(_menu[5]);
     1336        return 0;
     1337}
     1338
     1339int KyraEngine::gui_controlsChangeVoice(Button *button) {
     1340        debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeVoice()");
     1341        processMenuButton(button);
     1342
     1343        _configVoice = ++_configVoice % 3;
     1344        gui_setupControls(_menu[5]);
     1345        return 0;
     1346}
     1347
     1348int KyraEngine::gui_controlsApply(Button *button) {
     1349        debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsApply()");
     1350        writeSettings();
     1351        return gui_cancelSubMenu(button);
     1352}
     1353
     1354int KyraEngine::gui_scrollUp(Button *button) {
     1355        debugC(9, kDebugLevelGUI, "KyraEngine::gui_scrollUp()");
     1356        processMenuButton(button);
     1357
     1358        if (_savegameOffset > 0) {
     1359                _savegameOffset--;
     1360                setupSavegames(_menu[2], 5);
     1361                initMenu(_menu[2]);
     1362        }
     1363        return 0;
     1364}
     1365
     1366int KyraEngine::gui_scrollDown(Button *button) {
     1367        debugC(9, kDebugLevelGUI, "KyraEngine::gui_scrollDown()");
     1368        processMenuButton(button);
     1369
     1370        _savegameOffset++;
     1371        setupSavegames(_menu[2], 5);
     1372        initMenu(_menu[2]);
     1373
     1374        return 0;
     1375}
     1376
     1377void KyraEngine::gui_processHighlights(Menu &menu) {
     1378        int x1, y1, x2, y2;
     1379
     1380        Common::Point mouse = getMousePos();
     1381        for (int i = 0; i < menu.nrOfItems; i++) {
     1382                if (!menu.item[i].enabled)
     1383                        continue;
     1384
     1385                x1 = menu.x + menu.item[i].x;
     1386                y1 = menu.y + menu.item[i].y;
     1387
     1388                x2 = x1 + menu.item[i].width;
     1389                y2 = y1 + menu.item[i].height;
     1390
     1391                if (mouse.x > x1 && mouse.x < x2 &&
     1392                        mouse.y > y1 && mouse.y < y2) {
     1393                       
     1394                        if (menu.highlightedItem != i) {
     1395                                if (menu.item[menu.highlightedItem].enabled )
     1396                                        gui_redrawText(menu);
     1397
     1398                                menu.highlightedItem = i;
     1399                                gui_redrawHighlight(menu);
     1400                                _screen->updateScreen();
     1401                        }
     1402                }
     1403        }
     1404}
     1405
     1406void KyraEngine::gui_redrawText(Menu menu) {
     1407        int textX;
     1408        int i = menu.highlightedItem;
     1409
     1410        int x1 = menu.x + menu.item[i].x;
     1411        int y1 = menu.y + menu.item[i].y;
     1412
     1413        int x2 = x1 + menu.item[i].width - 1;
     1414
     1415        if (menu.item[i].field_12 != -1 &&_flags.lang == Common::EN_ANY)
     1416                textX = x1 + menu.item[i].field_12 + 3;
     1417        else
     1418                textX = _text->getCenterStringX(menu.item[i].itemString, x1, x2);
     1419
     1420        int textY = y1 + 2;
     1421        _text->printText(menu.item[i].itemString, textX - 1, textY + 1,  12, 0, 0);
     1422        _text->printText(menu.item[i].itemString, textX, textY, menu.item[i].textColor, 0, 0);
     1423}
     1424
     1425void KyraEngine::gui_redrawHighlight(Menu menu) {
     1426        int textX;
     1427        int i = menu.highlightedItem;
     1428
     1429        int x1 = menu.x + menu.item[i].x;
     1430        int y1 = menu.y + menu.item[i].y;
     1431
     1432        int x2 = x1 + menu.item[i].width - 1;
     1433
     1434        if (menu.item[i].field_12 != -1 &&_flags.lang == Common::EN_ANY)
     1435                textX = x1 + menu.item[i].field_12 + 3;
     1436        else
     1437                textX = _text->getCenterStringX(menu.item[i].itemString, x1, x2);
     1438
     1439        int textY = y1 + 2;
     1440        _text->printText(menu.item[i].itemString, textX - 1, textY + 1,  12, 0, 0);
     1441        _text->printText(menu.item[i].itemString, textX, textY, menu.item[i].highlightColor, 0, 0);
     1442}
     1443
     1444void KyraEngine::gui_fadePalette() {
     1445        if (_flags.platform == Common::kPlatformAmiga)
     1446                return;
     1447
     1448        static int16 menuPalIndexes[] = {248, 249, 250, 251, 252, 253, 254, -1};
     1449        int index = 0;
     1450
     1451        memcpy(_screen->getPalette(2), _screen->_currentPalette, 768);
     1452
     1453        for (int i = 0; i < 768; i++)
     1454                _screen->_currentPalette[i] >>= 1;
     1455
     1456        while (menuPalIndexes[index] != -1) {
     1457                memcpy(&_screen->_currentPalette[menuPalIndexes[index]*3], &_screen->getPalette(2)[menuPalIndexes[index]*3], 3);
     1458                index++;
     1459        }
     1460
     1461        _screen->fadePalette(_screen->_currentPalette, 2);
     1462}
     1463
     1464void KyraEngine::gui_restorePalette() {
     1465        if (_flags.platform == Common::kPlatformAmiga)
     1466                return;
     1467
     1468        memcpy(_screen->_currentPalette, _screen->getPalette(2), 768);
     1469        _screen->fadePalette(_screen->_currentPalette, 2);
     1470}
     1471
     1472#pragma mark -
     1473
     1474// Kyra 2 and 3 main menu
     1475
     1476void KyraEngine::gui_updateMainMenuAnimation() {
     1477        _screen->updateScreen();
     1478}
     1479
     1480bool KyraEngine::gui_mainMenuGetInput() {
     1481        Common::Event event;
     1482
     1483        while (_eventMan->pollEvent(event)) {
     1484                switch (event.type) {
     1485                case Common::EVENT_QUIT:
     1486                        quitGame();
     1487                        break;
     1488                case Common::EVENT_LBUTTONUP:
     1489                        return true;
     1490                default:
     1491                        break;
     1492                }
     1493        }
     1494        return false;
     1495}
     1496
     1497int KyraEngine::gui_handleMainMenu() {
     1498        debugC(9, kDebugLevelMain, "KyraEngine::gui_handleMainMenu()");
     1499        int command = -1;
     1500       
     1501        uint8 colorMap[16];
     1502        memset(colorMap, 0, sizeof(colorMap));
     1503        _screen->setTextColorMap(colorMap);
     1504       
     1505        const char * const *strings = &_mainMenuStrings[_lang << 2];
     1506        Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT);
     1507        int charWidthBackUp = _screen->_charWidth;
     1508       
     1509        _screen->_charWidth = -2;
     1510        _screen->setScreenDim(3);
     1511        int backUpX = _screen->_curDim->sx;
     1512        int backUpY = _screen->_curDim->sy;
     1513        int backUpWidth = _screen->_curDim->w;
     1514        int backUpHeight = _screen->_curDim->h;
     1515        _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 0, 3);
     1516
     1517        int x = _screen->_curDim->sx << 3;
     1518        int y = _screen->_curDim->sy;
     1519        int width = _screen->_curDim->w << 3;
     1520        int height =  _screen->_curDim->h;
     1521
     1522        gui_drawMainBox(x, y, width, height, 1);
     1523        gui_drawMainBox(x + 1, y + 1, width - 2, height - 2, 0);
     1524       
     1525        int selected = 0;
     1526       
     1527        gui_drawMainMenu(strings, selected);
     1528
     1529        _screen->showMouse();
     1530
     1531        int fh = _screen->getFontHeight();
     1532        int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3;
     1533
     1534        Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4);
     1535       
     1536        while (!_quitFlag) {
     1537                gui_updateMainMenuAnimation();
     1538                bool mousePressed = gui_mainMenuGetInput();
     1539
     1540                Common::Point mouse = getMousePos();
     1541                if (menuRect.contains(mouse)) {
     1542                        int item = (mouse.y - menuRect.top) / fh;
     1543
     1544                        if (item != selected) {
     1545                                gui_printString(strings[selected], textPos, menuRect.top + selected * fh, 0x80, 0, 5);
     1546                                gui_printString(strings[item], textPos, menuRect.top + item * fh, 0xFF, 0, 5);
     1547
     1548                                selected = item;
     1549                        }
     1550
     1551                        if (mousePressed) {
     1552                                // TODO: Flash the text
     1553                                command = item;
     1554                                break;
     1555                        }
     1556                }
     1557                _system->delayMillis(10);
     1558        }
     1559       
     1560        if (_quitFlag)
     1561                command = -1;
     1562       
     1563        _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0);
     1564        _screen->_charWidth = charWidthBackUp;
     1565        _screen->setFont(oldFont);
     1566       
     1567        return command;
     1568}
     1569
     1570void KyraEngine::gui_drawMainMenu(const char * const *strings, int select) {
     1571        debugC(9, kDebugLevelMain, "KyraEngine::gui_drawMainMenu(%p)", (const void*)strings);
     1572        static const uint16 menuTable[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 };
     1573       
     1574        int top = _screen->_curDim->sy;
     1575        top += menuTable[1];
     1576       
     1577        for (int i = 0; i < menuTable[3]; ++i) {
     1578                int curY = top + i * _screen->getFontHeight();
     1579                int color = (i == select) ? menuTable[6] : menuTable[5];
     1580                gui_printString(strings[i], ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5);
     1581        }
     1582}
     1583
     1584void KyraEngine::gui_drawMainBox(int x, int y, int w, int h, int fill) {
     1585        debugC(9, kDebugLevelMain, "KyraEngine::gui_drawMainBox(%d, %d, %d, %d, %d)", x, y, w, h, fill);
     1586        static const uint8 kyra3ColorTable[] = { 0x16, 0x19, 0x1A, 0x16 };
     1587        static const uint8 kyra2ColorTable[] = { 0x0, 0x19, 0x28, 0xc8 };
     1588       
     1589        const uint8 *colorTable;
     1590        if (_flags.gameID == GI_KYRA3)
     1591                colorTable = kyra3ColorTable;
     1592        else
     1593                colorTable = kyra2ColorTable;
     1594               
     1595        --w; --h;
     1596
     1597        if (fill)
     1598                _screen->fillRect(x, y, x+w, y+h, colorTable[0]);
     1599       
     1600        _screen->drawClippedLine(x, y+h, x+w, y+h, colorTable[1]);
     1601        _screen->drawClippedLine(x+w, y, x+w, y+h, colorTable[1]);
     1602        _screen->drawClippedLine(x, y, x+w, y, colorTable[2]);
     1603        _screen->drawClippedLine(x, y, x, y+h, colorTable[2]);
     1604       
     1605        _screen->setPagePixel(_screen->_curPage, x, y+h, colorTable[3]);
     1606        _screen->setPagePixel(_screen->_curPage, x+w, y, colorTable[3]);
     1607}
     1608
     1609void KyraEngine::gui_printString(const char *format, int x, int y, int col1, int col2, int flags, ...) {
     1610        debugC(9, kDebugLevelMain, "KyraEngine::gui_printString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags);
     1611        if (!format)
     1612                return;
     1613       
     1614        char string[512];
     1615        va_list vaList;
     1616        va_start(vaList, flags);
     1617        vsprintf(string, format, vaList);
     1618        va_end(vaList);
     1619       
     1620        if (flags & 1)
     1621                x -= _screen->getTextWidth(string) >> 1;
     1622       
     1623        if (flags & 2)
     1624                x -= _screen->getTextWidth(string);
     1625       
     1626        if (flags & 4) {
     1627                _screen->printText(string, x - 1, y, 240, col2);
     1628                _screen->printText(string, x, y + 1, 240, col2);
     1629        }
     1630       
     1631        if (flags & 8) {
     1632                _screen->printText(string, x - 1, y, 227, col2);
     1633                _screen->printText(string, x, y + 1, 227, col2);
     1634        }
     1635       
     1636        _screen->printText(string, x, y, col1, col2);
     1637}
     1638
     1639} // end of namespace Kyra
     1640 
  • engines/kyra/vqa.cpp

     
    3232// The jung2.vqa movie does work, but only thanks to a grotesque hack.
    3333
    3434#include "common/stdafx.h"
    35 #include "common/events.h"
     35#include "common/event-manager.h"
    3636#include "common/system.h"
    3737#include "sound/audiostream.h"
    3838#include "sound/mixer.h"
  • engines/kyra/sequences_v1.cpp

     
    3434#include "kyra/text.h"
    3535#include "kyra/timer.h"
    3636
    37 #include "common/events.h"
     37#include "common/event-manager.h"
    3838#include "common/system.h"
    3939#include "common/savefile.h"
    4040
  • engines/kyra/kyra.h

     
    2929#include "engines/engine.h"
    3030#include "common/rect.h"
    3131#include "common/array.h"
    32 #include "common/events.h"
     32#include "common/event-manager.h"
     33#include "common/system.h"
    3334
    3435#include "kyra/util.h"
    3536
  • engines/kyra/text.cpp

     
    2929#include "kyra/screen.h"
    3030#include "kyra/text.h"
    3131
    32 #include "common/events.h"
     32#include "common/event-manager.h"
    3333#include "common/system.h"
    3434#include "common/endian.h"
    3535
  • engines/kyra/gui_v1.cpp

     
    3232
    3333#include "common/config-manager.h"
    3434#include "common/savefile.h"
    35 #include "common/events.h"
     35#include "common/event-manager.h"
    3636#include "common/system.h"
    3737
    3838namespace Kyra {
  • engines/lure/events.cpp

     
    2424 */
    2525
    2626#include "common/stdafx.h"
    27 #include "common/events.h"
     27#include "common/event-manager.h"
    2828
    2929#include "graphics/cursorman.h"
    3030
  • engines/gob/mult_v2.cpp

     
    11741174
    11751175                if (_multData->imdIndices[i] != -1) {
    11761176                        int fileN;
    1177                         char *imdFile;
     1177                        char *imdFile = NULL;
    11781178                        int dir;
    11791179                        int startFrame;
    11801180
  • engines/gob/util.cpp

     
    2424 */
    2525
    2626#include "common/stdafx.h"
    27 #include "common/events.h"
     27#include "common/event-manager.h"
    2828
    2929#include "gob/gob.h"
    3030#include "gob/util.h"
  • engines/parallaction/dialogue.cpp

     
    2525
    2626#include "common/stdafx.h"
    2727
    28 #include "common/events.h"
     28#include "common/event-manager.h"
    2929#include "parallaction/parallaction.h"
    3030
     31#include "common/system.h"
    3132
    3233
     34
    3335namespace Parallaction {
    3436
    3537#define SKIPPED_ANSWER             1000
  • engines/parallaction/parallaction.cpp

     
    2626#include "common/stdafx.h"
    2727
    2828#include "common/config-manager.h"
    29 #include "common/events.h"
     29#include "common/event-manager.h"
    3030#include "common/file.h"
    3131#include "common/util.h"
    3232
     33#include "common/system.h"
     34
    3335#include "sound/mididrv.h"
    3436#include "sound/mixer.h"
    3537
  • engines/saga/input.cpp

     
    3333#include "saga/script.h"
    3434#include "saga/isomap.h"
    3535
    36 #include "common/events.h"
     36#include "common/event-manager.h"
    3737#include "common/system.h"
    3838
    3939namespace Saga {
  • engines/queen/input.h

     
    2828
    2929#include "common/util.h"
    3030#include "common/rect.h"
    31 #include "common/events.h"
     31#include "common/event-manager.h"
    3232#include "queen/defs.h"
    3333
    3434class OSystem;
  • engines/queen/journal.cpp

     
    2424 */
    2525
    2626#include "common/stdafx.h"
    27 #include "common/events.h"
     27#include "common/event-manager.h"
    2828#include "common/system.h"
    2929#include "queen/journal.h"
    3030
  • engines/cine/main_loop.cpp

     
    2525
    2626#include "common/stdafx.h"
    2727#include "common/scummsys.h"
    28 #include "common/events.h"
     28#include "common/event-manager.h"
    2929#include "common/system.h"
    3030
    3131#include "cine/main_loop.h"
  • gui/newgui.cpp

     Index: gui/newgui.cpp
     
    2323 */
    2424
    2525#include "common/stdafx.h"
    26 #include "common/events.h"
     26#include "common/event-manager.h"
    2727#include "common/system.h"
    2828#include "common/util.h"
    2929#include "graphics/cursorman.h"
  • gui/themes/modern.ini

     
    333333gameoptions_platform=prev.x opYoffset prev.w prev.h
    334334opYoffset=(opYoffset + prev.h + ySeparation)
    335335
     336# keys tab
     337gameoptions_defaultkeys=(parent.w - buttonWidth - 10) 10 buttonWidth buttonHeight
     338gameoptions_editkey=prev.x (prev.y2 + 10) prev.w prev.h
     339gameoptions_clearkey=prev.x (prev.y2 + 10) prev.w prev.h
     340gameoptions_actionslist=10 10 (parent.w - buttonWidth - 3 * 10) (parent.h - 3 * buttonHeight - 2 * 10)
     341
    336342# paths tab
    337343opYoffset=optionsVPad
    338344goOff=((buttonHeight - kLineHeight) / 2 + 2)
     
    387393keysdialog_mapping=prev.x (prev.y + kLineHeight) prev.w prev.h
    388394keysdialog_mapping.align=kTextAlignCenter
    389395
     396### key mapper dialog
     397keymapperdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 5)
     398set_parent=keymapperdialog
     399keymapperdialog_map=(parent.w - buttonWidth - 10) 20 buttonWidth buttonHeight
     400keymapperdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h
     401keymapperdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h
     402keymapperdialog_list=10 10 (prev.x - 20) (parent.h - kLineHeight * 4 - self.y)
     403keymapperdialog_action=prev.x (parent.h - kLineHeight * 3) (parent.w - self.x * 2) kLineHeight
     404keymapperdialog_action.align=kTextAlignCenter
     405keymapperdialog_mapping=prev.x (prev.y + kLineHeight) prev.w prev.h
     406keymapperdialog_mapping.align=kTextAlignCenter
     407
    390408### mass add dialog
    391409massadddialog=10 20 300 174
    392410set_parent=massadddialog
  • gui/themes/classic080.ini

     
    171171gameoptions_platform=prev.x opYoffset prev.w prev.h
    172172opYoffset=(opYoffset + prev.h + 5)
    173173
     174# keys tab
     175gameoptions_defaultkeys=(parent.w - buttonWidth - 10) 10 buttonWidth buttonHeight
     176gameoptions_editkey=prev.x (prev.y2 + 10) prev.w prev.h
     177gameoptions_clearkey=prev.x (prev.y2 + 10) prev.w prev.h
     178gameoptions_actionslist=10 10 (parent.w - buttonWidth - 3 * 10) (parent.h - 3 * buttonHeight - 2 * 10)
     179
    174180# paths tab
    175181opYoffset=vBorder
    176182goOff=((buttonHeight - kLineHeight) / 2 + 2)
     
    223229keysdialog_action=prev.x (parent.h - kLineHeight * 3) (parent.w - self.x * 2) kLineHeight
    224230keysdialog_mapping=prev.x (prev.y + kLineHeight) prev.w prev.h
    225231
     232### key mapper dialog
     233keymapperdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 5)
     234set_parent=keymapperdialog
     235keymapperdialog_map=(parent.w - buttonWidth - 10) 20 buttonWidth buttonHeight
     236keymapperdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h
     237keymapperdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h
     238keymapperdialog_list=10 10 (prev.x - 20) (parent.h - kLineHeight * 4 - self.y)
     239keymapperdialog_action=prev.x (parent.h - kLineHeight * 3) (parent.w - self.x * 2) kLineHeight
     240keymapperdialog_action.align=kTextAlignCenter
     241keymapperdialog_mapping=prev.x (prev.y + kLineHeight) prev.w prev.h
     242keymapperdialog_mapping.align=kTextAlignCenter
     243
     244
    226245### mass add dialog
    227246massadddialog=10 20 300 174
    228247set_parent=massadddialog
  • gui/key-mapper-dialog.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/gui/KeyMapperDialog.h $
     22 * $Id: KeyMapperDialog.h 27786 2007-06-30 12:26:59Z fingolfin $
     23 *
     24 */
     25
     26#ifndef KeyMapperDialog_H
     27#define KeyMapperDialog_H
     28
     29#include "gui/newgui.h"
     30#include "gui/dialog.h"
     31#include "gui/ListWidget.h"
     32#include "common/str.h"
     33#include "common/event-manager.h"
     34
     35namespace GUI {
     36
     37class KeyMapperDialog : public GUI::Dialog {
     38public:
     39
     40        virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
     41        virtual void handleKeyUp(Common::KeyState state);
     42        virtual void handleKeyDown(Common::KeyState state);
     43
     44        static void s_showKeyMapperDialog(const Common::String &title, Common::EventManager *, Common::ActionList);
     45
     46protected:
     47
     48        // key mapper dialog is instantiated only in s_showKeyMapperDialog
     49        // which makes sure that key mapping is enabled (Common::EventManager::getKeyMapper != NULL)
     50        KeyMapperDialog(const Common::String &title, Common::EventManager *, Common::ActionList);
     51
     52        // GUI elements
     53        GUI::ListWidget *_actionsList;
     54        GUI::StaticTextWidget *_actionTitle;
     55        GUI::StaticTextWidget *_keyMapping;
     56
     57        KeyMapper *_keyMapper;
     58        bool _isMappingActive;
     59        Common::ActionList _actions;
     60
     61private:
     62
     63        Common::UserAction getSelectedAction();
     64        uint16 getActionKey(Common::UserAction action);
     65};
     66
     67} // namespace GUI
     68
     69#endif
  • gui/launcher.cpp

     
    3030#include "base/version.h"
    3131
    3232#include "common/config-manager.h"
    33 #include "common/events.h"
     33#include "common/event-manager.h"
    3434#include "common/fs.h"
    3535#include "common/util.h"
    3636#include "common/system.h"
     
    7676
    7777        kCmdExtraBrowser = 'PEXT',
    7878        kCmdGameBrowser = 'PGME',
    79         kCmdSaveBrowser = 'PSAV'
     79        kCmdSaveBrowser = 'PSAV',
     80
     81        kCmdUseDefaultKeys = 'DFTK',
     82        kCmdEditKey = 'EDTK',
     83        kCmdClearKey = 'CLRK',
    8084};
    8185
    8286/*
     
    143147        CheckboxWidget *_globalAudioOverride;
    144148        CheckboxWidget *_globalMIDIOverride;
    145149        CheckboxWidget *_globalVolumeOverride;
     150
     151        ListWidget *_actionsList;
    146152};
    147153
    148154EditGameDialog::EditGameDialog(const String &domain, const String &desc)
     
    197203        }
    198204
    199205        //
     206        // 2) The keys tab
     207        //
     208        tab->addTab("Keys");
     209        ButtonWidget *defaultKeys = new ButtonWidget(tab, "gameoptions_defaultkeys", "Use default", kCmdUseDefaultKeys, 0);
     210        ButtonWidget *editKey = new ButtonWidget(tab, "gameoptions_editkey", "Edit key", kCmdEditKey, 0);
     211        ButtonWidget *clearKey = new ButtonWidget(tab, "gameoptions_clearkey", "Clear key", kCmdClearKey, 0);
     212
     213        _actionsList = new ListWidget(tab, "gameoptions_actionslist");
     214
     215        // TODO check if this is the correct way to use g_system
     216        KeyMapper *keyMapper = g_system->getEventManager()->getKeyMapper();
     217        if (keyMapper) {
     218               
     219        } else {
     220                defaultKeys->setEnabled(false);
     221                editKey->setEnabled(false);
     222                clearKey->setEnabled(false);
     223                _actionsList->setEnabled(false);
     224
     225                // TODO write a static text that key mapping is disabled
     226        }
     227
     228        //
    200229        // 3) The graphics tab
    201230        //
    202231        tab->addTab("Graphics");
     
    234263        addMIDIControls(tab, "gameoptions_");
    235264
    236265        //
    237         // 2) The 'Path' tab
     266        // 7) The 'Path' tab
    238267        //
    239268        tab->addTab("Paths");
    240269
     
    461490                        ConfMan.renameGameDomain(_domain, newDomain);
    462491                        _domain = newDomain;
    463492                }
    464                 }
    465                 // FALL THROUGH to default case
     493                break;
     494        }
     495
     496        case kCmdUseDefaultKeys: {
     497                // TODO add functionality
     498                break;
     499        }
     500
     501        case kCmdEditKey: {
     502                // TODO add functionality
     503                break;
     504        }
     505
     506        case kCmdClearKey: {
     507                // TODO add functionality
     508                break;
     509        }
     510
     511        // FALL THROUGH to default case
    466512        default:
    467513                OptionsDialog::handleCommand(sender, cmd, data);
    468514        }
  • gui/theme-config.cpp

     
    252252"gameoptions_platform=prev.x opYoffset prev.w prev.h\n"
    253253"opYoffset=(opYoffset + prev.h + 5)\n"
    254254"\n"
     255"# keys tab\n"
     256"gameoptions_defaultkeys=(parent.w - buttonWidth - 10) 10 buttonWidth buttonHeight\n"
     257"gameoptions_editkey=prev.x (prev.y2 + 10) prev.w prev.h\n"
     258"gameoptions_clearkey=prev.x (prev.y2 + 10) prev.w prev.h\n"
     259"gameoptions_actionslist=10 10 (parent.w - buttonWidth - 3 * 10) (parent.h - 3 * buttonHeight - 2 * 10)"
     260"\n"
    255261"# paths tab\n"
    256262"opYoffset=vBorder\n"
    257263"goOff=((buttonHeight - kLineHeight) / 2 + 2)\n"
  • gui/key-mapper-dialog.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/gui/KeyMapperDialog.cpp $
     22 * $Id: KeyMapperDialog.cpp 27825 2007-07-01 14:19:12Z robinwatts $
     23 *
     24 */
     25
     26#include "common/stdafx.h"
     27#include "gui/key-mapper-dialog.h"
     28#include <SDL_keyboard.h>
     29
     30#ifdef _WIN32_WCE
     31#include "CEDevice.h"
     32#endif
     33
     34namespace GUI {
     35
     36enum {
     37        kMapCmd = 'map ',
     38        kOKCmd  = 'ok  '
     39};
     40
     41KeyMapperDialog::KeyMapperDialog(const Common::String &title, Common::EventManager *eventManager,
     42        Common::ActionList actions) :
     43        GUI::Dialog("keymapperdialog"),
     44        _keyMapper(eventManager->getKeyMapper()),
     45        _actions(actions),
     46        _isMappingActive(false) {
     47
     48        new ButtonWidget(this, "keymapperdialog_map", "Map", kMapCmd, 0);
     49        new ButtonWidget(this, "keymapperdialog_ok", "OK", kOKCmd, 0);
     50        new ButtonWidget(this, "keymapperdialog_cancel", "Cancel", kCloseCmd, 0);
     51
     52        _actionsList = new ListWidget(this, "keymapperdialog_list");
     53        _actionsList->setNumberingMode(kListNumberingOne);
     54
     55        _actionTitle = new StaticTextWidget(this, "keymapperdialog_action", title);
     56        _keyMapping = new StaticTextWidget(this, "keymapperdialog_mapping", "Select an action and click 'Map'");
     57
     58        _actionTitle->setFlags(WIDGET_CLEARBG);
     59        _keyMapping->setFlags(WIDGET_CLEARBG);
     60
     61        // Get actions names
     62        Common::StringList l;
     63        for (Common::ActionList::iterator i = _actions.begin(); i != _actions.end(); i++) {
     64                l.push_back(i->description);
     65        }
     66        _actionsList->setList(l);
     67}
     68
     69void KeyMapperDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
     70        switch (cmd) {
     71
     72        case kListSelectionChangedCmd:
     73                if (_actionsList->getSelected() >= 0) {
     74                        char selection[100];
     75
     76                        Common::UserAction action = getSelectedAction();
     77                        uint16 key = getActionKey(action);
     78
     79                        if (key != 0)
     80                                sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey)key));
     81                        else
     82                                sprintf(selection, "Associated key : none");
     83
     84                        _keyMapping->setLabel(selection);
     85                        _keyMapping->draw();
     86                }
     87                break;
     88        case kMapCmd:
     89                if (_actionsList->getSelected() < 0) {
     90                        _actionTitle->setLabel("Please select an action");
     91                } else {
     92                        char selection[100];
     93
     94                        Common::UserAction action = getSelectedAction();
     95                        uint16 key = getActionKey(action);
     96
     97                        if (key != 0)
     98                                sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey)key));
     99                        else
     100                                sprintf(selection, "Associated key : none");
     101
     102                        _actionTitle->setLabel("Press the key to associate");
     103                        _keyMapping->setLabel(selection);
     104                        _keyMapping->draw();
     105                        _isMappingActive = true;
     106                        _actionsList->setEnabled(false);
     107                }
     108                _actionTitle->draw();
     109                break;
     110        case kOKCmd:
     111                _keyMapper->saveActionMappings();
     112                close();
     113                break;
     114        case kCloseCmd:
     115                _keyMapper->loadActionMappings();
     116                close();
     117                break;
     118        }
     119}
     120
     121uint16 KeyMapperDialog::getActionKey(Common::UserAction action) {
     122        uint16 key;
     123        const Common::KeyState *keyState = _keyMapper->getMappingKey(action);
     124        if (keyState) {
     125                key = keyState->keycode;
     126        } else {
     127                key = action.defaultKey.keycode;
     128        }
     129        return key;
     130}
     131
     132void KeyMapperDialog::handleKeyDown(Common::KeyState state){
     133        if (!_isMappingActive) {
     134                Dialog::handleKeyDown(state);
     135        }
     136}
     137
     138void KeyMapperDialog::handleKeyUp(Common::KeyState state) {
     139        if (_isMappingActive) {
     140                char selection[100];
     141
     142                // map action
     143                if (state.keycode != 0) {
     144                        Common::UserAction action = getSelectedAction();
     145                        _keyMapper->addActionMapping(state, action);
     146                        sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey) state.keycode));
     147                } else
     148                        sprintf(selection, "Associated key : none");
     149
     150                _actionTitle->setLabel("Choose an action to map");
     151                _actionTitle->draw();
     152                _keyMapping->setLabel(selection);
     153                _keyMapping->draw();
     154                _actionsList->setEnabled(true);
     155                _isMappingActive = false;
     156        } else
     157                Dialog::handleKeyUp(state);
     158}
     159
     160Common::UserAction KeyMapperDialog::getSelectedAction() {
     161        Common::ActionList::iterator it = _actions.begin();
     162        for (int i = 0, selected = _actionsList->getSelected(); i < selected; i++) {
     163                it++;
     164        }
     165        return *it;
     166}
     167
     168void KeyMapperDialog::s_showKeyMapperDialog(const Common::String &title, Common::EventManager *em, Common::ActionList al) {
     169        if (em->getKeyMapper()) {
     170                GUI::KeyMapperDialog *dialog = new GUI::KeyMapperDialog(title, em, al);
     171                dialog->runModal();
     172                delete dialog;
     173        }
     174}
     175
     176} // namespace GUI
  • gui/about.cpp

     
    2626#include "engines/engine.h"
    2727#include "base/plugins.h"
    2828#include "base/version.h"
    29 #include "common/events.h"
     29#include "common/event-manager.h"
    3030#include "common/system.h"
    3131#include "common/util.h"
    3232#include "gui/about.h"