Beispiel #1
0
/**
 * Create a valid path name from a possibly invalid name by erasing invalid
 * path parts at the end of the string.  If string doesn't contain any path
 * component, it will be pointed to the root directory.  Empty string will
 * be left as-is to prevent overwriting past allocated area.
 */
void File_MakeValidPathName(char *pPathName)
{
	struct stat dirstat;
	char *pLastSlash;

	do
	{
		/* Check for a valid path */
		if (stat(pPathName, &dirstat) == 0 && S_ISDIR(dirstat.st_mode))
		{
			break;
		}

		pLastSlash = strrchr(pPathName, PATHSEP);
		if (pLastSlash)
		{
			/* Erase the (probably invalid) part after the last slash */
			*pLastSlash = 0;
		}
		else
		{
			if (pPathName[0])
			{
				/* point to root */
				pPathName[0] = PATHSEP;
				pPathName[1] = 0;
			}
			return;
		}
	}
	while (pLastSlash);

	/* Make sure that path name ends with a slash */
	File_AddSlashToEndFileName(pPathName);
}
Beispiel #2
0
DlgFileSelect::DlgFileSelect(SGOBJ *dlg, char *new_path_and_name, bool bAllowNew)
	: Dialog(dlg), path_and_name(new_path_and_name)
	, reloaddir(true), refreshentries(true), selection(-1), ypos(0), eol(true)
	, pressed_ok(false), redraw(true)
{
	gui_file_list = NULL;

	fsdlg[SGFSDLG_FILENAME].type = bAllowNew ? SGEDITFIELD : SGTEXT;

	/* Prepare the path and filename variables */
	File_splitpath(path_and_name, file_path, file_fname, NULL);
	if (strlen(file_path) == 0) {
		assert(getcwd(file_path, sizeof(file_path)) != NULL);
		File_AddSlashToEndFileName(file_path);
	}
	File_ShrinkName(dlgpath, file_path, sizeof(dlgpath)-1);
	File_ShrinkName(dlgfname, file_fname, sizeof(dlgfname)-1);
}
Beispiel #3
0
/**
 * Show and process a file selection dialog.
 * Returns path/name user selected or NULL if user canceled
 * input: zip_path = pointer's pointer to buffer to contain file path
 * within a selected zip file, or NULL if browsing zip files is disallowed.
 * bAllowNew: true if the user is allowed to insert new file names.
 */
