コード例 #1
0
ファイル: custui.cpp プロジェクト: p0nley/mame
void ui_menu_rgb_ui::inkey_special(const ui_menu_event *m_event)
{
	if (m_event->iptkey == IPT_UI_SELECT)
	{
		m_key_active = !m_key_active;
		m_lock_ref = (FPTR)m_event->itemref;

		if (!m_key_active)
		{
			int val = atoi(m_search);
			val = m_color->clamp(val);

			switch ((FPTR)m_event->itemref)
			{
				case RGB_ALPHA:
					m_color->set_a(val);
					break;

				case RGB_RED:
					m_color->set_r(val);
					break;

				case RGB_GREEN:
					m_color->set_g(val);
					break;

				case RGB_BLUE:
					m_color->set_b(val);
					break;
			}

			m_search[0] = 0;
			m_lock_ref = 0;
			return;
		}
	}

	if (!m_key_active)
	{
		m_search[0] = 0;
		return;
	}

	int buflen = strlen(m_search);

	// if it's a backspace and we can handle it, do so
	if (((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0))
		*(char *)utf8_previous_char(&m_search[buflen]) = 0;
	else if (buflen >= 3)
		return;
	// if it's any other key and we're not maxed out, update
	else if ((m_event->unichar >= '0' && m_event->unichar <= '9'))
		buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar);

	m_search[buflen] = 0;
}
コード例 #2
0
ファイル: filesel.cpp プロジェクト: robsonfr/mame
static void input_character(char *buffer, size_t buffer_length, unicode_char unichar, int (*filter)(unicode_char))
{
	size_t buflen = strlen(buffer);

	if ((unichar == 8 || unichar == 0x7f) && (buflen > 0))
	{
		*(char *)utf8_previous_char(&buffer[buflen]) = 0;
	}
	else if ((unichar > ' ') && ((filter == NULL) || (*filter)(unichar)))
	{
		buflen += utf8_from_uchar(&buffer[buflen], buffer_length - buflen, unichar);
		buffer[buflen] = 0;
	}
}
コード例 #3
0
ファイル: selgame.c プロジェクト: mbcoguno/mame
void ui_menu_select_game::inkey_special(const ui_menu_event *menu_event)
{
	// typed characters append to the buffer
	int buflen = strlen(m_search);

	// if it's a backspace and we can handle it, do so
	if ((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0)
	{
		*(char *)utf8_previous_char(&m_search[buflen]) = 0;
		m_rerandomize = true;
		reset(UI_MENU_RESET_SELECT_FIRST);
	}

	// if it's any other key and we're not maxed out, update
	else if (menu_event->unichar >= ' ' && menu_event->unichar < 0x7f)
	{
		buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, menu_event->unichar);
		m_search[buflen] = 0;
		reset(UI_MENU_RESET_SELECT_FIRST);
	}
}
コード例 #4
0
ファイル: barcode.cpp プロジェクト: robsonfr/mame
void ui_menu_barcode_reader::handle()
{
	// rebuild the menu (so to update the selected device, if the user has pressed L or R)
	reset(UI_MENU_RESET_REMEMBER_POSITION);
	populate();

	// process the menu
	const ui_menu_event *event = process(UI_MENU_PROCESS_LR_REPEAT);

	// process the event
	if (event != NULL)
	{
		// handle selections
		switch (event->iptkey)
		{
			case IPT_UI_LEFT:
				if (event->itemref == ITEMREF_SELECT_READER)
					previous();
				break;

			case IPT_UI_RIGHT:
				if (event->itemref == ITEMREF_SELECT_READER)
					next();
				break;

			case IPT_UI_SELECT:
				if (event->itemref == ITEMREF_ENTER_BARCODE)
				{
					std::string tmp_file(m_barcode_buffer);
					//printf("code %s\n", m_barcode_buffer);
					if (!current_device()->is_valid(tmp_file.length()))
						machine().ui().popup_time(5, "Barcode length invalid!");
					else
					{
						current_device()->write_code(tmp_file.c_str(), tmp_file.length());
						// if sending was successful, reset char buffer
						if (m_barcode_buffer[0] != '\0')
							memset(m_barcode_buffer, '\0', ARRAY_LENGTH(m_barcode_buffer));
						reset(UI_MENU_RESET_REMEMBER_POSITION);
					}
				}
				break;

			case IPT_SPECIAL:
				if (get_selection() == ITEMREF_NEW_BARCODE)
				{
					int buflen = strlen(m_barcode_buffer);

					// 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(&m_barcode_buffer[buflen]) = 0;
					else if (event->unichar >= '0' && event->unichar <= '9')
					{
						buflen += utf8_from_uchar(&m_barcode_buffer[buflen], ARRAY_LENGTH(m_barcode_buffer) - buflen, event->unichar);
						m_barcode_buffer[buflen] = 0;
					}
					reset(UI_MENU_RESET_REMEMBER_POSITION);
				}
				break;

			case IPT_UI_CANCEL:
				// reset the char buffer also in this case
				if (m_barcode_buffer[0] != '\0')
					memset(m_barcode_buffer, '\0', ARRAY_LENGTH(m_barcode_buffer));
				break;
		}
	}
}
コード例 #5
0
ファイル: selector.cpp プロジェクト: GiuseppeGorgoglione/mame
void menu_selector::handle()
{
	// process the menu
	const event *menu_event = process(0);

	if (menu_event != nullptr && menu_event->itemref != nullptr)
	{
		if (menu_event->iptkey == IPT_UI_SELECT)
		{
			for (size_t idx = 0; idx < m_str_items.size(); ++idx)
				if ((void*)&m_str_items[idx] == menu_event->itemref)
					m_selector = idx;

			switch (m_category)
			{
			case INIFILE:
				mame_machine_manager::instance()->inifile().set_file(m_selector);
				mame_machine_manager::instance()->inifile().set_cat(0);
				reset_parent(reset_options::REMEMBER_REF);
				break;

			case CATEGORY:
				mame_machine_manager::instance()->inifile().set_cat(m_selector);
				reset_parent(reset_options::REMEMBER_REF);
				break;

			case GAME:
				main_filters::actual = m_hover;
				reset_parent(reset_options::SELECT_FIRST);
				break;

			case SOFTWARE:
				sw_filters::actual = m_hover;
				reset_parent(reset_options::SELECT_FIRST);
				break;

			default:
				reset_parent(reset_options::REMEMBER_REF);
				break;
			}

			ui_globals::switch_image = true;
			stack_pop();
		}
		else if (menu_event->iptkey == IPT_SPECIAL)
		{
			auto const buflen = strlen(m_search);
			if ((menu_event->unichar == 8) || (menu_event->unichar == 0x7f))
			{
				// if it's a backspace and we can handle it, do so
				if (0 < buflen)
				{
					*const_cast<char *>(utf8_previous_char(&m_search[buflen])) = 0;
					reset(reset_options::SELECT_FIRST);
				}
			}
			else if (menu_event->is_char_printable())
			{
				// if it's any other key and we're not maxed out, update
				if (menu_event->append_char(m_search, buflen))
					reset(reset_options::SELECT_FIRST);
			}
		}

		// escape pressed with non-empty text clears the text
		else if (menu_event->iptkey == IPT_UI_CANCEL && m_search[0] != 0)
		{
			m_search[0] = '\0';
			reset(reset_options::SELECT_FIRST);
		}
	}
}
コード例 #6
0
ファイル: filesel.cpp プロジェクト: robsonfr/mame
void ui_menu_file_selector::handle()
{
	file_error err;
	const file_selector_entry *entry;
	const file_selector_entry *selected_entry = NULL;
	int bestmatch = 0;

	// process the menu
	const ui_menu_event *event = process(0);
	if (event != NULL && event->itemref != NULL)
	{
		// handle selections
		if (event->iptkey == IPT_UI_SELECT)
		{
			entry = (const file_selector_entry *) event->itemref;
			switch(entry->type)
			{
				case SELECTOR_ENTRY_TYPE_EMPTY:
					// empty slot - unload
					*m_result = R_EMPTY;
					ui_menu::stack_pop(machine());
					break;

				case SELECTOR_ENTRY_TYPE_CREATE:
					// create
					*m_result = R_CREATE;
					ui_menu::stack_pop(machine());
					break;

				case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST:
					*m_result = R_SOFTLIST;
					ui_menu::stack_pop(machine());
					break;

				case SELECTOR_ENTRY_TYPE_DRIVE:
				case SELECTOR_ENTRY_TYPE_DIRECTORY:
					// drive/directory - first check the path
					err = zippath_opendir(entry->fullpath, NULL);
					if (err != FILERR_NONE)
					{
						// this path is problematic; present the user with an error and bail
						machine().ui().popup_time(1, "Error accessing %s", entry->fullpath);
						break;
					}
					m_current_directory.assign(entry->fullpath);
					reset((ui_menu_reset_options)0);
					break;

				case SELECTOR_ENTRY_TYPE_FILE:
					// file
					m_current_file.assign(entry->fullpath);
					*m_result = R_FILE;
					ui_menu::stack_pop(machine());
					break;
			}

			// reset the char buffer when pressing IPT_UI_SELECT
			if (m_filename_buffer[0] != '\0')
				memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));
		}
		else if (event->iptkey == IPT_SPECIAL)
		{
			int buflen = strlen(m_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(&m_filename_buffer[buflen]) = 0;
				update_selected = TRUE;

				if (ARRAY_LENGTH(m_filename_buffer) > 0)
					machine().ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_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(&m_filename_buffer[buflen], ARRAY_LENGTH(m_filename_buffer) - buflen, event->unichar);
				m_filename_buffer[buflen] = 0;
				update_selected = TRUE;

				if (ARRAY_LENGTH(m_filename_buffer) > 0)
					machine().ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
			}

			if (update_selected)
			{
				const file_selector_entry *cur_selected = (const file_selector_entry *)get_selection();

				// check for entries which matches our m_filename_buffer:
				// from current entry to the end
				for (entry = cur_selected; entry != NULL; entry = entry->next)
				{
					if (entry->basename != NULL && m_filename_buffer != NULL)
					{
						int match = 0;
						for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++)
						{
							if (core_strnicmp(entry->basename, m_filename_buffer, i) == 0)
								match = i;
						}

						if (match > bestmatch)
						{
							bestmatch = match;
							selected_entry = entry;
						}
					}
				}
				// and from the first entry to current one
				for (entry = m_entrylist; entry != cur_selected; entry = entry->next)
				{
					if (entry->basename != NULL && m_filename_buffer != NULL)
					{
						int match = 0;
						for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++)
						{
							if (core_strnicmp(entry->basename, m_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 (m_filename_buffer[0] != '\0')
				memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));
		}
	}
}
コード例 #7
0
ファイル: barcode.cpp プロジェクト: GiuseppeGorgoglione/mame
void menu_barcode_reader::handle()
{
	// rebuild the menu (so to update the selected device, if the user has pressed L or R)
	reset(reset_options::REMEMBER_POSITION);
	populate();

	// process the menu
	const event *event = process(PROCESS_LR_REPEAT);

	// process the event
	if (event)
	{
		// handle selections
		switch (event->iptkey)
		{
		case IPT_UI_LEFT:
			if (event->itemref == ITEMREF_SELECT_READER)
				previous();
			break;

		case IPT_UI_RIGHT:
			if (event->itemref == ITEMREF_SELECT_READER)
				next();
			break;

		case IPT_UI_SELECT:
			if (event->itemref == ITEMREF_ENTER_BARCODE)
			{
				std::string tmp_file(m_barcode_buffer);
				//printf("code %s\n", m_barcode_buffer);
				if (!current_device()->is_valid(tmp_file.length()))
					ui().popup_time(5, "%s", _("Barcode length invalid!"));
				else
				{
					current_device()->write_code(tmp_file.c_str(), tmp_file.length());
					// if sending was successful, reset char buffer
					if (m_barcode_buffer[0] != '\0')
						memset(m_barcode_buffer, '\0', ARRAY_LENGTH(m_barcode_buffer));
					reset(reset_options::REMEMBER_POSITION);
				}
			}
			break;

		case IPT_SPECIAL:
			if (get_selection_ref() == ITEMREF_NEW_BARCODE)
			{
				auto const buflen = std::strlen(m_barcode_buffer);

				// if it's a backspace and we can handle it, do so
				if ((event->unichar == 8) || (event->unichar == 0x7f))
				{
					if (0 < buflen)
						*const_cast<char *>(utf8_previous_char(&m_barcode_buffer[buflen])) = 0;
				}
				else if ((event->unichar >= '0') && (event->unichar <= '9'))
				{
					event->append_char(m_barcode_buffer, buflen);
				}
				reset(reset_options::REMEMBER_POSITION);
			}
			break;

		case IPT_UI_CANCEL:
			// reset the char buffer also in this case
			if (m_barcode_buffer[0] != '\0')
				memset(m_barcode_buffer, '\0', ARRAY_LENGTH(m_barcode_buffer));
			break;
		}
	}
}
コード例 #8
0
ファイル: selector.cpp プロジェクト: dlabi/mame
void ui_menu_selector::handle()
{
	// process the menu
	const ui_menu_event *m_event = process(0);

	if (m_event != nullptr && m_event->itemref != nullptr)
	{
		if (m_event->iptkey == IPT_UI_SELECT)
		{
			for (size_t idx = 0; idx < m_str_items.size(); ++idx)
				if ((void*)&m_str_items[idx] == m_event->itemref)
					m_selector = idx;

			switch (m_category)
			{
				case SELECTOR_INIFILE:
					machine().inifile().current_file = m_selector;
					machine().inifile().current_category = 0;
					ui_menu::menu_stack->parent->reset(UI_MENU_RESET_REMEMBER_REF);
					break;

				case SELECTOR_CATEGORY:
					machine().inifile().current_category = m_selector;
					ui_menu::menu_stack->parent->reset(UI_MENU_RESET_REMEMBER_REF);
					break;

				case SELECTOR_GAME:
					main_filters::actual = m_hover;
					ui_menu::menu_stack->parent->reset(UI_MENU_RESET_SELECT_FIRST);
					break;

				case SELECTOR_SOFTWARE:
					sw_filters::actual = m_hover;
					ui_menu::menu_stack->parent->reset(UI_MENU_RESET_SELECT_FIRST);
					break;

				default:
					ui_menu::menu_stack->parent->reset(UI_MENU_RESET_REMEMBER_REF);
					break;
			}

			ui_globals::switch_image = true;
			ui_menu::stack_pop(machine());
		}
		else if (m_event->iptkey == IPT_SPECIAL)
		{
			int buflen = strlen(m_search);

			// if it's a backspace and we can handle it, do so
			if ((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0)
			{
				*(char *)utf8_previous_char(&m_search[buflen]) = 0;
				reset(UI_MENU_RESET_SELECT_FIRST);
			}

			// if it's any other key and we're not maxed out, update
			else if (m_event->unichar >= ' ' && m_event->unichar < 0x7f)
			{
				buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar);
				m_search[buflen] = 0;
				reset(UI_MENU_RESET_SELECT_FIRST);
			}
		}

		// escape pressed with non-empty text clears the text
		else if (m_event->iptkey == IPT_UI_CANCEL && m_search[0] != 0)
		{
			m_search[0] = '\0';
			reset(UI_MENU_RESET_SELECT_FIRST);
		}
	}
}
コード例 #9
0
ファイル: dirmenu.cpp プロジェクト: hackwrench/mame
void ui_menu_add_change_folder::handle()
{
	// process the menu
	const ui_menu_event *m_event = process(0);

	if (m_event != nullptr && m_event->itemref != nullptr)
	{
		if (m_event->iptkey == IPT_UI_SELECT)
		{
			int index = (FPTR)m_event->itemref - 1;
			const ui_menu_item &pitem = item[index];

			// go up to the parent path
			if (!strcmp(pitem.text, ".."))
			{
				size_t first_sep = m_current_path.find_first_of(PATH_SEPARATOR[0]);
				size_t last_sep = m_current_path.find_last_of(PATH_SEPARATOR[0]);
				if (first_sep != last_sep)
					m_current_path.erase(++last_sep);
			}
			else
			{
				// if isn't a drive, appends the directory
				if (strcmp(pitem.subtext, "[DRIVE]") != 0)
				{
					if (m_current_path[m_current_path.length() - 1] == PATH_SEPARATOR[0])
						m_current_path.append(pitem.text);
					else
						m_current_path.append(PATH_SEPARATOR).append(pitem.text);
				}
				else
					m_current_path = pitem.text;
			}

			// reset the char buffer also in this case
			if (m_search[0] != 0)
				m_search[0] = '\0';
			reset(UI_MENU_RESET_SELECT_FIRST);
		}
		else if (m_event->iptkey == IPT_SPECIAL)
		{
			int buflen = strlen(m_search);
			bool update_selected = FALSE;

			// if it's a backspace and we can handle it, do so
			if ((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0)
			{
				*(char *)utf8_previous_char(&m_search[buflen]) = 0;
				update_selected = TRUE;
			}
			// if it's any other key and we're not maxed out, update
			else if (m_event->unichar >= ' ' && m_event->unichar < 0x7f)
			{
				buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar);
				m_search[buflen] = 0;
				update_selected = TRUE;
			}
			// Tab key, save current path
			else if (m_event->unichar == 0x09)
			{
				std::string error_string;
				if (m_change)
				{
					machine().options().set_value(s_folders_entry[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
					machine().datfile().reset_run();
				}
				else
				{
					std::string tmppath = std::string(machine().options().value(s_folders_entry[m_ref].option)).append(";").append(m_current_path.c_str());
					machine().options().set_value(s_folders_entry[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
				}

				ui_menu::menu_stack->parent->reset(UI_MENU_RESET_SELECT_FIRST);
				ui_menu::stack_pop(machine());
			}

			// check for entries which matches our search buffer
			if (update_selected)
			{
				const int cur_selected = selected;
				int entry, bestmatch = 0;

				// from current item to the end
				for (entry = cur_selected; entry < item.size(); entry++)
					if (item[entry].ref != nullptr && m_search[0] != 0)
					{
						int match = 0;
						for (int i = 0; i < ARRAY_LENGTH(m_search); i++)
						{
							if (core_strnicmp(item[entry].text, m_search, i) == 0)
								match = i;
						}

						if (match > bestmatch)
						{
							bestmatch = match;
							selected = entry;
						}
					}

				// and from the first item to current one
				for (entry = 0; entry < cur_selected; entry++)
				{
					if (item[entry].ref != nullptr && m_search[0] != 0)
					{
						int match = 0;
						for (int i = 0; i < ARRAY_LENGTH(m_search); i++)
						{
							if (core_strnicmp(item[entry].text, m_search, i) == 0)
								match = i;
						}

						if (match > bestmatch)
						{
							bestmatch = match;
							selected = entry;
						}
					}
				}
			}
		}
		else if (m_event->iptkey == IPT_UI_CANCEL)
		{
			// reset the char buffer also in this case
			if (m_search[0] != 0)
				m_search[0] = '\0';
		}
	}
}
コード例 #10
0
ファイル: filesel.cpp プロジェクト: csamuelson/mame
void menu_file_selector::handle()
{
	osd_file::error err;
	const file_selector_entry *selected_entry = nullptr;
	int bestmatch = 0;

	// process the menu
	const event *event = process(0);
	if (event != nullptr && event->itemref != nullptr)
	{
		// handle selections
		if (event->iptkey == IPT_UI_SELECT)
		{
			auto entry = (const file_selector_entry *) event->itemref;
			switch (entry->type)
			{
			case SELECTOR_ENTRY_TYPE_EMPTY:
				// empty slot - unload
				m_result = result::EMPTY;
				stack_pop();
				break;

			case SELECTOR_ENTRY_TYPE_CREATE:
				// create
				m_result = result::CREATE;
				stack_pop();
				break;

			case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST:
				m_result = result::SOFTLIST;
				stack_pop();
				break;

			case SELECTOR_ENTRY_TYPE_DRIVE:
			case SELECTOR_ENTRY_TYPE_DIRECTORY:
				// drive/directory - first check the path
				err = util::zippath_opendir(entry->fullpath.c_str(), nullptr);
				if (err != osd_file::error::NONE)
				{
					// this path is problematic; present the user with an error and bail
					ui().popup_time(1, "Error accessing %s", entry->fullpath);
					break;
				}
				m_current_directory.assign(entry->fullpath);
				reset(reset_options::SELECT_FIRST);
				break;

			case SELECTOR_ENTRY_TYPE_FILE:
				// file
				m_current_file.assign(entry->fullpath);
				m_result = result::FILE;
				stack_pop();
				break;
			}

			// reset the char buffer when pressing IPT_UI_SELECT
			m_filename.clear();
		}
		else if (event->iptkey == IPT_SPECIAL)
		{
			bool update_selected = false;

			if ((event->unichar == 8) || (event->unichar == 0x7f))
			{
				// if it's a backspace and we can handle it, do so
				auto const buflen = m_filename.size();
				if (0 < buflen)
				{
					auto buffer_oldend = m_filename.c_str() + buflen;
					auto buffer_newend = utf8_previous_char(buffer_oldend);
					m_filename.resize(buffer_newend - m_filename.c_str());
					update_selected = true;

					ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename.c_str());
				}
			}
			else if (event->is_char_printable())
			{
				// if it's any other key and we're not maxed out, update
				m_filename += utf8_from_uchar(event->unichar);
				update_selected = true;

				ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename.c_str());
			}

			if (update_selected)
			{
				file_selector_entry const *const cur_selected(reinterpret_cast<file_selector_entry const *>(get_selection_ref()));

				// check for entries which matches our m_filename_buffer:
				for (auto &entry : m_entrylist)
				{
					if (cur_selected != &entry)
					{
						int match = 0;
						for (int i = 0; i < m_filename.size(); i++)
						{
							if (core_strnicmp(entry.basename.c_str(), m_filename.c_str(), i) == 0)
								match = i;
						}

						if (match > bestmatch)
						{
							bestmatch = match;
							selected_entry = &entry;
						}
					}
				}

				if (selected_entry != nullptr && selected_entry != cur_selected)
				{
					set_selection((void *)selected_entry);
					centre_selection();
				}
			}
		}
		else if (event->iptkey == IPT_UI_CANCEL)
		{
			// reset the char buffer also in this case
			m_filename.clear();
		}
	}
}
コード例 #11
0
ファイル: swlist.cpp プロジェクト: user123456789101112/mame
void menu_software_list::handle()
{
	const entry_info *entry;
	const entry_info *selected_entry = nullptr;
	int bestmatch = 0;

	// process the menu
	const event *event = process(0);

	if (event && event->itemref)
	{
		if ((FPTR)event->itemref == 1 && event->iptkey == IPT_UI_SELECT)
		{
			m_ordered_by_shortname = !m_ordered_by_shortname;
			m_entrylist = nullptr;

			// reset the char buffer if we change ordering criterion
			memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));

			// reload the menu with the new order
			reset(reset_options::REMEMBER_REF);
			machine().popmessage(_("Switched Order: entries now ordered by %s"), m_ordered_by_shortname ? _("shortname") : _("description"));
		}
		// handle selections
		else if (event->iptkey == IPT_UI_SELECT)
		{
			entry_info *info = (entry_info *) event->itemref;
			m_result = info->short_name;
			menu::stack_pop(machine());
		}
		else if (event->iptkey == IPT_SPECIAL)
		{
			auto const buflen = std::strlen(m_filename_buffer);
			bool update_selected = false;

			if ((event->unichar == 8) || (event->unichar == 0x7f))
			{
				// if it's a backspace and we can handle it, do so
				if (0 < buflen)
				{
					*const_cast<char *>(utf8_previous_char(&m_filename_buffer[buflen])) = 0;
					update_selected = true;

					ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
				}
			}
			else if (event->is_char_printable())
			{
				// if it's any other key and we're not maxed out, update
				if (event->append_char(m_filename_buffer, buflen))
				{
					update_selected = true;

					ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_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 = m_entrylist;

				// check for entries which matches our filename_buffer:
				// from current entry to the end
				for (entry = cur_selected; entry != nullptr; entry = entry->next)
				{
					const char *compare_name = m_ordered_by_shortname ? entry->short_name : entry->long_name;

					if (compare_name != nullptr && m_filename_buffer != nullptr)
					{
						int match = 0;
						for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++)
						{
							if (core_strnicmp(compare_name, m_filename_buffer, i) == 0)
								match = i;
						}

						if (match > bestmatch)
						{
							bestmatch = match;
							selected_entry = entry;
						}
					}
				}
				// and from the first entry to current one
				for (entry = m_entrylist; entry != cur_selected; entry = entry->next)
				{
					const char *compare_name = m_ordered_by_shortname ? entry->short_name : entry->long_name;

					if (compare_name != nullptr && m_filename_buffer != nullptr)
					{
						int match = 0;
						for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++)
						{
							if (core_strnicmp(compare_name, m_filename_buffer, i) == 0)
								match = i;
						}

						if (match > bestmatch)
						{
							bestmatch = match;
							selected_entry = entry;
						}
					}
				}

				if (selected_entry != nullptr && selected_entry != cur_selected)
				{
					set_selection((void *)selected_entry);
					top_line = selected - (visible_lines / 2);
				}
			}
		}
		else if (event->iptkey == IPT_UI_CANCEL)
		{
			// reset the char buffer also in this case
			if (m_filename_buffer[0] != '\0')
				memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer));
			m_result = m_filename_buffer;
			menu::stack_pop(machine());
		}
	}
}