Free Hero Mesh

Check-in [ffd9bad655]
Login
This is a mirror of the main repository for Free Hero Mesh. New tickets and changes will not be accepted at this mirror.
Overview
Comment:Start to implement dependent pictures in the picture editor. (Currently, it just does nothing.)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ffd9bad6555b39149194ddfc121311ae9788edc5
User & Date: user on 2021-04-12 03:43:36
Other Links: manifest | tags
Context
2021-04-12
23:18
Data structures for dependent images in picture editor check-in: 120405b3b4 user: user tags: trunk
03:43
Start to implement dependent pictures in the picture editor. (Currently, it just does nothing.) check-in: ffd9bad655 user: user tags: trunk
2021-04-11
17:12
Add another item into TODO list check-in: 52cb71156f user: user tags: trunk
Changes

Modified picedit.c from [c6a6f01d28] to [9f00b04720].

18
19
20
21
22
23
24


25
26
27
28
29
30
31
#include "quarks.h"
#include "cursorshapes.h"

typedef struct {
  Uint8 size,meth;
  Uint8 data[0]; // the first row is all 0, since the compression algorithm requires this
} Picture;



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);
    return;
  }







>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "quarks.h"
#include "cursorshapes.h"

typedef struct {
  Uint8 size,meth;
  Uint8 data[0]; // the first row is all 0, since the compression algorithm requires this
} Picture;

static Uint8 cur_type;

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);
    return;
  }
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    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);







|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    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:!memcmp(".DEP",nam+i-4,4)?2: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);
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  if(st) sqlite3_finalize(st);
  if(fp) fclose(fp);
  free(nam);
  free(buf);
  fprintf(stderr,"Done\n");
  sqlite3_exec(userdb,
    "CREATE TRIGGER `PICEDIT_T1` BEFORE INSERT ON `PICEDIT` BEGIN"
    "  SELECT RAISE(FAIL,'Duplicate name') FROM `PICEDIT` WHERE `NAME`=NEW.`NAME`;"
    "END;"
    "CREATE TRIGGER `PICEDIT_T2` BEFORE UPDATE OF `NAME` ON `PICEDIT` BEGIN"
    "  SELECT RAISE(FAIL,'Duplicate name') FROM `PICEDIT` WHERE `NAME`=NEW.`NAME`;"
    "END;"
  ,0,0,0);
  return r;
}

static void save_picture_file(void) {
  sqlite3_stmt*st;







|


|







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  if(st) sqlite3_finalize(st);
  if(fp) fclose(fp);
  free(nam);
  free(buf);
  fprintf(stderr,"Done\n");
  sqlite3_exec(userdb,
    "CREATE TRIGGER `PICEDIT_T1` BEFORE INSERT ON `PICEDIT` BEGIN"
    "  SELECT RAISE(FAIL,'Duplicate name') FROM `PICEDIT` WHERE REPLACE(`NAME`||'*','.IMG*','.DEP*')=REPLACE(NEW.`NAME`||'*','.IMG*','.DEP*');"
    "END;"
    "CREATE TRIGGER `PICEDIT_T2` BEFORE UPDATE OF `NAME` ON `PICEDIT` BEGIN"
    "  SELECT RAISE(FAIL,'Duplicate name') FROM `PICEDIT` WHERE REPLACE(`NAME`||'*','.IMG*','.DEP*')=REPLACE(NEW.`NAME`||'*','.IMG*','.DEP*');"
    "END;"
  ,0,0,0);
  return r;
}

