tron@2186: /* $Id$ */ tron@2186: darkvater@801: #include "stdafx.h" Darkvater@1892: #include "openttd.h" orudge@2167: #include "variables.h" tron@1317: #include "string.h" darkvater@801: #include "table/strings.h" orudge@1888: #include "gfx.h" orudge@1888: #include "gui.h" orudge@2167: #include "functions.h" orudge@2167: #include "macros.h" darkvater@801: darkvater@801: #include darkvater@801: #include darkvater@801: #include orudge@1887: #include darkvater@801: #include darkvater@801: #include darkvater@801: truelight@818: #define INCL_WIN celestar@1524: #define INCL_WINCLIPBOARD truelight@810: darkvater@801: #include orudge@2167: #include orudge@2167: Darkvater@4223: bool FiosIsRoot(const char *file) truelight@810: { Darkvater@4221: return path[3] == '\0'; truelight@810: } truelight@810: Darkvater@4221: void FiosGetDrives(void) darkvater@801: { darkvater@801: FiosItem *fios; Darkvater@4221: unsigned disk, disk2, save, total; darkvater@801: Darkvater@4221: _dos_getdrive(&save); // save original drive tron@1486: Darkvater@4221: /* get an available drive letter */ Darkvater@4221: for (disk = 1;; disk++) { Darkvater@4221: _dos_setdrive(disk, &total); Darkvater@4221: if (disk >= total) return; Darkvater@4221: _dos_getdrive(&disk2); Darkvater@2099: Darkvater@4221: if (disk == disk2) { Darkvater@4221: FiosItem *fios = FiosAlloc(); Darkvater@4221: fios->type = FIOS_TYPE_DRIVE; Darkvater@4221: fios->mtime = 0; Darkvater@4221: snprintf(fios->name, lengthof(fios->name), "%c:", 'A' + disk - 1); Darkvater@4221: ttd_strlcpy(fios->title, fios->name, lengthof(fios->title)); darkvater@801: } darkvater@801: } darkvater@801: Darkvater@4221: _dos_setdrive(save, &total); // restore the original drive darkvater@801: } darkvater@801: Darkvater@4222: bool FiosGetDiskFreeSpace(const char *path, uint32 *tot) Darkvater@4222: { Darkvater@4222: struct diskfree_t free; Darkvater@4222: char drive = path[0] - 'A' + 1; Darkvater@4222: Darkvater@4222: if (tot != NULL && _getdiskfree(drive, &free) == 0) { Darkvater@4222: *tot = free.avail_clusters * free.sectors_per_cluster * free.bytes_per_sector; Darkvater@4222: return true; Darkvater@4222: } Darkvater@4222: Darkvater@4222: return false; Darkvater@4222: } Darkvater@4222: Darkvater@4221: bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) darkvater@801: { darkvater@801: char filename[MAX_PATH]; darkvater@801: Darkvater@4221: snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, ent->d_name); Darkvater@4221: if (stat(filename, sb) != 0) return false; tron@1486: Darkvater@4221: return (ent->d_name[0] != '.'); // hidden file darkvater@801: } darkvater@801: darkvater@801: static void ChangeWorkingDirectory(char *exe) darkvater@801: { darkvater@801: char *s = strrchr(exe, '\\'); darkvater@801: if (s != NULL) { tron@1486: *s = '\0'; darkvater@801: chdir(exe); darkvater@801: *s = '\\'; darkvater@801: } darkvater@801: } darkvater@801: darkvater@801: void ShowInfo(const char *str) darkvater@801: { truelight@818: HAB hab; truelight@818: HMQ hmq; truelight@818: ULONG rc; tron@915: truelight@818: // init PM env. truelight@818: hmq = WinCreateMsgQueue((hab = WinInitialize(0)), 0); truelight@818: truelight@818: // display the box truelight@818: rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, str, "OpenTTD", 0, MB_OK | MB_MOVEABLE | MB_INFORMATION); truelight@818: truelight@818: // terminate PM env. truelight@818: WinDestroyMsgQueue(hmq); truelight@818: WinTerminate(hab); darkvater@801: } darkvater@801: darkvater@801: void ShowOSErrorBox(const char *buf) darkvater@801: { truelight@818: HAB hab; truelight@818: HMQ hmq; truelight@818: ULONG rc; tron@915: truelight@818: // init PM env. truelight@818: hmq = WinCreateMsgQueue((hab = WinInitialize(0)), 0); truelight@818: truelight@818: // display the box truelight@818: rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, buf, "OpenTTD", 0, MB_OK | MB_MOVEABLE | MB_ERROR); truelight@818: truelight@818: // terminate PM env. truelight@818: WinDestroyMsgQueue(hmq); truelight@818: WinTerminate(hab); darkvater@801: } darkvater@801: darkvater@801: int CDECL main(int argc, char* argv[]) darkvater@801: { darkvater@801: // change the working directory to enable doubleclicking in UIs darkvater@801: ChangeWorkingDirectory(argv[0]); darkvater@801: rubidium@4369: _random_seeds[1][1] = _random_seeds[1][0] = _random_seeds[0][1] = _random_seeds[0][0] = time(NULL); darkvater@801: darkvater@801: return ttd_main(argc, argv); darkvater@801: } darkvater@801: Darkvater@1390: void DeterminePaths(void) darkvater@801: { darkvater@801: char *s; darkvater@801: Darkvater@5296: _paths.game_data_dir = malloc(MAX_PATH); Darkvater@5296: ttd_strlcpy(_paths.game_data_dir, GAME_DATA_DIR, MAX_PATH); darkvater@801: #if defined SECOND_DATA_DIR Darkvater@5296: _paths.second_data_dir = malloc(MAX_PATH); Darkvater@5296: ttd_strlcpy(_paths.second_data_dir, SECOND_DATA_DIR, MAX_PATH); darkvater@801: #endif darkvater@801: darkvater@801: #if defined(USE_HOMEDIR) darkvater@801: { tron@1486: const char *homedir = getenv("HOME"); darkvater@801: tron@1486: if (homedir == NULL) { tron@1486: const struct passwd *pw = getpwuid(getuid()); tron@1486: if (pw != NULL) homedir = pw->pw_dir; darkvater@801: } darkvater@801: Darkvater@5296: _paths.personal_dir = str_fmt("%s" PATHSEP "%s", homedir, PERSONAL_DIR); darkvater@801: } darkvater@801: darkvater@801: #else /* not defined(USE_HOMEDIR) */ darkvater@801: Darkvater@5296: _paths.personal_dir = malloc(MAX_PATH); Darkvater@5296: ttd_strlcpy(_paths.personal_dir, PERSONAL_DIR, MAX_PATH); darkvater@801: darkvater@801: // check if absolute or relative path Darkvater@5296: s = strchr(_paths.personal_dir, '\\'); darkvater@801: darkvater@801: // add absolute path Darkvater@5296: if (s == NULL || _paths.personal_dir != s) { Darkvater@5296: getcwd(_paths.personal_dir, MAX_PATH); Darkvater@5296: s = strchr(_paths.personal_dir, 0); darkvater@801: *s++ = '\\'; darkvater@801: ttd_strlcpy(s, PERSONAL_DIR, MAX_PATH); darkvater@801: } darkvater@801: darkvater@801: #endif /* defined(USE_HOMEDIR) */ darkvater@801: Darkvater@5296: s = strchr(_paths.personal_dir, 0); darkvater@801: darkvater@801: // append a / ? tron@1486: if (s[-1] != '\\') strcpy(s, "\\"); darkvater@801: Darkvater@5296: _paths.save_dir = str_fmt("%ssave", _paths.personal_dir); Darkvater@5296: _paths.autosave_dir = str_fmt("%s\\autosave", _paths.save_dir); Darkvater@5296: _paths.scenario_dir = str_fmt("%sscenario", _paths.personal_dir); Darkvater@5296: _paths.heightmap_dir = str_fmt("%sscenario\\heightmap", _paths.personal_dir); Darkvater@5296: _paths.gm_dir = str_fmt("%sgm\\", _paths.game_data_dir); Darkvater@5296: _paths.data_dir = str_fmt("%sdata\\", _paths.game_data_dir); Darkvater@1482: Darkvater@1482: if (_config_file == NULL) Darkvater@5296: _config_file = str_fmt("%sopenttd.cfg", _paths.personal_dir); tron@915: Darkvater@5296: _highscore_file = str_fmt("%shs.dat", _paths.personal_dir); Darkvater@5296: _log_file = str_fmt("%sopenttd.log", _paths.personal_dir); tron@1486: darkvater@801: #if defined CUSTOM_LANG_DIR darkvater@801: // sets the search path for lng files to the custom one Darkvater@5296: _paths.lang_dir = malloc( MAX_PATH ); Darkvater@5296: ttd_strlcpy( _paths.lang_dir, CUSTOM_LANG_DIR, MAX_PATH); darkvater@801: #else Darkvater@5296: _paths.lang_dir = str_fmt("%slang\\", _paths.game_data_dir); darkvater@801: #endif darkvater@801: darkvater@801: // create necessary folders Darkvater@5296: mkdir(_paths.personal_dir); Darkvater@5296: mkdir(_paths.save_dir); Darkvater@5296: mkdir(_paths.autosave_dir); Darkvater@5296: mkdir(_paths.scenario_dir); Darkvater@5296: mkdir(_paths.heightmap_dir); darkvater@801: } darkvater@801: orudge@1888: /** orudge@1888: * Insert a chunk of text from the clipboard onto the textbuffer. Get TEXT clipboard orudge@1888: * and append this up to the maximum length (either absolute or screenlength). If maxlength orudge@1888: * is zero, we don't care about the screenlength but only about the physical length of the string orudge@1888: * @param tb @Textbuf type to be changed orudge@1888: * @return Return true on successfull change of Textbuf, or false otherwise orudge@1888: */ tron@1486: bool InsertTextBufferClipboard(Textbuf *tb) tron@1486: { orudge@1893: HAB hab = 0; celestar@1524: celestar@1524: if (WinOpenClipbrd(hab)) celestar@1524: { orudge@1893: const char* text = (const char*)WinQueryClipbrdData(hab, CF_TEXT); orudge@1893: orudge@1893: if (text != NULL) orudge@1893: { orudge@1893: uint length = 0; orudge@1893: uint width = 0; orudge@1893: const char* i; orudge@1893: orudge@1893: for (i = text; IsValidAsciiChar(*i); i++) orudge@1893: { orudge@1893: uint w; orudge@1893: orudge@1893: if (tb->length + length >= tb->maxlength - 1) break; orudge@1893: peter1138@3800: w = GetCharacterWidth(FS_NORMAL, (byte)*i); orudge@1893: if (tb->maxwidth != 0 && width + tb->width + w > tb->maxwidth) break; orudge@1893: orudge@1893: width += w; orudge@1893: length++; orudge@1893: } orudge@1893: orudge@1893: memmove(tb->buf + tb->caretpos + length, tb->buf + tb->caretpos, tb->length - tb->caretpos + 1); orudge@1893: memcpy(tb->buf + tb->caretpos, text, length); orudge@1893: tb->width += width; orudge@1893: tb->caretxoffs += width; orudge@1893: tb->length += length; orudge@1893: tb->caretpos += length; orudge@1893: orudge@1893: WinCloseClipbrd(hab); orudge@1893: return true; orudge@1893: } orudge@1888: celestar@1524: WinCloseClipbrd(hab); celestar@1524: } celestar@1524: orudge@1893: return false; tron@1486: } orudge@1887: orudge@2167: orudge@2167: void CSleep(int milliseconds) orudge@2167: { orudge@2167: delay(milliseconds); orudge@2167: } Darkvater@5167: Darkvater@5167: const char *FS2OTTD(const char *name) {return name;} Darkvater@5167: const char *OTTD2FS(const char *name) {return name;}