#if 0 gcc ${CFLAGS:--s -O2} -c -Wno-multichar picedit.c `sdl-config --cflags` exit #endif /* This program is part of Free Hero Mesh and is public domain. */ #include "SDL.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" #include "smallxrm.h" #include "heromesh.h" #include "quarks.h" #include "cursorshapes.h" typedef struct { Uint8 size; Uint8 data[0]; } Picture; static int load_picture_file(void) { sqlite3_stmt*st=0; FILE*fp; char*nam; char*buf=0; int r=0; int i,j; i=sqlite3_exec(userdb, "BEGIN;" "CREATE TEMPORARY TABLE `PICEDIT`(`ID` INTEGER PRIMARY KEY,`NAME` TEXT NOT NULL COLLATE NOCASE,`TYPE` INT,`DATA` BLOB);" "CREATE INDEX `PICEDIT_I1` ON `PICEDIT`(`NAME`,`TYPE`);" ,0,0,0); if(i) fatal("SQL error (%d): %s\n",i,sqlite3_errmsg(userdb)); nam=sqlite3_mprintf("%s.xclass",basefilename); if(!nam) fatal("Allocation failed\n"); fprintf(stderr,"Loading pictures...\n"); fp=fopen(nam,"r"); sqlite3_free(nam); if(!fp) { nam=0; fprintf(stderr,"%m\n"); goto done; } nam=malloc(256); if(!nam) fatal("Allocation failed\n"); i=sqlite3_prepare_v2(userdb,"INSERT INTO `PICEDIT`(`NAME`,`TYPE`,`DATA`) VALUES(?1,?2,?3);",-1,&st,0); if(i) fatal("SQL error (%d): %s\n",i,sqlite3_errmsg(userdb)); while(!feof(fp)) { i=0; while(j=fgetc(fp)) { if(j==EOF) goto done; if(i<255) nam[i++]=j; } nam[i]=0; sqlite3_reset(st); sqlite3_bind_text(st,1,nam,i,SQLITE_TRANSIENT); sqlite3_bind_int(st,2,j=(i>4 && !memcmp(".IMG",nam+i-4,4)?1:0)); r+=j; i=fgetc(fp)<<16; i|=fgetc(fp)<<24; i|=fgetc(fp)<<0; i|=fgetc(fp)<<8; if(!i) continue; buf=realloc(buf,i); if(!buf) fatal("Allocation failed\n"); fread(buf,1,i,fp); sqlite3_bind_blob(st,3,buf,i,SQLITE_TRANSIENT); while((i=sqlite3_step(st))==SQLITE_ROW); if(i!=SQLITE_DONE) fatal("SQL error (%d): %s\n",i,sqlite3_errmsg(userdb)); } done: if(st) sqlite3_finalize(st); if(fp) fclose(fp); free(nam); free(buf); fprintf(stderr,"Done\n"); return r; } static void save_picture_file(void) { sqlite3_stmt*st; FILE*fp; char*s=sqlite3_mprintf("%s.xclass",basefilename); int i; const char*nam; const char*buf; if(!s) fatal("Allocation failed\n"); fprintf(stderr,"Saving pictures...\n"); fp=fopen(s,"w"); if(!fp) fatal("Cannot open picture file for writing: %m\n"); sqlite3_free(s); i=sqlite3_prepare_v2(userdb,"SELECT `NAME`,`DATA` FROM `PICEDIT`;",-1,&st,0); if(i) fatal("SQL error (%d): %s\n",i,sqlite3_errmsg(userdb)); while((i=sqlite3_step(st))==SQLITE_ROW) { nam=sqlite3_column_text(st,0); buf=sqlite3_column_blob(st,1); i=sqlite3_column_bytes(st,1); if(!nam) continue; fwrite(nam,1,strlen(nam)+1,fp); fputc(i>>16,fp); fputc(i>>24,fp); fputc(i>>0,fp); fputc(i>>8,fp); if(i) fwrite(buf,1,i,fp); } if(i!=SQLITE_DONE) fprintf(stderr,"SQL error (%d): %s\n",i,sqlite3_errmsg(userdb)); done: if(st) sqlite3_finalize(st); if(fp) fclose(fp); fprintf(stderr,"Done\n"); } static sqlite3_int64 ask_picture_id(const char*t) { sqlite3_stmt*st; const char*r=screen_prompt(t); int i; sqlite3_int64 id=0; if(!r || !*r) return 0; i=sqlite3_prepare_v2(userdb,"SELECT `ID` FROM `PICEDIT` WHERE `NAME` = (?1 || '.IMG');",-1,&st,0); if(i) { screen_message(sqlite3_errmsg(userdb)); return 0; } sqlite3_bind_text(st,1,r,-1,0); i=sqlite3_step(st); if(i==SQLITE_ROW) id=sqlite3_column_int64(st,0); if(i==SQLITE_DONE) screen_message("Picture not found"); sqlite3_finalize(st); return id; } static void edit_picture(sqlite3_int64 id) { } static void set_caption(void) { char buf[256]; snprintf(buf,255,"Free Hero Mesh - %s - Picture",basefilename); SDL_WM_SetCaption(buf,buf); } void run_picture_editor(void) { sqlite3_int64*ids; SDL_Event ev; SDL_Rect r; sqlite3_stmt*st; int sc=0; int max=load_picture_file(); int i,n; init_palette(); 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)); ids=calloc(screen->h/8,sizeof(sqlite3_int64)); if(!ids) fatal("Allocation failed\n"); redraw: sqlite3_reset(st); if(sc>max-screen->h/8) sc=max-screen->h/8; if(sc<0) sc=0; sqlite3_bind_int(st,1,screen->h/8-1); sqlite3_bind_int(st,2,sc); SDL_LockSurface(screen); r.x=r.y=0; r.w=screen->w; r.h=screen->h; SDL_FillRect(screen,&r,0xF0); draw_text(0,0,"<ESC> Save/Quit <F1> Add <F2> Delete <F3> Edit",0xF0,0xFB); n=0; while((i=sqlite3_step(st))==SQLITE_ROW) { ids[n++]=sqlite3_column_int64(st,0); draw_text(16,8*n,sqlite3_column_text(st,1),0xF0,0xF7); if(8*n+8>screen->h-8) break; } SDL_UnlockSurface(screen); sqlite3_reset(st); r.y=8; r.h-=8; scrollbar(&sc,r.h/8,max,0,&r); SDL_Flip(screen); while(SDL_WaitEvent(&ev)) { if(ev.type!=SDL_VIDEOEXPOSE && scrollbar(&sc,screen->h/8,max,&ev,&r)) goto redraw; switch(ev.type) { case SDL_QUIT: return; case SDL_KEYDOWN: switch(ev.key.keysym.sym) { case SDLK_ESCAPE: if(!(ev.key.keysym.mod&(KMOD_SHIFT|KMOD_CTRL))) save_picture_file(); return; case SDLK_q: if(!(ev.key.keysym.mod&KMOD_CTRL)) break; if(!(ev.key.keysym.mod&KMOD_SHIFT)) save_picture_file(); return; case SDLK_HOME: sc=0; goto redraw; case SDLK_UP: if(sc) --sc; goto redraw; case SDLK_DOWN: ++sc; goto redraw; case SDLK_END: sc=max-screen->h/8; goto redraw; case SDLK_PAGEUP: sc-=screen->h/8-1; goto redraw; case SDLK_PAGEDOWN: sc+=screen->h/8-1; goto redraw; case SDLK_F3: *ids=ask_picture_id("Edit:"); if(*ids) edit_picture(*ids); goto redraw; } break; case SDL_MOUSEMOTION: set_cursor(XC_arrow); break; case SDL_VIDEOEXPOSE: goto redraw; } } }