char* SDLGui_FileSelect(const char *path_and_name, char **zip_path, bool bAllowNew)
{
	struct dirent **files = NULL;
	char *pStringMem;
	char *retpath = NULL;
	const char *home;
	char *path, *fname;                 /* The actual file and path names */
	bool reloaddir = true;              /* Do we have to reload the directory file list? */
	int retbut;
	bool bOldMouseVisibility;
	int selection;                      /* The selection index */
	char *zipfilename;                  /* Filename in zip file */
	char *zipdir;
	bool browsingzip = false;           /* Are we browsing an archive? */
	zip_dir *zipfiles = NULL;
	SDL_Event sdlEvent;
	int yScrolbar_size;				/* Size of the vertical scrollbar */

	ypos = 0;
	scrollbar_Ypos = 0.0;
	refreshentries = true;
	entries = 0;

	/* Allocate memory for the file and path name strings: */
	pStringMem = malloc(4 * FILENAME_MAX);
	path = pStringMem;
	fname = pStringMem + FILENAME_MAX;
	zipdir = pStringMem + 2 * FILENAME_MAX;
	zipfilename = pStringMem + 3 * FILENAME_MAX;
	zipfilename[0] = 0;
	fname[0] = 0;
	path[0] = 0;

	/* Save mouse state and enable cursor */
	bOldMouseVisibility = SDL_ShowCursor(SDL_QUERY);
	SDL_ShowCursor(SDL_ENABLE);

	SDLGui_CenterDlg(fsdlg);
	if (bAllowNew)
	{
		fsdlg[SGFSDLG_FILENAME].type = SGEDITFIELD;
		fsdlg[SGFSDLG_FILENAME].flags |= SG_EXIT;
	}
	else
	{
		fsdlg[SGFSDLG_FILENAME].type = SGTEXT;
		fsdlg[SGFSDLG_FILENAME].flags &= ~SG_EXIT;
	}

	/* Prepare the path and filename variables */
	if (path_and_name && path_and_name[0])
	{
		strncpy(path, path_and_name, FILENAME_MAX);
		path[FILENAME_MAX-1] = '\0';
	}
	if (!File_DirExists(path))
	{
		File_SplitPath(path, path, fname, NULL);
		if (!(File_DirExists(path) || getcwd(path, FILENAME_MAX)))
		{
			perror("SDLGui_FileSelect: non-existing path and CWD failed");
			goto clean_exit;
		}
	}

	File_MakeAbsoluteName(path);
	File_MakeValidPathName(path);
	File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
	File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);

	do
	{
		if (reloaddir)
		{
			files = files_free(files);

			if (browsingzip)
			{
				files = ZIP_GetFilesDir(zipfiles, zipdir, &entries);
				if(!files)
				{
					fprintf(stderr, "SDLGui_FileSelect: ZIP_GetFilesDir error!\n");
					goto clean_exit;
				}
			}
			else
			{
				/* Load directory entries: */
				entries = scandir(path, &files, 0, alphasort);
			}
			
			/* Remove hidden files from the list if necessary: */
			if (!(fsdlg[SGFSDLG_SHOWHIDDEN].state & SG_SELECTED))
			{
				DlgFileSelect_RemoveHiddenFiles(files);
			}

			if (entries < 0)
			{
				fprintf(stderr, "SDLGui_FileSelect: Path not found.\n");
				goto clean_exit;
			}

			/* reload always implies refresh */
			reloaddir = false;
			refreshentries = true;
		}/* reloaddir */

		/* Refresh scrollbar size */
 		if (entries <= SGFS_NUMENTRIES)
			yScrolbar_size = (SGFS_NUMENTRIES-2) * sdlgui_fontheight;
		else
			yScrolbar_size = (int)((SGFS_NUMENTRIES-2) / ((float)entries/(float)SGFS_NUMENTRIES) * sdlgui_fontheight);
		fsdlg[SGFSDLG_SCROLLBAR].w = yScrolbar_size;
		
		/* Refresh scrolbar pos */
		fsdlg[SGFSDLG_SCROLLBAR].h = (int) (scrollbar_Ypos * sdlgui_fontheight);
		ypos = (int) (scrollbar_Ypos * ((float)entries/(float)(SGFS_NUMENTRIES-2)) + 0.5);
		
		/* Update the file name strings in the dialog? */
		if (refreshentries)
		{
			if (!DlgFileSelect_RefreshEntries(files, path, browsingzip))
			{
				goto clean_exit;
			}
			refreshentries = false;
		}

		/* Show dialog: */
		retbut = SDLGui_DoDialog(fsdlg, &sdlEvent);

		/* Has the user clicked on a file or folder? */
		if (retbut>=SGFSDLG_ENTRYFIRST && retbut<=SGFSDLG_ENTRYLAST && retbut-SGFSDLG_ENTRYFIRST+ypos<entries)
		{
			char *tempstr;
			
			tempstr = malloc(FILENAME_MAX);
			if (!tempstr)
			{
				perror("Error while allocating temporary memory in SDLGui_FileSelect()");
				goto clean_exit;
			}

			if (browsingzip == true)
			{
				if (!strcat_maxlen(tempstr, FILENAME_MAX,
						   zipdir, files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name))
				{
					fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
					goto clean_exit;
				}
				/* directory? */
				if (File_DoesFileNameEndWithSlash(tempstr))
				{
					/* handle the ../ directory */
					if (strcmp(files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name, "../") == 0)
					{
						/* close the zip file */
						if (strcmp(tempstr, "../") == 0)
						{
							/* free zip file entries */
							ZIP_FreeZipDir(zipfiles);
							zipfiles = NULL;
							/* Copy the path name to the dialog */
							File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
							browsingzip = false;
						}
						else
						{
							/* remove "../" and previous dir from path */
							File_PathShorten(tempstr, 2);
							correct_zip_root(tempstr);
							strcpy(zipdir, tempstr);
							File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
						}
					}
					else /* not the "../" directory */
					{
						strcpy(zipdir, tempstr);
						File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
					}
					reloaddir = true;
					/* Copy the path name to the dialog */
					zipfilename[0] = '\0';
					dlgfname[0] = 0;
					ypos = 0;
					scrollbar_Ypos = 0.0;
				}
				else
				{
					/* not dir, select a file in the zip */
					selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
					strcpy(zipfilename, files[selection]->d_name);
					File_ShrinkName(dlgfname, zipfilename, DLGFNAME_SIZE);
				}

			}
			else /* not browsingzip */
			{
				if (!strcat_maxlen(tempstr, FILENAME_MAX,
						   path, files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name))
				{
					fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
					goto clean_exit;
				}
				if (File_DirExists(tempstr))
				{
					File_HandleDotDirs(tempstr);
					File_AddSlashToEndFileName(tempstr);
					/* Copy the path name to the dialog */
					File_ShrinkName(dlgpath, tempstr, DLGPATH_SIZE);
					strcpy(path, tempstr);
					reloaddir = true;
					dlgfname[0] = 0;
					ypos = 0;
					scrollbar_Ypos = 0.0;
				}
				else if (ZIP_FileNameIsZIP(tempstr) && zip_path != NULL)
				{
					/* open a zip file */
					zipfiles = ZIP_GetFiles(tempstr);
					if (zipfiles != NULL && browsingzip == false)
					{
						selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
						strcpy(fname, files[selection]->d_name);
						File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);
						browsingzip = true;
						zipdir[0] = '\0'; /* zip root */
						File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
						reloaddir = true;
						ypos = 0;
						scrollbar_Ypos = 0.0;
					}

				}
				else
				{
					/* Select a file */
					selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
					strcpy(fname, files[selection]->d_name);
					File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);
				}

			} /* not browsingzip */

			free(tempstr);
		}
		else    /* Has the user clicked on another button? */
		{
			switch(retbut)
			{
			case SGFSDLG_UPDIR:                 /* Change path to parent directory */
				if (browsingzip)
				{
					/* close the zip file? */
					if (!zipdir[0])
					{
						/* free zip file entries */
						ZIP_FreeZipDir(zipfiles);
						browsingzip = false;
						zipfiles = NULL;
						File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
					}
					else
					{
						/* remove last dir from zipdir path */
						File_PathShorten(zipdir, 1);
						correct_zip_root(zipdir);
						File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
						zipfilename[0] = '\0';
					}
				}  /* not a zip file: */
				else
				{
					File_PathShorten(path, 1);
					File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
				}
				reloaddir = true;
				break;

			case SGFSDLG_HOMEDIR:               /* Change to home directory */
				home = Paths_GetUserHome();
				if (home == NULL || !*home)
					break;
				if (browsingzip)
				{
					/* free zip file entries */
					ZIP_FreeZipDir(zipfiles);
					zipfiles = NULL;
					browsingzip = false;
				}
				strcpy(path, home);
				File_AddSlashToEndFileName(path);
				File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
				reloaddir = true;
				break;

			case SGFSDLG_ROOTDIR:               /* Change to root directory */
				if (browsingzip)
				{
					/* free zip file entries */
					ZIP_FreeZipDir(zipfiles);
					zipfiles = NULL;
					browsingzip = false;
				}
				path[0] = PATHSEP; path[1] = '\0';
				strcpy(dlgpath, path);
				reloaddir = true;
				break;
			case SGFSDLG_UP:                    /* Scroll up */
				DlgFileSelect_ScrollUp();
				SDL_Delay(10);
				break;
			case SGFSDLG_DOWN:                  /* Scroll down */
				DlgFileSelect_ScrollDown();
				SDL_Delay(10);
				break;
			case SGFSDLG_SCROLLBAR:             /* Scrollbar selected */
				DlgFileSelect_ManageScrollbar();
				SDL_Delay(10);
				break;
			case SGFSDLG_FILENAME:              /* User entered new filename */
				strcpy(fname, dlgfname);
				break;
			case SGFSDLG_SHOWHIDDEN:            /* Show/hide hidden files */
				reloaddir = true;
				ypos = 0;
				scrollbar_Ypos = 0.0;
				break;
			case SDLGUI_UNKNOWNEVENT:
				DlgFileSelect_HandleSdlEvents(&sdlEvent);
				break;
			} /* switch */
      
			if (reloaddir)
			{
				/* Remove old selection */
				fname[0] = 0;
				dlgfname[0] = 0;
				ypos = 0;
				scrollbar_Ypos = 0.0;
			}
		} /* other button code */


	} /* do */
	while (retbut!=SGFSDLG_OKAY && retbut!=SGFSDLG_CANCEL
	       && retbut!=SDLGUI_QUIT && retbut != SDLGUI_ERROR && !bQuitProgram);

	files_free(files);

	if (browsingzip)
	{
		/* free zip file entries */
		ZIP_FreeZipDir(zipfiles);
		zipfiles = NULL;
	}

	if (retbut == SGFSDLG_OKAY)
	{
		if (zip_path)
			*zip_path = zip_get_path(zipdir, zipfilename, browsingzip);
		retpath = File_MakePath(path, fname, NULL);
	}
	else
		retpath = NULL;
