1 /*
2  *  This file is part of the XForms library package.
3  *
4  *  XForms is free software; you can redistribute it and/or modify it
5  *  under the terms of the GNU Lesser General Public License as
6  *  published by the Free Software Foundation; either version 2.1, or
7  *  (at your option) any later version.
8  *
9  *  XForms is distributed in the hope that it will be useful, but
10  *  WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public License
15  *  along with XForms. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 
19 /*
20  *  This file is part of the XForms library package.
21  *  Copyright (c) 1997-2002  by T.C. Zhao
22  *  All rights reserved.
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include "include/forms.h"
30 #include "flinternal.h"
31 #include "private/pflps.h"
32 #include <stdlib.h>
33 
34 extern char *fl_ul_magic_char;
35 
36 /*
37  * Text stuff. Default fonts follows the XFORM built-in
38  */
39 
40 static const char *fnts[ FL_MAXFONTS ] =
41 {
42     "Helvetica",
43     "Helvetica-Bold",
44     "Helvetica-Oblique",
45     "Helvetica-BoldOblique",
46     "Courier",
47     "Courier-Bold",
48     "Courier-Oblique",
49     "Courier-BoldOblique",
50     "Times-Roman",
51     "Times-Bold",
52     "Times-Italic",
53     "Times-BoldItalic",
54 
55  /* xforms users charter */
56 
57     "Times-Roman",
58     "Times-Bold",
59     "Times-Italic",
60     "Times-BoldItalic",
61 
62     "Symbol"
63 };
64 
65 
66 /***************************************
67  ***************************************/
68 
69 void
flps_invalidate_font_cache(void)70 flps_invalidate_font_cache( void )
71 {
72     flps->cur_style = flps->cur_size = -1;
73 }
74 
75 
76 /***************************************
77  ***************************************/
78 
79 void
flps_set_font(int style,int size)80 flps_set_font( int style,
81                int size )
82 {
83 
84     if ( style >= FL_SHADOW_STYLE )
85         style %= FL_SHADOW_STYLE;
86 
87     if ( style == flps->cur_style && size == flps->cur_size )
88         return;
89 
90     if ( flps->scale_text )
91         size = 0.5 * ( flps->final_xscale + flps->final_yscale );
92 
93     flps_output( "%d point /%s SetFont\n", size, fnts[ style ] );
94     flps_output( "/H %d point def\n", size );
95 
96     flps->cur_style = style;
97     flps->cur_size = size;
98 }
99 
100 
101 #define has_desc( s )    (    strchr( s, 'g' )    \
102                            || strchr( s, 'j' )    \
103                            || strchr( s, 'q' )    \
104                            || strchr( s, 'y' )    \
105                            || strchr( s, 'p' ) )
106 
107 #define is_desc( c )     (    c == 'g'    \
108                            || c == 'j'    \
109                            || c == 'q'    \
110                            || c == 'y'    \
111                            || c == 'p' )
112 
113 
114 /***************************************
115  ***************************************/
116 
117 static void
do_underline(const char * s,int n)118 do_underline( const char * s,
119               int          n )
120 {
121 
122     flps_output( "/len (%s) SW pop def\n", s );
123 
124     if ( n == -1 )
125     {
126         flps_output( "/ty CP exch pop %d sub def ", 1 + has_desc( s ) * 2 );
127         flps_output( "/tx CP pop len sub def " );
128         flps_output( "tx ty M len tx add ty LT S\n" );
129     }
130     else
131     {
132         char *t = fl_strdup( s );
133 
134         t[ n ] = '\0';
135         flps_output( "/ul (%c) SW pop def\n", s[ n ] );
136         flps_output( "/ty CP exch pop %d sub def ",
137                      1 + is_desc( s [ n ] ) * 2 );
138         flps_output( "/tx CP pop len sub (%s) SW pop add def\n", t );
139         flps_output( "tx ty M ul tx add ty LT S\n" );
140         fl_free( t );
141     }
142 }
143 
144 
145 #define Quote( c )   ( c == '(' || c == ')' || c == '%')
146 
147 
148 /***************************************
149  ***************************************/
150 
151 static char *
ps_quote(char * str)152 ps_quote( char * str )
153 {
154     static char buf[ 1024 ];
155     char *s,
156          *q = buf;
157 
158     for ( s = str; *s; s++ )
159     {
160         if ( Quote( *s ) )
161             *q++ = '\\';
162         *q++ = *s;
163     }
164     *q = '\0';
165 
166     return buf;
167 }
168 
169 
170 /***************************************
171  * This routine is always called by other routines. Once we get here,
172  * the text would always remain within the box specified by
173  * {x,y,w,h}.
174  ***************************************/
175 
176 static void
flps_drw_text(int align,float x,float y,float w,float h,FL_COLOR c,int style,int size,const char * sstr)177 flps_drw_text( int          align,
178                float        x,
179                float        y,
180                float        w,
181                float        h,
182                FL_COLOR     c,
183                int          style,
184                int          size,
185                const char * sstr )
186 {
187     int ulpos = -1, lnumb;
188     int i;
189     char *lines[ 512 ];
190     char *str;
191     char newlabel[ 255 ],
192          *p;
193     float bw = 2;
194     int halign,
195         valign;
196     int is_vert;
197 
198     flps_color( c );
199     flps_set_font( style, size );
200 
201     str = fl_strdup( sstr );
202 
203     lines[ 0 ] = str;
204 
205     if ( ( is_vert = align & FL_ALIGN_VERT ) )
206     {
207         align &= ~ FL_ALIGN_VERT;
208         flps_output( "gsave %.1f %.1f translate 90 rotate\n", x, y );
209         x = y = 0;
210     }
211 
212     /* this is a hack to get arbitary rotation for image_postscript */
213 
214     if ( flps->rotation )
215     {
216         flps_output( "gsave %.1f %.1f translate %g rotate\n", x, y,
217                      flps->rotation * 0.1 );
218         x = y = 0;
219     }
220 
221     /* split (multi-line)string into lines */
222 
223     for ( i = 0, lnumb = 1; str[ i ] != '\0'; i++ )
224     {
225         if ( str[ i ] == '\n')
226         {
227             str[ i ] = '\0';
228             lines[ lnumb ] = str + i + 1;
229             lnumb++;
230         }
231     }
232 
233     fli_get_hv_align( align, &halign, &valign );
234 
235     /* figure out where the starting point is */
236 
237     switch ( halign )
238     {
239         case FL_ALIGN_CENTER :
240             flps_output( "/x %.1f def ", x + 0.5 * w );
241             break;
242 
243         case FL_ALIGN_LEFT :
244             flps_output( "/x %.1f def ", bw + x );
245             break;
246 
247         case FL_ALIGN_RIGHT :
248             flps_output( "/x %.1f def ", x + w - 1 - bw );
249             break;
250     }
251 
252     switch ( valign )
253     {
254         case FL_ALIGN_TOP :
255             flps_output( "/y %.1f H sub def\n", y + h - bw );
256             break;
257 
258         case FL_ALIGN_BOTTOM :
259             flps_output( "/y %.1f %.1f H mul add def\n",
260                          y + bw, lnumb - 0.9 );
261             break;
262 
263         case FL_ALIGN_CENTER :
264             flps_output( "/y %.1f %.1f H mul add def\n",
265                          y + 0.5 * h, 0.5 * lnumb - 0.9 );
266             break;
267     }
268 
269     for ( i = 0; i < lnumb; i++ )
270     {
271         /* check if have underline request */
272 
273         if ( ( p = strchr( lines[ i ], *fl_ul_magic_char ) ) )
274         {
275             char *q;
276 
277             ulpos = p - lines[ i ];
278             q = newlabel;
279             p = lines[ i ];
280             for ( ;  *p; p++ )
281                 if ( *p != *fl_ul_magic_char )
282                     *q++ = *p;
283             *q = 0;
284             lines[ i ] = newlabel;
285         }
286 
287         flps_output( "x y M " );
288 
289         switch ( halign )
290         {
291             case FL_ALIGN_CENTER :
292                 flps_output( "(%s) Cshow\n", ps_quote( lines[ i ] ) );
293                 break;
294 
295             case FL_ALIGN_LEFT :
296                 flps_output( "(%s) Lshow\n", ps_quote( lines[ i ] ) );
297                 break;
298 
299             case FL_ALIGN_RIGHT :
300                 flps_output( "(%s) Rshow\n", ps_quote( lines[ i ] ) );
301                 break;
302         }
303 
304         if ( ulpos >= 0 )
305             do_underline( lines[ i ], ulpos - 1 );
306 
307         ulpos = -1;
308 
309         if ( i != lnumb - 1 )
310             flps_output( "/y y H sub def\n" );
311     }
312 
313     fl_free( str );
314 
315     if ( is_vert || flps->rotation )
316         flps_output( "grestore\n" );
317 }
318 
319 
320 #define D( x, y, c )   flps_drw_text( align, x, y, w, h, c, style, size, str )
321 
322 
323 /***************************************
324  ***************************************/
325 
326 void
flps_draw_text(int align,int x,int y,int w,int h,FL_COLOR col,int style,int size,const char * istr)327 flps_draw_text( int         align,
328                 int         x,
329                 int         y,
330                 int         w,
331                 int         h,
332                 FL_COLOR    col,
333                 int         style,
334                 int         size,
335                 const char * istr )
336 {
337     int special = FL_INVALID_STYLE;
338     const char *str = istr;
339 
340     if ( ! str || ! *str )
341         return;
342 
343     if ( *str == '@' && str[ 1 ] != '@' )
344     {
345         if ( w < 3 || h < 3 )
346         {
347             w = h = size + 4;
348             x -= w / 2;
349             y -= h / 2;
350         }
351 
352         flps_draw_symbol( str, x, y, w, h, col );
353         return;
354     }
355 
356     str += str[ 1 ] == '@';
357 
358     if ( special_style( style ) )
359     {
360         special = ( style / FL_SHADOW_STYLE ) * FL_SHADOW_STYLE;
361         style %= FL_SHADOW_STYLE;
362     }
363 
364     if ( special == FL_SHADOW_STYLE )
365         D( x + 2, y - 2, FL_BOTTOM_BCOL );
366     else if ( special == FL_ENGRAVED_STYLE )
367     {
368         D( x - 1, y,     FL_RIGHT_BCOL );
369         D( x, y + 1,     FL_RIGHT_BCOL );
370         D( x - 1, y + 1, FL_RIGHT_BCOL );
371         D( x + 1, y,     FL_LEFT_BCOL );
372         D( x,     y - 1, FL_LEFT_BCOL );
373         D( x + 1, y - 1, FL_LEFT_BCOL );
374     }
375     else if ( special == FL_EMBOSSED_STYLE )
376     {
377         D( x - 1, y,     FL_TOP_BCOL );
378         D( x,     y + 1, FL_TOP_BCOL );
379         D( x - 1, y + 1, FL_TOP_BCOL );
380         D( x + 1, y,     FL_RIGHT_BCOL );
381         D( x,     y - 1, FL_RIGHT_BCOL );
382         D( x + 1, y - 1, FL_RIGHT_BCOL );
383     }
384 
385     flps_drw_text( align, x, y, w, h, col, style, size, str );
386 }
387 
388 
389 /***************************************
390  ***************************************/
391 
392 void
flps_draw_text_beside(int align,int x,int y,int w,int h,FL_COLOR col,int style,int size,const char * str)393 flps_draw_text_beside( int          align,
394                        int          x,
395                        int          y,
396                        int          w,
397                        int          h,
398                        FL_COLOR     col,
399                        int          style,
400                        int          size,
401                        const char * str )
402 {
403     if ( ! str || ! *str )
404         return;
405 
406     switch( fl_to_outside_lalign( align ) )
407     {
408         case FL_ALIGN_LEFT :
409             flps_draw_text( FL_ALIGN_RIGHT, x - h, y, h, h, col, style, size,
410                             str );
411             break;
412 
413         case FL_ALIGN_RIGHT :
414             flps_draw_text( FL_ALIGN_LEFT, x + w, y, h, h, col, style, size,
415                             str );
416             break;
417 
418         case FL_ALIGN_TOP :
419             flps_draw_text( FL_ALIGN_BOTTOM, x, y + h, w, h, col, style, size,
420                             str );
421             break;
422 
423         case FL_ALIGN_BOTTOM :
424             flps_draw_text( FL_ALIGN_TOP, x, y - h, w, h, col, style, size,
425                             str );
426             break;
427 
428         case FL_ALIGN_LEFT_BOTTOM :
429             flps_draw_text( FL_ALIGN_LEFT_TOP, x, y - h, w, h, col, style,
430                             size, str );
431             break;
432 
433         case FL_ALIGN_RIGHT_BOTTOM :
434             flps_draw_text( FL_ALIGN_RIGHT_TOP, x, y - h, w, h, col, style,
435                             size, str );
436             break;
437 
438         case FL_ALIGN_LEFT_TOP :
439             flps_draw_text( FL_ALIGN_LEFT_BOTTOM, x, y + h, w, h, col, style,
440                             size, str );
441             break;
442 
443         case FL_ALIGN_RIGHT_TOP :
444             flps_draw_text( FL_ALIGN_RIGHT_BOTTOM, x, y + h, w, h, col, style,
445                             size, str );
446             break;
447 
448         case FL_ALIGN_CENTER :
449             flps_draw_text( FL_ALIGN_CENTER, x, y, w, h, col, style, size,
450                             str );
451             break;
452 
453         default :
454             flps_draw_text( FL_ALIGN_TOP, x, y - h, w, h, col, style, size,
455                             str );
456             break;
457     }
458 }
459 
460 
461 /*
462  * Local variables:
463  * tab-width: 4
464  * indent-tabs-mode: nil
465  * End:
466  */
467