1 /******************************************************************************
2 *******************************************************************************
3 *******************************************************************************
4
5 Copyright (C) 2013 Ben Martin
6
7 This file is part of FontForge.
8
9 FontForge is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation,either version 3 of the License, or
12 (at your option) any later version.
13
14 FontForge is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with FontForge. If not, see <http://www.gnu.org/licenses/>.
21
22 For more details see the COPYING.gplv3 file in the root directory of this
23 distribution.
24
25 *******************************************************************************
26 *******************************************************************************
27 ******************************************************************************/
28
29 #include <fontforge-config.h>
30
31 #include "sfundo.h"
32
33 #include "fvfonts.h"
34 #include "sfd.h"
35 #include "uiinterface.h"
36 #include "views.h"
37
38 #include <string.h>
39
SFUndoFreeAssociated(struct sfundoes * undo)40 void SFUndoFreeAssociated( struct sfundoes *undo )
41 {
42 if( undo->sfdchunk )
43 free( undo->sfdchunk );
44 }
45
SFUndoFree(struct sfundoes * undo)46 void SFUndoFree( struct sfundoes *undo )
47 {
48 SFUndoFreeAssociated( undo );
49 free( undo );
50 }
51
SFUndoRemoveAndFree(SplineFont * sf,struct sfundoes * undo)52 void SFUndoRemoveAndFree( SplineFont *sf, struct sfundoes *undo )
53 {
54 SFUndoFreeAssociated( undo );
55 dlist_erase( (struct dlistnode **)&sf->undoes, (struct dlistnode *)undo );
56 free(undo);
57 }
58
59
SFUndoCreateSFD(enum sfundotype t,char * staticmsg,char * sfdfrag)60 SFUndoes* SFUndoCreateSFD( enum sfundotype t, char* staticmsg, char* sfdfrag )
61 {
62 SFUndoes* undo = chunkalloc(sizeof(SFUndoes));
63 undo->ln.next = 0;
64 undo->ln.prev = 0;
65 undo->msg = staticmsg;
66 undo->type = t;
67 undo->sfdchunk = sfdfrag;
68 return undo;
69 }
70
SFUndoToString(SFUndoes * undo)71 char* SFUndoToString( SFUndoes* undo )
72 {
73 FILE* sfd;
74 if( (sfd = MakeTemporaryFile()) )
75 {
76 fprintf(sfd,"BeginFontLevelUndo\n");
77 fprintf(sfd,"FontLevelUndoType:%d\n",undo->type);
78 fprintf(sfd,"FontLevelUndoMessage:%s\n",undo->msg);
79 if( undo->sfdchunk )
80 fprintf(sfd,"%s\n", undo->sfdchunk );
81 fprintf(sfd,"EndFontLevelUndo\n");
82
83 char* str = FileToAllocatedString( sfd );
84 fclose( sfd );
85 return str;
86 }
87 return 0;
88 }
89
findterm(char ** str,char * term)90 static char* findterm( char** str, char* term )
91 {
92 char* p;
93 if( (p = strstr( *str, term )) )
94 {
95 p += strlen( term );
96 char* e = p;
97 while( *e && *e!='\n')
98 e++;
99 if( *e )
100 {
101 *e = '\0';
102 (*str) = e+1;
103 return p;
104 }
105 }
106 return NULL;
107 }
108
SFUndoFromString(char * str)109 SFUndoes* SFUndoFromString( char* str )
110 {
111 enum sfundotype t = sfut_fontinfo;
112 char* staticmsg = "fixme";
113 char* sfdfrag = str;
114
115 if( !strncmp( str, "BeginFontLevelUndo", strlen("BeginFontLevelUndo")))
116 {
117 char* p;
118 if( (p = findterm( &str, "FontLevelUndoType:" )) )
119 t = atoi(p);
120 if( (p = findterm( &str, "FontLevelUndoMessage:" )) )
121 staticmsg = p;
122 }
123
124 SFUndoes* ret = SFUndoCreateSFD( t, staticmsg, sfdfrag );
125 return ret;
126 }
127
SFUndoCreateRedo(SFUndoes * undo,SplineFont * sf)128 SFUndoes* SFUndoCreateRedo( SFUndoes* undo, SplineFont* sf )
129 {
130 SFUndoes* ret = 0;
131 char* sfdfrag = 0;
132
133 switch(undo->type) {
134 case sfut_fontinfo:
135
136 sfdfrag = DumpSplineFontMetadata( sf );
137 ret = SFUndoCreateSFD( sfut_fontinfo,
138 _("Font Information Dialog"),
139 sfdfrag );
140
141 break;
142 }
143
144 return ret;
145 }
146
SFUndoPerform(SFUndoes * undo,SplineFont * sf)147 void SFUndoPerform( SFUndoes* undo, SplineFont* sf )
148 {
149 char* sfdchunk = 0;
150 FILE* sfd = 0;
151
152 switch(undo->type) {
153 case sfut_fontinfo:
154 sfdchunk = undo->sfdchunk;
155 // printf("font level undo, font info sfd:%s\n", sfdchunk );
156 sfd = MakeTemporaryFile();
157 fwrite( sfdchunk, strlen(sfdchunk), 1, sfd );
158 fseek( sfd, 0, SEEK_SET );
159
160 SFD_GetFontMetaDataData d;
161 SFD_GetFontMetaDataData_Init( &d );
162 visitSFDFragment( sfd, sf, SFD_GetFontMetaDataVoid, &d );
163 break;
164 case sfut_lookups_kerns:
165 case sfut_lookups:
166 sfdchunk = undo->sfdchunk;
167 if( !sfdchunk ) {
168 ff_post_error(_("Undo information incomplete"),_("There is a splinefont level undo, but it does not contain any information to perform the undo. This is an application error, please report what you last did to the lookup tables so the developers can try to reproduce the issue and fix it."));
169 SFUndoRemoveAndFree( sf, undo );
170 return;
171 }
172
173 // Roll it on back!
174 sfd = MakeTemporaryFile();
175 fwrite( sfdchunk, strlen(sfdchunk), 1, sfd );
176 fseek( sfd, 0, SEEK_SET );
177
178 while( 1 ) {
179 char* name = SFDMoveToNextStartChar( sfd );
180 if( !name )
181 break;
182
183 int unienc = 0;
184 SplineChar *sc;
185 sc = SFGetChar( sf, unienc, name );
186 if( !sc ) {
187 ff_post_error(_("Bad undo"),_("couldn't find the character %s"), name );
188 break;
189 }
190 if( sc ) {
191 // Free the stuff in sc->psts so we don't leak it.
192 if( undo->type == sfut_lookups ) {
193 PSTFree(sc->possub);
194 sc->possub = 0;
195 }
196 char tok[2000];
197 getname( sfd, tok );
198 SFDGetPSTs( sfd, sc, tok );
199 SFDGetKerns( sfd, sc, tok );
200 }
201 free(name);
202 }
203
204 if( undo->type == sfut_lookups_kerns ) {
205 SFDFixupRefs( sf );
206 }
207 break;
208 default:
209 break;
210 }
211 }
212
SFUndoPushFront(struct sfundoes ** undoes,SFUndoes * undo)213 void SFUndoPushFront( struct sfundoes ** undoes, SFUndoes* undo )
214 {
215 dlist_pushfront( (struct dlistnode **)undoes, (struct dlistnode *)undo );
216 }
217