Take page as input and take advantage of s_visit_page.
[geda-gaf/berndj.git] / gschem / src / o_text.c
blob956dc162f279f0746c636c91d40b7b939e01a4b5
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 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
20 #include <config.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <sys/stat.h>
25 #include <math.h>
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #endif
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
33 #include "gschem.h"
35 #ifdef HAVE_LIBDMALLOC
36 #include <dmalloc.h>
37 #endif
40 /*! \todo Finish function documentation!!!
41 * \brief
42 * \par Function Description
45 void o_text_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
47 int left, right, top, bottom;
49 g_return_if_fail (o_current != NULL);
50 g_return_if_fail (o_current->text != NULL);
52 if (o_current->visibility == INVISIBLE && o_current->show_hidden &&
53 o_current->text->prim_objs == NULL) {
54 o_text_recreate(o_current);
57 o_redraw(w_current, o_current->text->prim_objs, TRUE);
59 world_get_object_list_bounds(o_current->text->prim_objs,
60 &left, &top, &right, &bottom);
61 o_current->w_left = left;
62 o_current->w_top = top;
63 o_current->w_right = right;
64 o_current->w_bottom = bottom;
68 /*! \todo Finish function documentation!!!
69 * \brief
70 * \par Function Description
73 void o_text_draw_rectangle(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
75 TOPLEVEL *toplevel = w_current->toplevel;
76 PAGE *page = toplevel->page_current;
77 int left=0, right=0, top=0, bottom=0;
78 GdkColor *color;
80 if (o_current->visibility == INVISIBLE && o_current->show_hidden &&
81 o_current->text->prim_objs == NULL) {
82 o_text_recreate(o_current);
85 /* text is too small so go through and draw a rectangle in
86 it's place */
88 /* NOTE THAT THE TOP AND BOTTOM ARE REVERSED THROUGHOUT THE WHOLE OF GEDA FOR WORLD COORDS */
89 WORLDtoSCREEN(page, o_current->w_left, o_current->w_bottom, &left, &top);
90 WORLDtoSCREEN(page, o_current->w_right, o_current->w_top, &right, &bottom);
92 if (toplevel->override_color != -1 ) { /* Override */
93 color = x_get_color(toplevel->override_color);
94 } else {
95 color = x_get_color(o_current->color);
97 gdk_gc_set_foreground(w_current->gc, color);
99 if (toplevel->DONT_REDRAW == 0) {
100 gdk_draw_rectangle( w_current->backingstore,
101 w_current->gc,
102 FALSE,
103 left,
104 top,
105 right - left,
106 bottom - top );
110 /*! \todo Finish function documentation!!!
111 * \brief
112 * \par Function Description
115 void o_text_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
117 TOPLEVEL *toplevel = w_current->toplevel;
118 PAGE *page = toplevel->page_current;
119 int screen_x1, screen_y1;
120 int small_dist, offset;
122 g_return_if_fail (o_current != NULL);
123 g_return_if_fail (o_current->type == OBJ_TEXT);
124 g_return_if_fail (o_current->text != NULL);
126 if (o_current->text->x == -1 && o_current->text->y -- -1) {
127 /* Off-schematic text has its own dialog. */
128 return;
131 if (toplevel->DONT_REDRAW == 1 ||
132 (o_current->visibility == INVISIBLE && !o_current->show_hidden)) {
133 return;
136 if (!w_current->fast_mousepan || !w_current->doing_pan) {
137 o_text_draw_lowlevel(w_current, o_current);
139 /* Indicate on the schematic that the text is invisible by */
140 /* drawing a little I on the screen at the origin */
141 if (o_current->visibility == INVISIBLE && o_current->show_hidden) {
142 if (toplevel->override_color != -1 ) {
143 gdk_gc_set_foreground(w_current->gc,
144 x_get_color(toplevel->override_color));
145 } else {
147 gdk_gc_set_foreground(w_current->gc,
148 x_get_color(w_current->lock_color));
151 offset = SCREENabs(page, 10);
152 small_dist = SCREENabs(page, 20);
153 WORLDtoSCREEN(page, o_current->text->x, o_current->text->y, &screen_x1, &screen_y1);
154 screen_x1 += offset;
155 screen_y1 += offset;
156 if (toplevel->DONT_REDRAW == 0) {
157 /* Top part of the I */
158 gdk_draw_line(w_current->backingstore, w_current->gc,
159 screen_x1,
160 screen_y1,
161 screen_x1+small_dist,
162 screen_y1);
163 /* Middle part of the I */
164 gdk_draw_line(w_current->backingstore, w_current->gc,
165 screen_x1+small_dist/2,
166 screen_y1,
167 screen_x1+small_dist/2,
168 screen_y1+small_dist);
169 /* Bottom part of the I */
170 gdk_draw_line(w_current->backingstore, w_current->gc,
171 screen_x1,
172 screen_y1+small_dist,
173 screen_x1+small_dist,
174 screen_y1+small_dist);
178 } else {
179 if (w_current->doing_pan) {
180 o_text_draw_rectangle(w_current, o_current);
181 return;
185 /* return if text origin marker displaying is disabled */
186 if (w_current->text_origin_marker == FALSE) {
187 return;
190 small_dist = SCREENabs(page, 10);
192 WORLDtoSCREEN(page, o_current->text->x, o_current->text->y, &screen_x1, &screen_y1);
194 /* this is not really a fix, but a lame patch */
195 /* not having this will cause a bad draw of things when coords */
196 /* get close to the 2^15 limit of X */
197 if (screen_x1+small_dist > 32767 || screen_y1+small_dist > 32767) {
198 return;
201 if (toplevel->override_color != -1 ) {
202 gdk_gc_set_foreground(w_current->gc,
203 x_get_color(toplevel->override_color));
204 } else {
206 gdk_gc_set_foreground(w_current->gc,
207 x_get_color(w_current->lock_color));
210 if (toplevel->DONT_REDRAW == 0) {
211 gdk_draw_line(w_current->backingstore, w_current->gc,
212 screen_x1-small_dist,
213 screen_y1+small_dist,
214 screen_x1+small_dist,
215 screen_y1-small_dist);
217 gdk_draw_line(w_current->backingstore, w_current->gc,
218 screen_x1+small_dist,
219 screen_y1+small_dist,
220 screen_x1-small_dist,
221 screen_y1-small_dist);
226 /*! \todo Finish function documentation!!!
227 * \brief
228 * \par Function Description
231 void o_text_draw_xor(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
233 TOPLEVEL *toplevel = w_current->toplevel;
234 PAGE *page = toplevel->page_current;
235 int top, bottom, left, right;
236 int color, factor;
238 if (o_current->visibility == INVISIBLE && !o_current->show_hidden) {
239 return;
242 /* always display text which is 12 or larger */
243 factor = (int) page->to_world_x_constant;
244 if ((factor < w_current->text_display_zoomfactor) ||
245 o_current->text->size >= 12 ||
246 w_current->text_feedback == ALWAYS) {
247 o_list_draw_xor(w_current, dx, dy, o_current->text->prim_objs);
248 } else {
249 /* text is too small so go through and draw a line in
250 it's place */
251 WORLDtoSCREEN(page, o_current->w_left + dx, o_current->w_bottom + dy, &left, &top);
252 WORLDtoSCREEN(page, o_current->w_right + dx, o_current->w_top + dy, &right, &bottom);
254 if (o_current->saved_color != -1) {
255 color = o_current->saved_color;
256 } else {
257 color = o_current->color;
260 gdk_gc_set_foreground(w_current->outline_xor_gc,
261 x_get_darkcolor(color));
263 gdk_draw_rectangle( w_current->backingstore,
264 w_current->outline_xor_gc,
265 FALSE,
266 left,
267 top,
268 right - left,
269 bottom - top );
273 void o_text_notice_changed(OBJECT *subject, GSCHEM_TOPLEVEL *w_current)
275 TOPLEVEL *toplevel = w_current->toplevel;
276 char const *string = o_text_get_string(subject);
278 /* erase old object */
279 o_erase_single(w_current, subject);
281 o_text_recreate(subject);
282 o_text_draw(w_current, subject);
284 /* handle slot= attribute, it's a special case */
285 if (string && g_ascii_strncasecmp (string, "slot=", 5) == 0) {
286 o_slot_end (w_current, string, strlen (string));
289 if (subject->attached_to) {
290 OBJECT *owner;
292 owner = subject->attached_to;
294 /* Another slotting special case. */
295 if (g_ascii_strncasecmp(string, "slotname=", 9) == 0 ||
296 g_ascii_strncasecmp(string, "slotowner=", 10) == 0) {
297 s_slot_reparent_from_attribs(toplevel, owner);
300 /* Rewrite symbols in slots, to pick up new values. */
301 if (owner->type == OBJ_COMPLEX) {
302 s_slot_rewrite_symbols(owner);
305 if (owner->type == OBJ_SLOT && owner->slot->owner) {
306 s_slot_rewrite_symbols(owner->slot->owner);
310 toplevel->page_current->CHANGED = 1;
313 /*! \todo Finish function documentation!!!
314 * \brief
315 * \par Function Description
318 void o_text_prepare_place(GSCHEM_TOPLEVEL *w_current, char *text)
320 TOPLEVEL *toplevel = w_current->toplevel;
321 OBJECT *new_text;
323 /* Insert the new object into the buffer at world coordinates (0,0).
324 * It will be translated to the mouse coordinates during placement. */
326 w_current->first_wx = 0;
327 w_current->first_wy = 0;
329 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
331 new_text = o_text_new(toplevel, OBJ_TEXT, w_current->text_color,
332 0, 0, LOWER_LEFT, 0, /* zero is angle */
333 text,
334 w_current->text_size,
335 /* has to be visible so you can place it */
336 /* visibility is set when you create the object */
337 VISIBLE, SHOW_NAME_VALUE);
339 s_page_replace_place_list(toplevel, toplevel->page_current,
340 g_list_prepend(NULL, new_text));
342 w_current->inside_action = 1;
343 i_set_state(w_current, DRAWTEXT);
347 /*! \todo Finish function documentation!!!
348 * \brief
349 * \par Function Description
352 void o_text_start (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
354 o_place_start (w_current, w_x, w_y);
358 /*! \todo Finish function documentation!!!
359 * \brief
360 * \par Function Description
363 void o_text_edit(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
365 /* you need to check to make sure only one object is selected */
366 /* no actually this is okay... not here in o_edit */
367 text_edit_dialog(w_current, o_text_get_string(o_current),
368 o_current->text->size, o_current->text->alignment);
371 /*! \todo Finish function documentation!!!
372 * \brief
373 * \par Function Description
376 void o_text_edit_end(GSCHEM_TOPLEVEL *w_current, char *string, int len, int text_size,
377 int text_alignment)
379 TOPLEVEL *toplevel = w_current->toplevel;
380 OBJECT *object;
381 GList *s_current;
382 int numselect;
384 /* skip over head */
385 s_current = geda_list_get_glist( toplevel->page_current->selection_list );
386 numselect = g_list_length( geda_list_get_glist( toplevel->page_current->selection_list ));
388 while(s_current != NULL) {
389 object = s_current->data;
391 if (object) {
392 if (object->type == OBJ_TEXT) {
393 o_erase_single(w_current, object);
395 object->text->size = text_size;
396 object->text->alignment = text_alignment;
398 /* probably the text object should be extended to carry a color */
399 /* and we should pass it here with a function parameter (?) */
400 object->saved_color = w_current->edit_color;
402 /* only change text string if there is only ONE text object selected */
403 if (numselect == 1 && string) {
404 o_text_set_string(object, string);
405 /* handle slot= attribute, it's a special case */
406 if (g_ascii_strncasecmp (string, "slot=", 5) == 0) {
407 o_slot_end (w_current, string, strlen (string));
411 g_signal_emit_by_name(G_OBJECT(object), "changed");
415 s_current = g_list_next(s_current);
418 toplevel->page_current->CHANGED = 1;
419 o_undo_savestate(w_current, UNDO_ALL);
422 void o_text_notice_create(GSCHEM_TOPLEVEL *w_current, OBJECT *o)
424 g_signal_connect(o, "changed", G_CALLBACK(o_text_notice_changed), w_current);