1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Grabber plugin for managing font objects.
12 *
13 * By Shawn Hargreaves.
14 *
15 * GRX font file reader by Mark Wodrich.
16 *
17 * See readme.txt for copyright information.
18 */
19
20
21 #include <stdio.h>
22 #include <string.h>
23
24 #include "allegro.h"
25 #include "allegro/internal/aintern.h"
26 #include "../datedit.h"
27
28
29
30 /* creates a new font object */
makenew_font(long * size)31 static void* makenew_font(long* size)
32 {
33 FONT *f;
34 FONT_MONO_DATA* mf = 0, * mfread = font->data;
35
36 f = _AL_MALLOC(sizeof(FONT));
37
38 f->height = font->height;
39 f->vtable = font->vtable;
40
41 while(mfread) {
42 int i;
43
44 if(mf) {
45 mf->next = _AL_MALLOC(sizeof(FONT_MONO_DATA));
46 mf = mf->next;
47 } else f->data = mf = _AL_MALLOC(sizeof(FONT_MONO_DATA));
48
49 mf->begin = mfread->begin;
50 mf->end = mfread->end;
51 mf->next = 0;
52 mf->glyphs = _AL_MALLOC(sizeof(FONT_GLYPH*) * (mf->end - mf->begin));
53
54 for(i = mf->begin; i < mf->end; i++) {
55 FONT_GLYPH *gsrc = mfread->glyphs[i - mf->begin], *gdest;
56 int sz = ((gsrc->w + 7) / 8) * gsrc->h;
57
58 gdest = _AL_MALLOC(sizeof(FONT_GLYPH) + sz);
59 gdest->w = gsrc->w;
60 gdest->h = gsrc->h;
61 memcpy(gdest->dat, gsrc->dat, sz);
62
63 mf->glyphs[i - mf->begin] = gdest;
64 }
65
66 mfread = mfread->next;
67 }
68
69 return f;
70 }
71
72
73
74 /* displays a font in the grabber object view window */
plot_font(AL_CONST DATAFILE * dat,int x,int y)75 static void plot_font(AL_CONST DATAFILE *dat, int x, int y)
76 {
77 FONT* f = dat->dat;
78 int cx = x, bufpos, ch;
79 char buf[8];
80
81 y += 32;
82
83 if(is_mono_font(f)) {
84 FONT_MONO_DATA* mf = f->data;
85
86 while(mf) {
87 for(ch = mf->begin; ch < mf->end; ch++) {
88 bufpos = usetc(buf, ch);
89 usetc(buf + bufpos, 0);
90
91 if(text_length(f, buf) + cx + 4 > SCREEN_W) {
92 cx = x;
93 y += text_height(f) + 4;
94 }
95
96 if(y > SCREEN_H) break;
97
98 textout_ex(screen, f, buf, cx, y, gui_fg_color, -1);
99
100 cx += text_length(f, buf) + 4;
101 }
102
103 mf = mf->next;
104 }
105 } else {
106 FONT_COLOR_DATA* cf = f->data;
107
108 while(cf) {
109 for(ch = cf->begin; ch < cf->end; ch++) {
110 bufpos = usetc(buf, ch);
111 usetc(buf + bufpos, 0);
112
113 if(text_length(f, buf) + cx + 4 > SCREEN_W) {
114 cx = x;
115 y += text_height(f) + 4;
116 }
117
118 if(y > SCREEN_H) break;
119
120 textout_ex(screen, f, buf, cx, y, -1, -1);
121
122 cx += text_length(f, buf) + 4;
123 }
124
125 cf = cf->next;
126 }
127 }
128 }
129
130
131 /* returns a description string for a font object */
get_font_desc(AL_CONST DATAFILE * dat,char * s)132 static void get_font_desc(AL_CONST DATAFILE *dat, char *s)
133 {
134 FONT *fnt = (FONT *)dat->dat;
135 char *mono = (is_mono_font(fnt)) ? "mono" : "color";
136 int ranges = 0;
137 int glyphs = 0;
138
139 if(is_mono_font(fnt)) {
140 FONT_MONO_DATA* mf = fnt->data;
141
142 while(mf) {
143 ranges++;
144 glyphs += mf->end - mf->begin;
145 mf = mf->next;
146 }
147 } else {
148 FONT_COLOR_DATA* cf = fnt->data;
149
150 while(cf) {
151 ranges++;
152 glyphs += cf->end - cf->begin;
153 cf = cf->next;
154 }
155 }
156
157 sprintf(s, "%s font, %d range%s, %d glyphs", mono, ranges, (ranges==1) ? "" : "s", glyphs);
158 }
159
160
161
162 /* exports a font into an external file */
export_font(AL_CONST DATAFILE * dat,AL_CONST char * filename)163 static int export_font(AL_CONST DATAFILE* dat, AL_CONST char* filename)
164 {
165 char buf[1024], tmp[1024];
166 PACKFILE *pack;
167 FONT* f = dat->dat;
168
169 BITMAP *bmp;
170 PALETTE pal;
171
172 int w = 0, h = 0, max = 0, i;
173
174 if(stricmp(get_extension(filename), "txt") == 0) {
175 replace_extension(buf, filename, "pcx", sizeof(buf));
176
177 if(exists(buf)) {
178 i = datedit_ask("%s already exists, overwrite", buf);
179 if(i == 27 || i == 'n' || i == 'N') return TRUE;
180 }
181
182 pack = pack_fopen(filename, F_WRITE);
183 if(!pack) return FALSE;
184
185 if(is_mono_font(f)) {
186 FONT_MONO_DATA* mf = f->data;
187 while(mf) {
188 sprintf(tmp, "%s 0x%04X 0x%04X\n", (mf == f->data) ? get_filename(buf) : "-", mf->begin, mf->end - 1);
189 pack_fputs(tmp, pack);
190 mf = mf->next;
191 }
192 } else {
193 FONT_COLOR_DATA* cf = f->data;
194 while(cf) {
195 sprintf(tmp, "%s 0x%04X 0x%04X\n", (cf == f->data) ? get_filename(buf) : "-", cf->begin, cf->end - 1);
196 pack_fputs(tmp, pack);
197 cf = cf->next;
198 }
199 }
200
201 pack_fclose(pack);
202
203 filename = buf;
204 } else {
205 int multi = 0;
206
207 if(is_mono_font(f)) {
208 if( ((FONT_MONO_DATA*)f->data) ->next) multi = 1;
209 } else {
210 if( ((FONT_COLOR_DATA*)f->data)->next) multi = 1;
211 }
212
213 if(multi) {
214 i = datedit_ask("Really export multi-range font as bitmap rather than .txt");
215 if(i == 27 || i == 'n' || i == 'N') return TRUE;
216 }
217 }
218
219 if(is_mono_font(f)) {
220 FONT_MONO_DATA* mf = f->data;
221
222 while(mf) {
223 for(i = mf->begin; i < mf->end; i++) {
224 FONT_GLYPH* g = mf->glyphs[i - mf->begin];
225
226 max++;
227 if(g->w > w) w = g->w;
228 if(g->h > h) h = g->h;
229 }
230
231 mf = mf->next;
232 }
233 } else {
234 FONT_COLOR_DATA* cf = f->data;
235 int i;
236
237 while(cf) {
238 for(i = cf->begin; i < cf->end; i++) {
239 BITMAP* g = cf->bitmaps[i - cf->begin];
240
241 max++;
242 if(g->w > w) w = g->w;
243 if(g->h > h) h = g->h;
244 }
245
246 cf = cf->next;
247 }
248 }
249
250 w = (w + 16) & 0xFFF0;
251 h = (h + 16) & 0xFFF0;
252
253 bmp = create_bitmap_ex(8, 1 + w * 16, 1 + h * ((max + 15) / 16) );
254 clear_to_color(bmp, 255);
255
256 max = 0;
257
258 if(is_mono_font(f)) {
259 FONT_MONO_DATA* mf = f->data;
260
261 while(mf) {
262 for(i = mf->begin; i < mf->end; i++) {
263 textprintf_ex(bmp, f, 1 + w * (max & 15), 1 + h * (max / 16), 1, 0, "%c", i);
264 max++;
265 }
266
267 mf = mf->next;
268 }
269 } else {
270 FONT_COLOR_DATA* cf = f->data;
271
272 while(cf) {
273 for(i = cf->begin; i < cf->end; i++) {
274 textprintf_ex(bmp, f, 1 + w * (max & 15), 1 + h * (max / 16), -1, 0, "%c", i);
275 max++;
276 }
277
278 cf = cf->next;
279 }
280 }
281
282 get_palette(pal);
283
284 save_bitmap(filename, bmp, pal);
285 destroy_bitmap(bmp);
286
287 return (errno == 0);
288 }
289
290
291
292 /* magic number for GRX format font files */
293 #define FONTMAGIC 0x19590214L
294
295
296
297 /* import routine for the GRX font copyright message */
import_grx_message(AL_CONST char * filename)298 static void import_grx_message(AL_CONST char* filename)
299 {
300 PACKFILE *pack;
301 int w, h, num, i, end, begin;
302
303 pack = pack_fopen(filename, F_READ);
304 if(!pack) return;
305
306 if(pack_igetl(pack) != FONTMAGIC) {
307 pack_fclose(pack);
308 return;
309 }
310 pack_igetl(pack);
311
312 w = pack_igetw(pack);
313 h = pack_igetw(pack);
314
315 begin = pack_igetw(pack);
316 end = pack_igetw(pack) + 1;
317 num = end - begin;
318
319 if(pack_igetw(pack) == 0) {
320 for(i = 0; i < 38; i++) pack_getc(pack);
321 for(i = 0; i < num; i++) pack_igetw(pack);
322 } else {
323 for(i = 0; i < 38; i++) pack_getc(pack);
324 }
325
326 for(i = 0; i < num; i++) {
327 int sz;
328
329 sz = ((w + 7) / 8) * h;
330 while(sz) {
331 pack_getc(pack);
332 sz--;
333 }
334 }
335
336 if(!pack_feof(pack)) {
337 char cw_char[1024];
338
339 strcpy(cw_char, filename);
340 strcpy(get_extension(cw_char), "txt");
341 i = datedit_ask("Save font copyright message into '%s'", cw_char);
342 if(i != 27 && i != 'n' && i != 'N') {
343 PACKFILE* pout = pack_fopen(cw_char, F_WRITE);
344 if(pout) {
345 while(!pack_feof(pack)) {
346 i = pack_fread(cw_char, 1024, pack);
347 pack_fwrite(cw_char, i, pout);
348 }
349 }
350 pack_fclose(pout);
351 }
352 }
353
354 pack_fclose(pack);
355 }
356
357
358
359 /* upgrade_to_color, upgrade_to_color_data:
360 * Helper functions. Upgrades a monochrome font to a color font.
361 */
upgrade_to_color_data(FONT_MONO_DATA * mf)362 static FONT_COLOR_DATA* upgrade_to_color_data(FONT_MONO_DATA* mf)
363 {
364 FONT_COLOR_DATA* cf = _AL_MALLOC(sizeof(FONT_COLOR_DATA));
365 BITMAP** bits = _AL_MALLOC(sizeof(BITMAP*) * (mf->end - mf->begin));
366 int i;
367
368 cf->begin = mf->begin;
369 cf->end = mf->end;
370 cf->bitmaps = bits;
371 cf->next = 0;
372
373 for(i = mf->begin; i < mf->end; i++) {
374 FONT_GLYPH* g = mf->glyphs[i - mf->begin];
375 BITMAP* b = create_bitmap_ex(8, g->w, g->h);
376 clear_to_color(b, 0);
377 b->vtable->draw_glyph(b, g, 0, 0, 1, 0);
378
379 bits[i - mf->begin] = b;
380 free(g);
381 }
382
383 free(mf->glyphs);
384 free(mf);
385
386 return cf;
387 }
388
389
390
upgrade_to_color(FONT * f)391 static void upgrade_to_color(FONT* f)
392 {
393 FONT_MONO_DATA* mf = f->data;
394 FONT_COLOR_DATA * cf, *cf_write = 0;
395
396 if(is_color_font(f)) return;
397 f->vtable = font_vtable_color;
398
399 while(mf) {
400 FONT_MONO_DATA* mf_next = mf->next;
401
402 cf = upgrade_to_color_data(mf);
403 if(!cf_write) f->data = cf;
404 else cf_write->next = cf;
405
406 cf_write = cf;
407 mf = mf_next;
408 }
409 }
410
411
412
413 static DATAFILE *fonts_datafile;
414
415 /* Get a list of fonts for a font datafile */
datafile_fontname_getter(int index,int * list_size)416 static AL_CONST char *datafile_fontname_getter(int index, int *list_size)
417 {
418 DATAFILE *datf = fonts_datafile;
419 int n;
420
421 if (index<0) {
422 *list_size = 0;
423 if (datf) {
424 for(n=0; datf[n].type != DAT_END; n++) {
425 if (datf[n].type == DAT_FONT) (*list_size)++;
426 }
427 }
428
429 return NULL;
430 }
431
432 if (datf) {
433 for(n=0; datf[n].type != DAT_END && index>-1; n++)
434 if (datf[n].type == DAT_FONT) index--;
435 return get_datafile_property(&(datf[n-1]), DAT_ID('N','A','M','E'));
436 }
437 else {
438 return NULL;
439 }
440 }
441
442
443
444 /* List the fonts available in a datafile */
grab_datafile_font(AL_CONST char * filename)445 static FONT *grab_datafile_font(AL_CONST char *filename)
446 {
447 const char *names[2] = { NULL, NULL };
448 FONT *f = NULL;
449 int c;
450
451 fonts_datafile = load_datafile(filename);
452
453 c = datedit_select(datafile_fontname_getter, "Select font:");
454 if (c>=0) {
455 names[0] = datafile_fontname_getter(c, NULL);
456 f = load_font(filename, NULL, (void*)names);
457 }
458
459 unload_datafile(fonts_datafile);
460 fonts_datafile = NULL;
461
462 return f;
463 }
464
465 /* imports a font from an external file (handles various formats) */
grab_font(int type,AL_CONST char * filename,DATAFILE_PROPERTY ** prop,int depth)466 static DATAFILE *grab_font(int type, AL_CONST char *filename, DATAFILE_PROPERTY **prop, int depth)
467 {
468 PACKFILE *f;
469 FONT *font;
470 int id;
471
472 if (stricmp(get_extension(filename), "dat") == 0) {
473 font = grab_datafile_font(filename);
474 }
475 else {
476 font = load_font(filename, NULL, NULL);
477 }
478
479 /* Safe copyright message for GRX fonts */
480 if (stricmp(get_extension(filename), "fnt") == 0) {
481 f = pack_fopen(filename, F_READ);
482 if (!f)
483 return NULL;
484
485 id = pack_igetl(f);
486 pack_fclose(f);
487
488 if (font && id == FONTMAGIC) {
489 /* GRX font; safe copyright message? */
490 import_grx_message(filename);
491 }
492 }
493 return datedit_construct(type, font, 0, prop);
494 }
495
496
497
498 /* helper for save_font, below */
save_mono_font(FONT * f,PACKFILE * pack)499 static int save_mono_font(FONT* f, PACKFILE* pack)
500 {
501 FONT_MONO_DATA* mf = f->data;
502 int i = 0;
503
504 *allegro_errno = 0;
505
506 /* count number of ranges */
507 while(mf) {
508 i++;
509 mf = mf->next;
510 }
511 pack_mputw(i, pack);
512
513 mf = f->data;
514
515 while(mf) {
516
517 /* mono, begin, end-1 */
518 pack_putc(1, pack);
519 pack_mputl(mf->begin, pack);
520 pack_mputl(mf->end - 1, pack);
521
522 for(i = mf->begin; i < mf->end; i++) {
523 FONT_GLYPH* g = mf->glyphs[i - mf->begin];
524
525 pack_mputw(g->w, pack);
526 pack_mputw(g->h, pack);
527
528 pack_fwrite(g->dat, ((g->w + 7) / 8) * g->h, pack);
529 }
530
531 mf = mf->next;
532
533 }
534
535 if (*allegro_errno)
536 return FALSE;
537 else
538 return TRUE;
539 }
540
541
542
543 /* helper for save_font, below */
save_color_font(FONT * f,PACKFILE * pack)544 static int save_color_font(FONT* f, PACKFILE* pack)
545 {
546 FONT_COLOR_DATA* cf = f->data;
547 int i = 0;
548 int depth;
549
550 *allegro_errno = 0;
551
552 /* count number of ranges */
553 while(cf) {
554 i++;
555 cf = cf->next;
556 }
557 pack_mputw(i, pack);
558
559 cf = f->data;
560
561 while(cf) {
562
563 /* Get font color depth */
564 depth = bitmap_color_depth(cf->bitmaps[0]);
565
566 /* Compatibility with older versions: depth=0 means 8 bit */
567 if (depth == 8)
568 depth = 0;
569
570 /* color, begin, end-1 */
571 pack_putc(depth, pack);
572 pack_mputl(cf->begin, pack);
573 pack_mputl(cf->end - 1, pack);
574
575 /* Save pixmap data */
576 for(i = cf->begin; i < cf->end; i++) {
577 BITMAP* glyph = cf->bitmaps[i - cf->begin];
578 int x, y, c, r, g, b, a;
579 uint16_t *p16;
580 uint8_t *p24;
581 uint32_t *p32;
582
583 pack_mputw(glyph->w, pack);
584 pack_mputw(glyph->h, pack);
585
586 switch (depth) {
587
588 case 0:
589 /* 256 colors */
590 for (y=0; y<glyph->h; y++)
591 for (x=0; x<glyph->w; x++)
592 pack_putc(glyph->line[y][x], pack);
593 break;
594
595 case 15:
596 case 16:
597 /* hicolor */
598 for (y=0; y<glyph->h; y++) {
599 p16 = (uint16_t *)glyph->line[y];
600
601 for (x=0; x<glyph->w; x++) {
602 c = p16[x];
603 r = getr_depth(depth, c);
604 g = getg_depth(depth, c);
605 b = getb_depth(depth, c);
606 c = ((r<<8)&0xF800) | ((g<<3)&0x7E0) | ((b>>3)&0x1F);
607 pack_iputw(c, pack);
608 }
609 }
610 break;
611
612 case 24:
613 /* 24 bit truecolor */
614 for (y=0; y<glyph->h; y++) {
615 p24 = (unsigned char *)glyph->line[y];
616
617 for (x=0; x<glyph->w; x++) {
618 c = READ3BYTES(p24);
619 r = getr24(c);
620 g = getg24(c);
621 b = getb24(c);
622 pack_putc(r, pack);
623 pack_putc(g, pack);
624 pack_putc(b, pack);
625 p24 += 3;
626 }
627 }
628 break;
629
630 case 32:
631 /* 32 bit truecolor */
632 for (y=0; y<glyph->h; y++) {
633 p32 = (uint32_t *)glyph->line[y];
634
635 for (x=0; x<glyph->w; x++) {
636 c = p32[x];
637 r = getr32(c);
638 g = getg32(c);
639 b = getb32(c);
640 pack_putc(r, pack);
641 pack_putc(g, pack);
642 pack_putc(b, pack);
643 }
644 }
645 break;
646
647 case -32:
648 /* 32 bit truecolor with alpha channel */
649 for (y=0; y<glyph->h; y++) {
650 p32 = (uint32_t *)glyph->line[y];
651
652 for (x=0; x<glyph->w; x++) {
653 c = p32[x];
654 r = getr32(c);
655 g = getg32(c);
656 b = getb32(c);
657 a = geta32(c);
658 pack_putc(r, pack);
659 pack_putc(g, pack);
660 pack_putc(b, pack);
661 pack_putc(a, pack);
662 }
663 }
664 break;
665 }
666
667 }
668
669 cf = cf->next;
670
671 }
672
673 if (*allegro_errno)
674 return FALSE;
675 else
676 return TRUE;
677 }
678
679
680
681 /* saves a font into a datafile */
save_font(DATAFILE * dat,AL_CONST int * fixed_prop,int pack,int pack_kids,int strip,int sort,int verbose,int extra,PACKFILE * f)682 static int save_font(DATAFILE *dat, AL_CONST int *fixed_prop, int pack, int pack_kids, int strip, int sort, int verbose, int extra, PACKFILE *f)
683 {
684 FONT* font = dat->dat;
685
686 pack_mputw(0, f);
687
688 if (is_mono_font(font))
689 return save_mono_font(font, f);
690 else
691 return save_color_font(font, f);
692 }
693
694
695
696 /* for the font viewer/editor */
697 static FONT *the_font;
698
699 static char char_string[8] = "0x0020";
700
701 static char *range_getter(int index, int *list_size);
702 static int import_proc(int msg, DIALOG *d, int c);
703 static int delete_proc(int msg, DIALOG *d, int c);
704 static int font_view_proc(int msg, DIALOG *d, int c);
705
706
707
708 static DIALOG char_dlg[] =
709 {
710 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
711 { d_shadow_box_proc, 0, 0, 225, 73, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
712 { d_text_proc, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, "Base character:", NULL, NULL },
713 { d_edit_proc, 144, 16, 56, 8, 0, 0, 0, 0, 6, 0, char_string, NULL, NULL },
714 { d_button_proc, 72, 44, 81, 17, 0, 0, 13, D_EXIT, 0, 0, "OK", NULL, NULL },
715 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
716 };
717
718
719
720 static DIALOG view_font_dlg[] =
721 {
722 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
723 { d_clear_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
724 { font_view_proc, 0, 100, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL },
725 { d_list_proc, 0, 0, 161, 100, 0, 0, 0, D_EXIT, 0, 0, range_getter, NULL, NULL },
726 { import_proc, 180, 8, 113, 17, 0, 0, 'i', D_EXIT, 0, 0, "&Import Range", NULL, NULL },
727 { delete_proc, 180, 40, 113, 17, 0, 0, 'd', D_EXIT, 0, 0, "&Delete Range", NULL, NULL },
728 { d_button_proc, 180, 72, 113, 17, 0, 0, 27, D_EXIT, 0, 0, "Exit", NULL, NULL },
729 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
730 };
731
732
733 #define VIEWER 1
734 #define RANGE_LIST 2
735
736
737
738 /* dialog callback for retrieving information about the font range list */
range_getter(int index,int * list_size)739 static char *range_getter(int index, int *list_size)
740 {
741 static char buf[64];
742 FONT* f = the_font;
743
744 if(index < 0) {
745 if(!list_size) return 0;
746
747 *list_size = get_font_ranges(f);
748 if (*list_size < 0)
749 *list_size = 0;
750
751 return 0;
752 }
753
754 sprintf(buf, "%04X-%04X, color", get_font_range_begin(f, index), get_font_range_end(f, index));
755
756 return buf;
757 }
758
759
760
761 /* imports a new font range */
import_proc(int msg,DIALOG * d,int c)762 static int import_proc(int msg, DIALOG *d, int c)
763 {
764 char name[80*6]; /* 80 chars * max UTF8 char width */
765 int ret = d_button_proc(msg, d, c);
766 DATAFILE *dat;
767 FONT *fnt, *f;
768 int base;
769 int i;
770
771 if (ret & D_CLOSE) {
772 #define EXT_LIST "bmp;fnt;lbm;pcx;tga"
773
774 strcpy(name, grabber_import_file);
775 *get_filename(name) = 0;
776
777 if (file_select_ex("Import range (" EXT_LIST ")", name, EXT_LIST, sizeof(name), 0, 0)) {
778 fix_filename_case(name);
779 strcpy(grabber_import_file, name);
780
781 grabber_busy_mouse(TRUE);
782 dat = grab_font(DAT_FONT, name, NULL, -1);
783 grabber_busy_mouse(FALSE);
784
785 if (!dat) {
786 datedit_error("Error importing %s", name);
787 }
788 else {
789 int import_begin, import_end;
790
791 fnt = dat->dat;
792
793 centre_dialog(char_dlg);
794 set_dialog_color(char_dlg, gui_fg_color, gui_bg_color);
795 do_dialog(char_dlg, 2);
796
797 base = strtol(char_string, NULL, 0);
798
799 if(is_mono_font(fnt)) {
800 FONT_MONO_DATA* mf = fnt->data;
801 import_end = (mf->end += (base - mf->begin));
802 import_begin = mf->begin = base;
803 } else {
804 FONT_COLOR_DATA* cf = fnt->data;
805 import_end = (cf->end += (base - cf->begin));
806 import_begin = cf->begin = base;
807 }
808
809 f = the_font;
810
811 if(is_mono_font(fnt)) {
812 FONT_MONO_DATA* mf = f->data;
813 while(mf) {
814 if(mf->end > import_begin && mf->begin < import_end) {
815 alert("Warning, data overlaps with an", "existing range. This almost", "certainly isn't what you want", "Silly me", NULL, 13, 0);
816 break;
817 }
818
819 mf = mf->next;
820 }
821 }
822
823 if(!is_compatible_font(f, fnt)) {
824 upgrade_to_color(f);
825 upgrade_to_color(fnt);
826 }
827
828 f = the_font;
829 i = 0;
830
831 if(is_mono_font(f)) {
832 FONT_MONO_DATA* mf = f->data, * mf2 = fnt->data;
833
834 if(mf->begin > import_begin) {
835 mf2->next = mf;
836 f->data = mf2;
837 } else {
838 i++;
839 while(mf->next && mf->next->begin < import_begin) {
840 mf = mf->next;
841 i++;
842 }
843 mf2->next = mf->next;
844 mf->next = mf2;
845 }
846 } else {
847 FONT_COLOR_DATA* cf = f->data, * cf2 = fnt->data;
848
849 if(cf->begin > import_begin) {
850 cf2->next = cf;
851 f->data = cf2;
852 } else {
853 i++;
854 while(cf->next && cf->next->begin < import_begin) {
855 cf = cf->next;
856 i++;
857 }
858 cf2->next = cf->next;
859 cf->next = cf2;
860 }
861 }
862
863 view_font_dlg[RANGE_LIST].d1 = i;
864
865 object_message(view_font_dlg+VIEWER, MSG_START, 0);
866 object_message(view_font_dlg+RANGE_LIST, MSG_START, 0);
867
868 grabber_modified(TRUE);
869 }
870 }
871
872 return D_REDRAW;
873 }
874
875 return ret;
876 }
877
878
879
880 /* deletes a font range */
delete_proc(int msg,DIALOG * d,int c)881 static int delete_proc(int msg, DIALOG *d, int c)
882 {
883 int ret = d_button_proc(msg, d, c);
884 FONT *fnt;
885 int i;
886
887 if (ret & D_CLOSE) {
888 fnt = the_font;
889
890 if(is_mono_font(fnt)) {
891
892 FONT_MONO_DATA* mf = fnt->data, * mf_prev = 0;
893
894 if(!mf->next) {
895 alert("Deletion not possible:", "fonts must always have at", "least one character range", "Sorry", NULL, 13, 0);
896 return D_O_K;
897 }
898
899 i = view_font_dlg[RANGE_LIST].d1;
900 while(i--) {
901 mf_prev = mf;
902 mf = mf->next;
903 }
904
905 if(mf_prev) mf_prev->next = mf->next;
906 else fnt->data = mf->next;
907
908 for(i = mf->begin; i < mf->end; i++) free(mf->glyphs[i - mf->begin]);
909 free(mf->glyphs);
910 free(mf);
911
912 } else {
913
914 FONT_COLOR_DATA* cf = fnt->data, * cf_prev = 0;
915
916 if(!cf->next) {
917 alert("Deletion not possible:", "fonts must always have at", "least one character range", "Sorry", NULL, 13, 0);
918 return D_O_K;
919 }
920
921 i = view_font_dlg[RANGE_LIST].d1;
922 while(i--) {
923 cf_prev = cf;
924 cf = cf->next;
925 }
926
927 if(cf_prev) cf_prev->next = cf->next;
928 else fnt->data = cf->next;
929
930 for(i = cf->begin; i < cf->end; i++) destroy_bitmap(cf->bitmaps[i - cf->begin]);
931 free(cf->bitmaps);
932 free(cf);
933
934 }
935
936 object_message(view_font_dlg+VIEWER, MSG_START, 0);
937 object_message(view_font_dlg+RANGE_LIST, MSG_START, 0);
938
939 grabber_modified(TRUE);
940
941 return D_REDRAW;
942 }
943
944 return ret;
945 }
946
947
948
949 /* displays the font contents */
font_view_proc(int msg,DIALOG * d,int c)950 static int font_view_proc(int msg, DIALOG *d, int c)
951 {
952 BITMAP** bits = 0;
953 FONT_GLYPH** gl = 0;
954 FONT *fnt;
955 int x, y, w, h, i;
956 int font_h;
957 int begin, end;
958
959 switch (msg) {
960
961 case MSG_START:
962 if (!d->dp)
963 d->dp = create_bitmap(d->w, d->h);
964 d->dp2 = NULL;
965 d->d1 = 0;
966 d->d2 = 0;
967 break;
968
969 case MSG_END:
970 destroy_bitmap(d->dp);
971 d->dp = NULL;
972 break;
973
974 case MSG_DRAW:
975 clear_to_color(d->dp, gui_mg_color);
976
977 fnt = the_font;
978 i = view_font_dlg[RANGE_LIST].d1;
979
980 if(is_mono_font(fnt)) {
981
982 FONT_MONO_DATA* mf = fnt->data;
983 while(i--) mf = mf->next;
984
985 gl = mf->glyphs;
986 begin = mf->begin;
987 end = mf->end;
988
989 } else {
990
991 FONT_COLOR_DATA* cf = fnt->data;
992 while(i--) cf = cf->next;
993
994 bits = cf->bitmaps;
995 begin = cf->begin;
996 end = cf->end;
997
998 }
999
1000 font_h = text_height(fnt);
1001 y = d->d1 + 8;
1002
1003 for (i = begin; i < end; i++) {
1004 if (gl) {
1005 w = gl[i - begin]->w;
1006 h = gl[i - begin]->h;
1007 }
1008 else {
1009 w = bits[i - begin]->w;
1010 h = bits[i - begin]->h;
1011 }
1012
1013 textprintf_ex(d->dp, font, 32, y+font_h/2-4, gui_fg_color, gui_mg_color, "U+%04X %3dx%-3d %c", i, w, h, i);
1014 textprintf_ex(d->dp, fnt, 200, y, (gl ? gui_fg_color : -1), makecol(0xC0, 0xC0, 0xC0), "%c", i);
1015
1016 y += font_h * 3/2;
1017 }
1018
1019 if (d->flags & D_GOTFOCUS) {
1020 for (i=0; i<d->w; i+=2) {
1021 putpixel(d->dp, i, 0, gui_fg_color);
1022 putpixel(d->dp, i+1, 0, gui_bg_color);
1023 putpixel(d->dp, i, d->h-1, gui_bg_color);
1024 putpixel(d->dp, i+1, d->h-1, gui_fg_color);
1025 }
1026 for (i=1; i<d->h-1; i+=2) {
1027 putpixel(d->dp, 0, i, gui_bg_color);
1028 putpixel(d->dp, 0, i+1, gui_fg_color);
1029 putpixel(d->dp, d->w-1, i, gui_fg_color);
1030 putpixel(d->dp, d->w-1, i+1, gui_bg_color);
1031 }
1032 }
1033
1034 blit(d->dp, screen, 0, 0, d->x, d->y, d->w, d->h);
1035
1036 d->d2 = y - d->d1;
1037 d->dp2 = fnt;
1038 break;
1039
1040 case MSG_WANTFOCUS:
1041 return D_WANTFOCUS;
1042
1043 case MSG_CHAR:
1044 switch (c >> 8) {
1045
1046 case KEY_UP:
1047 d->d1 += 8;
1048 break;
1049
1050 case KEY_DOWN:
1051 d->d1 -= 8;
1052 break;
1053
1054 case KEY_PGUP:
1055 d->d1 += d->h*2/3;
1056 break;
1057
1058 case KEY_PGDN:
1059 d->d1 -= d->h*2/3;
1060 break;
1061
1062 case KEY_HOME:
1063 d->d1 = 0;
1064 break;
1065
1066 case KEY_END:
1067 d->d1 = -d->d2 + d->h;
1068 break;
1069
1070 default:
1071 return D_O_K;
1072 }
1073
1074 if (d->d1 < -d->d2 + d->h)
1075 d->d1 = -d->d2 + d->h;
1076
1077 if (d->d1 > 0)
1078 d->d1 = 0;
1079
1080 d->flags |= D_DIRTY;
1081 return D_USED_CHAR;
1082
1083 case MSG_CLICK:
1084 if (mouse_b & 2)
1085 return D_CLOSE;
1086
1087 x = mouse_x;
1088 y = mouse_y;
1089
1090 show_mouse(NULL);
1091
1092 while (mouse_b) {
1093 poll_mouse();
1094
1095 if (mouse_y != y) {
1096 d->d1 += (y - mouse_y);
1097 position_mouse(x, y);
1098
1099 if (d->d1 < -d->d2 + d->h)
1100 d->d1 = -d->d2 + d->h;
1101
1102 if (d->d1 > 0)
1103 d->d1 = 0;
1104
1105 object_message(d, MSG_DRAW, 0);
1106 }
1107 }
1108
1109 show_mouse(screen);
1110 return D_O_K;
1111
1112 case MSG_KEY:
1113 return D_CLOSE;
1114
1115 case MSG_IDLE:
1116 if(d->fg != view_font_dlg[RANGE_LIST].d1) {
1117 d->fg = view_font_dlg[RANGE_LIST].d1;
1118 d->d1 = 0;
1119 object_message(d, MSG_DRAW, 0);
1120 }
1121 }
1122
1123 return D_O_K;
1124 }
1125
1126
1127
1128 /* handles double-clicking on a font in the grabber */
view_font(DATAFILE * dat)1129 static int view_font(DATAFILE *dat)
1130 {
1131 show_mouse(NULL);
1132 clear_to_color(screen, gui_mg_color);
1133
1134 the_font = dat->dat;
1135
1136 view_font_dlg[RANGE_LIST].d1 = 0;
1137 view_font_dlg[RANGE_LIST].d2 = 0;
1138
1139 view_font_dlg[VIEWER].w = SCREEN_W;
1140 view_font_dlg[VIEWER].h = SCREEN_H - view_font_dlg[VIEWER].y;
1141
1142 set_dialog_color(view_font_dlg, gui_fg_color, gui_bg_color);
1143
1144 view_font_dlg[0].bg = gui_mg_color;
1145
1146 do_dialog(view_font_dlg, VIEWER);
1147
1148 dat->dat = the_font;
1149
1150 show_mouse(screen);
1151 return D_REDRAW;
1152 }
1153
1154
1155
1156 /* plugin interface header */
1157 DATEDIT_OBJECT_INFO datfont_info =
1158 {
1159 DAT_FONT,
1160 "Font",
1161 get_font_desc,
1162 makenew_font,
1163 save_font,
1164 plot_font,
1165 view_font,
1166 NULL
1167 };
1168
1169
1170
1171 DATEDIT_GRABBER_INFO datfont_grabber =
1172 {
1173 DAT_FONT,
1174 "txt;fnt;bmp;lbm;pcx;tga;dat",
1175 "txt;bmp;pcx;tga",
1176 grab_font,
1177 export_font,
1178 NULL
1179 };
1180
1181