clean_exit:
	SDL_ShowCursor(bOldMouseVisibility);
	free(pStringMem);
	return retpath;
}
Beispiel #4
0
int DlgFileSelect::processDialog(void)
{
	int retval = Dialog::GUI_CONTINUE;

	switch (return_obj) {
		case SGFSDLG_UPDIR:
			/* Change path to parent directory */
			if (strlen(file_path) > 2) {
				File_CleanFileName(file_path);
				char *ptr = strrchr(file_path, '/');
				if (ptr)
					*(ptr + 1) = 0;
				File_AddSlashToEndFileName(file_path);
				reloaddir = true;
				/* Copy the path name to the dialog */
				File_ShrinkName(dlgpath, file_path, sizeof(dlgpath)-1);
				/* Remove old selection */
				selection = -1;
				file_fname[0] = 0;
				dlgfname[0] = 0;
				ypos = 0;
			}
			break;
		case SGFSDLG_ROOTDIR:
			/* Change to root directory */
			strcpy(file_path, "/");
			reloaddir = true;
			strcpy(dlgpath, file_path);
			/* Remove old selection */
			selection = -1;
			file_fname[0] = 0;
			dlgfname[0] = 0;
			ypos = 0;
			break;
		case SGFSDLG_UP:
			/* Scroll up */
			if (ypos > 0) {
				--ypos;
				refreshentries = true;
			}
			break;
		case SGFSDLG_DOWN:
			/* Scroll down */
			if (eol == false) {
				++ypos;
				refreshentries = true;
			}
			break;

		case SGFSDLG_OKAY:
			pressed_ok = true;
			confirm();
			// passthrough
		case SGFSDLG_CANCEL:
			retval = Dialog::GUI_CLOSE;
			break;

		default:
			break;
	}

	/* Has the user clicked on a file or folder? */
	if ((return_obj >= SGFSDLG_FIRSTENTRY) && (return_obj <= SGFSDLG_LASTENTRY)) {
		char tempstr[MAX_FILENAME_LENGTH];
		struct stat filestat;
		struct listentry *temp = gui_file_list;
		int i;

		strcpy(tempstr, file_path);
		for (i = 0; i < ((return_obj - SGFSDLG_FIRSTENTRY) + ypos); i++)
			temp = temp->next;
		strcat(tempstr, temp->filename);
		if (stat(tempstr, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
			/* Set the new directory */
			strcpy(file_path, tempstr);
			if (strlen(file_path) >= 3) {
				if ((file_path[strlen(file_path) - 2] == '/')
					&& (file_path[strlen(file_path) - 1] == '.'))
				{
					/* Strip a single dot at the end of the path name */
					file_path[strlen(file_path) - 2] = 0;
				}
				if ((file_path[strlen(file_path) - 3] == '/')
					&& (file_path[strlen(file_path) - 2] == '.')
					&& (file_path[strlen(file_path) - 1] == '.'))
				{
					/* Handle the ".." folder */
					char *ptr;
					if (strlen(file_path) == 3) {
						file_path[1] = 0;
					} else {
						file_path[strlen(file_path) - 3] = 0;
						ptr = strrchr(file_path, '/');
						if (ptr)
							*(ptr + 1) = 0;
					}
				}
			}
			File_AddSlashToEndFileName(file_path);
			reloaddir = true;
			/* Copy the path name to the dialog */
			File_ShrinkName(dlgpath, file_path, sizeof(dlgpath)-1);
			selection = -1;	/* Remove old selection */
			// gui_file_fname[0] = 0;
			dlgfname[0] = 0;
			ypos = 0;
		} else {
			/* Select a file */
			selection = return_obj - SGFSDLG_FIRSTENTRY + ypos;
			strcpy(file_fname, temp->filename);
			File_ShrinkName(dlgfname, file_fname, sizeof(dlgfname)-1);
		}
	}

	if (reloaddir || refreshentries) {
		refreshEntries();
	}

	return retval;
}
Beispiel #5
0
/**
 * Create a clean absolute file name from a (possibly) relative file name.
 * I.e. filter out all occurancies of "./" and "../".
 * pFileName needs to point to a buffer of at least FILENAME_MAX bytes.
 */
void File_MakeAbsoluteName(char *pFileName)
{
	char *pTempName;
	int inpos, outpos;

#if defined (__AMIGAOS4__)
	/* This function does not work on Amiga OS */
	return;
#endif

	inpos = 0;
	pTempName = malloc(FILENAME_MAX);
	if (!pTempName)
	{
		perror("File_MakeAbsoluteName - malloc");
		return;
	}

	/* Is it already an absolute name? */
	if (File_IsRootFileName(pFileName))
	{
		outpos = 0;
	}
	else
	{
		if (!getcwd(pTempName, FILENAME_MAX))
		{
			perror("File_MakeAbsoluteName - getcwd");
			free(pTempName);
			return;
		}
		File_AddSlashToEndFileName(pTempName);
		outpos = strlen(pTempName);
	}

	/* Now filter out the relative paths "./" and "../" */
	while (pFileName[inpos] != 0 && outpos < FILENAME_MAX)
	{
		if (pFileName[inpos] == '.' && pFileName[inpos+1] == PATHSEP)
		{
			/* Ignore "./" */
			inpos += 2;
		}
		else if (pFileName[inpos] == '.' && pFileName[inpos+1] == 0)
		{
			inpos += 1;        /* Ignore "." at the end of the path string */
			if (outpos > 1)
				pTempName[outpos - 1] = 0;   /* Remove the last slash, too */
		}
		else if (pFileName[inpos] == '.' && pFileName[inpos+1] == '.'
		         && (pFileName[inpos+2] == PATHSEP || pFileName[inpos+2] == 0))
		{
			/* Handle "../" */
			char *pSlashPos;
			inpos += 2;
			pTempName[outpos - 1] = 0;
			pSlashPos = strrchr(pTempName, PATHSEP);
			if (pSlashPos)
			{
				*(pSlashPos + 1) = 0;
				outpos = strlen(pTempName);
			}
			else
			{
				pTempName[0] = PATHSEP;
				outpos = 1;
			}
			/* Were we already at the end of the string or is there more to come? */
			if (pFileName[inpos] == PATHSEP)
			{
				/* There was a slash after the '..', so skip slash and
				 * simply proceed with next part */
				inpos += 1;
			}
			else
			{
				/* We were at the end of the string, so let's remove the slash
				 * from the new string, too */
				if (outpos > 1)
					pTempName[outpos - 1] = 0;
			}
		}
		else
		{
			/* Copy until next slash or end of input string */
			while (pFileName[inpos] != 0 && outpos < FILENAME_MAX)
			{
				pTempName[outpos++] = pFileName[inpos++];
				if (pFileName[inpos - 1] == PATHSEP)
					break;
			}
		}
	}

	pTempName[outpos] = 0;

	strcpy(pFileName, pTempName);          /* Copy back */
	free(pTempName);
}