bool GetClipboardContents(char *buffer, size_t buff_len) { HGLOBAL cbuf; const char *ptr; if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { OpenClipboard(NULL); cbuf = GetClipboardData(CF_UNICODETEXT); ptr = (const char*)GlobalLock(cbuf); const char *ret = convert_from_fs((wchar_t*)ptr, buffer, buff_len); GlobalUnlock(cbuf); CloseClipboard(); if (*ret == '\0') return false; #if !defined(UNICODE) } else if (IsClipboardFormatAvailable(CF_TEXT)) { OpenClipboard(NULL); cbuf = GetClipboardData(CF_TEXT); ptr = (const char*)GlobalLock(cbuf); ttd_strlcpy(buffer, FS2OTTD(ptr), buff_len); GlobalUnlock(cbuf); CloseClipboard(); #endif /* UNICODE */ } else { return false; } return true; }
/** * Create a path consisting of an already existing path, a possible * path separator and the filename. The separator is only appended if the path * does not already end with a separator */ static inline char *mkpath(char *buf, size_t buflen, const char *path, const char *file) { ttd_strlcpy(buf, path, buflen); // copy directory into buffer char *p = strchr(buf, '\0'); // add path separator if necessary if (p[-1] != PATHSEPCHAR && (size_t)(p - buf) + 1 < buflen) *p++ = PATHSEPCHAR; ttd_strlcpy(p, file, buflen - (size_t)(p - buf)); // concatenate filename at end of buffer return buf; }
/** The return of the client's request of the names of some NewGRFs */ DEF_UDP_RECEIVE_COMMAND(Client, PACKET_UDP_SERVER_NEWGRFS) { uint8 num_grfs; uint i; DEBUG(net, 6, "[udp] newgrf data reply from %s", client_addr->GetAddressAsString()); num_grfs = p->Recv_uint8 (); if (num_grfs > NETWORK_MAX_GRF_COUNT) return; for (i = 0; i < num_grfs; i++) { char *unknown_name; char name[NETWORK_GRF_NAME_LENGTH]; GRFConfig c; this->Recv_GRFIdentifier(p, &c); p->Recv_string(name, sizeof(name)); /* An empty name is not possible under normal circumstances * and causes problems when showing the NewGRF list. */ if (StrEmpty(name)) continue; /* Finds the fake GRFConfig for the just read GRF ID and MD5sum tuple. * If it exists and not resolved yet, then name of the fake GRF is * overwritten with the name from the reply. */ unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false); if (unknown_name != NULL && strcmp(unknown_name, UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) { ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH); } } }
/** * Appends characters from one string to another. * * Appends the source string to the destination string with respect of the * terminating null-character and the maximum size of the destination * buffer. * * @note usage ttd_strlcat(dst, src, lengthof(dst)); * @note lengthof() applies only to fixed size arrays * * @param dst The buffer containing the target string * @param src The buffer containing the string to append * @param size The maximum size of the destination buffer */ void ttd_strlcat(char *dst, const char *src, size_t size) { assert(size > 0); while (size > 0 && *dst != '\0') { size--; dst++; } ttd_strlcpy(dst, src, size); }
bool AIController::LoadedLibrary(const char *library_name, int *next_number, char *fake_class_name, int fake_class_name_len) { LoadedLibraryList::iterator iter = this->loaded_library.find(library_name); if (iter == this->loaded_library.end()) { *next_number = ++this->loaded_library_count; return false; } ttd_strlcpy(fake_class_name, (*iter).second, fake_class_name_len); return true; }
char *FioGetDirectory(char *buf, size_t buflen, Subdirectory subdir) { Searchpath sp; /* Find and return the first valid directory */ FOR_ALL_SEARCHPATHS(sp) { char *ret = FioAppendDirectory(buf, buflen, sp, subdir); if (FileExists(buf)) return ret; } /* Could not find the directory, fall back to a base path */ ttd_strlcpy(buf, _personal_dir, buflen); return buf; }
GameInfo *GameScannerInfo::FindInfo(const char *nameParam, int versionParam, bool force_exact_match) { if (this->info_list.size() == 0) return NULL; if (nameParam == NULL) return NULL; char game_name[1024]; ttd_strlcpy(game_name, nameParam, sizeof(game_name)); strtolower(game_name); GameInfo *info = NULL; int version = -1; if (versionParam == -1) { /* We want to load the latest version of this Game script; so find it */ if (this->info_single_list.find(game_name) != this->info_single_list.end()) return static_cast<GameInfo *>(this->info_single_list[game_name]); /* If we didn't find a match Game script, maybe the user included a version */ char *e = strrchr(game_name, '.'); if (e == NULL) return NULL; *e = '\0'; e++; versionParam = atoi(e); /* FALL THROUGH, like we were calling this function with a version. */ } if (force_exact_match) { /* Try to find a direct 'name.version' match */ char game_name_tmp[1024]; snprintf(game_name_tmp, sizeof(game_name_tmp), "%s.%d", game_name, versionParam); strtolower(game_name_tmp); if (this->info_list.find(game_name_tmp) != this->info_list.end()) return static_cast<GameInfo *>(this->info_list[game_name_tmp]); } /* See if there is a compatible Game script which goes by that name, with the highest * version which allows loading the requested version */ ScriptInfoList::iterator it = this->info_list.begin(); for (; it != this->info_list.end(); it++) { GameInfo *i = static_cast<GameInfo *>((*it).second); if (strcasecmp(game_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) { version = (*it).second->GetVersion(); info = i; } } return info; }
/** * Allocates and files a variable with the full path * based on the given directory. * @param dir the directory to base the path on * @return the malloced full path */ char *BuildWithFullPath(const char *dir) { char *dest = MallocT<char>(MAX_PATH); ttd_strlcpy(dest, dir, MAX_PATH); /* Check if absolute or relative path */ const char *s = strchr(dest, PATHSEPCHAR); /* Add absolute path */ if (s == NULL || dest != s) { if (getcwd(dest, MAX_PATH) == NULL) *dest = '\0'; AppendPathSeparator(dest, MAX_PATH); ttd_strlcat(dest, dir, MAX_PATH); } AppendPathSeparator(dest, MAX_PATH); return dest; }
/** * Create a directory with the given name * @param name the new name of the directory */ static void FioCreateDirectory(const char *name) { #if defined(WIN32) || defined(WINCE) CreateDirectory(OTTD2FS(name), NULL); #elif defined(OS2) && !defined(__INNOTEK_LIBC__) mkdir(OTTD2FS(name)); #elif defined(__MORPHOS__) || defined(__AMIGAOS__) char buf[MAX_PATH]; ttd_strlcpy(buf, name, MAX_PATH); size_t len = strlen(name) - 1; if (buf[len] == '/') { buf[len] = '\0'; // Kill pathsep, so mkdir() will not fail } mkdir(OTTD2FS(buf), 0755); #else mkdir(OTTD2FS(name), 0755); #endif }
static void SaveReal_AIPL(int *index_ptr) { CompanyID index = (CompanyID)*index_ptr; AIConfig *config = AIConfig::GetConfig(index); if (config->HasAI()) { ttd_strlcpy(_ai_saveload_name, config->GetName(), lengthof(_ai_saveload_name)); _ai_saveload_version = config->GetVersion(); } else { /* No AI is configured for this so store an empty string as name. */ _ai_saveload_name[0] = '\0'; _ai_saveload_version = -1; } _ai_saveload_is_random = config->IsRandomAI(); _ai_saveload_settings[0] = '\0'; config->SettingsToString(_ai_saveload_settings, lengthof(_ai_saveload_settings)); SlObject(NULL, _ai_company); /* If the AI was active, store his data too */ if (Company::IsValidAiID(index)) AI::Save(index); }
bool GetClipboardContents(char *buffer, size_t buff_len) { /* XXX -- Currently no clipboard support implemented with GCC */ #ifndef __INNOTEK_LIBC__ HAB hab = 0; if (WinOpenClipbrd(hab)) { const char *text = (const char*)WinQueryClipbrdData(hab, CF_TEXT); if (text != NULL) { ttd_strlcpy(buffer, text, buff_len); WinCloseClipbrd(hab); return true; } WinCloseClipbrd(hab); } #endif return false; }
/** * Navigate Up/Down in the history of typed commands * @param direction Go further back in history (+1), go to recently typed commands (-1) */ static void IConsoleHistoryNavigate(int direction) { if (_iconsole_history[0] == NULL) return; // Empty history int i = _iconsole_historypos + direction; /* watch out for overflows, just wrap around */ if (i < 0) i = ICON_HISTORY_SIZE - 1; if ((uint)i >= ICON_HISTORY_SIZE) i = 0; if (direction > 0) { if (_iconsole_history[i] == NULL) i = 0; } if (direction < 0) { while (i > 0 && _iconsole_history[i] == NULL) i--; } _iconsole_historypos = i; IConsoleClearCommand(); /* copy history to 'command prompt / bash' */ assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE)); ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.max_bytes); UpdateTextBufferSize(&_iconsole_cmdline); }
/* static */ HSQOBJECT ScriptController::Import(const char *library, const char *class_name, int version) { ScriptController *controller = ScriptObject::GetActiveInstance()->GetController(); Squirrel *engine = ScriptObject::GetActiveInstance()->engine; HSQUIRRELVM vm = engine->GetVM(); /* Internally we store libraries as 'library.version' */ char library_name[1024]; snprintf(library_name, sizeof(library_name), "%s.%d", library, version); strtolower(library_name); ScriptInfo *lib = ScriptObject::GetActiveInstance()->FindLibrary(library, version); if (lib == NULL) { char error[1024]; snprintf(error, sizeof(error), "couldn't find library '%s' with version %d", library, version); throw sq_throwerror(vm, OTTD2SQ(error)); } /* Get the current table/class we belong to */ HSQOBJECT parent; sq_getstackobj(vm, 1, &parent); char fake_class[1024]; LoadedLibraryList::iterator iter = controller->loaded_library.find(library_name); if (iter != controller->loaded_library.end()) { ttd_strlcpy(fake_class, (*iter).second, sizeof(fake_class)); } else { int next_number = ++controller->loaded_library_count; /* Create a new fake internal name */ snprintf(fake_class, sizeof(fake_class), "_internalNA%d", next_number); /* Load the library in a 'fake' namespace, so we can link it to the name the user requested */ sq_pushroottable(vm); sq_pushstring(vm, OTTD2SQ(fake_class), -1); sq_newclass(vm, SQFalse); /* Load the library */ if (!engine->LoadScript(vm, lib->GetMainScript(), false)) { char error[1024]; snprintf(error, sizeof(error), "there was a compile error when importing '%s' version %d", library, version); throw sq_throwerror(vm, OTTD2SQ(error)); } /* Create the fake class */ sq_newslot(vm, -3, SQFalse); sq_pop(vm, 1); controller->loaded_library[strdup(library_name)] = strdup(fake_class); } /* Find the real class inside the fake class (like 'sets.Vector') */ sq_pushroottable(vm); sq_pushstring(vm, OTTD2SQ(fake_class), -1); if (SQ_FAILED(sq_get(vm, -2))) { throw sq_throwerror(vm, _SC("internal error assigning library class")); } sq_pushstring(vm, OTTD2SQ(lib->GetInstanceName()), -1); if (SQ_FAILED(sq_get(vm, -2))) { char error[1024]; snprintf(error, sizeof(error), "unable to find class '%s' in the library '%s' version %d", lib->GetInstanceName(), library, version); throw sq_throwerror(vm, OTTD2SQ(error)); } HSQOBJECT obj; sq_getstackobj(vm, -1, &obj); sq_pop(vm, 3); if (StrEmpty(class_name)) return obj; /* Now link the name the user wanted to our 'fake' class */ sq_pushobject(vm, parent); sq_pushstring(vm, OTTD2SQ(class_name), -1); sq_pushobject(vm, obj); sq_newclass(vm, SQTrue); sq_newslot(vm, -3, SQFalse); sq_pop(vm, 1); return obj; }
virtual void OnClick(Point pt, int widget, int click_count) { switch (widget) { case SNGRFS_PRESET_LIST: { DropDownList *list = new DropDownList(); /* Add 'None' option for clearing list */ list->push_back(new DropDownListStringItem(STR_NONE, -1, false)); for (uint i = 0; i < _grf_preset_list.Length(); i++) { if (_grf_preset_list[i] != NULL) { list->push_back(new DropDownListPresetItem(i)); } } ShowDropDownList(this, list, this->preset, SNGRFS_PRESET_LIST); break; } case SNGRFS_PRESET_SAVE: this->query_widget = widget; ShowQueryString(STR_EMPTY, STR_NEWGRF_SETTINGS_PRESET_SAVE_QUERY, 32, 100, this, CS_ALPHANUMERAL, QSF_NONE); break; case SNGRFS_PRESET_DELETE: if (this->preset == -1) return; DeleteGRFPresetFromConfig(_grf_preset_list[this->preset]); GetGRFPresetList(&_grf_preset_list); this->preset = -1; this->InvalidateData(); break; case SNGRFS_ADD: // Add GRF DeleteWindowByClass(WC_SAVELOAD); new NewGRFAddWindow(&_newgrf_add_dlg_desc, this, &this->list); break; case SNGRFS_REMOVE: { // Remove GRF GRFConfig **pc, *c, *newsel; /* Choose the next GRF file to be the selected file */ newsel = this->sel->next; for (pc = &this->list; (c = *pc) != NULL; pc = &c->next) { /* If the new selection is empty (i.e. we're deleting the last item * in the list, pick the file just before the selected file */ if (newsel == NULL && c->next == this->sel) newsel = c; if (c == this->sel) { *pc = c->next; free(c); break; } } this->sel = newsel; this->preset = -1; this->InvalidateData(3); this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window break; } case SNGRFS_MOVE_UP: { // Move GRF up GRFConfig **pc, *c; if (this->sel == NULL) break; int pos = 0; for (pc = &this->list; (c = *pc) != NULL; pc = &c->next, pos++) { if (c->next == this->sel) { c->next = this->sel->next; this->sel->next = c; *pc = this->sel; break; } } this->vscroll.ScrollTowards(pos); this->preset = -1; this->InvalidateData(); break; } case SNGRFS_MOVE_DOWN: { // Move GRF down GRFConfig **pc, *c; if (this->sel == NULL) break; int pos = 1; // Start at 1 as we swap the selected newgrf with the next one for (pc = &this->list; (c = *pc) != NULL; pc = &c->next, pos++) { if (c == this->sel) { *pc = c->next; c->next = c->next->next; (*pc)->next = c; break; } } this->vscroll.ScrollTowards(pos); this->preset = -1; this->InvalidateData(); break; } case SNGRFS_FILE_LIST: { // Select a GRF GRFConfig *c; uint i = (pt.y - this->GetWidget<NWidgetBase>(SNGRFS_FILE_LIST)->pos_y) / this->resize.step_height + this->vscroll.GetPosition(); for (c = this->list; c != NULL && i > 0; c = c->next, i--) {} if (this->sel != c) this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window this->sel = c; this->InvalidateData(); if (click_count > 1) this->OnClick(pt, SNGRFS_SET_PARAMETERS, 1); break; } case SNGRFS_APPLY_CHANGES: // Apply changes made to GRF list if (this->execute) { ShowQuery( STR_NEWGRF_POPUP_CAUTION_CAPTION, STR_NEWGRF_CONFIRMATION_TEXT, this, NewGRFConfirmationCallback ); } else { CopyGRFConfigList(this->orig_list, this->list, true); ResetGRFConfig(false); ReloadNewGRFData(); } break; case SNGRFS_SET_PARAMETERS: { // Edit parameters if (this->sel == NULL) break; this->query_widget = widget; static char buff[512]; GRFBuildParamList(buff, this->sel, lastof(buff)); SetDParamStr(0, buff); ShowQueryString(STR_JUST_RAW_STRING, STR_NEWGRF_SETTINGS_PARAMETER_QUERY, 63, 250, this, CS_NUMERAL_SPACE, QSF_NONE); break; } case SNGRFS_TOGGLE_PALETTE: if (this->sel != NULL) { this->sel->windows_paletted ^= true; this->SetDirty(); } break; case SNGRFS_CONTENT_DOWNLOAD: if (!_network_available) { ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, 0, 0); } else { #if defined(ENABLE_NETWORK) /* Only show the things in the current list, or everything when nothing's selected */ ContentVector cv; for (const GRFConfig *c = this->list; c != NULL; c = c->next) { if (c->status != GCS_NOT_FOUND && !HasBit(c->flags, GCF_COMPATIBLE)) continue; ContentInfo *ci = new ContentInfo(); ci->type = CONTENT_TYPE_NEWGRF; ci->state = ContentInfo::DOES_NOT_EXIST; ttd_strlcpy(ci->name, c->name != NULL ? c->name : c->filename, lengthof(ci->name)); ci->unique_id = BSWAP32(c->grfid); memcpy(ci->md5sum, c->md5sum, sizeof(ci->md5sum)); if (HasBit(c->flags, GCF_COMPATIBLE)) GamelogGetOriginalGRFMD5Checksum(c->grfid, ci->md5sum); *cv.Append() = ci; } ShowNetworkContentListWindow(cv.Length() == 0 ? NULL : &cv, CONTENT_TYPE_NEWGRF); #endif } break; } }
virtual void OnClick(Point pt, int widget, int click_count) { switch (widget) { case SLWW_SORT_BYNAME: // Sort save names by name _savegame_sort_order = (_savegame_sort_order == SORT_BY_NAME) ? SORT_BY_NAME | SORT_DESCENDING : SORT_BY_NAME; _savegame_sort_dirty = true; this->SetDirty(); break; case SLWW_SORT_BYDATE: // Sort save names by date _savegame_sort_order = (_savegame_sort_order == SORT_BY_DATE) ? SORT_BY_DATE | SORT_DESCENDING : SORT_BY_DATE; _savegame_sort_dirty = true; this->SetDirty(); break; case SLWW_HOME_BUTTON: // OpenTTD 'button', jumps to OpenTTD directory FiosBrowseTo(&o_dir); this->InvalidateData(); break; case SLWW_LOAD_BUTTON: if (this->selected != NULL && !_load_check_data.HasErrors()) { _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD; const char *name = FiosBrowseTo(this->selected); SetFiosType(this->selected->type); strecpy(_file_to_saveload.name, name, lastof(_file_to_saveload.name)); strecpy(_file_to_saveload.title, this->selected->title, lastof(_file_to_saveload.title)); delete this; } break; case SLWW_NEWGRF_INFO: if (_load_check_data.HasNewGrfs()) { ShowNewGRFSettings(false, false, false, &_load_check_data.grfconfig); } break; case SLWW_DRIVES_DIRECTORIES_LIST: { // Click the listbox int y = (pt.y - this->GetWidget<NWidgetBase>(SLWW_DRIVES_DIRECTORIES_LIST)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height; if (y < 0 || (y += this->vscroll.GetPosition()) >= this->vscroll.GetCount()) return; const FiosItem *file = _fios_items.Get(y); const char *name = FiosBrowseTo(file); if (name != NULL) { if (click_count == 1) { if (this->selected != file) { this->selected = file; _load_check_data.Clear(); if (file->type == FIOS_TYPE_FILE || file->type == FIOS_TYPE_SCENARIO) { SaveOrLoad(name, SL_LOAD_CHECK, NO_DIRECTORY, false); } this->InvalidateData(1); } if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) { /* Copy clicked name to editbox */ ttd_strlcpy(this->text.buf, file->title, this->text.maxsize); UpdateTextBufferSize(&this->text); this->SetWidgetDirty(SLWW_SAVE_OSK_TITLE); } } else if (!_load_check_data.HasErrors()) { this->selected = file; if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) { this->OnClick(pt, SLWW_LOAD_BUTTON, 1); } else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) { SetFiosType(file->type); strecpy(_file_to_saveload.name, name, lastof(_file_to_saveload.name)); strecpy(_file_to_saveload.title, file->title, lastof(_file_to_saveload.title)); delete this; ShowHeightmapLoad(); } } } else { /* Changed directory, need refresh. */ this->InvalidateData(); } break; } case SLWW_CONTENT_DOWNLOAD: if (!_network_available) { ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR); } else { #if defined(ENABLE_NETWORK) switch (_saveload_mode) { default: NOT_REACHED(); case SLD_LOAD_SCENARIO: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_SCENARIO); break; case SLD_LOAD_HEIGHTMAP: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_HEIGHTMAP); break; } #endif } break; case SLWW_DELETE_SELECTION: case SLWW_SAVE_GAME: // Delete, Save game break; } }
/** * Copy a string into the textbuffer. * @param text Source. */ void Textbuf::Assign(const char *text) { ttd_strlcpy(this->buf, text, this->max_bytes); this->UpdateSize(); }
int CDECL main(int argc, char *argv[]) { char pathbuf[MAX_PATH]; const char *src_dir = "."; const char *dest_dir = NULL; GetOptData mgo(argc - 1, argv + 1, _opts); for (;;) { int i = mgo.GetOpt(); if (i == -1) break; switch (i) { case 'v': puts("$Revision$"); return 0; case 'C': printf("args\tflags\tcommand\treplacement\n"); for (const CmdStruct *cs = _cmd_structs; cs < endof(_cmd_structs); cs++) { char flags; switch (cs->value) { case 0x200E: case 0x200F: // Implicit BIDI controls case 0x202A: case 0x202B: case 0x202C: case 0x202D: case 0x202E: // Explicit BIDI controls case 0xA0: // Non breaking space case '\n': // Newlines may be added too case '{': // This special /* This command may be in the translation when it is not in base */ flags = 'i'; break; default: if (cs->proc == EmitGender) { flags = 'g'; // Command needs number of parameters defined by number of genders } else if (cs->proc == EmitPlural) { flags = 'p'; // Command needs number of parameters defined by plural value } else { flags = '0'; // Command needs no parameters } } printf("%i\t%c\t\"%s\"\t\"%s\"\n", cs->consumes, flags, cs->cmd, strstr(cs->cmd, "STRING") ? "STRING" : cs->cmd); } return 0; case 'L': printf("count\tdescription\tnames\n"); for (const PluralForm *pf = _plural_forms; pf < endof(_plural_forms); pf++) { printf("%i\t\"%s\"\t%s\n", pf->plural_count, pf->description, pf->names); } return 0; case 'P': printf("name\tflags\tdefault\tdescription\n"); for (size_t i = 0; i < lengthof(_pragmas); i++) { printf("\"%s\"\t%s\t\"%s\"\t\"%s\"\n", _pragmas[i][0], _pragmas[i][1], _pragmas[i][2], _pragmas[i][3]); } return 0; case 't': _show_todo |= 1; break; case 'w': _show_todo |= 2; break; case 'h': puts( "strgen - $Revision$\n" " -v | --version print version information and exit\n" " -t | --todo replace any untranslated strings with '<TODO>'\n" " -w | --warning print a warning for any untranslated strings\n" " -h | -? | --help print this help message and exit\n" " -s | --source_dir search for english.txt in the specified directory\n" " -d | --dest_dir put output file in the specified directory, create if needed\n" " -export-commands export all commands and exit\n" " -export-plurals export all plural forms and exit\n" " -export-pragmas export all pragmas and exit\n" " Run without parameters and strgen will search for english.txt and parse it,\n" " creating strings.h. Passing an argument, strgen will translate that language\n" " file using english.txt as a reference and output <language>.lng." ); return 0; case 's': src_dir = replace_pathsep(mgo.opt); break; case 'd': dest_dir = replace_pathsep(mgo.opt); break; case -2: fprintf(stderr, "Invalid arguments\n"); return 0; } } if (dest_dir == NULL) dest_dir = src_dir; // if dest_dir is not specified, it equals src_dir try { /* strgen has two modes of operation. If no (free) arguments are passed * strgen generates strings.h to the destination directory. If it is supplied * with a (free) parameter the program will translate that language to destination * directory. As input english.txt is parsed from the source directory */ if (mgo.numleft == 0) { mkpath(pathbuf, lengthof(pathbuf), src_dir, "english.txt"); /* parse master file */ StringData data(TAB_COUNT); FileStringReader master_reader(data, pathbuf, true, false); master_reader.ParseFile(); if (_errors != 0) return 1; /* write strings.h */ ottd_mkdir(dest_dir); mkpath(pathbuf, lengthof(pathbuf), dest_dir, "strings.h"); HeaderFileWriter writer(pathbuf); writer.WriteHeader(data); writer.Finalise(data); } else if (mgo.numleft >= 1) { char *r; mkpath(pathbuf, lengthof(pathbuf), src_dir, "english.txt"); StringData data(TAB_COUNT); /* parse master file and check if target file is correct */ FileStringReader master_reader(data, pathbuf, true, false); master_reader.ParseFile(); for (int i = 0; i < mgo.numleft; i++) { data.FreeTranslation(); const char *translation = replace_pathsep(mgo.argv[i]); const char *file = strrchr(translation, PATHSEPCHAR); FileStringReader translation_reader(data, translation, false, file == NULL || strcmp(file + 1, "english.txt") != 0); translation_reader.ParseFile(); // target file if (_errors != 0) return 1; /* get the targetfile, strip any directories and append to destination path */ r = strrchr(mgo.argv[i], PATHSEPCHAR); mkpath(pathbuf, lengthof(pathbuf), dest_dir, (r != NULL) ? &r[1] : mgo.argv[i]); /* rename the .txt (input-extension) to .lng */ r = strrchr(pathbuf, '.'); if (r == NULL || strcmp(r, ".txt") != 0) r = strchr(pathbuf, '\0'); ttd_strlcpy(r, ".lng", (size_t)(r - pathbuf)); LanguageFileWriter writer(pathbuf); writer.WriteLang(data); writer.Finalise(); /* if showing warnings, print a summary of the language */ if ((_show_todo & 2) != 0) { fprintf(stdout, "%d warnings and %d errors for %s\n", _warnings, _errors, pathbuf); } } } } catch (...) { return 2; } return 0; }