1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2008 Ales Hvezda
4 * Copyright (C) 1998-2008 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
34 #ifdef HAVE_LIBDMALLOC
41 char *unescape_text_and_overbars (char *text
, PangoAttrList
*attrs
)
43 char *p
, *sp
, *strip_text
;
44 char *overbar_start
= NULL
;
47 /* The unescaped text is alwasys shorter than the original
48 string, so just allocate the same ammount of memory. */
49 sp
= strip_text
= g_malloc (strlen (text
) + 1);
51 for (p
= text
; p
!= NULL
; p
++) {
52 int finish_overbar
= FALSE
;
54 /* If we find an escape character "\", we note it and continue looping */
55 if (!escape
&& *p
== '\\') {
60 if (escape
&& *p
== '_') {
61 /* Overbar start or end sequence */
62 if (overbar_start
!= NULL
) {
63 finish_overbar
= TRUE
;
68 /* just append the character, which may have been escaped */
73 if (overbar_start
!= NULL
&&
74 (finish_overbar
|| *p
== '\0')) {
77 attr
= gschem_pango_attr_overbar_new (TRUE
);
78 attr
->start_index
= overbar_start
- strip_text
;
79 attr
->end_index
= sp
- strip_text
;
80 pango_attr_list_insert (attrs
, attr
);
84 /* end of the string, stop iterating */
93 float calculate_font_size (GSCHEM_TOPLEVEL
*w_current
, TEXT
*text
)
95 TOPLEVEL
*toplevel
= w_current
->toplevel
;
98 /* This is probably the more "theoretically" accurate scale factor: */
99 // font_size_px = SCREENabs(toplevel, text->size * 1000) / 72.0;
100 /* But the magic number used in libgeda/src/o_text_basic.c is 26 mil for a 2 pt font */
101 // font_size_px = SCREENabs (toplevel, 13 * text->size * 1000) / 1000.;
103 /* Scale by a magic number */
104 /* TODO: Define this magic number somewhere */
105 font_size_px
= (float)SCREENabs(toplevel
, text
->size
* 1000) / 72.0 * 1.3;
107 /* Clamp the minimum font-size at 1px */
108 /* TODO: Decide if we should switch to some kind of placeholder,
109 * or just skip drawing these elements at a certain size */
110 if (font_size_px
< 1.0)
117 /*! \todo Finish function documentation!!!
119 * \par Function Description
122 int o_text_get_rendered_bounds (void *user_data
, OBJECT
*o_current
,
123 int *min_x
, int *min_y
,
124 int *max_x
, int *max_y
)
126 GSCHEM_TOPLEVEL
*w_current
= user_data
;
127 TOPLEVEL
*toplevel
= w_current
->toplevel
;
128 PangoFontDescription
*desc
;
136 PangoFontMetrics
*font_metrics
;
137 PangoRectangle logical_rect
;
138 PangoRectangle inked_rect
;
139 PangoContext
*context
;
140 PangoAttrList
*attrs
;
141 int left
, top
, width
, height
;
143 g_return_val_if_fail (o_current
!= NULL
, FALSE
);
144 g_return_val_if_fail (o_current
->text
!= NULL
, FALSE
);
146 if (o_current
->visibility
== INVISIBLE
&&
147 !toplevel
->show_hidden_text
)
150 if (o_current
->text
->disp_string
== NULL
)
153 cr
= gdk_cairo_create (w_current
->drawable
);
154 layout
= pango_cairo_create_layout (cr
);
156 WORLDtoSCREEN(toplevel
, o_current
->text
->x
, o_current
->text
->y
, &sx
, &sy
);
158 font_size_px
= calculate_font_size (w_current
, o_current
->text
);
160 context
= pango_layout_get_context (layout
);
161 // font_string = g_strdup_printf ("Helvetica %fpx\n", font_size_px);
162 font_string
= g_strdup_printf ("Arial %fpx\n", font_size_px
);
163 desc
= pango_font_description_from_string (font_string
);
164 g_free (font_string
);
165 pango_layout_set_font_description (layout
, desc
);
166 font_metrics
= pango_context_get_metrics (context
, desc
, NULL
);
167 pango_font_description_free (desc
);
169 attrs
= pango_attr_list_new ();
170 unescaped
= unescape_text_and_overbars (o_current
->text
->disp_string
, attrs
);
172 pango_layout_set_text (layout
, unescaped
, -1);
175 pango_layout_set_attributes (layout
, attrs
);
176 pango_attr_list_unref (attrs
);
178 pango_layout_get_pixel_extents (layout
, &inked_rect
, &logical_rect
);
180 /*! \bug Here be dragons */
181 /*! \bug Should be using font metrics for vertical alignment */
182 #define Y_LOWER 0 // ?
183 #define Y_MIDDLE ((logical_rect.height - pango_font_metrics_get_descent (font_metrics) / PANGO_SCALE - inked_rect.y) / 2.) // ?
184 #define Y_UPPER (logical_rect.height - pango_font_metrics_get_descent (font_metrics) / PANGO_SCALE - inked_rect.y) // ?
186 #define X_LEFT 0 // ?
187 #define X_MIDDLE -(logical_rect.width / 2.) // ?
188 #define X_RIGHT -logical_rect.width // ?
190 switch (o_current
->text
->alignment
) {
193 fprintf (stderr
, "BUG\n");
194 /* Fall through to LOWER_LEFT case */
195 case LOWER_LEFT
: y
= Y_LOWER
; x
= X_LEFT
; break;
196 case MIDDLE_LEFT
: y
= Y_MIDDLE
; x
= X_LEFT
; break;
197 case UPPER_LEFT
: y
= Y_UPPER
; x
= X_LEFT
; break;
198 case LOWER_MIDDLE
: y
= Y_LOWER
; x
= X_MIDDLE
; break;
199 case MIDDLE_MIDDLE
: y
= Y_MIDDLE
; x
= X_MIDDLE
; break;
200 case UPPER_MIDDLE
: y
= Y_UPPER
; x
= X_MIDDLE
; break;
201 case LOWER_RIGHT
: y
= Y_LOWER
; x
= X_RIGHT
; break;
202 case MIDDLE_RIGHT
: y
= Y_MIDDLE
; x
= X_RIGHT
; break;
203 case UPPER_RIGHT
: y
= Y_UPPER
; x
= X_RIGHT
; break;
213 /* Special case turns upside-down text back upright */
214 if (o_current
->text
->angle
== 180) {
215 x
= -x
- logical_rect
.width
;
216 y
= -y
+ logical_rect
.height
; /*! /bug Might need font metrics instead */
219 if (o_current
->text
->angle
== 90) {
220 left
= y
+ logical_rect
.y
- logical_rect
.height
+
221 pango_font_metrics_get_descent (font_metrics
) / PANGO_SCALE
;
222 top
= -x
- logical_rect
.x
- logical_rect
.width
;
223 width
= logical_rect
.height
;
224 height
= logical_rect
.width
;
225 } else if (o_current
->text
->angle
== 270) {
226 left
= -y
- logical_rect
.y
-
227 pango_font_metrics_get_descent (font_metrics
) / PANGO_SCALE
;
228 top
= x
+ logical_rect
.x
;
229 width
= logical_rect
.height
;
230 height
= logical_rect
.width
;
233 left
= x
+ logical_rect
.x
;
234 top
= y
+ logical_rect
.y
- logical_rect
.height
+
235 pango_font_metrics_get_descent (font_metrics
) / PANGO_SCALE
;
236 width
= logical_rect
.width
;
237 height
= logical_rect
.height
;
240 pango_font_metrics_unref (font_metrics
);
242 SCREENtoWORLD (toplevel
, sx
+ left
, sy
+ top
+ height
, min_x
, min_y
);
243 SCREENtoWORLD (toplevel
, sx
+ left
+ width
, sy
+ top
, max_x
, max_y
);
245 g_object_unref (layout
);
252 /*! \todo Finish function documentation!!!
254 * \par Function Description
257 void o_text_draw_lowlevel(GSCHEM_TOPLEVEL
*w_current
, OBJECT
*o_current
)
259 TOPLEVEL
*toplevel
= w_current
->toplevel
;
260 PangoFontDescription
*desc
;
263 cairo_t
*cr
= w_current
->cr
;
267 PangoFontMetrics
*font_metrics
;
268 PangoRectangle logical_rect
;
269 PangoRectangle inked_rect
;
270 PangoContext
*context
;
271 PangoAttrList
*attrs
;
278 g_return_if_fail (o_current
!= NULL
);
279 g_return_if_fail (o_current
->text
!= NULL
);
281 if (o_current
->visibility
== INVISIBLE
&&
282 !toplevel
->show_hidden_text
)
285 if (o_current
->text
->disp_string
== NULL
) return;
286 WORLDtoSCREEN(toplevel
, o_current
->text
->x
, o_current
->text
->y
, &sx
, &sy
);
288 font_size_px
= calculate_font_size (w_current
, o_current
->text
);
290 context
= pango_layout_get_context (w_current
->pl
);
291 // pango_cairo_context_set_resolution (context, double dpi);
292 // font_string = g_strdup_printf ("Helvetica %fpx\n", font_size_px);
293 font_string
= g_strdup_printf ("Arial %fpx\n", font_size_px
);
294 desc
= pango_font_description_from_string (font_string
);
295 g_free (font_string
);
296 pango_layout_set_font_description (w_current
->pl
, desc
);
297 font_metrics
= pango_context_get_metrics (context
, desc
, NULL
);
298 pango_font_description_free (desc
);
300 attrs
= pango_attr_list_new ();
301 unescaped
= unescape_text_and_overbars (o_current
->text
->disp_string
, attrs
);
303 pango_layout_set_text (w_current
->pl
, unescaped
, -1);
306 pango_layout_set_attributes (w_current
->pl
, attrs
);
307 pango_attr_list_unref (attrs
);
309 pango_layout_get_pixel_extents (w_current
->pl
, &inked_rect
, &logical_rect
);
311 /*! \bug Here be dragons */
312 /*! \bug Should be using font metrics for vertical alignment */
313 #define Y_LOWER 0 // ?
315 /* Non gschem back-compat centering of multi-line text. Uses inked extents to cheat at a nice center position */
316 //#define Y_MIDDLE ((pango_font_metrics_get_ascent (font_metrics) / PANGO_SCALE - inked_rect.y) / 2.) // ?
317 //#define Y_UPPER (pango_font_metrics_get_ascent (font_metrics) / PANGO_SCALE - inked_rect.y) // ?
319 /* Gschem back-compat centering of multi-line text. Uses inked extents to cheat at a nice center position */
320 #define Y_MIDDLE ((logical_rect.height - pango_font_metrics_get_descent (font_metrics) / PANGO_SCALE - inked_rect.y) / 2.) // ?
321 #define Y_UPPER (logical_rect.height - pango_font_metrics_get_descent (font_metrics) / PANGO_SCALE - inked_rect.y) // ?
323 /* Centering on font metrics. Is possibly not gschem back-compat centering multi-line text */
324 //#define Y_MIDDLE (pango_font_metrics_get_ascent (font_metrics) / PANGO_SCALE / 2.) // ?
325 //#define Y_UPPER (pango_font_metrics_get_ascent (font_metrics) / PANGO_SCALE) // ?
327 #define X_LEFT 0 // ?
328 #define X_MIDDLE -(logical_rect.width / 2.) // ?
329 #define X_RIGHT -logical_rect.width // ?
331 switch (o_current
->text
->alignment
) {
334 fprintf (stderr
, "BUG\n");
335 /* Fall through to LOWER_LEFT case */
336 case LOWER_LEFT
: y
= Y_LOWER
; x
= X_LEFT
; break;
337 case MIDDLE_LEFT
: y
= Y_MIDDLE
; x
= X_LEFT
; break;
338 case UPPER_LEFT
: y
= Y_UPPER
; x
= X_LEFT
; break;
339 case LOWER_MIDDLE
: y
= Y_LOWER
; x
= X_MIDDLE
; break;
340 case MIDDLE_MIDDLE
: y
= Y_MIDDLE
; x
= X_MIDDLE
; break;
341 case UPPER_MIDDLE
: y
= Y_UPPER
; x
= X_MIDDLE
; break;
342 case LOWER_RIGHT
: y
= Y_LOWER
; x
= X_RIGHT
; break;
343 case MIDDLE_RIGHT
: y
= Y_MIDDLE
; x
= X_RIGHT
; break;
344 case UPPER_RIGHT
: y
= Y_UPPER
; x
= X_RIGHT
; break;
349 cairo_translate (cr
, sx
, sy
);
351 /* Special case turns upside-down text back upright */
352 if (o_current
->text
->angle
== 180) {
353 x
= -x
- logical_rect
.width
;
356 cairo_rotate (cr
, - M_PI
* o_current
->text
->angle
/ 180.);
361 /* Pick an arbitrary size constant for the construction lines */
362 // px = SCREENabs (toplevel, 2 * 10); /* Includes * 10 factor for precision */
364 /* Threshold the drawing to be above a certain size */
370 /* baseline, descent, ascent, height */
371 cairo_set_line_width (cr
, 2 * px
);
373 cairo_set_dash (cr
, &dashlength
, 1, 0);
375 /* Underline logical text rect in green, y coord is as gschem text origin */
376 cairo_set_source_rgba (cr
, 0, 0.6, 0, 0.5);
377 cairo_move_to (cr
, x
+ logical_rect
.x
, y
);
378 cairo_rel_line_to (cr
, logical_rect
.width
, 0);
381 /* Underline descent height in red */
382 cairo_set_source_rgba (cr
, 1, 0, 0, 1);
383 cairo_move_to (cr
, x
+ logical_rect
.x
, y
+ pango_font_metrics_get_descent (font_metrics
)/ PANGO_SCALE
);
384 cairo_rel_line_to (cr
, logical_rect
.width
, 0);
387 /* Overbar ascent height in yellow */
388 cairo_set_source_rgba (cr
, 1, 1, 0, 1);
389 cairo_move_to (cr
, x
+ logical_rect
.x
, y
- pango_font_metrics_get_ascent (font_metrics
) / PANGO_SCALE
);
390 cairo_rel_line_to (cr
, logical_rect
.width
, 0);
393 /* Pango doesn't seem to have this */
394 // cairo_move_to (cr, x + logical_rect.x, y - font_extents.height);
395 // cairo_rel_line_to (cr, logical_rect.width, 0);
398 /* extents: width & height in blue*/
399 cairo_set_source_rgba (cr
, 0, 0, 0.75, 0.5);
400 cairo_set_line_width (cr
, px
);
402 cairo_set_dash (cr
, &dashlength
, 1, 0);
403 cairo_rectangle (cr
, x
+ logical_rect
.x
, y
- logical_rect
.y
+ pango_font_metrics_get_descent (font_metrics
) / PANGO_SCALE
,
404 logical_rect
.width
, - logical_rect
.height
);
410 gschem_cairo_set_source_color (cr
,
411 (toplevel
->override_color
!= -1) ?
412 x_color_lookup (toplevel
->override_color
) :
413 x_color_lookup (o_current
->color
));
415 // cairo_move_to (cr, x, y - logical_rect.height - logical_rect.y);
416 // cairo_move_to (cr, x, y - pango_font_metrics_get_ascent (font_metrics) / PANGO_SCALE);
417 cairo_move_to (cr
, x
, y
- logical_rect
.height
+ pango_font_metrics_get_descent (font_metrics
) / PANGO_SCALE
);
419 gschem_pango_show_layout (cr
, w_current
->pl
);
423 /* show layout origin point in black */
424 cairo_arc (cr
, x
, y
- pango_font_metrics_get_ascent (font_metrics
) / PANGO_SCALE
, 3 * px
, 0, 2 * M_PI
);
425 cairo_set_source_rgba (cr
, 0.0, 0, 0, 0.5);
429 cairo_set_dash (cr
, NULL
, 0, 0);
430 cairo_set_line_width (cr
, 2 * px
);
431 cairo_set_source_rgba (cr
, 0, 0, 0.75, 0.5);
432 cairo_move_to (cr
, x
, y
);
433 cairo_rel_line_to (cr
, logical_rect
.x
, -logical_rect
.y
);
436 /* text's advance in blue */
437 cairo_set_source_rgba (cr
, 0, 0, 0.75, 0.5);
438 cairo_arc (cr
, x
+ logical_rect
.x
+ logical_rect
.width
, y
- logical_rect
.y
,
439 3 * px
, 0, 2 * M_PI
);
442 /* reference point in red */
443 cairo_arc (cr
, x
, y
, 3 * px
, 0, 2 * M_PI
);
444 cairo_set_source_rgba (cr
, 0.75, 0, 0, 0.5);
450 printf ("String %s\n", o_current
->text
->disp_string
);
451 printf ("x %i, y %i, width %i, height%i\n", logical_rect
.x
, logical_rect
.y
, logical_rect
.width
, logical_rect
.height
);
452 printf ("x %i, y %i, width %i, height%i\n", inked_rect
.x
, inked_rect
.y
, inked_rect
.width
, inked_rect
.height
);
455 pango_font_metrics_unref (font_metrics
);
460 /*! \todo Finish function documentation!!!
462 * \par Function Description
465 void o_text_draw_rectangle(GSCHEM_TOPLEVEL
*w_current
, OBJECT
*o_current
)
467 TOPLEVEL
*toplevel
= w_current
->toplevel
;
468 int left
=0, right
=0, top
=0, bottom
=0;
471 /* text is too small so go through and draw a rectangle in
474 /* NOTE THAT THE TOP AND BOTTOM ARE REVERSED THROUGHT THE WHOLE OF GEDA FOR WORLD COORDS */
475 WORLDtoSCREEN( toplevel
, o_current
->w_left
, o_current
->w_bottom
, &left
, &top
);
476 WORLDtoSCREEN( toplevel
, o_current
->w_right
, o_current
->w_top
, &right
, &bottom
);
478 if (toplevel
->override_color
!= -1 ) { /* Override */
479 color
= x_get_color (toplevel
->override_color
);
481 color
= x_get_color (o_current
->color
);
483 gdk_gc_set_foreground(w_current
->gc
, color
);
485 if (toplevel
->DONT_REDRAW
== 0) {
486 gdk_draw_rectangle (w_current
->drawable
,
496 /*! \todo Finish function documentation!!!
498 * \par Function Description
501 void o_text_draw(GSCHEM_TOPLEVEL
*w_current
, OBJECT
*o_current
)
503 TOPLEVEL
*toplevel
= w_current
->toplevel
;
504 int screen_x1
, screen_y1
;
505 int small_dist
, offset
;
507 g_return_if_fail (o_current
!= NULL
);
508 g_return_if_fail (o_current
->type
== OBJ_TEXT
);
509 g_return_if_fail (o_current
->text
!= NULL
);
511 if (toplevel
->DONT_REDRAW
== 1 ||
512 (o_current
->visibility
== INVISIBLE
&& !toplevel
->show_hidden_text
)) {
516 if (!w_current
->fast_mousepan
|| !w_current
->doing_pan
) {
517 o_text_draw_lowlevel(w_current
, o_current
);
519 /* Indicate on the schematic that the text is invisible by */
520 /* drawing a little I on the screen at the origin */
521 if (o_current
->visibility
== INVISIBLE
&& toplevel
->show_hidden_text
) {
522 if (toplevel
->override_color
!= -1 ) {
523 gdk_gc_set_foreground(w_current
->gc
,
524 x_get_color(toplevel
->override_color
));
527 gdk_gc_set_foreground(w_current
->gc
,
528 x_get_color(w_current
->lock_color
));
531 offset
= SCREENabs(toplevel
, 10);
532 small_dist
= SCREENabs(toplevel
, 20);
533 WORLDtoSCREEN( toplevel
, o_current
->text
->x
, o_current
->text
->y
, &screen_x1
, &screen_y1
);
536 if (toplevel
->DONT_REDRAW
== 0) {
537 /* Top part of the I */
538 gdk_draw_line (w_current
->drawable
, w_current
->gc
,
541 screen_x1
+small_dist
,
543 /* Middle part of the I */
544 gdk_draw_line (w_current
->drawable
, w_current
->gc
,
545 screen_x1
+small_dist
/2,
547 screen_x1
+small_dist
/2,
548 screen_y1
+small_dist
);
549 /* Bottom part of the I */
550 gdk_draw_line (w_current
->drawable
, w_current
->gc
,
552 screen_y1
+small_dist
,
553 screen_x1
+small_dist
,
554 screen_y1
+small_dist
);
559 if (w_current
->doing_pan
) {
560 o_text_draw_rectangle(w_current
, o_current
);
566 // o_text_draw_rectangle(w_current, o_current);
568 /* return if text origin marker displaying is disabled */
569 if (w_current
->text_origin_marker
== FALSE
) {
573 small_dist
= SCREENabs(toplevel
, 10);
575 /* Switch of mark drawing at small sizes */
576 if (small_dist
< 1) /* TODO: Define this somewhere? */
579 /* Test to see what happens if we only display the mark for selected text */
580 if (!o_current
->selected
)
583 WORLDtoSCREEN( toplevel
, o_current
->text
->x
, o_current
->text
->y
, &screen_x1
, &screen_y1
);
585 /* this is not really a fix, but a lame patch */
586 /* not having this will cause a bad draw of things when coords */
587 /* get close to the 2^15 limit of X */
588 if (screen_x1
+small_dist
> 32767 || screen_y1
+small_dist
> 32767) {
592 if (toplevel
->override_color
!= -1 ) {
593 gdk_gc_set_foreground(w_current
->gc
,
594 x_get_color(toplevel
->override_color
));
597 gdk_gc_set_foreground(w_current
->gc
,
598 x_get_color(w_current
->lock_color
));
601 if (toplevel
->DONT_REDRAW
== 0) {
603 /* reference point */
605 gschem_cairo_set_source_color (w_current
->cr
,
606 (toplevel
->override_color
!= -1) ?
607 x_color_lookup (toplevel
->override_color
) :
608 x_color_lookup (w_current
->lock_color
));
609 cairo_set_line_width (w_current
->cr
, 1);
610 cairo_move_to (w_current
->cr
, screen_x1
- small_dist
, screen_y1
- small_dist
);
611 cairo_line_to (w_current
->cr
, screen_x1
+ small_dist
, screen_y1
+ small_dist
);
612 cairo_move_to (w_current
->cr
, screen_x1
- small_dist
, screen_y1
+ small_dist
);
613 cairo_line_to (w_current
->cr
, screen_x1
+ small_dist
, screen_y1
- small_dist
);
615 cairo_stroke (w_current
->cr
);
619 gschem_cairo_set_line_type (w_current
->cr
, TYPE_SOLID
,
621 o_line_draw_cairo (w_current
->cr
,
622 (toplevel
->override_color
!= -1 ) ?
623 x_get_color(toplevel
->override_color
) :
624 x_get_color(w_current
->lock_color
),
626 screen_x1
-small_dist
,
627 screen_y1
+small_dist
,
628 screen_x1
+small_dist
,
629 screen_y1
-small_dist
,
631 o_line_draw_cairo (w_current
->cr
,
632 (toplevel
->override_color
!= -1 ) ?
633 x_get_color(toplevel
->override_color
) :
634 x_get_color(w_current
->lock_color
),
636 screen_x1
+small_dist
,
637 screen_y1
+small_dist
,
638 screen_x1
-small_dist
,
639 screen_y1
-small_dist
,
646 /*! \todo Finish function documentation!!!
648 * \par Function Description
651 void o_text_draw_xor(GSCHEM_TOPLEVEL
*w_current
, int dx
, int dy
, OBJECT
*o_current
)
653 TOPLEVEL
*toplevel
= w_current
->toplevel
;
654 int top
, bottom
, left
, right
;
657 if (o_current
->visibility
== INVISIBLE
&& !toplevel
->show_hidden_text
) {
661 /* always display text which is 12 or larger */
662 factor
= (int) toplevel
->page_current
->to_world_x_constant
;
663 if ((factor
< w_current
->text_display_zoomfactor
) ||
664 o_current
->text
->size
>= 12 ||
665 w_current
->text_feedback
== ALWAYS
) {
667 sdx
= SCREENabs (toplevel
, dx
);
668 sdy
= -SCREENabs (toplevel
, dy
);
669 cairo_save (w_current
->cr
);
670 cairo_translate (w_current
->cr
, sdx
, sdy
);
671 o_text_draw_lowlevel (w_current
, o_current
);
672 cairo_restore (w_current
->cr
);
675 /* text is too small so go through and draw a line in
677 WORLDtoSCREEN(toplevel
, o_current
->w_left
+ dx
, o_current
->w_bottom
+ dy
, &left
, &top
);
678 WORLDtoSCREEN(toplevel
, o_current
->w_right
+ dx
, o_current
->w_top
+ dy
, &right
, &bottom
);
680 if (o_current
->saved_color
!= -1) {
681 color
= o_current
->saved_color
;
683 color
= o_current
->color
;
686 gdk_gc_set_foreground(w_current
->outline_xor_gc
,
687 x_get_darkcolor(color
));
689 gdk_draw_rectangle (w_current
->drawable
,
690 w_current
->outline_xor_gc
,
700 /*! \todo Finish function documentation!!!
702 * \par Function Description
705 void o_text_prepare_place(GSCHEM_TOPLEVEL
*w_current
, char *text
)
707 TOPLEVEL
*toplevel
= w_current
->toplevel
;
709 /* Insert the new object into the buffer at world coordinates (0,0).
710 * It will be translated to the mouse coordinates during placement. */
712 w_current
->first_wx
= 0;
713 w_current
->first_wy
= 0;
715 w_current
->last_drawb_mode
= LAST_DRAWB_MODE_NONE
;
717 /* remove the old place list if it exists */
718 s_delete_object_glist(toplevel
, toplevel
->page_current
->place_list
);
719 toplevel
->page_current
->place_list
= NULL
;
721 /* here you need to add OBJ_TEXT when it's done */
722 toplevel
->page_current
->place_list
=
723 g_list_append(toplevel
->page_current
->place_list
,
725 OBJ_TEXT
, w_current
->text_color
,
726 0, 0, LOWER_LEFT
, 0, /* zero is angle */
728 w_current
->text_size
,
729 /* has to be visible so you can place it */
730 /* visibility is set when you create the object */
731 VISIBLE
, SHOW_NAME_VALUE
));
733 w_current
->inside_action
= 1;
734 i_set_state (w_current
, ENDTEXT
);
738 /*! \todo Finish function documentation!!!
740 * \par Function Description
743 void o_text_edit(GSCHEM_TOPLEVEL
*w_current
, OBJECT
*o_current
)
745 /* you need to check to make sure only one object is selected */
746 /* no actually this is okay... not here in o_edit */
747 text_edit_dialog(w_current
,
748 o_text_get_string (w_current
->toplevel
, o_current
),
749 o_current
->text
->size
, o_current
->text
->alignment
);
752 /*! \todo Finish function documentation!!!
754 * \par Function Description
757 void o_text_edit_end(GSCHEM_TOPLEVEL
*w_current
, char *string
, int len
, int text_size
,
760 TOPLEVEL
*toplevel
= w_current
->toplevel
;
766 s_current
= geda_list_get_glist( toplevel
->page_current
->selection_list
);
767 numselect
= g_list_length( geda_list_get_glist( toplevel
->page_current
->selection_list
));
769 while(s_current
!= NULL
) {
770 object
= (OBJECT
*) s_current
->data
;
773 if (object
->type
== OBJ_TEXT
) {
774 o_invalidate (w_current
, object
);
776 object
->text
->size
= text_size
;
777 object
->text
->alignment
= text_alignment
;
779 /* probably the text object should be extended to carry a color */
780 /* and we should pass it here with a function parameter (?) */
781 object
->saved_color
= w_current
->edit_color
;
783 /* only change text string if there is only ONE text object selected */
784 if (numselect
== 1 && string
) {
785 o_text_set_string (w_current
->toplevel
, object
, string
);
786 /* handle slot= attribute, it's a special case */
787 if (g_ascii_strncasecmp (string
, "slot=", 5) == 0) {
788 o_slot_end (w_current
, string
, strlen (string
));
791 o_text_recreate(toplevel
, object
);
792 o_invalidate (w_current
, object
);
796 s_current
= g_list_next(s_current
);
799 toplevel
->page_current
->CHANGED
= 1;
800 o_undo_savestate(w_current
, UNDO_ALL
);
803 /*! \todo Finish function documentation!!!
805 * \par Function Description
808 * The object passed in should be the REAL object, NOT any copy in any
811 void o_text_change(GSCHEM_TOPLEVEL
*w_current
, OBJECT
*object
, char *string
,
812 int visibility
, int show
)
814 TOPLEVEL
*toplevel
= w_current
->toplevel
;
815 if (object
== NULL
) {
819 if (object
->type
!= OBJ_TEXT
) {
823 /* erase old object */
824 o_invalidate (w_current
, object
);
826 /* second change the real object */
827 o_text_set_string (toplevel
, object
, string
);
829 object
->visibility
= visibility
;
830 object
->show_name_value
= show
;
831 o_text_recreate(toplevel
, object
);
832 o_invalidate (w_current
, object
);
834 /* handle slot= attribute, it's a special case */
835 if (g_ascii_strncasecmp (string
, "slot=", 5) == 0) {
836 o_slot_end (w_current
, string
, strlen (string
));
839 toplevel
->page_current
->CHANGED
= 1;