mtsedit/src/main.c

283 lines
9.1 KiB
C

/*
* mtsedit/main.c
*
* Copyright (C) 2019 bzt (bztsrc@gitlab)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* @brief Main function
*
*/
#define STB_IMAGE_IMPLEMENTATION
#include "main.h"
/* those SDL guys are not familiar with the C standard. They redefine main(), but incorrectly, they lack envp */
#ifdef main
#undef main
int main(int argc, char** argv, char** envp);
#endif
/* translation dictionary */
extern char *dict[NUMLANGS][NUMTEXTS + 1];
char **lang = &dict[0][1];
/**
* Windows workaround
*/
#ifdef __WIN32__
/* these two functions were borrowed from sdl_windows_main.c */
static void UnEscapeQuotes(char *arg)
{
char *last = NULL, *c_curr, *c_last;
while (*arg) {
if (*arg == '"' && (last != NULL && *last == '\\')) {
c_curr = arg;
c_last = last;
while (*c_curr) {
*c_last = *c_curr;
c_last = c_curr;
c_curr++;
}
*c_last = '\0';
}
last = arg;
arg++;
}
}
/* Parse a command line buffer into arguments */
static int ParseCommandLine(char *cmdline, char **argv)
{
char *bufp;
char *lastp = NULL;
int argc, last_argc;
argc = last_argc = 0;
for (bufp = cmdline; *bufp;) {
/* Skip leading whitespace */
while (SDL_isspace(*bufp)) {
++bufp;
}
/* Skip over argument */
if (*bufp == '"') {
++bufp;
if (*bufp) {
if (argv) {
argv[argc] = bufp;
}
++argc;
}
/* Skip over word */
lastp = bufp;
while (*bufp && (*bufp != '"' || *lastp == '\\')) {
lastp = bufp;
++bufp;
}
} else {
if (*bufp) {
if (argv) {
argv[argc] = bufp;
}
++argc;
}
/* Skip over word */
while (*bufp && !SDL_isspace(*bufp)) {
++bufp;
}
}
if (*bufp) {
if (argv) {
*bufp = '\0';
}
++bufp;
}
/* Strip out \ from \" sequences */
if (argv && last_argc != argc) {
UnEscapeQuotes(argv[last_argc]);
}
last_argc = argc;
}
if (argv) {
argv[argc] = NULL;
}
return (argc);
}
/* Windows entry point */
int APIENTRY WinMain(_unused HINSTANCE hInstance, _unused HINSTANCE hPrevInstance, _unused LPSTR lpCmdLine, _unused int nCmdShow)
{
char *cmdline = GetCommandLine();
int ret, argc = ParseCommandLine(cmdline, NULL);
char **argv = SDL_stack_alloc(char*, argc+2);
ParseCommandLine(cmdline, argv);
if(!argv[1]) {
argc++;
argv[1] = ".";
}
SDL_SetMainReady();
ret = main(argc, argv, (char**)GetEnvironmentStrings());
SDL_stack_free(argv);
exit(ret);
return ret;
}
#endif
/**
* The real main procedure
*/
int main(int argc, char** argv, char** envp)
{
int i, j, opt = 0, ret = 0;
char **env, *newmap = NULL, *lc = NULL;
/* detect the language (or get from command line) and load dictionary for it */
for(env = envp; env && *env; env++) if(!memcmp(*env, "LANG=", 5)) { lc = *env + 5; break; }
for(i = 1; i < argc; i++) if(argv[i][0] == '-' && argv[i][1] == 'l') { lc = argv[i+1]; break; }
if(lc)
for(i = 0; i < NUMLANGS; i++) {
if(!memcmp(lc, dict[i][0], strlen(dict[i][0]))) {
lang = &dict[i][1];
break;
}
}
/* get blocks data */
blocks_getdir(argv, envp);
#ifndef __WIN32__
/* MacOSX does not allow specifying arguments when started from Launchpad,
* and it won't show the output in a terminal either. So fake home dir. */
if(argc < 2 && !isatty(1)) { argc++; argv[1] = "~"; }
/* Instead MacOSX likes to append unwanted arguments to the command line... */
if(argc == 2 && !memcmp(argv[1], "-psn_", 5)) argv[1] = "~";
#endif
if(argc < 2) {
usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license\r\n\r\n"
"./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b|-B|-V] [-r remapfile] [-m map] <schematic> [out.mts]\r\n"
"./mtsedit [-G|-C|-T]\r\n"
"./mtsedit -g <block.png>\r\n"
"./mtsedit -t <blockimgs.csv> [blockid]\r\n"
"./mtsedit -i [Minetest mods dir]\r\n"
"\r\n -v: %s\r\n -l lang: %s\r\n -d: %s\r\n -p: %s\r\n -P: %s\r\n -b, -B: %s\r\n -r remapfile: %s\r\n"
" -m map: %s\r\n -g: %s\r\n -t: %s\r\n -i: %s\r\n -V: %s\r\n out.mts: %s\r\n",
lang[INF_VERB], lang[INF_LANG], lang[INF_DUMP], lang[INF_PRE1], lang[INF_PRE2], lang[INF_BPRINT], lang[INF_REMAP],
lang[INF_MAP], lang[INF_GEN], lang[INF_BLK], lang[INF_MOD], lang[INF_VOX], lang[INF_OUT]);
exit(0);
}
for(i = j = 1; j < argc; j++) {
if(argv[j][0] == '-') {
switch(argv[j][1]) {
case 'v': verbose++; break;
case 'd': opt = 1; break;
case 'p': opt = 2; break;
case 'P': opt = 3; break;
case 'b': opt = 4; break;
case 'B': opt = 4; shift = 1; break;
case 'g': opt = 5; break;
case 't': opt = 6; break;
case 'i': opt = 7; break;
case 'm': if(!opt) { opt = 8; } newmap = argv[++j]; i++; break;
case 'V': opt = 9; break;
case 'r': remapfile = argv[++j]; i++; break;
case 'l': j++; i++; break;
case 'G': gimppal(); return 0; break;
case 'C':
blocks_parse();
if(newmap) {
j = atoi(newmap);
if(j) savepal = j - 1;
else {
for(j = 0; j < numpalettes; j++)
if(!strcmp(palettes[j], newmap)) { savepal = j; break; }
}
}
mapperpal();
return 0;
break;
case 'T': tileremap(); return 0; break;
default: goto usage; break;
}
i++;
} else {
i = j; break;
}
}
if(i >= argc || !argv[i]) goto usage;
#ifndef __WIN32__
if(argv[i][0] == '~') {
strncpy(mtsfile, home, sizeof(mtsfile) - 1);
strncat(mtsfile, argv[i] + 1, sizeof(mtsfile) - 1);
} else
#endif
strncpy(mtsfile, argv[i], sizeof(mtsfile) - 1);
savelen = savepos = strlen(mtsfile);
tmpblk = (unsigned char*)malloc(32 * 32 * 4);
if(!tmpblk) error(lang[ERR_MEM]);
mts_x = mts_y = mts_z = 0;
if(i+1 < argc && argv[i+1] && !opt) opt = 8;
if(opt && (opt < 5 || opt >= 8)) {
blocks_parse();
readschem();
if(!mts_y || !mts_y || !mts_x)
fprintf(stderr, "mtsedit: %s: %s\r\n", mtsfile, lang[ERR_LOAD]);
if(newmap) {
j = atoi(newmap);
if(j) savepal = j - 1;
else {
for(j = 0; j < numpalettes; j++)
if(!strcmp(palettes[j], newmap)) { savepal = j; break; }
}
}
if(argv[i+1]) {
#ifndef __WIN32__
if(argv[i+1][0] == '~') {
strncpy(mtsfile, home, sizeof(mtsfile) - 1);
strncat(mtsfile, argv[i+1] + 1, sizeof(mtsfile) - 1);
} else
#endif
strncpy(mtsfile, argv[i+1], sizeof(mtsfile) - 1);
ret = opt == 9 ? vox_save() : mts_save();
}
}
switch(opt) {
case 1: ret = mts_dump(); break;
case 2:
case 3: ret = mts_view(opt-2); break;
case 5: ret = stairgen(); break;
case 6: ret = blockgen(argv[i+1]); break;
case 4: /* handle these in sdl.c, because extern does not know sizeof() */
case 7:
case 0:
/* start the main user interface */
ret = sdlmain(opt);
break;
}
free(path);
free(tmpblk);
return ret;
}