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