627 lines
18 KiB
C
627 lines
18 KiB
C
/* vim:expandtab:ts=2 sw=2:
|
|
*/
|
|
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
|
|
|
Copyright 2020 Thomas Bernard
|
|
Copyright 2011 Pawel Góralski
|
|
Copyright 2008 Yves Rizoud
|
|
Copyright 2008 Franck Charlet
|
|
Copyright 2007 Adrien Destugues
|
|
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
|
|
|
|
Grafx2 is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; version 2
|
|
of the License.
|
|
|
|
Grafx2 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Grafx2; if not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
///@file osdep.c
|
|
/// OS Dependend code
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if defined(USE_SDL) || defined(USE_SDL2)
|
|
#include <SDL.h>
|
|
#elif !defined(WIN32)
|
|
#include <sys/time.h>
|
|
#endif
|
|
|
|
#if defined(WIN32)
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#if defined(__macosx__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
#include <sys/param.h>
|
|
#include <sys/mount.h>
|
|
#elif defined(__NetBSD__)
|
|
#include <sys/statvfs.h>
|
|
#elif defined (__linux__) || defined(__SYLLABLE__)
|
|
#include <sys/vfs.h>
|
|
#elif defined (__HAIKU__)
|
|
#include "haiku.h"
|
|
#elif defined (__MINT__)
|
|
#include <mint/sysbind.h>
|
|
#include <mint/osbind.h>
|
|
#include <mint/ostruct.h>
|
|
#elif defined(__AROS__)
|
|
#include <sys/mount.h>
|
|
#include <proto/iffparse.h>
|
|
#include <datatypes/textclass.h>
|
|
#endif
|
|
|
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#endif
|
|
|
|
#if defined(__macosx__)
|
|
#import <CoreFoundation/CoreFoundation.h>
|
|
#import <ApplicationServices/ApplicationServices.h>
|
|
#endif
|
|
|
|
#if defined(USE_X11)
|
|
#include <X11/Xlib.h>
|
|
extern Display * X11_display;
|
|
extern Window X11_window;
|
|
#elif defined(__macosx__)
|
|
const char * get_paste_board(void);
|
|
#endif
|
|
#if defined(USE_X11) || defined(USE_SDL) || defined(USE_SDL2)
|
|
#include <string.h>
|
|
#endif
|
|
|
|
#ifdef _MSC_VER
|
|
#define strdup _strdup
|
|
#endif
|
|
|
|
#include "struct.h"
|
|
#include "input.h"
|
|
#include "screen.h"
|
|
#include "unicode.h"
|
|
#include "gfx2log.h"
|
|
#include "gfx2mem.h"
|
|
|
|
dword GFX2_GetTicks(void)
|
|
{
|
|
#if defined(USE_SDL) || defined(USE_SDL2)
|
|
return SDL_GetTicks();
|
|
#elif defined(WIN32)
|
|
return GetTickCount();
|
|
#else
|
|
struct timeval tv;
|
|
if (gettimeofday(&tv, NULL) < 0)
|
|
return 0;
|
|
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
#endif
|
|
}
|
|
|
|
void GFX2_OpenURL(const char * buffer, unsigned int len)
|
|
{
|
|
#if defined(WIN32)
|
|
(void)len;
|
|
/*HINSTANCE hInst = */ShellExecuteA(NULL, "open", buffer, NULL, NULL, SW_SHOWNORMAL);
|
|
#elif defined(__macosx__)
|
|
OSStatus ret;
|
|
|
|
CFURLRef url = CFURLCreateWithBytes (
|
|
NULL, // allocator
|
|
(UInt8*)buffer, // URLBytes
|
|
len, // length
|
|
kCFStringEncodingASCII, // encoding
|
|
NULL // baseURL
|
|
);
|
|
ret = LSOpenCFURLRef(url,0);
|
|
if (ret != noErr)
|
|
GFX2_Log(GFX2_ERROR, "LSOpenCFURLRef() returned %d\n", ret);
|
|
CFRelease(url);
|
|
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
|
int ret;
|
|
char command[256]; // use the xdg-open command to open the url in the default browser
|
|
(void)len;
|
|
|
|
snprintf(command, sizeof(command), "xdg-open \"%s\"", buffer);
|
|
ret = system(command);
|
|
if (ret < 0)
|
|
GFX2_Log(GFX2_ERROR, "system('%s') FAILED\n", command);
|
|
else if (ret == 127)
|
|
GFX2_Log(GFX2_ERROR, "system() FAILED to execute shell\n");
|
|
#else
|
|
// TODO : HAIKU, MINT, etc.
|
|
(void)len; (void)buffer;
|
|
GFX2_Log(GFX2_WARNING, "URL open not supported yet on this system.\n");
|
|
#endif
|
|
}
|
|
|
|
qword GFX2_DiskFreeSpace(const char * path)
|
|
{
|
|
#if defined(__WIN32__) || defined(WIN32)
|
|
ULARGE_INTEGER tailleU, totalbytes, totalfreebytes;
|
|
if (GetDiskFreeSpaceExA(path, &tailleU, &totalbytes, &totalfreebytes))
|
|
{
|
|
GFX2_Log(GFX2_DEBUG, "%s: %luMB free for GrafX2 (total %luMB, %luMB free)\n",
|
|
path, (unsigned long)(tailleU.QuadPart >> 20),
|
|
(unsigned long)(totalbytes.QuadPart >> 20), (unsigned long)(totalfreebytes.QuadPart >> 20));
|
|
return tailleU.QuadPart;
|
|
}
|
|
else
|
|
{
|
|
GFX2_Log(GFX2_ERROR, "GetDiskFreeSpaceExA() failed\n");
|
|
return 0;
|
|
}
|
|
#elif defined(__linux__) || defined(__macosx__) || defined(__FreeBSD__) || defined(__SYLLABLE__) || defined(__AROS__) || defined(__OpenBSD__)
|
|
struct statfs disk_info;
|
|
statfs(path ,&disk_info);
|
|
return (qword) disk_info.f_bfree * (qword) disk_info.f_bsize;
|
|
#elif defined(__NetBSD__)
|
|
struct statvfs disk_info;
|
|
statvfs(path, &disk_info);
|
|
return (qword) disk_info.f_bfree * (qword) disk_info.f_bsize;
|
|
#elif defined(__HAIKU__)
|
|
return haiku_get_free_space(path);
|
|
#elif defined (__MINT__)
|
|
_DISKINFO drvInfo;
|
|
|
|
Dfree(&drvInfo, 0);
|
|
//number of free clusters*sectors per cluster*bytes per sector;
|
|
// reports current drive
|
|
return drvInfo.b_free*drvInfo.b_clsiz*drvInfo.b_secsiz;
|
|
#else
|
|
#define NODISKSPACESUPPORT
|
|
// Free disk space is only for shows. Other platforms can display 0.
|
|
#if !defined(__SWITCH__)
|
|
#warning "Missing code for your platform !!! Check and correct please :)"
|
|
#endif
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#if defined(__macosx__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__SWITCH__)
|
|
#if defined(__OpenBSD__)
|
|
#include <sys/param.h>
|
|
#endif
|
|
#include <sys/types.h>
|
|
#include <sys/sysctl.h>
|
|
#elif defined(__BEOS__) || defined(__HAIKU__)
|
|
#include <kernel/OS.h>
|
|
#elif defined(__AROS__) || defined(__amigaos4__) || defined(__MORPHOS__) || defined(__amigaos__)
|
|
#include <proto/exec.h>
|
|
#elif defined(__MINT__)
|
|
#include <mint/osbind.h>
|
|
#include <mint/sysbind.h>
|
|
#elif defined(__SKYOS__)
|
|
#include <skyos/sysinfo.h>
|
|
#elif !defined(WIN32)
|
|
#include <sys/sysinfo.h> // sysinfo() for free RAM
|
|
#endif
|
|
|
|
#if defined (__MINT__)
|
|
// atari have two kinds of memory
|
|
// standard and fast ram
|
|
void Atari_Memory_free(unsigned long *stRam, unsigned long *ttRam){
|
|
*stRam = Mxalloc(-1L, 0);
|
|
*ttRam = Mxalloc(-1L, 1);
|
|
}
|
|
#else
|
|
// Indique quelle est la mémoire disponible
|
|
unsigned long Memory_free(void)
|
|
{
|
|
// Memory is no longer relevant. If there is ANY problem or doubt here,
|
|
// you can simply return 10*1024*1024 (10Mb), to make the "Pages"something
|
|
// memory allocation functions happy.
|
|
|
|
// However, it is still a good idea to make a proper function if you can...
|
|
// If Grafx2 thinks the memory is full, weird things may happen. And if memory
|
|
// ever becomes full and you're still saying there are 10MB free here, the
|
|
// program will crash without saving any picture backup ! You've been warned...
|
|
#if defined(WIN32)
|
|
#if _WIN32_WINNT >= _WIN32_WINNT_WIN2K
|
|
// GlobalMemoryStatusEx() is supported since Windows 2000
|
|
MEMORYSTATUSEX mstt;
|
|
mstt.dwLength = sizeof(mstt);
|
|
if (GlobalMemoryStatusEx(&mstt))
|
|
{
|
|
GFX2_Log(GFX2_DEBUG, "Phys %lu / %luMB, Page %lu / %luMB, Virtual %lu / %luMB\n",
|
|
(unsigned long)(mstt.ullAvailPhys >> 20), (unsigned long)(mstt.ullTotalPhys >> 20),
|
|
(unsigned long)(mstt.ullAvailPageFile >> 20), (unsigned long)(mstt.ullTotalPageFile >> 20),
|
|
(unsigned long)(mstt.ullAvailVirtual >> 20), (unsigned long)(mstt.ullTotalVirtual >> 20));
|
|
return mstt.ullAvailPhys;
|
|
}
|
|
else
|
|
{
|
|
GFX2_Log(GFX2_ERROR, "GlobalMemoryStatusEx() failed\n");
|
|
return 10*1024*1024;
|
|
}
|
|
#else
|
|
MEMORYSTATUS mstt;
|
|
mstt.dwLength = sizeof(MEMORYSTATUS);
|
|
GlobalMemoryStatus(&mstt);
|
|
return mstt.dwAvailPhys;
|
|
#endif
|
|
#elif defined(__macosx__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
|
int mib[2];
|
|
int maxmem;
|
|
size_t len;
|
|
|
|
mib[0] = CTL_HW;
|
|
mib[1] = HW_USERMEM;
|
|
len = sizeof(maxmem);
|
|
sysctl(mib,2,&maxmem,&len,NULL,0);
|
|
return maxmem;
|
|
#elif defined(__HAIKU__) || defined(__BEOS__)
|
|
int pages;
|
|
system_info systemInfo;
|
|
get_system_info(&systemInfo);
|
|
|
|
pages = systemInfo.max_pages - systemInfo.used_pages;
|
|
return pages * B_PAGE_SIZE;
|
|
#elif defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
|
|
return AvailMem(MEMF_ANY);
|
|
#elif defined(__linux__)
|
|
struct sysinfo info;
|
|
sysinfo(&info);
|
|
return info.freeram*info.mem_unit;
|
|
#else
|
|
// AvailMem is misleading on os4 (os4 caches stuff in memory that you can still allocate)
|
|
#if defined(__SWITCH__)
|
|
// There is some way to get memory information on switch (see include switch/kernel/svc.h svcGetInfo svcGetSystemInfo)
|
|
// but the usage is a bit confusing for the first and the later need privilege to be used.
|
|
// If you come here with a solution, you'r welcome. For now we just return the default value.
|
|
#elif
|
|
#warning "There is missing code there for your platform ! please check and correct :)"
|
|
#endif
|
|
return 10*1024*1024;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if defined(WIN32)
|
|
/**
|
|
* Converts an unicode string to UTF8
|
|
* @param str the unicode string
|
|
* @param utf8len pointer to receive the utf8 string length (excluding null terminator)
|
|
* @return malloc'ed UTF8 string
|
|
*/
|
|
char * Unicode_to_utf8(const word * str, size_t * utf8len)
|
|
{
|
|
size_t unicode_len = Unicode_strlen(str);
|
|
int len = WideCharToMultiByte(CP_UTF8, 0, str, unicode_len, NULL, 0, NULL, NULL);
|
|
if (len <= 0)
|
|
{
|
|
GFX2_Log(GFX2_WARNING, "WideCharToMultiByte() failed\n");
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
char * utf8 = (char *)GFX2_malloc(len+1);
|
|
if (utf8 == NULL)
|
|
return NULL;
|
|
if (WideCharToMultiByte(CP_UTF8, 0, str, unicode_len, utf8, len, NULL, NULL) <= 0)
|
|
{
|
|
DWORD error = GetLastError();
|
|
GFX2_Log(GFX2_WARNING, "WideCharToMultiByte() failed error=%u\n", error);
|
|
free(utf8);
|
|
return NULL;
|
|
}
|
|
if (utf8len != NULL)
|
|
*utf8len = (size_t)len;
|
|
utf8[len] = '\0';
|
|
return utf8;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* UTF8 to Unicode (16bits per character).
|
|
* use MultiByteToWideChar(CP_UTF8, ...) under WIN32.
|
|
* Note : For UTF-8, dwFlags must be set to either 0 or MB_ERR_INVALID_CHARS.
|
|
*/
|
|
void Unicode_from_utf8(const char * utf8, word * unicode, size_t unicodelen)
|
|
{
|
|
int r = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, (LPWSTR)unicode, unicodelen);
|
|
if (r == 0)
|
|
{
|
|
GFX2_Log(GFX2_ERROR, "MultiByteToWideChar(CP_UTF8, \"%s\", ...) failed with error #%u\n", utf8, GetLastError());
|
|
unicode[0] = 0;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/**
|
|
* Get clipboard text content.
|
|
* Inspired from http://www.libsdl.org/projects/scrap/
|
|
* @param unicode NULL for pure ANSI working, or a pointer to get Unicode text data
|
|
* that should be free()'d by the caller
|
|
* @return a ANSI C string that should be free()'d by the caller
|
|
*/
|
|
char * GFX2_GetTextClipboard(word * * unicode)
|
|
{
|
|
#ifdef WIN32
|
|
char* dst = NULL;
|
|
if (OpenClipboard(GFX2_Get_Window_Handle()))
|
|
{
|
|
HANDLE hMem;
|
|
if ( IsClipboardFormatAvailable(CF_TEXT) )
|
|
{
|
|
char *src;
|
|
|
|
hMem = GetClipboardData(CF_TEXT);
|
|
if ( hMem != NULL )
|
|
{
|
|
src = (char *)GlobalLock(hMem);
|
|
dst = strdup(src);
|
|
GlobalUnlock(hMem);
|
|
}
|
|
}
|
|
if (unicode != NULL && IsClipboardFormatAvailable(CF_UNICODETEXT) )
|
|
{
|
|
word * src;
|
|
hMem = GetClipboardData(CF_UNICODETEXT);
|
|
if ( hMem != NULL )
|
|
{
|
|
src = (word *)GlobalLock(hMem);
|
|
*unicode = Unicode_strdup(src);
|
|
GlobalUnlock(hMem);
|
|
}
|
|
}
|
|
CloseClipboard();
|
|
}
|
|
return dst;
|
|
#elif defined(__AROS__)
|
|
|
|
struct IFFHandle *iff = NULL;
|
|
struct ContextNode *cn;
|
|
long error=0, unitnumber=0;
|
|
char *dst = NULL;
|
|
|
|
if (!(iff = AllocIFF ()))
|
|
{
|
|
goto bye;
|
|
}
|
|
|
|
if (!(iff->iff_Stream = (IPTR) OpenClipboard (unitnumber)))
|
|
{
|
|
goto bye;
|
|
}
|
|
|
|
InitIFFasClip (iff);
|
|
|
|
if ((error = OpenIFF (iff, IFFF_READ)) != 0)
|
|
{
|
|
goto bye;
|
|
}
|
|
|
|
if ((error = StopChunk(iff, ID_FTXT, ID_CHRS)) != 0)
|
|
{
|
|
goto bye;
|
|
}
|
|
|
|
while(1)
|
|
{
|
|
error = ParseIFF(iff,IFFPARSE_SCAN);
|
|
if (error) break; // we're reading only the 1st chunk
|
|
|
|
cn = CurrentChunk(iff);
|
|
|
|
if (cn && (cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS))
|
|
{
|
|
if ((dst = malloc(cn->cn_Size + 1)) != NULL)
|
|
{
|
|
dst[0] = '\0';
|
|
if ((ReadChunkBytes(iff,dst,cn->cn_Size)) > 0)
|
|
{
|
|
dst[cn->cn_Size] = '\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bye:
|
|
if (iff)
|
|
{
|
|
CloseIFF (iff);
|
|
|
|
if (iff->iff_Stream)
|
|
CloseClipboard ((struct ClipboardHandle *)iff->iff_Stream);
|
|
FreeIFF (iff);
|
|
}
|
|
|
|
return dst;
|
|
|
|
#elif defined __HAIKU__
|
|
if (unicode)
|
|
*unicode = NULL;
|
|
return haiku_get_clipboard();
|
|
#elif defined(USE_X11) || defined(__macosx__) || defined(USE_SDL2) || (defined(USE_SDL) && defined(SDL_VIDEO_DRIVER_X11) && !defined(NO_X11))
|
|
if (unicode)
|
|
*unicode = NULL;
|
|
#if defined(USE_SDL2)
|
|
if (!SDL_HasClipboardText())
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
char * utf8_str = SDL_GetClipboardText();
|
|
if (utf8_str != NULL)
|
|
{
|
|
#elif defined(USE_X11) || (defined(USE_SDL) && defined(SDL_VIDEO_DRIVER_X11) && !defined(NO_X11))
|
|
{
|
|
int i;
|
|
Atom selection;
|
|
Window selection_owner;
|
|
#if defined(SDL_VIDEO_DRIVER_X11)
|
|
Display * X11_display;
|
|
Window X11_window;
|
|
int old_wmevent_state;
|
|
|
|
if (!GFX2_Get_X11_Display_Window(&X11_display, &X11_window))
|
|
{
|
|
GFX2_Log(GFX2_ERROR, "Failed to get X11 display and window\n");
|
|
return NULL;
|
|
}
|
|
if (X11_display == NULL)
|
|
{
|
|
char video_driver_name[32];
|
|
GFX2_Log(GFX2_WARNING, "X11 display is NULL. X11 is needed for Copy/Paste. SDL video driver is currently %s\n", SDL_VideoDriverName(video_driver_name, sizeof(video_driver_name)));
|
|
return NULL;
|
|
}
|
|
#endif
|
|
selection = XInternAtom(X11_display, "CLIPBOARD", False);
|
|
selection_owner = XGetSelectionOwner(X11_display, selection);
|
|
|
|
if (selection_owner == None)
|
|
{
|
|
selection = XInternAtom(X11_display, "PRIMARY", False);
|
|
selection_owner = XGetSelectionOwner(X11_display, selection);
|
|
}
|
|
if (selection_owner == None)
|
|
return NULL;
|
|
#if defined(USE_SDL)
|
|
old_wmevent_state = SDL_EventState(SDL_SYSWMEVENT, SDL_QUERY);
|
|
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
|
|
#endif
|
|
|
|
XConvertSelection(X11_display, selection, XInternAtom(X11_display, "UTF8_STRING", False),
|
|
XInternAtom(X11_display, "GFX2_CLIP", False), /* Property */
|
|
X11_window, CurrentTime);
|
|
// wait for the event to be received
|
|
for(i = 0; X11_clipboard == NULL && i < 10; i++)
|
|
{
|
|
Get_input(20);
|
|
}
|
|
#if defined(USE_SDL)
|
|
SDL_EventState(SDL_SYSWMEVENT, old_wmevent_state);
|
|
#endif
|
|
if (X11_clipboard != NULL)
|
|
{
|
|
char * utf8_str = X11_clipboard;
|
|
X11_clipboard = NULL;
|
|
X11_clipboard_size = 0;
|
|
X11_clipboard_type = X11_CLIPBOARD_NONE;
|
|
#else
|
|
{
|
|
// mac OS without X11
|
|
const char * utf8_str = get_paste_board();
|
|
if (utf8_str != NULL)
|
|
{
|
|
#endif
|
|
// UTF8 -> UTF16 and UTF8 -> ANSI conversions
|
|
#if defined(ENABLE_FILENAMES_ICONV)
|
|
if (unicode != NULL)
|
|
{
|
|
char * input = (char *)utf8_str;
|
|
size_t inbytesleft = strlen(utf8_str);
|
|
char * output;
|
|
size_t outbytesleft;
|
|
size_t r;
|
|
*unicode = (word *)malloc(2 * inbytesleft + 2);
|
|
if (*unicode != NULL)
|
|
{
|
|
output = (char *)*unicode;
|
|
outbytesleft = 2 * inbytesleft;
|
|
r = iconv(cd_utf16, &input, &inbytesleft, &output, &outbytesleft);
|
|
if (r != (size_t)-1)
|
|
{
|
|
output[1] = output[0] = '\0';
|
|
}
|
|
else
|
|
{
|
|
GFX2_Log(GFX2_WARNING, "Unicode conversion of clipboard text failed\n");
|
|
free(*unicode);
|
|
*unicode = NULL;
|
|
}
|
|
}
|
|
}
|
|
{
|
|
char * ansi_str;
|
|
char * input = (char *)utf8_str;
|
|
size_t inbytesleft = strlen(utf8_str);
|
|
char * output;
|
|
size_t outbytesleft;
|
|
size_t r;
|
|
ansi_str = (char *)malloc(inbytesleft + 1);
|
|
if (ansi_str != NULL)
|
|
{
|
|
output = ansi_str;
|
|
outbytesleft = inbytesleft;
|
|
r = iconv(cd, &input, &inbytesleft, &output, &outbytesleft);
|
|
if (r != (size_t)-1)
|
|
{
|
|
*output = '\0';
|
|
#if defined(USE_X11)
|
|
free(utf8_str);
|
|
#elif defined(USE_SDL2)
|
|
SDL_free(utf8_str);
|
|
#endif
|
|
return ansi_str;
|
|
}
|
|
else
|
|
{
|
|
GFX2_Log(GFX2_WARNING, "ANSI conversion of clipboard text failed\n");
|
|
free(ansi_str);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
// we can get there if the charset conversions failed
|
|
// return the uf8_string, that's better than nothing
|
|
#if defined(USE_X11)
|
|
return utf8_str;
|
|
#elif defined(USE_SDL2)
|
|
{
|
|
char * return_str = strdup(utf8_str);
|
|
SDL_free(utf8_str);
|
|
return return_str;
|
|
}
|
|
#else
|
|
// mac OS without X11
|
|
return strdup(utf8_str);
|
|
#endif
|
|
}
|
|
}
|
|
return NULL;
|
|
#else
|
|
// Not implemented (no standard) on Linux systems. Maybe someday...
|
|
if (unicode)
|
|
*unicode = NULL;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
#if defined(WIN32)
|
|
void GFX2_GetShortPathName(char * shortname, size_t shortname_len, const word * longname)
|
|
{
|
|
DWORD short_len = GetShortPathNameW((WCHAR *)longname, NULL, 0);
|
|
if (short_len > 0)
|
|
{
|
|
WCHAR * temp_str = (WCHAR *)GFX2_malloc(short_len * sizeof(WCHAR));
|
|
short_len = GetShortPathNameW((WCHAR *)longname, temp_str, short_len);
|
|
if (short_len > 0)
|
|
{
|
|
DWORD i;
|
|
for (i = 0; i < short_len && temp_str[i] != 0; i++)
|
|
shortname[i] = temp_str[i];
|
|
shortname[i] = '\0';
|
|
}
|
|
free(temp_str);
|
|
}
|
|
if (short_len == 0)
|
|
{
|
|
// generate a temporary ansi name
|
|
int i;
|
|
for (i = 0; (i < (int)shortname_len - 1) && (longname[i] != 0); i++)
|
|
{
|
|
shortname[i] = (longname[i] < 256) ? (byte)longname[i] : '_';
|
|
}
|
|
shortname[i] = '\0';
|
|
}
|
|
}
|
|
#endif
|