Line data Source code
1 : /* -*- coding: utf-8 -*- */
2 : /* Copyright (C) 2000-2012 by George Williams */
3 : /*
4 : * Redistribution and use in source and binary forms, with or without
5 : * modification, are permitted provided that the following conditions are met:
6 :
7 : * Redistributions of source code must retain the above copyright notice, this
8 : * list of conditions and the following disclaimer.
9 :
10 : * Redistributions in binary form must reproduce the above copyright notice,
11 : * this list of conditions and the following disclaimer in the documentation
12 : * and/or other materials provided with the distribution.
13 :
14 : * The name of the author may not be used to endorse or promote products
15 : * derived from this software without specific prior written permission.
16 :
17 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : */
28 : #include "bitmapchar.h"
29 : #include "bvedit.h"
30 : #include "cvundoes.h"
31 : #include "encoding.h"
32 : #include "fontforgeui.h"
33 : #include "fvfonts.h"
34 : #include "splinefill.h"
35 : #include "splinesaveafm.h"
36 : #include <gkeysym.h>
37 : #include <utype.h>
38 : #include <ustring.h>
39 : #include <math.h>
40 : #include <locale.h>
41 : #include <gresource.h>
42 : #include <gresedit.h>
43 :
44 : #include "gutils/unicodelibinfo.h"
45 :
46 : int bv_width = 270, bv_height=250;
47 :
48 : extern int _GScrollBar_Width;
49 : extern struct lconv localeinfo;
50 : extern char *coord_sep;
51 : struct bvshows BVShows = { 1, 1, 1, 0 };
52 :
53 : #define RPT_BASE 3 /* Place to draw the pointer icon */
54 : #define RPT_DATA 24 /* x,y text after above */
55 : #define RPT_COLOR 40 /* Blob showing the foreground color */
56 :
57 0 : static void BVNewScale(BitmapView *bv) {
58 0 : int fh = bv->bdf->ascent+bv->bdf->descent;
59 :
60 0 : GScrollBarSetBounds(bv->vsb,-2*fh*bv->scale,4*fh*bv->scale,bv->height);
61 0 : GScrollBarSetBounds(bv->hsb,-3*fh*bv->scale,6*fh*bv->scale,bv->width);
62 0 : GScrollBarSetPos(bv->vsb,bv->yoff);
63 0 : GScrollBarSetPos(bv->hsb,bv->xoff);
64 :
65 0 : GDrawRequestExpose(bv->v,NULL,false);
66 0 : }
67 :
68 0 : static void BVFit(BitmapView *bv) {
69 : int left, right, top, bottom, hsc, wsc;
70 0 : int fh = bv->bdf->ascent+bv->bdf->descent;
71 : extern int palettes_docked;
72 0 : int offset = palettes_docked ? 80 : 0;
73 :
74 0 : if ( offset>bv->width ) offset = 0;
75 :
76 0 : bottom = bv->bc->ymin;
77 0 : top = bv->bc->ymax;
78 0 : left = bv->bc->xmin;
79 0 : right = bv->bc->xmax;
80 :
81 0 : if ( bottom>0 ) bottom = 0;
82 0 : if ( left>0 ) left = 0;
83 0 : if ( top==-1 && bottom==0 ) { /* Empty */
84 0 : top = bv->bdf->ascent;
85 0 : bottom = -bv->bdf->descent;
86 0 : if ( right==-1 ) right = fh;
87 : }
88 0 : if ( top<bottom ) IError("Bottom bigger than top!");
89 0 : if ( right<left ) IError("Left bigger than right!");
90 0 : top -= bottom;
91 0 : right -= left;
92 0 : if ( top==0 ) top = bv->bdf->pixelsize;
93 0 : if ( right==0 ) right = bv->bdf->pixelsize;
94 0 : wsc = (8*(bv->width-offset)) / (10*right);
95 0 : hsc = (8*bv->height) / (10*top);
96 0 : if ( wsc<hsc ) hsc = wsc;
97 0 : if ( hsc<=0 ) hsc = 1;
98 0 : if ( hsc>32 ) hsc = 32;
99 :
100 0 : bv->scale = hsc;
101 :
102 0 : bv->xoff = left+(bv->width-offset-right*bv->scale)/2 + offset;
103 0 : bv->yoff = bottom + (bv->height-top*bv->scale)/2;
104 0 : if ( bv->xoff<-3*fh*bv->scale ) bv->xoff = -3*fh*bv->scale;
105 0 : if ( bv->yoff<-2*fh*bv->scale ) bv->yoff = -2*fh*bv->scale;
106 :
107 0 : BVNewScale(bv);
108 0 : }
109 :
110 0 : static void BVUnlinkView(BitmapView *bv ) {
111 : BitmapView *test;
112 :
113 0 : if ( bv->bc->views == bv ) {
114 0 : bv->bc->views = bv->next;
115 : } else {
116 0 : for ( test=bv->bc->views; test->next!=bv && test->next!=NULL; test=test->next );
117 0 : if ( test->next==bv )
118 0 : test->next = bv->next;
119 : }
120 0 : if ( bv->bc->views==NULL ) {
121 : /* We just got rid of the last view. Do a little clean up */
122 : /* compress the bitmap, and get rid of the floating selection */
123 0 : BCCompressBitmap(bv->bc);
124 0 : BCFlattenFloat(bv->bc);
125 : }
126 0 : }
127 :
128 0 : static void BVRefreshImage(BitmapView *bv) {
129 : GRect box;
130 :
131 0 : box.x = 0; box.width = bv->infoh;
132 0 : box.y = bv->mbh; box.height = bv->infoh;
133 0 : GDrawRequestExpose(bv->gw,&box,false);
134 0 : }
135 :
136 0 : static void BCCharUpdate(BDFChar *bc) {
137 : BitmapView *bv;
138 :
139 0 : for ( bv = bc->views; bv!=NULL; bv=bv->next ) {
140 0 : GDrawRequestExpose(bv->v, NULL, false );
141 : /*BVRefreshImage(bv);*/ /* Select All gives us a blank image if we do this */
142 : }
143 0 : }
144 :
145 0 : static void BC_CharChangedUpdate(BDFChar *bc) {
146 : BDFFont *bdf;
147 : BitmapView *bv;
148 0 : int waschanged = bc->changed;
149 : FontView *fv;
150 : struct bdfcharlist *dlist;
151 :
152 0 : bc->changed = true;
153 0 : for ( bv = bc->views; bv!=NULL; bv=bv->next ) {
154 0 : GDrawRequestExpose(bv->v, NULL, false );
155 0 : BVRefreshImage(bv);
156 : }
157 :
158 0 : fv = (FontView *) (bc->sc->parent->fv);
159 0 : fv->b.sf->changed = true;
160 0 : if ( fv->show!=fv->filled ) {
161 0 : for ( bdf=fv->b.sf->bitmaps; bdf!=NULL && bdf->glyphs[bc->orig_pos]!=bc; bdf=bdf->next );
162 0 : if ( bdf!=NULL ) {
163 0 : FVRefreshChar(fv,bc->orig_pos);
164 0 : if ( fv->b.sf->onlybitmaps && !waschanged )
165 0 : FVToggleCharChanged(fv->b.sf->glyphs[bc->orig_pos]);
166 : }
167 : }
168 0 : for ( dlist=bc->dependents; dlist!=NULL; dlist=dlist->next )
169 0 : BC_CharChangedUpdate(dlist->bc);
170 0 : }
171 :
172 0 : static char *BVMakeTitles(BitmapView *bv, BDFChar *bc,char *buf) {
173 : char *title;
174 : SplineChar *sc;
175 0 : BDFFont *bdf = bv->bdf;
176 : char *uniname;
177 :
178 0 : sc = bc->sc;
179 : /* GT: This is the title for a window showing a bitmap character */
180 : /* GT: It will look something like: */
181 : /* GT: exclam at 33 size 12 from Arial */
182 : /* GT: $1 is the name of the glyph */
183 : /* GT: $2 is the glyph's encoding */
184 : /* GT: $3 is the pixel size of the bitmap font */
185 : /* GT: $4 is the font name */
186 0 : sprintf(buf,_("%1$.80s at %2$d size %3$d from %4$.80s"),
187 0 : sc!=NULL ? sc->name : "<Nameless>", bv->enc, bdf->pixelsize, sc==NULL ? "" : sc->parent->fontname);
188 0 : title = copy(buf);
189 :
190 : /* Enhance 'buf' description with Nameslist.txt unicode name definition */
191 0 : if ( (uniname=unicode_name(sc->unicodeenc))!=NULL ) {
192 0 : strcat(buf, " ");
193 0 : strcpy(buf+strlen(buf), uniname);
194 0 : free(uniname);
195 : }
196 0 : return( title );
197 : }
198 :
199 0 : void BVChangeBC(BitmapView *bv, BDFChar *bc, int fitit ) {
200 : char *title;
201 : char buf[300];
202 :
203 0 : BVUnlinkView(bv);
204 0 : bv->bc = bc;
205 0 : bv->next = bc->views;
206 0 : bc->views = bv;
207 :
208 0 : if ( fitit )
209 0 : BVFit(bv);
210 : else
211 0 : BVNewScale(bv);
212 0 : BVRefreshImage(bv);
213 :
214 0 : title = BVMakeTitles(bv,bc,buf);
215 0 : GDrawSetWindowTitles8(bv->gw,buf,title);
216 0 : free(title);
217 :
218 0 : BVPaletteChangedChar(bv);
219 0 : }
220 :
221 0 : static void BVChangeChar(BitmapView *bv, int i, int fitit ) {
222 : BDFChar *bc;
223 0 : BDFFont *bdf = bv->bdf;
224 0 : EncMap *map = bv->fv->b.map;
225 :
226 0 : if ( bv->fv->b.cidmaster!=NULL && !map->enc->is_compact && i<bdf->glyphcnt &&
227 0 : (bc=bdf->glyphs[i])!=NULL ) {
228 : /* The attached bitmap fonts don't have the complexities of subfonts-- they are flat */
229 : } else {
230 0 : if ( i<0 || i>=map->enccount )
231 0 : return;
232 0 : bc = BDFMakeChar(bdf,map,i);
233 : }
234 :
235 0 : if ( bc==NULL || bv->bc == bc )
236 0 : return;
237 0 : bv->map_of_enc = map;
238 0 : bv->enc = i;
239 :
240 0 : BVChangeBC(bv,bc,fitit);
241 : }
242 :
243 : static void BVDoClear(BitmapView *bv);
244 : static void BVHScroll(BitmapView *bv,struct sbevent *sb);
245 : static void BVVScroll(BitmapView *bv,struct sbevent *sb);
246 :
247 0 : void BVChar(BitmapView *bv, GEvent *event ) {
248 : BDFRefChar *head;
249 : extern int navigation_mask;
250 :
251 : #if _ModKeysAutoRepeat
252 : /* Under cygwin these keys auto repeat, they don't under normal X */
253 : if ( bv->autorpt!=NULL ) {
254 : GDrawCancelTimer(bv->autorpt); bv->autorpt = NULL;
255 : if ( bv->keysym == event->u.chr.keysym ) /* It's an autorepeat, ignore it */
256 : return;
257 : BVToolsSetCursor(bv,bv->oldstate,NULL);
258 : }
259 : #endif
260 :
261 0 : BVPaletteActivate(bv);
262 0 : BVToolsSetCursor(bv,TrueCharState(event),NULL);
263 0 : if ( event->u.chr.keysym=='s' &&
264 0 : (event->u.chr.state&ksm_control) &&
265 0 : (event->u.chr.state&ksm_meta) )
266 0 : MenuSaveAll(NULL,NULL,NULL);
267 0 : else if ( !(event->u.chr.state&(ksm_control|ksm_meta)) &&
268 0 : event->u.chr.keysym == GK_BackSpace ) {
269 : /* Menu does delete */
270 0 : BVDoClear(bv);
271 0 : } else if ( event->u.chr.keysym == GK_Help ) {
272 0 : MenuHelp(NULL,NULL,NULL); /* Menu does F1 */
273 0 : } else if ( event->u.chr.keysym == GK_Left ||
274 0 : event->u.chr.keysym == GK_Up ||
275 0 : event->u.chr.keysym == GK_Right ||
276 0 : event->u.chr.keysym == GK_Down ||
277 0 : event->u.chr.keysym == GK_KP_Left ||
278 0 : event->u.chr.keysym == GK_KP_Up ||
279 0 : event->u.chr.keysym == GK_KP_Right ||
280 0 : event->u.chr.keysym == GK_KP_Down ||
281 0 : event->u.chr.keysym == GK_KP_Home ||
282 0 : event->u.chr.keysym == GK_Home ) {
283 0 : int xoff=0, yoff=0;
284 0 : if ( event->u.chr.keysym == GK_Up || event->u.chr.keysym == GK_KP_Up )
285 0 : yoff = 1;
286 0 : else if ( event->u.chr.keysym == GK_Down || event->u.chr.keysym == GK_KP_Down )
287 0 : yoff = -1;
288 0 : else if ( event->u.chr.keysym == GK_Right || event->u.chr.keysym == GK_KP_Right )
289 0 : xoff = 1;
290 0 : else if ( event->u.chr.keysym == GK_Left || event->u.chr.keysym == GK_KP_Left )
291 0 : xoff = -1;
292 0 : else if ( event->u.chr.keysym == GK_Home || event->u.chr.keysym == GK_KP_Home ) {
293 0 : if ( bv->bc->selection==NULL ) {
294 0 : xoff = -bv->bc->xmin;
295 0 : yoff = -bv->bc->ymin;
296 : } else {
297 0 : xoff = bv->bc->xmin-bv->bc->selection->xmin;
298 0 : yoff = bv->bc->ymin-bv->bc->selection->ymin;
299 : }
300 : }
301 0 : if ( event->u.chr.state & (ksm_meta|ksm_control) ) {
302 : struct sbevent sb;
303 0 : sb.type = yoff>0 || xoff<0 ? et_sb_halfup : et_sb_halfdown;
304 0 : if ( xoff==0 )
305 0 : BVVScroll(bv,&sb);
306 : else
307 0 : BVHScroll(bv,&sb);
308 : } else {
309 0 : BCPreserveState(bv->bc);
310 0 : if ( bv->bc->selection==NULL ) {
311 0 : bv->bc->xmin += xoff; bv->bc->xmax += xoff;
312 0 : bv->bc->ymin += yoff; bv->bc->ymax += yoff;
313 0 : for ( head=bv->bc->refs; head!=NULL; head=head->next ) {
314 0 : if ( head->selected ) {
315 0 : head->xoff += xoff;
316 0 : head->yoff += yoff;
317 : }
318 : }
319 : } else {
320 0 : bv->bc->selection->xmin += xoff;
321 0 : bv->bc->selection->xmax += xoff;
322 0 : bv->bc->selection->ymin += yoff;
323 0 : bv->bc->selection->ymax += yoff;
324 : }
325 0 : BCCharChangedUpdate(bv->bc);
326 : }
327 0 : } else if ( (event->u.chr.state&((GMenuMask()|navigation_mask)&~(ksm_shift|ksm_capslock)))==navigation_mask &&
328 0 : event->type == et_char &&
329 0 : event->u.chr.keysym!=0 &&
330 0 : (event->u.chr.keysym<GK_Special /*|| event->u.chr.keysym>=0x10000*/)) {
331 0 : SplineFont *sf = bv->bc->sc->parent;
332 : int i;
333 0 : EncMap *map = bv->fv->b.map;
334 : extern int cv_auto_goto;
335 0 : if ( cv_auto_goto ) {
336 0 : i = SFFindSlot(sf,map,event->u.chr.keysym,NULL);
337 0 : if ( i!=-1 )
338 0 : BVChangeChar(bv,i,false);
339 : }
340 : }
341 0 : }
342 :
343 0 : static int BVCurEnc(BitmapView *bv) {
344 0 : if ( bv->map_of_enc == bv->fv->b.map && bv->enc!=-1 )
345 0 : return( bv->enc );
346 :
347 0 : return( bv->fv->b.map->backmap[bv->bc->orig_pos] );
348 : }
349 :
350 0 : static void BVCharUp(BitmapView *bv, GEvent *event ) {
351 0 : if ( event->u.chr.keysym=='I' &&
352 0 : (event->u.chr.state&ksm_shift) &&
353 0 : (event->u.chr.state&ksm_meta) )
354 0 : SCCharInfo(bv->bc->sc,bv->fv->b.active_layer,bv->fv->b.map,BVCurEnc(bv));
355 : #if _ModKeysAutoRepeat
356 : /* Under cygwin these keys auto repeat, they don't under normal X */
357 : else if ( event->u.chr.keysym == GK_Shift_L || event->u.chr.keysym == GK_Shift_R ||
358 : event->u.chr.keysym == GK_Control_L || event->u.chr.keysym == GK_Control_R ||
359 : event->u.chr.keysym == GK_Meta_L || event->u.chr.keysym == GK_Meta_R ||
360 : event->u.chr.keysym == GK_Alt_L || event->u.chr.keysym == GK_Alt_R ||
361 : event->u.chr.keysym == GK_Super_L || event->u.chr.keysym == GK_Super_R ||
362 : event->u.chr.keysym == GK_Hyper_L || event->u.chr.keysym == GK_Hyper_R ) {
363 : if ( bv->autorpt!=NULL ) {
364 : GDrawCancelTimer(bv->autorpt);
365 : BVToolsSetCursor(bv,bv->oldstate,NULL);
366 : }
367 : bv->keysym = event->u.chr.keysym;
368 : bv->oldstate = TrueCharState(event);
369 : bv->autorpt = GDrawRequestTimer(bv->v,100,0,NULL);
370 : } else {
371 : if ( bv->autorpt!=NULL ) {
372 : GDrawCancelTimer(bv->autorpt); bv->autorpt=NULL;
373 : BVToolsSetCursor(bv,bv->oldstate,NULL);
374 : }
375 : BVToolsSetCursor(bv,TrueCharState(event),NULL);
376 : }
377 : #else
378 0 : BVToolsSetCursor(bv,TrueCharState(event),NULL);
379 : #endif
380 0 : }
381 :
382 0 : static void BVDrawTempPoint(BitmapView *bv,int x, int y,void *pixmap) {
383 : GRect pixel;
384 :
385 0 : pixel.width = pixel.height = bv->scale+1;
386 0 : pixel.x = bv->xoff + x*bv->scale;
387 0 : pixel.y = bv->height-bv->yoff-(y+1)*bv->scale;
388 0 : GDrawSetStippled(pixmap,1, 0,0);
389 0 : GDrawFillRect(pixmap,&pixel,0x909000);
390 0 : GDrawSetStippled(pixmap,0, 0,0);
391 0 : }
392 :
393 0 : static void BVDrawRefBorder(BitmapView *bv, BDFChar *bc, GWindow pixmap,
394 : uint8 selected, int8 xoff, int8 yoff) {
395 : int i, j;
396 : int isblack, lw, rw, tw, bw;
397 : int tx, ty;
398 0 : Color outcolor = selected ? 0x606000 : 0x606060;
399 :
400 0 : for ( i=bc->ymax-bc->ymin; i>=0; --i ) {
401 0 : for ( j=0; j<=bc->xmax-bc->xmin; ++j ) {
402 0 : tx = bv->xoff + (bc->xmin + xoff +j)*bv->scale;
403 0 : ty = bv->height-bv->yoff - (bc->ymax + yoff - i)*bv->scale;
404 :
405 0 : isblack = ( !bc->byte_data &&
406 0 : ( bc->bitmap[i*bc->bytes_per_line+(j>>3)] & (1<<(7-(j&7))))) ||
407 0 : ( bc->byte_data && bc->bitmap[i*bc->bytes_per_line+j] != 0 );
408 0 : if ( !isblack )
409 0 : continue;
410 0 : lw = ( j == 0 || ( !bc->byte_data &&
411 0 : !( bc->bitmap[i*bc->bytes_per_line+((j-1)>>3)] & (1<<(7-((j-1)&7))))) ||
412 0 : ( bc->byte_data && bc->bitmap[i*bc->bytes_per_line+j-1] == 0 ));
413 0 : rw = ( j == bc->xmax-bc->xmin || ( !bc->byte_data &&
414 0 : !( bc->bitmap[i*bc->bytes_per_line+((j+1)>>3)] & (1<<(7-((j+1)&7))))) ||
415 0 : ( bc->byte_data && bc->bitmap[i*bc->bytes_per_line+j+1] == 0 ));
416 0 : tw = ( i == bc->ymax-bc->ymin || ( !bc->byte_data &&
417 0 : !( bc->bitmap[(i+1)*bc->bytes_per_line+(j>>3)] & (1<<(7-(j&7))))) ||
418 0 : ( bc->byte_data && bc->bitmap[(i+1)*bc->bytes_per_line+j] == 0 ));
419 0 : bw = ( i == 0 || ( !bc->byte_data &&
420 0 : !( bc->bitmap[(i-1)*bc->bytes_per_line+(j>>3)] & (1<<(7-(j&7))))) ||
421 0 : ( bc->byte_data && bc->bitmap[(i-1)*bc->bytes_per_line+j] == 0 ));
422 :
423 0 : if ( lw )
424 0 : GDrawDrawLine(pixmap,tx+1,ty, tx+1,ty-bv->scale,outcolor);
425 0 : if ( rw )
426 0 : GDrawDrawLine(pixmap,tx+bv->scale-1,ty, tx+bv->scale-1,ty-bv->scale,outcolor);
427 0 : if ( tw )
428 0 : GDrawDrawLine(pixmap,tx,ty-1, tx+bv->scale,ty-1,outcolor);
429 0 : if ( bw )
430 0 : GDrawDrawLine(pixmap,tx,ty-bv->scale+1, tx+bv->scale,ty-bv->scale+1,outcolor);
431 : }
432 : }
433 0 : }
434 :
435 0 : static void BVDrawSelection(BitmapView *bv,void *pixmap) {
436 : GRect pixel, rect;
437 0 : BDFFloat *sel = bv->bc->selection;
438 0 : GClut *clut = bv->bdf->clut;
439 0 : Color bg = view_bgcol;
440 : int i,j;
441 :
442 0 : pixel.width = pixel.height = bv->scale+1;
443 0 : for ( i=sel->ymax-sel->ymin; i>=0; --i ) {
444 0 : for ( j=0; j<=sel->xmax-sel->xmin; ++j ) {
445 0 : pixel.x = bv->xoff + (sel->xmin+j)*bv->scale;
446 0 : pixel.y = bv->height-bv->yoff-(sel->ymax-i+1)*bv->scale;
447 0 : if ( clut==NULL ) {
448 0 : if ( sel->bitmap[i*sel->bytes_per_line+(j>>3)] & (1<<(7-(j&7))) ) {
449 0 : GDrawFillRect(pixmap,&pixel,0x808080);
450 : } else {
451 0 : GDrawFillRect(pixmap,&pixel,bg);
452 : }
453 : } else
454 0 : GDrawFillRect(pixmap,&pixel,
455 0 : clut->clut[sel->bitmap[i*sel->bytes_per_line+j]]);
456 : }
457 : }
458 0 : GDrawSetStippled(pixmap,1, 0,0);
459 0 : rect.width = (sel->xmax-sel->xmin+1)*bv->scale;
460 0 : rect.height = (sel->ymax-sel->ymin+1)*bv->scale;
461 0 : rect.x = bv->xoff + sel->xmin*bv->scale;
462 0 : rect.y = bv->height-bv->yoff-(sel->ymax+1)*bv->scale;
463 0 : GDrawFillRect(pixmap,&rect,0x909000);
464 0 : GDrawSetStippled(pixmap,0, 0,0);
465 0 : }
466 :
467 0 : static void BCBresenhamLine(BitmapView *bv,
468 : void (*SetPoint)(BitmapView *,int x, int y, void *data),void *data) {
469 : /* Draw a line from (pressed_x,pressed_y) to (info_x,info_y) */
470 : /* and call SetPoint for each point */
471 : int dx,dy,incr1,incr2,d,x,y,xend;
472 0 : int x1 = bv->pressed_x, y1 = bv->pressed_y;
473 0 : int x2 = bv->info_x, y2 = bv->info_y;
474 : int up;
475 :
476 0 : if ( y2<y1 ) {
477 0 : y2 ^= y1; y1 ^= y2; y2 ^= y1;
478 0 : x2 ^= x1; x1 ^= x2; x2 ^= x1;
479 : }
480 0 : dy = y2-y1;
481 0 : if (( dx = x2-x1)<0 ) dx=-dx;
482 :
483 0 : if ( dy<=dx ) {
484 0 : d = 2*dy-dx;
485 0 : incr1 = 2*dy;
486 0 : incr2 = 2*(dy-dx);
487 0 : if ( x1>x2 ) {
488 0 : x = x2; y = y2;
489 0 : xend = x1;
490 0 : up = -1;
491 : } else {
492 0 : x = x1; y = y1;
493 0 : xend = x2;
494 0 : up = 1;
495 : }
496 0 : (SetPoint)(bv,x,y,data);
497 0 : while ( x<xend ) {
498 0 : ++x;
499 0 : if ( d<0 ) d+=incr1;
500 : else {
501 0 : y += up;
502 0 : d += incr2;
503 : }
504 0 : (SetPoint)(bv,x,y,data);
505 : }
506 : } else {
507 0 : d = 2*dx-dy;
508 0 : incr1 = 2*dx;
509 0 : incr2 = 2*(dx-dy);
510 0 : x = x1; y = y1;
511 0 : if ( x1>x2 ) up = -1; else up = 1;
512 0 : (SetPoint)(bv,x,y,data);
513 0 : while ( y<y2 ) {
514 0 : ++y;
515 0 : if ( d<0 ) d+=incr1;
516 : else {
517 0 : x += up;
518 0 : d += incr2;
519 : }
520 0 : (SetPoint)(bv,x,y,data);
521 : }
522 : }
523 0 : }
524 :
525 0 : static void CirclePoints(BitmapView *bv,int x, int y, int ox, int oy, int xmod, int ymod,
526 : void (*SetPoint)(BitmapView *,int x, int y, void *data),void *data) {
527 : /* we draw the quadrant between Pi/2 and 0 */
528 0 : if ( bv->active_tool == bvt_filledelipse ) {
529 : int j;
530 0 : for ( j=2*oy+ymod-y; j<=y; ++j ) {
531 0 : SetPoint(bv,x,j,data);
532 0 : SetPoint(bv,2*ox+xmod-x,j,data);
533 : }
534 : } else {
535 0 : SetPoint(bv,x,y,data);
536 0 : SetPoint(bv,x,2*oy+ymod-y,data);
537 0 : SetPoint(bv,2*ox+xmod-x,y,data);
538 0 : SetPoint(bv,2*ox+xmod-x,2*oy+ymod-y,data);
539 : }
540 0 : }
541 :
542 0 : void BCGeneralFunction(BitmapView *bv,
543 : void (*SetPoint)(BitmapView *,int x, int y, void *data),void *data) {
544 : int i, j;
545 : int xmin, xmax, ymin, ymax;
546 : int ox, oy, modx, mody;
547 : int dx, dy, c,d,dx2,dy2,xp,yp;
548 : int x,y;
549 :
550 0 : if ( bv->pressed_x<bv->info_x ) {
551 0 : xmin = bv->pressed_x; xmax = bv->info_x;
552 : } else {
553 0 : xmin = bv->info_x; xmax = bv->pressed_x;
554 : }
555 0 : if ( bv->pressed_y<bv->info_y ) {
556 0 : ymin = bv->pressed_y; ymax = bv->info_y;
557 : } else {
558 0 : ymin = bv->info_y; ymax = bv->pressed_y;
559 : }
560 :
561 0 : switch ( bv->active_tool ) {
562 : case bvt_line:
563 0 : BCBresenhamLine(bv,SetPoint,data);
564 0 : break;
565 : case bvt_rect:
566 0 : for ( i=xmin; i<=xmax; ++i ) {
567 0 : SetPoint(bv,i,bv->pressed_y,data);
568 0 : SetPoint(bv,i,bv->info_y,data);
569 : }
570 0 : for ( i=ymin; i<=ymax; ++i ) {
571 0 : SetPoint(bv,bv->pressed_x,i,data);
572 0 : SetPoint(bv,bv->info_x,i,data);
573 : }
574 0 : break;
575 : case bvt_filledrect:
576 0 : for ( i=xmin; i<=xmax; ++i ) {
577 0 : for ( j=ymin; j<=ymax; ++j )
578 0 : SetPoint(bv,i,j,data);
579 : }
580 0 : break;
581 : case bvt_elipse: case bvt_filledelipse:
582 0 : if ( xmax==xmin || ymax==ymin ) /* degenerate case */
583 0 : BCBresenhamLine(bv,SetPoint,data);
584 : else {
585 0 : ox = floor( (xmin+xmax)/2.0 );
586 0 : oy = floor( (ymin+ymax)/2.0 );
587 0 : modx = (xmax+xmin)&1; mody = (ymax+ymin)&1;
588 0 : dx = ox-xmin;
589 0 : dy = oy-ymin;
590 0 : dx2 = dx*dx; dy2 = dy*dy;
591 0 : xp = 0; yp = 4*dy*dx2;
592 0 : c = dy2+(2-4*dy)*dx2; d = 2*dy2 + (1-2*dy)*dx2;
593 0 : x = ox+modx; y = ymax;
594 0 : CirclePoints(bv,x,y,ox,oy,modx,mody,SetPoint,data);
595 0 : while ( x!=xmax ) {
596 : #define move_right() (c += 4*dy2+xp, d += 6*dy2+xp, ++x, xp += 4*dy2 )
597 : #define move_down() (c += 6*dx2-yp, d += 4*dx2-yp, --y, yp -= 4*dx2 )
598 0 : if ( d<0 || y==0 )
599 0 : move_right();
600 0 : else if ( c > 0 )
601 0 : move_down();
602 : else {
603 0 : move_right();
604 0 : move_down();
605 : }
606 : #undef move_right
607 : #undef move_down
608 0 : if ( y<oy ) /* degenerate cases */
609 0 : break;
610 0 : CirclePoints(bv,x,y,ox,oy,modx,mody,SetPoint,data);
611 : }
612 0 : if ( bv->active_tool==bvt_elipse ) {
613 : /* there may be quite a gap between the two semi-circles */
614 : /* because the tangent is nearly vertical here. So just fill */
615 : /* it in */
616 : int j;
617 0 : for ( j=2*oy+mody-y; j<=y; ++j ) {
618 0 : SetPoint(bv,x,j,data);
619 0 : SetPoint(bv,2*ox+modx-x,j,data);
620 : }
621 : }
622 : }
623 0 : break;
624 : }
625 0 : }
626 :
627 0 : static void BVDrawRefName(BitmapView *bv,GWindow pixmap,BDFRefChar *ref,int fg) {
628 : int x,y, len;
629 : GRect size;
630 : char *refinfo;
631 : IBounds bb;
632 :
633 0 : refinfo = malloc(strlen(ref->bdfc->sc->name) + 30);
634 0 : sprintf(refinfo,"%s XOff: %d YOff: %d", ref->bdfc->sc->name, ref->xoff, ref->yoff);
635 :
636 0 : bb.minx = ref->bdfc->xmin + ref->xoff;
637 0 : bb.maxx = ref->bdfc->xmax + ref->xoff;
638 0 : bb.miny = ref->bdfc->ymin + ref->yoff;
639 0 : bb.maxy = ref->bdfc->ymax + ref->yoff;
640 0 : BDFCharQuickBounds(ref->bdfc,&bb,ref->xoff,ref->yoff,false,true);
641 0 : x = bv->xoff + (bb.minx)*bv->scale;
642 0 : y = bv->height - bv->yoff - (bb.maxy + 1)*bv->scale;
643 0 : y -= 5;
644 0 : if ( x<-400 || y<-40 || x>bv->width+400 || y>bv->height )
645 : {
646 0 : free(refinfo);
647 0 : return;
648 : }
649 :
650 0 : GDrawLayoutInit(pixmap,refinfo,-1,bv->small);
651 0 : GDrawLayoutExtents(pixmap,&size);
652 0 : GDrawLayoutDraw(pixmap,x-size.width/2,y,fg);
653 0 : len = size.width;
654 0 : free(refinfo);
655 : }
656 :
657 0 : static void BVDrawGlyph(BitmapView *bv, BDFChar *bc, GWindow pixmap, GRect *pixel,
658 : uint8 is_ref, uint8 selected, int8 xoff, int8 yoff) {
659 : int i, j;
660 0 : int color = 0x808080;
661 0 : BDFFont *bdf = bv->bdf;
662 : BDFRefChar *cur;
663 :
664 0 : if ( is_ref && !selected )
665 0 : GDrawSetStippled(pixmap,1, 0,0);
666 0 : for ( i=bc->ymax-bc->ymin; i>=0; --i ) {
667 0 : for ( j=0; j<=bc->xmax-bc->xmin; ++j ) {
668 0 : pixel->x = bv->xoff + (bc->xmin + xoff +j)*bv->scale;
669 0 : pixel->y = bv->height-bv->yoff - (bc->ymax + yoff - i + 1)*bv->scale;
670 0 : if ( bdf->clut==NULL ) {
671 0 : if ( bc->bitmap[i*bc->bytes_per_line+(j>>3)] & (1<<(7-(j&7))) ) {
672 0 : GDrawFillRect(pixmap,pixel,color);
673 0 : if ( selected ) {
674 0 : GDrawSetStippled(pixmap,2, 0,0);
675 0 : GDrawFillRect(pixmap,pixel,0x909000);
676 0 : GDrawSetStippled(pixmap,0, 0,0);
677 : }
678 : }
679 : } else {
680 0 : int index = bc->bitmap[i*bc->bytes_per_line+j];
681 0 : if ( index!=0 ) {
682 0 : GDrawFillRect(pixmap,pixel,bdf->clut->clut[index]);
683 0 : if ( selected ) {
684 0 : GDrawSetStippled(pixmap,2, 0,0);
685 0 : GDrawFillRect(pixmap,pixel,0x909000);
686 0 : GDrawSetStippled(pixmap,0, 0,0);
687 : }
688 : }
689 : }
690 : }
691 : }
692 0 : if ( is_ref ) {
693 0 : GDrawSetStippled(pixmap,0, 0,0);
694 0 : BVDrawRefBorder( bv,bc,pixmap,selected,xoff,yoff );
695 : }
696 0 : for ( cur=bc->refs; cur!=NULL; cur=cur->next ) if ( cur->bdfc != NULL ) {
697 0 : BVDrawGlyph( bv,cur->bdfc,pixmap,pixel,true,(cur->selected | selected),
698 0 : xoff+cur->xoff,yoff+cur->yoff );
699 : }
700 0 : }
701 :
702 0 : static void BVExpose(BitmapView *bv, GWindow pixmap, GEvent *event ) {
703 : CharView cvtemp;
704 : GRect old;
705 : DRect clip;
706 : int i;
707 : GRect pixel;
708 0 : BDFChar *bc = bv->bc;
709 : BDFRefChar *bref;
710 : RefChar *refs;
711 : extern Color widthcol;
712 :
713 0 : GDrawPushClip(pixmap,&event->u.expose.rect,&old);
714 0 : GDrawSetLineWidth(pixmap,0);
715 0 : if ( bv->showfore ) {
716 : /* fore ground is a misnomer. it's what we're interested in but we */
717 : /* actually need to draw it first, otherwise it obscures everything */
718 0 : pixel.width = pixel.height = bv->scale+1;
719 0 : BVDrawGlyph( bv,bc,pixmap,&pixel,false,false,0,0 );
720 :
721 0 : if ( bv->active_tool!=bvt_none ) {
722 : /* This does nothing for many tools, but for lines, rects and circles */
723 : /* it draws temporary points */
724 0 : BCGeneralFunction(bv,BVDrawTempPoint,pixmap);
725 : }
726 : /* Selected references are handled in BVDrawGlyph() */
727 0 : if ( bv->bc->selection )
728 0 : BVDrawSelection(bv,pixmap);
729 : }
730 0 : if ( bv->showgrid ) {
731 0 : if ( bv->scale>2 ) {
732 0 : for ( i=bv->xoff+bv->scale; i<bv->width; i += bv->scale )
733 0 : GDrawDrawLine(pixmap,i,0, i,bv->height,0xa0a0a0);
734 0 : for ( i=bv->xoff-bv->scale; i>0; i -= bv->scale )
735 0 : GDrawDrawLine(pixmap,i,0, i,bv->height,0xa0a0a0);
736 0 : for ( i=-bv->yoff+bv->height-bv->scale; i>0; i -= bv->scale )
737 0 : GDrawDrawLine(pixmap,0,i,bv->width,i,0xa0a0a0);
738 0 : for ( i=-bv->yoff+bv->height+bv->scale; i<bv->height; i += bv->scale )
739 0 : GDrawDrawLine(pixmap,0,i,bv->width,i,0xa0a0a0);
740 : }
741 0 : GDrawDrawLine(pixmap,0,-bv->yoff+bv->height-0*bv->scale,bv->width,-bv->yoff+bv->height-0*bv->scale,0x404040);
742 0 : GDrawDrawLine(pixmap,0,-bv->yoff+bv->height-bv->bdf->ascent*bv->scale,
743 0 : bv->width,-bv->yoff+bv->height-bv->bdf->ascent*bv->scale,0x404040);
744 0 : GDrawDrawLine(pixmap,0,-bv->yoff+bv->height+bv->bdf->descent*bv->scale,
745 0 : bv->width,-bv->yoff+bv->height+bv->bdf->descent*bv->scale,0x404040);
746 0 : GDrawDrawLine(pixmap,bv->xoff+0*bv->scale,0, bv->xoff+0*bv->scale,bv->height,0x404040);
747 0 : GDrawDrawLine(pixmap,bv->xoff+bv->bc->width*bv->scale,0, bv->xoff+bv->bc->width*bv->scale,bv->height,widthcol);
748 0 : if ( bv->bdf->sf->hasvmetrics )
749 0 : GDrawDrawLine(pixmap,0,-bv->yoff+bv->height-(bv->bdf->ascent-bc->vwidth)*bv->scale,
750 0 : bv->width,-bv->yoff+bv->height-(bv->bdf->ascent-bc->vwidth)*bv->scale,widthcol);
751 : }
752 0 : if ( bv->showfore ) {
753 : /* Reference names are drawn after grid (otherwise some characters may get unreadable */
754 0 : for ( bref=bc->refs; bref!=NULL; bref=bref->next )
755 0 : BVDrawRefName( bv,pixmap,bref,0 );
756 : }
757 0 : if ( bv->showoutline ) {
758 0 : Color col = (view_bgcol<0x808080)
759 0 : ? (bv->bc->byte_data ? 0x008800 : 0x004400 )
760 : : 0x00ff00;
761 0 : memset(&cvtemp,'\0',sizeof(cvtemp));
762 0 : cvtemp.v = bv->v;
763 0 : cvtemp.width = bv->width;
764 0 : cvtemp.height = bv->height;
765 0 : cvtemp.scale = bv->scscale*bv->scale;
766 0 : cvtemp.xoff = bv->xoff/* *bv->scscale*/;
767 0 : cvtemp.yoff = bv->yoff/* *bv->scscale*/;
768 0 : cvtemp.b.sc = bv->bc->sc;
769 0 : cvtemp.b.drawmode = dm_fore;
770 :
771 0 : clip.width = event->u.expose.rect.width/cvtemp.scale;
772 0 : clip.height = event->u.expose.rect.height/cvtemp.scale;
773 0 : clip.x = (event->u.expose.rect.x-cvtemp.xoff)/cvtemp.scale;
774 0 : clip.y = (cvtemp.height-event->u.expose.rect.y-event->u.expose.rect.height-cvtemp.yoff)/cvtemp.scale;
775 0 : CVDrawSplineSet(&cvtemp,pixmap,cvtemp.b.sc->layers[ly_fore].splines,col,false,&clip);
776 0 : for ( refs = cvtemp.b.sc->layers[ly_fore].refs; refs!=NULL; refs = refs->next )
777 0 : CVDrawSplineSet(&cvtemp,pixmap,refs->layers[0].splines,col,false,&clip);
778 : }
779 0 : if ( bv->active_tool==bvt_pointer ) {
780 0 : if ( bv->bc->selection==NULL ) {
781 : int xmin, xmax, ymin, ymax;
782 0 : xmin = bv->pressed_x; xmax = bv->info_x;
783 0 : ymin = bv->info_y; ymax = bv->pressed_y;
784 0 : if ( ymin>ymax ) { ymax = ymin; ymin = bv->pressed_y; }
785 0 : if ( xmin>xmax ) { xmin = xmax; xmax = bv->pressed_x; }
786 0 : pixel.width = (xmax-xmin+1) * bv->scale;
787 0 : pixel.height = (ymax-ymin+1) * bv->scale;
788 0 : pixel.x = bv->xoff + xmin*bv->scale;
789 0 : pixel.y = bv->height-bv->yoff-(ymax+1)*bv->scale;
790 0 : GDrawSetDashedLine(pixmap,3,3,0);
791 0 : GDrawDrawRect(pixmap,&pixel,0xffffff);
792 0 : GDrawSetDashedLine(pixmap,3,3,3);
793 0 : GDrawDrawRect(pixmap,&pixel,0x000000);
794 0 : GDrawSetDashedLine(pixmap,0,0,0);
795 : }
796 : }
797 0 : GDrawPopClip(pixmap,&old);
798 0 : }
799 :
800 0 : static void BVInfoDrawText(BitmapView *bv, GWindow pixmap ) {
801 : GRect r;
802 0 : Color bg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(pixmap));
803 : char buffer[50];
804 0 : int ybase = bv->mbh+10+bv->sas;
805 :
806 0 : GDrawSetFont(pixmap,bv->small);
807 0 : r.x = bv->infoh+RPT_DATA; r.width = 39;
808 0 : r.y = bv->mbh; r.height = 36 /* bv->infoh-1 */;
809 0 : GDrawFillRect(pixmap,&r,bg);
810 :
811 0 : sprintf(buffer,"%d%s%d", bv->info_x, coord_sep, bv->info_y );
812 0 : buffer[11] = '\0';
813 0 : GDrawDrawText8(pixmap,bv->infoh+RPT_DATA,ybase,buffer,-1,GDrawGetDefaultForeground(NULL));
814 :
815 0 : if ( bv->active_tool!=cvt_none ) {
816 0 : sprintf(buffer,"%d%s%d", bv->info_x-bv->pressed_x, coord_sep, bv->info_y-bv->pressed_y );
817 0 : buffer[11] = '\0';
818 0 : GDrawDrawText8(pixmap,bv->infoh+RPT_DATA,ybase+bv->sfh+10,buffer,-1,GDrawGetDefaultForeground(NULL));
819 : }
820 0 : }
821 :
822 0 : static void BVMainExpose(BitmapView *bv, GWindow pixmap, GEvent *event ) {
823 : GRect old, temp, box, old2, r;
824 : GImage gi;
825 : struct _GImage base;
826 : GClut clut;
827 0 : BDFChar *bdfc = BDFGetMergedChar( bv->bc );
828 :
829 0 : temp = event->u.expose.rect;
830 0 : if ( temp.y+temp.height < bv->mbh )
831 0 : return;
832 0 : if ( temp.y <bv->mbh ) {
833 0 : temp.height -= (bv->mbh-temp.y);
834 0 : temp.y = bv->mbh;
835 : }
836 0 : GDrawPushClip(pixmap,&temp,&old);
837 0 : GDrawSetLineWidth(pixmap,0);
838 :
839 0 : if ( event->u.expose.rect.x<6+bdfc->xmax-bdfc->xmin ) {
840 0 : box.x = 0; box.width = bv->infoh;
841 0 : box.y = bv->mbh; box.height = bv->infoh;
842 0 : GDrawPushClip(pixmap,&box,&old2);
843 :
844 0 : memset(&gi,'\0',sizeof(gi));
845 0 : memset(&base,'\0',sizeof(base));
846 0 : memset(&clut,'\0',sizeof(clut));
847 0 : gi.u.image = &base;
848 0 : if ( bv->bdf->clut==NULL ) {
849 0 : base.image_type = it_mono;
850 0 : base.clut = &clut;
851 0 : clut.clut_len = 2;
852 0 : clut.clut[0] = GDrawGetDefaultBackground(NULL);
853 : } else {
854 0 : base.image_type = it_index;
855 0 : base.clut = bv->bdf->clut;
856 : }
857 0 : base.data = bdfc->bitmap;
858 0 : base.bytes_per_line = bdfc->bytes_per_line;
859 0 : base.width = bdfc->xmax-bdfc->xmin+1;
860 0 : base.height = bdfc->ymax-bdfc->ymin+1;
861 0 : GDrawDrawImage(pixmap,&gi,NULL, 5,bv->mbh+(bv->infoh-base.height)/2);
862 :
863 0 : GDrawPopClip(pixmap,&old2);
864 :
865 0 : GDrawDrawImage(pixmap,&GIcon_rightpointer,NULL,bv->infoh+RPT_BASE,bv->mbh+8);
866 0 : GDrawDrawImage(pixmap,&GIcon_press2ptr,NULL,bv->infoh+RPT_BASE,bv->mbh+18+bv->sfh);
867 0 : BVInfoDrawText(bv,pixmap );
868 :
869 0 : r.x = bv->infoh+RPT_DATA; r.y = bv->mbh+36;
870 0 : r.width = 20; r.height = 10;
871 0 : GDrawFillRect(pixmap,&r,
872 0 : bv->bdf->clut==NULL ? GDrawGetDefaultBackground(NULL) :
873 0 : bv->bdf->clut->clut[bv->color/( 255/((1<<BDFDepth(bv->bdf))-1) )] );
874 :
875 0 : GDrawDrawImage(pixmap,&GIcon_press2ptr,NULL,bv->infoh+RPT_BASE,bv->mbh+18+bv->sfh);
876 : }
877 0 : GDrawDrawLine(pixmap,0,bv->mbh+bv->infoh-1,bv->width+300,bv->mbh+bv->infoh-1,GDrawGetDefaultForeground(NULL));
878 :
879 0 : r.x = bv->width; r.y = bv->height+bv->infoh+bv->mbh;
880 0 : LogoExpose(pixmap,event,&r,dm_fore);
881 :
882 0 : GDrawPopClip(pixmap,&old);
883 0 : BDFCharFree( bdfc );
884 : }
885 :
886 0 : static void BVShowInfo(BitmapView *bv) {
887 0 : BVInfoDrawText(bv,bv->gw );
888 0 : }
889 :
890 0 : static void BVResize(BitmapView *bv, GEvent *event ) {
891 0 : int sbsize = GDrawPointsToPixels(bv->gw,_GScrollBar_Width);
892 0 : int newwidth = event->u.resize.size.width-sbsize,
893 0 : newheight = event->u.resize.size.height-sbsize - bv->mbh-bv->infoh;
894 : GRect size;
895 :
896 0 : if ( newwidth == bv->width && newheight == bv->height )
897 0 : return;
898 :
899 : /* MenuBar takes care of itself */
900 0 : GDrawResize(bv->v,newwidth,newheight);
901 0 : GGadgetMove(bv->vsb,newwidth, bv->mbh+bv->infoh);
902 0 : GGadgetResize(bv->vsb,sbsize,newheight);
903 0 : GGadgetMove(bv->hsb,0,event->u.resize.size.height-sbsize);
904 0 : GGadgetResize(bv->hsb,newwidth,sbsize);
905 0 : bv->width = newwidth; bv->height = newheight;
906 0 : GGadgetGetSize(bv->recalc,&size);
907 0 : GGadgetMove(bv->recalc,event->u.resize.size.width - size.width - GDrawPointsToPixels(bv->gw,6),size.y);
908 0 : GDrawRequestExpose(bv->gw,NULL,false);
909 0 : BVFit(bv);
910 :
911 0 : bv_width = event->u.resize.size.width;
912 0 : bv_height = event->u.resize.size.height;
913 0 : SavePrefs(true);
914 : }
915 :
916 0 : static void BVHScroll(BitmapView *bv,struct sbevent *sb) {
917 0 : int newpos = bv->xoff;
918 0 : int fh = bv->bdf->ascent+bv->bdf->descent;
919 :
920 0 : switch( sb->type ) {
921 : case et_sb_top:
922 0 : newpos = 0;
923 0 : break;
924 : case et_sb_uppage:
925 0 : newpos += 9*bv->width/10;
926 0 : break;
927 : case et_sb_up:
928 0 : newpos += bv->width/15;
929 0 : break;
930 : case et_sb_down:
931 0 : newpos -= bv->width/15;
932 0 : break;
933 : case et_sb_downpage:
934 0 : newpos -= 9*bv->width/10;
935 0 : break;
936 : case et_sb_bottom:
937 0 : newpos = 0;
938 0 : break;
939 : case et_sb_thumb:
940 : case et_sb_thumbrelease:
941 0 : newpos = -sb->pos;
942 0 : break;
943 : case et_sb_halfup:
944 0 : newpos += bv->width/30;
945 0 : break;
946 : case et_sb_halfdown:
947 0 : newpos -= bv->width/30;
948 0 : break;
949 : }
950 0 : if ( newpos>6*fh*bv->scale-bv->width )
951 0 : newpos = 6*fh*bv->scale-bv->width;
952 0 : if ( newpos<-3*fh*bv->scale ) newpos = -3*fh*bv->scale;
953 0 : if ( newpos!=bv->xoff ) {
954 0 : int diff = newpos-bv->xoff;
955 0 : bv->xoff = newpos;
956 0 : GScrollBarSetPos(bv->hsb,-newpos);
957 0 : GDrawScroll(bv->v,NULL,diff,0);
958 : }
959 0 : }
960 :
961 0 : static void BVVScroll(BitmapView *bv,struct sbevent *sb) {
962 0 : int newpos = bv->yoff;
963 0 : int fh = bv->bdf->ascent+bv->bdf->descent;
964 :
965 0 : switch( sb->type ) {
966 : case et_sb_top:
967 0 : newpos = 0;
968 0 : break;
969 : case et_sb_uppage:
970 0 : newpos -= 9*bv->width/10;
971 0 : break;
972 : case et_sb_up:
973 0 : newpos -= bv->width/15;
974 0 : break;
975 : case et_sb_down:
976 0 : newpos += bv->width/15;
977 0 : break;
978 : case et_sb_downpage:
979 0 : newpos += 9*bv->width/10;
980 0 : break;
981 : case et_sb_bottom:
982 0 : newpos = 0;
983 0 : break;
984 : case et_sb_thumb:
985 : case et_sb_thumbrelease:
986 0 : newpos = sb->pos;
987 0 : break;
988 : case et_sb_halfup:
989 0 : newpos -= bv->width/30;
990 0 : break;
991 : case et_sb_halfdown:
992 0 : newpos += bv->width/30;
993 0 : break;
994 : }
995 0 : if ( newpos>4*fh*bv->scale-bv->height )
996 0 : newpos = 4*fh*bv->scale-bv->height;
997 0 : if ( newpos<-2*fh*bv->scale ) newpos = -2*fh*bv->scale;
998 0 : if ( newpos!=bv->yoff ) {
999 0 : int diff = newpos-bv->yoff;
1000 0 : bv->yoff = newpos;
1001 0 : GScrollBarSetPos(bv->vsb,newpos);
1002 0 : GDrawScroll(bv->v,NULL,0,diff);
1003 : }
1004 0 : }
1005 :
1006 0 : static int BVRecalc(GGadget *g, GEvent *e) {
1007 : BitmapView *bv;
1008 : BDFChar *bdfc;
1009 0 : void *freetypecontext=NULL;
1010 :
1011 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
1012 0 : bv = GDrawGetUserData(GGadgetGetWindow(g));
1013 0 : BCPreserveState(bv->bc);
1014 0 : BCFlattenFloat(bv->bc);
1015 0 : freetypecontext = FreeTypeFontContext(bv->bc->sc->parent,bv->bc->sc,NULL,ly_fore);
1016 0 : if ( freetypecontext!=NULL ) {
1017 0 : bdfc = SplineCharFreeTypeRasterize(freetypecontext,bv->bc->sc->orig_pos,bv->bdf->pixelsize,72,BDFDepth(bv->bdf));
1018 0 : FreeTypeFreeContext(freetypecontext);
1019 : } else
1020 0 : bdfc = SplineCharAntiAlias(bv->bc->sc,ly_fore,bv->bdf->pixelsize,(1<<(BDFDepth(bv->bdf)/2)));
1021 0 : free(bv->bc->bitmap);
1022 0 : bv->bc->bitmap = bdfc->bitmap; bdfc->bitmap = NULL;
1023 0 : bv->bc->width = bdfc->width;
1024 0 : bv->bc->xmin = bdfc->xmin;
1025 0 : bv->bc->xmax = bdfc->xmax;
1026 0 : bv->bc->ymin = bdfc->ymin;
1027 0 : bv->bc->ymax = bdfc->ymax;
1028 0 : bv->bc->bytes_per_line = bdfc->bytes_per_line;
1029 0 : BDFCharFree(bdfc);
1030 0 : BCCharChangedUpdate(bv->bc);
1031 : }
1032 0 : return( true );
1033 : }
1034 :
1035 0 : static void BVSetWidth(BitmapView *bv, int x) {
1036 : int tot, cnt;
1037 : BDFFont *bdf;
1038 0 : BDFChar *bc = bv->bc;
1039 :
1040 0 : bc->width = x;
1041 0 : if ( bv->bdf->sf->onlybitmaps ) {
1042 0 : tot=0; cnt=0;
1043 0 : for ( bdf = bv->bdf->sf->bitmaps; bdf!=NULL; bdf=bdf->next )
1044 0 : if ( bdf->glyphs[bc->orig_pos]) {
1045 0 : tot += bdf->glyphs[bc->orig_pos]->width*1000/(bdf->ascent+bdf->descent);
1046 0 : ++cnt;
1047 : }
1048 0 : if ( cnt!=0 ) {
1049 0 : bc->sc->width = tot/cnt;
1050 0 : bc->sc->widthset = true;
1051 : }
1052 : }
1053 0 : BCCharChangedUpdate(bc);
1054 0 : }
1055 :
1056 0 : static void BVSetVWidth(BitmapView *bv, int y) {
1057 : int tot, cnt;
1058 : BDFFont *bdf;
1059 0 : BDFChar *bc = bv->bc;
1060 :
1061 0 : if ( !bv->bdf->sf->hasvmetrics )
1062 0 : return;
1063 0 : bc->vwidth = bv->bdf->ascent-y;
1064 0 : if ( bv->bdf->sf->onlybitmaps ) {
1065 0 : tot=0; cnt=0;
1066 0 : for ( bdf = bv->bdf->sf->bitmaps; bdf!=NULL; bdf=bdf->next )
1067 0 : if ( bdf->glyphs[bc->orig_pos]) {
1068 0 : tot += bdf->glyphs[bc->orig_pos]->vwidth*1000/(bdf->ascent+bdf->descent);
1069 0 : ++cnt;
1070 : }
1071 0 : if ( cnt!=0 && bv->bdf->sf->onlybitmaps ) {
1072 0 : bc->sc->vwidth = tot/cnt;
1073 0 : bc->sc->widthset = true;
1074 : }
1075 : }
1076 0 : BCCharChangedUpdate(bc);
1077 : }
1078 :
1079 0 : int BVColor(BitmapView *bv) {
1080 0 : int div = 255/((1<<BDFDepth(bv->bdf))-1);
1081 0 : return ( (bv->color+div/2)/div );
1082 : }
1083 :
1084 0 : static int IsReferenceTouched(BitmapView *bv, BDFRefChar *ref, int x, int y){
1085 : BDFRefChar *head;
1086 : BDFChar *rbc;
1087 : int nx, ny;
1088 :
1089 0 : if ( ref == NULL )
1090 0 : return( false );
1091 :
1092 0 : rbc = ref->bdfc;
1093 0 : ny = rbc->ymax - y + ref->yoff;
1094 0 : nx = x - rbc->xmin - ref->xoff;
1095 0 : if (nx>=0 && nx<=( rbc->xmax - rbc->xmin ) &&
1096 0 : ny>=0 && ny<=( rbc->ymax - rbc->ymin ) &&
1097 0 : (( rbc->byte_data && rbc->bitmap[ny*rbc->bytes_per_line+nx] != 0 ) ||
1098 0 : (( !rbc->byte_data &&
1099 0 : rbc->bitmap[ny*rbc->bytes_per_line + (nx>>3)] & (1<<(7 - (nx&7)))))))
1100 0 : return( true );
1101 :
1102 0 : for ( head = rbc->refs; head != NULL; head = head->next ) {
1103 0 : if ( IsReferenceTouched( bv,head,x,y))
1104 0 : return( true );
1105 : }
1106 0 : return( false );
1107 : }
1108 :
1109 0 : static void BVMouseDown(BitmapView *bv, GEvent *event) {
1110 0 : int x = floor( (event->u.mouse.x-bv->xoff)/ (real) bv->scale);
1111 0 : int y = floor( (bv->height-event->u.mouse.y-bv->yoff)/ (real) bv->scale);
1112 : int ny;
1113 0 : BDFChar *bc = bv->bc;
1114 : BDFFloat *sel;
1115 : int color_under_cursor;
1116 0 : BDFRefChar *refsel = NULL, *head;
1117 :
1118 0 : if ( event->u.mouse.button==2 && event->u.mouse.device!=NULL &&
1119 0 : strcmp(event->u.mouse.device,"stylus")==0 )
1120 0 : return; /* I treat this more like a modifier key change than a button press */
1121 :
1122 0 : if ( event->u.mouse.button==3 ) {
1123 0 : BVToolsPopup(bv,event);
1124 0 : return;
1125 : }
1126 0 : BVToolsSetCursor(bv,event->u.mouse.state|(1<<(7+event->u.mouse.button)), event->u.mouse.device );
1127 0 : bv->active_tool = bv->showing_tool;
1128 0 : bv->pressed_x = x; bv->pressed_y = y;
1129 0 : bv->info_x = x; bv->info_y = y;
1130 0 : ny = bc->ymax-y;
1131 0 : if ( x<bc->xmin || x>bc->xmax || ny<0 || ny>bc->ymax-bc->ymin )
1132 0 : color_under_cursor = 0;
1133 0 : else if ( bc->byte_data )
1134 0 : color_under_cursor = bc->bitmap[(bc->ymax-y)*bc->bytes_per_line + x-bc->xmin] *
1135 0 : 255/((1<<BDFDepth(bv->bdf))-1);
1136 : else
1137 0 : color_under_cursor = bc->bitmap[(bc->ymax-y)*bc->bytes_per_line + (x-bc->xmin)/8]&(0x80>>((x-bc->xmin)&7)) *
1138 : 255;
1139 0 : BVPaletteColorUnderChange(bv,color_under_cursor);
1140 0 : bv->event_x = event->u.mouse.x; bv->event_y = event->u.mouse.y;
1141 0 : bv->recentchange = false;
1142 0 : for ( head = bc->refs; head != NULL; head = head->next ) {
1143 0 : if ( IsReferenceTouched( bv,head,x,y ))
1144 0 : refsel = head;
1145 : }
1146 0 : switch ( bv->active_tool ) {
1147 : case bvt_eyedropper:
1148 0 : bv->color = color_under_cursor;
1149 : /* Store color as a number between 0 and 255 no matter what the clut size is */
1150 0 : BVPaletteColorChange(bv);
1151 0 : break;
1152 : case bvt_pencil: case bvt_line:
1153 : case bvt_rect: case bvt_filledrect:
1154 0 : ny = bc->ymax-y;
1155 0 : bv->clearing = false;
1156 0 : if ( !bc->byte_data && x>=bc->xmin && x<=bc->xmax &&
1157 0 : ny>=0 && ny<=bc->ymax-bc->ymin ) {
1158 0 : int nx = x-bc->xmin;
1159 0 : if ( bc->bitmap[ny*bc->bytes_per_line + (nx>>3)] &
1160 0 : (1<<(7-(nx&7))) )
1161 0 : bv->clearing = true;
1162 : }
1163 0 : BCPreserveState(bc);
1164 0 : BCFlattenFloat(bc);
1165 0 : if ( bv->active_tool == bvt_pencil )
1166 0 : BCSetPoint(bc,x,y,bc->byte_data?BVColor(bv):!bv->clearing);
1167 0 : BCCharChangedUpdate(bc);
1168 0 : break;
1169 : case bvt_elipse: case bvt_filledelipse:
1170 0 : BCPreserveState(bc);
1171 0 : BCFlattenFloat(bc);
1172 0 : BCCharChangedUpdate(bc);
1173 0 : break;
1174 : case bvt_pointer:
1175 0 : if ( !( event->u.mouse.state&ksm_shift )) {
1176 0 : for ( head = bc->refs; head != NULL; head=head->next )
1177 0 : head->selected = false;
1178 : }
1179 0 : if ( refsel != NULL ) {
1180 0 : BCFlattenFloat(bc);
1181 0 : refsel->selected = ( event->u.mouse.state&ksm_shift ) ?
1182 0 : !(refsel->selected) : true;
1183 0 : GDrawSetCursor(bv->v,ct_shift);
1184 0 : } else if ( (sel = bc->selection)!=NULL ) {
1185 0 : if ( x<sel->xmin || x>sel->xmax || y<sel->ymin || y>sel->ymax )
1186 0 : BCFlattenFloat(bc);
1187 : else {
1188 0 : GDrawSetCursor(bv->v,ct_shift);
1189 : /* otherwise we'll move the selection */
1190 : }
1191 0 : } else if ( /*bc->sc->parent->onlybitmaps &&*/
1192 0 : event->u.mouse.x-bv->xoff > bc->width*bv->scale-3 &&
1193 0 : event->u.mouse.x-bv->xoff < bc->width*bv->scale+3 ) {
1194 0 : bv->active_tool = bvt_setwidth;
1195 0 : BVToolsSetCursor(bv,event->u.mouse.state|(1<<(7+event->u.mouse.button)), event->u.mouse.device );
1196 0 : } else if ( /*bc->sc->parent->onlybitmaps &&*/ bc->sc->parent->hasvmetrics &&
1197 0 : bv->height-event->u.mouse.y-bv->yoff > (bv->bdf->ascent-bc->vwidth)*bv->scale-3 &&
1198 0 : bv->height-event->u.mouse.y-bv->yoff < (bv->bdf->ascent-bc->vwidth)*bv->scale+3 ) {
1199 0 : bv->active_tool = bvt_setvwidth;
1200 0 : BVToolsSetCursor(bv,event->u.mouse.state|(1<<(7+event->u.mouse.button)), event->u.mouse.device );
1201 : }
1202 0 : BCCharUpdate(bc);
1203 0 : break;
1204 : case bvt_setwidth:
1205 0 : BVSetWidth(bv,x);
1206 0 : break;
1207 : case bvt_setvwidth:
1208 0 : BVSetVWidth(bv,y);
1209 0 : break;
1210 : }
1211 : }
1212 :
1213 0 : static void BVMouseMove(BitmapView *bv, GEvent *event) {
1214 0 : int x = floor( (event->u.mouse.x-bv->xoff)/ (real) bv->scale);
1215 0 : int y = floor( (bv->height-event->u.mouse.y-bv->yoff)/ (real) bv->scale);
1216 : int newx, newy;
1217 0 : int fh = bv->bdf->ascent+bv->bdf->descent;
1218 0 : BDFChar *bc = bv->bc;
1219 0 : int color_under_cursor, ny, has_selected_refs = false;
1220 : BDFRefChar *head;
1221 :
1222 0 : bv->info_x = x; bv->info_y = y;
1223 0 : ny = bc->ymax-y;
1224 0 : if ( x<bc->xmin || x>bc->xmax || ny<0 || ny>bc->ymax-bc->ymin )
1225 0 : color_under_cursor = 0;
1226 0 : else if ( bc->byte_data )
1227 0 : color_under_cursor = bc->bitmap[(bc->ymax-y)*bc->bytes_per_line + x-bc->xmin] *
1228 0 : 255/((1<<BDFDepth(bv->bdf))-1);
1229 : else
1230 0 : color_under_cursor = bc->bitmap[(bc->ymax-y)*bc->bytes_per_line + (x-bc->xmin)/8]&(0x80>>((x-bc->xmin)&7)) *
1231 : 255;
1232 0 : BVShowInfo(bv);
1233 0 : BVPaletteColorUnderChange(bv,color_under_cursor);
1234 0 : if ( bv->active_tool==bvt_none )
1235 0 : return; /* Not pressed */
1236 0 : switch ( bv->active_tool ) {
1237 : case bvt_pencil:
1238 0 : BCSetPoint(bc,x,y,bc->byte_data?BVColor(bv):!bv->clearing);
1239 0 : BCCharChangedUpdate(bc);
1240 0 : break;
1241 : case bvt_line: case bvt_rect: case bvt_filledrect:
1242 : case bvt_elipse: case bvt_filledelipse:
1243 0 : BCCharChangedUpdate(bc);
1244 0 : break;
1245 : case bvt_hand:
1246 0 : newx = bv->xoff + event->u.mouse.x-bv->event_x;
1247 0 : newy = bv->yoff + bv->event_y-event->u.mouse.y;
1248 0 : if ( newy>4*fh*bv->scale-bv->height )
1249 0 : newy = 4*fh*bv->scale-bv->height;
1250 0 : if ( newy<-2*fh*bv->scale ) newy = -2*fh*bv->scale;
1251 0 : if ( newx>6*fh*bv->scale-bv->width )
1252 0 : newx = 6*fh*bv->scale-bv->width;
1253 0 : if ( newx<-3*fh*bv->scale ) newx = -3*fh*bv->scale;
1254 0 : if ( newx!=bv->xoff || newy!=bv->yoff ) {
1255 0 : newx -= bv->xoff; bv->xoff += newx;
1256 0 : newy -= bv->yoff; bv->yoff += newy;
1257 0 : GScrollBarSetPos(bv->hsb,-bv->xoff);
1258 0 : GScrollBarSetPos(bv->vsb,-bv->yoff);
1259 0 : GDrawScroll(bv->v,NULL,newx,newy);
1260 : }
1261 0 : bv->event_x = event->u.mouse.x; bv->event_y = event->u.mouse.y;
1262 0 : break;
1263 : case bvt_shift:
1264 0 : if ( x!=bv->pressed_x || y!=bv->pressed_y ) {
1265 0 : if ( !bv->recentchange ) {
1266 0 : BCPreserveState(bc);
1267 0 : BCFlattenFloat(bc);
1268 0 : bv->recentchange = true;
1269 : }
1270 0 : bc->xmin += x-bv->pressed_x;
1271 0 : bc->xmax += x-bv->pressed_x;
1272 0 : bc->ymin += y-bv->pressed_y;
1273 0 : bc->ymax += y-bv->pressed_y;
1274 :
1275 0 : for ( head=bc->refs; head!=NULL; head=head->next ) {
1276 0 : if ( head->selected ) {
1277 0 : head->xoff += x-bv->pressed_x;
1278 0 : head->yoff += y-bv->pressed_y;
1279 : }
1280 : }
1281 0 : BCCharChangedUpdate(bc);
1282 0 : bv->pressed_x = x; bv->pressed_y = y;
1283 : }
1284 0 : break;
1285 : case bvt_pointer:
1286 0 : for ( head=bc->refs; head!=NULL && !has_selected_refs; head=head->next ) {
1287 0 : if ( head->selected ) has_selected_refs = true;
1288 : }
1289 0 : if ( bc->selection!=NULL || has_selected_refs ) {
1290 0 : if ( x!=bv->pressed_x || y!=bv->pressed_y ) {
1291 0 : if ( !bv->recentchange ) {
1292 0 : BCPreserveState(bc);
1293 0 : bv->recentchange = true;
1294 : }
1295 0 : if ( has_selected_refs ) {
1296 0 : for ( head=bc->refs; head!=NULL; head=head->next ) {
1297 0 : if ( head->selected ) {
1298 0 : head->xoff += x-bv->pressed_x;
1299 0 : head->yoff += y-bv->pressed_y;
1300 : }
1301 : }
1302 0 : } else if ( bc->selection != NULL ) {
1303 0 : bc->selection->xmin += x-bv->pressed_x;
1304 0 : bc->selection->xmax += x-bv->pressed_x;
1305 0 : bc->selection->ymin += y-bv->pressed_y;
1306 0 : bc->selection->ymax += y-bv->pressed_y;
1307 : }
1308 0 : BCCharChangedUpdate(bc);
1309 0 : bv->pressed_x = x; bv->pressed_y = y;
1310 : }
1311 : } else {
1312 0 : GDrawRequestExpose(bv->v,NULL,false);
1313 : }
1314 0 : break;
1315 : case bvt_setwidth:
1316 0 : BVSetWidth(bv,x);
1317 0 : break;
1318 : case bvt_setvwidth:
1319 0 : BVSetVWidth(bv,y);
1320 0 : break;
1321 : }
1322 : }
1323 :
1324 0 : static void BVSetPoint(BitmapView *bv, int x, int y, void *junk) {
1325 0 : BCSetPoint(bv->bc,x,y,bv->bc->byte_data?BVColor(bv):!bv->clearing);
1326 0 : }
1327 :
1328 : static void BVMagnify(BitmapView *bv, int midx, int midy, int bigger);
1329 :
1330 0 : static void BVMouseUp(BitmapView *bv, GEvent *event) {
1331 0 : int x = floor( (event->u.mouse.x-bv->xoff)/ (real) bv->scale);
1332 0 : int y = floor( (bv->height-event->u.mouse.y-bv->yoff)/ (real) bv->scale);
1333 0 : BDFRefChar *refsel = NULL, *head;
1334 :
1335 0 : BVMouseMove(bv,event);
1336 0 : for ( head = bv->bc->refs; head != NULL; head = head->next ) {
1337 0 : if ( IsReferenceTouched( bv,head,x,y ))
1338 0 : refsel = head;
1339 : }
1340 0 : switch ( bv->active_tool ) {
1341 : case bvt_magnify: case bvt_minify:
1342 0 : BVMagnify(bv,x,y,bv->active_tool==bvt_magnify?1:-1);
1343 0 : break;
1344 : case bvt_line: case bvt_rect: case bvt_filledrect:
1345 : case bvt_elipse: case bvt_filledelipse:
1346 0 : if ( refsel == NULL ) {
1347 0 : BCGeneralFunction(bv,BVSetPoint,NULL);
1348 0 : bv->active_tool = bvt_none;
1349 0 : BCCharChangedUpdate(bv->bc);
1350 : }
1351 0 : break;
1352 : case bvt_pointer:
1353 0 : if ( bv->bc->selection!=NULL ) {
1354 : /* we've been moving it */
1355 0 : GDrawSetCursor(bv->v,ct_mypointer);
1356 0 : if ( !bv->recentchange ) { /* Oh, we just clicked in it, get rid of it */
1357 0 : BCFlattenFloat(bv->bc);
1358 0 : BCCharChangedUpdate(bv->bc);
1359 : }
1360 0 : } else if ( refsel ) {
1361 0 : GDrawSetCursor(bv->v,ct_mypointer);
1362 0 : bv->active_tool = bvt_none;
1363 0 : BCCharChangedUpdate(bv->bc);
1364 : } else {
1365 : int dx,dy;
1366 0 : if ( (dx = event->u.mouse.x-bv->event_x)<0 ) dx = -dx;
1367 0 : if ( (dy = event->u.mouse.y-bv->event_y)<0 ) dy = -dy;
1368 0 : if ( dx+dy>4 ) {
1369 : /* we've just dragged out a new one */
1370 0 : BDFFloatCreate(bv->bc,bv->pressed_x,bv->info_x,bv->pressed_y,bv->info_y,true);
1371 : }
1372 0 : bv->active_tool = bvt_none;
1373 0 : BCCharChangedUpdate(bv->bc);
1374 : }
1375 0 : break;
1376 : case bvt_setwidth:
1377 0 : BVSetWidth(bv,x);
1378 0 : break;
1379 : case bvt_setvwidth:
1380 0 : BVSetVWidth(bv,y);
1381 0 : break;
1382 : }
1383 0 : bv->active_tool = bvt_none;
1384 0 : BVToolsSetCursor(bv,event->u.mouse.state&~(1<<(7+event->u.mouse.button)), event->u.mouse.device); /* X still has the buttons set in the state, even though we just released them. I don't want em */
1385 0 : }
1386 :
1387 0 : static int v_e_h(GWindow gw, GEvent *event) {
1388 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1389 :
1390 0 : if (( event->type==et_mouseup || event->type==et_mousedown ) &&
1391 0 : (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
1392 0 : int ish = event->u.mouse.button>5;
1393 0 : if ( event->u.mouse.state&ksm_shift ) ish = !ish;
1394 0 : if ( ish ) /* bind shift to vertical scrolling */
1395 0 : return( GGadgetDispatchEvent(bv->hsb,event));
1396 : else
1397 0 : return( GGadgetDispatchEvent(bv->vsb,event));
1398 : }
1399 :
1400 0 : switch ( event->type ) {
1401 : case et_selclear:
1402 0 : ClipboardClear();
1403 0 : break;
1404 : case et_expose:
1405 0 : GDrawSetLineWidth(gw,0);
1406 0 : BVExpose(bv,gw,event);
1407 0 : break;
1408 : case et_crossing:
1409 0 : BVToolsSetCursor(bv,event->u.mouse.state, event->u.mouse.device);
1410 0 : break;
1411 : case et_mousedown:
1412 0 : BVPaletteActivate(bv);
1413 0 : BVMouseDown(bv,event);
1414 0 : break;
1415 : case et_mousemove:
1416 0 : BVMouseMove(bv,event);
1417 0 : break;
1418 : case et_mouseup:
1419 0 : BVMouseUp(bv,event);
1420 0 : break;
1421 : case et_char:
1422 0 : BVChar(bv,event);
1423 0 : break;
1424 : case et_charup:
1425 0 : BVCharUp(bv,event);
1426 0 : break;
1427 : case et_timer:
1428 : #if _ModKeysAutoRepeat
1429 : /* Under cygwin the modifier keys auto repeat, they don't under normal X */
1430 : if ( bv->autorpt==event->u.timer.timer ) {
1431 : bv->autorpt = NULL;
1432 : BVToolsSetCursor(bv,bv->oldstate,NULL);
1433 : }
1434 : #endif
1435 0 : break;
1436 : case et_focus:
1437 0 : break;
1438 : default:
1439 0 : break;
1440 : }
1441 0 : return( true );
1442 : }
1443 :
1444 0 : static int bv_e_h(GWindow gw, GEvent *event) {
1445 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1446 : int enc;
1447 :
1448 0 : if (( event->type==et_mouseup || event->type==et_mousedown ) &&
1449 0 : (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
1450 0 : int ish = event->u.mouse.button>5;
1451 0 : if ( event->u.mouse.state&ksm_shift ) ish = !ish;
1452 0 : if ( ish ) /* bind shift to vertical scrolling */
1453 0 : return( GGadgetDispatchEvent(bv->hsb,event));
1454 : else
1455 0 : return( GGadgetDispatchEvent(bv->vsb,event));
1456 : }
1457 :
1458 0 : switch ( event->type ) {
1459 : case et_expose:
1460 0 : GDrawSetLineWidth(gw,0);
1461 0 : BVMainExpose(bv,gw,event);
1462 0 : break;
1463 : case et_char:
1464 0 : BVChar(bv,event);
1465 0 : break;
1466 : case et_charup:
1467 0 : BVCharUp(bv,event);
1468 0 : break;
1469 : case et_resize:
1470 0 : if ( event->u.resize.sized )
1471 0 : BVResize(bv,event);
1472 0 : break;
1473 : case et_controlevent:
1474 0 : switch ( event->u.control.subtype ) {
1475 : case et_scrollbarchange:
1476 0 : if ( event->u.control.g == bv->hsb )
1477 0 : BVHScroll(bv,&event->u.control.u.sb);
1478 : else
1479 0 : BVVScroll(bv,&event->u.control.u.sb);
1480 0 : break;
1481 : }
1482 0 : break;
1483 : case et_destroy:
1484 0 : BVUnlinkView(bv);
1485 0 : BVPalettesHideIfMine(bv);
1486 0 : BitmapViewFree(bv);
1487 0 : break;
1488 : case et_map:
1489 0 : if ( event->u.map.is_visible )
1490 0 : BVPaletteActivate(bv);
1491 : else
1492 0 : BVPalettesHideIfMine(bv);
1493 0 : break;
1494 : case et_close:
1495 0 : GDrawDestroyWindow(gw);
1496 0 : break;
1497 : case et_mouseup: case et_mousedown:
1498 0 : GGadgetEndPopup();
1499 0 : BVPaletteActivate(bv);
1500 0 : break;
1501 : case et_mousemove:
1502 0 : enc = BVCurEnc(bv);
1503 0 : SCPreparePopup(bv->gw,bv->bc->sc,bv->fv->b.map->remap,enc,
1504 0 : UniFromEnc(enc,bv->fv->b.map->enc));
1505 0 : break;
1506 : case et_focus:
1507 0 : break;
1508 : }
1509 0 : return( true );
1510 : }
1511 :
1512 : #define MID_Fit 2001
1513 : #define MID_ZoomIn 2002
1514 : #define MID_ZoomOut 2003
1515 : #define MID_Next 2007
1516 : #define MID_Prev 2008
1517 : #define MID_Bigger 2009
1518 : #define MID_Smaller 2010
1519 : #define MID_NextDef 2012
1520 : #define MID_PrevDef 2013
1521 : #define MID_Cut 2101
1522 : #define MID_Copy 2102
1523 : #define MID_Paste 2103
1524 : #define MID_Clear 2104
1525 : #define MID_SelAll 2106
1526 : #define MID_CopyRef 2107
1527 : #define MID_UnlinkRef 2108
1528 : #define MID_Undo 2109
1529 : #define MID_Redo 2110
1530 : #define MID_RemoveUndoes 2111
1531 : #define MID_GetInfo 2203
1532 : #define MID_AvailBitmaps 2210
1533 : #define MID_RegenBitmaps 2211
1534 : #define MID_Tools 2501
1535 : #define MID_Layers 2502
1536 : #define MID_Shades 2503
1537 : #define MID_DockPalettes 2504
1538 : #define MID_Revert 2702
1539 : #define MID_Recent 2703
1540 : #define MID_SetWidth 2601
1541 : #define MID_SetVWidth 2602
1542 :
1543 : #define MID_Warnings 3000
1544 :
1545 0 : static void BVMenuOpen(GWindow gw, struct gmenuitem *mi, GEvent *g) {
1546 0 : BitmapView *d = (BitmapView*)GDrawGetUserData(gw);
1547 0 : FontView *fv = NULL;
1548 0 : if (d) {
1549 0 : fv = (FontView*)d->fv;
1550 : }
1551 0 : _FVMenuOpen(fv);
1552 0 : }
1553 :
1554 0 : static void BVMenuClose(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1555 0 : GDrawDestroyWindow(gw);
1556 0 : }
1557 :
1558 0 : static void BVMenuOpenOutline(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1559 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1560 :
1561 0 : CharViewCreate(bv->bc->sc,bv->fv,bv->map_of_enc==bv->fv->b.map?bv->enc:-1);
1562 0 : }
1563 :
1564 0 : static void BVMenuOpenMetrics(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1565 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1566 0 : MetricsViewCreate(bv->fv,bv->bc->sc,bv->bdf);
1567 0 : }
1568 :
1569 0 : static void BVMenuSave(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1570 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1571 0 : _FVMenuSave(bv->fv);
1572 0 : }
1573 :
1574 0 : static void BVMenuSaveAs(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1575 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1576 0 : _FVMenuSaveAs(bv->fv);
1577 0 : }
1578 :
1579 0 : static void BVMenuGenerate(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1580 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1581 0 : _FVMenuGenerate(bv->fv,false);
1582 0 : }
1583 :
1584 0 : static void BVMenuGenerateFamily(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1585 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1586 0 : _FVMenuGenerate(bv->fv,gf_macfamily);
1587 0 : }
1588 :
1589 0 : static void BVMenuGenerateTTC(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1590 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1591 0 : _FVMenuGenerate(bv->fv,gf_ttc);
1592 0 : }
1593 :
1594 0 : static void BVMenuExport(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1595 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1596 0 : BVExport(bv);
1597 0 : }
1598 :
1599 0 : static void BVMenuImport(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1600 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1601 0 : BVImport(bv);
1602 0 : }
1603 :
1604 0 : static void BVMenuRevert(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1605 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1606 0 : FVDelay(bv->fv,(void (*)(FontView *)) FVRevert);
1607 : /* The revert command can potentially */
1608 : /* destroy our window (if the char weren't in the */
1609 : /* old font). If that happens before the menu finishes */
1610 : /* we get a crash. So delay till after the menu completes */
1611 0 : }
1612 :
1613 0 : static void fllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1614 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1615 :
1616 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
1617 0 : switch ( mi->mid ) {
1618 : case MID_Revert:
1619 0 : mi->ti.disabled = bv->bdf->sf->origname==NULL || bv->bdf->sf->new;
1620 0 : break;
1621 : case MID_Recent:
1622 0 : mi->ti.disabled = !RecentFilesAny();
1623 0 : break;
1624 : }
1625 : }
1626 0 : }
1627 :
1628 0 : static void BVMagnify(BitmapView *bv, int midx, int midy, int bigger) {
1629 : /* available sizes: 1, 2, 3, 4, 6, 8, 12, 16, 24, 32 */
1630 :
1631 0 : if ( bigger>0 ) {
1632 0 : if ( bv->scale == 1 )
1633 0 : bv->scale = 2;
1634 0 : else if ( (bv->scale & (bv->scale - 1)) == 0 ) /* power of 2 */
1635 0 : bv->scale += bv->scale / 2;
1636 : else
1637 0 : bv->scale += bv->scale / 3;
1638 0 : if ( bv->scale > 32 ) bv->scale = 32;
1639 : } else {
1640 0 : if ( bv->scale <= 2 )
1641 0 : bv->scale = 1;
1642 0 : else if ( (bv->scale & (bv->scale - 1)) == 0 )
1643 0 : bv->scale -= bv->scale / 4;
1644 : else
1645 0 : bv->scale -= bv->scale / 3;
1646 : }
1647 0 : bv->xoff = -(midx*bv->scale - bv->width/2);
1648 0 : bv->yoff = -(midy*bv->scale - bv->height/2);
1649 0 : BVNewScale(bv);
1650 0 : }
1651 :
1652 0 : static void BVMenuScale(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1653 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1654 :
1655 0 : if ( mi->mid == MID_Fit ) {
1656 0 : BVFit(bv);
1657 : } else {
1658 0 : real midx = (bv->width/2-bv->xoff)/bv->scale;
1659 0 : real midy = (bv->height/2-bv->yoff)/bv->scale;
1660 0 : BVMagnify(bv,midx,midy,mi->mid==MID_ZoomOut?-1:1);
1661 : }
1662 0 : }
1663 :
1664 0 : static void BVMenuChangeChar(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1665 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1666 0 : SplineFont *sf = bv->bc->sc->parent;
1667 0 : EncMap *map = bv->fv->b.map;
1668 0 : int pos = -1, gid;
1669 :
1670 0 : if ( mi->mid == MID_Next ) {
1671 0 : pos = BVCurEnc(bv)+1;
1672 0 : } else if ( mi->mid == MID_Prev ) {
1673 0 : pos = BVCurEnc(bv)-1;
1674 0 : } else if ( mi->mid == MID_NextDef ) {
1675 0 : for ( pos = BVCurEnc(bv)+1; pos<map->enccount &&
1676 0 : ((gid=map->map[pos])==-1 || !SCWorthOutputting(sf->glyphs[gid]) ||
1677 0 : bv->bdf->glyphs[gid]==NULL) ;
1678 0 : ++pos );
1679 0 : if ( pos==map->enccount )
1680 0 : return;
1681 0 : } else if ( mi->mid == MID_PrevDef ) {
1682 0 : for ( pos = BVCurEnc(bv)-1; pos>=0 &&
1683 0 : ((gid=map->map[pos])==-1 || !SCWorthOutputting(sf->glyphs[gid]) ||
1684 0 : bv->bdf->glyphs[gid]==NULL) ;
1685 0 : --pos );
1686 0 : if ( pos<0 )
1687 0 : return;
1688 : }
1689 0 : if ( pos>=0 && pos<map->enccount )
1690 0 : BVChangeChar(bv,pos,false);
1691 : }
1692 :
1693 0 : static void BVMenuChangePixelSize(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1694 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1695 0 : BDFFont *best=NULL, *bdf;
1696 : /* Bigger will find either a bigger pixelsize or a font with same pixelsize and greater depth */
1697 :
1698 0 : if ( mi->mid == MID_Bigger ) {
1699 0 : best = bv->bdf->next; /* I rely on the bitmap list being ordered */
1700 : } else {
1701 0 : for ( bdf=bv->bdf->sf->bitmaps; bdf!=NULL && bdf->next!=bv->bdf; bdf=bdf->next );
1702 0 : best = bdf;
1703 : }
1704 0 : if ( best!=NULL && bv->bdf!=best ) {
1705 0 : bv->bdf = best;
1706 0 : bv->scscale = ((real) (best->pixelsize))/(best->sf->ascent+best->sf->descent);
1707 0 : BVChangeChar(bv,bv->enc,true);
1708 0 : BVShows.lastpixelsize = best->pixelsize;
1709 : }
1710 0 : }
1711 :
1712 0 : static void BVMenuGotoChar(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1713 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1714 0 : int pos = GotoChar(bv->fv->b.sf,bv->fv->b.map,NULL);
1715 :
1716 0 : if ( pos!=-1 )
1717 0 : BVChangeChar(bv,pos,false);
1718 0 : }
1719 :
1720 0 : static void BVMenuFindInFontView(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1721 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1722 :
1723 0 : FVChangeChar(bv->fv,bv->bc->sc->orig_pos);
1724 0 : GDrawSetVisible(bv->fv->gw,true);
1725 0 : GDrawRaise(bv->fv->gw);
1726 0 : }
1727 :
1728 0 : static void BVMenuPalettesDock(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1729 0 : PalettesChangeDocking();
1730 0 : }
1731 :
1732 0 : static void BVMenuPaletteShow(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1733 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1734 :
1735 0 : BVPaletteSetVisible(bv, mi->mid==MID_Tools?1:mi->mid==MID_Shades?2:0, !BVPaletteIsVisible(bv, mi->mid==MID_Tools?1:mi->mid==MID_Shades?2:0));
1736 0 : }
1737 :
1738 0 : static void BVUndo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1739 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1740 0 : if ( bv->bc->undoes==NULL )
1741 0 : return;
1742 0 : BCDoUndo(bv->bc);
1743 : }
1744 :
1745 0 : static SplineChar *SCofBV(BitmapView *bv) {
1746 0 : SplineFont *sf = bv->bdf->sf;
1747 0 : int i, cid = bv->bc->orig_pos;
1748 :
1749 0 : if ( sf->subfonts ) {
1750 0 : for ( i=0; i<sf->subfontcnt; ++i )
1751 0 : if ( cid<sf->subfonts[i]->glyphcnt && sf->subfonts[i]->glyphs[cid]!=NULL )
1752 0 : return( sf->subfonts[i]->glyphs[cid] );
1753 :
1754 0 : return( NULL );
1755 : } else
1756 0 : return( sf->glyphs[cid] );
1757 : }
1758 :
1759 0 : static void BVMenuSetWidth(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1760 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1761 : char buffer[10];
1762 : char *ret;
1763 : BDFFont *bdf;
1764 0 : int mysize = bv->bdf->pixelsize;
1765 : SplineChar *sc;
1766 : int val;
1767 :
1768 0 : if ( !bv->bdf->sf->onlybitmaps )
1769 0 : return;
1770 0 : if ( mi->mid==MID_SetWidth ) {
1771 0 : sprintf( buffer,"%d",bv->bc->width);
1772 0 : ret = gwwv_ask_string(_("Set Width..."),buffer,_("Set Width..."));
1773 : } else {
1774 0 : sprintf( buffer,"%d",bv->bc->vwidth);
1775 0 : ret = gwwv_ask_string(_("Set Vertical Width..."),buffer,_("Set Vertical Width..."));
1776 : }
1777 0 : if ( ret==NULL )
1778 0 : return;
1779 0 : val = strtol(ret,NULL,10);
1780 0 : free(ret);
1781 0 : if ( val<0 )
1782 0 : return;
1783 0 : if ( mi->mid==MID_SetWidth )
1784 0 : bv->bc->width = val;
1785 : else
1786 0 : bv->bc->vwidth = val;
1787 0 : BCCharChangedUpdate(bv->bc);
1788 0 : for ( bdf=bv->bdf->sf->bitmaps; bdf!=NULL; bdf=bdf->next )
1789 0 : if ( bdf->pixelsize > mysize )
1790 0 : return;
1791 0 : if ( (sc=SCofBV(bv))!=NULL ) {
1792 0 : if ( mi->mid==MID_SetWidth )
1793 0 : sc->width = val*(sc->parent->ascent+sc->parent->descent)/mysize;
1794 : else
1795 0 : sc->vwidth = val*(sc->parent->ascent+sc->parent->descent)/mysize;
1796 0 : SCCharChangedUpdate(sc,ly_none);
1797 : }
1798 : }
1799 :
1800 0 : static void BVRedo(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1801 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1802 0 : if ( bv->bc->redoes==NULL )
1803 0 : return;
1804 0 : BCDoRedo(bv->bc);
1805 : }
1806 :
1807 0 : static void _BVUnlinkRef(BitmapView *bv) {
1808 0 : int anyrefs = false;
1809 0 : BDFRefChar *ref, *next, *prev = NULL;
1810 :
1811 0 : if ( bv->bc->refs!=NULL ) {
1812 0 : BCPreserveState(bv->bc);
1813 0 : for ( ref=bv->bc->refs; ref!=NULL && !anyrefs; ref=ref->next )
1814 0 : if ( ref->selected ) anyrefs = true;
1815 0 : for ( ref=bv->bc->refs; ref!=NULL ; ref=next ) {
1816 0 : next = ref->next;
1817 0 : if ( ref->selected || !anyrefs) {
1818 0 : BCPasteInto( bv->bc,ref->bdfc,ref->xoff,ref->yoff,false,false );
1819 0 : BCMergeReferences( bv->bc,ref->bdfc,ref->xoff,ref->yoff );
1820 0 : BCRemoveDependent( bv->bc,ref );
1821 : } else
1822 0 : prev = ref;
1823 : }
1824 0 : BCCharChangedUpdate(bv->bc);
1825 : }
1826 0 : }
1827 :
1828 0 : static void BVUnlinkRef(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1829 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1830 0 : _BVUnlinkRef(bv);
1831 0 : }
1832 :
1833 0 : static void BVRemoveUndoes(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1834 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1835 0 : UndoesFree(bv->bc->undoes); bv->bc->undoes = NULL;
1836 0 : UndoesFree(bv->bc->redoes); bv->bc->redoes = NULL;
1837 0 : }
1838 :
1839 0 : static void BVCopy(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1840 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1841 0 : BCCopySelected(bv->bc,bv->bdf->pixelsize,BDFDepth(bv->bdf));
1842 0 : }
1843 :
1844 0 : static void BVCopyRef(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1845 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1846 0 : BCCopyReference(bv->bc,bv->bdf->pixelsize,BDFDepth(bv->bdf));
1847 0 : }
1848 :
1849 0 : static void BVDoClear(BitmapView *bv) {
1850 : BDFRefChar *head, *next;
1851 0 : BDFChar *bc = bv->bc;
1852 0 : int refs_changed = false;
1853 :
1854 0 : for ( head=bc->refs; head!=NULL; head=next ) {
1855 0 : next = head->next;
1856 0 : if ( head->selected ) {
1857 0 : if ( !refs_changed ) {
1858 0 : BCPreserveState( bc );
1859 0 : refs_changed = true;
1860 : }
1861 0 : BCRemoveDependent( bc,head );
1862 : }
1863 : }
1864 :
1865 0 : if ( bc->selection!=NULL ) {
1866 0 : BCPreserveState( bc );
1867 0 : BDFFloatFree( bc->selection );
1868 0 : bv->bc->selection = NULL;
1869 0 : BCCharChangedUpdate( bc );
1870 0 : } else if ( refs_changed ) {
1871 0 : BCCharChangedUpdate( bc );
1872 : }
1873 0 : }
1874 :
1875 0 : static void BVClear(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1876 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1877 0 : BVDoClear(bv);
1878 0 : }
1879 :
1880 0 : static void BVPaste(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1881 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1882 0 : if ( CopyContainsBitmap())
1883 0 : PasteToBC(bv->bc,bv->bdf->pixelsize,BDFDepth(bv->bdf));
1884 0 : }
1885 :
1886 0 : static void BVCut(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1887 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1888 0 : BVCopy(gw,mi,e);
1889 0 : BVDoClear(bv);
1890 0 : }
1891 :
1892 0 : static void BVSelectAll(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1893 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1894 0 : BDFChar *bc = bv->bc;
1895 :
1896 0 : BDFFloatCreate(bc,bc->xmin,bc->xmax,bc->ymin,bc->ymax, true);
1897 0 : BCCharUpdate(bc);
1898 0 : }
1899 :
1900 0 : static void BVMenuFontInfo(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1901 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1902 0 : DelayEvent(FontMenuFontInfo,bv->fv);
1903 0 : }
1904 :
1905 0 : static void BVMenuBDFInfo(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1906 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1907 0 : SFBdfProperties(bv->bdf->sf,bv->fv->b.map,bv->bdf);
1908 0 : }
1909 :
1910 0 : static void BVMenuGetInfo(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1911 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1912 0 : SCCharInfo(bv->bc->sc,bv->fv->b.active_layer,bv->fv->b.map,BVCurEnc(bv));
1913 0 : }
1914 :
1915 0 : static void BVMenuBitmaps(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1916 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1917 0 : BitmapDlg(bv->fv,bv->bc->sc,mi->mid==MID_AvailBitmaps );
1918 0 : }
1919 :
1920 0 : static void BVMenuRmGlyph(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1921 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1922 : BitmapView *bvs, *bvnext;
1923 0 : BDFFont *bdf = bv->bdf;
1924 0 : BDFChar *bc = bv->bc;
1925 : FontView *fv;
1926 :
1927 0 : for ( bvs=bc->views; bvs!=NULL; bvs=bvnext ) {
1928 0 : bvnext = bvs->next;
1929 0 : GDrawDestroyWindow(bvs->gw);
1930 : }
1931 0 : bdf->glyphs[bc->orig_pos] = NULL;
1932 : /* Can't free the glyph yet, need to process all the destroy events */
1933 : /* which touch bc->views first */
1934 0 : DelayEvent( (void (*)(void *))BDFCharFree,bc);
1935 0 : for ( fv = (FontView *) (bdf->sf->fv); fv!=NULL; fv=(FontView *) (fv->b.nextsame) )
1936 0 : GDrawRequestExpose(fv->v,NULL,false);
1937 0 : }
1938 :
1939 0 : static int askfraction(int *xoff, int *yoff) {
1940 : static int lastx=1, lasty = 3;
1941 : char buffer[30];
1942 : char *ret, *end, *end2;
1943 : int xv, yv;
1944 :
1945 0 : sprintf( buffer, "%d:%d", lastx, lasty );
1946 0 : ret = ff_ask_string(_("Skew"),buffer,_("Skew Ratio"));
1947 0 : if ( ret==NULL )
1948 0 : return( 0 );
1949 0 : xv = strtol(ret,&end,10);
1950 0 : yv = strtol(end+1,&end2,10);
1951 0 : if ( xv==0 || xv>10 || xv<-10 || yv<=0 || yv>10 || *end!=':' || *end2!='\0' ) {
1952 0 : ff_post_error( _("Bad Number"),_("Bad Number") );
1953 0 : free(ret);
1954 0 : return( 0 );
1955 : }
1956 0 : free(ret);
1957 0 : *xoff = lastx = xv; *yoff = lasty = yv;
1958 0 : return( 1 );
1959 : }
1960 :
1961 0 : void BVRotateBitmap(BitmapView *bv,enum bvtools type ) {
1962 0 : int xoff=0, yoff=0;
1963 :
1964 0 : if ( type==bvt_skew )
1965 0 : if ( !askfraction(&xoff,&yoff))
1966 0 : return;
1967 0 : BCPreserveState(bv->bc);
1968 0 : BCTransFunc(bv->bc,type,xoff,yoff);
1969 0 : BCCharChangedUpdate(bv->bc);
1970 : }
1971 :
1972 0 : void BVMenuRotateInvoked(GWindow gw,struct gmenuitem *mi,GEvent *g) {
1973 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1974 0 : BVRotateBitmap(bv,mi->mid);
1975 0 : }
1976 :
1977 0 : static void ellistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1978 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1979 :
1980 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
1981 0 : switch ( mi->mid ) {
1982 : case MID_RegenBitmaps:
1983 0 : mi->ti.disabled = bv->bdf->sf->onlybitmaps;
1984 0 : break;
1985 : }
1986 : }
1987 0 : }
1988 :
1989 0 : static void edlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
1990 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
1991 : BDFRefChar *cur;
1992 :
1993 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
1994 0 : switch ( mi->mid ) {
1995 : case MID_Cut: /*case MID_Copy:*/ case MID_Clear:
1996 : /* If nothing is selected, copy copies everything */
1997 0 : mi->ti.disabled = bv->bc->selection==NULL;
1998 0 : for ( cur=bv->bc->refs; cur!=NULL && mi->ti.disabled; cur=cur->next ) {
1999 0 : if ( cur->selected )
2000 0 : mi->ti.disabled = false;
2001 : }
2002 0 : break;
2003 : case MID_Paste:
2004 0 : mi->ti.disabled = !CopyContainsBitmap();
2005 0 : break;
2006 : case MID_Undo:
2007 0 : mi->ti.disabled = bv->bc->undoes==NULL;
2008 0 : break;
2009 : case MID_Redo:
2010 0 : mi->ti.disabled = bv->bc->redoes==NULL;
2011 0 : break;
2012 : case MID_RemoveUndoes:
2013 0 : mi->ti.disabled = bv->bc->redoes==NULL && bv->bc->undoes==NULL;
2014 0 : break;
2015 : case MID_UnlinkRef:
2016 0 : mi->ti.disabled = bv->bc->refs==NULL;
2017 0 : break;
2018 : }
2019 : }
2020 0 : }
2021 :
2022 0 : static void pllistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
2023 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
2024 : extern int palettes_docked;
2025 :
2026 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
2027 0 : switch ( mi->mid ) {
2028 : case MID_Tools:
2029 0 : mi->ti.checked = BVPaletteIsVisible(bv,1);
2030 0 : break;
2031 : case MID_Layers:
2032 0 : mi->ti.checked = BVPaletteIsVisible(bv,0);
2033 0 : break;
2034 : case MID_Shades:
2035 0 : mi->ti.disabled = BDFDepth(bv->bdf)==1;
2036 0 : if ( !mi->ti.disabled )
2037 0 : mi->ti.checked = BVPaletteIsVisible(bv,2);
2038 0 : break;
2039 : case MID_DockPalettes:
2040 0 : mi->ti.checked = palettes_docked;
2041 0 : break;
2042 : }
2043 : }
2044 0 : }
2045 :
2046 0 : static void vwlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
2047 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
2048 : BDFFont *bdf;
2049 :
2050 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
2051 0 : switch ( mi->mid ) {
2052 : case MID_ZoomIn:
2053 0 : mi->ti.disabled = bv->scale==32;
2054 0 : break;
2055 : case MID_ZoomOut:
2056 0 : mi->ti.checked = bv->scale==1;
2057 0 : break;
2058 : case MID_Bigger:
2059 0 : mi->ti.disabled = bv->bdf->next==NULL;
2060 0 : break;
2061 : case MID_Smaller:
2062 0 : for ( bdf=bv->bdf->sf->bitmaps; bdf!=NULL && bdf->next!=bv->bdf; bdf=bdf->next );
2063 0 : mi->ti.disabled = bdf==NULL;
2064 0 : break;
2065 : }
2066 : }
2067 0 : }
2068 :
2069 0 : static void mtlistcheck(GWindow gw,struct gmenuitem *mi,GEvent *e) {
2070 0 : BitmapView *bv = (BitmapView *) GDrawGetUserData(gw);
2071 :
2072 0 : for ( mi = mi->sub; mi->ti.text!=NULL || mi->ti.line ; ++mi ) {
2073 0 : switch ( mi->mid ) {
2074 : case MID_SetWidth:
2075 0 : mi->ti.disabled = !bv->bdf->sf->onlybitmaps;
2076 0 : break;
2077 : case MID_SetVWidth:
2078 0 : mi->ti.disabled = !bv->bdf->sf->onlybitmaps || !bv->bdf->sf->hasvmetrics;
2079 0 : break;
2080 : }
2081 : }
2082 0 : }
2083 :
2084 : static GMenuItem2 wnmenu[] = {
2085 : { { (unichar_t *) N_("New O_utline Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'u' }, H_("New Outline Window|Ctl+H"), NULL, NULL, BVMenuOpenOutline, 0 },
2086 : { { (unichar_t *) N_("New _Bitmap Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("New Bitmap Window|Ctl+J"), NULL, NULL, /* No function, never avail */NULL, 0 },
2087 : { { (unichar_t *) N_("New _Metrics Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("New Metrics Window|Ctl+K"), NULL, NULL, BVMenuOpenMetrics, 0 },
2088 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2089 : { { (unichar_t *) N_("Warnings"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, H_("Warnings|No Shortcut"), NULL, NULL, _MenuWarnings, MID_Warnings },
2090 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2091 : GMENUITEM2_EMPTY
2092 : };
2093 :
2094 0 : static void BVWindowMenuBuild(GWindow gw,struct gmenuitem *mi,GEvent *e) {
2095 : struct gmenuitem *wmi;
2096 0 : WindowMenuBuild(gw,mi,e);
2097 0 : for ( wmi = mi->sub; wmi->ti.text!=NULL || wmi->ti.line ; ++wmi ) {
2098 0 : switch ( wmi->mid ) {
2099 : case MID_Warnings:
2100 0 : wmi->ti.disabled = ErrorWindowExists();
2101 0 : break;
2102 : }
2103 : }
2104 0 : }
2105 :
2106 0 : static void BVMenuContextualHelp(GWindow base,struct gmenuitem *mi,GEvent *e) {
2107 0 : help("bitmapview.html");
2108 0 : }
2109 :
2110 : char *BVFlipNames[] = { N_("Flip Horizontally"), N_("Flip Vertically"),
2111 : /* GT: "CW" means Clockwise */
2112 : NU_("Rotate 90° CW"),
2113 : /* GT: "CW" means Counter-Clockwise */
2114 : NU_("Rotate 90° CCW"),
2115 : NU_("Rotate 180°"),
2116 : N_("Skew..."), NULL };
2117 :
2118 : static GMenuItem2 dummyitem[] = {
2119 : { { (unichar_t *) N_("Font|_New"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'N' }, NULL, NULL, NULL, NULL, 0 },
2120 : GMENUITEM2_EMPTY
2121 : };
2122 : static GMenuItem2 fllist[] = {
2123 : { { (unichar_t *) N_("Font|_New"), (GImage *) "filenew.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("New|Ctl+N"), NULL, NULL, MenuNew, 0 },
2124 : { { (unichar_t *) N_("_Open"), (GImage *) "fileopen.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'O' }, H_("Open|Ctl+O"), NULL, NULL, BVMenuOpen, 0 },
2125 : { { (unichar_t *) N_("Recen_t"), (GImage *) "filerecent.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 't' }, NULL, dummyitem, MenuRecentBuild, NULL, MID_Recent },
2126 : { { (unichar_t *) N_("_Close"), (GImage *) "fileclose.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Close|Ctl+Shft+Q"), NULL, NULL, BVMenuClose, 0 },
2127 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2128 : { { (unichar_t *) N_("_Save"), (GImage *) "filesave.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Save|Ctl+S"), NULL, NULL, BVMenuSave, 0 },
2129 : { { (unichar_t *) N_("S_ave as..."), (GImage *) "filesaveas.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Save as...|Ctl+Shft+S"), NULL, NULL, BVMenuSaveAs, 0 },
2130 : { { (unichar_t *) N_("_Generate Fonts..."), (GImage *) "filegenerate.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Generate Fonts...|Ctl+Shft+G"), NULL, NULL, BVMenuGenerate, 0 },
2131 : { { (unichar_t *) N_("Generate Mac _Family..."), (GImage *) "filegeneratefamily.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Generate Mac Family...|Alt+Ctl+G"), NULL, NULL, BVMenuGenerateFamily, 0 },
2132 : { { (unichar_t *) N_("Generate TTC..."), (GImage *) "filegeneratefamily.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Generate TTC...|No Shortcut"), NULL, NULL, BVMenuGenerateTTC, 0 },
2133 : { { (unichar_t *) N_("Expor_t..."), (GImage *) "fileexport.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Export...|No Shortcut"), NULL, NULL, BVMenuExport, 0 },
2134 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2135 : { { (unichar_t *) N_("_Import..."), (GImage *) "fileimport.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Import...|Ctl+Shft+I"), NULL, NULL, BVMenuImport, 0 },
2136 : { { (unichar_t *) N_("_Revert File"), (GImage *) "filerevert.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Revert File|Ctl+Shft+R"), NULL, NULL, BVMenuRevert, MID_Revert },
2137 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2138 : { { (unichar_t *) N_("Pr_eferences..."), (GImage *) "fileprefs.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Preferences...|No Shortcut"), NULL, NULL, MenuPrefs, 0 },
2139 : { { (unichar_t *) N_("_X Resource Editor..."), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("X Resource Editor...|No Shortcut"), NULL, NULL, MenuXRes, 0 },
2140 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2141 : { { (unichar_t *) N_("_Quit"), (GImage *) "filequit.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'Q' }, H_("Quit|Ctl+Q"), NULL, NULL, MenuExit, 0 },
2142 : GMENUITEM2_EMPTY
2143 : };
2144 :
2145 : static GMenuItem2 edlist[] = {
2146 : { { (unichar_t *) N_("_Undo"), (GImage *) "editundo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Undo|Ctl+Z"), NULL, NULL, BVUndo, MID_Undo },
2147 : { { (unichar_t *) N_("_Redo"), (GImage *) "editredo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Redo|Ctl+Y"), NULL, NULL, BVRedo, MID_Redo },
2148 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2149 : { { (unichar_t *) N_("Cu_t"), (GImage *) "editcut.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 't' }, H_("Cut|Ctl+X"), NULL, NULL, BVCut, MID_Cut },
2150 : { { (unichar_t *) N_("_Copy"), (GImage *) "editcopy.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'C' }, H_("Copy|Ctl+C"), NULL, NULL, BVCopy, MID_Copy },
2151 : { { (unichar_t *) N_("C_opy Reference"), (GImage *) "editcopyref.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Copy Reference|Ctl+G"), NULL, NULL, BVCopyRef, MID_CopyRef },
2152 : { { (unichar_t *) N_("_Paste"), (GImage *) "editpaste.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Paste|Ctl+V"), NULL, NULL, BVPaste, MID_Paste },
2153 : { { (unichar_t *) N_("C_lear"), (GImage *) "editclear.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, H_("Clear|Delete"), NULL, NULL, BVClear, MID_Clear },
2154 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2155 : { { (unichar_t *) N_("Select _All"), (GImage *) "editselect.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Select All|Ctl+A"), NULL, NULL, BVSelectAll, MID_SelAll },
2156 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2157 : { { (unichar_t *) N_("Remo_ve Undoes"), (GImage *) "menuempty.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'e' }, H_("Remove Undoes|No Shortcut"), NULL, NULL, BVRemoveUndoes, MID_RemoveUndoes },
2158 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2159 : { { (unichar_t *) N_("U_nlink Reference"), (GImage *) "editunlink.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'U' }, H_("Unlink Reference|Ctl+U"), NULL, NULL, BVUnlinkRef, MID_UnlinkRef },
2160 : GMENUITEM2_EMPTY
2161 : };
2162 :
2163 : static GMenuItem2 trlist[] = {
2164 : { { (unichar_t *) N_("Flip _Horizontally"), (GImage *) "transformfliphor.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, H_("Flip Horizontally|No Shortcut"), NULL, NULL, BVMenuRotateInvoked, bvt_fliph },
2165 : { { (unichar_t *) N_("Flip _Vertically"), (GImage *) "transformflipvert.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Flip Vertically|No Shortcut"), NULL, NULL, BVMenuRotateInvoked, bvt_flipv },
2166 : { { (unichar_t *) NU_("_Rotate 90° CW"), (GImage *) "transformrotatecw.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'R' }, H_("Rotate 90 CW|No Shortcut"), NULL, NULL, BVMenuRotateInvoked, bvt_rotate90cw },
2167 : { { (unichar_t *) NU_("Rotate _90° CCW"), (GImage *) "transformrotateccw.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '9' }, H_("Rotate 90 CCW|No Shortcut"), NULL, NULL, BVMenuRotateInvoked, bvt_rotate90ccw },
2168 : { { (unichar_t *) NU_("Rotate _180°"), (GImage *) "transformrotate180.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, '1' }, H_("Rotate 180|No Shortcut"), NULL, NULL, BVMenuRotateInvoked, bvt_rotate180 },
2169 : { { (unichar_t *) N_("_Skew..."), (GImage *) "transformskew.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Skew...|No Shortcut"), NULL, NULL, BVMenuRotateInvoked, bvt_skew },
2170 : GMENUITEM2_EMPTY
2171 : };
2172 :
2173 : static GMenuItem2 ellist[] = {
2174 : { { (unichar_t *) N_("_Font Info..."), (GImage *) "elementfontinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Font Info...|Ctl+Shft+F"), NULL, NULL, BVMenuFontInfo, 0 },
2175 : { { (unichar_t *) N_("Glyph _Info..."), (GImage *) "elementglyphinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("Glyph Info...|Ctl+I"), NULL, NULL, BVMenuGetInfo, MID_GetInfo },
2176 : { { (unichar_t *) N_("BDF Info..."), (GImage *) "elementbdfinfo.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'I' }, H_("BDF Info...|No Shortcut"), NULL, NULL, BVMenuBDFInfo, 0 },
2177 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2178 : { { (unichar_t *) N_("Bitm_ap Strikes Available..."), (GImage *) "elementbitmapsavail.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'A' }, H_("Bitmap Strikes Available...|Ctl+Shft+B"), NULL, NULL, BVMenuBitmaps, MID_AvailBitmaps },
2179 : { { (unichar_t *) N_("Regenerate _Bitmap Glyphs..."), (GImage *) "elementregenbitmaps.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Regenerate Bitmap Glyphs...|Ctl+B"), NULL, NULL, BVMenuBitmaps, MID_RegenBitmaps },
2180 : { { (unichar_t *) N_("Remove This Glyph"), (GImage *) "elementremovebitmaps.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Remove This Glyph|No Shortcut"), NULL, NULL, BVMenuRmGlyph, 0 },
2181 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2182 : { { (unichar_t *) N_("_Transformations"), (GImage *) "elementtransform.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'T' }, NULL, trlist, NULL, NULL, 0 },
2183 : GMENUITEM2_EMPTY
2184 : };
2185 :
2186 : static GMenuItem2 pllist[] = {
2187 : { { (unichar_t *) N_("_Tools"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'T' }, H_("Tools|No Shortcut"), NULL, NULL, BVMenuPaletteShow, MID_Tools },
2188 : { { (unichar_t *) N_("_Layers"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'L' }, H_("Layers|No Shortcut"), NULL, NULL, BVMenuPaletteShow, MID_Layers },
2189 : { { (unichar_t *) N_("_Shades"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'S' }, H_("Shades|No Shortcut"), NULL, NULL, BVMenuPaletteShow, MID_Shades },
2190 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2191 : { { (unichar_t *) N_("_Docked Palettes"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 1, 0, 0, 0, 1, 1, 0, 'D' }, H_("Docked Palettes|No Shortcut"), NULL, NULL, BVMenuPalettesDock, MID_DockPalettes },
2192 : GMENUITEM2_EMPTY
2193 : };
2194 :
2195 : static GMenuItem2 vwlist[] = {
2196 : { { (unichar_t *) N_("_Fit"), (GImage *) "viewfit.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, H_("Fit|Ctl+F"), NULL, NULL, BVMenuScale, MID_Fit },
2197 : { { (unichar_t *) N_("Z_oom out"), (GImage *) "viewzoomout.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'o' }, H_("Zoom out|Alt+Ctl+-"), NULL, NULL, BVMenuScale, MID_ZoomOut },
2198 : { { (unichar_t *) N_("Zoom _in"), (GImage *) "viewzoomin.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'i' }, H_("Zoom in|Alt+Ctl+Shft++"), NULL, NULL, BVMenuScale, MID_ZoomIn },
2199 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2200 : { { (unichar_t *) N_("_Next Glyph"), (GImage *) "viewnext.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'N' }, H_("Next Glyph|Ctl+]"), NULL, NULL, BVMenuChangeChar, MID_Next },
2201 : { { (unichar_t *) N_("_Prev Glyph"), (GImage *) "viewprev.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'P' }, H_("Prev Glyph|Ctl+["), NULL, NULL, BVMenuChangeChar, MID_Prev },
2202 : { { (unichar_t *) N_("Next _Defined Glyph"), (GImage *) "viewnextdef.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'D' }, H_("Next Defined Glyph|Alt+Ctl+]"), NULL, NULL, BVMenuChangeChar, MID_NextDef },
2203 : { { (unichar_t *) N_("Prev Defined Gl_yph"), (GImage *) "viewprevdef.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'a' }, H_("Prev Defined Glyph|Alt+Ctl+["), NULL, NULL, BVMenuChangeChar, MID_PrevDef },
2204 : { { (unichar_t *) N_("_Goto"), (GImage *) "viewgoto.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'G' }, H_("Goto|Ctl+Shft+>"), NULL, NULL, BVMenuGotoChar, 0 },
2205 : { { (unichar_t *) N_("Find In Font _View"), (GImage *) "viewfindinfont.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, H_("Find In Font View|Ctl+Shft+<"), NULL, NULL, BVMenuFindInFontView, 0 },
2206 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2207 : { { (unichar_t *) N_("_Bigger Pixel Size"), (GImage *) "viewbiggersize.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'B' }, H_("Bigger Pixel Size|Ctl+Shft++"), NULL, NULL, BVMenuChangePixelSize, MID_Bigger },
2208 : { { (unichar_t *) N_("_Smaller Pixel Size"), (GImage *) "viewsmallersize.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'S' }, H_("Smaller Pixel Size|Ctl+-"), NULL, NULL, BVMenuChangePixelSize, MID_Smaller },
2209 : { { NULL, NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 1, 0, 0, 0, '\0' }, NULL, NULL, NULL, NULL, 0 }, /* line */
2210 : { { (unichar_t *) N_("_Palettes"), (GImage *) "viewpalettes.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, NULL, pllist, pllistcheck, NULL, 0 },
2211 : GMENUITEM2_EMPTY
2212 : };
2213 :
2214 : static GMenuItem2 mtlist[] = {
2215 : { { (unichar_t *) N_("Set _Width..."), (GImage *) "metricssetwidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Set Width...|Ctl+Shft+L"), NULL, NULL, BVMenuSetWidth, MID_SetWidth },
2216 : { { (unichar_t *) N_("Set _Vertical Width..."), (GImage *) "metricssetvwidth.png", COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, H_("Set Vertical Width...|Ctl+Shft+L"), NULL, NULL, BVMenuSetWidth, MID_SetVWidth },
2217 : GMENUITEM2_EMPTY
2218 : };
2219 :
2220 : static GMenuItem2 mblist[] = {
2221 : { { (unichar_t *) N_("_File"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'F' }, NULL, fllist, fllistcheck, NULL, 0 },
2222 : { { (unichar_t *) N_("_Edit"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'E' }, NULL, edlist, edlistcheck, NULL, 0 },
2223 : { { (unichar_t *) N_("E_lement"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'l' }, NULL, ellist, ellistcheck, NULL, 0 },
2224 : { { (unichar_t *) N_("_View"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'V' }, NULL, vwlist, vwlistcheck, NULL, 0 },
2225 : { { (unichar_t *) N_("_Metrics"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'M' }, NULL, mtlist, mtlistcheck, NULL, 0 },
2226 : { { (unichar_t *) N_("_Window"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'W' }, NULL, wnmenu, BVWindowMenuBuild, NULL, 0 },
2227 : { { (unichar_t *) N_("_Help"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 1, 0, 0, 0, 0, 1, 1, 0, 'H' }, NULL, helplist, NULL, NULL, 0 },
2228 : GMENUITEM2_EMPTY
2229 : };
2230 :
2231 : #define bitmap_width 16
2232 : #define bitmap_height 16
2233 : static unsigned char bitmap_bits[] = {
2234 : 0x00, 0x00, 0xfc, 0x03, 0xfc, 0x03, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c,
2235 : 0x30, 0x0c, 0xf0, 0x03, 0xf0, 0x03, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c,
2236 : 0x30, 0x0c, 0xfc, 0x03, 0xfc, 0x03, 0x00, 0x00};
2237 :
2238 : static int bitmapview_ready = false;
2239 :
2240 0 : static void BitmapViewFinish() {
2241 0 : if ( !bitmapview_ready ) return;
2242 0 : bitmapview_ready = 0;
2243 0 : mb2FreeGetText(mblist);
2244 : }
2245 :
2246 0 : void BitmapViewFinishNonStatic() {
2247 0 : BitmapViewFinish();
2248 0 : }
2249 :
2250 0 : static void BitmapViewInit(void) {
2251 : // static int done = false; // superseded by bitmapview_ready.
2252 : int i;
2253 :
2254 0 : if ( bitmapview_ready )
2255 0 : return;
2256 0 : bitmapview_ready = true;
2257 :
2258 0 : mb2DoGetText(mblist);
2259 0 : for ( i=0; BVFlipNames[i]!=NULL ; ++i )
2260 0 : BVFlipNames[i] = S_(BVFlipNames[i]);
2261 0 : atexit(&BitmapViewFinishNonStatic);
2262 : }
2263 :
2264 0 : BitmapView *BitmapViewCreate(BDFChar *bc, BDFFont *bdf, FontView *fv, int enc) {
2265 0 : BitmapView *bv = calloc(1,sizeof(BitmapView));
2266 : GRect pos, zoom, size;
2267 : GWindow gw;
2268 : GWindowAttrs wattrs;
2269 : GGadgetData gd;
2270 : GRect gsize;
2271 : int sbsize;
2272 : char buf[300];
2273 : static GWindow icon = NULL;
2274 : GTextInfo ti;
2275 : FontRequest rq;
2276 : int as, ds, ld;
2277 : static char *infofamily = NULL;
2278 :
2279 0 : BitmapViewInit();
2280 :
2281 0 : BVShows.lastpixelsize = bdf->pixelsize;
2282 :
2283 0 : if ( icon==NULL )
2284 0 : icon = GDrawCreateBitmap(NULL,bitmap_width,bitmap_height,bitmap_bits);
2285 :
2286 0 : bv->bc = bc;
2287 0 : bv->scale = 1;
2288 0 : bv->xoff = bv->yoff = 20;
2289 0 : bv->next = bc->views;
2290 0 : bc->views = bv;
2291 0 : bv->fv = fv;
2292 0 : bv->enc = enc;
2293 0 : bv->map_of_enc = fv->b.map;
2294 0 : bv->bdf = bdf;
2295 0 : bv->color = 255;
2296 0 : bv->shades_hidden = bdf->clut==NULL;
2297 :
2298 0 : bv->showfore = BVShows.showfore;
2299 0 : bv->showoutline = BVShows.showoutline;
2300 0 : bv->showgrid = BVShows.showgrid;
2301 0 : bv->scscale = ((real) (bdf->pixelsize))/(bdf->sf->ascent+bdf->sf->descent);
2302 :
2303 0 : memset(&wattrs,0,sizeof(wattrs));
2304 0 : wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_utf8_ititle;
2305 0 : wattrs.event_masks = ~(1<<et_charup);
2306 0 : wattrs.cursor = ct_pointer;
2307 0 : wattrs.utf8_icon_title = BVMakeTitles(bv,bc,buf);
2308 0 : wattrs.utf8_window_title = buf;
2309 0 : wattrs.icon = icon;
2310 0 : if ( wattrs.icon )
2311 0 : wattrs.mask |= wam_icon;
2312 0 : pos.x = 8+9*16+10; pos.width=bv_width; pos.height = bv_height;
2313 0 : DefaultY(&pos);
2314 :
2315 0 : bv->gw = gw = GDrawCreateTopWindow(NULL,&pos,bv_e_h,bv,&wattrs);
2316 0 : free( (unichar_t *) wattrs.icon_title );
2317 :
2318 0 : GDrawGetSize(GDrawGetRoot(screen_display),&zoom);
2319 0 : zoom.x = BVPalettesWidth(); zoom.width -= zoom.x-10;
2320 0 : zoom.height -= 30; /* Room for title bar & such */
2321 0 : GDrawSetZoom(gw,&zoom,-1);
2322 :
2323 0 : memset(&gd,0,sizeof(gd));
2324 0 : gd.flags = gg_visible | gg_enabled;
2325 0 : helplist[0].invoke = BVMenuContextualHelp;
2326 0 : gd.u.menu2 = mblist;
2327 0 : bv->mb = GMenu2BarCreate( gw, &gd, NULL);
2328 0 : GGadgetGetSize(bv->mb,&gsize);
2329 0 : bv->mbh = gsize.height;
2330 0 : bv->infoh = GDrawPointsToPixels(gw,36);
2331 :
2332 0 : gd.pos.y = bv->mbh+bv->infoh;
2333 0 : gd.pos.width = sbsize = GDrawPointsToPixels(gw,_GScrollBar_Width);
2334 0 : gd.pos.height = pos.height-bv->mbh-bv->infoh - sbsize;
2335 0 : gd.pos.x = pos.width-sbsize;
2336 0 : gd.u.sbinit = NULL;
2337 0 : gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
2338 0 : bv->vsb = GScrollBarCreate(gw,&gd,bv);
2339 :
2340 0 : gd.pos.y = pos.height-sbsize; gd.pos.height = sbsize;
2341 0 : gd.pos.width = pos.width - sbsize;
2342 0 : gd.pos.x = 0;
2343 0 : gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels;
2344 0 : bv->hsb = GScrollBarCreate(gw,&gd,bv);
2345 :
2346 0 : memset(&gd, '\0', sizeof(gd));
2347 0 : memset(&ti, '\0', sizeof(ti));
2348 0 : gd.pos.x = pos.width - GDrawPointsToPixels(gw,111);
2349 0 : gd.pos.y = bv->mbh + GDrawPointsToPixels(gw,6);
2350 : /*gd.pos.width = GDrawPointsToPixels(gw,106);*/
2351 0 : gd.label = &ti;
2352 0 : ti.text = (unichar_t *) _("Recalculate Bitmaps");
2353 0 : ti.text_is_1byte = true;
2354 0 : gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels;
2355 0 : if ( fv->b.sf->onlybitmaps )
2356 0 : gd.flags = gg_pos_in_pixels;
2357 0 : gd.handle_controlevent = BVRecalc;
2358 0 : bv->recalc = GButtonCreate(gw,&gd,bv);
2359 0 : GGadgetGetSize(bv->recalc,&size);
2360 0 : GGadgetMove(bv->recalc,pos.width - size.width - GDrawPointsToPixels(gw,6),size.y);
2361 :
2362 0 : pos.y = bv->mbh+bv->infoh; pos.height -= bv->mbh + sbsize + bv->infoh;
2363 0 : pos.x = 0; pos.width -= sbsize;
2364 0 : wattrs.mask = wam_events|wam_cursor|wam_backcol;
2365 0 : wattrs.background_color = view_bgcol;
2366 0 : wattrs.event_masks = -1;
2367 0 : wattrs.cursor = ( bc->refs == NULL ) ? ct_pencil : ct_pointer;
2368 0 : bv->v = GWidgetCreateSubWindow(gw,&pos,v_e_h,bv,&wattrs);
2369 :
2370 0 : bv->height = pos.height; bv->width = pos.width;
2371 0 : bv->b1_tool = ( bc->refs == NULL ) ? bvt_pencil : bvt_pointer; bv->cb1_tool = bvt_pointer;
2372 0 : bv->b2_tool = bvt_magnify; bv->cb2_tool = bvt_shift;
2373 0 : bv->s1_tool = bv->s2_tool = bv->er_tool = bvt_pointer;
2374 0 : bv->showing_tool = ( bc->refs == NULL ) ? bvt_pencil : bvt_pointer;
2375 0 : bv->pressed_tool = bv->pressed_display = bv->active_tool = bvt_none;
2376 :
2377 : /*GWidgetHidePalettes();*/
2378 : /*bv->tools = BVMakeTools(bv);*/
2379 : /*bv->layers = BVMakeLayers(bv);*/
2380 :
2381 0 : if ( infofamily==NULL ) { /* Yes, let's use the same resource name */
2382 0 : infofamily = copy(GResourceFindString("CharView.InfoFamily"));
2383 : /* FontConfig doesn't have access to all the X11 bitmap fonts */
2384 : /* so the font I used to use isn't found, and a huge monster is */
2385 : /* inserted instead */
2386 0 : if ( infofamily==NULL )
2387 0 : infofamily = SANS_UI_FAMILIES;
2388 : }
2389 :
2390 0 : memset(&rq,0,sizeof(rq));
2391 0 : rq.utf8_family_name = infofamily;
2392 0 : rq.point_size = -7;
2393 0 : rq.weight = 400;
2394 0 : bv->small = GDrawInstanciateFont(gw,&rq);
2395 0 : GDrawWindowFontMetrics(gw,bv->small,&as,&ds,&ld);
2396 0 : bv->sfh = as+ds; bv->sas = as;
2397 :
2398 0 : BVFit(bv);
2399 0 : GDrawSetVisible(bv->v,true);
2400 0 : GDrawSetVisible(gw,true);
2401 0 : return( bv );
2402 : }
2403 :
2404 0 : BitmapView *BitmapViewCreatePick(int enc, FontView *fv) {
2405 : BDFFont *bdf;
2406 : SplineFont *sf;
2407 : EncMap *map;
2408 :
2409 0 : sf = fv->b.cidmaster ? fv->b.cidmaster : fv->b.sf;
2410 0 : map = fv->b.map;
2411 :
2412 0 : if ( fv->show!=fv->filled )
2413 0 : bdf = fv->show;
2414 : else
2415 0 : for ( bdf = sf->bitmaps; bdf!=NULL && bdf->pixelsize!=BVShows.lastpixelsize; bdf = bdf->next );
2416 0 : if ( bdf==NULL )
2417 0 : bdf = sf->bitmaps;
2418 :
2419 0 : return( BitmapViewCreate(BDFMakeChar(bdf,map,enc),bdf,fv,enc));
2420 : }
2421 :
2422 0 : void BitmapViewFree(BitmapView *bv) {
2423 0 : free(bv);
2424 0 : }
2425 :
2426 0 : static void BC_RefreshAll(BDFChar *bc) {
2427 : BitmapView *bv;
2428 :
2429 0 : for ( bv = bc->views; bv!=NULL; bv = bv->next )
2430 0 : GDrawRequestExpose(bv->v,NULL,false);
2431 0 : }
2432 :
2433 0 : static void BC_DestroyAll(BDFChar *bc) {
2434 : BitmapView *bv, *next;
2435 :
2436 0 : for ( bv = bc->views; bv!=NULL; bv=next ) {
2437 0 : next = bv->next;
2438 0 : GDrawDestroyWindow(bv->gw);
2439 : }
2440 0 : }
2441 :
2442 : struct bc_interface gdraw_bc_interface = {
2443 : BC_CharChangedUpdate,
2444 : BC_RefreshAll,
2445 : BC_DestroyAll
2446 : };
|