Overview
Comment: | Implement the "portable app" mode. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3d7617dc1f0ac620e99ccf344e0d16a1 |
User & Date: | user on 2021-05-23 20:24:40 |
Other Links: | manifest | tags |
Context
2021-05-23
| ||
23:23 | Implement portable compilation mode, to compile it for "portable app" use. check-in: ec088682c3 user: user tags: trunk | |
20:24 | Implement the "portable app" mode. check-in: 3d7617dc1f user: user tags: trunk | |
02:22 | Implement a key binding command to record the solution even if auto recording solutions is not enabled. check-in: 1a2fee8a44 user: user tags: trunk | |
Changes
Modified TODO from [f6f521f828] to [a0fc23867b].
︙ | ︙ | |||
28 29 30 31 32 33 34 | * Bookmarks * Message trace menu to enable/disable * Bugs * Figure out why the $SeekerCloser class doesn't seem to work properly * Level 232 of SUPERHRO puzzle set (the Lava shouldn't expand? why?) * Display solution comments/timestamp * VCR mode | < < < | 28 29 30 31 32 33 34 35 36 37 38 | * Bookmarks * Message trace menu to enable/disable * Bugs * Figure out why the $SeekerCloser class doesn't seem to work properly * Level 232 of SUPERHRO puzzle set (the Lava shouldn't expand? why?) * Display solution comments/timestamp * VCR mode * Command-line switch for batch import/export levels * SQL * Implement the GROUP column in the CLASSES table * Allow multiple SQL statements in one binding |
Modified commandline.doc from [64526b83d0] to [f6413bcb62].
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 | -e Start in the editor instead of game. -f Only flush the user cache and then terminate. -n Create a new puzzle set. The .xclass and .class files should already exist; the .level and .solution files should not already exist, and will be created with minimal data. -p Start the picture editor. | > > > > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | -e Start in the editor instead of game. -f Only flush the user cache and then terminate. -h Disable portable mode; always use the HOME environment variable to find the configuration and database files. -n Create a new puzzle set. The .xclass and .class files should already exist; the .level and .solution files should not already exist, and will be created with minimal data. -p Start the picture editor. |
︙ | ︙ | |||
85 86 87 88 89 90 91 | .x0 Disable loading SQLite extensions. .x1 Enable loading SQLite extensions. | > > > > > > > > > > > > > > > > > > > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | .x0 Disable loading SQLite extensions. .x1 Enable loading SQLite extensions. === Portable mode === Free Hero Mesh may run either in "home mode" or in "portable mode". The following rules are used to determine which mode to use: 1. If the -h switch is present, use home mode. 2. If the HEROMESH_PREFIX environment variable is present, use portable mode; its value is the file name prefix (the ".heromeshsession" and ".heromeshrc" names are appended directly to this value, so if it does not end with a slash, it will be a prefix to the file name too). 3. If argv[0] contains a forward slash, use portable mode; it will use files "current.heromeshrc" and "current.heromeshsession" in the directory where the executable file is allegedly found. 4. Otherwise, home mode is used. |
Modified main.c from [6c4bf4088e] to [00e076bcbf].
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 | static const char*globalclassname; static SDL_Cursor*cursor[77]; static FILE*levelfp; static FILE*solutionfp; static sqlite3_int64 leveluc,solutionuc; static sqlite3_stmt*readusercachest; static sqlite3_int64 reset_usercache(FILE*fp,const char*nam,struct stat*stats,const char*suffix) { sqlite3_stmt*st; sqlite3_int64 t,id; char buf[128]; int i,z; if(z=sqlite3_prepare_v2(userdb,"DELETE FROM `USERCACHEDATA` WHERE `FILE` = (SELECT `ID` FROM `USERCACHEINDEX` WHERE `NAME` = ?1);",-1,&st,0)) { | > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | static const char*globalclassname; static SDL_Cursor*cursor[77]; static FILE*levelfp; static FILE*solutionfp; static sqlite3_int64 leveluc,solutionuc; static sqlite3_stmt*readusercachest; static char*hpath; static sqlite3_int64 reset_usercache(FILE*fp,const char*nam,struct stat*stats,const char*suffix) { sqlite3_stmt*st; sqlite3_int64 t,id; char buf[128]; int i,z; if(z=sqlite3_prepare_v2(userdb,"DELETE FROM `USERCACHEDATA` WHERE `FILE` = (SELECT `ID` FROM `USERCACHEINDEX` WHERE `NAME` = ?1);",-1,&st,0)) { |
︙ | ︙ | |||
541 542 543 544 545 546 547 | sqlite3_config(SQLITE_CONFIG_SMALL_MALLOC,(int)boolxrm(v,0)); optionquery[1]=Q_sqlCoveringIndexScan; v=xrm_get_resource(resourcedb,optionquery,optionquery,2)?:""; sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN,(int)boolxrm(v,1)); if(sqlite3_initialize()) fatal("Failure to initialize SQLite.\n"); optionquery[1]=Q_sqlFile; v=xrm_get_resource(resourcedb,optionquery,optionquery,2); | | < < < < < < | < | 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | sqlite3_config(SQLITE_CONFIG_SMALL_MALLOC,(int)boolxrm(v,0)); optionquery[1]=Q_sqlCoveringIndexScan; v=xrm_get_resource(resourcedb,optionquery,optionquery,2)?:""; sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN,(int)boolxrm(v,1)); if(sqlite3_initialize()) fatal("Failure to initialize SQLite.\n"); optionquery[1]=Q_sqlFile; v=xrm_get_resource(resourcedb,optionquery,optionquery,2); if(!v || !*v) strcpy(hpath+strlen(hpath)-2,"session"),v=hpath; if(z=sqlite3_open(v,&userdb)) fatal("Failed to open user database %s (%s)\n",v,userdb?sqlite3_errmsg(userdb):sqlite3_errstr(z)); optionquery[1]=Q_sqlExtensions; v=xrm_get_resource(resourcedb,optionquery,optionquery,2)?:""; sqlite3_db_config(userdb,SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION,*v?1:0,&z); if(*v) { p=s=strdup(v); if(!s) fatal("Allocation failed\n"); while(*v) { |
︙ | ︙ | |||
586 587 588 589 590 591 592 593 | } void set_cursor(int id) { id>>=1; if(!cursor[id]) cursor[id]=SDL_CreateCursor((void*)cursorimg+(id<<6),(void*)cursorimg+(id<<6)+32,16,16,cursorhot[id]>>4,cursorhot[id]&15); SDL_SetCursor(cursor[id]); } | | > > > > > > > > > > > > > > > | | > > > > > < | | < | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | } void set_cursor(int id) { id>>=1; if(!cursor[id]) cursor[id]=SDL_CreateCursor((void*)cursorimg+(id<<6),(void*)cursorimg+(id<<6)+32,16,16,cursorhot[id]>>4,cursorhot[id]&15); SDL_SetCursor(cursor[id]); } static void set_path(const char*arg) { const char*s; if(main_options['h']) goto home; if((s=getenv("HEROMESH_PREFIX")) && *s) { hpath=malloc(strlen(s)+32); if(!hpath) fatal("Allocation failed\n"); sprintf(hpath,"%s.heromeshrc",s); return; } if(s=strrchr(arg,'/')) { hpath=malloc(s+64-arg); if(!hpath) fatal("Allocation failed\n"); sprintf(hpath,"%.*s/current.heromeshrc",(int)(s-arg),arg); return; } home: s=getenv("HOME")?:"."; hpath=malloc(strlen(s)+32); if(!hpath) fatal("Allocation failed\n"); sprintf(hpath,"%s%s.heromeshrc",s,s[strlen(s)-1]=='/'?"":"/"); } static void load_options(void) { FILE*fp; fp=fopen(hpath,"r"); if(!fp) fatal("Failed to open %s (%m)\n",hpath); if(xrm_load(resourcedb,fp,1)) fatal("Error while loading .heromeshrc\n"); fclose(fp); } static void read_options(int argc,char**argv) { xrm_db*db=xrm_sub(resourcedb,0,xrm_make_quark(globalclassname,0)?:xrm_anyq); while(argc--) xrm_load_line(db,*argv++,1); |
︙ | ︙ | |||
887 888 889 890 891 892 893 | if(main_options['n']) { if(main_options['r']) fatal("Switches -r and -n are conflicting\n"); main_options['x']=1; } if(main_options['a']) main_options['r']=main_options['x']=1; if(main_options['p']) main_options['r']=1; if(main_options['f']) main_options['x']=1; | | > > > > | 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 | if(main_options['n']) { if(main_options['r']) fatal("Switches -r and -n are conflicting\n"); main_options['x']=1; } if(main_options['a']) main_options['r']=main_options['x']=1; if(main_options['p']) main_options['r']=1; if(main_options['f']) main_options['x']=1; if(!main_options['c']) { set_path(argv[0]); load_options(); } if(argc>optind) read_options(argc-optind,argv+optind); *optionquery=xrm_make_quark(globalclassname,0)?:xrm_anyq; #ifdef __GNUC__ stack_protect_mark=__builtin_frame_address(0); set_stack_protection(); #endif if(main_options['c']) { load_classes(); return 0; } init_sql(); load_key_bindings(); init_screen(); if(main_options['p']) { run_picture_editor(); return 0; } load_pictures(); if(main_options['T']) { printf("argv[0] = %s\n",argv[0]); test_mode(); return 0; } init_usercache(); if(main_options['n']) return 0; load_classes(); load_level_index(); |
︙ | ︙ |
Modified man6/heromesh.6 from [4391f87609] to [ed5c74f628].
︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | Only load classes and then terminate. This can be used to verify that the class definition file does not contain syntax errors. You can also use it with some other options to display details. .IP -e Start the level editor. .IP -f Only flush the user cache and then terminate. .IP -n Create a new puzzle set. The class definition file and image set must already exist. .IP -p Start the picture editor. .IP -r Open in read-only mode. | > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | Only load classes and then terminate. This can be used to verify that the class definition file does not contain syntax errors. You can also use it with some other options to display details. .IP -e Start the level editor. .IP -f Only flush the user cache and then terminate. .IP -h Disable portable mode; always use the HOME environment variable to find the files. .IP -n Create a new puzzle set. The class definition file and image set must already exist. .IP -p Start the picture editor. .IP -r Open in read-only mode. |
︙ | ︙ | |||
52 53 54 55 56 57 58 59 60 61 62 63 64 | The configuration file, in X resource manager format. .TP .I ~/.heromeshsession A SQLite database containing user cache data. .TP .I \*[Document_Dir]/*.doc Documentation. .SH ENVIRONMENT .TP .B HOME The home directory; used to find .heromeshrc and .heromeshsession files. .PP Any of the SDL environment variables can also be used. | > > > > > > > > > > > > > > > > > > > | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | The configuration file, in X resource manager format. .TP .I ~/.heromeshsession A SQLite database containing user cache data. .TP .I \*[Document_Dir]/*.doc Documentation. .PP The files it expects to find in the home directory may be looked for elsewhere if portable mode is used. .SH ENVIRONMENT .TP .B HEROMESH_PREFIX If defined, force portable mode. This value is used as the prefix to find the files. (It may include a file name prefix as well as a directory path.) .TP .B HOME The home directory; used to find .heromeshrc and .heromeshsession files. .PP Any of the SDL environment variables can also be used. .SH "PORTABLE MODE" There is a "portable mode" available. The following rules are used to determine if portable mode should be used: .PP 1. If the -h switch is specified, use home mode. .PP 2. If the HEROMESH_PREFIX environment variable is nonempty, use portable mode. .PP 3. If argv[0] contains a forward slash, use portable mode. In this case, the files are named "current.heromeshrc" and "current.heromeshsession" in the directory where the executable file is found. .PP 4. Otherwise, use home mode. |