diff options
Diffstat (limited to 'trunk/src/emu/uiswlist.c')
-rw-r--r-- | trunk/src/emu/uiswlist.c | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/trunk/src/emu/uiswlist.c b/trunk/src/emu/uiswlist.c new file mode 100644 index 00000000000..ecb41b480f2 --- /dev/null +++ b/trunk/src/emu/uiswlist.c @@ -0,0 +1,399 @@ +/********************************************************************* + + uiswlist.c + + Internal MAME user interface for software list. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + + *********************************************************************/ + +#include "emu.h" +#include "ui.h" +#include "uiswlist.h" + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* time (in seconds) to display errors */ +#define ERROR_MESSAGE_TIME 5 + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +ui_menu_software_parts::ui_menu_software_parts(running_machine &machine, render_container *container, const software_info *_info, const char *_interface, const software_part **part, bool _opt_fmgr, int *_result) : ui_menu(machine, container) +{ + info = _info; + interface = _interface; + selected_part = part; + opt_fmgr = _opt_fmgr; + result = _result; +} + +void ui_menu_software_parts::populate() +{ + for (const software_part *swpart = software_find_part(info, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) + { + if (softlist_contain_interface(interface, swpart->interface_)) + { + software_part_menu_entry *entry = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry)); + // check if the available parts have specific part_id to be displayed (e.g. "Map Disc", "Bonus Disc", etc.) + // if not, we simply display "part_name"; if yes we display "part_name (part_id)" + astring menu_part_name(swpart->name); + if (software_part_get_feature(swpart, "part_id") != NULL) + { + menu_part_name.cat(" ("); + menu_part_name.cat(software_part_get_feature(swpart, "part_id")); + menu_part_name.cat(")"); + } + entry->type = T_ENTRY; + entry->part = swpart; + item_append(info->shortname, menu_part_name.cstr(), 0, entry); + } + } + if(opt_fmgr) { + software_part_menu_entry *entry = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry)); + entry->type = T_FMGR; + entry->part = 0; + item_append("[file manager]", 0, 0, entry); + } +} + +ui_menu_software_parts::~ui_menu_software_parts() +{ +} + +void ui_menu_software_parts::handle() +{ + /* process the menu */ + const ui_menu_event *event = process(0); + + if (event != NULL && event->iptkey == IPT_UI_SELECT && event->itemref != NULL) + { + software_part_menu_entry *entry = (software_part_menu_entry *) event->itemref; + *result = entry->type; + *selected_part = entry->part; + ui_menu::stack_pop(machine()); + } +} + +int ui_menu_software_list::compare_entries(const entry_info *e1, const entry_info *e2, bool shortname) +{ + int result; + const char *e1_basename; + const char *e2_basename; + + if (shortname) + { + e1_basename = (e1->short_name != NULL) ? e1->short_name : ""; + e2_basename = (e2->short_name != NULL) ? e2->short_name : ""; + } + else + { + e1_basename = (e1->long_name != NULL) ? e1->long_name : ""; + e2_basename = (e2->long_name != NULL) ? e2->long_name : ""; + } + + result = mame_stricmp(e1_basename, e2_basename); + if (result == 0) + { + result = strcmp(e1_basename, e2_basename); + if (result == 0) + { + if (e1 < e2) + result = -1; + else if (e1 > e2) + result = 1; + } + } + + return result; +} + +/* populate a specific list */ + +ui_menu_software_list::entry_info *ui_menu_software_list::append_software_entry(const software_info *swinfo) +{ + entry_info *entry = NULL; + entry_info **entryptr; + bool entry_updated = FALSE; + + // check if at least one of the parts has the correct interface and add a menu entry only in this case + for (const software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) + { + if ((softlist_contain_interface(interface, swpart->interface_)) && is_software_compatible(swpart, swlist)) + { + entry_updated = TRUE; + // allocate a new entry + entry = (entry_info *) m_pool_alloc(sizeof(*entry)); + memset(entry, 0, sizeof(*entry)); + + entry->short_name = pool_strdup(swinfo->shortname); + entry->long_name = pool_strdup(swinfo->longname); + break; + } + } + + // skip this if no new entry has been allocated (e.g. if the software has no matching interface for this image device) + if (entry_updated) + { + // find the end of the list + entryptr = &entrylist; + while ((*entryptr != NULL) && (compare_entries(entry, *entryptr, ordered_by_shortname) >= 0)) + entryptr = &(*entryptr)->next; + + // insert the entry + entry->next = *entryptr; + *entryptr = entry; + } + + return entry; +} + +ui_menu_software_list::ui_menu_software_list(running_machine &machine, render_container *container, const software_list_device *_swlist, const char *_interface, astring &_result) : ui_menu(machine, container), result(_result) +{ + swlist = _swlist; + interface = _interface; + entrylist = NULL; + ordered_by_shortname = true; +} + +ui_menu_software_list::~ui_menu_software_list() +{ +} + +void ui_menu_software_list::populate() +{ + const software_list *list = software_list_open(machine().options(), swlist->list_name(), false, NULL); + + // build up the list of entries for the menu + if (list) + { + for (const software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) + append_software_entry(swinfo); + + software_list_close(list); + } + + // add an entry to change ordering + item_append("Switch Item Ordering", NULL, 0, (void *)1); + + // append all of the menu entries + for (entry_info *entry = entrylist; entry != NULL; entry = entry->next) + item_append(entry->short_name, entry->long_name, 0, entry); +} + +void ui_menu_software_list::handle() +{ + const entry_info *entry; + const entry_info *selected_entry = NULL; + int bestmatch = 0; + + /* process the menu */ + const ui_menu_event *event = process(0); + + if (event != NULL && event->itemref != NULL) + { + if ((FPTR)event->itemref == 1 && event->iptkey == IPT_UI_SELECT) + { + ordered_by_shortname = !ordered_by_shortname; + entrylist = NULL; + // reset the char buffer if we change ordering criterion + memset(filename_buffer, '\0', ARRAY_LENGTH(filename_buffer)); + + // reload the menu with the new order + reset(UI_MENU_RESET_REMEMBER_REF); + popmessage("Switched Order: entries now ordered by %s", ordered_by_shortname ? "shortname" : "description"); + } + /* handle selections */ + else if (event->iptkey == IPT_UI_SELECT) + { + entry_info *entry = (entry_info *) event->itemref; + result = entry->short_name; + ui_menu::stack_pop(machine()); + } + else if (event->iptkey == IPT_SPECIAL) + { + int buflen = strlen(filename_buffer); + bool update_selected = false; + + /* if it's a backspace and we can handle it, do so */ + if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0) + { + *(char *)utf8_previous_char(&filename_buffer[buflen]) = 0; + update_selected = true; + + if (ARRAY_LENGTH(filename_buffer) > 0) + ui_popup_time(ERROR_MESSAGE_TIME, "%s", filename_buffer); + } + /* if it's any other key and we're not maxed out, update */ + else if (event->unichar >= ' ' && event->unichar < 0x7f) + { + buflen += utf8_from_uchar(&filename_buffer[buflen], ARRAY_LENGTH(filename_buffer) - buflen, event->unichar); + filename_buffer[buflen] = 0; + update_selected = true; + + if (ARRAY_LENGTH(filename_buffer) > 0) + ui_popup_time(ERROR_MESSAGE_TIME, "%s", filename_buffer); + } + + if (update_selected) + { + const entry_info *cur_selected; + + // if the current selection is a software entry, start search from here + if ((FPTR)event->itemref != 1) + cur_selected= (const entry_info *)get_selection(); + // else (if we are on the 'Switch Order' entry) start from the beginning + else + cur_selected= entrylist; + + // check for entries which matches our filename_buffer: + // from current entry to the end + for (entry = cur_selected; entry != NULL; entry = entry->next) + { + const char *compare_name = ordered_by_shortname ? entry->short_name : entry->long_name; + + if (compare_name != NULL && filename_buffer != NULL) + { + int match = 0; + for (int i = 0; i < ARRAY_LENGTH(filename_buffer); i++) + { + if (mame_strnicmp(compare_name, filename_buffer, i) == 0) + match = i; + } + + if (match > bestmatch) + { + bestmatch = match; + selected_entry = entry; + } + } + } + // and from the first entry to current one + for (entry = entrylist; entry != cur_selected; entry = entry->next) + { + const char *compare_name = ordered_by_shortname ? entry->short_name : entry->long_name; + + if (compare_name != NULL && filename_buffer != NULL) + { + int match = 0; + for (int i = 0; i < ARRAY_LENGTH(filename_buffer); i++) + { + if (mame_strnicmp(compare_name, filename_buffer, i) == 0) + match = i; + } + + if (match > bestmatch) + { + bestmatch = match; + selected_entry = entry; + } + } + } + + if (selected_entry != NULL && selected_entry != cur_selected) + set_selection((void *) selected_entry); + } + } + else if (event->iptkey == IPT_UI_CANCEL) + { + // reset the char buffer also in this case + if (filename_buffer[0] != '\0') + memset(filename_buffer, '\0', ARRAY_LENGTH(filename_buffer)); + result = filename_buffer; + ui_menu::stack_pop(machine()); + } + } +} + +/* list of available software lists - i.e. cartridges, floppies */ +ui_menu_software::ui_menu_software(running_machine &machine, render_container *container, const char *_interface, const software_list_device **_result) : ui_menu(machine, container) +{ + interface = _interface; + result = _result; +} + +void ui_menu_software::populate() +{ + bool haveCompatible = false; + + // Add original software lists for this system + software_list_device_iterator iter(machine().config().root_device()); + for (const software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) + { + if (swlist->list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) + { + const software_list *list = software_list_open(machine().options(), swlist->list_name(), false, NULL); + + if (list && interface) + { + bool found = false; + for (const software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) + { + const software_part *part = software_find_part(swinfo, NULL, NULL); + if (softlist_contain_interface(interface,part->interface_)) { + found = true; + } + } + if (found) { + item_append(list->description, NULL, 0, (void *)swlist); + } + + software_list_close(list); + } + } + } + + // Add compatible software lists for this system + for (const software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) + { + if (swlist->list_type() == SOFTWARE_LIST_COMPATIBLE_SYSTEM) + { + const software_list *list = software_list_open(machine().options(), swlist->list_name(), false, NULL); + + if (list && interface) + { + bool found = false; + for (const software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) + { + const software_part *part = software_find_part(swinfo, NULL, NULL); + if (softlist_contain_interface(interface,part->interface_)) { + found = true; + } + } + if (found) { + if (!haveCompatible) { + item_append("[compatible lists]", NULL, MENU_FLAG_DISABLE, NULL); + } + item_append(list->description, NULL, 0, (void *)swlist); + } + + haveCompatible = true; + software_list_close(list); + } + } + } + +} + +ui_menu_software::~ui_menu_software() +{ +} + +void ui_menu_software::handle() +{ + /* process the menu */ + const ui_menu_event *event = process(0); + + if (event != NULL && event->iptkey == IPT_UI_SELECT) { + // ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software_list(machine(), container, (software_list_config *)event->itemref, image))); + *result = (software_list_device *)event->itemref; + ui_menu::stack_pop(machine()); + } +} |