Bumped versions to 1.1.2/20070818/30:2:0 for the next development snapshot
[geda-gaf/whiteaudio.git] / gschem / src / x_event.c
blobfcf553e51379764db5cbbf7559236b528b1b1790
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 <math.h>
24 #ifdef HAVE_STDLIB_H
25 #include <stdlib.h>
26 #endif
28 #include <libgeda/libgeda.h>
30 #include "../include/globals.h"
31 #include "../include/prototype.h"
33 #ifdef HAVE_LIBDMALLOC
34 #include <dmalloc.h>
35 #endif
37 /* used in key_press, since it isn't passed this information */
38 /* filled in x_event_motion */
39 int mouse_x, mouse_y;
41 /* used by mouse pan */
42 extern int current_center_x, current_center_y;
43 int start_pan_x, start_pan_y;
44 int throttle = 0;
46 /* used for the stroke stuff */
47 #ifdef HAS_LIBSTROKE
49 #define MAX_SEQUENCE 20
50 static int DOING_STROKE = FALSE;
51 char sequence[MAX_SEQUENCE+1];
53 /* libstroke prototypes */
54 void stroke_init (void);
55 void stroke_record (int x, int y);
56 int stroke_trans (char *sequence);
57 #endif
59 /*! \todo Finish function documentation!!!
60 * \brief
61 * \par Function Description
64 gint x_event_expose(GtkWidget *widget, GdkEventExpose *event,
65 TOPLEVEL *w_current)
67 #if DEBUG
68 printf("EXPOSE\n");
69 #endif
71 exit_if_null(w_current);
72 /* nasty global variable */
73 global_window_current = (TOPLEVEL *) w_current;
75 gdk_draw_pixmap(widget->window,
76 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
77 w_current->backingstore,
78 event->area.x, event->area.y,
79 event->area.x, event->area.y,
80 event->area.width, event->area.height);
82 /* either this or put xor's and friends into backingstore */
83 /* take care of ghosting when you get an expose event */
84 if (w_current->inside_action) {
85 switch(w_current->event_state) {
86 case(MOVE):
87 case(ENDMOVE):
88 case(COPY):
89 case(ENDCOPY):
90 case(ENDMCOPY):
91 o_drawbounding(w_current, NULL,
92 geda_list_get_glist( w_current->page_current->selection_list ),
93 x_get_darkcolor(w_current->bb_color), FALSE);
94 break;
95 case(DRAWCOMP):
96 case(ENDCOMP):
97 case(ENDPASTE):
98 o_drawbounding(w_current, NULL,
99 w_current->page_current->complex_place_list,
100 x_get_darkcolor(w_current->bb_color), FALSE);
101 break;
103 case(BUSCONT):
104 case(DRAWBUS):
105 o_bus_xorrubber(w_current);
106 break;
107 case(DRAWNET):
108 case(NETCONT):
109 o_net_xorrubber(w_current);
110 break;
111 case(ENDARC):
112 o_arc_rubberarc_xor(w_current);
113 break;
114 case(ENDATTRIB): /*! \todo how to test ??? */
115 o_attrib_rubberattrib(w_current);
116 break;
117 case(ENDBOX):
118 o_box_rubberbox_xor(w_current);
119 break;
120 case(ENDCIRCLE):
121 o_circle_rubbercircle_xor(w_current);
122 break;
123 case(ENDLINE):
124 o_line_rubberline_xor(w_current);
125 break;
126 case(ENDPIN): /*! \todo (no function in o_pin.nw available) */
127 break;
128 case(ENDTEXT):
129 o_text_rubberattrib(w_current);
130 break;
131 case(GRIPS): /*! \todo (larger changes in o_grips.nw necessary) */
132 break;
133 case(ZOOMBOXEND): /*! \todo (not realy a problem as zoom will redraw) */
134 break;
138 /* raise the dialog boxes if this feature is enabled */
139 if (w_current->raise_dialog_boxes) {
140 x_dialog_raise_all(w_current);
143 return(0);
146 /*! \todo Finish function documentation!!!
147 * \brief
148 * \par Function Description
151 gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
152 TOPLEVEL *w_current)
154 int prev_state;
155 int w_x, w_y;
157 exit_if_null(w_current);
158 global_window_current = w_current;
160 #if DEBUG
161 printf("pressed button %d! \n", event->button);
162 printf("event state: %d \n", event->state);
163 printf("w_current state: %d \n", w_current->event_state);
164 printf("Selection is:\n");
165 o_selection_print_all(&(w_current->page_current->selection_list));
166 printf("\n");
167 #endif
169 if (event->type == GDK_2BUTTON_PRESS &&
170 (w_current->event_state == STARTSELECT ||
171 w_current->event_state == SELECT)) {
172 o_find_object(w_current, (int) event->x, (int) event->y, TRUE);
173 if ( geda_list_get_glist( w_current->page_current->selection_list )) {
174 o_edit(w_current, geda_list_get_glist( w_current->page_current->selection_list ));
175 return(0);
179 w_current->SHIFTKEY = (event->state & GDK_SHIFT_MASK ) ? 1 : 0;
180 w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0;
181 w_current->ALTKEY = (event->state & GDK_MOD1_MASK) ? 1 : 0;
183 if (event->button == 1) {
184 switch(w_current->event_state) {
186 case(SELECT):
187 /* look for grips or fall through if not enabled */
188 if (!o_grips_start(
189 w_current, (int) event->x, (int) event->y)) {
190 /* now go into normal SELECT */
191 w_current->event_state = STARTSELECT;
192 w_current->start_x = w_current->last_x =
193 (int) event->x;
194 w_current->start_y = w_current->last_y =
195 (int) event->y;
196 } else {
197 /* a grip was found */
198 w_current->event_state = GRIPS;
199 w_current->inside_action = 1;
201 break;
203 case(STARTCOPY):
204 if (o_select_selected(w_current)) {
205 w_current->rotated_inside = 0;
206 o_copy_start(w_current,
207 (int) event->x, (int) event->y);
208 w_current->event_state = COPY;
209 w_current->inside_action = 1;
211 break;
213 case(STARTMCOPY):
214 if (o_select_selected(w_current)) {
215 w_current->rotated_inside = 0;
216 o_copy_start(w_current,
217 (int) event->x, (int) event->y);
218 w_current->event_state = MCOPY;
219 w_current->inside_action = 1;
221 break;
223 case(STARTMOVE):
224 if (o_select_selected(w_current)) {
225 w_current->rotated_inside = 0;
226 o_move_start(w_current,
227 (int) event->x, (int) event->y);
228 w_current->event_state = MOVE;
229 w_current->inside_action = 1;
231 break;
233 case(STARTPASTE):
234 o_buffer_paste_start(w_current,
235 (int) event->x,
236 (int) event->y,
237 w_current->buffer_number);
238 w_current->event_state = ENDPASTE;
239 w_current->inside_action = 1;
240 break;
242 case(DRAWLINE):
243 o_line_start(w_current,
244 (int) event->x,
245 (int) event->y);
246 w_current->event_state = ENDLINE;
247 w_current->inside_action = 1;
248 break;
250 case(ENDLINE):
251 o_line_end(w_current,
252 (int) event->x,
253 (int) event->y);
254 w_current->inside_action = 0;
255 w_current->event_state = DRAWLINE;
256 break;
258 case(DRAWBOX):
259 o_box_start(w_current,
260 (int) event->x,
261 (int) event->y);
262 w_current->event_state = ENDBOX;
263 w_current->inside_action = 1;
264 break;
266 case(ENDBOX):
267 o_box_end(w_current,
268 (int) event->x,
269 (int) event->y);
270 w_current->inside_action = 0;
271 w_current->event_state = DRAWBOX;
272 break;
274 case(DRAWPICTURE):
275 o_picture_start(w_current,
276 (int) event->x,
277 (int) event->y);
278 w_current->event_state = ENDPICTURE;
279 w_current->inside_action = 1;
280 break;
282 case(ENDPICTURE):
283 o_picture_end(w_current,
284 (int) event->x,
285 (int) event->y);
286 w_current->inside_action = 0;
287 w_current->event_state = DRAWPICTURE;
288 break;
290 case(DRAWCIRCLE):
291 o_circle_start(w_current,
292 (int) event->x,
293 (int) event->y);
294 w_current->event_state = ENDCIRCLE;
295 w_current->inside_action = 1;
296 break;
298 case(ENDCIRCLE):
299 o_circle_end(w_current,
300 (int) event->x,
301 (int) event->y);
302 w_current->inside_action = 0;
303 w_current->event_state = DRAWCIRCLE;
304 break;
306 case(DRAWARC):
307 o_arc_start(w_current,
308 (int) event->x,
309 (int) event->y);
310 w_current->event_state = ENDARC;
311 w_current->inside_action = 1;
312 break;
314 case(ENDARC):
315 o_arc_end1(w_current,
316 (int) event->x,
317 (int) event->y);
318 w_current->inside_action = 0;
319 w_current->event_state = DRAWARC;
320 break;
322 case(DRAWPIN):
323 o_pin_start(w_current,
324 (int) event->x,
325 (int) event->y);
326 w_current->event_state = ENDPIN;
327 w_current->inside_action = 1;
328 break;
330 case(ENDPIN):
331 o_pin_end(w_current,
332 (int) event->x,
333 (int) event->y);
334 w_current->inside_action = 0;
335 w_current->event_state = DRAWPIN;
336 break;
338 case(STARTDRAWNET): /*! \todo change state name? */
339 o_net_start(w_current,
340 (int) event->x,
341 (int) event->y);
342 w_current->inside_action = 1;
343 w_current->event_state=DRAWNET;
345 break;
347 case(STARTDRAWBUS):
348 o_bus_start(w_current,
349 (int) event->x,
350 (int) event->y);
351 w_current->inside_action = 1;
352 w_current->event_state=DRAWBUS;
354 break;
356 case(DRAWNET):
357 case(NETCONT):
358 /* Only continue the net if net end worked */
359 if (o_net_end(w_current, (int) event->x,
360 (int) event->y)) {
361 o_net_start(w_current,
362 (int) w_current->save_x,
363 (int) w_current->save_y);
364 w_current->event_state=NETCONT;
366 break;
368 case(DRAWBUS):
369 case(BUSCONT):
370 /* Only continue the net if net end worked */
371 if (o_bus_end(w_current, (int) event->x,
372 (int) event->y)) {
373 o_bus_start(w_current,
374 (int) w_current->save_x,
375 (int) w_current->save_y);
376 w_current->event_state=BUSCONT;
378 break;
380 case(ENDCOMP):
381 o_complex_end(w_current,
382 fix_x(w_current, (int) event->x),
383 fix_y(w_current, (int) event->y));
384 /* not sure on this one */
385 /* probably keep this one */
387 o_redraw_single(w_current, w_current->page_current->
388 object_tail);
389 if (w_current->continue_component_place) {
390 o_complex_start(w_current,
391 (int) event->x,
392 (int) event->y);
393 } else {
394 w_current->inside_action = 0;
395 i_set_state(w_current, SELECT);
396 i_update_toolbar(w_current);
398 break;
400 case(ENDPASTE):
401 o_buffer_paste_end(w_current,
402 fix_x(w_current, (int) event->x),
403 fix_y(w_current, (int) event->y),
404 w_current->buffer_number);
405 w_current->inside_action = 0;
406 i_set_state(w_current, SELECT);
407 i_update_toolbar(w_current);
408 break;
410 case(ENDATTRIB):
411 o_attrib_end(w_current);
412 /* not sure on this one either... */
413 /* keep it as well */
414 w_current->inside_action = 0;
415 i_set_state(w_current, SELECT);
416 i_update_toolbar(w_current);
417 /* the following happen inside attrib_end */
418 /* therefore they are commeneted out here */
419 /* o_redraw_single(object_tail);*/
420 /* o_redraw_selected(); not sure on this */
421 break;
423 case(ENDROTATEP):
424 prev_state = w_current->DONT_REDRAW;
425 w_current->DONT_REDRAW = 0;
427 SCREENtoWORLD( w_current,
428 (int) event->x,
429 (int) event->y,
430 &w_x, &w_y );
431 w_x = snap_grid(w_current, w_x);
432 w_y = snap_grid(w_current, w_y);
434 o_rotate_90_world(
435 w_current,
436 geda_list_get_glist( w_current->page_current->selection_list ),
437 w_x, w_y);
438 w_current->DONT_REDRAW = prev_state;
440 w_current->inside_action = 0;
441 i_set_state(w_current, SELECT);
442 i_update_toolbar(w_current);
443 break;
445 case(ENDMIRROR):
446 SCREENtoWORLD( w_current,
447 (int) event->x,
448 (int) event->y,
449 &w_x, &w_y );
450 o_mirror_world(w_current,
451 geda_list_get_glist( w_current->page_current->selection_list ),
452 w_x, w_y);
453 w_x = snap_grid(w_current, w_x);
454 w_y = snap_grid(w_current, w_y);
456 w_current->inside_action = 0;
457 i_set_state(w_current, SELECT);
458 i_update_toolbar(w_current);
459 break;
461 case(ENDTEXT):
462 o_text_end(w_current);
463 /* not sure on this one either... */
464 /* keep it as well */
465 w_current->inside_action = 0;
466 i_set_state(w_current, SELECT);
467 i_update_toolbar(w_current);
468 /* the following happen inside attrib_end */
469 /* therefore they are commeneted out here */
470 /* o_redraw_single(object_tail);*/
471 /* o_redraw_selected(); not sure on this */
472 break;
474 case(STARTPAN):
475 a_pan(w_current,
476 (int) event->x,
477 (int) event->y);
479 /* keep this one too */
480 i_set_state(w_current, SELECT);
481 i_update_toolbar(w_current);
482 /* go to select state or not? hack */
483 break;
485 case(ZOOMBOXSTART):
486 a_zoom_box_start(w_current,
487 (int) event->x,
488 (int) event->y);
489 w_current->event_state = ZOOMBOXEND;
490 w_current->inside_action = 1;
491 break;
494 } else if (event->button == 2) {
496 /* try this out and see how it behaves */
497 if (w_current->inside_action) {
498 if (w_current->event_state == ENDCOMP ||
499 w_current->event_state == ENDTEXT ||
500 w_current->event_state == ENDMOVE ||
501 w_current->event_state == ENDCOPY ||
502 w_current->event_state == ENDMCOPY) {
503 return(0);
504 } else {
505 i_callback_cancel(w_current, 0, NULL);
506 return(0);
510 switch(w_current->middle_button) {
512 case(ACTION):
513 /* determine here if copy or move */
514 /* for now do move only */
515 /* make sure the list is not empty */
516 if (o_select_selected(w_current)) {
518 /* don't want to search if shift */
519 /* key is depresed */
520 if (!w_current->SHIFTKEY) {
521 o_find_object(w_current,
522 (int) event->x,
523 (int) event->y, TRUE);
525 } else {
526 o_select_unselect_all(w_current);
527 /* don't want to search if shift */
528 /* key is depresed */
529 if (!w_current->SHIFTKEY) {
530 o_find_object(w_current,
531 (int) event->x,
532 (int) event->y, TRUE);
536 if (!o_select_selected(w_current)) {
537 /* this means the above find did not
538 * find anything */
539 w_current->inside_action = 0;
540 i_set_state(w_current, SELECT);
541 i_update_toolbar(w_current);
542 return(0);
545 if (w_current->ALTKEY) {
546 o_copy_start(w_current,
547 (int) event->x,
548 (int) event->y);
549 w_current->inside_action = 1;
550 i_set_state(w_current, COPY);
551 } else {
552 o_move_start(w_current,
553 (int) event->x,
554 (int) event->y);
555 w_current->inside_action = 1;
556 i_set_state(w_current, MOVE);
558 break;
560 case(REPEAT):
561 if (w_current->last_callback != NULL) {
562 (*w_current->last_callback)(w_current,
563 0, NULL);
565 break;
566 #ifdef HAS_LIBSTROKE
567 case(STROKE):
568 DOING_STROKE=TRUE;
569 break;
571 #endif
572 case(MID_MOUSEPAN_ENABLED):
573 w_current->event_state = MOUSEPAN; /* start */
574 w_current->inside_action = 1;
575 w_current->doing_pan = TRUE;
576 start_pan_x = (int) event->x;
577 start_pan_y = (int) event->y;
578 throttle=0;
579 break;
582 } else if (event->button == 3) {
583 if (!w_current->inside_action) {
584 if (w_current->third_button == POPUP_ENABLED) {
585 i_update_menus(w_current); /* update menus before popup */
586 do_popup(w_current, event);
587 } else {
588 w_current->event_state = MOUSEPAN; /* start */
589 w_current->inside_action = 1;
590 w_current->doing_pan = TRUE;
591 start_pan_x = (int) event->x;
592 start_pan_y = (int) event->y;
593 throttle=0;
595 } else { /* this is the default cancel */
596 switch (w_current->event_state) {
597 case(STARTDRAWNET):
598 case(DRAWNET):
599 case(NETCONT):
600 w_current->inside_action = 0;
601 i_set_state(w_current, STARTDRAWNET);
602 o_net_eraserubber(w_current);
603 break;
605 case(STARTDRAWBUS):
606 case(DRAWBUS):
607 case(BUSCONT):
608 w_current->inside_action = 0;
609 i_set_state(w_current, STARTDRAWBUS);
610 o_bus_eraserubber(w_current);
611 break;
613 case(DRAWPIN):
614 case(ENDPIN):
615 w_current->inside_action = 0;
616 i_set_state(w_current, DRAWPIN);
617 o_pin_eraserubber(w_current);
618 break;
620 case(DRAWLINE):
621 case(ENDLINE):
622 w_current->inside_action = 0;
623 i_set_state(w_current, DRAWLINE);
624 o_line_eraserubber(w_current);
625 break;
627 case(DRAWBOX):
628 case(ENDBOX):
629 w_current->inside_action = 0;
630 i_set_state(w_current, DRAWBOX);
631 o_box_eraserubber(w_current);
632 break;
634 case(DRAWPICTURE):
635 case(ENDPICTURE):
636 w_current->inside_action = 0;
637 i_set_state(w_current, DRAWPICTURE);
638 o_picture_eraserubber(w_current);
639 break;
641 case(DRAWCIRCLE):
642 case(ENDCIRCLE):
643 w_current->inside_action = 0;
644 i_set_state(w_current, DRAWCIRCLE);
645 o_circle_eraserubber(w_current);
646 break;
648 case(DRAWARC):
649 case(ENDARC):
650 w_current->inside_action = 0;
651 i_set_state(w_current, DRAWARC);
652 o_arc_eraserubber(w_current);
653 break;
655 default:
656 i_callback_cancel(w_current, 0, NULL);
657 break;
659 i_update_toolbar(w_current);
662 return(0);
665 /*! \todo Finish function documentation!!!
666 * \brief
667 * \par Function Description
670 gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
671 TOPLEVEL *w_current)
673 int prev_state;
674 int redraw_state;
675 int w_x, w_y;
677 exit_if_null(w_current);
678 global_window_current = w_current;
680 #if DEBUG
681 printf("released! %d \n", w_current->event_state);
682 #endif
684 w_current->SHIFTKEY = (event->state & GDK_SHIFT_MASK ) ? 1 : 0;
685 w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0;
686 w_current->ALTKEY = (event->state & GDK_MOD1_MASK) ? 1 : 0;
688 if (event->button == 1) {
689 switch(w_current->event_state) {
690 case(SELECT):
691 /* do nothing */
692 break;
694 case(MOVE):
695 w_current->event_state = ENDMOVE;
696 break;
698 case(COPY):
699 w_current->event_state = ENDCOPY;
700 break;
702 case(MCOPY):
703 w_current->event_state = ENDMCOPY;
704 break;
706 case(GRIPS):
707 o_grips_end(w_current),
708 w_current->inside_action = 0;
709 i_set_state(w_current, SELECT);
710 i_update_toolbar(w_current);
711 break;
713 case(ENDMOVE):
714 o_move_end(w_current);
715 /* having this stay in copy was driving me nuts*/
716 w_current->inside_action = 0;
717 i_set_state(w_current, SELECT);
718 i_update_toolbar(w_current);
719 break;
721 case(ENDCOPY):
722 o_copy_end(w_current);
723 /* having this stay in copy was driving me nuts*/
724 w_current->inside_action = 0;
725 i_set_state(w_current, SELECT);
726 i_update_toolbar(w_current);
727 break;
729 case(ENDMCOPY):
730 o_copy_end(w_current);
731 /* having this stay in copy was driving me nuts*/
732 w_current->inside_action = 1;
733 /* Keep the state and the inside_action, as the copy has not finished. */
734 w_current->last_x = w_current->start_x = fix_x(w_current, mouse_x);
735 w_current->last_y = w_current->start_y = fix_y(w_current, mouse_y);
736 i_set_state(w_current, ENDMCOPY);
737 i_update_toolbar(w_current);
738 o_undo_savestate(w_current, UNDO_ALL);
739 break;
741 case(SBOX):
742 /* fix_x,y was removed to allow more flex */
743 w_current->last_x = (int) event->x;
744 w_current->last_y = (int) event->y;
745 /* NEW SELECTION code */
746 o_select_box_end(w_current,
747 (int) event->x,
748 (int) event->y);
749 /* this one stays */
750 w_current->inside_action = 0;
751 i_set_state(w_current, SELECT);
752 i_update_toolbar(w_current);
753 break;
755 case(ZOOMBOXEND):
756 /* fix_x,y was removed to allow more flex */
757 w_current->last_x = (int) event->x;
758 w_current->last_y = (int) event->y;
759 a_zoom_box_end(w_current,
760 (int) event->x,
761 (int) event->y);
762 /* this one stays */
763 w_current->inside_action = 0;
764 i_set_state(w_current, SELECT);
765 i_update_toolbar(w_current);
766 break;
768 case(STARTSELECT):
769 /* first look for grips */
770 if (!o_grips_start(
771 w_current, (int) event->x, (int) event->y)) {
772 /* now go looking for objects to select */
773 o_find_object(w_current,
774 (int) event->x,
775 (int) event->y, TRUE);
776 w_current->event_state = SELECT;
777 w_current->inside_action = 0;
778 } else {
779 /* an grip was found */
780 w_current->event_state = GRIPS;
781 w_current->inside_action = 1;
783 break;
786 } else if (event->button == 2) {
788 if (w_current->inside_action) {
789 if (w_current->event_state == ENDCOMP) {
790 o_drawbounding(w_current,
791 NULL,
792 w_current->page_current->complex_place_list,
793 x_get_darkcolor(w_current->bb_color), TRUE);
795 w_current->complex_rotate =
796 (w_current->complex_rotate + 90) % 360;
798 o_complex_place_rotate(w_current);
800 /* Run the complex place list changed hook without redrawing */
801 /* since all objects are being redrawn afterwards */
802 prev_state = w_current->DONT_REDRAW;
803 w_current->DONT_REDRAW = 1;
804 o_complex_place_changed_run_hook (w_current);
805 w_current->DONT_REDRAW = prev_state;
807 o_drawbounding(w_current,
808 NULL,
809 w_current->page_current->complex_place_list,
810 x_get_darkcolor(w_current->bb_color), TRUE);
811 return(0);
812 } else if (w_current->event_state == ENDTEXT) {
813 o_drawbounding(w_current,
814 w_current->page_current->
815 attrib_place_head->next,
816 NULL,
817 x_get_darkcolor(w_current->bb_color), TRUE);
819 w_current->complex_rotate =
820 (w_current->complex_rotate + 90) % 360;
822 o_text_place_rotate(w_current);
824 o_drawbounding(w_current,
825 w_current->page_current->
826 attrib_place_head->next,
827 NULL,
828 x_get_darkcolor(w_current->bb_color), TRUE);
829 return(0);
832 else if (w_current->event_state == ENDMOVE) {
833 prev_state = w_current->event_state;
835 o_drawbounding(w_current, NULL,
836 w_current->page_current->complex_place_list,
837 x_get_darkcolor(w_current->bb_color), TRUE);
839 /* Don't allow o_rotate_90 to erase the selection, neither to
840 redraw the objects after rotating */
841 /* skip over head node */
842 redraw_state = w_current->DONT_REDRAW;
843 w_current->DONT_REDRAW = 1;
844 SCREENtoWORLD( w_current,
845 w_current->start_x, w_current->start_y,
846 &w_x, &w_y );
847 w_x = snap_grid(w_current, w_x);
848 w_y = snap_grid(w_current, w_y);
849 o_rotate_90_world(w_current, w_current->page_current->complex_place_list, w_x, w_y );
850 w_current->DONT_REDRAW = redraw_state;
851 w_current->rotated_inside ++;
852 w_current->event_state = prev_state;
854 o_drawbounding(w_current, NULL,
855 w_current->page_current->complex_place_list,
856 x_get_darkcolor(w_current->bb_color), TRUE);
858 return(0);
860 else if ((w_current->event_state == ENDCOPY) ||
861 (w_current->event_state == ENDMCOPY)) {
862 /* Rotating while copying is still not supported, so do nothing */
863 return 0;
868 switch(w_current->middle_button) {
869 case(ACTION):
870 switch(w_current->event_state) {
871 case(MOVE):
872 o_move_end(w_current);
873 w_current->inside_action = 0;
874 i_set_state(w_current, SELECT);
875 i_update_toolbar(w_current);
876 break;
878 case(COPY):
879 o_copy_end(w_current);
880 w_current->inside_action = 0;
881 i_set_state(w_current, SELECT);
882 i_update_toolbar(w_current);
883 break;
885 break;
887 #ifdef HAS_LIBSTROKE
888 case(STROKE):
890 DOING_STROKE = FALSE;
892 if (stroke_trans (sequence) == TRUE) {
893 if (stroke_info_mode) {
894 printf ("LibStroke Translation"
895 " succeeded: ");
897 } else {
898 if (stroke_info_mode) {
899 printf ("LibStroke Translation"
900 " failed: ");
904 if (stroke_info_mode) {
905 printf ("Sequence=\"%s\"\n",sequence);
908 /* new way written by Stefan Petersen */
909 /* much better */
910 if (x_stroke_search_execute(sequence)) {
912 if (stroke_info_mode) {
913 printf("Sequence understood\n");
915 x_stroke_erase_all(w_current);
917 break;
918 #endif
920 case(MID_MOUSEPAN_ENABLED):
921 w_current->doing_pan=FALSE;
922 o_redraw_all_fast(w_current);
923 o_undo_savestate(w_current, UNDO_VIEWPORT_ONLY);
924 /* this needs to be REDONE */
925 /* if you mouse pan, you will be thrown out of the current mode. */
926 /* not good */
927 w_current->inside_action = 0;
928 i_set_state(w_current, SELECT);
929 i_update_toolbar(w_current);
930 break;
933 } else if (event->button == 3) {
934 if (w_current->doing_pan) { /* just for ending a mouse pan */
935 w_current->doing_pan=FALSE;
936 o_redraw_all_fast(w_current);
937 o_undo_savestate(w_current, UNDO_VIEWPORT_ONLY);
938 /* this needs to be REDONE */
939 /* if you mouse pan, you will be thrown out of the current mode. */
940 /* not good */
941 w_current->inside_action = 0;
942 i_set_state(w_current, SELECT);
943 i_update_toolbar(w_current);
946 return(0);
949 /*! \todo Finish function documentation!!!
950 * \brief
951 * \par Function Description
954 gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
955 TOPLEVEL *w_current)
957 int temp_x, temp_y;
958 int pdiff_x, pdiff_y;
960 int zoom_scale;
961 int diff_x;
962 int skip_event=0;
963 GdkEvent *test_event;
965 exit_if_null(w_current);
966 global_window_current = w_current;
968 w_current->SHIFTKEY = (event->state & GDK_SHIFT_MASK ) ? 1 : 0;
969 w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0;
970 w_current->ALTKEY = (event->state & GDK_MOD1_MASK) ? 1 : 0;
972 #if DEBUG
973 /* printf("MOTION!\n");*/
974 #endif
976 #ifdef HAS_LIBSTROKE
977 if (DOING_STROKE == TRUE) {
978 x_stroke_add_point(w_current, (int) event->x, (int) event->y);
980 stroke_record ((int) event->x, (int) event->y);
981 return(0);
983 #endif
985 /* skip the moving event if there are other moving events in the
986 gdk event queue (Werner)
987 Only skip the event if is the same event and no buttons or modifier
988 keys changed*/
989 if ((test_event = gdk_event_get()) != NULL) {
990 if (test_event->type == GDK_MOTION_NOTIFY
991 && ((GdkEventMotion *) test_event)->state == event->state) {
992 skip_event= 1;
994 gdk_event_put(test_event); /* put it back in front of the queue */
995 gdk_event_free(test_event);
996 if (skip_event == 1)
997 return 0;
1000 mouse_x = (int) event->x;
1001 mouse_y = (int) event->y;
1003 if (w_current->cowindow) {
1004 coord_display_update(w_current, mouse_x, mouse_y);
1007 if (w_current->third_button == MOUSEPAN_ENABLED || w_current->middle_button == MID_MOUSEPAN_ENABLED) {
1008 if((w_current->event_state == MOUSEPAN) &&
1009 w_current->inside_action) {
1010 pdiff_x = mouse_x - start_pan_x;
1011 pdiff_y = mouse_y - start_pan_y;
1013 if (!(throttle % 5)) {
1014 a_pan_mouse(w_current, pdiff_x*w_current->mousepan_gain,
1015 pdiff_y*w_current->mousepan_gain);
1017 start_pan_x = (int) event->x;
1018 start_pan_y = (int) event->y;
1020 throttle++;
1021 return(0);
1025 switch(w_current->event_state) {
1027 case(SELECT):
1028 /* do nothing */
1029 break;
1031 case(GRIPS):
1032 o_grips_motion(w_current, (int) event->x, (int) event->y);
1033 break;
1035 case(STARTSELECT):
1036 if ( (!w_current->drag_can_move) ||
1037 (w_current->drag_can_move &&
1038 (! o_find_selected_object(w_current,
1039 w_current->start_x, w_current->start_y)))) {
1040 temp_x = fix_x(w_current, (int) event->x);
1041 temp_y = fix_y(w_current, (int) event->y);
1042 /* is eight enough of a threshold? */
1043 /* make this configurable anyways */
1044 diff_x = fabs(w_current->page_current->right -
1045 w_current->page_current->left);
1047 #ifdef HAS_RINT
1048 zoom_scale = (int) rint(w_current->init_right / diff_x);
1049 #else
1050 zoom_scale = (int) w_current->init_right / diff_x;
1051 #endif
1053 if (zoom_scale < 10) {
1054 zoom_scale = 10;
1057 if ( (abs(temp_x - w_current->start_x) > zoom_scale) ||
1058 (abs(temp_y - w_current->start_y) > zoom_scale) ) {
1059 w_current->event_state = SBOX;
1060 /* NEW SELECTION code */
1061 o_select_box_start(w_current,
1062 (int) event->x,
1063 (int) event->y);
1064 w_current->inside_action = 1;
1066 break;
1068 else {
1069 /* Start the object movement */
1070 w_current->rotated_inside = 0;
1071 o_move_start(w_current,
1072 (int) event->x, (int) event->y);
1073 w_current->event_state = ENDMOVE;
1074 w_current->inside_action = 1;
1076 /* Continue to the MOVE actions */
1077 /* Important!! keep the MOVE and ENDMOVE cases below this
1078 without the break statement!! */
1081 case(ENDMOVE):
1082 case(MOVE):
1083 if (w_current->inside_action) {
1085 if (w_current->netconn_rubberband) {
1086 o_move_stretch_rubberband(w_current);
1089 o_complex_rubbercomplex(w_current);
1090 w_current->last_x = fix_x(w_current, (int) event->x);
1091 w_current->last_y = fix_y(w_current, (int) event->y);
1092 o_complex_rubbercomplex(w_current);
1093 if (w_current->netconn_rubberband) {
1094 o_move_stretch_rubberband(w_current);
1098 break;
1100 case(ENDCOPY):
1101 case(COPY):
1102 case(ENDMCOPY):
1103 case(MCOPY):
1104 if (w_current->inside_action) {
1105 o_drawbounding(w_current, NULL,
1106 geda_list_get_glist( w_current->page_current->selection_list ),
1107 x_get_darkcolor(w_current->bb_color), FALSE);
1108 w_current->last_x = fix_x(w_current, (int) event->x);
1109 w_current->last_y = fix_y(w_current, (int) event->y);
1110 o_drawbounding(w_current, NULL,
1111 geda_list_get_glist( w_current->page_current->selection_list ),
1112 x_get_darkcolor(w_current->bb_color), FALSE);
1114 break;
1116 case(ENDLINE):
1117 if (w_current->inside_action)
1118 o_line_rubberline(w_current,
1119 (int) event->x,
1120 (int) event->y);
1121 break;
1123 case(ENDBOX):
1124 if (w_current->inside_action)
1125 o_box_rubberbox( w_current,
1126 (int) event->x,
1127 (int) event->y);
1128 break;
1130 case(ENDPICTURE):
1131 if (w_current->inside_action)
1132 o_picture_rubberbox( w_current,
1133 (int) event->x,
1134 (int) event->y);
1135 break;
1137 case(ENDCIRCLE):
1138 if (w_current->inside_action)
1139 o_circle_rubbercircle(w_current,
1140 (int) event->x,
1141 (int) event->y);
1142 break;
1144 case(ENDARC):
1145 if (w_current->inside_action)
1146 /* pb20011022 - changed name to _rubberarc() and added a parameter */
1147 o_arc_rubberarc(w_current,
1148 (int) event->x,
1149 (int) event->y, ARC_RADIUS);
1150 break;
1152 case(DRAWNET):
1153 case(NETCONT):
1154 if (w_current->inside_action)
1155 o_net_rubbernet(w_current,
1156 (int) event->x,
1157 (int) event->y);
1158 break;
1160 case(DRAWBUS):
1161 case(BUSCONT):
1162 if (w_current->inside_action)
1163 o_bus_rubberbus(w_current,
1164 (int) event->x,
1165 (int) event->y);
1166 break;
1168 case(ENDPIN):
1169 if (w_current->inside_action)
1170 o_pin_rubberpin(w_current,
1171 (int) event->x,
1172 (int) event->y);
1173 break;
1175 case(DRAWCOMP):
1176 w_current->complex_rotate = 0; /* reset to known state */
1177 o_complex_start(w_current,
1178 (int) event->x,
1179 (int) event->y);
1180 w_current->event_state = ENDCOMP;
1181 w_current->inside_action = 1;
1182 break;
1184 case(ENDCOMP):
1185 o_complex_rubbercomplex(w_current);
1186 w_current->last_x = fix_x(w_current, (int) event->x);
1187 w_current->last_y = fix_y(w_current, (int) event->y);
1188 o_complex_rubbercomplex(w_current);
1189 break;
1191 case(ENDPASTE):
1192 o_buffer_paste_rubberpaste(w_current, w_current->buffer_number);
1193 w_current->last_x = fix_x(w_current, (int) event->x);
1194 w_current->last_y = fix_y(w_current, (int) event->y);
1195 o_buffer_paste_rubberpaste(w_current, w_current->buffer_number);
1196 break;
1198 case(DRAWATTRIB):
1199 o_attrib_start(w_current, (int) event->x, (int) event->y);
1200 w_current->event_state = ENDATTRIB;
1201 w_current->inside_action = 1;
1202 break;
1204 case(DRAWTEXT):
1205 w_current->complex_rotate = 0; /* reset to known state */
1206 o_text_start(w_current, (int) event->x, (int) event->y);
1207 w_current->event_state = ENDTEXT;
1208 w_current->inside_action = 1;
1209 break;
1211 case(ENDATTRIB):
1212 o_attrib_rubberattrib(w_current);
1213 w_current->last_x = fix_x(w_current, (int) event->x);
1214 w_current->last_y = fix_y(w_current, (int) event->y);
1215 o_attrib_rubberattrib(w_current);
1216 break;
1218 case(ENDTEXT):
1219 o_text_rubberattrib(w_current);
1220 w_current->last_x = fix_x(w_current, (int) event->x);
1221 w_current->last_y = fix_y(w_current, (int) event->y);
1222 o_text_rubberattrib(w_current);
1223 break;
1225 case(SBOX):
1226 if (w_current->inside_action)
1227 /* NEW SELECTION code */
1228 o_select_box_rubberband(w_current,
1229 (int) event->x,
1230 (int) event->y);
1231 break;
1233 case(ZOOMBOXEND):
1234 if (w_current->inside_action)
1235 a_zoom_box_rubberband( w_current,
1236 (int) event->x,
1237 (int) event->y);
1238 break;
1241 return(0);
1244 /*! \brief Updates the toplevel and display when drawing area is configured.
1245 * \par Function Description
1246 * This is the callback function connected to the configure event of
1247 * the drawing area of the main window.
1249 * It updates the size of the backingstore for the associated
1250 * toplevel structure (creates a new pixmap) and re-pans each of its
1251 * pages to keep their contents centered in the drawing area.
1253 * When the window is maximised, the zoom of every page is changed to
1254 * best fit the previously displayed area of the page in the new
1255 * area. Otherwise the current zoom level is left unchanged.
1257 * \param [in] widget The drawing area which received the signal.
1258 * \param [in] event The event structure of signal configure-event.
1259 * \param [in] user_data The toplevel environment as user data.
1260 * \returns FALSE to propagate the event further.
1262 gboolean
1263 x_event_configure (GtkWidget *widget,
1264 GdkEventConfigure *event,
1265 gpointer user_data)
1267 TOPLEVEL *toplevel = (TOPLEVEL*)user_data;
1268 PAGE *old_page_current, *p_current;
1269 gint old_win_width, old_win_height, new_win_width, new_win_height;
1270 gdouble relativ_zoom_factor = 1.0;
1272 g_assert (toplevel != NULL);
1273 global_window_current = toplevel;
1275 if (toplevel->page_current == NULL) {
1276 /* don't want to call this if the current page isn't setup yet */
1277 return FALSE;
1280 old_win_width = toplevel->win_width;
1281 old_win_height = toplevel->win_height;
1282 new_win_width = event->width;
1283 new_win_height = event->height;
1285 if (old_win_width == new_win_width &&
1286 old_win_height == new_win_height) {
1287 /* the size of the drawing area has not changed */
1288 /* nothing to do here */
1289 return FALSE;
1292 /* update the backingstore of toplevel */
1293 if (toplevel->backingstore != NULL) {
1294 gdk_pixmap_unref (toplevel->backingstore);
1296 toplevel->backingstore = gdk_pixmap_new (widget->window,
1297 new_win_width,
1298 new_win_height,
1299 -1);
1300 /* update the toplevel with new size of drawing area */
1301 toplevel->win_width = toplevel->width = new_win_width;
1302 toplevel->win_height = toplevel->height = new_win_height;
1305 /* in the case the user has maximised the window (hence the */
1306 /* configure event) fit the view by playing with zoom level */
1307 if (gdk_window_get_state (
1308 (gtk_widget_get_toplevel (
1309 widget))->window) & GDK_WINDOW_STATE_MAXIMIZED) {
1310 gdouble width_ratio, height_ratio;
1312 /* tweak relative_zoom to better fit page in maximized window */
1313 width_ratio = ((gdouble)new_win_width) / ((gdouble)old_win_width);
1314 height_ratio = ((gdouble)new_win_height) / ((gdouble)old_win_height);
1315 /* keep smallest ratio as relative zoom factor when panning */
1316 relativ_zoom_factor =
1317 (width_ratio < height_ratio) ? width_ratio : height_ratio;
1321 /* save current page */
1322 old_page_current = toplevel->page_current;
1323 /* re-pan each page of the toplevel */
1324 for (p_current = toplevel->page_head->next;
1325 p_current != NULL;
1326 p_current = p_current->next) {
1327 gdouble cx, cy;
1329 /* doing this the aspectratio is kept when changing (hw)*/
1330 cx = ((gdouble)(p_current->left + p_current->right)) / 2;
1331 cy = ((gdouble)(p_current->top + p_current->bottom)) / 2;
1332 s_page_goto (toplevel, p_current);
1333 a_pan_general (toplevel, cx, cy, relativ_zoom_factor, A_PAN_DONT_REDRAW);
1336 /* restore current page to saved value */
1337 s_page_goto (toplevel, old_page_current);
1339 if (!toplevel->DONT_REDRAW) {
1340 /* redraw the current page and update UI */
1341 o_redraw_all_fast (toplevel);
1342 x_scrollbars_update (toplevel);
1345 return FALSE;
1348 /*! \todo Finish function documentation!!!
1349 * \brief
1350 * \par Function Description
1352 * \note
1353 * this is used during an open command
1354 * to setup the correct sizes
1356 void x_manual_resize(TOPLEVEL *w_current)
1359 /* of the actual win window (drawing_area) */
1360 w_current->win_width = w_current->drawing_area->allocation.width;
1361 w_current->win_height = w_current->drawing_area->allocation.height;
1363 #if DEBUG
1364 printf("manual: %d %d\n", w_current->win_width, w_current->win_height);
1365 #endif
1367 w_current->width = w_current->win_width;
1368 w_current->height = w_current->win_height;
1370 /* need to do this every time you change width / height */
1371 set_window(w_current, w_current->page_current,
1372 w_current->page_current->left,
1373 w_current->page_current->right,
1374 w_current->page_current->top,
1375 w_current->page_current->bottom);
1377 #if DEBUG
1378 printf("Window aspect: %f\n",
1379 (float) w_current->win_width / (float) w_current->win_height);
1380 /* No longer used?
1381 printf("w: %d h: %d\n", width, height); */
1382 printf("aw: %d ah: %d\n", w_current->win_width, w_current->win_height);
1383 #endif
1385 /* I'm assuming that the backingstore pixmap is of the right
1386 * size */
1389 /*! \todo Finish function documentation!!!
1390 * \brief
1391 * \par Function Description
1394 void x_event_hschanged (GtkAdjustment *adj, TOPLEVEL *w_current)
1396 int current_left;
1397 int new_left;
1398 GtkAdjustment *hadjustment;
1400 exit_if_null(w_current);
1401 global_window_current = w_current;
1403 if (w_current->scrollbars_flag == FALSE) {
1404 return;
1407 hadjustment =
1408 gtk_range_get_adjustment(GTK_RANGE(w_current->h_scrollbar));
1410 current_left = w_current->page_current->left;
1411 new_left = (int) hadjustment->value;
1413 if (!w_current->DONT_RECALC) {
1414 w_current->page_current->left = new_left;
1415 w_current->page_current->right =
1416 w_current->page_current->right -
1417 (current_left - new_left);
1420 if (!w_current->DONT_REDRAW) {
1421 o_redraw_all_fast(w_current);
1425 /*! \todo Finish function documentation!!!
1426 * \brief
1427 * \par Function Description
1430 void x_event_vschanged (GtkAdjustment *adj, TOPLEVEL *w_current)
1432 int current_bottom;
1433 int new_bottom;
1434 GtkAdjustment *vadjustment;
1436 exit_if_null(w_current);
1437 global_window_current = w_current;
1439 if (w_current->scrollbars_flag == FALSE) {
1440 return;
1443 vadjustment = gtk_range_get_adjustment(
1444 GTK_RANGE(w_current->v_scrollbar));
1446 current_bottom = w_current->page_current->bottom;
1447 new_bottom = w_current->init_bottom - (int) vadjustment->value;
1449 if (!w_current->DONT_RECALC) {
1450 w_current->page_current->bottom = new_bottom;
1451 w_current->page_current->top =
1452 w_current->page_current->top -
1453 (current_bottom - new_bottom);
1456 #if DEBUG
1457 printf("vrange %f %f\n", vadjustment->lower, vadjustment->upper);
1458 printf("vvalue %f\n", vadjustment->value);
1459 printf("actual: %d %d\n", w_current->page_current->top,
1460 w_current->page_current->bottom);
1461 #endif
1463 if (!w_current->DONT_REDRAW) {
1464 o_redraw_all_fast(w_current);
1468 /*! \todo Finish function documentation!!!
1469 * \brief
1470 * \par Function Description
1473 gint x_event_enter(GtkWidget *widget, GdkEventCrossing *event,
1474 TOPLEVEL *w_current)
1476 exit_if_null(w_current);
1477 global_window_current = w_current;
1478 /* do nothing or now */
1479 return(0);
1482 /*! \todo Finish function documentation!!!
1483 * \brief
1484 * \par Function Description
1487 gboolean x_event_key_press (GtkWidget *widget, GdkEventKey *event,
1488 TOPLEVEL *w_current)
1490 int retval;
1492 retval = FALSE;
1494 exit_if_null(w_current);
1495 global_window_current = w_current;
1497 if (event) {
1498 #if DEBUG
1499 printf("x_event_key_pressed: Pressed key %i.\n", event->keyval);
1500 #endif
1501 retval = g_keys_execute(event->state, event->keyval) ? TRUE : FALSE;
1504 return retval;
1508 /*! \todo Finish function documentation!!!
1509 * \brief
1510 * \par Function Description
1513 gint x_event_scroll (GtkWidget *widget, GdkEventScroll *event,
1514 TOPLEVEL *w_current)
1516 GtkAdjustment *adj;
1518 exit_if_null(w_current);
1519 global_window_current = w_current;
1521 /* update the state of the modifiers */
1522 w_current->SHIFTKEY = (event->state & GDK_SHIFT_MASK ) ? 1 : 0;
1523 w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0;
1524 w_current->ALTKEY = (event->state & GDK_MOD1_MASK) ? 1 : 0;
1526 switch (event->direction) {
1527 case(GDK_SCROLL_UP):
1528 if (!w_current->CONTROLKEY && !w_current->SHIFTKEY)
1530 /* turn the up/down scroll wheel into a zoom in / out */
1531 /*! \todo Change "HOTKEY" TO new "MOUSE" specifier?
1533 a_zoom(w_current, ZOOM_IN, HOTKEY, 0);
1534 o_undo_savestate(w_current, UNDO_VIEWPORT_ONLY);
1535 } else if ( !w_current->CONTROLKEY ) {
1536 /* if the control key is not held down, scroll up / down */
1537 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1538 if (w_current->scrollbars_flag == FALSE )
1539 return 0;
1540 adj = gtk_range_get_adjustment(GTK_RANGE(w_current->v_scrollbar));
1541 gtk_adjustment_set_value(adj, adj->value - (adj->page_increment / 4));
1542 } else {
1543 /* if the control key is held down, then scroll left as well */
1544 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1545 if (w_current->scrollbars_flag == FALSE )
1546 return 0;
1547 adj = gtk_range_get_adjustment(GTK_RANGE(w_current->h_scrollbar));
1548 gtk_adjustment_set_value(adj, adj->value - (adj->page_increment / 4));
1550 break;
1552 case(GDK_SCROLL_DOWN):
1553 if (!w_current->CONTROLKEY && !w_current->SHIFTKEY)
1555 /* turn the up/down scroll wheel into a zoom in / out */
1556 /*! \todo Change "HOTKEY" TO new "MOUSE" specifier?
1558 a_zoom(w_current, ZOOM_OUT, HOTKEY, 0);
1559 o_undo_savestate(w_current, UNDO_VIEWPORT_ONLY);
1560 } else if ( !w_current->CONTROLKEY ) {
1561 /* if the control key is not held down, scroll up / down */
1562 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1563 if (w_current->scrollbars_flag == FALSE )
1564 return 0;
1565 adj = gtk_range_get_adjustment(GTK_RANGE(w_current->v_scrollbar));
1566 gtk_adjustment_set_value(adj, min(adj->value + (adj->page_increment / 4),
1567 adj->upper - adj->page_size));
1568 } else {
1569 /* if the control key is held down, then scroll right as well */
1570 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1571 if (w_current->scrollbars_flag == FALSE )
1572 return 0;
1573 adj = gtk_range_get_adjustment(GTK_RANGE(w_current->h_scrollbar));
1574 gtk_adjustment_set_value(adj, min(adj->value + (adj->page_increment / 4),
1575 adj->upper - adj->page_size));
1577 break;
1579 case(GDK_SCROLL_LEFT):
1580 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1581 if (w_current->scrollbars_flag == FALSE)
1582 return 0;
1583 adj = gtk_range_get_adjustment(GTK_RANGE(w_current->h_scrollbar));
1584 gtk_adjustment_set_value(adj, adj->value - (adj->page_increment / 4));
1585 break;
1587 case(GDK_SCROLL_RIGHT):
1588 /* You must have scrollbars enabled if you want to use the scroll wheel to pan */
1589 if (w_current->scrollbars_flag == FALSE)
1590 return 0;
1591 adj = gtk_range_get_adjustment(GTK_RANGE(w_current->h_scrollbar));
1592 gtk_adjustment_set_value(adj, min(adj->value + (adj->page_increment / 4),
1593 adj->upper - adj->page_size));
1594 break;
1598 return(0);