mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
Merge pull request #360 from pryon/UINotepad-fixes
UINotepad fixes and improvements
This commit is contained in:
commit
1fd6c2bd52
11 changed files with 486 additions and 335 deletions
|
@ -83,7 +83,7 @@ void PickFile(const char *name, Listener *obj, Event& event)
|
|||
if (name && *name && strchr(name, '/')) {
|
||||
currentpath = name;
|
||||
|
||||
for (i = currentpath.length(); i > 0; i--) {
|
||||
for (i = currentpath.length() - 1; i > 0; i--) {
|
||||
if (currentpath[i] == '/') {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
#ifndef _WIN32
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <errno.h>
|
||||
# include <dirent.h>
|
||||
#endif
|
||||
|
||||
|
@ -4445,13 +4447,51 @@ void FS_CanonicalFilename(char* filename)
|
|||
*dest = 0;
|
||||
}
|
||||
|
||||
void FS_FileTime(const char* filename, char* date, char* size) {
|
||||
const char* ospath;
|
||||
void FS_FileTime(const char *filename, char *date, char *size)
|
||||
{
|
||||
const char *ospath;
|
||||
struct stat fileStat;
|
||||
int result = -1;
|
||||
|
||||
date[0] = 0;
|
||||
size[0] = 0;
|
||||
date[0] = 0;
|
||||
size[0] = 0;
|
||||
|
||||
ospath = FS_BuildOSPath(fs_homepath->string, fs_gamedir, filename);
|
||||
// Fixed in OPM:
|
||||
// don't only check the home directory (fs_homepath) for possible files,
|
||||
// but look through all searchpaths
|
||||
//ospath = FS_BuildOSPath(fs_homepath->string, fs_gamedir, filename);
|
||||
for (auto search = fs_searchpaths; search; search = search->next) {
|
||||
if (search->dir != NULL && search->dir->path != NULL) {
|
||||
ospath = FS_BuildOSPath(search->dir->path, fs_gamedir, filename);
|
||||
result = stat(ospath, &fileStat);
|
||||
if (result != -1) {
|
||||
// found the valid file
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: unimplemented
|
||||
if (result == -1) {
|
||||
int err = errno;
|
||||
return;
|
||||
}
|
||||
|
||||
time_t modTime = fileStat.st_mtime;
|
||||
off_t fileSize = fileStat.st_size;
|
||||
|
||||
// FIXME: provide option not to use idiotic date formats
|
||||
tm tm = *localtime(&modTime);
|
||||
Q_snprintf(
|
||||
date,
|
||||
128,
|
||||
"%2d/%02d/%04d %2d:%02d%c",
|
||||
tm.tm_mon + 1,
|
||||
tm.tm_mday,
|
||||
tm.tm_year + 1900,
|
||||
(tm.tm_hour + 12) % 12,
|
||||
tm.tm_min,
|
||||
tm.tm_hour < 12 ? 'a' : 'p'
|
||||
);
|
||||
|
||||
Q_snprintf(size, 128, "%ld", fileSize);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
#include "../win_localization.h"
|
||||
#include "../sys_loadlib.h"
|
||||
|
||||
// a pointer to the last piece of data retrieved from the clipboard is stored here,
|
||||
// so that it can be cleaned up when new data is retrieved, preventing memory leaks
|
||||
static void* clipboard_text = NULL;
|
||||
|
||||
static void* game_library = NULL;
|
||||
static void* cgame_library = NULL;
|
||||
qboolean GLimp_SpawnRenderThread(void (*function)(void))
|
||||
|
@ -134,7 +138,36 @@ Sys_GetWholeClipboard
|
|||
*/
|
||||
const char* Sys_GetWholeClipboard(void)
|
||||
{
|
||||
#ifndef DEDICATED
|
||||
char *data = NULL;
|
||||
char *cliptext;
|
||||
|
||||
if ((cliptext = SDL_GetClipboardText()) != NULL) {
|
||||
if (cliptext[0] != NULL) {
|
||||
// It's necessary to limit buffersize to 4096 as each character
|
||||
// is pasted via CharEvent, which is very-very slow and jams up the EventQueue.
|
||||
// A smaller buffer doesn't jam the EventQueue up as much and avoids dropping
|
||||
// characters that otherwise happens when the EventQueue is overloaded.
|
||||
// FIXME: speed up paste logic so this restriction can be removed
|
||||
size_t bufsize = Q_min(strlen(cliptext) + 1, 4096);
|
||||
|
||||
if (clipboard_text != NULL) {
|
||||
// clean up previously allocated clipboard buffer
|
||||
Z_Free(clipboard_text);
|
||||
clipboard_text = NULL;
|
||||
}
|
||||
|
||||
data = clipboard_text = Z_Malloc(bufsize);
|
||||
// Changed in OPM:
|
||||
// original game skips the Windows-specific '\r' (carriage return) char here!
|
||||
Q_strncpyz(data, cliptext, bufsize);
|
||||
}
|
||||
SDL_free(cliptext);
|
||||
}
|
||||
return data;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -142,8 +175,15 @@ const char* Sys_GetWholeClipboard(void)
|
|||
Sys_SetClipboard
|
||||
==============
|
||||
*/
|
||||
void Sys_SetClipboard(const char* contents)
|
||||
void Sys_SetClipboard(const char *contents)
|
||||
{
|
||||
#ifndef DEDICATED
|
||||
if (contents == NULL || contents[0] == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetClipboardText(contents);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -146,26 +146,8 @@ Sys_GetClipboardData
|
|||
*/
|
||||
char *Sys_GetClipboardData(void)
|
||||
{
|
||||
#ifdef DEDICATED
|
||||
return NULL;
|
||||
#else
|
||||
char *data = NULL;
|
||||
char *cliptext;
|
||||
|
||||
if ( ( cliptext = SDL_GetClipboardText() ) != NULL ) {
|
||||
if ( cliptext[0] != '\0' ) {
|
||||
size_t bufsize = strlen( cliptext ) + 1;
|
||||
|
||||
data = Z_Malloc( bufsize );
|
||||
Q_strncpyz( data, cliptext, bufsize );
|
||||
|
||||
// find first listed char and set to '\0'
|
||||
strtok( data, "\n\r\b" );
|
||||
}
|
||||
SDL_free( cliptext );
|
||||
}
|
||||
return data;
|
||||
#endif
|
||||
// unused - actual function is implemented in sys_main_new.c
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEDICATED
|
||||
|
|
|
@ -369,60 +369,76 @@ DIRECTORY SCANNING
|
|||
Sys_ListFilteredFiles
|
||||
==================
|
||||
*/
|
||||
void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles )
|
||||
void Sys_ListFilteredFiles(
|
||||
const char *basedir, char *subdirs, char *filter, qboolean wantsubs, char **list, int *numfiles
|
||||
)
|
||||
{
|
||||
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
|
||||
char filename[MAX_OSPATH];
|
||||
DIR *fdir;
|
||||
struct dirent *d;
|
||||
struct stat st;
|
||||
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
|
||||
char filename[MAX_OSPATH];
|
||||
DIR *fdir;
|
||||
struct dirent *d;
|
||||
struct stat st;
|
||||
|
||||
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
|
||||
return;
|
||||
}
|
||||
if (*numfiles >= MAX_FOUND_FILES - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( basedir[0] == '\0' ) {
|
||||
return;
|
||||
}
|
||||
if (basedir[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs );
|
||||
}
|
||||
else {
|
||||
Com_sprintf( search, sizeof(search), "%s", basedir );
|
||||
}
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf(search, sizeof(search), "%s/%s", basedir, subdirs);
|
||||
} else {
|
||||
Com_sprintf(search, sizeof(search), "%s", basedir);
|
||||
}
|
||||
|
||||
if ((fdir = opendir(search)) == NULL) {
|
||||
return;
|
||||
}
|
||||
if ((fdir = opendir(search)) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ((d = readdir(fdir)) != NULL) {
|
||||
Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
|
||||
if (stat(filename, &st) == -1)
|
||||
continue;
|
||||
while ((d = readdir(fdir)) != NULL) {
|
||||
// Fixed in OPM:
|
||||
// don't show current and parent dir entries twice
|
||||
if (!(Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) && Q_stricmp(d->d_name, "cvs")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (st.st_mode & S_IFDIR) {
|
||||
if (Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) {
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
|
||||
}
|
||||
else {
|
||||
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
|
||||
}
|
||||
Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
|
||||
}
|
||||
}
|
||||
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
|
||||
break;
|
||||
}
|
||||
Com_sprintf( filename, sizeof(filename), "%s/%s", subdirs, d->d_name );
|
||||
if (!Com_FilterPath( filter, filename, qfalse ))
|
||||
continue;
|
||||
list[ *numfiles ] = CopyString( filename );
|
||||
(*numfiles)++;
|
||||
}
|
||||
Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
|
||||
if (stat(filename, &st) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
closedir(fdir);
|
||||
if ((st.st_mode & S_IFDIR) != 0 && wantsubs) {
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf(newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
|
||||
} else {
|
||||
Com_sprintf(newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
|
||||
}
|
||||
|
||||
// recursively iterate into subdirectory
|
||||
Sys_ListFilteredFiles(basedir, newsubdirs, filter, wantsubs, list, numfiles);
|
||||
}
|
||||
|
||||
if (*numfiles >= MAX_FOUND_FILES - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf(filename, sizeof(filename), "%s/%s", subdirs, d->d_name);
|
||||
} else {
|
||||
Q_strncpyz(filename, d->d_name, sizeof(filename));
|
||||
}
|
||||
|
||||
if (!Com_FilterPath(filter, filename, qfalse)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list[*numfiles] = CopyString(filename);
|
||||
(*numfiles)++;
|
||||
}
|
||||
|
||||
closedir(fdir);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -430,104 +446,105 @@ void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, ch
|
|||
Sys_ListFiles
|
||||
==================
|
||||
*/
|
||||
char **Sys_ListFiles( const char *directory, const char *extension, const char *filter, int *numfiles, qboolean wantsubs )
|
||||
char **Sys_ListFiles(const char *directory, const char *extension, const char *filter, int *numfiles, qboolean wantsubs)
|
||||
{
|
||||
struct dirent *d;
|
||||
DIR *fdir;
|
||||
qboolean dironly = wantsubs;
|
||||
char search[MAX_OSPATH];
|
||||
int nfiles;
|
||||
char **listCopy;
|
||||
char *list[MAX_FOUND_FILES];
|
||||
int i;
|
||||
struct stat st;
|
||||
struct dirent *d;
|
||||
DIR *fdir;
|
||||
char search[MAX_OSPATH];
|
||||
int nfiles;
|
||||
char **listCopy;
|
||||
char *list[MAX_FOUND_FILES];
|
||||
int i;
|
||||
struct stat st;
|
||||
char buffer[64];
|
||||
|
||||
int extLen;
|
||||
if (directory[0] == '\0') {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
if (!extension) {
|
||||
extension = "";
|
||||
}
|
||||
|
||||
nfiles = 0;
|
||||
Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
|
||||
// passing a slash as extension will find directories,
|
||||
// anything else looks only for files with that extension
|
||||
if (!filter && (extension[0] != '/' || extension[1])) {
|
||||
Q_snprintf(buffer, sizeof(buffer), "*%s", extension);
|
||||
filter = buffer;
|
||||
}
|
||||
|
||||
list[ nfiles ] = NULL;
|
||||
*numfiles = nfiles;
|
||||
if (filter) {
|
||||
nfiles = 0;
|
||||
Sys_ListFilteredFiles(directory, "", filter, wantsubs, list, &nfiles);
|
||||
|
||||
if (!nfiles)
|
||||
return NULL;
|
||||
list[nfiles] = NULL;
|
||||
*numfiles = nfiles;
|
||||
if (!nfiles) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
|
||||
for ( i = 0 ; i < nfiles ; i++ ) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
listCopy = Z_Malloc((nfiles + 1) * sizeof(*listCopy));
|
||||
for (i = 0; i < nfiles; i++) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
return listCopy;
|
||||
}
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
if ( directory[0] == '\0' ) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
// only enumerate directories from this point onward
|
||||
|
||||
if ( !extension)
|
||||
extension = "";
|
||||
// search
|
||||
nfiles = 0;
|
||||
|
||||
if ( extension[0] == '/' && extension[1] == 0 ) {
|
||||
extension = "";
|
||||
dironly = qtrue;
|
||||
}
|
||||
if ((fdir = opendir(directory)) == NULL) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extLen = strlen( extension );
|
||||
while ((d = readdir(fdir)) != NULL) {
|
||||
Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
|
||||
if (stat(search, &st) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// search
|
||||
nfiles = 0;
|
||||
// Fixed in OPM:
|
||||
// don't show current and parent dir entries twice
|
||||
if (!(Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..") && Q_stricmp(d->d_name, "cvs"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((fdir = opendir(directory)) == NULL) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
if ((st.st_mode & S_IFDIR) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((d = readdir(fdir)) != NULL) {
|
||||
Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
|
||||
if (stat(search, &st) == -1)
|
||||
continue;
|
||||
if ((dironly && !(st.st_mode & S_IFDIR)) ||
|
||||
(!dironly && (st.st_mode & S_IFDIR)))
|
||||
continue;
|
||||
if (nfiles == MAX_FOUND_FILES - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (*extension) {
|
||||
if ( strlen( d->d_name ) < extLen ||
|
||||
Q_stricmp(
|
||||
d->d_name + strlen( d->d_name ) - extLen,
|
||||
extension ) ) {
|
||||
continue; // didn't match
|
||||
}
|
||||
}
|
||||
list[nfiles] = CopyString(d->d_name);
|
||||
nfiles++;
|
||||
}
|
||||
|
||||
if ( nfiles == MAX_FOUND_FILES - 1 )
|
||||
break;
|
||||
list[ nfiles ] = CopyString( d->d_name );
|
||||
nfiles++;
|
||||
}
|
||||
list[nfiles] = NULL;
|
||||
|
||||
list[ nfiles ] = NULL;
|
||||
closedir(fdir);
|
||||
|
||||
closedir(fdir);
|
||||
// return a copy of the list
|
||||
*numfiles = nfiles;
|
||||
|
||||
// return a copy of the list
|
||||
*numfiles = nfiles;
|
||||
if (!nfiles) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( !nfiles ) {
|
||||
return NULL;
|
||||
}
|
||||
listCopy = Z_Malloc((nfiles + 1) * sizeof(*listCopy));
|
||||
for (i = 0; i < nfiles; i++) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
|
||||
for ( i = 0 ; i < nfiles ; i++ ) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
return listCopy;
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -477,56 +477,78 @@ DIRECTORY SCANNING
|
|||
Sys_ListFilteredFiles
|
||||
==============
|
||||
*/
|
||||
void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles )
|
||||
void Sys_ListFilteredFiles(
|
||||
const char *basedir, const char *subdirs, char *filter, qboolean wantsubs, char **list, int *numfiles
|
||||
)
|
||||
{
|
||||
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
|
||||
char filename[MAX_OSPATH];
|
||||
intptr_t findhandle;
|
||||
struct _finddata_t findinfo;
|
||||
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
|
||||
char filename[MAX_OSPATH];
|
||||
intptr_t findhandle;
|
||||
struct _finddata_t findinfo;
|
||||
|
||||
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
|
||||
return;
|
||||
}
|
||||
if (*numfiles >= MAX_FOUND_FILES - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( basedir[0] == '\0' ) {
|
||||
return;
|
||||
}
|
||||
if (basedir[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf( search, sizeof(search), "%s\\%s\\*", basedir, subdirs );
|
||||
}
|
||||
else {
|
||||
Com_sprintf( search, sizeof(search), "%s\\*", basedir );
|
||||
}
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf(search, sizeof(search), "%s\\%s\\*", basedir, subdirs);
|
||||
} else {
|
||||
Com_sprintf(search, sizeof(search), "%s\\*", basedir);
|
||||
}
|
||||
|
||||
findhandle = _findfirst (search, &findinfo);
|
||||
if (findhandle == -1) {
|
||||
return;
|
||||
}
|
||||
findhandle = _findfirst(search, &findinfo);
|
||||
if (findhandle == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (findinfo.attrib & _A_SUBDIR) {
|
||||
if (Q_stricmp(findinfo.name, ".") && Q_stricmp(findinfo.name, "..")) {
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s\\%s", subdirs, findinfo.name);
|
||||
}
|
||||
else {
|
||||
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", findinfo.name);
|
||||
}
|
||||
Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
|
||||
}
|
||||
}
|
||||
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
|
||||
break;
|
||||
}
|
||||
Com_sprintf( filename, sizeof(filename), "%s\\%s", subdirs, findinfo.name );
|
||||
if (!Com_FilterPath( filter, filename, qfalse ))
|
||||
continue;
|
||||
list[ *numfiles ] = CopyString( filename );
|
||||
(*numfiles)++;
|
||||
} while ( _findnext (findhandle, &findinfo) != -1 );
|
||||
do {
|
||||
// Fixed in OPM:
|
||||
// don't show current and parent dir entries twice
|
||||
if (!(Q_stricmp(findinfo.name, ".") && Q_stricmp(findinfo.name, "..") && Q_stricmp(findinfo.name, "cvs"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_findclose (findhandle);
|
||||
if ((findinfo.attrib & _A_SUBDIR) != 0 && wantsubs) {
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf(newsubdirs, sizeof(newsubdirs), "%s\\%s\\*", subdirs, findinfo.name);
|
||||
} else {
|
||||
Com_sprintf(newsubdirs, sizeof(newsubdirs), "%s", findinfo.name);
|
||||
}
|
||||
|
||||
// recursively iterate into subdirectory
|
||||
Sys_ListFilteredFiles(basedir, newsubdirs, filter, wantsubs, list, numfiles);
|
||||
}
|
||||
|
||||
if (*numfiles >= MAX_FOUND_FILES - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strlen(subdirs)) {
|
||||
Com_sprintf(filename, sizeof(filename), "%s\\%s", subdirs, findinfo.name);
|
||||
} else {
|
||||
Q_strncpyz(filename, findinfo.name, sizeof(filename));
|
||||
}
|
||||
|
||||
if (!Com_FilterPath(filter, filename, qfalse)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list[*numfiles] = CopyString(filename);
|
||||
|
||||
// replace backslashes with forward slashes, if any
|
||||
// FS_ReplaceSeparators would be nice but it does the opposite
|
||||
for (char *c = strchr(list[*numfiles], '\\'); c; c = strchr(list[*numfiles], '\\')) {
|
||||
*c = '/';
|
||||
}
|
||||
|
||||
(*numfiles)++;
|
||||
} while (_findnext(findhandle, &findinfo) != -1);
|
||||
|
||||
_findclose(findhandle);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -536,24 +558,24 @@ strgtr
|
|||
*/
|
||||
static qboolean strgtr(const char *s0, const char *s1)
|
||||
{
|
||||
int l0, l1, i;
|
||||
int l0, l1, i;
|
||||
|
||||
l0 = strlen(s0);
|
||||
l1 = strlen(s1);
|
||||
l0 = strlen(s0);
|
||||
l1 = strlen(s1);
|
||||
|
||||
if (l1<l0) {
|
||||
l0 = l1;
|
||||
}
|
||||
if (l1 < l0) {
|
||||
l0 = l1;
|
||||
}
|
||||
|
||||
for(i=0;i<l0;i++) {
|
||||
if (s1[i] > s0[i]) {
|
||||
return qtrue;
|
||||
}
|
||||
if (s1[i] < s0[i]) {
|
||||
return qfalse;
|
||||
}
|
||||
}
|
||||
return qfalse;
|
||||
for (i = 0; i < l0; i++) {
|
||||
if (s1[i] > s0[i]) {
|
||||
return qtrue;
|
||||
}
|
||||
if (s1[i] < s0[i]) {
|
||||
return qfalse;
|
||||
}
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -561,116 +583,121 @@ static qboolean strgtr(const char *s0, const char *s1)
|
|||
Sys_ListFiles
|
||||
==============
|
||||
*/
|
||||
char **Sys_ListFiles( const char *directory, const char *extension, const char *filter, int *numfiles, qboolean wantsubs )
|
||||
char **Sys_ListFiles(const char *directory, const char *extension, const char *filter, int *numfiles, qboolean wantsubs)
|
||||
{
|
||||
char search[MAX_OSPATH];
|
||||
int nfiles;
|
||||
char **listCopy;
|
||||
char *list[MAX_FOUND_FILES];
|
||||
struct _finddata_t findinfo;
|
||||
intptr_t findhandle;
|
||||
int flag;
|
||||
int i;
|
||||
int extLen;
|
||||
char search[MAX_OSPATH];
|
||||
int nfiles;
|
||||
char **listCopy;
|
||||
char *list[MAX_FOUND_FILES] = {NULL};
|
||||
struct _finddata_t findinfo;
|
||||
intptr_t findhandle;
|
||||
qboolean swapped;
|
||||
int i;
|
||||
char buffer[64];
|
||||
|
||||
if (filter) {
|
||||
if (directory[0] == NULL) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nfiles = 0;
|
||||
Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
|
||||
if (!extension) {
|
||||
extension = "";
|
||||
}
|
||||
|
||||
list[ nfiles ] = 0;
|
||||
*numfiles = nfiles;
|
||||
// passing a slash as extension will find directories,
|
||||
// anything else looks only for files with that extension
|
||||
if (!filter && (extension[0] != '/' || extension[1])) {
|
||||
Q_snprintf(buffer, sizeof(buffer), "*%s", extension);
|
||||
filter = buffer;
|
||||
}
|
||||
|
||||
if (!nfiles)
|
||||
return NULL;
|
||||
if (filter) {
|
||||
nfiles = 0;
|
||||
Sys_ListFilteredFiles(directory, "", filter, wantsubs, list, &nfiles);
|
||||
|
||||
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
|
||||
for ( i = 0 ; i < nfiles ; i++ ) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
list[nfiles] = NULL;
|
||||
*numfiles = nfiles;
|
||||
if (!nfiles) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return listCopy;
|
||||
}
|
||||
listCopy = Z_Malloc((nfiles + 1) * sizeof(*listCopy));
|
||||
for (i = 0; i < nfiles; i++) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
if ( directory[0] == '\0' ) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
if ( !extension) {
|
||||
extension = "";
|
||||
}
|
||||
// only enumerate directories from this point onward
|
||||
Com_sprintf(search, 256, "%s\\*", directory);
|
||||
|
||||
// passing a slash as extension will find directories
|
||||
if ( extension[0] == '/' && extension[1] == 0 ) {
|
||||
extension = "";
|
||||
flag = 0;
|
||||
} else {
|
||||
flag = _A_SUBDIR;
|
||||
}
|
||||
// search
|
||||
nfiles = 0;
|
||||
findhandle = _findfirst(search, &findinfo);
|
||||
if (findhandle == -1) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extLen = strlen( extension );
|
||||
do {
|
||||
// Fixed in OPM:
|
||||
// don't show current and parent dir entries twice
|
||||
if (!(Q_stricmp(findinfo.name, ".") && Q_stricmp(findinfo.name, "..") && Q_stricmp(findinfo.name, "cvs"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Com_sprintf( search, sizeof(search), "%s\\*%s", directory, extension );
|
||||
if ((findinfo.attrib & _A_SUBDIR) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// search
|
||||
nfiles = 0;
|
||||
if (nfiles >= MAX_FOUND_FILES - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
findhandle = _findfirst (search, &findinfo);
|
||||
if (findhandle == -1) {
|
||||
*numfiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
list[nfiles] = CopyString(findinfo.name);
|
||||
|
||||
do {
|
||||
if ( (!wantsubs && flag ^ ( findinfo.attrib & _A_SUBDIR )) || (wantsubs && findinfo.attrib & _A_SUBDIR) ) {
|
||||
if (*extension) {
|
||||
if ( strlen( findinfo.name ) < extLen ||
|
||||
Q_stricmp(
|
||||
findinfo.name + strlen( findinfo.name ) - extLen,
|
||||
extension ) ) {
|
||||
continue; // didn't match
|
||||
}
|
||||
}
|
||||
if ( nfiles == MAX_FOUND_FILES - 1 ) {
|
||||
break;
|
||||
}
|
||||
list[ nfiles ] = CopyString( findinfo.name );
|
||||
nfiles++;
|
||||
}
|
||||
} while ( _findnext (findhandle, &findinfo) != -1 );
|
||||
// replace backslashes with forward slashes
|
||||
// FS_ReplaceSeparators would be nice but it does the opposite
|
||||
for (char *c = strchr(list[nfiles], '\\'); c; c = strchr(list[nfiles], '\\')) {
|
||||
*c = '/';
|
||||
}
|
||||
|
||||
list[ nfiles ] = 0;
|
||||
++nfiles;
|
||||
} while (_findnext(findhandle, &findinfo) != -1);
|
||||
|
||||
_findclose (findhandle);
|
||||
list[nfiles] = NULL;
|
||||
|
||||
// return a copy of the list
|
||||
*numfiles = nfiles;
|
||||
_findclose(findhandle);
|
||||
|
||||
if ( !nfiles ) {
|
||||
return NULL;
|
||||
}
|
||||
// return a copy of the list
|
||||
*numfiles = nfiles;
|
||||
|
||||
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
|
||||
for ( i = 0 ; i < nfiles ; i++ ) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
if (!nfiles) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
flag = 0;
|
||||
for(i=1; i<nfiles; i++) {
|
||||
if (strgtr(listCopy[i-1], listCopy[i])) {
|
||||
char *temp = listCopy[i];
|
||||
listCopy[i] = listCopy[i-1];
|
||||
listCopy[i-1] = temp;
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
} while(flag);
|
||||
listCopy = Z_Malloc((nfiles + 1) * sizeof(*listCopy));
|
||||
for (i = 0; i < nfiles; i++) {
|
||||
listCopy[i] = list[i];
|
||||
}
|
||||
listCopy[i] = NULL;
|
||||
|
||||
return listCopy;
|
||||
// bubble-sort name entries alphabetically, in ascending order
|
||||
do {
|
||||
swapped = qfalse;
|
||||
for (i = 1; i < nfiles; i++) {
|
||||
if (strgtr(listCopy[i - 1], listCopy[i])) {
|
||||
char *temp = listCopy[i];
|
||||
listCopy[i] = listCopy[i - 1];
|
||||
listCopy[i - 1] = temp;
|
||||
swapped = qtrue;
|
||||
}
|
||||
}
|
||||
} while (swapped);
|
||||
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -124,6 +124,7 @@ typedef struct uiimport_s {
|
|||
const char *( *Key_KeynumToString )( int keynum );
|
||||
const char *( *GetConfigstring )( int index );
|
||||
void ( *UI_CloseDMConsole )( void );
|
||||
void ( *GetClipboardData )( char *buf, int buflen );
|
||||
} uiimport_t;
|
||||
|
||||
#if 1
|
||||
|
|
|
@ -128,7 +128,13 @@ void UIMultiLineEdit::getData(str& data)
|
|||
data = "";
|
||||
|
||||
for (i = 0, m_lines.IterateFromHead(); m_lines.IsCurrentValid(); i++, m_lines.IterateNext()) {
|
||||
data += m_lines.getCurrent();
|
||||
str text = m_lines.getCurrent();
|
||||
if (i == 0 && !text.length() && m_lines.getCount() <= 1) {
|
||||
// file is empty
|
||||
return;
|
||||
}
|
||||
|
||||
data += text;
|
||||
|
||||
if (i != m_lines.getCount() - 1) {
|
||||
data += "\n";
|
||||
|
@ -213,7 +219,11 @@ void UIMultiLineEdit::Draw(void)
|
|||
// print entire line with the selection highlight box around it
|
||||
DrawBox(0.0f, aty, linewidth, m_font->getHeight(m_bVirtual), selectionBG, 1.f);
|
||||
m_font->setColor(selectionColor);
|
||||
m_font->Print(0, aty, Sys_LV_CL_ConvertString(cur), -1, m_bVirtual);
|
||||
// Fixed in OPM:
|
||||
// don't spam LOCALIZATION ERROR messages to console
|
||||
// for clicking lines in the opened text document
|
||||
//m_font->Print(0, aty, Sys_LV_CL_ConvertString(cur), -1, m_bVirtual);
|
||||
m_font->Print(0, aty, cur, -1, m_bVirtual);
|
||||
} else if (i != topsel->line) {
|
||||
// part of this line is selected, and selection continues/began above
|
||||
if (i == botsel->line) { // sanity check, should always be true
|
||||
|
@ -261,7 +271,11 @@ void UIMultiLineEdit::Draw(void)
|
|||
// no selection or highlighted text
|
||||
caret = m_font->getWidth(cur, topsel->column);
|
||||
m_font->setColor(m_foreground_color);
|
||||
m_font->Print(0, aty, Sys_LV_CL_ConvertString(cur), -1, m_bVirtual);
|
||||
// Fixed in OPM:
|
||||
// don't spam LOCALIZATION ERROR messages to console
|
||||
// for clicking lines in the opened text document
|
||||
//m_font->Print(0, aty, Sys_LV_CL_ConvertString(cur), -1, m_bVirtual);
|
||||
m_font->Print(0, aty, cur, -1, m_bVirtual);
|
||||
} else {
|
||||
// selection starts and ends on this line
|
||||
int toplen = m_font->getWidth(cur, topsel->column); // X coord of highlighting start
|
||||
|
@ -313,6 +327,7 @@ void UIMultiLineEdit::Draw(void)
|
|||
}
|
||||
}
|
||||
|
||||
// num is the ZERO-BASED index of the sought line!
|
||||
str& UIMultiLineEdit::LineFromLineNumber(int num, bool resetpos)
|
||||
{
|
||||
static str emptyLine;
|
||||
|
@ -349,9 +364,7 @@ void UIMultiLineEdit::PointToSelectionPoint(const UIPoint2D& p, selectionpoint_t
|
|||
float lastWidth = 0;
|
||||
|
||||
clickedLine = m_vertscroll->getTopItem() + p.y / m_font->getHeight(m_bVirtual);
|
||||
if (clickedLine >= m_lines.getCount()) {
|
||||
clickedLine = m_lines.getCount() - 1;
|
||||
}
|
||||
clickedLine = Q_min(clickedLine, m_lines.getCount() - 1);
|
||||
|
||||
if (clickedLine < 0) {
|
||||
sel.line = 0;
|
||||
|
@ -360,12 +373,12 @@ void UIMultiLineEdit::PointToSelectionPoint(const UIPoint2D& p, selectionpoint_t
|
|||
}
|
||||
|
||||
const char *line = LineFromLineNumber(clickedLine, true).c_str();
|
||||
for (i = 0; i < line[i] && totalWidth < p.x; i++) {
|
||||
for (i = 0; line[i] && totalWidth < p.x; i++) {
|
||||
lastWidth = m_font->getCharWidth(line[i]);
|
||||
totalWidth += lastWidth;
|
||||
}
|
||||
|
||||
if (i < line[i] && i) {
|
||||
if (line[i] && i) {
|
||||
lastWidth *= 0.5f;
|
||||
if (totalWidth - lastWidth >= p.x) {
|
||||
i--;
|
||||
|
@ -448,7 +461,10 @@ void UIMultiLineEdit::EnsureSelectionPointVisible(selectionpoint_t& point)
|
|||
|
||||
void UIMultiLineEdit::BoundSelectionPoint(selectionpoint_t& point)
|
||||
{
|
||||
point.line = Q_clamp_int(point.line, 0, m_lines.getCount());
|
||||
// since LineFromLineNumber expects a zero-based line index,
|
||||
// clamp it to one less than the number of lines if the selection point
|
||||
// is right at the end of the text document
|
||||
point.line = Q_clamp_int(point.line, 0, m_lines.getCount() - 1);
|
||||
|
||||
str& line = LineFromLineNumber(point.line, true);
|
||||
point.column = Q_clamp_int(point.column, 0, line.length());
|
||||
|
@ -618,7 +634,7 @@ void UIMultiLineEdit::DeleteSelection(void)
|
|||
EnsureSelectionPointVisible(*topsel);
|
||||
return;
|
||||
} else if (botsel->line - topsel->line > 1) {
|
||||
for (i = 0, m_lines.IterateFromHead(); m_lines.IsCurrentValid() && i < topsel->line;
|
||||
for (i = 0, m_lines.IterateFromHead(); m_lines.IsCurrentValid() && i < botsel->line;
|
||||
i++, m_lines.IterateNext()) {
|
||||
if (i > topsel->line) {
|
||||
m_lines.RemoveCurrentSetPrev();
|
||||
|
@ -630,12 +646,19 @@ void UIMultiLineEdit::DeleteSelection(void)
|
|||
|
||||
for (i = 0, m_lines.IterateFromHead(); m_lines.IsCurrentValid() && i < topsel->line; i++, m_lines.IterateNext()) {}
|
||||
|
||||
// delete topmost line of the selection, but only up to topsel->column
|
||||
str& topline = m_lines.getCurrent();
|
||||
topline.CapLength(topsel->column);
|
||||
if (topline.length() > topsel->column) {
|
||||
topline.CapLength(topsel->column);
|
||||
}
|
||||
m_lines.IterateNext();
|
||||
str& line = m_lines.getCurrent();
|
||||
str line = m_lines.getCurrent();
|
||||
|
||||
// merge remainder of topmost line with the remainder after the end of selection
|
||||
if (line.length() > botsel->column) {
|
||||
topline += &line[botsel->column];
|
||||
}
|
||||
|
||||
topline += &line[botsel->column];
|
||||
m_lines.RemoveCurrentSetPrev();
|
||||
*botsel = *topsel;
|
||||
m_vertscroll->setNumItems(m_lines.getCount());
|
||||
|
@ -675,8 +698,11 @@ void UIMultiLineEdit::CharEvent(int ch)
|
|||
m_changed = true;
|
||||
|
||||
str& line = LineFromLineNumber(m_selection.begin.line, false);
|
||||
str otherline = &line[m_selection.begin.column];
|
||||
otherline.CapLength(m_selection.begin.column);
|
||||
str otherline = "";
|
||||
if (line.length() > m_selection.begin.column) {
|
||||
otherline = &line[m_selection.begin.column];
|
||||
line.CapLength(m_selection.begin.column);
|
||||
}
|
||||
|
||||
if (m_lines.IsCurrentValid()) {
|
||||
m_lines.InsertAfterCurrent(otherline);
|
||||
|
@ -714,21 +740,24 @@ void UIMultiLineEdit::CopySelection(void)
|
|||
|
||||
line = LineFromLineNumber(topsel->line, true);
|
||||
|
||||
clipText += &line[topsel->column];
|
||||
if (line.length() > topsel->column) {
|
||||
clipText += &line[topsel->column];
|
||||
}
|
||||
|
||||
if (topsel->line == botsel->line) {
|
||||
clipText.CapLength(botsel->column - topsel->column);
|
||||
} else {
|
||||
for (int i = topsel->line + 1; i < botsel->line; ++i) {
|
||||
clipText += LineFromLineNumber(i, 1);
|
||||
clipText += "\n" + LineFromLineNumber(i, 1);
|
||||
}
|
||||
|
||||
line = LineFromLineNumber(botsel->line, true);
|
||||
line.CapLength(botsel->column);
|
||||
if (line.length() > botsel->column) {
|
||||
line.CapLength(botsel->column);
|
||||
}
|
||||
clipText += "\n" + line;
|
||||
}
|
||||
|
||||
// FIXME: clipboard not implemented yet
|
||||
uii.Sys_SetClipboard(clipText);
|
||||
}
|
||||
|
||||
|
@ -737,12 +766,11 @@ void UIMultiLineEdit::PasteSelection(void)
|
|||
str sel;
|
||||
int i;
|
||||
|
||||
// temporary variable added in OPM as str cannot handle NULL assignment
|
||||
// will be removed when Sys_GetClipboard is properly implemented
|
||||
// variable added in OPM as str cannot handle NULL assignment
|
||||
// we can get NULL here if clipboard is empty/couldn't be retrieved
|
||||
const char *clipboardData = uii.Sys_GetClipboard();
|
||||
if (clipboardData == NULL)
|
||||
{
|
||||
// FIXME: clipboard not implemented yet
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -753,8 +781,17 @@ void UIMultiLineEdit::PasteSelection(void)
|
|||
for (i = 0; i < sel.length(); i++) {
|
||||
if (sel[i] == '\n') {
|
||||
CharEvent('\r');
|
||||
} else if (sel[i] == '\r') {
|
||||
// Changed in OPM:
|
||||
// NOP, drop CR characters.
|
||||
// On Linux/Mac they aren't present anyway,
|
||||
// on Windows we already have LF chars next to them.
|
||||
// The filtering for CR on the Windows side was originally done
|
||||
// in Sys_GetWholeClipboard with a "manual" selective strcpy,
|
||||
// but here we iterate over all characters of the clipboard anyways,
|
||||
// so this feels like a better place to do the filtering.
|
||||
} else {
|
||||
CharEvent(sel[i]);
|
||||
CharEvent(sel[i]); // FIXME: this is VERY slow and jams up the EventQueue!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -303,14 +303,7 @@ UINotepad::~UINotepad()
|
|||
for (int j = inner->NumObjects(); j > 0; j--) {
|
||||
uipopup_describe *uipd = inner->ObjectAt(j);
|
||||
inner->RemoveObjectAt(j);
|
||||
// NOTE: `delete uipd` is intentionally missing here!
|
||||
// Since uipds created for this class have data fields
|
||||
// that contain pointers only to static Event objects,
|
||||
// the fields don't need to be cleaned up as they weren't
|
||||
// dynamically allocated in the first place.
|
||||
// See UINotepad::Create for reference.
|
||||
// However, FIXME: the uipds themselves should still
|
||||
// get cleaned up, but that doesn't happen yet.
|
||||
delete uipd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -431,13 +424,16 @@ void UINotepad::Save(Event *ev)
|
|||
{
|
||||
if (!m_filename.length()) {
|
||||
SaveAs(NULL);
|
||||
// Fixed in OPM:
|
||||
// devs probably forgot to return here - saving was attempted,
|
||||
// even though there was no filename to save the file with
|
||||
return;
|
||||
}
|
||||
|
||||
str filecontents;
|
||||
m_edit->getData(filecontents);
|
||||
m_edit->setChanged(false);
|
||||
|
||||
// FIXME: m_filename could be blank
|
||||
FS_WriteTextFile(m_filename, filecontents, filecontents.length());
|
||||
|
||||
str result = "Saved " + m_filename;
|
||||
|
|
|
@ -68,12 +68,19 @@ uipopup_describe::uipopup_describe
|
|||
inline
|
||||
uipopup_describe::~uipopup_describe()
|
||||
{
|
||||
if (this->data)
|
||||
{
|
||||
// clean up strdup'd C-string from memory
|
||||
free(this->data);
|
||||
this->data = NULL;
|
||||
}
|
||||
if (this->data == NULL) {
|
||||
// nothing to clean up
|
||||
return;
|
||||
}
|
||||
|
||||
// only clean up these types of uipds, because:
|
||||
// - UIP_EVENT types point to static Event instances,
|
||||
// - UIP_EVENT_STRING types point to already freed Event instances
|
||||
if (this->type == UIP_CMD || this->type == UIP_CVAR) {
|
||||
// clean up strdup'd C-string from memory
|
||||
free(this->data);
|
||||
this->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
class UIPopupMenu : public UIWidget {
|
||||
|
|
|
@ -344,7 +344,11 @@ void UIVertScroll::MouseEnter
|
|||
)
|
||||
|
||||
{
|
||||
uWinMan.ActivateControl(this);
|
||||
// Fixed in OPM
|
||||
// Why should hovering over the scrollbar activate the control it's on?
|
||||
// This is more disorienting than useful, also no sane window manager
|
||||
// works like this. Simply clicking into it should be sufficient.
|
||||
//uWinMan.ActivateControl(this);
|
||||
}
|
||||
|
||||
void UIVertScroll::MouseLeave
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue