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