Take page as input and take advantage of s_visit_page.
[geda-gaf/berndj.git] / gschem / src / o_cue.c
blob06ca2f53c1326c4f4b8919db3111196174773f47
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 <stdio.h>
23 #include <string.h>
25 #include "gschem.h"
27 #ifdef HAVE_LIBDMALLOC
28 #include <dmalloc.h>
29 #endif
31 /*! \todo Finish function documentation!!!
32 * \brief
33 * \par Function Description
36 void o_cue_redraw_all(GSCHEM_TOPLEVEL *w_current, OBJECT *head, gboolean draw_selected)
38 TOPLEVEL *toplevel = w_current->toplevel;
39 OBJECT *o_current;
40 int redraw_state = w_current->toplevel->DONT_REDRAW;
42 o_current = head;
43 while(o_current != NULL) {
44 switch(o_current->type) {
45 case(OBJ_NET):
46 case(OBJ_BUS):
47 case(OBJ_PIN):
48 if (o_current->dont_redraw ||
49 (o_current->selected && !draw_selected)) {
50 w_current->toplevel->DONT_REDRAW = 1 || redraw_state;
52 else {
53 w_current->toplevel->DONT_REDRAW = 0 || redraw_state;
55 o_cue_draw_single(w_current, o_current);
56 break;
58 case(OBJ_COMPLEX):
59 case(OBJ_PLACEHOLDER):
60 if (o_current->dont_redraw ||
61 (o_current->selected && !draw_selected)) {
62 toplevel->DONT_REDRAW = 1 || redraw_state;
64 else {
65 toplevel->DONT_REDRAW = 0 || redraw_state;
67 o_cue_redraw_all(w_current, o_current->complex->prim_objs,
68 draw_selected);
69 break;
73 o_current = o_current->next;
75 toplevel->DONT_REDRAW = redraw_state;
79 /*!
80 * \brief Set the color on the gc depending on the passed in color id
82 static void o_cue_set_color(GSCHEM_TOPLEVEL *w_current, int color)
84 if (w_current->toplevel->override_color != -1 ) {
85 gdk_gc_set_foreground(w_current->gc,
86 x_get_color(w_current->toplevel->override_color));
87 } else {
88 gdk_gc_set_foreground(w_current->gc, x_get_color(color));
93 /*! \todo Finish function documentation!!!
94 * \brief
95 * \par Function Description
98 void o_cue_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *object, int whichone)
100 TOPLEVEL *toplevel = w_current->toplevel;
101 PAGE *page = toplevel->page_current;
102 int x[2], y[2], screen_x, screen_y;
103 GList *cl_current;
104 CONN *conn;
105 int type, count = 0;
106 int done = FALSE;
107 int size, x2size, pinsize;
108 int otherone;
109 int bus_involved=FALSE;
111 if (whichone != GRIP_1 && whichone != GRIP_2) return;
113 s_basic_get_grip(object, whichone, &x[0], &y[0]);
115 type = CONN_ENDPOINT;
117 cl_current = object->conn_list;
118 while(cl_current != NULL && !done) {
119 conn = (CONN *) cl_current->data;
121 if (conn->x == x[0] && conn->y == y[0]) {
122 switch(conn->type) {
124 case(CONN_ENDPOINT):
125 count++;
126 if (conn->other_object &&
127 ((object->type == OBJ_NET &&
128 conn->other_object->type == OBJ_BUS) ||
129 (object->type == OBJ_BUS &&
130 conn->other_object->type == OBJ_NET))) {
131 bus_involved=TRUE;
133 break;
135 case(CONN_MIDPOINT):
136 type = CONN_MIDPOINT;
137 done = TRUE;
138 count = 0;
139 if (conn->other_object &&
140 ((object->type == OBJ_NET &&
141 conn->other_object->type == OBJ_BUS) ||
142 (object->type == OBJ_BUS &&
143 conn->other_object->type == OBJ_NET))) {
144 bus_involved=TRUE;
146 break;
150 cl_current = g_list_next(cl_current);
153 #if DEBUG
154 printf("type: %d count: %d\n", type, count);
155 #endif
157 size = SCREENabs(page, CUE_BOX_SIZE);
158 x2size = 2 * size;
160 WORLDtoSCREEN(page, x[0], y[0], &screen_x, &screen_y);
162 switch(type) {
164 case(CONN_ENDPOINT):
165 if (object->type == OBJ_NET) { /* only nets have these cues */
166 if (count < 1) { /* Didn't find anything connected there */
167 if (toplevel->DONT_REDRAW == 0) {
168 o_cue_set_color(w_current, toplevel->net_endpoint_color);
169 gdk_draw_rectangle(w_current->backingstore,
170 w_current->gc, TRUE,
171 screen_x - size,
172 screen_y - size,
173 x2size,
174 x2size);
175 o_invalidate_rect(w_current, screen_x - size, screen_y - size,
176 screen_x + size, screen_y + size);
179 } else if (count >= 2) {
180 /* draw circle */
182 if (bus_involved) {
183 size = SCREENabs(page, CUE_CIRCLE_SMALL_SIZE) / 2;
184 } else {
185 size = SCREENabs(page, CUE_CIRCLE_LARGE_SIZE) / 2;
187 x2size = 2 * size;
188 if (toplevel->DONT_REDRAW == 0) {
189 o_cue_set_color(w_current, toplevel->junction_color);
190 gdk_draw_arc(w_current->backingstore,
191 w_current->gc, TRUE,
192 screen_x - size,
193 screen_y - size,
194 x2size, x2size, 0, FULL_CIRCLE);
195 o_invalidate_rect(w_current, screen_x - size, screen_y - size,
196 screen_x + size, screen_y + size);
199 } else if (object->type == OBJ_PIN) {
200 /* Didn't find anything connected there */
201 if (count < 1 && object->whichend == whichone) {
203 otherone = (whichone == GRIP_1 ? GRIP_2 : GRIP_1);
205 pinsize = SCREENabs(page, 10);
206 if (toplevel->pin_style == THICK ) {
207 gdk_gc_set_line_attributes(w_current->gc, pinsize,
208 GDK_LINE_SOLID,
209 GDK_CAP_NOT_LAST,
210 GDK_JOIN_MITER);
213 /* No need to invalidate the PIN end CUE, as the
214 * whole pin region is already invalidated. */
215 if (toplevel->DONT_REDRAW == 0) {
216 s_basic_get_grip(object, otherone, &x[1], &y[1]);
218 o_cue_set_color(w_current, toplevel->net_endpoint_color);
220 if (y[0] == y[1]) {
221 /* horizontal line */
222 if (x[0] <= x[1]) {
223 gdk_draw_line(w_current->backingstore, w_current->gc,
224 screen_x, screen_y, screen_x + size, screen_y);
225 } else {
226 gdk_draw_line(w_current->backingstore, w_current->gc,
227 screen_x, screen_y, screen_x - size, screen_y);
229 } else if (x[0] == x[1]) {
230 /* vertical line */
231 if (y[0] <= y[1]) {
232 gdk_draw_line(w_current->backingstore, w_current->gc,
233 screen_x, screen_y, screen_x, screen_y - size);
234 } else {
235 gdk_draw_line(w_current->backingstore, w_current->gc,
236 screen_x, screen_y, screen_x, screen_y + size);
238 } else {
239 /* angled line */
240 /* not supporting rendering of cue for angled pin for now. hack */
244 if (toplevel->pin_style == THICK ) {
245 gdk_gc_set_line_attributes(w_current->gc, 0,
246 GDK_LINE_SOLID,
247 GDK_CAP_NOT_LAST,
248 GDK_JOIN_MITER);
252 break;
254 case(CONN_MIDPOINT):
256 /* draw circle */
257 if (bus_involved) {
258 size = SCREENabs(page, CUE_CIRCLE_SMALL_SIZE) / 2;
259 } else {
260 size = SCREENabs(page, CUE_CIRCLE_LARGE_SIZE) / 2;
262 x2size = size * 2;
264 if (toplevel->DONT_REDRAW == 0) {
265 o_cue_set_color(w_current, toplevel->junction_color);
266 gdk_draw_arc(w_current->backingstore,
267 w_current->gc, TRUE,
268 screen_x - size,
269 screen_y - size,
270 x2size, x2size, 0, FULL_CIRCLE);
271 o_invalidate_rect(w_current, screen_x - size, screen_y - size,
272 screen_x + size, screen_y + size);
274 break;
276 /* here is where you draw bus rippers */
282 /*! \brief Lowlevel endpoint erase.
283 * \par Function Description
284 * This function erases OBJECT endpoints forcibly.
286 * \param [in] w_current The GSCHEM_TOPLEVEL object.
287 * \param [in] object OBJECT to forcibly erase endpoint from.
288 * \param [in] whichone Which endpoint to erase from OBJECT.
290 void o_cue_erase_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *object, int whichone)
292 TOPLEVEL *toplevel = w_current->toplevel;
293 PAGE *page = toplevel->page_current;
294 int x, y, screen_x, screen_y;
295 int size, x2size;
297 s_basic_get_grip(object, whichone, &x, &y);
299 size = SCREENabs(page, CUE_BOX_SIZE);
300 x2size = 2 * size;
302 gdk_gc_set_foreground(w_current->gc,
303 x_get_color(toplevel->background_color));
305 WORLDtoSCREEN(page, x, y, &screen_x, &screen_y);
307 if (toplevel->DONT_REDRAW == 0) {
308 gdk_draw_rectangle(w_current->backingstore,
309 w_current->gc, TRUE,
310 screen_x - size,
311 screen_y - size,
312 x2size,
313 x2size);
314 o_invalidate_rect(w_current, screen_x - size, screen_y - size,
315 screen_x + size, screen_y + size);
320 /*! \todo Finish function documentation!!!
321 * \brief
322 * \par Function Description
325 void o_cue_draw_lowlevel_midpoints(GSCHEM_TOPLEVEL *w_current, OBJECT *object)
327 TOPLEVEL *toplevel = w_current->toplevel;
328 PAGE *page = toplevel->page_current;
329 int x, y, screen_x, screen_y;
330 GList *cl_current;
331 CONN *conn;
332 int size, x2size;
334 if (toplevel->override_color != -1 ) {
335 gdk_gc_set_foreground(w_current->gc,
336 x_get_color(toplevel->override_color));
337 } else {
338 gdk_gc_set_foreground(w_current->gc,
339 x_get_color(toplevel->junction_color));
342 cl_current = object->conn_list;
343 while(cl_current != NULL) {
344 conn = (CONN *) cl_current->data;
346 switch(conn->type) {
347 case(CONN_MIDPOINT):
349 x = conn->x;
350 y = conn->y;
352 WORLDtoSCREEN(page, x, y, &screen_x, &screen_y);
354 /* draw circle */
355 if (conn->other_object &&
356 ( (object->type == OBJ_BUS &&
357 conn->other_object->type == OBJ_NET) ||
358 (object->type == OBJ_NET &&
359 conn->other_object->type == OBJ_BUS))) {
360 size = SCREENabs(page, CUE_CIRCLE_SMALL_SIZE) / 2;
361 } else {
362 size = SCREENabs(page, CUE_CIRCLE_LARGE_SIZE) / 2;
364 x2size = size * 2;
366 if (toplevel->DONT_REDRAW == 0) {
367 gdk_draw_arc(w_current->backingstore,
368 w_current->gc, TRUE,
369 screen_x - size,
370 screen_y - size,
371 x2size, x2size, 0, FULL_CIRCLE);
372 o_invalidate_rect(w_current, screen_x - size, screen_y - size,
373 screen_x + size, screen_y + size);
375 break;
379 cl_current = g_list_next(cl_current);
383 /*! \todo Finish function documentation!!!
384 * \brief
385 * \par Function Description
388 void o_cue_draw_single(GSCHEM_TOPLEVEL *w_current, OBJECT *object)
390 if (!object) {
391 return;
394 if (object->type != OBJ_NET && object->type != OBJ_PIN &&
395 object->type != OBJ_BUS) {
396 return;
399 if (object->type != OBJ_PIN) {
400 o_cue_draw_lowlevel(w_current, object, GRIP_1);
401 o_cue_draw_lowlevel(w_current, object, GRIP_2);
402 o_cue_draw_lowlevel_midpoints(w_current, object);
403 } else {
404 o_cue_draw_lowlevel(w_current, object, object->whichend);
408 /*! \todo Finish function documentation!!!
409 * \brief
410 * \par Function Description
413 void o_cue_erase_single(GSCHEM_TOPLEVEL *w_current, OBJECT *object)
415 TOPLEVEL *toplevel = w_current->toplevel;
416 if (!object) {
417 return;
420 if (object->type != OBJ_NET && object->type != OBJ_PIN &&
421 object->type != OBJ_BUS)
423 return;
426 if (object->type != OBJ_PIN) {
427 o_cue_erase_lowlevel(w_current, object, GRIP_1);
428 o_cue_erase_lowlevel(w_current, object, GRIP_2);
429 toplevel->override_color = toplevel->background_color;
430 o_cue_draw_lowlevel_midpoints(w_current, object);
431 toplevel->override_color = -1;
432 } else {
433 o_cue_erase_lowlevel(w_current, object, object->whichend);
437 /*! \brief Erase the cues of an object and redraw connected objects.
438 * \par Function Description
439 * This function erases the cues on object \a object. It then redraws
440 * the cues of its connected objects.
442 * \param [in] w_current The GSCHEM_TOPLEVEL object.
443 * \param [in] object The object to redraw with no cue.
445 static void o_cue_undraw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *object)
447 GList *cl_current;
448 CONN *conn;
450 o_cue_erase_single(w_current, object);
452 cl_current = object->conn_list;
453 while(cl_current != NULL) {
454 conn = (CONN *) cl_current->data;
456 if (conn->other_object) {
457 o_redraw_single(w_current, conn->other_object);
460 cl_current = g_list_next(cl_current);
464 /*! \brief Hide the cues of an object.
465 * \par Function Description
466 * This function takes an object and redraws it without its cues. It
467 * also manages the redraw of connected objects.
469 * \note
470 * The connections of the object are unchanged by this function.
472 * \param [in] w_current The GSCHEM_TOPLEVEL object.
473 * \param [in] object The object to redraw with no cue.
475 void o_cue_undraw(GSCHEM_TOPLEVEL *w_current, OBJECT *object)
477 switch (object->type) {
478 case OBJ_PIN:
479 case OBJ_NET:
480 case OBJ_BUS:
481 o_cue_undraw_lowlevel (w_current, object);
482 break;
483 case OBJ_COMPLEX:
484 case OBJ_PLACEHOLDER:
486 OBJECT *o_current;
487 for (o_current = object->complex->prim_objs;
488 o_current != NULL;
489 o_current = o_current->next) {
490 if (o_current->type == OBJ_PIN ||
491 o_current->type == OBJ_NET ||
492 o_current->type == OBJ_BUS) {
493 o_cue_undraw_lowlevel (w_current, o_current);
499 o_redraw_single(w_current, object);
502 /*! \todo Finish function documentation!!!
503 * \brief
504 * \par Function Description
507 void o_cue_draw_list(GSCHEM_TOPLEVEL *w_current, GList const *object_list)
509 OBJECT *object;
510 GList const *ol_current;
512 ol_current = object_list;
513 while(ol_current != NULL) {
514 object = ol_current->data;
516 o_cue_draw_single(w_current, object);
518 ol_current = g_list_next(ol_current);
522 /*! \todo Finish function documentation!!!
523 * \brief
524 * \par Function Description
527 void o_cue_undraw_list(GSCHEM_TOPLEVEL *w_current, GList const *object_list)
529 OBJECT *object;
530 GList const *ol_current;
532 ol_current = object_list;
533 while(ol_current != NULL) {
534 object = ol_current->data;
536 o_cue_undraw(w_current, object);
538 ol_current = g_list_next(ol_current);