win32.cpp

Go to the documentation of this file.
00001 /* $Id: win32.cpp 18424 2009-12-07 17:13:28Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD 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.
00006  * OpenTTD 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.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "../../stdafx.h"
00013 #include "../../debug.h"
00014 #include "../../gfx_func.h"
00015 #include "../../textbuf_gui.h"
00016 #include "../../fileio_func.h"
00017 #include "../../fios.h"
00018 #include <windows.h>
00019 #include <fcntl.h>
00020 #include <shlobj.h> /* SHGetFolderPath */
00021 #include "win32.h"
00022 #include "../../core/alloc_func.hpp"
00023 #include "../../functions.h"
00024 #include "../../core/random_func.hpp"
00025 #include "../../string_func.h"
00026 #include "../../crashlog.h"
00027 #include <errno.h>
00028 #include <sys/stat.h>
00029 
00030 static bool _has_console;
00031 
00032 static bool cursor_visible = true;
00033 
00034 bool MyShowCursor(bool show)
00035 {
00036   if (cursor_visible == show) return show;
00037 
00038   cursor_visible = show;
00039   ShowCursor(show);
00040 
00041   return !show;
00042 }
00043 
00047 bool LoadLibraryList(Function proc[], const char *dll)
00048 {
00049   while (*dll != '\0') {
00050     HMODULE lib;
00051     lib = LoadLibrary(MB_TO_WIDE(dll));
00052 
00053     if (lib == NULL) return false;
00054     for (;;) {
00055       FARPROC p;
00056 
00057       while (*dll++ != '\0') { /* Nothing */ }
00058       if (*dll == '\0') break;
00059 #if defined(WINCE)
00060       p = GetProcAddress(lib, MB_TO_WIDE(dll));
00061 #else
00062       p = GetProcAddress(lib, dll);
00063 #endif
00064       if (p == NULL) return false;
00065       *proc++ = (Function)p;
00066     }
00067     dll++;
00068   }
00069   return true;
00070 }
00071 
00072 void ShowOSErrorBox(const char *buf, bool system)
00073 {
00074   MyShowCursor(true);
00075   MessageBox(GetActiveWindow(), MB_TO_WIDE(buf), _T("Error!"), MB_ICONSTOP);
00076 }
00077 
00078 /* Code below for windows version of opendir/readdir/closedir copied and
00079  * modified from Jan Wassenberg's GPL implementation posted over at
00080  * http://www.gamedev.net/community/forums/topic.asp?topic_id=364584&whichpage=1&#2398903 */
00081 
00082 /* suballocator - satisfies most requests with a reusable static instance.
00083  * this avoids hundreds of alloc/free which would fragment the heap.
00084  * To guarantee concurrency, we fall back to malloc if the instance is
00085  * already in use (it's important to avoid suprises since this is such a
00086  * low-level routine). */
00087 static DIR _global_dir;
00088 static LONG _global_dir_is_in_use = false;
00089 
00090 static inline DIR *dir_calloc()
00091 {
00092   DIR *d;
00093 
00094   if (InterlockedExchange(&_global_dir_is_in_use, true) == (LONG)true) {
00095     d = CallocT<DIR>(1);
00096   } else {
00097     d = &_global_dir;
00098     memset(d, 0, sizeof(*d));
00099   }
00100   return d;
00101 }
00102 
00103 static inline void dir_free(DIR *d)
00104 {
00105   if (d == &_global_dir) {
00106     _global_dir_is_in_use = (LONG)false;
00107   } else {
00108     free(d);
00109   }
00110 }
00111 
00112 DIR *opendir(const TCHAR *path)
00113 {
00114   DIR *d;
00115   UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box
00116   DWORD fa = GetFileAttributes(path);
00117 
00118   if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) {
00119     d = dir_calloc();
00120     if (d != NULL) {
00121       TCHAR search_path[MAX_PATH];
00122       bool slash = path[_tcslen(path) - 1] == '\\';
00123 
00124       /* build search path for FindFirstFile, try not to append additional slashes
00125        * as it throws Win9x off its groove for root directories */
00126       _sntprintf(search_path, lengthof(search_path), _T("%s%s*"), path, slash ? _T("") : _T("\\"));
00127       *lastof(search_path) = '\0';
00128       d->hFind = FindFirstFile(search_path, &d->fd);
00129 
00130       if (d->hFind != INVALID_HANDLE_VALUE ||
00131           GetLastError() == ERROR_NO_MORE_FILES) { // the directory is empty
00132         d->ent.dir = d;
00133         d->at_first_entry = true;
00134       } else {
00135         dir_free(d);
00136         d = NULL;
00137       }
00138     } else {
00139       errno = ENOMEM;
00140     }
00141   } else {
00142     /* path not found or not a directory */
00143     d = NULL;
00144     errno = ENOENT;
00145   }
00146 
00147   SetErrorMode(sem); // restore previous setting
00148   return d;
00149 }
00150 
00151 struct dirent *readdir(DIR *d)
00152 {
00153   DWORD prev_err = GetLastError(); // avoid polluting last error
00154 
00155   if (d->at_first_entry) {
00156     /* the directory was empty when opened */
00157     if (d->hFind == INVALID_HANDLE_VALUE) return NULL;
00158     d->at_first_entry = false;
00159   } else if (!FindNextFile(d->hFind, &d->fd)) { // determine cause and bail
00160     if (GetLastError() == ERROR_NO_MORE_FILES) SetLastError(prev_err);
00161     return NULL;
00162   }
00163 
00164   /* This entry has passed all checks; return information about it.
00165    * (note: d_name is a pointer; see struct dirent definition) */
00166   d->ent.d_name = d->fd.cFileName;
00167   return &d->ent;
00168 }
00169 
00170 int closedir(DIR *d)
00171 {
00172   FindClose(d->hFind);
00173   dir_free(d);
00174   return 0;
00175 }
00176 
00177 bool FiosIsRoot(const char *file)
00178 {
00179   return file[3] == '\0'; // C:\...
00180 }
00181 
00182 void FiosGetDrives()
00183 {
00184 #if defined(WINCE)
00185   /* WinCE only knows one drive: / */
00186   FiosItem *fios = _fios_items.Append();
00187   fios->type = FIOS_TYPE_DRIVE;
00188   fios->mtime = 0;
00189   snprintf(fios->name, lengthof(fios->name), PATHSEP "");
00190   strecpy(fios->title, fios->name, lastof(fios->title));
00191 #else
00192   TCHAR drives[256];
00193   const TCHAR *s;
00194 
00195   GetLogicalDriveStrings(lengthof(drives), drives);
00196   for (s = drives; *s != '\0';) {
00197     FiosItem *fios = _fios_items.Append();
00198     fios->type = FIOS_TYPE_DRIVE;
00199     fios->mtime = 0;
00200     snprintf(fios->name, lengthof(fios->name),  "%c:", s[0] & 0xFF);
00201     strecpy(fios->title, fios->name, lastof(fios->title));
00202     while (*s++ != '\0') { /* Nothing */ }
00203   }
00204 #endif
00205 }
00206 
00207 bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
00208 {
00209   /* hectonanoseconds between Windows and POSIX epoch */
00210   static const int64 posix_epoch_hns = 0x019DB1DED53E8000LL;
00211   const WIN32_FIND_DATA *fd = &ent->dir->fd;
00212 
00213   sb->st_size  = ((uint64) fd->nFileSizeHigh << 32) + fd->nFileSizeLow;
00214   /* UTC FILETIME to seconds-since-1970 UTC
00215    * we just have to subtract POSIX epoch and scale down to units of seconds.
00216    * http://www.gamedev.net/community/forums/topic.asp?topic_id=294070&whichpage=1&#1860504
00217    * XXX - not entirely correct, since filetimes on FAT aren't UTC but local,
00218    * this won't entirely be correct, but we use the time only for comparsion. */
00219   sb->st_mtime = (time_t)((*(uint64*)&fd->ftLastWriteTime - posix_epoch_hns) / 1E7);
00220   sb->st_mode  = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? S_IFDIR : S_IFREG;
00221 
00222   return true;
00223 }
00224 
00225 bool FiosIsHiddenFile(const struct dirent *ent)
00226 {
00227   return (ent->dir->fd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0;
00228 }
00229 
00230 bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
00231 {
00232   UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS);  // disable 'no-disk' message box
00233   bool retval = false;
00234   TCHAR root[4];
00235   DWORD spc, bps, nfc, tnc;
00236 
00237   _sntprintf(root, lengthof(root), _T("%c:") _T(PATHSEP), path[0]);
00238   if (tot != NULL && GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) {
00239     *tot = ((spc * bps) * (uint64)nfc);
00240     retval = true;
00241   }
00242 
00243   SetErrorMode(sem); // reset previous setting
00244   return retval;
00245 }
00246 
00247 static int ParseCommandLine(char *line, char **argv, int max_argc)
00248 {
00249   int n = 0;
00250 
00251   do {
00252     /* skip whitespace */
00253     while (*line == ' ' || *line == '\t') line++;
00254 
00255     /* end? */
00256     if (*line == '\0') break;
00257 
00258     /* special handling when quoted */
00259     if (*line == '"') {
00260       argv[n++] = ++line;
00261       while (*line != '"') {
00262         if (*line == '\0') return n;
00263         line++;
00264       }
00265     } else {
00266       argv[n++] = line;
00267       while (*line != ' ' && *line != '\t') {
00268         if (*line == '\0') return n;
00269         line++;
00270       }
00271     }
00272     *line++ = '\0';
00273   } while (n != max_argc);
00274 
00275   return n;
00276 }
00277 
00278 void CreateConsole()
00279 {
00280 #if defined(WINCE)
00281   /* WinCE doesn't support console stuff */
00282 #else
00283   HANDLE hand;
00284   CONSOLE_SCREEN_BUFFER_INFO coninfo;
00285 
00286   if (_has_console) return;
00287   _has_console = true;
00288 
00289   AllocConsole();
00290 
00291   hand = GetStdHandle(STD_OUTPUT_HANDLE);
00292   GetConsoleScreenBufferInfo(hand, &coninfo);
00293   coninfo.dwSize.Y = 500;
00294   SetConsoleScreenBufferSize(hand, coninfo.dwSize);
00295 
00296   /* redirect unbuffered STDIN, STDOUT, STDERR to the console */
00297 #if !defined(__CYGWIN__)
00298   *stdout = *_fdopen( _open_osfhandle((intptr_t)hand, _O_TEXT), "w" );
00299   *stdin = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "r" );
00300   *stderr = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" );
00301 #else
00302   /* open_osfhandle is not in cygwin */
00303   *stdout = *fdopen(1, "w" );
00304   *stdin = *fdopen(0, "r" );
00305   *stderr = *fdopen(2, "w" );
00306 #endif
00307 
00308   setvbuf(stdin, NULL, _IONBF, 0);
00309   setvbuf(stdout, NULL, _IONBF, 0);
00310   setvbuf(stderr, NULL, _IONBF, 0);
00311 #endif
00312 }
00313 
00315 static const char *_help_msg;
00316 
00318 static INT_PTR CALLBACK HelpDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
00319 {
00320   switch (msg) {
00321     case WM_INITDIALOG: {
00322       char help_msg[8192];
00323       const char *p = _help_msg;
00324       char *q = help_msg;
00325       while (q != lastof(help_msg) && *p != '\0') {
00326         if (*p == '\n') {
00327           *q++ = '\r';
00328           if (q == lastof(help_msg)) {
00329             q[-1] = '\0';
00330             break;
00331           }
00332         }
00333         *q++ = *p++;
00334       }
00335       *q = '\0';
00336 #if defined(UNICODE)
00337       /* We need to put the text in a seperate buffer because the default
00338        * buffer in MB_TO_WIDE might not be large enough (512 chars) */
00339       wchar_t help_msgW[8192];
00340 #endif
00341       SetDlgItemText(wnd, 11, MB_TO_WIDE_BUFFER(help_msg, help_msgW, lengthof(help_msgW)));
00342       SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE);
00343     } return TRUE;
00344 
00345     case WM_COMMAND:
00346       if (wParam == 12) ExitProcess(0);
00347       return TRUE;
00348     case WM_CLOSE:
00349       ExitProcess(0);
00350   }
00351 
00352   return FALSE;
00353 }
00354 
00355 void ShowInfo(const char *str)
00356 {
00357   if (_has_console) {
00358     fprintf(stderr, "%s\n", str);
00359   } else {
00360     bool old;
00361     ReleaseCapture();
00362     _left_button_clicked = _left_button_down = false;
00363 
00364     old = MyShowCursor(true);
00365     if (strlen(str) > 2048) {
00366       /* The minimum length of the help message is 2048. Other messages sent via
00367        * ShowInfo are much shorter, or so long they need this way of displaying
00368        * them anyway. */
00369       _help_msg = str;
00370       DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(101), NULL, HelpDialogFunc);
00371     } else {
00372 #if defined(UNICODE)
00373       /* We need to put the text in a seperate buffer because the default
00374        * buffer in MB_TO_WIDE might not be large enough (512 chars) */
00375       wchar_t help_msgW[8192];
00376 #endif
00377       if (MessageBox(GetActiveWindow(), MB_TO_WIDE_BUFFER(str, help_msgW, lengthof(help_msgW)), _T("OpenTTD"), MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) {
00378         CreateConsole();
00379       }
00380     }
00381     MyShowCursor(old);
00382   }
00383 }
00384 
00385 #if defined(WINCE)
00386 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
00387 #else
00388 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
00389 #endif
00390 {
00391   int argc;
00392   char *argv[64]; // max 64 command line arguments
00393   char *cmdline;
00394 
00395 #if !defined(UNICODE)
00396   _codepage = GetACP(); // get system codepage as some kind of a default
00397 #endif /* UNICODE */
00398 
00399   CrashLog::InitialiseCrashLog();
00400 
00401 #if defined(UNICODE)
00402 
00403 #if !defined(WINCE)
00404   /* Check if a win9x user started the win32 version */
00405   if (HasBit(GetVersion(), 31)) usererror("This version of OpenTTD doesn't run on windows 95/98/ME.\nPlease download the win9x binary and try again.");
00406 #endif
00407 
00408   /* For UNICODE we need to convert the commandline to char* _AND_
00409    * save it because argv[] points into this buffer and thus needs to
00410    * be available between subsequent calls to FS2OTTD() */
00411   char cmdlinebuf[MAX_PATH];
00412 #endif /* UNICODE */
00413 
00414   cmdline = WIDE_TO_MB_BUFFER(GetCommandLine(), cmdlinebuf, lengthof(cmdlinebuf));
00415 
00416 #if defined(_DEBUG)
00417   CreateConsole();
00418 #endif
00419 
00420 #if !defined(WINCE)
00421   _set_error_mode(_OUT_TO_MSGBOX); // force assertion output to messagebox
00422 #endif
00423 
00424   /* setup random seed to something quite random */
00425   SetRandomSeed(GetTickCount());
00426 
00427   argc = ParseCommandLine(cmdline, argv, lengthof(argv));
00428 
00429   ttd_main(argc, argv);
00430   return 0;
00431 }
00432 
00433 #if defined(WINCE)
00434 void GetCurrentDirectoryW(int length, wchar_t *path)
00435 {
00436   /* Get the name of this module */
00437   GetModuleFileName(NULL, path, length);
00438 
00439   /* Remove the executable name, this we call CurrentDir */
00440   wchar_t *pDest = wcsrchr(path, '\\');
00441   if (pDest != NULL) {
00442     int result = pDest - path + 1;
00443     path[result] = '\0';
00444   }
00445 }
00446 #endif
00447 
00448 char *getcwd(char *buf, size_t size)
00449 {
00450 #if defined(WINCE)
00451   TCHAR path[MAX_PATH];
00452   GetModuleFileName(NULL, path, MAX_PATH);
00453   convert_from_fs(path, buf, size);
00454   /* GetModuleFileName returns dir with file, so remove everything behind latest '\\' */
00455   char *p = strrchr(buf, '\\');
00456   if (p != NULL) *p = '\0';
00457 #elif defined(UNICODE)
00458   TCHAR path[MAX_PATH];
00459   GetCurrentDirectory(MAX_PATH - 1, path);
00460   convert_from_fs(path, buf, size);
00461 #else
00462   GetCurrentDirectory(size, buf);
00463 #endif
00464   return buf;
00465 }
00466 
00467 
00468 void DetermineBasePaths(const char *exe)
00469 {
00470   char tmp[MAX_PATH];
00471   TCHAR path[MAX_PATH];
00472 #ifdef WITH_PERSONAL_DIR
00473   SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path);
00474   strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp));
00475   AppendPathSeparator(tmp, MAX_PATH);
00476   ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH);
00477   AppendPathSeparator(tmp, MAX_PATH);
00478   _searchpaths[SP_PERSONAL_DIR] = strdup(tmp);
00479 
00480   SHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path);
00481   strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp));
00482   AppendPathSeparator(tmp, MAX_PATH);
00483   ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH);
00484   AppendPathSeparator(tmp, MAX_PATH);
00485   _searchpaths[SP_SHARED_DIR] = strdup(tmp);
00486 #else
00487   _searchpaths[SP_PERSONAL_DIR] = NULL;
00488   _searchpaths[SP_SHARED_DIR]   = NULL;
00489 #endif
00490 
00491   /* Get the path to working directory of OpenTTD */
00492   getcwd(tmp, lengthof(tmp));
00493   AppendPathSeparator(tmp, MAX_PATH);
00494   _searchpaths[SP_WORKING_DIR] = strdup(tmp);
00495 
00496   if (!GetModuleFileName(NULL, path, lengthof(path))) {
00497     DEBUG(misc, 0, "GetModuleFileName failed (%lu)\n", GetLastError());
00498     _searchpaths[SP_BINARY_DIR] = NULL;
00499   } else {
00500     TCHAR exec_dir[MAX_PATH];
00501     _tcsncpy(path, MB_TO_WIDE_BUFFER(exe, path, lengthof(path)), lengthof(path));
00502     if (!GetFullPathName(path, lengthof(exec_dir), exec_dir, NULL)) {
00503       DEBUG(misc, 0, "GetFullPathName failed (%lu)\n", GetLastError());
00504       _searchpaths[SP_BINARY_DIR] = NULL;
00505     } else {
00506       strecpy(tmp, WIDE_TO_MB_BUFFER(exec_dir, tmp, lengthof(tmp)), lastof(tmp));
00507       char *s = strrchr(tmp, PATHSEPCHAR);
00508       *(s + 1) = '\0';
00509       _searchpaths[SP_BINARY_DIR] = strdup(tmp);
00510     }
00511   }
00512 
00513   _searchpaths[SP_INSTALLATION_DIR]       = NULL;
00514   _searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL;
00515 }
00516 
00517 
00518 bool GetClipboardContents(char *buffer, size_t buff_len)
00519 {
00520   HGLOBAL cbuf;
00521   const char *ptr;
00522 
00523   if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
00524     OpenClipboard(NULL);
00525     cbuf = GetClipboardData(CF_UNICODETEXT);
00526 
00527     ptr = (const char*)GlobalLock(cbuf);
00528     const char *ret = convert_from_fs((wchar_t*)ptr, buffer, buff_len);
00529     GlobalUnlock(cbuf);
00530     CloseClipboard();
00531 
00532     if (*ret == '\0') return false;
00533 #if !defined(UNICODE)
00534   } else if (IsClipboardFormatAvailable(CF_TEXT)) {
00535     OpenClipboard(NULL);
00536     cbuf = GetClipboardData(CF_TEXT);
00537 
00538     ptr = (const char*)GlobalLock(cbuf);
00539     ttd_strlcpy(buffer, FS2OTTD(ptr), buff_len);
00540 
00541     GlobalUnlock(cbuf);
00542     CloseClipboard();
00543 #endif /* UNICODE */
00544   } else {
00545     return false;
00546   }
00547 
00548   return true;
00549 }
00550 
00551 
00552 void CSleep(int milliseconds)
00553 {
00554   Sleep(milliseconds);
00555 }
00556 
00557 
00570 const char *FS2OTTD(const TCHAR *name)
00571 {
00572   static char utf8_buf[512];
00573 #if defined(UNICODE)
00574   return convert_from_fs(name, utf8_buf, lengthof(utf8_buf));
00575 #else
00576   char *s = utf8_buf;
00577 
00578   for (; *name != '\0'; name++) {
00579     wchar_t w;
00580     int len = MultiByteToWideChar(_codepage, 0, name, 1, &w, 1);
00581     if (len != 1) {
00582       DEBUG(misc, 0, "[utf8] M2W error converting '%c'. Errno %lu", *name, GetLastError());
00583       continue;
00584     }
00585 
00586     if (s + Utf8CharLen(w) >= lastof(utf8_buf)) break;
00587     s += Utf8Encode(s, w);
00588   }
00589 
00590   *s = '\0';
00591   return utf8_buf;
00592 #endif /* UNICODE */
00593 }
00594 
00607 const TCHAR *OTTD2FS(const char *name)
00608 {
00609   static TCHAR system_buf[512];
00610 #if defined(UNICODE)
00611   return convert_to_fs(name, system_buf, lengthof(system_buf));
00612 #else
00613   char *s = system_buf;
00614 
00615   for (WChar c; (c = Utf8Consume(&name)) != '\0';) {
00616     if (s >= lastof(system_buf)) break;
00617 
00618     char mb;
00619     int len = WideCharToMultiByte(_codepage, 0, (wchar_t*)&c, 1, &mb, 1, NULL, NULL);
00620     if (len != 1) {
00621       DEBUG(misc, 0, "[utf8] W2M error converting '0x%X'. Errno %lu", c, GetLastError());
00622       continue;
00623     }
00624 
00625     *s++ = mb;
00626   }
00627 
00628   *s = '\0';
00629   return system_buf;
00630 #endif /* UNICODE */
00631 }
00632 
00633 
00640 char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen)
00641 {
00642   int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, (int)buflen, NULL, NULL);
00643   if (len == 0) {
00644     DEBUG(misc, 0, "[utf8] W2M error converting wide-string. Errno %lu", GetLastError());
00645     utf8_buf[0] = '\0';
00646   }
00647 
00648   return utf8_buf;
00649 }
00650 
00651 
00659 wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen)
00660 {
00661   int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, utf16_buf, (int)buflen);
00662   if (len == 0) {
00663     DEBUG(misc, 0, "[utf8] M2W error converting '%s'. Errno %lu", name, GetLastError());
00664     utf16_buf[0] = '\0';
00665   }
00666 
00667   return utf16_buf;
00668 }
00669 
00674 HRESULT OTTDSHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath)
00675 {
00676   static HRESULT (WINAPI *SHGetFolderPath)(HWND, int, HANDLE, DWORD, LPTSTR) = NULL;
00677   static bool first_time = true;
00678 
00679   /* We only try to load the library one time; if it fails, it fails */
00680   if (first_time) {
00681 #if defined(UNICODE)
00682 # define W(x) x "W"
00683 #else
00684 # define W(x) x "A"
00685 #endif
00686     if (!LoadLibraryList((Function*)&SHGetFolderPath, "SHFolder.dll\0" W("SHGetFolderPath") "\0\0")) {
00687       DEBUG(misc, 0, "Unable to load " W("SHGetFolderPath") "from SHFolder.dll");
00688     }
00689 #undef W
00690     first_time = false;
00691   }
00692 
00693   if (SHGetFolderPath != NULL) return SHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath);
00694 
00695   /* SHGetFolderPath doesn't exist, try a more conservative approach,
00696    * eg environment variables. This is only included for legacy modes
00697    * MSDN says: that 'pszPath' is a "Pointer to a null-terminated string of
00698    * length MAX_PATH which will receive the path" so let's assume that
00699    * Windows 95 with Internet Explorer 5.0, Windows 98 with Internet Explorer 5.0,
00700    * Windows 98 Second Edition (SE), Windows NT 4.0 with Internet Explorer 5.0,
00701    * Windows NT 4.0 with Service Pack 4 (SP4) */
00702   {
00703     DWORD ret;
00704     switch (csidl) {
00705       case CSIDL_FONTS: // Get the system font path, eg %WINDIR%\Fonts
00706         ret = GetEnvironmentVariable(_T("WINDIR"), pszPath, MAX_PATH);
00707         if (ret == 0) break;
00708         _tcsncat(pszPath, _T("\\Fonts"), MAX_PATH);
00709 
00710         return (HRESULT)0;
00711         break;
00712       /* XXX - other types to go here when needed... */
00713     }
00714   }
00715 
00716   return E_INVALIDARG;
00717 }
00718 
00720 const char *GetCurrentLocale(const char *)
00721 {
00722   char lang[9], country[9];
00723   if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lang, lengthof(lang)) == 0 ||
00724       GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, country, lengthof(country)) == 0) {
00725     /* Unable to retrieve the locale. */
00726     return NULL;
00727   }
00728   /* Format it as 'en_us'. */
00729   static char retbuf[6] = {lang[0], lang[1], '_', country[0], country[1], 0};
00730   return retbuf;
00731 }

Generated on Thu Feb 4 17:20:26 2010 for OpenTTD by  doxygen 1.5.6