DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 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 along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include <string> 00020 #include "config.h" 00021 #include "menudef.h" 00022 void SetVal(const std::string& secname, const 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 DOSBox_CheckOS(int &id, int &major, int &minor); 00041 void MountDrive(char drive, const char drive2[DOS_PATHLENGTH]); 00042 void MountDrive_2(char drive, const char drive2[DOS_PATHLENGTH], std::string drive_type); 00043 void MENU_Check_Drive(HMENU handle, int cdrom, int floppy, int local, int image, int automount, int umount, char drive); 00044 bool MENU_SetBool(std::string secname, std::string value); 00045 void MENU_swapstereo(bool enabled); 00046 void* GetSetSDLValue(int isget, std::string& target, void* setval); 00047 void GFX_SetTitle(Bit32s cycles, Bits frameskip, Bits timing, bool paused); 00048 void change_output(int output); 00049 void res_input(bool type, const char * res); 00050 void res_init(void); 00051 int Reflect_Menu(void); 00052 extern bool DOSBox_Kor(void); 00053 00054 extern unsigned int hdd_defsize; 00055 extern char hdd_size[20]; 00056 extern HWND GetHWND(void); 00057 extern HWND GetSurfaceHWND(void); 00058 extern void GetDefaultSize(void); 00059 #define SCALER(opscaler,opsize) \ 00060 if ((render.scale.op==opscaler) && (render.scale.size==opsize)) 00061 00062 #define SCALER_SW(opscaler,opsize) \ 00063 if ((render.scale.op==opscaler) && (render.scale.size==opsize) && (!render.scale.hardware)) 00064 00065 #define SCALER_HW(opscaler,opsize) \ 00066 if ((render.scale.op==opscaler) && (render.scale.size==opsize) && (render.scale.hardware)) 00067 00068 #define SCALER_2(opscaler,opsize) \ 00069 ((render.scale.op==opscaler) && (render.scale.size==opsize)) 00070 00071 #define SCALER_SW_2(opscaler,opsize) \ 00072 ((render.scale.op==opscaler) && (render.scale.size==opsize) && (!render.scale.hardware)) 00073 00074 #define SCALER_HW_2(opscaler,opsize) \ 00075 ((render.scale.op==opscaler) && (render.scale.size==opsize) && (render.scale.hardware)) 00076 00077 #define AUTOMOUNT(name,name2) \ 00078 (((GetDriveType(name) == 2) || (GetDriveType(name) == 3) || (GetDriveType(name) == 4) || (GetDriveType(name) == 5) || (GetDriveType(name) == 6)))&&(!Drives[name2-'A']) 00079 00080 #else 00081 00082 void DOSBox_CheckOS(int &id, int &major, int &minor); 00083 void DOSBox_RefreshMenu(void); 00084 void DOSBox_SetMenu(void); 00085 void DOSBox_NoMenu(void); 00086 00087 // dummy Win32 functions for less #ifdefs 00088 #define GetHWND() (0) 00089 #define SetMenu(a,b) 00090 #define DragAcceptFiles(a,b) 00091 #define GetMenu(a) (0) 00092 00093 // menu.cpp replacements; the optimizer will completely remove code based on these 00094 #define VER_PLATFORM_WIN32_NT (1) 00095 #define DOSBox_Kor() !strncmp("ko", getenv("LANG"), 2) // dirty hack. 00096 00097 #endif 00098 00099 /* menu interface mode */ 00100 #define DOSBOXMENU_NULL (0) /* nothing */ 00101 #define DOSBOXMENU_HMENU (1) /* Windows HMENU resources */ 00102 #define DOSBOXMENU_NSMENU (2) /* Mac OS X NSMenu / NSMenuItem resources */ 00103 #define DOSBOXMENU_SDLDRAW (3) /* menus that WE draw on the SDL surface */ 00104 00105 #if C_FORCE_MENU_SDLDRAW /* Programmer/Dev wants to compile with SDL drawn menus even if host OS offers menus (shrug) Ok */ 00106 # define DOSBOXMENU_TYPE DOSBOXMENU_SDLDRAW 00107 #elif defined(WIN32) && !defined(C_SDL2) && !defined(HX_DOS) 00108 # define DOSBOXMENU_TYPE DOSBOXMENU_HMENU 00109 #elif defined(MACOSX) 00110 # define DOSBOXMENU_TYPE DOSBOXMENU_NSMENU 00111 #elif defined(C_SDL2) /* SDL 2.x only */ 00112 # define DOSBOXMENU_TYPE DOSBOXMENU_SDLDRAW 00113 #elif !defined(C_SDL2) /* SDL 1.x only */ 00114 # define DOSBOXMENU_TYPE DOSBOXMENU_SDLDRAW 00115 #else 00116 # define DOSBOXMENU_TYPE DOSBOXMENU_NULL 00117 #endif 00118 00119 /* Whether or not the menu exists, and is NOT drawn by ourself (Windows and Mac OS X) */ 00120 #if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU || DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU 00121 # define DOSBOXMENU_EXTERNALLY_MANAGED 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 itemHoverDrawn = false; 00250 bool itemHilightDrawn = false; 00251 bool borderTop = false; 00252 public: 00253 void removeFocus(DOSBoxMenu &menu); 00254 void removeHover(DOSBoxMenu &menu); 00255 void drawMenuItem(DOSBoxMenu &menu); 00256 void showItem(DOSBoxMenu &menu,bool show=true); 00257 item& setHover(DOSBoxMenu &menu,bool ho=true); 00258 item& setHilight(DOSBoxMenu &menu,bool hi=true); 00259 void placeItem(DOSBoxMenu &menu,int x,int y,bool isTopLevel=false); 00260 void placeItemFinal(DOSBoxMenu &menu,int finalwidth,bool isTopLevel=false); 00261 void layoutSubmenu(DOSBoxMenu &menu, bool isTopLevel=false); 00262 void updateScreenFromPopup(DOSBoxMenu &menu); 00263 void updateScreenFromItem(DOSBoxMenu &menu); 00264 void drawBackground(DOSBoxMenu &menu); 00265 public: 00266 inline bool isHilight(void) const { 00267 return itemHilight; 00268 } 00269 #endif 00270 protected: 00271 item& allocate(const DOSBoxMenu::item_handle_t id, const enum item_type_t new_type, const std::string& new_name); 00272 void deallocate(void); 00273 public: 00274 inline bool checkResetRedraw(void) { 00275 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00276 bool r = needRedraw || (itemHilight != itemHilightDrawn) || (itemHover != itemHoverDrawn); 00277 needRedraw = false; 00278 return r; 00279 #else 00280 return false; 00281 #endif 00282 } 00283 inline const std::string &get_name(void) const { 00284 return name; 00285 } 00286 inline item_handle_t get_master_id(void) const { 00287 return master_id; 00288 } 00289 inline bool is_allocated(void) const { 00290 return master_id != unassigned_item_handle; 00291 } 00292 inline bool has_vis_text(void) const { 00293 return type <= submenu_type_id; 00294 } 00295 inline bool has_vis_shortcut_text(void) const { 00296 return type <= item_type_id; 00297 } 00298 inline bool has_vis_description(void) const { 00299 return false; 00300 } 00301 inline bool has_vis_accelerator(void) const { 00302 return type <= item_type_id; 00303 } 00304 inline bool has_vis_enabled(void) const { 00305 return type <= submenu_type_id; 00306 } 00307 inline bool can_enable(void) const { 00308 return type <= submenu_type_id; 00309 } 00310 inline bool has_vis_checked(void) const { 00311 return type <= item_type_id; 00312 } 00313 inline bool can_check(void) const { 00314 return type <= item_type_id; 00315 } 00316 public: 00317 void refresh_item(DOSBoxMenu &menu); 00318 inline bool has_changed(void) const { 00319 return status.changed; 00320 } 00321 void clear_changed(void) { 00322 status.changed = false; 00323 } 00324 public: 00325 inline item &check(const bool f=true) { 00326 if (status.checked != f) { 00327 status.checked = f; 00328 if (can_check() && has_vis_checked()) 00329 status.changed = 1; 00330 } 00331 00332 return *this; 00333 } 00334 inline bool is_checked(void) const { 00335 return status.checked; 00336 } 00337 public: 00338 inline item &enable(const bool f=true) { 00339 if (status.enabled != f) { 00340 status.enabled = f; 00341 if (can_enable() && has_vis_enabled()) 00342 status.changed = 1; 00343 } 00344 00345 return *this; 00346 } 00347 inline bool is_enabled(void) const { 00348 return status.enabled; 00349 } 00350 public: 00351 inline item_type_t get_type(void) const { 00352 return type; 00353 } 00354 void set_type(const item_type_t t) { 00355 if (type >= separator_type_id && t >= separator_type_id) 00356 type = t; 00357 } 00358 public: 00359 inline callback_t get_callback_function(void) const { 00360 return callback_func; 00361 } 00362 inline item &set_callback_function(const callback_t f) { 00363 callback_func = f; 00364 return *this; 00365 } 00366 public: 00367 inline mapper_event_t get_mapper_event(void) const { 00368 return mapper_event; 00369 } 00370 inline item& set_mapper_event(const mapper_event_t& e) { 00371 mapper_event = e; 00372 return *this; 00373 } 00374 public: 00375 inline const std::string &get_text(void) const { 00376 return text; 00377 } 00378 inline item &set_text(const std::string &str) { 00379 if (has_vis_text() && text != str) 00380 status.changed = 1; 00381 00382 text = str; 00383 return *this; 00384 } 00385 public: 00386 inline const std::string &get_shortcut_text(void) const { 00387 return shortcut_text; 00388 } 00389 inline item &set_shortcut_text(const std::string &str) { 00390 if (has_vis_shortcut_text() && shortcut_text != str) 00391 status.changed = 1; 00392 00393 shortcut_text = str; 00394 return *this; 00395 } 00396 public: 00397 inline const std::string &get_description(void) const { 00398 return description; 00399 } 00400 inline item &set_description(const std::string &str) { 00401 if (has_vis_description() && description != str) 00402 status.changed = 1; 00403 00404 description = str; 00405 return *this; 00406 } 00407 public: 00408 inline const struct accelerator &get_accelerator(void) const { 00409 return accelerator; 00410 } 00411 inline item &set_accelerator(const struct accelerator &str) { 00412 if (has_vis_accelerator()/* && accelerator != str*//*TODO*/) 00413 status.changed = 1; 00414 00415 accelerator = str; 00416 return *this; 00417 } 00418 }; 00419 public: 00420 DOSBoxMenu(); 00421 ~DOSBoxMenu(); 00422 public: 00423 bool item_exists(const item_handle_t i); 00424 bool item_exists(const std::string &name); 00425 item& get_item(const item_handle_t i); 00426 item& get_item(const std::string &name); 00427 item_handle_t get_item_id_by_name(const std::string &name); 00428 item& alloc_item(const enum item_type_t type,const std::string &name); 00429 void delete_item(const item_handle_t i); 00430 void clear_all_menu_items(void); 00431 void dump_log_debug(void); 00432 void dump_log_displaylist(DOSBoxMenu::displaylist &ls, unsigned int indent); 00433 const char* TypeToString(const enum item_type_t type); 00434 void rebuild(void); 00435 void unbuild(void); 00436 public: 00437 displaylist display_list; 00438 protected: 00439 std::vector<item> master_list; 00440 std::map<std::string,item_handle_t> name_map; 00441 item_handle_t master_list_alloc = 0; 00442 #if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU /* Windows menu handle */ 00443 protected: 00444 HMENU winMenu = NULL; 00445 bool winMenuInit(void); 00446 void winMenuDestroy(void); 00447 bool winMenuSubInit(DOSBoxMenu::item &item); 00448 public: 00449 HMENU getWinMenu(void) const; 00450 bool mainMenuWM_COMMAND(unsigned int id); 00451 public: 00452 static constexpr unsigned int winMenuMinimumID = 0x1000; 00453 #endif 00454 #if DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU /* Mac OS X NSMenu / NSMenuItem handle */ 00455 protected: 00456 void* nsMenu = NULL; 00457 bool nsMenuInit(void); 00458 void nsMenuDestroy(void); 00459 bool nsMenuSubInit(DOSBoxMenu::item &item); 00460 public: 00461 void* getNsMenu(void) const; 00462 bool mainMenuAction(unsigned int id); 00463 public: 00464 static constexpr unsigned int nsMenuMinimumID = 0x1000; 00465 #endif 00466 #if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW 00467 public: 00468 bool needRedraw = false; 00469 bool menuVisible = false; 00470 item_handle_t menuUserAttentionAt = unassigned_item_handle; 00471 item_handle_t menuUserHoverAt = unassigned_item_handle; 00472 public: 00473 SDL_Rect menuBox = {0,0,0,0}; 00474 public: 00475 inline bool isVisible(void) const { 00476 return menuVisible; 00477 } 00478 inline bool needsRedraw(void) const { 00479 return needRedraw; 00480 } 00481 inline void setRedraw(void) { 00482 needRedraw = true; 00483 } 00484 inline void clearRedraw(void) { 00485 needRedraw = false; 00486 } 00487 public: 00488 void showMenu(bool show=true); 00489 void setScale(size_t s); 00490 void removeHover(void); 00491 void removeFocus(void); 00492 void updateRect(void); 00493 void layoutMenu(void); 00494 public: 00495 static constexpr size_t menuBarHeightBase = (16 + 1); 00496 size_t menuBarHeight = menuBarHeightBase; 00497 public: 00498 size_t screenWidth = 640; 00499 size_t screenHeight = 400; 00500 public: 00501 static constexpr size_t fontCharWidthBase = 8; 00502 static constexpr size_t fontCharHeightBase = 16; 00503 static constexpr size_t dropshadowX = 8; 00504 static constexpr size_t dropshadowY = 8; 00505 public: 00506 size_t fontCharScale = 1; 00507 size_t fontCharWidth = fontCharWidthBase; 00508 size_t fontCharHeight = fontCharHeightBase; 00509 #endif 00510 public: 00511 void dispatchItemCommand(item &item); 00512 public: 00513 static constexpr size_t master_list_limit = 4096; 00514 public: 00515 void displaylist_append(displaylist &ls,const DOSBoxMenu::item_handle_t item_id); 00516 void displaylist_clear(displaylist &ls); 00517 }; 00518 00519 extern DOSBoxMenu mainMenu; 00520 00521 void DOSBox_SetMenu(DOSBoxMenu &altMenu); 00522 00523 #endif /* MENU_DOSBOXMENU_H */ 00524