static void save_picture_file(void) {
  sqlite3_stmt*st;
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

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 uncompress_picture(FILE*fp,Picture*pic) {
  Uint8*p=pic->data+pic->size;
  int c,n,t,x,y;







|






|
|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

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`, `TYPE` FROM `PICEDIT` WHERE `NAME` = (?1 || '.IMG') OR `NAME` = (?1 || '.DEP');",-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),cur_type=sqlite3_column_int(st,1);
  if(i==SQLITE_DONE) screen_message("Picture not found"),cur_type=0;
  sqlite3_finalize(st);
  return id;
}

static void uncompress_picture(FILE*fp,Picture*pic) {
  Uint8*p=pic->data+pic->size;
  int c,n,t,x,y;
924
925
926
927
928
929
930




931
932
933
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948

949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
  }
  sqlite3_bind_int64(st,1,id);
  sqlite3_bind_blob(st,2,buf,size,free);
  i=sqlite3_step(st);
  if(i!=SQLITE_DONE) screen_message(sqlite3_errmsg(userdb));
  sqlite3_finalize(st);
}





static int add_picture(int t) {
  sqlite3_stmt*st;
  const char*s=screen_prompt("Enter name of new picture:");
  int i;
  if(!s || !*s) return 0;
  if(sqlite3_prepare_v2(userdb,"INSERT INTO `PICEDIT`(`NAME`,`TYPE`,`DATA`) SELECT VALID_NAME(?1)||'.IMG',1,X'';",-1,&st,0)) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  sqlite3_bind_text(st,1,s,-1,0);

  i=sqlite3_step(st);
  sqlite3_finalize(st);
  if(i!=SQLITE_DONE) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  edit_picture(sqlite3_last_insert_rowid(userdb));

  return 1;
}

static int delete_picture(void) {
  sqlite3_stmt*st;
  const char*s=screen_prompt("Enter name of picture to delete:");
  int i;
  if(!s || !*s) return 0;
  if(sqlite3_prepare_v2(userdb,"DELETE FROM `PICEDIT` WHERE `NAME`=?1||'.IMG';",-1,&st,0)) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  sqlite3_bind_text(st,1,s,-1,0);
  i=sqlite3_step(st);
  sqlite3_finalize(st);
  if(i!=SQLITE_DONE) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  return 1;
}

static void rename_picture(void) {
  sqlite3_stmt*st;
  const char*s=screen_prompt("Old name:");
  int i;
  if(!s || !*s) return;
  if(sqlite3_prepare_v2(userdb,"UPDATE `PICEDIT` SET `NAME`=VALID_NAME(?2)||'.IMG' WHERE `NAME`=?1||'.IMG';",-1,&st,0)) {
    screen_message(sqlite3_errmsg(userdb));
    return;
  }
  sqlite3_bind_text(st,1,s,-1,SQLITE_TRANSIENT);
  s=screen_prompt("New name:");
  if(!s || !*s) {
    sqlite3_finalize(st);







>
>
>
>






|




>






|
>








|


















|







926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
  }
  sqlite3_bind_int64(st,1,id);
  sqlite3_bind_blob(st,2,buf,size,free);
  i=sqlite3_step(st);
  if(i!=SQLITE_DONE) screen_message(sqlite3_errmsg(userdb));
  sqlite3_finalize(st);
}

static void edit_dependent_picture(sqlite3_int64 rowid) {
  
}

static int add_picture(int t) {
  sqlite3_stmt*st;
  const char*s=screen_prompt("Enter name of new picture:");
  int i;
  if(!s || !*s) return 0;
  if(sqlite3_prepare_v2(userdb,"INSERT INTO `PICEDIT`(`NAME`,`TYPE`,`DATA`) SELECT VALID_NAME(?1)||CASE ?2 WHEN 1 THEN '.IMG' ELSE '.DEP' END,?2,X'';",-1,&st,0)) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  sqlite3_bind_text(st,1,s,-1,0);
  sqlite3_bind_int(st,2,t);
  i=sqlite3_step(st);
  sqlite3_finalize(st);
  if(i!=SQLITE_DONE) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  if(t==1) edit_picture(sqlite3_last_insert_rowid(userdb));
  if(t==2) edit_dependent_picture(sqlite3_last_insert_rowid(userdb));
  return 1;
}

static int delete_picture(void) {
  sqlite3_stmt*st;
  const char*s=screen_prompt("Enter name of picture to delete:");
  int i;
  if(!s || !*s) return 0;
  if(sqlite3_prepare_v2(userdb,"DELETE FROM `PICEDIT` WHERE `NAME`=?1||'.IMG' OR `NAME`=?1||'.DEP';",-1,&st,0)) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  sqlite3_bind_text(st,1,s,-1,0);
  i=sqlite3_step(st);
  sqlite3_finalize(st);
  if(i!=SQLITE_DONE) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  return 1;
}

static void rename_picture(void) {
  sqlite3_stmt*st;
  const char*s=screen_prompt("Old name:");
  int i;
  if(!s || !*s) return;
  if(sqlite3_prepare_v2(userdb,"UPDATE `PICEDIT` SET `NAME`=VALID_NAME(?2)||SUBSTR(`NAME`,-4) WHERE `NAME`=?1||'.IMG' OR `NAME`=?1||'.DEP';",-1,&st,0)) {
    screen_message(sqlite3_errmsg(userdb));
    return;
  }
  sqlite3_bind_text(st,1,s,-1,SQLITE_TRANSIENT);
  s=screen_prompt("New name:");
  if(!s || !*s) {
    sqlite3_finalize(st);
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
  if(sc>max-screen->h/8+1) sc=max-screen->h/8+1;
  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  <F4> Rename",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);







|



|







1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  if(sc>max-screen->h/8+1) sc=max-screen->h/8+1;
  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  <F4> Rename  <F5> AddDependent",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,sqlite3_column_int(st,2)==1?0xF7:0xF2);
    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);
1059
1060
1061
1062
1063
1064
1065
1066



1067
1068
1069
1070




1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
            else screen_message("Too many pictures");
            goto redraw;
          case SDLK_F2:
            max-=delete_picture();
            goto redraw;
          case SDLK_F3:
            *ids=ask_picture_id("Edit:");
            if(*ids) edit_picture(*ids);



            goto redraw;
          case SDLK_F4:
            rename_picture();
            goto redraw;




        }
        break;
      case SDL_MOUSEMOTION:
        set_cursor(XC_arrow);
        break;
      case SDL_VIDEOEXPOSE:
        goto redraw;
    }
  }
}







|
>
>
>




>
>
>
>










1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
            else screen_message("Too many pictures");
            goto redraw;
          case SDLK_F2:
            max-=delete_picture();
            goto redraw;
          case SDLK_F3:
            *ids=ask_picture_id("Edit:");
            if(*ids) {
              if(cur_type==1) edit_picture(*ids);
              else if(cur_type==2) edit_dependent_picture(*ids);
            }
            goto redraw;
          case SDLK_F4:
            rename_picture();
            goto redraw;
          case SDLK_F5:
            if(max<65535) max+=add_picture(2);
            else screen_message("Too many pictures");
            goto redraw;
        }
        break;
      case SDL_MOUSEMOTION:
        set_cursor(XC_arrow);
        break;
      case SDL_VIDEOEXPOSE:
        goto redraw;
    }
  }
}

Modified picedit.doc from [1293f34972] to [fdf1601d98].

24
25
26
27
28
29
30


31
32
33
34
35
36
37

The F2 key deletes a picture by name.

The F3 key allows entering a name of a picture to edit.

The F4 key renames a picture.




=== Drawing ===

The following keyboard commands are available:

Esc
  Leave the drawing screen.







>
>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

The F2 key deletes a picture by name.

The F3 key allows entering a name of a picture to edit.

The F4 key renames a picture.

The F5 key adds a dependent picture (see the below section).


=== Drawing ===

The following keyboard commands are available:

Esc
  Leave the drawing screen.
164
165
166
167
168
169
170





  Click the left button on one corner of the bounding rectangle of the
  ellipse, and then click the middle or right button on the other side.

Filled ellipse (S)
  Click the left button on one corner of the bounding rectangle of the
  ellipse, and then click the middle or right button on the other side.













>
>
>
>
>
166
167
168
169
170
171
172
173
174
175
176
177
  Click the left button on one corner of the bounding rectangle of the
  ellipse, and then click the middle or right button on the other side.

Filled ellipse (S)
  Click the left button on one corner of the bounding rectangle of the
  ellipse, and then click the middle or right button on the other side.


=== Dependent pictures ===

(Not implemented yet.)