mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-08 19:32:39 +08:00
526 lines
22 KiB
C++
526 lines
22 KiB
C++
/*
|
|
* Copyright (C) 2002-2021 The DOSBox Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <string>
|
|
#include "config.h"
|
|
#include "menudef.h"
|
|
void SetVal(const std::string& secname, const std::string& preval, const std::string& val);
|
|
|
|
#include <SDL_video.h>
|
|
|
|
#ifdef __WIN32__
|
|
#include "programs.h"
|
|
|
|
void ToggleMenu(bool pressed);
|
|
void mem_conf(std::string memtype, int option);
|
|
void UnMount(int i_drive);
|
|
void BrowseFolder( char drive , std::string drive_type );
|
|
void Mount_Img(char drive, std::string realpath);
|
|
void Mount_Img_Floppy(char drive, std::string realpath);
|
|
void Mount_Img_HDD(char drive, std::string realpath);
|
|
void DOSBox_SetMenu(void);
|
|
void DOSBox_NoMenu(void);
|
|
void DOSBox_RefreshMenu(void);
|
|
void ToggleMenu(bool pressed);
|
|
void DOSBox_CheckOS(int &id, int &major, int &minor);
|
|
void MountDrive(char drive, const char drive2[DOS_PATHLENGTH]);
|
|
void MountDrive_2(char drive, const char drive2[DOS_PATHLENGTH], std::string drive_type);
|
|
void MENU_Check_Drive(HMENU handle, int cdrom, int floppy, int local, int image, int automount, int umount, char drive);
|
|
bool MENU_SetBool(std::string secname, std::string value);
|
|
void MENU_swapstereo(bool enabled);
|
|
void* GetSetSDLValue(int isget, std::string& target, void* setval);
|
|
void GFX_SetTitle(int32_t cycles, int frameskip, Bits timing, bool paused);
|
|
void change_output(int output);
|
|
void res_input(bool type, const char * res);
|
|
void res_init(void);
|
|
int Reflect_Menu(void);
|
|
extern bool DOSBox_Kor(void);
|
|
|
|
extern unsigned int hdd_defsize;
|
|
extern char hdd_size[20];
|
|
extern HWND GetHWND(void);
|
|
extern HWND GetSurfaceHWND(void);
|
|
extern void GetDefaultSize(void);
|
|
#define SCALER(opscaler,opsize) \
|
|
if ((render.scale.op==opscaler) && (render.scale.size==opsize))
|
|
|
|
#define SCALER_SW(opscaler,opsize) \
|
|
if ((render.scale.op==opscaler) && (render.scale.size==opsize) && (!render.scale.hardware))
|
|
|
|
#define SCALER_HW(opscaler,opsize) \
|
|
if ((render.scale.op==opscaler) && (render.scale.size==opsize) && (render.scale.hardware))
|
|
|
|
#define SCALER_2(opscaler,opsize) \
|
|
((render.scale.op==opscaler) && (render.scale.size==opsize))
|
|
|
|
#define SCALER_SW_2(opscaler,opsize) \
|
|
((render.scale.op==opscaler) && (render.scale.size==opsize) && (!render.scale.hardware))
|
|
|
|
#define SCALER_HW_2(opscaler,opsize) \
|
|
((render.scale.op==opscaler) && (render.scale.size==opsize) && (render.scale.hardware))
|
|
|
|
#define AUTOMOUNT(name,name2) \
|
|
(((GetDriveType(name) == 2) || (GetDriveType(name) == 3) || (GetDriveType(name) == 4) || (GetDriveType(name) == 5) || (GetDriveType(name) == 6)))&&(!Drives[name2-'A'])
|
|
|
|
#else
|
|
|
|
void DOSBox_CheckOS(int &id, int &major, int &minor);
|
|
void DOSBox_RefreshMenu(void);
|
|
void DOSBox_SetMenu(void);
|
|
void DOSBox_NoMenu(void);
|
|
|
|
// dummy Win32 functions for less #ifdefs
|
|
#define GetHWND() (0)
|
|
#define SetMenu(a,b)
|
|
#define DragAcceptFiles(a,b)
|
|
#define GetMenu(a) (0)
|
|
|
|
// menu.cpp replacements; the optimizer will completely remove code based on these
|
|
#define VER_PLATFORM_WIN32_NT (1)
|
|
#define DOSBox_Kor() !strncmp("ko", getenv("LANG"), 2) // dirty hack.
|
|
|
|
#endif
|
|
|
|
/* menu interface mode */
|
|
#define DOSBOXMENU_NULL (0) /* nothing */
|
|
#define DOSBOXMENU_HMENU (1) /* Windows HMENU resources */
|
|
#define DOSBOXMENU_NSMENU (2) /* Mac OS X NSMenu / NSMenuItem resources */
|
|
#define DOSBOXMENU_SDLDRAW (3) /* menus that WE draw on the SDL surface */
|
|
|
|
#if C_FORCE_MENU_SDLDRAW /* Programmer/Dev wants to compile with SDL drawn menus even if host OS offers menus (shrug) Ok */
|
|
# define DOSBOXMENU_TYPE DOSBOXMENU_SDLDRAW
|
|
#elif defined(WIN32) && !defined(C_SDL2) && !defined(HX_DOS)
|
|
# define DOSBOXMENU_TYPE DOSBOXMENU_HMENU
|
|
#elif defined(MACOSX)
|
|
# define DOSBOXMENU_TYPE DOSBOXMENU_NSMENU
|
|
#elif defined(C_SDL2) /* SDL 2.x only */
|
|
# define DOSBOXMENU_TYPE DOSBOXMENU_SDLDRAW
|
|
#elif !defined(C_SDL2) /* SDL 1.x only */
|
|
# define DOSBOXMENU_TYPE DOSBOXMENU_SDLDRAW
|
|
#else
|
|
# define DOSBOXMENU_TYPE DOSBOXMENU_NULL
|
|
#endif
|
|
|
|
/* Whether or not the menu exists, and is NOT drawn by ourself (Windows and Mac OS X) */
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU || DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU
|
|
# define DOSBOXMENU_EXTERNALLY_MANAGED
|
|
#endif
|
|
|
|
void GUI_Shortcut(int select);
|
|
|
|
#define DOSBOXMENU_ACCELMARK_STR "\x01"
|
|
#define DOSBOXMENU_ACCELMARK_CHAR '\x01'
|
|
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
#ifndef MENU_DOSBOXMENU_H
|
|
#define MENU_DOSBOXMENU_H
|
|
|
|
class DOSBoxMenu {
|
|
public:
|
|
DOSBoxMenu(const DOSBoxMenu &src) = delete; /* don't copy me */
|
|
DOSBoxMenu(const DOSBoxMenu &&src) = delete; /* don't move me */
|
|
public:
|
|
class item;
|
|
public:
|
|
enum item_type_t {
|
|
item_type_id=0,
|
|
submenu_type_id,
|
|
separator_type_id,
|
|
vseparator_type_id,
|
|
|
|
MAX_id
|
|
};
|
|
public:
|
|
typedef uint16_t item_handle_t;
|
|
typedef bool (*callback_t)(DOSBoxMenu * const,item * const);
|
|
typedef std::string mapper_event_t; /* event name */
|
|
public:
|
|
class displaylist {
|
|
friend DOSBoxMenu;
|
|
|
|
public:
|
|
displaylist();
|
|
~displaylist();
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
|
|
public:
|
|
void DrawDisplayList(DOSBoxMenu &menu,bool updateScreen=true);
|
|
item_handle_t itemFromPoint(DOSBoxMenu &menu,int x,int y);
|
|
#endif
|
|
protected:
|
|
bool items_changed = false;
|
|
bool order_changed = false;
|
|
std::vector<item_handle_t> disp_list;
|
|
public:
|
|
const std::vector<item_handle_t> &get_disp_list(void) const {
|
|
return disp_list;
|
|
}
|
|
};
|
|
public:
|
|
static constexpr item_handle_t unassigned_item_handle = ((item_handle_t)(0xFFFFU));
|
|
static constexpr callback_t unassigned_callback = NULL;
|
|
static const mapper_event_t unassigned_mapper_event; /* empty std::string */
|
|
public:
|
|
struct accelerator {
|
|
accelerator() { }
|
|
accelerator(char _key,unsigned char _instance=0) : key(_key), key_instance(_instance) { }
|
|
|
|
char key = 0; /* ascii code i.e. 'g' */
|
|
unsigned char key_instance = 0; /* which occurrence of the letter in the text */
|
|
};
|
|
public:
|
|
class item {
|
|
friend DOSBoxMenu;
|
|
|
|
public:
|
|
item();
|
|
~item();
|
|
protected:
|
|
std::string name; /* item name */
|
|
std::string text; /* item text */
|
|
std::string shortcut_text; /* shortcut text on the right */
|
|
std::string description; /* description text */
|
|
struct accelerator accelerator; /* menu accelerator */
|
|
protected:
|
|
item_handle_t parent_id = unassigned_item_handle;
|
|
item_handle_t master_id = unassigned_item_handle;
|
|
enum item_type_t type = item_type_id;
|
|
protected:
|
|
struct status {
|
|
status() : changed(false), allocated(false),
|
|
enabled(true), checked(false),
|
|
in_use(false) { };
|
|
|
|
unsigned int changed:1;
|
|
unsigned int allocated:1;
|
|
unsigned int enabled:1;
|
|
unsigned int checked:1;
|
|
unsigned int in_use:1;
|
|
} status = {};
|
|
protected:
|
|
callback_t callback_func = unassigned_callback;
|
|
mapper_event_t mapper_event = unassigned_mapper_event;
|
|
public:
|
|
displaylist display_list;
|
|
public:
|
|
uint64_t user_defined = 0;
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU /* Windows menu handle */
|
|
protected:
|
|
HMENU winMenu = NULL;
|
|
protected:
|
|
void winAppendMenu(HMENU handle);
|
|
std::string winConstructMenuText(void);
|
|
#endif
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU /* Mac OS X menu handle */
|
|
protected:
|
|
void* nsMenuItem = NULL;
|
|
void* nsMenu = NULL;
|
|
protected:
|
|
void nsAppendMenu(void *nsMenu);
|
|
#endif
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
|
|
protected:
|
|
SDL_Rect screenBox = {0,0,0,0}; /* absolute screen coords */
|
|
SDL_Rect checkBox = {0,0,0,0}; /* relative to screenbox */
|
|
SDL_Rect textBox = {0,0,0,0}; /* relative to screenbox */
|
|
SDL_Rect shortBox = {0,0,0,0}; /* relative to screenbox */
|
|
SDL_Rect popupBox = {0,0,0,0}; /* absolute screen coords */
|
|
bool boxInit = false;
|
|
bool itemHover = false;
|
|
bool needRedraw = false;
|
|
bool itemHilight = false;
|
|
bool itemVisible = false;
|
|
bool itemHoverDrawn = false;
|
|
bool itemHilightDrawn = false;
|
|
bool borderTop = false;
|
|
public:
|
|
void removeFocus(DOSBoxMenu &menu);
|
|
void removeHover(DOSBoxMenu &menu);
|
|
void drawMenuItem(DOSBoxMenu &menu);
|
|
void showItem(DOSBoxMenu &menu,bool show=true);
|
|
item& setHover(DOSBoxMenu &menu,bool ho=true);
|
|
item& setHilight(DOSBoxMenu &menu,bool hi=true);
|
|
void placeItem(DOSBoxMenu &menu,int x,int y,bool isTopLevel=false);
|
|
void placeItemFinal(DOSBoxMenu &menu,int finalwidth,bool isTopLevel=false);
|
|
void layoutSubmenu(DOSBoxMenu &menu, bool isTopLevel=false);
|
|
void updateScreenFromPopup(DOSBoxMenu &menu);
|
|
void updateScreenFromItem(DOSBoxMenu &menu);
|
|
void drawBackground(DOSBoxMenu &menu);
|
|
public:
|
|
inline bool isHilight(void) const {
|
|
return itemHilight;
|
|
}
|
|
#endif
|
|
protected:
|
|
item& allocate(const DOSBoxMenu::item_handle_t id, const enum item_type_t new_type, const std::string& new_name);
|
|
void deallocate(void);
|
|
public:
|
|
inline bool checkResetRedraw(void) {
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
|
|
bool r = needRedraw || (itemHilight != itemHilightDrawn) || (itemHover != itemHoverDrawn);
|
|
needRedraw = false;
|
|
return r;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
inline const std::string &get_name(void) const {
|
|
return name;
|
|
}
|
|
inline item_handle_t get_master_id(void) const {
|
|
return master_id;
|
|
}
|
|
inline bool is_allocated(void) const {
|
|
return master_id != unassigned_item_handle;
|
|
}
|
|
inline bool has_vis_text(void) const {
|
|
return type <= submenu_type_id;
|
|
}
|
|
inline bool has_vis_shortcut_text(void) const {
|
|
return type <= item_type_id;
|
|
}
|
|
inline bool has_vis_description(void) const {
|
|
return false;
|
|
}
|
|
inline bool has_vis_accelerator(void) const {
|
|
return type <= item_type_id;
|
|
}
|
|
inline bool has_vis_enabled(void) const {
|
|
return type <= submenu_type_id;
|
|
}
|
|
inline bool can_enable(void) const {
|
|
return type <= submenu_type_id;
|
|
}
|
|
inline bool has_vis_checked(void) const {
|
|
return type <= item_type_id;
|
|
}
|
|
inline bool can_check(void) const {
|
|
return type <= item_type_id;
|
|
}
|
|
public:
|
|
void refresh_item(DOSBoxMenu &menu);
|
|
inline bool has_changed(void) const {
|
|
return status.changed;
|
|
}
|
|
void clear_changed(void) {
|
|
status.changed = false;
|
|
}
|
|
public:
|
|
inline item &check(const bool f=true) {
|
|
if (status.checked != f) {
|
|
status.checked = f;
|
|
if (can_check() && has_vis_checked())
|
|
status.changed = 1;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
inline bool is_checked(void) const {
|
|
return status.checked;
|
|
}
|
|
public:
|
|
inline item &enable(const bool f=true) {
|
|
if (status.enabled != f) {
|
|
status.enabled = f;
|
|
if (can_enable() && has_vis_enabled())
|
|
status.changed = 1;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
inline bool is_enabled(void) const {
|
|
return status.enabled;
|
|
}
|
|
public:
|
|
inline item_type_t get_type(void) const {
|
|
return type;
|
|
}
|
|
void set_type(const item_type_t t) {
|
|
if (type >= separator_type_id && t >= separator_type_id)
|
|
type = t;
|
|
}
|
|
public:
|
|
inline callback_t get_callback_function(void) const {
|
|
return callback_func;
|
|
}
|
|
inline item &set_callback_function(const callback_t f) {
|
|
callback_func = f;
|
|
return *this;
|
|
}
|
|
public:
|
|
inline mapper_event_t get_mapper_event(void) const {
|
|
return mapper_event;
|
|
}
|
|
inline item& set_mapper_event(const mapper_event_t& e) {
|
|
mapper_event = e;
|
|
return *this;
|
|
}
|
|
public:
|
|
inline const std::string &get_text(void) const {
|
|
return text;
|
|
}
|
|
inline item &set_text(const std::string &str) {
|
|
if (has_vis_text() && text != str)
|
|
status.changed = 1;
|
|
|
|
text = str;
|
|
return *this;
|
|
}
|
|
public:
|
|
inline const std::string &get_shortcut_text(void) const {
|
|
return shortcut_text;
|
|
}
|
|
inline item &set_shortcut_text(const std::string &str) {
|
|
if (has_vis_shortcut_text() && shortcut_text != str)
|
|
status.changed = 1;
|
|
|
|
shortcut_text = str;
|
|
return *this;
|
|
}
|
|
public:
|
|
inline const std::string &get_description(void) const {
|
|
return description;
|
|
}
|
|
inline item &set_description(const std::string &str) {
|
|
if (has_vis_description() && description != str)
|
|
status.changed = 1;
|
|
|
|
description = str;
|
|
return *this;
|
|
}
|
|
public:
|
|
inline const struct accelerator &get_accelerator(void) const {
|
|
return accelerator;
|
|
}
|
|
inline item &set_accelerator(const struct accelerator &str) {
|
|
if (has_vis_accelerator()/* && accelerator != str*//*TODO*/)
|
|
status.changed = 1;
|
|
|
|
accelerator = str;
|
|
return *this;
|
|
}
|
|
};
|
|
public:
|
|
DOSBoxMenu();
|
|
~DOSBoxMenu();
|
|
public:
|
|
bool item_exists(const item_handle_t i);
|
|
bool item_exists(const std::string &name);
|
|
std::vector<item> get_master_list(void);
|
|
item& get_item(const item_handle_t i);
|
|
item& get_item(const std::string &name);
|
|
item_handle_t get_item_id_by_name(const std::string &name);
|
|
item& alloc_item(const enum item_type_t type,const std::string &name);
|
|
void delete_item(const item_handle_t i);
|
|
void clear_all_menu_items(void);
|
|
void dump_log_debug(void);
|
|
void dump_log_displaylist(DOSBoxMenu::displaylist &ls, unsigned int indent);
|
|
const char* TypeToString(const enum item_type_t type);
|
|
void rebuild(void);
|
|
void unbuild(void);
|
|
public:
|
|
displaylist display_list;
|
|
protected:
|
|
std::vector<item> master_list;
|
|
std::map<std::string,item_handle_t> name_map;
|
|
item_handle_t master_list_alloc = 0;
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU /* Windows menu handle */
|
|
protected:
|
|
HMENU winMenu = NULL;
|
|
bool winMenuInit(void);
|
|
void winMenuDestroy(void);
|
|
bool winMenuSubInit(DOSBoxMenu::item &item);
|
|
public:
|
|
HMENU getWinMenu(void) const;
|
|
bool mainMenuWM_COMMAND(unsigned int id);
|
|
#endif
|
|
public:
|
|
static constexpr unsigned int winMenuMinimumID = 0x1000;
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU /* Mac OS X NSMenu / NSMenuItem handle */
|
|
protected:
|
|
void* nsMenu = NULL;
|
|
bool nsMenuInit(void);
|
|
void nsMenuDestroy(void);
|
|
bool nsMenuSubInit(DOSBoxMenu::item &item);
|
|
public:
|
|
void* getNsMenu(void) const;
|
|
bool mainMenuAction(unsigned int id);
|
|
public:
|
|
static constexpr unsigned int nsMenuMinimumID = 0x1000;
|
|
#endif
|
|
#if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
|
|
public:
|
|
bool needRedraw = false;
|
|
bool menuVisible = false;
|
|
item_handle_t menuUserAttentionAt = unassigned_item_handle;
|
|
item_handle_t menuUserHoverAt = unassigned_item_handle;
|
|
public:
|
|
SDL_Rect menuBox = {0,0,0,0};
|
|
public:
|
|
inline bool isVisible(void) const {
|
|
return menuVisible;
|
|
}
|
|
inline bool needsRedraw(void) const {
|
|
return needRedraw;
|
|
}
|
|
inline void setRedraw(void) {
|
|
needRedraw = true;
|
|
}
|
|
inline void clearRedraw(void) {
|
|
needRedraw = false;
|
|
}
|
|
public:
|
|
void showMenu(bool show=true);
|
|
void setScale(size_t s);
|
|
void removeHover(void);
|
|
void removeFocus(void);
|
|
void updateRect(void);
|
|
void layoutMenu(void);
|
|
public:
|
|
static constexpr size_t menuBarHeightBase = (16 + 1);
|
|
size_t menuBarHeight = menuBarHeightBase;
|
|
public:
|
|
size_t screenWidth = 640;
|
|
size_t screenHeight = 400;
|
|
public:
|
|
static constexpr size_t fontCharWidthBase = 8;
|
|
static constexpr size_t fontCharHeightBase = 16;
|
|
static constexpr size_t dropshadowX = 8;
|
|
static constexpr size_t dropshadowY = 8;
|
|
public:
|
|
size_t fontCharScale = 1;
|
|
size_t fontCharWidth = fontCharWidthBase;
|
|
size_t fontCharHeight = fontCharHeightBase;
|
|
#endif
|
|
public:
|
|
void dispatchItemCommand(item &item);
|
|
public:
|
|
static constexpr size_t master_list_limit = 4096;
|
|
public:
|
|
void displaylist_append(displaylist &ls,const DOSBoxMenu::item_handle_t item_id);
|
|
void displaylist_clear(displaylist &ls);
|
|
};
|
|
|
|
extern DOSBoxMenu mainMenu;
|
|
|
|
void DOSBox_SetMenu(DOSBoxMenu &altMenu);
|
|
|
|
#endif /* MENU_DOSBOXMENU_H */
|
|
|