DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
include/menu.h
00001 /*
00002  *  Copyright (C) 2002-2013  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include <string>
00020 #include "config.h"
00021 #include "menudef.h"
00022 void SetVal(const std::string secname, std::string preval, const std::string val);
00023 
00024 #include <SDL_video.h>
00025 
00026 #ifdef __WIN32__
00027 #include "programs.h"
00028 
00029 void ToggleMenu(bool pressed);
00030 void mem_conf(std::string memtype, int option);
00031 void UnMount(int i_drive);
00032 void BrowseFolder( char drive , std::string drive_type );
00033 void Mount_Img(char drive, std::string realpath);
00034 void Mount_Img_Floppy(char drive, std::string realpath);
00035 void Mount_Img_HDD(char drive, std::string realpath);
00036 void DOSBox_SetMenu(void);
00037 void DOSBox_NoMenu(void);
00038 void DOSBox_RefreshMenu(void);
00039 void ToggleMenu(bool pressed);
00040 void D3D_PS(void);
00041 void DOSBox_CheckOS(int &id, int &major, int &minor);
00042 void MountDrive(char drive, const char drive2[DOS_PATHLENGTH]);
00043 void MountDrive_2(char drive, const char drive2[DOS_PATHLENGTH], std::string drive_type);
00044 void MENU_Check_Drive(HMENU handle, int cdrom, int floppy, int local, int image, int automount, int umount, char drive);
00045 bool MENU_SetBool(std::string secname, std::string value);
00046 void MENU_swapstereo(bool enabled);
00047 void* GetSetSDLValue(int isget, std::string target, void* setval);
00048 void Go_Boot(const char boot_drive[_MAX_DRIVE]);
00049 void Go_Boot2(const char boot_drive[_MAX_DRIVE]);
00050 void OpenFileDialog(char * path_arg);
00051 void OpenFileDialog_Img(char drive);
00052 void GFX_SetTitle(Bit32s cycles, Bits frameskip, Bits timing, bool paused);
00053 void change_output(int output);
00054 void res_input(bool type, const char * res);
00055 void res_init(void);
00056 int Reflect_Menu(void);
00057 extern bool DOSBox_Kor(void);
00058 
00059 extern unsigned int hdd_defsize;
00060 extern char hdd_size[20];
00061 extern HWND GetHWND(void);
00062 extern void GetDefaultSize(void);
00063 #define SCALER(opscaler,opsize) \
00064         if ((render.scale.op==opscaler) && (render.scale.size==opsize))
00065 
00066 #define SCALER_SW(opscaler,opsize) \
00067         if ((render.scale.op==opscaler) && (render.scale.size==opsize) && (!render.scale.hardware))
00068 
00069 #define SCALER_HW(opscaler,opsize) \
00070         if ((render.scale.op==opscaler) && (render.scale.size==opsize) && (render.scale.hardware))
00071 
00072 #define SCALER_2(opscaler,opsize) \
00073         ((render.scale.op==opscaler) && (render.scale.size==opsize))
00074 
00075 #define SCALER_SW_2(opscaler,opsize) \
00076         ((render.scale.op==opscaler) && (render.scale.size==opsize) && (!render.scale.hardware))
00077 
00078 #define SCALER_HW_2(opscaler,opsize) \
00079         ((render.scale.op==opscaler) && (render.scale.size==opsize) && (render.scale.hardware))
00080 
00081 #define AUTOMOUNT(name,name2) \
00082         (((GetDriveType(name) == 2) || (GetDriveType(name) == 3) || (GetDriveType(name) == 4) || (GetDriveType(name) == 5) || (GetDriveType(name) == 6)))&&(!Drives[name2-'A'])
00083 
00084 #else
00085 
00086 void DOSBox_CheckOS(int &id, int &major, int &minor);
00087 void DOSBox_RefreshMenu(void);
00088 void DOSBox_SetMenu(void);
00089 void DOSBox_NoMenu(void);
00090 
00091 // dummy Win32 functions for less #ifdefs
00092 #define GetHWND() (0)
00093 #define SetMenu(a,b)
00094 #define DragAcceptFiles(a,b)
00095 #define GetMenu(a) (0)
00096 
00097 // menu.cpp replacements; the optimizer will completely remove code based on these
00098 #define VER_PLATFORM_WIN32_NT (1)
00099 #define DOSBox_Kor() !strncmp("ko", getenv("LANG"), 2) // dirty hack.
00100 
00101 #endif
00102 
00103 /* menu interface mode */
00104 #define DOSBOXMENU_NULL     (0)     /* nothing */
00105 #define DOSBOXMENU_HMENU    (1)     /* Windows HMENU resources */
00106 #define DOSBOXMENU_NSMENU   (2)     /* Mac OS X NSMenu / NSMenuItem resources */
00107 #define DOSBOXMENU_SDLDRAW  (3)     /* menus that WE draw on the SDL surface */
00108 
00109 #if C_FORCE_MENU_SDLDRAW /* Programmer/Dev wants to compile with SDL drawn menus even if host OS offers menus (shrug) Ok */
00110 # define DOSBOXMENU_TYPE    DOSBOXMENU_SDLDRAW
00111 #elif defined(WIN32) && !defined(C_SDL2) && !defined(HX_DOS)
00112 # define DOSBOXMENU_TYPE    DOSBOXMENU_HMENU
00113 #elif defined(MACOSX) && !defined(C_SDL2)
00114 # define DOSBOXMENU_TYPE    DOSBOXMENU_NSMENU
00115 #elif defined(C_SDL2) /* SDL 2.x only */
00116 # define DOSBOXMENU_TYPE    DOSBOXMENU_SDLDRAW
00117 #elif !defined(C_SDL2) /* SDL 1.x only */
00118 # define DOSBOXMENU_TYPE    DOSBOXMENU_SDLDRAW
00119 #else
00120 # define DOSBOXMENU_TYPE    DOSBOXMENU_NULL
00121 #endif
00122 
00123 void GUI_Shortcut(int select);
00124 
00125 #define DOSBOXMENU_ACCELMARK_STR        "\x01"
00126 #define DOSBOXMENU_ACCELMARK_CHAR       '\x01'
00127 
00128 #include <map>
00129 #include <vector>
00130 
00131 #ifndef MENU_DOSBOXMENU_H
00132 #define MENU_DOSBOXMENU_H
00133 
00134 class DOSBoxMenu {
00135     public:
00136         DOSBoxMenu(const DOSBoxMenu &src) = delete;             /* don't copy me */
00137         DOSBoxMenu(const DOSBoxMenu &&src) = delete;            /* don't move me */
00138     public:
00139         class item;
00140     public:
00141         enum item_type_t {
00142             item_type_id=0,
00143             submenu_type_id,
00144             separator_type_id,
00145             vseparator_type_id,
00146 
00147             MAX_id
00148         };
00149     public:
00150         typedef uint16_t                item_handle_t;
00151         typedef bool                  (*callback_t)(DOSBoxMenu * const,item * const);
00152         typedef std::string             mapper_event_t;     /* event name */
00153     public:
00154         class displaylist {
00155             friend DOSBoxMenu;
00156 
00157             public:
00158                                         displaylist();
00159                                         ~displaylist();
00160 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
00161             public:
00162                 void                    DrawDisplayList(DOSBoxMenu &menu,bool updateScreen=true);
00163                 item_handle_t           itemFromPoint(DOSBoxMenu &menu,int x,int y);
00164 #endif
00165             protected:
00166                 bool                    items_changed = false;
00167                 bool                    order_changed = false;
00168                 std::vector<item_handle_t> disp_list;
00169             public:
00170                 const std::vector<item_handle_t> &get_disp_list(void) const {
00171                     return disp_list;
00172                 }
00173         };
00174     public:
00175         static constexpr item_handle_t  unassigned_item_handle = ((item_handle_t)(0xFFFFU)); 
00176         static constexpr callback_t     unassigned_callback = NULL;
00177         static const mapper_event_t     unassigned_mapper_event; /* empty std::string */
00178     public:
00179         struct accelerator {
00180                                         accelerator() { }
00181                                         accelerator(char _key,unsigned char _instance=0) : key(_key), key_instance(_instance) { }
00182 
00183             char                        key = 0;            /* ascii code i.e. 'g' */
00184             unsigned char               key_instance = 0;   /* which occurrence of the letter in the text */
00185         };
00186     public:
00187         class item {
00188             friend DOSBoxMenu;
00189 
00190             public:
00191                                         item();
00192                                         ~item();
00193             protected:
00194                 std::string             name;               /* item name */
00195                 std::string             text;               /* item text */
00196                 std::string             shortcut_text;      /* shortcut text on the right */
00197                 std::string             description;        /* description text */
00198                 struct accelerator      accelerator;        /* menu accelerator */
00199             protected:
00200                 item_handle_t           parent_id = unassigned_item_handle;
00201                 item_handle_t           master_id = unassigned_item_handle;
00202                 enum item_type_t        type = item_type_id;
00203             protected:
00204                 struct status {
00205                                         status() : changed(false), allocated(false),
00206                                                    enabled(true), checked(false),
00207                                                    in_use(false) { };
00208 
00209                     unsigned int        changed:1;
00210                     unsigned int        allocated:1;
00211                     unsigned int        enabled:1;
00212                     unsigned int        checked:1;
00213                     unsigned int        in_use:1;
00214                 } status;
00215             protected:
00216                 callback_t              callback_func = unassigned_callback;
00217                 mapper_event_t          mapper_event = unassigned_mapper_event;
00218             public:
00219                 displaylist             display_list;
00220             public:
00221                 uint64_t                user_defined = 0;
00222 #if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU /* Windows menu handle */
00223             protected:
00224                 HMENU                   winMenu = NULL;
00225             protected:
00226                 void                    winAppendMenu(HMENU handle);
00227                 std::string             winConstructMenuText(void);
00228 #endif
00229 #if DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU /* Mac OS X menu handle */
00230             protected:
00231                 void*                   nsMenuItem = NULL;
00232                 void*                   nsMenu = NULL;
00233             protected:
00234                 void                    nsAppendMenu(void *nsMenu);
00235 #endif
00236 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
00237             protected:
00238                 SDL_Rect                screenBox = {0,0,0,0};      /* absolute screen coords */
00239                 SDL_Rect                checkBox = {0,0,0,0};       /* relative to screenbox */
00240                 SDL_Rect                textBox = {0,0,0,0};        /* relative to screenbox */
00241                 SDL_Rect                shortBox = {0,0,0,0};       /* relative to screenbox */
00242                 SDL_Rect                popupBox = {0,0,0,0};       /* absolute screen coords */
00243                 bool                    boxInit = false;
00244                 bool                    itemHover = false;
00245                 bool                    needRedraw = false;
00246                 bool                    itemHilight = false;
00247                 bool                    itemVisible = false;
00248                 bool                    borderTop = false;
00249             public:
00250                 void                    removeFocus(DOSBoxMenu &menu);
00251                 void                    removeHover(DOSBoxMenu &menu);
00252                 void                    drawMenuItem(DOSBoxMenu &menu);
00253                 void                    showItem(DOSBoxMenu &menu,bool show=true);
00254                 item&                   setHover(DOSBoxMenu &menu,bool ho=true);
00255                 item&                   setHilight(DOSBoxMenu &menu,bool hi=true);
00256                 void                    placeItem(DOSBoxMenu &menu,int x,int y,bool isTopLevel=false);
00257                 void                    placeItemFinal(DOSBoxMenu &menu,int finalwidth,bool isTopLevel=false);
00258                 void                    layoutSubmenu(DOSBoxMenu &menu, bool isTopLevel=false);
00259                 void                    updateScreenFromPopup(DOSBoxMenu &menu);
00260                 void                    updateScreenFromItem(DOSBoxMenu &menu);
00261                 void                    drawBackground(DOSBoxMenu &menu);
00262             public:
00263                 inline bool isHilight(void) const {
00264                     return itemHilight;
00265                 }
00266 #endif
00267             protected:
00268                 item&                   allocate(const item_handle_t id,const enum item_type_t type,const std::string &name);
00269                 void                    deallocate(void);
00270             public:
00271                 inline bool checkResetRedraw(void) {
00272 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
00273                                         bool r = needRedraw;
00274                     needRedraw = false;
00275                     return r;
00276 #else
00277                                         return false;
00278 #endif
00279                 }
00280                 inline const std::string &get_name(void) const {
00281                     return name;
00282                 }
00283                 inline item_handle_t get_master_id(void) const {
00284                     return master_id;
00285                 }
00286                 inline bool is_allocated(void) const {
00287                     return master_id != unassigned_item_handle;
00288                 }
00289                 inline bool has_vis_text(void) const {
00290                     return type <= submenu_type_id;
00291                 }
00292                 inline bool has_vis_shortcut_text(void) const {
00293                     return type <= item_type_id;
00294                 }
00295                 inline bool has_vis_description(void) const {
00296                     return false;
00297                 }
00298                 inline bool has_vis_accelerator(void) const {
00299                     return type <= item_type_id;
00300                 }
00301                 inline bool has_vis_enabled(void) const {
00302                     return type <= submenu_type_id;
00303                 }
00304                 inline bool can_enable(void) const {
00305                     return type <= submenu_type_id;
00306                 }
00307                 inline bool has_vis_checked(void) const {
00308                     return type <= item_type_id;
00309                 }
00310                 inline bool can_check(void) const {
00311                     return type <= item_type_id;
00312                 }
00313             public:
00314                 void refresh_item(DOSBoxMenu &menu);
00315                 inline bool has_changed(void) const {
00316                     return status.changed;
00317                 }
00318                 void clear_changed(void) {
00319                     status.changed = false;
00320                 }
00321             public:
00322                 inline item &check(const bool f=true) {
00323                     if (status.checked != f) {
00324                         status.checked  = f;
00325                         if (can_check() && has_vis_checked())
00326                             status.changed = 1;
00327                     }
00328 
00329                     return *this;
00330                 }
00331                 inline bool is_checked(void) const {
00332                     return status.checked;
00333                 }
00334             public:
00335                 inline item &enable(const bool f=true) {
00336                     if (status.enabled != f) {
00337                         status.enabled  = f;
00338                         if (can_enable() && has_vis_enabled())
00339                             status.changed = 1;
00340                     }
00341 
00342                     return *this;
00343                 }
00344                 inline bool is_enabled(void) const {
00345                     return status.enabled;
00346                 }
00347             public:
00348                 inline item_type_t get_type(void) const {
00349                     return type;
00350                 }
00351                 void set_type(const item_type_t t) {
00352                     if (type >= separator_type_id && t >= separator_type_id)
00353                         type = t;
00354                 }
00355             public:
00356                 inline callback_t get_callback_function(void) const {
00357                     return callback_func;
00358                 }
00359                 inline item &set_callback_function(const callback_t f) {
00360                     callback_func = f;
00361                     return *this;
00362                 }
00363             public:
00364                 inline mapper_event_t get_mapper_event(void) const {
00365                     return mapper_event;
00366                 }
00367                 inline item &set_mapper_event(const mapper_event_t e) {
00368                     mapper_event = e;
00369                     return *this;
00370                 }
00371             public:
00372                 inline const std::string &get_text(void) const {
00373                     return text;
00374                 }
00375                 inline item &set_text(const std::string &str) {
00376                     if (has_vis_text() && text != str)
00377                         status.changed = 1;
00378 
00379                     text = str;
00380                     return *this;
00381                 }
00382             public:
00383                 inline const std::string &get_shortcut_text(void) const {
00384                     return shortcut_text;
00385                 }
00386                 inline item &set_shortcut_text(const std::string &str) {
00387                     if (has_vis_shortcut_text() && shortcut_text != str)
00388                         status.changed = 1;
00389 
00390                     shortcut_text = str;
00391                     return *this;
00392                 }
00393             public:
00394                 inline const std::string &get_description(void) const {
00395                     return description;
00396                 }
00397                 inline item &set_description(const std::string &str) {
00398                     if (has_vis_description() && description != str)
00399                         status.changed = 1;
00400 
00401                     description = str;
00402                     return *this;
00403                 }
00404             public:
00405                 inline const struct accelerator &get_accelerator(void) const {
00406                     return accelerator;
00407                 }
00408                 inline item &set_accelerator(const struct accelerator &str) {
00409                     if (has_vis_accelerator()/* && accelerator != str*//*TODO*/)
00410                         status.changed = 1;
00411 
00412                     accelerator = str;
00413                     return *this;
00414                 }
00415         };
00416     public:
00417                                         DOSBoxMenu();
00418                                         ~DOSBoxMenu();
00419     public:
00420         bool                            item_exists(const item_handle_t i);
00421         bool                            item_exists(const std::string &name);
00422         item&                           get_item(const item_handle_t i);
00423         item&                           get_item(const std::string &name);
00424         item_handle_t                   get_item_id_by_name(const std::string &name);
00425         item&                           alloc_item(const enum item_type_t type,const std::string &name);
00426         void                            delete_item(const item_handle_t i);
00427         void                            clear_all_menu_items(void);
00428         void                            dump_log_debug(void);
00429         void                            dump_log_displaylist(DOSBoxMenu::displaylist &ls, unsigned int indent);
00430         const char*                     TypeToString(const enum item_type_t type);
00431         void                            rebuild(void);
00432         void                            unbuild(void);
00433     public:
00434         displaylist                     display_list;
00435     protected:
00436         std::vector<item>               master_list;
00437         std::map<std::string,item_handle_t> name_map;
00438         item_handle_t                   master_list_alloc = 0;
00439 #if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU /* Windows menu handle */
00440     protected:
00441         HMENU                           winMenu = NULL;
00442         bool                            winMenuInit(void);
00443         void                            winMenuDestroy(void);
00444         bool                            winMenuSubInit(DOSBoxMenu::item &item);
00445     public:
00446         HMENU                           getWinMenu(void) const;
00447         bool                            mainMenuWM_COMMAND(unsigned int id);
00448     public:
00449         static constexpr unsigned int   winMenuMinimumID = 0x1000;
00450 #endif
00451 #if DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU /* Mac OS X NSMenu / NSMenuItem handle */
00452     protected:
00453         void*                           nsMenu = NULL;
00454         bool                            nsMenuInit(void);
00455         void                            nsMenuDestroy(void);
00456         bool                            nsMenuSubInit(DOSBoxMenu::item &item);
00457     public:
00458         void*                           getNsMenu(void) const;
00459         bool                            mainMenuAction(unsigned int id);
00460     public:
00461         static constexpr unsigned int   nsMenuMinimumID = 0x1000;
00462 #endif
00463 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
00464     public:
00465         bool                            needRedraw = false;
00466         bool                            menuVisible = false;
00467         item_handle_t                   menuUserAttentionAt = unassigned_item_handle;
00468         item_handle_t                   menuUserHoverAt = unassigned_item_handle;
00469     public:
00470         SDL_Rect                        menuBox = {0,0,0,0};
00471     public:
00472         inline bool isVisible(void) const {
00473             return menuVisible;
00474         }
00475         inline bool needsRedraw(void) const {
00476             return needRedraw;
00477         }
00478         inline void setRedraw(void) {
00479             needRedraw = true;
00480         }
00481         inline void clearRedraw(void) {
00482             needRedraw = false;
00483         }
00484     public:
00485         void                            showMenu(bool show=true);
00486         void                            setScale(size_t s);
00487         void                            removeHover(void);
00488         void                            removeFocus(void);
00489         void                            updateRect(void);
00490         void                            layoutMenu(void);
00491     public:
00492         static constexpr size_t         menuBarHeightBase = (16 + 1);
00493         size_t                          menuBarHeight = menuBarHeightBase;
00494     public:
00495         size_t                          screenWidth = 320;
00496     public:
00497         static constexpr size_t         fontCharWidthBase = 8;
00498         static constexpr size_t         fontCharHeightBase = 16;
00499         static constexpr size_t         dropshadowX = 8;
00500         static constexpr size_t         dropshadowY = 8;
00501     public:
00502         size_t                          fontCharScale = 1;
00503         size_t                          fontCharWidth = fontCharWidthBase;
00504         size_t                          fontCharHeight = fontCharHeightBase;
00505 #endif
00506     public:
00507         void                            dispatchItemCommand(item &item);
00508     public:
00509         static constexpr size_t         master_list_limit = 4096;
00510     public:
00511         void                            displaylist_append(displaylist &ls,const DOSBoxMenu::item_handle_t item_id);
00512         void                            displaylist_clear(displaylist &ls);
00513 };
00514 
00515 extern DOSBoxMenu mainMenu;
00516 
00517 #endif /* MENU_DOSBOXMENU_H */
00518