Index: config.doc ================================================================== --- config.doc +++ config.doc @@ -80,10 +80,14 @@ .pasteCommand The command to use for pasting text from the clipboard. When it asks for a single line of text, you can push SHIFT+INSERT to paste. +.picedit.macro.? + Define a macro in the picture editor, if you push ALT and a letter, + will execute a SQL statement. + .progress If positive, how many steps between dots in the progress report for the auto testing mode. If negative, number of milliseconds to sleep before each level is executed. Index: picedit.c ================================================================== --- picedit.c +++ picedit.c @@ -64,10 +64,11 @@ static Uint8 cur_type; static Uint8 gsizes[16]; static Picture*cur_pic; static Picture*spare_page; +static sqlite3_stmt**macro[26]; static void fn_valid_name(sqlite3_context*cxt,int argc,sqlite3_value**argv) { const char*s=sqlite3_value_text(*argv); if(!s || !*s || s[strspn(s,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-0123456789")]) { sqlite3_result_error(cxt,"Invalid name",-1); @@ -158,10 +159,23 @@ .xNext=vt_graph_next, .xOpen=vt_graph_open, .xRowid=vt_graph_rowid, .xUpdate=vt_graph_update, }; + +static void*load_macros_1(xrm_db*db,void*usr,int loose,xrm_quark q) { + const char*txt; + if(q<Q_A || q>Q_Z) return 0; + if(!(db=xrm_sub(db,loose,q)) || !(txt=xrm_get(db))) return 0; + if(sqlite3_prepare_v3(userdb,txt,-1,SQLITE_PREPARE_PERSISTENT,macro+(q-Q_A),0)) fatal("Error in macro: %s\n%s\n",txt,sqlite3_errmsg(userdb)); + return 0; +} + +static void*load_macros(xrm_db*db,void*usr) { + xrm_enumerate(db,load_macros_1,0); + return 0; +} static int load_picture_file(void) { sqlite3_stmt*st=0; FILE*fp; char*nam; @@ -910,10 +924,41 @@ } goto redraw; } break; case SDL_KEYDOWN: + if((ev.key.keysym.mod&(KMOD_ALT|KMOD_META)) && ev.key.keysym.sym>=SDLK_a && ev.key.keysym.sym<=SDLK_z) { + sqlite3_stmt*st=macro[ev.key.keysym.sym-SDLK_a]; + if(!st) goto redraw; + sqlite3_reset(st); + sqlite3_bind_int(st,sqlite3_bind_parameter_index(st,"$cc"),cc); + sqlite3_bind_int(st,sqlite3_bind_parameter_index(st,"$xx"),xx); + sqlite3_bind_int(st,sqlite3_bind_parameter_index(st,"$yy"),yy); + sqlite3_bind_int(st,sqlite3_bind_parameter_index(st,"$mx"),m.x); + sqlite3_bind_int(st,sqlite3_bind_parameter_index(st,"$my"),m.y); + sqlite3_bind_int(st,sqlite3_bind_parameter_index(st,"$mw"),m.w); + sqlite3_bind_int(st,sqlite3_bind_parameter_index(st,"$mh"),m.h); + while((i=sqlite3_step(st))==SQLITE_ROW) { + for(j=0;j<sqlite3_data_count(st);) switch(sqlite3_column_int(st,j++)) { + case 1: + xx=sqlite3_column_int(st,j++); + yy=sqlite3_column_int(st,j++); + break; + case 2: + m.x=sqlite3_column_int(st,j++); + m.y=sqlite3_column_int(st,j++); + m.w=sqlite3_column_int(st,j++); + m.h=sqlite3_column_int(st,j++); + break; + case 3: + cc=sqlite3_column_int(st,j++); + break; + } + } + if(i!=SQLITE_DONE) screen_message(sqlite3_errmsg(userdb)); + goto redraw; + } switch(ev.key.keysym.sym) { case SDLK_ESCAPE: return; case SDLK_LEFTBRACKET: case SDLK_LEFTPAREN: --sel; m.x=m.y=m.w=m.h=0; goto redraw; case SDLK_RIGHTBRACKET: case SDLK_RIGHTPAREN: ++sel; m.x=m.y=m.w=m.h=0; goto redraw; case SDLK_1 ... SDLK_9: sel=ev.key.keysym.sym-SDLK_1; m.x=m.y=m.w=m.h=0; goto redraw; @@ -1626,10 +1671,13 @@ sqlite3_create_function(userdb,"VALID_NAME",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_valid_name,0,0); sqlite3_create_module(userdb,"GRAPH",&vt_graph,0); init_palette(); optionquery[1]=Q_imageSize; picture_size=strtol(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"16",0,10); + optionquery[1]=Q_picedit; + optionquery[2]=Q_macro; + xrm_search(resourcedb,optionquery,optionquery,3,load_macros,0); if(!*gsizes) *gsizes=picture_size; set_cursor(XC_arrow); set_caption(); i=sqlite3_prepare_v3(userdb,"SELECT `ID`,SUBSTR(`NAME`,1,LENGTH(`NAME`)-4),`TYPE` FROM `PICEDIT` WHERE `TYPE` ORDER BY `NAME` LIMIT ?1 OFFSET ?2;",-1,SQLITE_PREPARE_PERSISTENT,&st,0); if(i) fatal("SQL error (%d): %s\n",i,sqlite3_errmsg(userdb)); Index: quarks ================================================================== --- quarks +++ quarks @@ -196,10 +196,14 @@ ! Solutions saveSolutions solutionComment solutionTimestamp + +! Picture editor +picedit +macro ! SQL settings sqlFile sqlInit sqlExtensions Index: quarks.h ================================================================== --- quarks.h +++ quarks.h @@ -165,31 +165,33 @@ #define Q_class 166 #define Q_quiz 167 #define Q_saveSolutions 168 #define Q_solutionComment 169 #define Q_solutionTimestamp 170 -#define Q_sqlFile 171 -#define Q_sqlInit 172 -#define Q_sqlExtensions 173 -#define Q_sqlMemStatus 174 -#define Q_sqlSmallAllocations 175 -#define Q_sqlCoveringIndexScan 176 -#define Q_sqlPowerSafe 177 -#define Q_level 178 -#define Q_tracePrefix 179 -#define Q_stackProtection 180 -#define Q_maxObjects 181 -#define Q_traceAll 182 -#define Q_traceObject 183 -#define Q_showInventory 184 -#define Q_progress 185 -#define Q_autoSave 186 -#define Q_maxTrigger 187 -#define Q_pasteCommand 188 -#define Q_codepage 189 -#define Q_replaySpeed 190 -#define Q_autoWin 191 +#define Q_picedit 171 +#define Q_macro 172 +#define Q_sqlFile 173 +#define Q_sqlInit 174 +#define Q_sqlExtensions 175 +#define Q_sqlMemStatus 176 +#define Q_sqlSmallAllocations 177 +#define Q_sqlCoveringIndexScan 178 +#define Q_sqlPowerSafe 179 +#define Q_level 180 +#define Q_tracePrefix 181 +#define Q_stackProtection 182 +#define Q_maxObjects 183 +#define Q_traceAll 184 +#define Q_traceObject 185 +#define Q_showInventory 186 +#define Q_progress 187 +#define Q_autoSave 188 +#define Q_maxTrigger 189 +#define Q_pasteCommand 190 +#define Q_codepage 191 +#define Q_replaySpeed 192 +#define Q_autoWin 193 static const char*const global_quarks[]={ "screenWidth", "screenHeight", "margin", "palette", @@ -356,10 +358,12 @@ "class", "quiz", "saveSolutions", "solutionComment", "solutionTimestamp", + "picedit", + "macro", "sqlFile", "sqlInit", "sqlExtensions", "sqlMemStatus", "sqlSmallAllocations",