2 * Grace - GRaphing, Advanced Computation and Exploration of data
4 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
6 * Copyright (c) 1996-2002 Grace Development Team
8 * Maintained by Evgeny Stambulchik
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 * Parsing escape sequences in composite strings
37 #include "core_utils.h"
40 int init_font_db(Canvas
*canvas
)
43 char buf
[GR_MAXPATHLEN
], abuf
[GR_MAXPATHLEN
], fbuf
[GR_MAXPATHLEN
], *bufp
;
45 Grace
*grace
= (Grace
*) canvas_get_udata(canvas
);
47 /* Set default encoding */
48 bufp
= grace_path2(grace
, "fonts/enc/", T1_DEFAULT_ENCODING_FILE
);
49 if (canvas_set_encoding(canvas
, bufp
) != RETURN_SUCCESS
) {
50 bufp
= grace_path2(grace
, "fonts/enc/", T1_FALLBACK_ENCODING_FILE
);
51 if (canvas_set_encoding(canvas
, bufp
) != RETURN_SUCCESS
) {
52 return RETURN_FAILURE
;
56 /* Open & process the font database */
57 fd
= grace_openr(grace
, "fonts/FontDataBase", SOURCE_DISK
);
59 return RETURN_FAILURE
;
62 /* the first line - number of fonts */
63 grace_fgets(buf
, GR_MAXPATHLEN
- 1, fd
);
64 if (sscanf(buf
, "%d", &nfonts
) != 1 || nfonts
<= 0) {
66 return RETURN_FAILURE
;
69 for (i
= 0; i
< nfonts
; i
++) {
70 grace_fgets(buf
, GR_MAXPATHLEN
- 1, fd
);
71 if (sscanf(buf
, "%s %*s %s", abuf
, fbuf
) != 2) {
73 return RETURN_FAILURE
;
75 bufp
= grace_path2(grace
, "fonts/type1/", fbuf
);
76 if (canvas_add_font(canvas
, bufp
, abuf
) != RETURN_SUCCESS
) {
78 return RETURN_FAILURE
;
83 return RETURN_SUCCESS
;
86 /* TODO: optimize, e.g. via a hashed array */
87 int fmap_proc(const Canvas
*canvas
, int font_id
)
89 Grace
*grace
= (Grace
*) canvas_get_udata(canvas
);
90 Project
*pr
= project_get_data(grace
->project
);
91 int font
= BAD_FONT_ID
;
94 for (i
= 0; i
< pr
->nfonts
; i
++) {
95 Fontdef
*f
= &pr
->fontmap
[i
];
97 if (f
->id
== font_id
) {
98 font
= canvas_get_font_by_name(canvas
, f
->fontname
);
99 if (font
== BAD_FONT_ID
) {
100 font
= canvas_get_font_by_name(canvas
, f
->fallback
);
103 if (font
== BAD_FONT_ID
) {
105 sprintf(buf
, "Couldn't map font %d to any existing one", f
->id
);
118 static const TextMatrix unit_tm
= UNIT_TM
;
120 static int get_escape_args(const char *s
, char *buf
)
140 static char *expand_macros(const Canvas
*canvas
, const char *s
)
142 Grace
*grace
= (Grace
*) canvas_get_udata(canvas
);
143 char *es
, *macro
, *subst
;
144 int i
, j
, k
, slen
, extra_len
= 0;
151 macro
= xmalloc(slen
*SIZEOF_CHAR
);
158 if (s
[i
] == '\\' && s
[i
+ 1] == '$' &&
159 (k
= get_escape_args(&(s
[i
+ 2]), macro
)) >= 0) {
160 if (!strcmp(macro
, "timestamp")) {
161 subst
= project_get_timestamp(grace
->project
);
163 if (!strcmp(macro
, "filename")) {
164 subst
= project_get_docname(grace
->project
);
166 if (!strcmp(macro
, "filebname")) {
167 subst
= get_docbname(grace
->project
);
171 /* 4 == strlen("\\${}") */
172 extra_len
+= (strlen(subst
) - (4 + k
));
179 es
= xmalloc((slen
+ extra_len
+ 1)*SIZEOF_CHAR
);
187 if (s
[i
] == '\\' && s
[i
+ 1] == '$' &&
188 (k
= get_escape_args(&(s
[i
+ 2]), macro
)) >= 0) {
189 if (!strcmp(macro
, "timestamp")) {
190 subst
= project_get_timestamp(grace
->project
);
192 if (!strcmp(macro
, "filename")) {
193 subst
= project_get_docname(grace
->project
);
195 if (!strcmp(macro
, "filebname")) {
196 subst
= get_docbname(grace
->project
);
200 strcpy(&es
[j
], subst
);
201 i
+= (4 + k
); j
+= strlen(subst
);
214 int csparse_proc(const Canvas
*canvas
, const char *s
, CompositeString
*cstring
)
216 Grace
*grace
= (Grace
*) canvas_get_udata(canvas
);
217 CStringSegment
*cseg
;
219 char *string
, *ss
, *buf
, *acc_buf
;
220 int inside_escape
= FALSE
;
225 int upperset
= FALSE
;
229 int font
= BAD_FONT_ID
, new_font
= font
;
230 int color
= BAD_COLOR
, new_color
= color
;
231 TextMatrix tm
= unit_tm
, tm_new
= tm
;
232 double hshift
= 0.0, new_hshift
= hshift
;
233 double baseline
= 0.0, baseline_old
;
234 double vshift
= baseline
, new_vshift
= vshift
;
235 int underline
= FALSE
, overline
= FALSE
;
236 int new_underline
= underline
, new_overline
= overline
;
237 int kerning
= FALSE
, new_kerning
= kerning
;
238 int direction
= STRING_DIRECTION_LR
, new_direction
= direction
;
239 int advancing
= TEXT_ADVANCING_LR
, new_advancing
= advancing
;
240 int ligatures
= FALSE
, new_ligatures
= ligatures
;
242 int setmark
= MARK_NONE
;
243 int gotomark
= MARK_NONE
, new_gotomark
= gotomark
;
247 string
= expand_macros(canvas
, s
);
249 if (string
== NULL
) {
250 return RETURN_FAILURE
;
253 slen
= strlen(string
);
256 return RETURN_FAILURE
;
259 ss
= xmalloc(slen
+ 1);
260 buf
= xmalloc(slen
+ 1);
261 acc_buf
= xmalloc(slen
+ 1);
262 if (ss
== NULL
|| buf
== NULL
|| acc_buf
== NULL
) {
267 return RETURN_FAILURE
;
273 for (i
= 0; i
<= slen
; i
++) {
276 if (ccode
< 32 && ccode
> 0) {
277 /* skip control codes */
281 inside_escape
= FALSE
;
283 if (isdigit(ccode
)) {
284 new_font
= ccode
- '0';
286 } else if (ccode
== 'd') {
290 new_direction
= STRING_DIRECTION_LR
;
293 new_direction
= STRING_DIRECTION_RL
;
296 new_advancing
= TEXT_ADVANCING_LR
;
299 new_advancing
= TEXT_ADVANCING_RL
;
307 } else if (ccode
== 'F') {
317 new_ligatures
= TRUE
;
320 new_ligatures
= FALSE
;
328 } else if (isoneof(ccode
, "cCsSNBxuUoO+-qQn")) {
331 new_vshift
-= tm_size(&tm_new
)*SUBSCRIPT_SHIFT
;
332 tm_scale(&tm_new
, SSCRIPT_SCALE
);
335 new_vshift
+= tm_size(&tm_new
)*SUPSCRIPT_SHIFT
;
336 tm_scale(&tm_new
, SSCRIPT_SCALE
);
339 scale
= 1.0/tm_size(&tm_new
);
340 tm_scale(&tm_new
, scale
);
341 new_vshift
= baseline
;
344 new_font
= BAD_FONT_ID
;
347 new_font
= get_font_by_name(grace
->project
, "Symbol");
356 new_underline
= TRUE
;
359 new_underline
= FALSE
;
365 new_overline
= FALSE
;
368 tm_scale(&tm_new
, 1.0/ENLARGE_SCALE
);
371 tm_scale(&tm_new
, ENLARGE_SCALE
);
374 tm_slant(&tm_new
, OBLIQUE_FACTOR
);
377 tm_slant(&tm_new
, -OBLIQUE_FACTOR
);
380 new_gotomark
= MARK_CR
;
382 new_vshift
= baseline
;
387 } else if (isoneof(ccode
, "fhvVzZmM#rltTR") &&
388 (j
= get_escape_args(&(string
[i
+ 1]), buf
)) >= 0) {
393 new_font
= BAD_FONT_ID
;
394 } else if (isdigit(buf
[0])) {
395 new_font
= atoi(buf
);
397 new_font
= get_font_by_name(grace
->project
, buf
);
402 new_vshift
= baseline
;
405 new_vshift
+= tm_size(&tm_new
)*val
;
409 baseline_old
= baseline
;
414 baseline
+= tm_size(&tm_new
)*val
;
416 new_vshift
= baseline
;
420 new_hshift
= tm_size(&tm_new
)*val
;
424 scale
= 1.0/tm_size(&tm_new
);
425 tm_scale(&tm_new
, scale
);
428 tm_scale(&tm_new
, scale
);
432 scale
= atof(buf
)/tm_size(&tm_new
);
433 tm_scale(&tm_new
, scale
);
436 tm_rotate(&tm_new
, atof(buf
));
439 tm_slant(&tm_new
, atof(buf
));
445 if (sscanf(buf
, "%lf %lf %lf %lf",
446 &tm_buf
.cxx
, &tm_buf
.cxy
,
447 &tm_buf
.cyx
, &tm_buf
.cyy
) == 4) {
448 tm_product(&tm_new
, &tm_buf
);
453 if (sscanf(buf
, "%lf %lf %lf %lf",
454 &tm_buf
.cxx
, &tm_buf
.cxy
,
455 &tm_buf
.cyx
, &tm_buf
.cyy
) == 4) {
463 new_gotomark
= atoi(buf
);
464 new_vshift
= baseline
;
469 new_color
= BAD_COLOR
;
470 } else if (isdigit(buf
[0])) {
471 new_color
= atof(buf
);
473 new_color
= get_color_by_name(grace
->project
, buf
);
481 for (k
= 0; k
< j
; k
+= 2) {
484 acc_buf
[acc_len
] = strtol(hex
, NULL
, 16);
496 acc_buf
[0] = (ccode
+ (upperset
*0x80)) & 0xff;
501 inside_escape
= TRUE
;
505 acc_buf
[0] = (ccode
+ (upperset
*0x80)) & 0xff;
510 if ((new_font
!= font
) ||
511 (new_color
!= color
) ||
512 (tm_new
.cxx
!= tm
.cxx
) ||
513 (tm_new
.cxy
!= tm
.cxy
) ||
514 (tm_new
.cyx
!= tm
.cyx
) ||
515 (tm_new
.cyy
!= tm
.cyy
) ||
516 (new_hshift
!= 0.0 ) ||
517 (new_vshift
!= vshift
) ||
518 (new_underline
!= underline
) ||
519 (new_overline
!= overline
) ||
520 (new_kerning
!= kerning
) ||
521 (new_direction
!= direction
) ||
522 (new_advancing
!= advancing
) ||
523 (new_ligatures
!= ligatures
) ||
525 (new_gotomark
>= 0 ) ||
528 if (isub
!= 0 || setmark
>= 0) { /* non-empty substring */
530 cseg
= cstring_seg_new(cstring
);
534 cseg
->hshift
= hshift
;
535 cseg
->vshift
= vshift
;
536 cseg
->underline
= underline
;
537 cseg
->overline
= overline
;
538 cseg
->kerning
= kerning
;
539 cseg
->direction
= direction
;
540 cseg
->advancing
= advancing
;
541 cseg
->ligatures
= ligatures
;
542 cseg
->setmark
= setmark
;
544 cseg
->gotomark
= gotomark
;
546 cseg
->s
= xmalloc(isub
*SIZEOF_CHAR
);
547 memcpy(cseg
->s
, ss
, isub
);
557 /* once a substring is manually advanced, all the following
558 * substrings will be advanced as well!
563 underline
= new_underline
;
564 overline
= new_overline
;
565 kerning
= new_kerning
;
566 direction
= new_direction
;
567 advancing
= new_advancing
;
568 ligatures
= new_ligatures
;
569 gotomark
= new_gotomark
;
571 /* once a substring is manually advanced, all the following
572 * substrings will be advanced as well!
574 new_gotomark
= MARK_NONE
;
577 memcpy(&ss
[isub
], acc_buf
, acc_len
*SIZEOF_CHAR
);
586 return RETURN_SUCCESS
;