blob: d02f304702a339823c126828340a1da1897d534f [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "DFPlatform.h"
// This file contains functions that are applicable to Windows
#ifdef _WINDOWS
#include <windows.h>
#include <SDL_image.h>
#include <stdio.h>
static void DFErrorMsgSetWin32(char **errmsg, DWORD code)
{
if (errmsg == NULL)
return;
char *lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
size_t len = strlen(lpMsgBuf);
while ((len > 0) &&
((lpMsgBuf[len - 1] == '\n') ||
(lpMsgBuf[len - 1] == '\r') ||
(lpMsgBuf[len - 1] == '.')))
len--;
lpMsgBuf[len] = '\0';
*errmsg = xstrdup(lpMsgBuf);
LocalFree(lpMsgBuf);
}
HANDLE onceMutex = NULL;
static int testAndSet(int *var,int value,HANDLE lock)
{
WaitForSingleObject(lock,INFINITE);
int oldValue = *var;
*var = value;
ReleaseMutex(lock);
return oldValue;
}
static BOOL CALLBACK initOnceMutex(PINIT_ONCE initOnce,PVOID Parameter,PVOID *Context)
{
onceMutex = CreateMutex(NULL,FALSE,NULL);
return TRUE;
}
void DFInitOnce(DFOnce *once, DFOnceFunction fun)
{
static INIT_ONCE initOnce = INIT_ONCE_STATIC_INIT;
InitOnceExecuteOnce(&initOnce,initOnceMutex,NULL,NULL);
if (testAndSet(once,1,onceMutex) == 0)
fun();
}
int DFMkdirIfAbsent(const char *path, char **errmsg)
{
if (!CreateDirectory(path,NULL) && (GetLastError() != ERROR_ALREADY_EXISTS)) {
DFErrorMsgSetWin32(errmsg,GetLastError());
return 0;
}
return 1;
}
int DFAddDirContents(const char *absPath, const char *relPath, int recursive, DFDirEntryList ***list, char **errmsg)
{
DFDirEntryList **listptr = *list;
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
size_t patternLen = strlen(absPath) + 2;
char *pattern = (char *)xmalloc(patternLen+1);
snprintf(pattern,patternLen+1,"%s/*",absPath);
hFind = FindFirstFile(pattern,&ffd);
if (hFind == INVALID_HANDLE_VALUE) {
DFErrorMsgSetWin32(errmsg,GetLastError());
free(pattern);
return 0;
}
int ok = 1;
do {
if (!strcmp(ffd.cFileName,".") || !strcmp(ffd.cFileName,".."))
continue;
size_t absSubPathLen = strlen(absPath) + 1 + strlen(ffd.cFileName);
size_t relSubPathLen = strlen(relPath) + 1 + strlen(ffd.cFileName);
char *absSubPath = (char *)xmalloc(absSubPathLen+1);
char *relSubPath = (char *)xmalloc(relSubPathLen+1);
snprintf(absSubPath,absSubPathLen+1,"%s/%s",absPath,ffd.cFileName);
snprintf(relSubPath,relSubPathLen+1,"%s/%s",relPath,ffd.cFileName);
char *entryName;
if (relSubPath[0] == '/')
entryName = &relSubPath[1];
else
entryName = relSubPath;
*listptr = (DFDirEntryList *)xcalloc(1,sizeof(DFDirEntryList));
(*listptr)->name = xstrdup(entryName);
listptr = &(*listptr)->next;
if (recursive && (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
ok = DFAddDirContents(absSubPath,relSubPath,recursive,&listptr,errmsg);
free(absSubPath);
free(relSubPath);
} while (ok && (FindNextFile(hFind,&ffd) != 0));
FindClose(hFind);
free(pattern);
*list = listptr;
return ok;
}
int DFGetImageDimensions(const void *data, size_t len, const char *ext,
unsigned int *width, unsigned int *height, char **errmsg)
{
SDL_Surface *image = IMG_Load_RW(SDL_RWFromMem((void *)data,(int)len),1);
if (image == NULL) {
if (errmsg != NULL)
*errmsg = xstrdup(IMG_GetError());
return 0;
}
*width = (unsigned int)image->w;
*height = (unsigned int)image->h;
SDL_FreeSurface(image);
return 1;
}
#endif