12 #include "../../stdafx.h" 13 #include "../../debug.h" 14 #include "../../gfx_func.h" 15 #include "../../textbuf_gui.h" 16 #include "../../fileio_func.h" 23 #include "../../fios.h" 24 #include "../../core/alloc_func.hpp" 25 #include "../../openttd.h" 26 #include "../../core/random_func.hpp" 27 #include "../../string_func.h" 28 #include "../../crashlog.h" 33 #include "../../safeguards.h" 37 static bool _has_console;
38 static bool _cursor_disable =
true;
39 static bool _cursor_visible =
true;
41 bool MyShowCursor(
bool show,
bool toggle)
43 if (toggle) _cursor_disable = !_cursor_disable;
44 if (_cursor_disable)
return show;
45 if (_cursor_visible == show)
return show;
47 _cursor_visible = show;
60 while (*dll !=
'\0') {
62 lib = LoadLibrary(MB_TO_WIDE(dll));
64 if (lib == NULL)
return false;
68 while (*dll++ !=
'\0') { }
69 if (*dll ==
'\0')
break;
71 p = GetProcAddress(lib, MB_TO_WIDE(dll));
73 p = GetProcAddress(lib, dll);
75 if (p == NULL)
return false;
76 *proc++ = (Function)p;
83 void ShowOSErrorBox(
const char *buf,
bool system)
86 MessageBox(GetActiveWindow(),
OTTD2FS(buf), _T(
"Error!"), MB_ICONSTOP);
89 void OSOpenBrowser(
const char *url)
91 ShellExecute(GetActiveWindow(), _T(
"open"),
OTTD2FS(url), NULL, NULL, SW_SHOWNORMAL);
116 static DIR _global_dir;
117 static LONG _global_dir_is_in_use =
false;
119 static inline DIR *dir_calloc()
123 if (InterlockedExchange(&_global_dir_is_in_use,
true) == (LONG)
true) {
127 memset(d, 0,
sizeof(*d));
132 static inline void dir_free(
DIR *d)
134 if (d == &_global_dir) {
135 _global_dir_is_in_use = (LONG)
false;
141 DIR *opendir(
const TCHAR *path)
144 UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS);
145 DWORD fa = GetFileAttributes(path);
147 if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) {
150 TCHAR search_path[MAX_PATH];
151 bool slash = path[_tcslen(path) - 1] ==
'\\';
155 _sntprintf(search_path,
lengthof(search_path), _T(
"%s%s*"), path, slash ? _T(
"") : _T(
"\\"));
156 *
lastof(search_path) =
'\0';
157 d->hFind = FindFirstFile(search_path, &d->fd);
159 if (d->hFind != INVALID_HANDLE_VALUE ||
160 GetLastError() == ERROR_NO_MORE_FILES) {
162 d->at_first_entry =
true;
180 struct dirent *readdir(
DIR *d)
182 DWORD prev_err = GetLastError();
184 if (d->at_first_entry) {
186 if (d->hFind == INVALID_HANDLE_VALUE)
return NULL;
187 d->at_first_entry =
false;
188 }
else if (!FindNextFile(d->hFind, &d->fd)) {
189 if (GetLastError() == ERROR_NO_MORE_FILES) SetLastError(prev_err);
195 d->ent.d_name = d->fd.cFileName;
206 bool FiosIsRoot(
const char *file)
208 return file[3] ==
'\0';
211 void FiosGetDrives(
FileList &file_list)
216 fios->type = FIOS_TYPE_DRIVE;
224 GetLogicalDriveStrings(
lengthof(drives), drives);
225 for (s = drives; *s !=
'\0';) {
227 fios->type = FIOS_TYPE_DRIVE;
231 while (*s++ !=
'\0') { }
236 bool FiosIsValidFile(
const char *path,
const struct dirent *ent,
struct stat *sb)
239 static const int64 posix_epoch_hns = 0x019DB1DED53E8000LL;
240 const WIN32_FIND_DATA *fd = &ent->dir->fd;
242 sb->st_size = ((uint64) fd->nFileSizeHigh << 32) + fd->nFileSizeLow;
248 sb->st_mtime = (time_t)((*(
const uint64*)&fd->ftLastWriteTime - posix_epoch_hns) / 1E7);
249 sb->st_mode = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? S_IFDIR : S_IFREG;
254 bool FiosIsHiddenFile(
const struct dirent *ent)
256 return (ent->dir->fd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0;
259 bool FiosGetDiskFreeSpace(
const char *path, uint64 *tot)
261 UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS);
264 DWORD spc, bps, nfc, tnc;
266 _sntprintf(root,
lengthof(root), _T(
"%c:") _T(PATHSEP), path[0]);
267 if (tot != NULL && GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) {
268 *tot = ((spc * bps) * (uint64)nfc);
276 static int ParseCommandLine(
char *line,
char **argv,
int max_argc)
282 while (*line ==
' ' || *line ==
'\t') line++;
285 if (*line ==
'\0')
break;
290 while (*line !=
'"') {
291 if (*line ==
'\0')
return n;
296 while (*line !=
' ' && *line !=
'\t') {
297 if (*line ==
'\0')
return n;
302 }
while (n != max_argc);
313 CONSOLE_SCREEN_BUFFER_INFO coninfo;
315 if (_has_console)
return;
320 hand = GetStdHandle(STD_OUTPUT_HANDLE);
321 GetConsoleScreenBufferInfo(hand, &coninfo);
322 coninfo.dwSize.Y = 500;
323 SetConsoleScreenBufferSize(hand, coninfo.dwSize);
326 #if !defined(__CYGWIN__) 329 int fd = _open_osfhandle((intptr_t)hand, _O_TEXT);
333 _has_console =
false;
337 ShowInfo(
"Unable to open an output handle to the console. Check known-bugs.txt for details.");
341 #if defined(_MSC_VER) && _MSC_VER >= 1900 342 freopen(
"CONOUT$",
"a", stdout);
343 freopen(
"CONIN$",
"r", stdin);
344 freopen(
"CONOUT$",
"a", stderr);
346 *stdout = *_fdopen(fd,
"w");
347 *stdin = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT),
"r" );
348 *stderr = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT),
"w" );
353 *stdout = *fdopen(1,
"w" );
354 *stdin = *fdopen(0,
"r" );
355 *stderr = *fdopen(2,
"w" );
358 setvbuf(stdin, NULL, _IONBF, 0);
359 setvbuf(stdout, NULL, _IONBF, 0);
360 setvbuf(stderr, NULL, _IONBF, 0);
368 static INT_PTR CALLBACK
HelpDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
371 case WM_INITDIALOG: {
375 while (q !=
lastof(help_msg) && *p !=
'\0') {
378 if (q ==
lastof(help_msg)) {
388 TCHAR help_msg_buf[8192];
390 SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE);
394 if (wParam == 12) ExitProcess(0);
403 void ShowInfo(
const char *str)
406 fprintf(stderr,
"%s\n", str);
412 old = MyShowCursor(
true);
413 if (strlen(str) > 2048) {
418 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(101), NULL,
HelpDialogFunc);
422 TCHAR help_msg_buf[8192];
423 MessageBox(GetActiveWindow(),
convert_to_fs(str, help_msg_buf,
lengthof(help_msg_buf)), _T(
"OpenTTD"), MB_ICONINFORMATION | MB_OK);
430 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,
int nCmdShow)
432 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
440 #if defined(UNICODE) && !defined(WINCE) 442 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.");
455 _set_error_mode(_OUT_TO_MSGBOX);
461 argc = ParseCommandLine(cmdline, argv,
lengthof(argv));
472 void GetCurrentDirectoryW(
int length,
wchar_t *path)
475 GetModuleFileName(NULL, path, length);
478 wchar_t *pDest = wcsrchr(path,
'\\');
480 int result = pDest - path + 1;
486 char *getcwd(
char *buf,
size_t size)
489 TCHAR path[MAX_PATH];
490 GetModuleFileName(NULL, path, MAX_PATH);
493 char *p = strrchr(buf,
'\\');
494 if (p != NULL) *p =
'\0';
496 TCHAR path[MAX_PATH];
497 GetCurrentDirectory(MAX_PATH - 1, path);
507 TCHAR path[MAX_PATH];
508 #ifdef WITH_PERSONAL_DIR 509 if (SUCCEEDED(
OTTDSHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path))) {
519 if (SUCCEEDED(
OTTDSHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path))) {
538 if (!GetModuleFileName(NULL, path,
lengthof(path))) {
539 DEBUG(misc, 0,
"GetModuleFileName failed (%lu)\n", GetLastError());
542 TCHAR exec_dir[MAX_PATH];
544 if (!GetFullPathName(path,
lengthof(exec_dir), exec_dir, NULL)) {
545 DEBUG(misc, 0,
"GetFullPathName failed (%lu)\n", GetLastError());
549 char *s = strrchr(tmp, PATHSEPCHAR);
565 if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
567 cbuf = GetClipboardData(CF_UNICODETEXT);
569 ptr = (
const char*)GlobalLock(cbuf);
570 int out_len = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)ptr, -1, buffer, (last - buffer) + 1, NULL, NULL);
574 if (out_len == 0)
return false;
575 #if !defined(UNICODE) 576 }
else if (IsClipboardFormatAvailable(CF_TEXT)) {
578 cbuf = GetClipboardData(CF_TEXT);
580 ptr = (
const char*)GlobalLock(cbuf);
594 void CSleep(
int milliseconds)
615 static char utf8_buf[512];
631 const TCHAR *
OTTD2FS(
const char *name,
bool console_cp)
633 static TCHAR system_buf[512];
649 const WCHAR *wide_buf = name;
652 int wide_len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
658 WCHAR *wide_buf =
AllocaM(WCHAR, wide_len);
659 MultiByteToWideChar(CP_ACP, 0, name, -1, wide_buf, wide_len);
663 int len = WideCharToMultiByte(CP_UTF8, 0, wide_buf, -1, utf8_buf, (
int)buflen, NULL, NULL);
664 if (len == 0) utf8_buf[0] =
'\0';
680 TCHAR *
convert_to_fs(
const char *name, TCHAR *system_buf,
size_t buflen,
bool console_cp)
683 int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, system_buf, (
int)buflen);
684 if (len == 0) system_buf[0] =
'\0';
686 int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
688 system_buf[0] =
'\0';
692 WCHAR *wide_buf =
AllocaM(WCHAR, len);
693 MultiByteToWideChar(CP_UTF8, 0, name, -1, wide_buf, len);
695 len = WideCharToMultiByte(console_cp ? CP_OEMCP : CP_ACP, 0, wide_buf, len, system_buf, (
int)buflen, NULL, NULL);
696 if (len == 0) system_buf[0] =
'\0';
710 static HRESULT (WINAPI *SHGetFolderPath)(HWND, int, HANDLE, DWORD, LPTSTR) = NULL;
711 static bool first_time =
true;
721 if (!
LoadLibraryList((Function*)&SHGetFolderPath,
"shell32.dll\0" W(
"SHGetFolderPath")
"\0\0")) {
722 if (!
LoadLibraryList((Function*)&SHGetFolderPath,
"SHFolder.dll\0" W(
"SHGetFolderPath")
"\0\0")) {
723 DEBUG(misc, 0,
"Unable to load " W(
"SHGetFolderPath")
"from either shell32.dll or SHFolder.dll");
730 if (SHGetFolderPath != NULL)
return SHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath);
743 ret = GetEnvironmentVariable(_T(
"WINDIR"), pszPath, MAX_PATH);
745 _tcsncat(pszPath, _T(
"\\Fonts"), MAX_PATH);
750 case CSIDL_COMMON_DOCUMENTS: {
752 if (RegOpenKeyEx(csidl == CSIDL_PERSONAL ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, REGSTR_PATH_SPECIAL_FOLDERS, 0, KEY_READ, &key) != ERROR_SUCCESS)
break;
753 DWORD len = MAX_PATH;
754 ret = RegQueryValueEx(key, csidl == CSIDL_PERSONAL ? _T(
"Personal") : _T(
"Common Documents"), NULL, NULL, (LPBYTE)pszPath, &len);
756 if (ret == ERROR_SUCCESS)
return (HRESULT)0;
770 char lang[9], country[9];
771 if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lang,
lengthof(lang)) == 0 ||
772 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, country,
lengthof(country)) == 0) {
777 static char retbuf[6] = {lang[0], lang[1],
'_', country[0], country[1], 0};
785 GetSystemInfo(&info);
786 return info.dwNumberOfProcessors;
791 const DWORD MS_VC_EXCEPTION = 0x406D1388;
804 void SetWin32ThreadName(DWORD dwThreadID,
const char* threadName)
806 THREADNAME_INFO info;
807 info.dwType = 0x1000;
808 info.szName = threadName;
809 info.dwThreadID = dwThreadID;
812 #pragma warning(push) 813 #pragma warning(disable: 6320 6322) 815 RaiseException(MS_VC_EXCEPTION, 0,
sizeof(info) /
sizeof(ULONG_PTR), (ULONG_PTR*)&info);
816 } __except (EXCEPTION_EXECUTE_HANDLER) {
int openttd_main(int argc, char *argv[])
Main entry point for this lovely game.
static char * strecat(char *dst, const char *src, const char *last)
Appends characters from one string to another.
TCHAR * convert_to_fs(const char *name, TCHAR *system_buf, size_t buflen, bool console_cp)
Convert from OpenTTD's encoding to that of the environment in UNICODE.
const char * FS2OTTD(const TCHAR *name)
Convert to OpenTTD's encoding from that of the local environment.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Search in the directory where the binary resides.
HRESULT OTTDSHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath)
Our very own SHGetFolderPath function for support of windows operating systems that don't have this f...
void SetRandomSeed(uint32 seed)
(Re)set the state of the random number generators.
#define lastof(x)
Get the last element of an fixed size array.
static void InitialiseCrashLog()
Initialiser for crash logs; do the appropriate things so crashes are handled by our crash handler ins...
#define AllocaM(T, num_elements)
alloca() has to be called in the parent function, so define AllocaM() as a macro
char * convert_from_fs(const TCHAR *name, char *utf8_buf, size_t buflen)
Convert to OpenTTD's encoding from that of the environment in UNICODE.
const char * GetCurrentLocale(const char *)
Determine the current user's locale.
Deals with finding savegames.
bool _left_button_clicked
Is left mouse button clicked?
bool AppendPathSeparator(char *buf, const char *last)
Appends, if necessary, the path separator character to the end of the string.
bool LoadLibraryList(Function proc[], const char *dll)
Helper function needed by dynamically loading libraries XXX: Hurray for MS only having an ANSI GetPro...
bool _left_button_down
Is left mouse button pressed?
static const char * _help_msg
Temporary pointer to get the help message to the window.
static INT_PTR CALLBACK HelpDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
Callback function to handle the window.
void CDECL usererror(const char *s,...)
Error handling for fatal user errors.
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
bool GetClipboardContents(char *buffer, const char *last)
Try to retrieve the current clipboard contents.
#define lengthof(x)
Return the length of an fixed size array.
void DetermineBasePaths(const char *exe)
Determine the base (personal dir and game data dir) paths.
const TCHAR * OTTD2FS(const char *name, bool console_cp)
Convert from OpenTTD's encoding to that of the local environment.
#define DEBUG(name, level,...)
Output a line of debugging information.
Search in the personal directory.
List of file information.
const char * _searchpaths[NUM_SEARCHPATHS]
The search paths OpenTTD could search through.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Search in the working directory.
Search in the installation directory.
Search within the application bundle.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
void ValidateString(const char *str)
Scans the string for valid characters and if it finds invalid ones, replaces them with a question mar...
uint GetCPUCoreCount()
Get number of processor cores in the system, including HyperThreading or similar. ...
FiosItem * Append()
Construct a new entry in the file list.
declarations of functions for MS windows systems
Search in the shared directory, like 'Shared Files' under Windows.