Beispiel #1
0
void menu_file_selector::type_search_char(char32_t ch)
{
	std::string const current(m_filename);
	if (input_character(m_filename, ch, uchar_is_printable))
	{
		ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename.c_str());

		file_selector_entry const *const cur_selected(reinterpret_cast<file_selector_entry const *>(get_selection_ref()));

		// if it's a perfect match for the current selection, don't move it
		if (!cur_selected || core_strnicmp(cur_selected->basename.c_str(), m_filename.c_str(), m_filename.size()))
		{
			std::string::size_type bestmatch(0);
			file_selector_entry const *selected_entry(cur_selected);
			for (auto &entry : m_entrylist)
			{
				// TODO: more efficient "common prefix" code
				std::string::size_type match(0);
				for (std::string::size_type i = 1; m_filename.size() >= i; ++i)
				{
					if (!core_strnicmp(entry.basename.c_str(), m_filename.c_str(), i))
						match = i;
					else
						break;
				}

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

			if (selected_entry && (selected_entry != cur_selected))
			{
				set_selection((void *)selected_entry);
				centre_selection();
			}
		}
	}
}
Beispiel #2
0
char* MyStrStrI(const char* pFirst, const char* pSrch)
{
	char* cp = (char*)pFirst;
	char* s1;
	char* s2;

	while (*cp)
	{
		s1 = cp;
		s2 = (char*)pSrch;

		while (*s1 && *s2 && !core_strnicmp(s1, s2, 1))
			s1++, s2++;

		if (!*s2)
			return cp;

		cp++;
	}
	return NULL;
}
Beispiel #3
0
//-------------------------------------------------
//  create the menu index
//-------------------------------------------------
void datfile_manager::index_menuidx(const game_driver *drv, dataindex &idx, drvindex &index)
{
	dataindex::iterator itemsiter = idx.find(drv);
	if (itemsiter == idx.end())
	{
		int cloneof = driver_list::non_bios_clone(*drv);
		if (cloneof == -1)
			return;
		else
		{
			const game_driver *c_drv = &driver_list::driver(cloneof);
			itemsiter = idx.find(c_drv);
			if (itemsiter == idx.end())
				return;
		}
	}

	// seek to correct point in datafile
	long s_offset = (*itemsiter).second;
	fseek(fp, s_offset, SEEK_SET);
	size_t tinfo = TAG_INFO.size();
	char rbuf[64 * 1024];
	std::string readbuf;
	while (fgets(rbuf, 64 * 1024, fp) != nullptr)
	{
		readbuf = chartrimcarriage(rbuf);

		if (!core_strnicmp(TAG_INFO.c_str(), readbuf.c_str(), tinfo))
			break;

		// TAG_COMMAND identifies the driver
		if (readbuf == TAG_COMMAND)
		{
			fgets(rbuf, 64 * 1024, fp);
			chartrimcarriage(rbuf);
			index.emplace(rbuf, ftell(fp));
		}
	}
}
Beispiel #4
0
//-------------------------------------------------
//  create the menu index
//-------------------------------------------------
void datfile_manager::index_menuidx(fileptr &&fp, const game_driver *drv, dataindex const &idx, drvindex &index)
{
	auto itemsiter = idx.find(drv);
	if (itemsiter == idx.end())
	{
		auto const cloneof = driver_list::non_bios_clone(*drv);
		if (cloneof == -1)
			return;

		auto const c_drv = &driver_list::driver(cloneof);
		if ((itemsiter = idx.find(c_drv)) == idx.end())
			return;
	}

	// seek to correct point in datafile
	auto const s_offset = itemsiter->second;
	std::fseek(fp.get(), s_offset, SEEK_SET);
	auto const tinfo = TAG_INFO.size();
	char rbuf[64 * 1024];
	std::string readbuf;
	while (std::fgets(rbuf, 64 * 1024, fp.get()) != nullptr)
	{
		readbuf = chartrimcarriage(rbuf);

		if (!core_strnicmp(TAG_INFO.c_str(), readbuf.c_str(), tinfo))
			break;

		// TAG_COMMAND identifies the driver
		if (readbuf == TAG_COMMAND)
		{
			std::fgets(rbuf, 64 * 1024, fp.get());
			chartrimcarriage(rbuf);
			index.emplace(rbuf, std::ftell(fp.get()));
		}
	}
}
Beispiel #5
0
const osd_directory_entry *zippath_readdir(zippath_directory *directory)
{
	const osd_directory_entry *result = NULL;
	const zip_file_header *header;
	const char *relpath;
	const char *separator;
	const char *s;
	zippath_returned_directory *rdent;

	if (!directory->returned_parent)
	{
		/* first thing's first - return parent directory */
		directory->returned_parent = true;
		memset(&directory->returned_entry, 0, sizeof(directory->returned_entry));
		directory->returned_entry.name = "..";
		directory->returned_entry.type = ENTTYPE_DIR;
		result = &directory->returned_entry;
	}
	else if (directory->directory != NULL)
	{
		/* a normal directory read */
		do
		{
			result = osd_readdir(directory->directory);
		}
		while((result != NULL) && (!strcmp(result->name, ".") || !strcmp(result->name, "..")));

		/* special case - is this entry a ZIP file?  if so we need to return it as a "directory" */
		if ((result != NULL) && is_zip_file(result->name))
		{
			/* copy; but change the entry type */
			directory->returned_entry = *result;
			directory->returned_entry.type = ENTTYPE_DIR;
			result = &directory->returned_entry;
		}
	}
	else if (directory->zipfile != NULL)
	{
		do
		{
			/* a zip file read */
			do
			{
				if (!directory->called_zip_first)
					header = zip_file_first_file(directory->zipfile);
				else
					header = zip_file_next_file(directory->zipfile);
				directory->called_zip_first = true;
				relpath = NULL;
			}
			while((header != NULL) && ((relpath = get_relative_path(directory, header)) == NULL));

			if (relpath != NULL)
			{
				/* we've found a ZIP entry; but this may be an entry deep within the target directory */
				for (s = relpath; *s && !is_zip_file_separator(*s); s++)
					;
				separator = *s ? s : NULL;

				if (separator != NULL)
				{
					/* a nested entry; loop through returned_dirlist to see if we've returned the parent directory */
					for (rdent = directory->returned_dirlist; rdent != NULL; rdent = rdent->next)
					{
						if (!core_strnicmp(rdent->name.c_str(), relpath, separator - relpath))
							break;
					}

					if (rdent == NULL)
					{
						/* we've found a new directory; add this to returned_dirlist */
						rdent = new zippath_returned_directory;
						rdent->next = directory->returned_dirlist;
						rdent->name.assign(relpath, separator - relpath);
						directory->returned_dirlist = rdent;

						/* ...and return it */
						memset(&directory->returned_entry, 0, sizeof(directory->returned_entry));
						directory->returned_entry.name = rdent->name.c_str();
						directory->returned_entry.type = ENTTYPE_DIR;
						result = &directory->returned_entry;
					}
				}
				else
				{
					/* a real file */
					memset(&directory->returned_entry, 0, sizeof(directory->returned_entry));
					directory->returned_entry.name = relpath;
					directory->returned_entry.type = ENTTYPE_FILE;
					directory->returned_entry.size = header->uncompressed_length;
					result = &directory->returned_entry;
				}
			}
		}
		while((relpath != NULL) && (result == NULL));
	}
	return result;
}
Beispiel #6
0
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));
		}
	}
}
Beispiel #7
0
void menu_software_list::handle()
{
	const entry_info *selected_entry = nullptr;
	int bestmatch = 0;

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

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

			// reset the char buffer if we change ordering criterion
			m_filename_buffer.clear();

			// 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;
			stack_pop();
		}
		else if (event->iptkey == IPT_SPECIAL)
		{
			if (input_character(m_filename_buffer, event->unichar, &is_valid_softlist_part_char))
			{
				// display the popup
				ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);

				// identify the selected entry
				entry_info const *const cur_selected = (uintptr_t(event->itemref) != 1)
						? reinterpret_cast<entry_info const *>(get_selection_ref())
						: nullptr;

				// loop through all entries
				for (auto &entry : m_entrylist)
				{
					// is this entry the selected entry?
					if (cur_selected != &entry)
					{
						auto &compare_name = m_ordered_by_shortname ? entry.short_name : entry.long_name;

						int match = 0;
						for (int i = 0; i < m_filename_buffer.size() + 1; i++)
						{
							if (core_strnicmp(compare_name.c_str(), m_filename_buffer.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_buffer.clear();
			m_result = m_filename_buffer;
			stack_pop();
		}
	}
}
Beispiel #8
0
/**************************************************************************
 *      load_datafile_text
 *
 *      Loads text field for a driver into the buffer specified. Specify the
 *      driver, a pointer to the buffer, the buffer size, the index created by
 *      index_datafile(), and the desired text field (e.g., DATAFILE_TAG_BIO).
 *
 *      Returns 0 if successful.
 **************************************************************************/
static int load_datafile_text(const game_driver *drv, char *buffer, int bufsize, struct tDatafileIndex *idx, const char *tag, int source_file, int mameinfo)
{
	char readbuf[16384];

	*buffer = '\0';

	if (!source_file)
	{
		/* find driver in datafile index */
		while (idx->driver)
		{
			if (idx->driver == drv)
				break;

		idx++;
		}
	}
	else
	{
		/* find source file in datafile index */
		while (idx->driver)
		{
			if (idx->driver->source_file == drv->source_file)
				break;

			idx++;
		}
	}

	if (idx->driver == 0)
		return 1; /* driver not found in index */

	/* seek to correct point in datafile */
	if (ParseSeek (idx->offset, SEEK_SET))
		return 1;

	/* read text until buffer is full or end of entry is encountered */
	while (fgets(readbuf, 16384, fp))
	{
		if (!core_strnicmp(DATAFILE_TAG_END, readbuf, strlen(DATAFILE_TAG_END)))
			break;

		if (!core_strnicmp(tag, readbuf, strlen(tag)))
			continue;

		if (strlen(buffer) + strlen(readbuf) > bufsize)
			break;

		if (mameinfo)
		{
			char *temp = strtok(readbuf, "\r\n\r\n");
			if (temp != nullptr)
				strcat(buffer, temp);
			else
				strcat(buffer, readbuf);
		}
		else
			strcat(buffer, readbuf);
	}

	return 0;
}
Beispiel #9
0
 /**************************************************************************
 *      index_datafile
 *      Create an index for the records in the currently open datafile.
 *
 *      Returns 0 on error, or the number of index entries created.
 **************************************************************************/
static int index_datafile(struct tDatafileIndex **_index, int source)
{
	struct tDatafileIndex *idx;
	int count = 0;
	char readbuf[512];
	char name[40];
	int num_games = driver_list::total();

	/* rewind file */
	if (ParseSeek (0L, SEEK_SET))
		return 0;

	/* allocate index */
	idx = *_index = global_alloc_array(tDatafileIndex, (num_games + 1) * sizeof (struct tDatafileIndex));

	if (!idx)
		return 0;

	while (fgets(readbuf, 512, fp))
	{
		/* DATAFILE_TAG_KEY identifies the driver */
		if (!core_strnicmp(DATAFILE_TAG_KEY, readbuf, strlen(DATAFILE_TAG_KEY)))
		{
			int game_index = 0;
			char *curpoint = &readbuf[strlen(DATAFILE_TAG_KEY) + 1];
			char *pch = NULL;
			char *ends = &readbuf[strlen(readbuf) - 1];

			while (curpoint < ends)
			{
				// search for comma
				pch = strpbrk(curpoint, ",");

				// found it
				if (pch)
				{
					// copy data and validate driver
					int len = pch - curpoint;
					strncpy(name, curpoint, len);
					name[len] = '\0';

					if (!source)
						game_index = GetGameNameIndex(name);
					else
						game_index = GetSrcDriverIndex(name);

					if (game_index >= 0)
					{
						idx->driver = &driver_list::driver(game_index);
						idx->offset = ftell(fp);
						idx++;
						count++;
					}

					// update current point
					curpoint = pch + 1;
				}
				// if comma not found, copy data while until reach the end of string
				else if (!pch && curpoint < ends)
				{
					int len = ends - curpoint;
					strncpy(name, curpoint, len);
					name[len] = '\0';

					if (!source)
						game_index = GetGameNameIndex(name);
					else
						game_index = GetSrcDriverIndex(name);

					if (game_index >= 0)
					{
						idx->driver = &driver_list::driver(game_index);
						idx->offset = ftell(fp);
						idx++;
						count++;
					}

					// update current point
					curpoint = ends;
				}
			}
		}
	}

	/* mark end of index */
	idx->offset = 0L;
	idx->driver = 0;
	return count;
}
Beispiel #10
0
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, 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)
		{
			// if it's any other key and we're not maxed out, update
			if (input_character(m_filename, event->unichar, uchar_is_printable))
			{
				ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename.c_str());

				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() + 1; 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();
		}
	}
}
Beispiel #11
0
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';
		}
	}
}
Beispiel #12
0
void menu_add_change_folder::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)
		{
			int index = (uintptr_t)menu_event->itemref - 1;
			const menu_item &pitem = item[index];

			// go up to the parent path
			if (!strcmp(pitem.text.c_str(), ".."))
			{
				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.c_str(), "[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
			m_search[0] = '\0';
			reset(reset_options::SELECT_FIRST);
		}
		else if (menu_event->iptkey == IPT_SPECIAL)
		{
			bool update_selected = false;

			if (menu_event->unichar == 0x09)
			{
				// Tab key, save current path
				std::string error_string;
				if (m_change)
				{
					if (ui().options().exists(s_folders[m_ref].option))
						ui().options().set_value(s_folders[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
					else if (strcmp(machine().options().value(s_folders[m_ref].option), m_current_path.c_str()) != 0)
					{
						machine().options().set_value(s_folders[m_ref].option, m_current_path.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
						machine().options().mark_changed(s_folders[m_ref].option);
					}
				}
				else
				{
					m_folders.push_back(m_current_path);
					std::string tmppath;
					for (int x = 0; x < m_folders.size(); ++x)
					{
						tmppath.append(m_folders[x]);
						if (x != m_folders.size() - 1)
							tmppath.append(";");
					}

					if (ui().options().exists(s_folders[m_ref].option))
						ui().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
					else if (strcmp(machine().options().value(s_folders[m_ref].option), tmppath.c_str()) != 0)
					{
						machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
						machine().options().mark_changed(s_folders[m_ref].option);
					}
				}

				reset_parent(reset_options::SELECT_FIRST);
				stack_pop();
			}
			else
			{
				// if it's any other key and we're not maxed out, update
				update_selected = input_character(m_search, menu_event->unichar, uchar_is_printable);
			}

			// check for entries which matches our search buffer
			if (update_selected)
			{
				const int cur_selected = selected_index();
				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.empty())
					{
						int match = 0;
						for (int i = 0; i < m_search.size() + 1; i++)
						{
							if (core_strnicmp(item[entry].text.c_str(), m_search.data(), 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.empty())
					{
						int match = 0;
						for (int i = 0; i < m_search.size() + 1; i++)
						{
							if (core_strnicmp(item[entry].text.c_str(), m_search.data(), i) == 0)
								match = i;
						}

						if (match > bestmatch)
						{
							bestmatch = match;
							selected = entry;
						}
					}
				}
				centre_selection();
			}
		}
		else if (menu_event->iptkey == IPT_UI_CANCEL)
		{
			// reset the char buffer also in this case
			m_search.clear();
		}
	}
}
Beispiel #13
0
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());
		}
	}
}