14 #include "xincludes.h"
19 #include "crosshair.h"
22 #include "pcb-printf.h"
29 #include "../hidint.h"
30 #include "hid/common/hidnogui.h"
31 #include "hid/common/draw_helpers.h"
32 #include "hid/common/hid_resource.h"
35 #ifdef HAVE_LIBDMALLOC
42 #define XtRDouble "Double"
45 /* How big the viewport can be relative to the pcb size. */
46 #define MAX_ZOOM_SCALE 10
47 #define UUNIT Settings.grid_unit->allow
49 typedef struct hid_gc_struct
53 const char *colorname
;
60 static HID lesstif_hid
;
61 static HID_DRAW lesstif_graphics
;
63 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented GUI function %s\n", __FUNCTION__), abort()
65 XtAppContext app_context
;
68 static Window window
= 0;
69 static Cursor my_cursor
= 0;
70 static int old_cursor_mode
= -1;
71 static int over_point
= 0;
73 /* The first is the "current" pixmap. The main_ is the real one we
74 usually use, the mask_ are the ones for doing polygon masks. The
75 pixmap is the saved pixels, the bitmap is for the "erase" color.
76 We set pixmap to point to main_pixmap or mask_pixmap as needed. */
77 static Pixmap pixmap
= 0;
78 static Pixmap main_pixmap
= 0;
79 static Pixmap mask_pixmap
= 0;
80 static Pixmap mask_bitmap
= 0;
81 static int use_mask
= 0;
83 static int use_xrender
= 0;
85 static Picture main_picture
;
86 static Picture mask_picture
;
87 static Pixmap pale_pixmap
;
88 static Picture pale_picture
;
89 #endif /* HAVE_XRENDER */
91 static int pixmap_w
= 0, pixmap_h
= 0;
94 static Colormap colormap
;
95 static GC my_gc
= 0, bg_gc
, clip_gc
= 0, bset_gc
= 0, bclear_gc
= 0, mask_gc
=
97 static Pixel bgcolor
, offlimit_color
, grid_color
;
98 static int bgred
, bggreen
, bgblue
;
100 static GC arc1_gc
, arc2_gc
;
102 /* These are for the pinout windows. */
103 typedef struct PinoutData
105 struct PinoutData
*prev
, *next
;
108 Coord left
, right
, top
, bottom
; /* PCB extents of item */
109 Coord x
, y
; /* PCB coordinates of upper right corner of window */
110 double zoom
; /* PCB units per screen pixel */
111 int v_width
, v_height
; /* pixels */
115 /* Linked list of all pinout windows. */
116 static PinoutData
*pinouts
= 0;
117 /* If set, we are currently updating this pinout window. */
118 static PinoutData
*pinout
= 0;
120 static int crosshair_x
= 0, crosshair_y
= 0;
121 static int in_move_event
= 0, crosshair_in_window
= 1;
124 Widget work_area
, messages
, command
, hscroll
, vscroll
;
125 static Widget m_mark
, m_crosshair
, m_grid
, m_zoom
, m_mode
, m_status
;
126 static Widget m_rats
;
127 Widget lesstif_m_layer
;
130 /* This is the size, in pixels, of the viewport. */
131 static int view_width
, view_height
;
132 /* This is the PCB location represented by the upper left corner of
133 the viewport. Note that PCB coordinates put 0,0 in the upper left,
135 static int view_left_x
= 0, view_top_y
= 0;
136 /* Denotes PCB units per screen pixel. Larger numbers mean zooming
137 out - the largest value means you are looking at the whole
139 static double view_zoom
= MIL_TO_COORD (10), prev_view_zoom
= MIL_TO_COORD (10);
140 static bool flip_x
= 0, flip_y
= 0;
141 static bool autofade
= 0;
142 static bool crosshair_on
= true;
145 ShowCrosshair (bool show
)
147 if (crosshair_on
== show
)
150 notify_crosshair_change (false);
152 notify_mark_change (false);
156 notify_crosshair_change (true);
158 notify_mark_change (true);
162 flag_flipx (void *data
)
167 flag_flipy (void *data
)
172 HID_Flag lesstif_main_flag_list
[] = {
173 {"flip_x", flag_flipx
, NULL
},
174 {"flip_y", flag_flipy
, NULL
}
177 REGISTER_FLAGS (lesstif_main_flag_list
)
179 /* This is the size of the current PCB work area. */
180 /* Use PCB->MaxWidth, PCB->MaxHeight. */
181 /* static int pcb_width, pcb_height; */
185 #define stdarg(t,v) XtSetArg(args[n], t, v), n++
188 static int use_private_colormap
= 0;
189 static int stdin_listen
= 0;
190 static char *background_image_file
= 0;
191 char *lesstif_pcbmenu_path
= "pcb-menu.res";
193 HID_Attribute lesstif_attribute_list
[] = {
194 {"install", "Install private colormap",
195 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &use_private_colormap
},
196 #define HA_colormap 0
198 /* %start-doc options "22 lesstif GUI Options"
201 Listen for actions on stdin.
205 {"listen", "Listen on standard input for actions",
206 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &stdin_listen
},
209 /* %start-doc options "22 lesstif GUI Options"
211 @item --bg-image <string>
212 File name of an image to put into the background of the GUI canvas. The image must
213 be a color PPM image, in binary (not ASCII) format. It can be any size, and will be
214 automatically scaled to fit the canvas.
218 {"bg-image", "Background Image",
219 HID_String
, 0, 0, {0, 0, 0}, 0, &background_image_file
},
220 #define HA_bg_image 2
222 /* %start-doc options "22 lesstif GUI Options"
224 @item --pcb-menu <string>
225 Location of the @file{pcb-menu.res} file which defines the menu for the lesstif GUI.
229 {"pcb-menu", "Location of pcb-menu.res file",
230 HID_String
, 0, 0, {0, PCBLIBDIR
"/pcb-menu.res", 0}, 0, &lesstif_pcbmenu_path
}
234 REGISTER_ATTRIBUTES (lesstif_attribute_list
)
236 static void lesstif_use_mask (int use_it
);
237 static void zoom_max ();
238 static void zoom_to (double factor
, int x
, int y
);
239 static void zoom_by (double factor
, int x
, int y
);
240 static void zoom_toggle (int x
, int y
);
241 static void pinout_callback (Widget
, PinoutData
*,
242 XmDrawingAreaCallbackStruct
*);
243 static void pinout_unmap (Widget
, PinoutData
*, void *);
244 static void Pan (int mode
, int x
, int y
);
246 /* Px converts view->pcb, Vx converts pcb->view */
251 int rv
= (x
- view_left_x
) / view_zoom
+ 0.5;
253 rv
= view_width
- rv
;
260 int rv
= (y
- view_top_y
) / view_zoom
+ 0.5;
262 rv
= view_height
- rv
;
269 return z
/ view_zoom
+ 0.5;
277 return x
* view_zoom
+ view_left_x
;
285 return y
* view_zoom
+ view_top_y
;
291 return z
* view_zoom
;
295 lesstif_coords_to_pcb (int vx
, int vy
, Coord
*px
, Coord
*py
)
302 lesstif_parse_color (char *value
)
305 if (XParseColor (display
, colormap
, value
, &color
))
306 if (XAllocColor (display
, colormap
, &color
))
312 do_color (char *value
, char *which
)
315 if (XParseColor (display
, colormap
, value
, &color
))
316 if (XAllocColor (display
, colormap
, &color
))
318 stdarg (which
, color
.pixel
);
322 /* ------------------------------------------------------------ */
327 if (TEST_FLAG (ORTHOMOVEFLAG
, PCB
))
329 if (TEST_FLAG (ALLDIRECTIONFLAG
, PCB
))
331 if (PCB
->Clipping
== 0)
333 if (PCB
->Clipping
== 1)
338 /* Called from the core when it's busy doing something and we need to
339 indicate that to the user. */
341 Busy(int argc
, char **argv
, Coord x
, Coord y
)
343 static Cursor busy_cursor
= 0;
344 if (busy_cursor
== 0)
345 busy_cursor
= XCreateFontCursor (display
, XC_watch
);
346 XDefineCursor (display
, window
, busy_cursor
);
348 old_cursor_mode
= -1;
352 /* ---------------------------------------------------------------------- */
357 PointCursor (int argc
, char **argv
, Coord x
, Coord y
)
363 old_cursor_mode
= -1;
368 PCBChanged (int argc
, char **argv
, Coord x
, Coord y
)
372 /*pcb_printf("PCB Changed! %$mD\n", PCB->MaxWidth, PCB->MaxHeight); */
374 stdarg (XmNminimum
, 0);
375 stdarg (XmNvalue
, 0);
376 stdarg (XmNsliderSize
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
377 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
378 XtSetValues (hscroll
, args
, n
);
380 stdarg (XmNminimum
, 0);
381 stdarg (XmNvalue
, 0);
382 stdarg (XmNsliderSize
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
383 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
384 XtSetValues (vscroll
, args
, n
);
387 hid_action ("NetlistChanged");
388 hid_action ("LayersChanged");
389 hid_action ("RouteStylesChanged");
390 lesstif_sizes_reset ();
391 lesstif_update_layer_groups ();
393 pinout_unmap (0, pinouts
, 0);
396 char *cp
= strrchr (PCB
->Filename
, '/');
398 stdarg (XmNtitle
, cp
? cp
+ 1 : PCB
->Filename
);
399 XtSetValues (appwidget
, args
, n
);
405 static const char setunits_syntax
[] =
408 static const char setunits_help
[] =
409 "Set the default measurement units.";
411 /* %start-doc actions SetUnits
416 Sets the display units to mils (1/1000 inch).
419 Sets the display units to millimeters.
426 SetUnits (int argc
, char **argv
, Coord x
, Coord y
)
428 const Unit
*new_unit
;
431 new_unit
= get_unit_struct (argv
[0]);
432 if (new_unit
!= NULL
&& new_unit
->allow
!= NO_PRINT
)
434 Settings
.grid_unit
= new_unit
;
435 Settings
.increments
= get_increments_struct (Settings
.grid_unit
->family
);
436 AttributePut (PCB
, "PCB::grid::unit", argv
[0]);
438 lesstif_sizes_reset ();
439 lesstif_styles_update_values ();
443 static const char zoom_syntax
[] =
447 static const char zoom_help
[] =
448 "Various zoom factor changes.";
450 /* %start-doc actions Zoom
452 Changes the zoom (magnification) of the view of the board. If no
453 arguments are passed, the view is scaled such that the board just fits
454 inside the visible window (i.e. ``view all''). Otherwise,
455 @var{factor} specifies a change in zoom factor. It may be prefixed by
456 @code{+}, @code{-}, or @code{=} to change how the zoom factor is
457 modified. The @var{factor} is a floating point number, such as
458 @code{1.5} or @code{0.75}.
463 Values greater than 1.0 cause the board to be drawn smaller; more of
464 the board will be visible. Values between 0.0 and 1.0 cause the board
465 to be drawn bigger; less of the board will be visible.
468 Values greater than 1.0 cause the board to be drawn bigger; less of
469 the board will be visible. Values between 0.0 and 1.0 cause the board
470 to be drawn smaller; more of the board will be visible.
474 The @var{factor} is an absolute zoom factor; the unit for this value
475 is "PCB units per screen pixel". Since PCB units are 0.01 mil, a
476 @var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI,
477 about the actual resolution of most screens - resulting in an "actual
478 size" board. Similarly, a @var{factor} of 100 gives you a 10x actual
483 Note that zoom factors of zero are silently ignored.
488 ZoomAction (int argc
, char **argv
, Coord x
, Coord y
)
492 if (x
== 0 && y
== 0)
508 if (strcasecmp (vp
, "toggle") == 0)
513 if (*vp
== '+' || *vp
== '-' || *vp
== '=')
515 v
= g_ascii_strtod (vp
, 0);
521 zoom_by (1 / v
, x
, y
);
534 static int pan_thumb_mode
;
537 PanAction (int argc
, char **argv
, Coord x
, Coord y
)
543 pan_thumb_mode
= (strcasecmp (argv
[0], "thumb") == 0) ? 1 : 0;
544 mode
= atoi (argv
[1]);
549 mode
= atoi (argv
[0]);
551 Pan (mode
, Vx(x
), Vy(y
));
556 static const char swapsides_syntax
[] =
559 static const char swapsides_help
[] =
560 "Swaps the side of the board you're looking at.";
562 /* %start-doc actions SwapSides
564 This action changes the way you view the board.
569 Flips the board over vertically (up/down).
572 Flips the board over horizontally (left/right), like flipping pages in
576 Rotates the board 180 degrees without changing sides.
580 If no argument is given, the board isn't moved but the opposite side
583 Normally, this action changes which pads and silk layer are drawn as
584 true silk, and which are drawn as the "invisible" layer. It also
585 determines which solder mask you see.
587 As a special case, if the layer group for the side you're looking at
588 is visible and currently active, and the layer group for the opposite
589 is not visible (i.e. disabled), then this action will also swap which
590 layer group is visible and active, effectively swapping the ``working
596 group_showing (int g
, int *c
)
599 *c
= PCB
->LayerGroups
.Entries
[g
][0];
600 for (i
=0; i
<PCB
->LayerGroups
.Number
[g
]; i
++)
602 l
= PCB
->LayerGroups
.Entries
[g
][i
];
603 if (l
>= 0 && l
< max_copper_layer
)
606 if (PCB
->Data
->Layer
[l
].On
)
614 SwapSides (int argc
, char **argv
, Coord x
, Coord y
)
616 int old_shown_side
= Settings
.ShowBottomSide
;
617 int top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
618 int bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
619 int active_group
= GetLayerGroupNumberByNumber (LayerStack
[0]);
622 int top_showing
= group_showing (top_group
, &top_layer
);
623 int bottom_showing
= group_showing (bottom_group
, &bottom_layer
);
627 switch (argv
[0][0]) {
644 /* SwapSides will swap this */
645 Settings
.ShowBottomSide
= (flip_x
== flip_y
);
650 stdarg (XmNprocessingDirection
, XmMAX_ON_LEFT
);
652 stdarg (XmNprocessingDirection
, XmMAX_ON_RIGHT
);
653 XtSetValues (hscroll
, args
, n
);
657 stdarg (XmNprocessingDirection
, XmMAX_ON_TOP
);
659 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
660 XtSetValues (vscroll
, args
, n
);
662 Settings
.ShowBottomSide
= !Settings
.ShowBottomSide
;
664 /* The idea is that if we're looking at the front side and the front
665 layer is active (or visa versa), switching sides should switch
666 layers too. We used to only do this if the other layer wasn't
667 shown, but we now do it always. Change it back if users get
669 if (Settings
.ShowBottomSide
!= old_shown_side
)
671 if (Settings
.ShowBottomSide
)
673 if (active_group
== top_group
)
675 if (top_showing
&& !bottom_showing
)
676 ChangeGroupVisibility (top_layer
, 0, 0);
677 ChangeGroupVisibility (bottom_layer
, 1, 1);
682 if (active_group
== bottom_group
)
684 if (bottom_showing
&& !top_showing
)
685 ChangeGroupVisibility (bottom_layer
, 0, 0);
686 ChangeGroupVisibility (top_layer
, 1, 1);
690 lesstif_invalidate_all ();
694 static Widget m_cmd
= 0, m_cmd_label
;
697 command_callback (Widget w
, XtPointer uptr
, XmTextVerifyCallbackStruct
* cbs
)
703 s
= XmTextGetString (w
);
704 lesstif_show_crosshair (0);
705 hid_parse_command (s
);
707 XmTextSetString (w
, "");
708 case XmCR_LOSING_FOCUS
:
709 XtUnmanageChild (m_cmd
);
710 XtUnmanageChild (m_cmd_label
);
716 command_event_handler (Widget w
, XtPointer p
, XEvent
* e
, Boolean
* cont
)
724 XLookupString ((XKeyEvent
*)e
, buf
, sizeof (buf
), &sym
, NULL
);
728 XtUnmanageChild (m_cmd
);
729 XtUnmanageChild (m_cmd_label
);
730 XmTextSetString (w
, "");
738 static const char command_syntax
[] =
741 static const char command_help
[] =
742 "Displays the command line input window.";
744 /* %start-doc actions Command
746 The command window allows the user to manually enter actions to be
747 executed. Action syntax can be done one of two ways:
752 Follow the action name by an open parenthesis, arguments separated by
753 commas, end with a close parenthesis. Example: @code{Abc(1,2,3)}
756 Separate the action name and arguments by spaces. Example: @code{Abc
761 The first option allows you to have arguments with spaces in them,
762 but the second is more ``natural'' to type for most people.
764 Note that action names are not case sensitive, but arguments normally
765 are. However, most actions will check for ``keywords'' in a case
768 There are three ways to finish with the command window. If you press
769 the @code{Enter} key, the command is invoked, the window goes away,
770 and the next time you bring up the command window it's empty. If you
771 press the @code{Esc} key, the window goes away without invoking
772 anything, and the next time you bring up the command window it's
773 empty. If you change focus away from the command window (i.e. click
774 on some other window), the command window goes away but the next time
775 you bring it up it resumes entering the command you were entering
781 Command (int argc
, char **argv
, Coord x
, Coord y
)
783 XtManageChild (m_cmd_label
);
784 XtManageChild (m_cmd
);
785 XmProcessTraversal (m_cmd
, XmTRAVERSE_CURRENT
);
789 static const char benchmark_syntax
[] =
792 static const char benchmark_help
[] =
793 "Benchmark the GUI speed.";
795 /* %start-doc actions Benchmark
797 This action is used to speed-test the Lesstif graphics subsystem. It
798 redraws the current screen as many times as possible in ten seconds.
799 It reports the amount of time needed to draw the screen once.
804 Benchmark (int argc
, char **argv
, Coord x
, Coord y
)
811 save_main
= main_pixmap
;
812 main_pixmap
= window
;
816 region
.X2
= PCB
->MaxWidth
;
817 region
.Y2
= PCB
->MaxHeight
;
824 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, view_width
, view_height
);
825 hid_expose_callback (&lesstif_hid
, ®ion
, 0);
830 while (end
- start
< 10);
832 printf ("%g redraws per second\n", i
/ 10.0);
834 main_pixmap
= save_main
;
839 Center(int argc
, char **argv
, Coord x
, Coord y
)
841 x
= GridFit (x
, PCB
->Grid
, PCB
->GridOffsetX
);
842 y
= GridFit (y
, PCB
->Grid
, PCB
->GridOffsetY
);
843 view_left_x
= x
- (view_width
* view_zoom
) / 2;
844 view_top_y
= y
- (view_height
* view_zoom
) / 2;
845 lesstif_pan_fixup ();
846 /* Move the pointer to the center of the window, but only if it's
847 currently within the window already. Watch out for edges,
849 XWarpPointer (display
, window
, window
, 0, 0, view_width
, view_height
,
854 static const char cursor_syntax
[] =
855 "Cursor(Type,DeltaUp,DeltaRight,Units)";
857 static const char cursor_help
[] =
860 /* %start-doc actions Cursor
862 This action moves the mouse cursor. Unlike other actions which take
863 coordinates, this action's coordinates are always relative to the
864 user's view of the board. Thus, a positive @var{DeltaUp} may move the
865 cursor towards the board origin if the board is inverted.
867 Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the
868 viewport to move such that the crosshair is under the mouse cursor.
869 @samp{Warp} causes the mouse cursor to move to be above the crosshair.
871 @var{Units} can be one of the following:
877 The cursor is moved by that amount, in board units.
880 The cursor is moved by that many grid points.
883 The values are percentages of the viewport's view. Thus, a pan of
884 @samp{100} would scroll the viewport by exactly the width of the
888 The values are percentages of the board size. Thus, a move of
889 @samp{50,50} moves you halfway across the board.
896 CursorAction(int argc
, char **argv
, Coord x
, Coord y
)
898 UnitList extra_units_x
= {
899 { "grid", PCB
->Grid
, 0 },
900 { "view", Pz(view_width
), UNIT_PERCENT
},
901 { "board", PCB
->MaxWidth
, UNIT_PERCENT
},
904 UnitList extra_units_y
= {
905 { "grid", PCB
->Grid
, 0 },
906 { "view", Pz(view_height
), UNIT_PERCENT
},
907 { "board", PCB
->MaxHeight
, UNIT_PERCENT
},
910 int pan_warp
= HID_SC_DO_NOTHING
;
916 if (strcasecmp (argv
[0], "pan") == 0)
917 pan_warp
= HID_SC_PAN_VIEWPORT
;
918 else if (strcasecmp (argv
[0], "warp") == 0)
919 pan_warp
= HID_SC_WARP_POINTER
;
923 dx
= GetValueEx (argv
[1], argv
[3], NULL
, extra_units_x
, "mil");
926 dy
= GetValueEx (argv
[2], argv
[3], NULL
, extra_units_y
, "mil");
930 EventMoveCrosshair (Crosshair
.X
+ dx
, Crosshair
.Y
+ dy
);
931 gui
->set_crosshair (Crosshair
.X
, Crosshair
.Y
, pan_warp
);
936 HID_Action lesstif_main_action_list
[] = {
937 {"PCBChanged", 0, PCBChanged
,
938 pcbchanged_help
, pcbchanged_syntax
},
939 {"SetUnits", 0, SetUnits
,
940 setunits_help
, setunits_syntax
},
941 {"Zoom", "Click on a place to zoom in", ZoomAction
,
942 zoom_help
, zoom_syntax
},
943 {"Pan", "Click on a place to pan", PanAction
,
944 zoom_help
, zoom_syntax
},
945 {"SwapSides", 0, SwapSides
,
946 swapsides_help
, swapsides_syntax
},
947 {"Command", 0, Command
,
948 command_help
, command_syntax
},
949 {"Benchmark", 0, Benchmark
,
950 benchmark_help
, benchmark_syntax
},
951 {"PointCursor", 0, PointCursor
},
952 {"Center", "Click on a location to center", Center
},
954 {"Cursor", 0, CursorAction
,
955 cursor_help
, cursor_syntax
},
958 REGISTER_ACTIONS (lesstif_main_action_list
)
961 /* ----------------------------------------------------------------------
962 * redraws the background image
965 static int bg_w
, bg_h
, bgi_w
, bgi_h
;
966 static Pixel
**bg
= 0;
967 static XImage
*bgi
= 0;
972 } pixel_type
= PT_unknown
;
975 LoadBackgroundFile (FILE *f
, char *filename
)
977 XVisualInfo vinfot
, *vinfo
;
981 int p
[3], rows
, cols
, maxval
;
985 printf("bgimage: %s signature not P6\n", filename
);
990 printf("bgimage: %s signature not P6\n", filename
);
1000 while (!feof(f
) && b
!= '\n')
1002 } while (!isdigit(b
));
1004 while (isdigit(b
= fgetc(f
)))
1005 p
[i
] = p
[i
]*10 + b
- '0';
1012 bg
= (Pixel
**) malloc (rows
* sizeof (Pixel
*));
1015 printf("Out of memory loading %s\n", filename
);
1018 for (i
=0; i
<rows
; i
++)
1020 bg
[i
] = (Pixel
*) malloc (cols
* sizeof (Pixel
));
1023 printf("Out of memory loading %s\n", filename
);
1032 vis
= DefaultVisual (display
, DefaultScreen(display
));
1034 vinfot
.visualid
= XVisualIDFromVisual(vis
);
1035 vinfo
= XGetVisualInfo (display
, VisualIDMask
, &vinfot
, &nret
);
1038 /* If you want to support more visuals below, you'll probably need
1040 printf("vinfo: rm %04x gm %04x bm %04x depth %d class %d\n",
1041 vinfo
->red_mask
, vinfo
->green_mask
, vinfo
->blue_mask
,
1042 vinfo
->depth
, vinfo
->class);
1045 #if !defined(__cplusplus)
1046 #define c_class class
1049 if (vinfo
->c_class
== TrueColor
1050 && vinfo
->depth
== 16
1051 && vinfo
->red_mask
== 0xf800
1052 && vinfo
->green_mask
== 0x07e0
1053 && vinfo
->blue_mask
== 0x001f)
1054 pixel_type
= PT_RGB565
;
1056 if (vinfo
->c_class
== TrueColor
1057 && vinfo
->depth
== 24
1058 && vinfo
->red_mask
== 0xff0000
1059 && vinfo
->green_mask
== 0x00ff00
1060 && vinfo
->blue_mask
== 0x0000ff)
1061 pixel_type
= PT_RGB888
;
1063 for (r
=0; r
<rows
; r
++)
1065 for (c
=0; c
<cols
; c
++)
1068 unsigned int pr
= (unsigned)fgetc(f
);
1069 unsigned int pg
= (unsigned)fgetc(f
);
1070 unsigned int pb
= (unsigned)fgetc(f
);
1075 pix
.red
= pr
* 65535 / maxval
;
1076 pix
.green
= pg
* 65535 / maxval
;
1077 pix
.blue
= pb
* 65535 / maxval
;
1078 pix
.flags
= DoRed
| DoGreen
| DoBlue
;
1079 XAllocColor (display
, colormap
, &pix
);
1080 bg
[r
][c
] = pix
.pixel
;
1083 bg
[r
][c
] = (pr
>>3)<<11 | (pg
>>2)<<5 | (pb
>>3);
1086 bg
[r
][c
] = (pr
<< 16) | (pg
<< 8) | (pb
);
1094 LoadBackgroundImage (char *filename
)
1096 FILE *f
= fopen(filename
, "rb");
1099 if (NSTRCMP (filename
, "pcb-background.ppm"))
1103 LoadBackgroundFile (f
, filename
);
1108 DrawBackgroundImage ()
1111 double xscale
, yscale
;
1112 int pcbwidth
= PCB
->MaxWidth
/ view_zoom
;
1113 int pcbheight
= PCB
->MaxHeight
/ view_zoom
;
1118 if (!bgi
|| view_width
!= bgi_w
|| view_height
!= bgi_h
)
1121 XDestroyImage (bgi
);
1122 /* Cheat - get the image, which sets up the format too. */
1123 bgi
= XGetImage (XtDisplay(work_area
),
1125 0, 0, view_width
, view_height
,
1128 bgi_h
= view_height
;
1131 w
= MIN (view_width
, pcbwidth
);
1132 h
= MIN (view_height
, pcbheight
);
1134 xscale
= (double)bg_w
/ PCB
->MaxWidth
;
1135 yscale
= (double)bg_h
/ PCB
->MaxHeight
;
1140 int ir
= pr
* yscale
;
1144 int ic
= pc
* xscale
;
1145 XPutPixel (bgi
, x
, y
, bg
[ir
][ic
]);
1148 XPutImage(display
, main_pixmap
, bg_gc
,
1152 /* ---------------------------------------------------------------------- */
1154 static HID_Attribute
*
1155 lesstif_get_export_options (int *n
)
1157 *n
= sizeof (lesstif_attribute_list
) / sizeof (HID_Attribute
);
1158 return lesstif_attribute_list
;
1162 set_scroll (Widget s
, int pos
, int view
, int pcb
)
1164 int sz
= view
* view_zoom
;
1168 stdarg (XmNvalue
, pos
);
1169 stdarg (XmNsliderSize
, sz
);
1170 stdarg (XmNincrement
, view_zoom
);
1171 stdarg (XmNpageIncrement
, sz
);
1172 stdarg (XmNmaximum
, pcb
);
1173 XtSetValues (s
, args
, n
);
1177 lesstif_pan_fixup ()
1180 if (view_left_x
> PCB
->MaxWidth
- (view_width
* view_zoom
))
1181 view_left_x
= PCB
->MaxWidth
- (view_width
* view_zoom
);
1182 if (view_top_y
> PCB
->MaxHeight
- (view_height
* view_zoom
))
1183 view_top_y
= PCB
->MaxHeight
- (view_height
* view_zoom
);
1184 if (view_left_x
< 0)
1188 if (view_width
* view_zoom
> PCB
->MaxWidth
1189 && view_height
* view_zoom
> PCB
->MaxHeight
)
1196 set_scroll (hscroll
, view_left_x
, view_width
, PCB
->MaxWidth
);
1197 set_scroll (vscroll
, view_top_y
, view_height
, PCB
->MaxHeight
);
1199 lesstif_invalidate_all ();
1205 double new_zoom
= PCB
->MaxWidth
/ view_width
;
1206 if (new_zoom
< PCB
->MaxHeight
/ view_height
)
1207 new_zoom
= PCB
->MaxHeight
/ view_height
;
1209 view_left_x
= -(view_width
* new_zoom
- PCB
->MaxWidth
) / 2;
1210 view_top_y
= -(view_height
* new_zoom
- PCB
->MaxHeight
) / 2;
1211 view_zoom
= new_zoom
;
1212 pixel_slop
= view_zoom
;
1213 lesstif_pan_fixup ();
1217 zoom_to (double new_zoom
, int x
, int y
)
1219 double max_zoom
, xfrac
, yfrac
;
1222 xfrac
= (double) x
/ (double) view_width
;
1223 yfrac
= (double) y
/ (double) view_height
;
1230 max_zoom
= PCB
->MaxWidth
/ view_width
;
1231 if (max_zoom
< PCB
->MaxHeight
/ view_height
)
1232 max_zoom
= PCB
->MaxHeight
/ view_height
;
1234 max_zoom
*= MAX_ZOOM_SCALE
;
1238 if (new_zoom
> max_zoom
)
1239 new_zoom
= max_zoom
;
1241 cx
= view_left_x
+ view_width
* xfrac
* view_zoom
;
1242 cy
= view_top_y
+ view_height
* yfrac
* view_zoom
;
1244 if (view_zoom
!= new_zoom
)
1246 view_zoom
= new_zoom
;
1247 pixel_slop
= view_zoom
;
1249 view_left_x
= cx
- view_width
* xfrac
* view_zoom
;
1250 view_top_y
= cy
- view_height
* yfrac
* view_zoom
;
1252 lesstif_pan_fixup ();
1256 zoom_toggle(int x
, int y
)
1260 tmp
= prev_view_zoom
;
1261 prev_view_zoom
= view_zoom
;
1266 zoom_by (double factor
, int x
, int y
)
1268 zoom_to (view_zoom
* factor
, x
, y
);
1271 static int panning
= 0;
1272 static int shift_pressed
;
1273 static int ctrl_pressed
;
1274 static int alt_pressed
;
1276 /* X and Y are in screen coordinates. */
1278 Pan (int mode
, int x
, int y
)
1281 static int opx
, opy
;
1284 /* This is for ctrl-pan, where the viewport's position is directly
1285 proportional to the cursor position in the window (like the Xaw
1289 opx
= x
* PCB
->MaxWidth
/ view_width
;
1290 opy
= y
* PCB
->MaxHeight
/ view_height
;
1292 opx
= PCB
->MaxWidth
- opx
;
1294 opy
= PCB
->MaxHeight
- opy
;
1295 view_left_x
= opx
- view_width
/ 2 * view_zoom
;
1296 view_top_y
= opy
- view_height
/ 2 * view_zoom
;
1297 lesstif_pan_fixup ();
1299 /* This is the start of a regular pan. On the first click, we
1300 remember the coordinates where we "grabbed" the screen. */
1308 /* continued drag, we calculate how far we've moved the cursor and
1309 set the position accordingly. */
1313 view_left_x
= opx
+ (x
- ox
) * view_zoom
;
1315 view_left_x
= opx
- (x
- ox
) * view_zoom
;
1317 view_top_y
= opy
+ (y
- oy
) * view_zoom
;
1319 view_top_y
= opy
- (y
- oy
) * view_zoom
;
1320 lesstif_pan_fixup ();
1325 mod_changed (XKeyEvent
* e
, int set
)
1327 switch (XKeycodeToKeysym (display
, e
->keycode
, 0))
1331 shift_pressed
= set
;
1338 case XK_Mode_switch
:
1346 // to include the Apple keyboard left and right command keys use XK_Meta_L and XK_Meta_R respectivly.
1350 notify_crosshair_change (false);
1352 Pan (2, e
->x
, e
->y
);
1353 EventMoveCrosshair (Px (e
->x
), Py (e
->y
));
1354 AdjustAttachedObjects ();
1355 notify_crosshair_change (true);
1360 work_area_input (Widget w
, XtPointer v
, XEvent
* e
, Boolean
* ctd
)
1362 static int pressed_button
= 0;
1363 static int ignore_release
= 0;
1369 mod_changed (&(e
->xkey
), 1);
1370 if (lesstif_key_event (&(e
->xkey
)))
1375 mod_changed (&(e
->xkey
), 0);
1383 /*printf("click %d\n", e->xbutton.button); */
1384 if (lesstif_button_event (w
, e
))
1391 notify_crosshair_change (false);
1392 pressed_button
= e
->xbutton
.button
;
1393 mods
= ((e
->xbutton
.state
& ShiftMask
) ? M_Shift
: 0)
1394 + ((e
->xbutton
.state
& ControlMask
) ? M_Ctrl
: 0)
1396 + ((e
->xbutton
.state
& (1<<13)) ? M_Alt
: 0);
1398 + ((e
->xbutton
.state
& Mod1Mask
) ? M_Alt
: 0);
1400 do_mouse_action(e
->xbutton
.button
, mods
);
1401 notify_crosshair_change (true);
1408 if (e
->xbutton
.button
!= pressed_button
)
1410 lesstif_button_event (w
, e
);
1411 notify_crosshair_change (false);
1413 mods
= ((e
->xbutton
.state
& ShiftMask
) ? M_Shift
: 0)
1414 + ((e
->xbutton
.state
& ControlMask
) ? M_Ctrl
: 0)
1416 + ((e
->xbutton
.state
& (1<<13)) ? M_Alt
: 0)
1418 + ((e
->xbutton
.state
& Mod1Mask
) ? M_Alt
: 0)
1421 do_mouse_action (e
->xbutton
.button
, mods
);
1422 notify_crosshair_change (true);
1429 unsigned int keys_buttons
;
1430 int root_x
, root_y
, pos_x
, pos_y
;
1431 while (XCheckMaskEvent (display
, PointerMotionMask
, e
));
1432 XQueryPointer (display
, e
->xmotion
.window
, &root
, &child
,
1433 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
1434 shift_pressed
= (keys_buttons
& ShiftMask
);
1435 ctrl_pressed
= (keys_buttons
& ControlMask
);
1437 alt_pressed
= (keys_buttons
& (1<<13));
1439 alt_pressed
= (keys_buttons
& Mod1Mask
);
1441 /*pcb_printf("m %#mS %#mS\n", Px(e->xmotion.x), Py(e->xmotion.y)); */
1442 crosshair_in_window
= 1;
1445 Pan (2, pos_x
, pos_y
);
1446 EventMoveCrosshair (Px (pos_x
), Py (pos_y
));
1452 crosshair_in_window
= 0;
1453 ShowCrosshair (false);
1458 crosshair_in_window
= 1;
1460 EventMoveCrosshair (Px (e
->xcrossing
.x
), Py (e
->xcrossing
.y
));
1461 ShowCrosshair (true);
1467 printf ("work_area: unknown event %d\n", e
->type
);
1473 draw_right_cross (GC xor_gc
, int x
, int y
,
1474 int view_width
, int view_height
)
1476 XDrawLine (display
, window
, xor_gc
, 0, y
, view_width
, y
);
1477 XDrawLine (display
, window
, xor_gc
, x
, 0, x
, view_height
);
1481 draw_slanted_cross (GC xor_gc
, int x
, int y
,
1482 int view_width
, int view_height
)
1486 x0
= x
+ (view_height
- y
);
1487 x0
= MAX(0, MIN (x0
, view_width
));
1489 x1
= MAX(0, MIN (x1
, view_width
));
1490 y0
= y
+ (view_width
- x
);
1491 y0
= MAX(0, MIN (y0
, view_height
));
1493 y1
= MAX(0, MIN (y1
, view_height
));
1494 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1495 x0
= x
- (view_height
- y
);
1496 x0
= MAX(0, MIN (x0
, view_width
));
1498 x1
= MAX(0, MIN (x1
, view_width
));
1500 y0
= MAX(0, MIN (y0
, view_height
));
1501 y1
= y
- (view_width
- x
);
1502 y1
= MAX(0, MIN (y1
, view_height
));
1503 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1507 draw_dozen_cross (GC xor_gc
, int x
, int y
,
1508 int view_width
, int view_height
)
1511 double tan60
= sqrt (3);
1513 x0
= x
+ (view_height
- y
) / tan60
;
1514 x0
= MAX(0, MIN (x0
, view_width
));
1516 x1
= MAX(0, MIN (x1
, view_width
));
1517 y0
= y
+ (view_width
- x
) * tan60
;
1518 y0
= MAX(0, MIN (y0
, view_height
));
1520 y1
= MAX(0, MIN (y1
, view_height
));
1521 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1523 x0
= x
+ (view_height
- y
) * tan60
;
1524 x0
= MAX(0, MIN (x0
, view_width
));
1526 x1
= MAX(0, MIN (x1
, view_width
));
1527 y0
= y
+ (view_width
- x
) / tan60
;
1528 y0
= MAX(0, MIN (y0
, view_height
));
1530 y1
= MAX(0, MIN (y1
, view_height
));
1531 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1533 x0
= x
- (view_height
- y
) / tan60
;
1534 x0
= MAX(0, MIN (x0
, view_width
));
1536 x1
= MAX(0, MIN (x1
, view_width
));
1538 y0
= MAX(0, MIN (y0
, view_height
));
1539 y1
= y
- (view_width
- x
) * tan60
;
1540 y1
= MAX(0, MIN (y1
, view_height
));
1541 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1543 x0
= x
- (view_height
- y
) * tan60
;
1544 x0
= MAX(0, MIN (x0
, view_width
));
1546 x1
= MAX(0, MIN (x1
, view_width
));
1548 y0
= MAX(0, MIN (y0
, view_height
));
1549 y1
= y
- (view_width
- x
) / tan60
;
1550 y1
= MAX(0, MIN (y1
, view_height
));
1551 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1555 draw_crosshair (GC xor_gc
, int x
, int y
,
1556 int view_width
, int view_height
)
1558 draw_right_cross (xor_gc
, x
, y
, view_width
, view_height
);
1559 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
1560 draw_slanted_cross (xor_gc
, x
, y
, view_width
, view_height
);
1561 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
1562 draw_dozen_cross (xor_gc
, x
, y
, view_width
, view_height
);
1565 lesstif_show_crosshair (int show
)
1567 static int showing
= 0;
1569 static GC xor_gc
= 0;
1570 Pixel crosshair_color
;
1572 if (!crosshair_in_window
|| !window
)
1576 crosshair_color
= lesstif_parse_color (Settings
.CrosshairColor
) ^ bgcolor
;
1577 xor_gc
= XCreateGC (display
, window
, 0, 0);
1578 XSetFunction (display
, xor_gc
, GXxor
);
1579 XSetForeground (display
, xor_gc
, crosshair_color
);
1581 if (show
== showing
)
1585 sx
= Vx (crosshair_x
);
1586 sy
= Vy (crosshair_y
);
1590 draw_crosshair (xor_gc
, sx
, sy
, view_width
, view_height
);
1595 work_area_expose (Widget work_area
, void *me
,
1596 XmDrawingAreaCallbackStruct
* cbs
)
1601 e
= &(cbs
->event
->xexpose
);
1602 XSetFunction (display
, my_gc
, GXcopy
);
1603 XCopyArea (display
, main_pixmap
, window
, my_gc
,
1604 e
->x
, e
->y
, e
->width
, e
->height
, e
->x
, e
->y
);
1609 scroll_callback (Widget scroll
, int *view_dim
,
1610 XmScrollBarCallbackStruct
* cbs
)
1612 *view_dim
= cbs
->value
;
1613 lesstif_invalidate_all ();
1617 work_area_make_pixmaps (Dimension width
, Dimension height
)
1620 XFreePixmap (display
, main_pixmap
);
1622 XCreatePixmap (display
, window
, width
, height
,
1623 XDefaultDepth (display
, screen
));
1626 XFreePixmap (display
, mask_pixmap
);
1628 XCreatePixmap (display
, window
, width
, height
,
1629 XDefaultDepth (display
, screen
));
1633 XRenderFreePicture (display
, main_picture
);
1638 XRenderFreePicture (display
, mask_picture
);
1643 main_picture
= XRenderCreatePicture (display
, main_pixmap
,
1644 XRenderFindVisualFormat(display
,
1645 DefaultVisual(display
, screen
)), 0, 0);
1646 mask_picture
= XRenderCreatePicture (display
, mask_pixmap
,
1647 XRenderFindVisualFormat(display
,
1648 DefaultVisual(display
, screen
)), 0, 0);
1649 if (!main_picture
|| !mask_picture
)
1652 #endif /* HAVE_XRENDER */
1655 XFreePixmap (display
, mask_bitmap
);
1656 mask_bitmap
= XCreatePixmap (display
, window
, width
, height
, 1);
1658 pixmap
= use_mask
? main_pixmap
: mask_pixmap
;
1664 work_area_resize (Widget work_area
, void *me
,
1665 XmDrawingAreaCallbackStruct
* cbs
)
1668 Dimension width
, height
;
1673 stdarg (XtNwidth
, &width
);
1674 stdarg (XtNheight
, &height
);
1675 stdarg (XmNbackground
, &bgcolor
);
1676 XtGetValues (work_area
, args
, n
);
1678 view_height
= height
;
1680 color
.pixel
= bgcolor
;
1681 XQueryColor (display
, colormap
, &color
);
1683 bggreen
= color
.green
;
1684 bgblue
= color
.blue
;
1689 work_area_make_pixmaps (view_width
, view_height
);
1695 work_area_first_expose (Widget work_area
, void *me
,
1696 XmDrawingAreaCallbackStruct
* cbs
)
1699 Dimension width
, height
;
1700 static char dashes
[] = { 4, 4 };
1702 window
= XtWindow (work_area
);
1703 my_gc
= XCreateGC (display
, window
, 0, 0);
1705 arc1_gc
= XCreateGC (display
, window
, 0, 0);
1706 c
= lesstif_parse_color ("#804000");
1707 XSetForeground (display
, arc1_gc
, c
);
1708 arc2_gc
= XCreateGC (display
, window
, 0, 0);
1709 c
= lesstif_parse_color ("#004080");
1710 XSetForeground (display
, arc2_gc
, c
);
1711 XSetLineAttributes (display
, arc1_gc
, 1, LineOnOffDash
, 0, 0);
1712 XSetLineAttributes (display
, arc2_gc
, 1, LineOnOffDash
, 0, 0);
1713 XSetDashes (display
, arc1_gc
, 0, dashes
, 2);
1714 XSetDashes (display
, arc2_gc
, 0, dashes
, 2);
1717 stdarg (XtNwidth
, &width
);
1718 stdarg (XtNheight
, &height
);
1719 stdarg (XmNbackground
, &bgcolor
);
1720 XtGetValues (work_area
, args
, n
);
1722 view_height
= height
;
1724 offlimit_color
= lesstif_parse_color (Settings
.OffLimitColor
);
1725 grid_color
= lesstif_parse_color (Settings
.GridColor
);
1727 bg_gc
= XCreateGC (display
, window
, 0, 0);
1728 XSetForeground (display
, bg_gc
, bgcolor
);
1730 work_area_make_pixmaps (width
, height
);
1735 XRenderPictureAttributes pa
;
1736 XRenderColor a
= {0, 0, 0, 0x8000};
1738 pale_pixmap
= XCreatePixmap (display
, window
, 1, 1, 8);
1740 pale_picture
= XRenderCreatePicture (display
, pale_pixmap
,
1741 XRenderFindStandardFormat(display
, PictStandardA8
),
1744 XRenderFillRectangle(display
, PictOpSrc
, pale_picture
, &a
, 0, 0, 1, 1);
1748 #endif /* HAVE_XRENDER */
1750 clip_gc
= XCreateGC (display
, window
, 0, 0);
1751 bset_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1752 XSetForeground (display
, bset_gc
, 1);
1753 bclear_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1754 XSetForeground (display
, bclear_gc
, 0);
1756 XtRemoveCallback (work_area
, XmNexposeCallback
,
1757 (XtCallbackProc
) work_area_first_expose
, 0);
1758 XtAddCallback (work_area
, XmNexposeCallback
,
1759 (XtCallbackProc
) work_area_expose
, 0);
1760 lesstif_invalidate_all ();
1764 make_message (char *name
, Widget left
, int resizeable
)
1770 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1771 stdarg (XmNleftWidget
, XtParent(left
));
1775 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1777 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1778 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1779 stdarg (XmNshadowType
, XmSHADOW_IN
);
1780 stdarg (XmNshadowThickness
, 1);
1781 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1782 stdarg (XmNmarginWidth
, 4);
1783 stdarg (XmNmarginHeight
, 1);
1785 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
1786 f
= XmCreateForm (messages
, name
, args
, n
);
1789 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1790 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1791 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1792 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1793 w
= XmCreateLabel (f
, name
, args
, n
);
1799 lesstif_do_export (HID_Attr_Val
* options
)
1801 Dimension width
, height
;
1803 Widget work_area_frame
;
1806 stdarg (XtNwidth
, &width
);
1807 stdarg (XtNheight
, &height
);
1808 XtGetValues (appwidget
, args
, n
);
1812 if (width
> XDisplayWidth (display
, screen
))
1813 width
= XDisplayWidth (display
, screen
);
1816 if (height
> XDisplayHeight (display
, screen
))
1817 height
= XDisplayHeight (display
, screen
);
1820 stdarg (XmNwidth
, width
);
1821 stdarg (XmNheight
, height
);
1822 XtSetValues (appwidget
, args
, n
);
1824 stdarg (XmNspacing
, 0);
1825 mainwind
= XmCreateMainWindow (appwidget
, "mainWind", args
, n
);
1826 XtManageChild (mainwind
);
1829 stdarg (XmNmarginWidth
, 0);
1830 stdarg (XmNmarginHeight
, 0);
1831 menu
= lesstif_menu (mainwind
, "menubar", args
, n
);
1832 XtManageChild (menu
);
1835 stdarg (XmNshadowType
, XmSHADOW_IN
);
1837 XmCreateFrame (mainwind
, "work_area_frame", args
, n
);
1838 XtManageChild (work_area_frame
);
1841 do_color (Settings
.BackgroundColor
, XmNbackground
);
1842 work_area
= XmCreateDrawingArea (work_area_frame
, "work_area", args
, n
);
1843 XtManageChild (work_area
);
1844 XtAddCallback (work_area
, XmNexposeCallback
,
1845 (XtCallbackProc
) work_area_first_expose
, 0);
1846 XtAddCallback (work_area
, XmNresizeCallback
,
1847 (XtCallbackProc
) work_area_resize
, 0);
1848 /* A regular callback won't work here, because lesstif swallows any
1849 Ctrl<Button>1 event. */
1850 XtAddEventHandler (work_area
,
1851 ButtonPressMask
| ButtonReleaseMask
1852 | PointerMotionMask
| PointerMotionHintMask
1853 | KeyPressMask
| KeyReleaseMask
1854 | EnterWindowMask
| LeaveWindowMask
,
1855 0, work_area_input
, 0);
1858 stdarg (XmNorientation
, XmVERTICAL
);
1859 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
1860 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
1861 vscroll
= XmCreateScrollBar (mainwind
, "vscroll", args
, n
);
1862 XtAddCallback (vscroll
, XmNvalueChangedCallback
,
1863 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_top_y
);
1864 XtAddCallback (vscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1865 (XtPointer
) & view_top_y
);
1866 XtManageChild (vscroll
);
1869 stdarg (XmNorientation
, XmHORIZONTAL
);
1870 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
1871 hscroll
= XmCreateScrollBar (mainwind
, "hscroll", args
, n
);
1872 XtAddCallback (hscroll
, XmNvalueChangedCallback
,
1873 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_left_x
);
1874 XtAddCallback (hscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1875 (XtPointer
) & view_left_x
);
1876 XtManageChild (hscroll
);
1879 stdarg (XmNresize
, True
);
1880 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
1881 messages
= XmCreateForm (mainwind
, "messages", args
, n
);
1882 XtManageChild (messages
);
1885 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1886 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1887 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1888 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1889 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1890 stdarg (XmNshadowThickness
, 2);
1891 m_click
= XmCreateLabel (messages
, "click", args
, n
);
1894 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1895 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1896 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1897 stdarg (XmNlabelString
, XmStringCreatePCB ("Command: "));
1898 m_cmd_label
= XmCreateLabel (messages
, "command", args
, n
);
1901 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1902 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1903 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1904 stdarg (XmNleftWidget
, m_cmd_label
);
1905 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1906 stdarg (XmNshadowThickness
, 1);
1907 stdarg (XmNhighlightThickness
, 0);
1908 stdarg (XmNmarginWidth
, 2);
1909 stdarg (XmNmarginHeight
, 2);
1910 m_cmd
= XmCreateTextField (messages
, "command", args
, n
);
1911 XtAddCallback (m_cmd
, XmNactivateCallback
,
1912 (XtCallbackProc
) command_callback
, 0);
1913 XtAddCallback (m_cmd
, XmNlosingFocusCallback
,
1914 (XtCallbackProc
) command_callback
, 0);
1915 XtAddEventHandler (m_cmd
, KeyPressMask
, 0, command_event_handler
, 0);
1917 m_mark
= make_message ("m_mark", 0, 0);
1918 m_crosshair
= make_message ("m_crosshair", m_mark
, 0);
1919 m_grid
= make_message ("m_grid", m_crosshair
, 1);
1920 m_zoom
= make_message ("m_zoom", m_grid
, 1);
1921 lesstif_m_layer
= make_message ("m_layer", m_zoom
, 0);
1922 m_mode
= make_message ("m_mode", lesstif_m_layer
, 1);
1923 m_rats
= make_message ("m_rats", m_mode
, 1);
1924 m_status
= make_message ("m_status", m_mode
, 1);
1926 XtUnmanageChild (XtParent (m_mark
));
1927 XtUnmanageChild (XtParent (m_rats
));
1930 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1931 XtSetValues (XtParent (m_status
), args
, n
);
1933 /* We'll use this later. */
1935 stdarg (XmNleftWidget
, XtParent (m_mark
));
1936 XtSetValues (XtParent (m_crosshair
), args
, n
);
1939 stdarg (XmNmessageWindow
, messages
);
1940 XtSetValues (mainwind
, args
, n
);
1942 if (background_image_file
)
1943 LoadBackgroundImage (background_image_file
);
1945 XtRealizeWidget (appwidget
);
1950 XtAppNextEvent (app_context
, &e
);
1951 XtDispatchEvent (&e
);
1954 PCBChanged (0, 0, 0, 0);
1956 XtAppMainLoop (app_context
);
1960 XrmOptionDescRec lesstif_options
[] = {
1963 XtResource lesstif_resources
[] = {
1976 pcb_cvt_string_to_double (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
1977 XrmValue
* from
, XrmValue
* to
, XtPointer
* data
)
1980 rv
= strtod ((char *) from
->addr
, 0);
1982 *(double *) to
->addr
= rv
;
1984 to
->addr
= (XPointer
) & rv
;
1985 to
->size
= sizeof (rv
);
1990 pcb_cvt_string_to_coord (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
1991 XrmValue
* from
, XrmValue
* to
, XtPointer
*data
)
1994 rv
= GetValue ((char *) from
->addr
, NULL
, NULL
);
1996 *(Coord
*) to
->addr
= rv
;
1998 to
->addr
= (XPointer
) &rv
;
1999 to
->size
= sizeof (rv
);
2004 mainwind_delete_cb ()
2006 hid_action ("Quit");
2010 lesstif_listener_cb (XtPointer client_data
, int *fid
, XtInputId
*id
)
2015 if ((nbytes
= read (*fid
, buf
, BUFSIZ
)) == -1)
2016 perror ("lesstif_listener_cb");
2021 hid_parse_actions (buf
);
2026 lesstif_parse_arguments (int *argc
, char ***argv
)
2030 int acount
= 0, amax
;
2031 int rcount
= 0, rmax
;
2033 XrmOptionDescRec
*new_options
;
2034 XtResource
*new_resources
;
2035 val_union
*new_values
;
2036 int render_event
, render_error
;
2038 XtSetTypeConverter (XtRString
,
2040 pcb_cvt_string_to_double
, NULL
, 0, XtCacheAll
, NULL
);
2041 XtSetTypeConverter (XtRString
,
2043 pcb_cvt_string_to_coord
, NULL
, 0, XtCacheAll
, NULL
);
2046 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2047 for (i
= 0; i
< ha
->n
; i
++)
2049 HID_Attribute
*a
= ha
->attributes
+ i
;
2067 amax
= acount
+ XtNumber (lesstif_options
);
2072 new_options
= (XrmOptionDescRec
*) malloc ((amax
+ 1) * sizeof (XrmOptionDescRec
));
2075 memcpy (new_options
+ acount
, lesstif_options
, sizeof (lesstif_options
));
2080 rmax
= rcount
+ XtNumber (lesstif_resources
);
2085 new_resources
= (XtResource
*) malloc ((rmax
+ 1) * sizeof (XtResource
));
2086 new_values
= (val_union
*) malloc ((rmax
+ 1) * sizeof (val_union
));
2088 memcpy (new_resources
+ acount
, lesstif_resources
,
2089 sizeof (lesstif_resources
));
2093 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2094 for (i
= 0; i
< ha
->n
; i
++)
2096 HID_Attribute
*a
= ha
->attributes
+ i
;
2097 XrmOptionDescRec
*o
= new_options
+ acount
;
2098 char *tmpopt
, *tmpres
;
2099 XtResource
*r
= new_resources
+ rcount
;
2101 tmpopt
= (char *) malloc (strlen (a
->name
) + 3);
2102 tmpopt
[0] = tmpopt
[1] = '-';
2103 strcpy (tmpopt
+ 2, a
->name
);
2106 tmpres
= (char *) malloc (strlen (a
->name
) + 2);
2108 strcpy (tmpres
+ 1, a
->name
);
2109 o
->specifier
= tmpres
;
2118 o
->argKind
= XrmoptionSepArg
;
2123 o
->argKind
= XrmoptionNoArg
;
2131 r
->resource_name
= a
->name
;
2132 r
->resource_class
= a
->name
;
2133 r
->resource_offset
= sizeof (val_union
) * rcount
;
2138 r
->resource_type
= XtRInt
;
2139 r
->default_type
= XtRInt
;
2140 r
->resource_size
= sizeof (int);
2141 r
->default_addr
= &(a
->default_val
.int_value
);
2145 r
->resource_type
= XtRPCBCoord
;
2146 r
->default_type
= XtRPCBCoord
;
2147 r
->resource_size
= sizeof (Coord
);
2148 r
->default_addr
= &(a
->default_val
.coord_value
);
2152 r
->resource_type
= XtRDouble
;
2153 r
->default_type
= XtRDouble
;
2154 r
->resource_size
= sizeof (double);
2155 r
->default_addr
= &(a
->default_val
.real_value
);
2160 r
->resource_type
= XtRString
;
2161 r
->default_type
= XtRString
;
2162 r
->resource_size
= sizeof (char *);
2163 r
->default_addr
= (char *) a
->default_val
.str_value
;
2167 r
->resource_type
= XtRBoolean
;
2168 r
->default_type
= XtRInt
;
2169 r
->resource_size
= sizeof (int);
2170 r
->default_addr
= &(a
->default_val
.int_value
);
2178 for (i
= 0; i
< XtNumber (lesstif_resources
); i
++)
2180 XtResource
*r
= new_resources
+ rcount
;
2181 r
->resource_offset
= sizeof (val_union
) * rcount
;
2187 stdarg (XmNdeleteResponse
, XmDO_NOTHING
);
2189 appwidget
= XtAppInitialize (&app_context
,
2191 new_options
, amax
, argc
, *argv
, 0, args
, n
);
2193 display
= XtDisplay (appwidget
);
2194 screen_s
= XtScreen (appwidget
);
2195 screen
= XScreenNumberOfScreen (screen_s
);
2196 colormap
= XDefaultColormap (display
, screen
);
2198 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
2199 XmAddWMProtocolCallback (appwidget
, close_atom
,
2200 (XtCallbackProc
) mainwind_delete_cb
, 0);
2202 /* XSynchronize(display, True); */
2204 XtGetApplicationResources (appwidget
, new_values
, new_resources
,
2208 use_xrender
= XRenderQueryExtension (display
, &render_event
, &render_error
) &&
2209 XRenderFindVisualFormat (display
, DefaultVisual(display
, screen
));
2210 #ifdef HAVE_XINERAMA
2211 /* Xinerama and XRender don't get along well */
2212 if (XineramaQueryExtension (display
, &render_event
, &render_error
)
2213 && XineramaIsActive (display
))
2215 #endif /* HAVE_XINERAMA */
2216 #endif /* HAVE_XRENDER */
2219 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2220 for (i
= 0; i
< ha
->n
; i
++)
2222 HID_Attribute
*a
= ha
->attributes
+ i
;
2223 val_union
*v
= new_values
+ rcount
;
2228 *(int *) a
->value
= v
->i
;
2230 a
->default_val
.int_value
= v
->i
;
2235 *(Coord
*) a
->value
= v
->c
;
2237 a
->default_val
.coord_value
= v
->c
;
2242 *(char *) a
->value
= v
->i
;
2244 a
->default_val
.int_value
= v
->i
;
2249 *(double *) a
->value
= v
->f
;
2251 a
->default_val
.real_value
= v
->f
;
2257 *(char **) a
->value
= v
->s
;
2259 a
->default_val
.str_value
= v
->s
;
2267 /* redefine colormap, if requested via "-install" */
2268 if (use_private_colormap
)
2270 colormap
= XCopyColormapAndFree (display
, colormap
);
2271 XtVaSetValues (appwidget
, XtNcolormap
, colormap
, NULL
);
2274 /* listen on standard input for actions */
2277 XtAppAddInput (app_context
, fileno (stdin
), (XtPointer
) XtInputReadMask
,
2278 lesstif_listener_cb
, NULL
);
2285 static XPoint
*points
= 0;
2286 static int npoints
= 0;
2287 Coord x1
, y1
, x2
, y2
, prevx
;
2290 static GC grid_gc
= 0;
2292 if (!Settings
.DrawGrid
)
2294 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
2298 grid_gc
= XCreateGC (display
, window
, 0, 0);
2299 XSetFunction (display
, grid_gc
, GXxor
);
2300 XSetForeground (display
, grid_gc
, grid_color
);
2304 x2
= GridFit (Px (0), PCB
->Grid
, PCB
->GridOffsetX
);
2305 x1
= GridFit (Px (view_width
), PCB
->Grid
, PCB
->GridOffsetX
);
2308 if (Vx (x1
) >= view_width
)
2313 x1
= GridFit (Px (0), PCB
->Grid
, PCB
->GridOffsetX
);
2314 x2
= GridFit (Px (view_width
), PCB
->Grid
, PCB
->GridOffsetX
);
2317 if (Vx (x2
) >= view_width
)
2322 y2
= GridFit (Py (0), PCB
->Grid
, PCB
->GridOffsetY
);
2323 y1
= GridFit (Py (view_height
), PCB
->Grid
, PCB
->GridOffsetY
);
2326 if (Vy (y1
) >= view_height
)
2331 y1
= GridFit (Py (0), PCB
->Grid
, PCB
->GridOffsetY
);
2332 y2
= GridFit (Py (view_height
), PCB
->Grid
, PCB
->GridOffsetY
);
2335 if (Vy (y2
) >= view_height
)
2338 n
= (x2
- x1
) / PCB
->Grid
+ 1;
2342 points
= (XPoint
*) realloc (points
, npoints
* sizeof (XPoint
));
2346 for (x
= x1
; x
<= x2
; x
+= PCB
->Grid
)
2352 points
[n
].x
-= prevx
;
2358 for (y
= y1
; y
<= y2
; y
+= PCB
->Grid
)
2362 XDrawPoints (display
, pixmap
, grid_gc
, points
, n
, CoordModePrevious
);
2367 mark_delta_to_widget (Coord dx
, Coord dy
, Widget w
)
2370 double g
= coord_to_unit (Settings
.grid_unit
, PCB
->Grid
);
2374 /* Integer-sized grid? */
2375 if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2378 prec
= Settings
.grid_unit
->default_prec
;
2380 if (dx
== 0 && dy
== 0)
2381 buf
= pcb_g_strdup_printf ("%m+%+.*mS, %+.*mS", UUNIT
, prec
, dx
, prec
, dy
);
2384 Angle angle
= atan2 (dy
, -dx
) * 180 / M_PI
;
2385 Coord dist
= Distance (0, 0, dx
, dy
);
2387 buf
= pcb_g_strdup_printf ("%m+%+.*mS, %+.*mS (%.*mS, %d\260)", UUNIT
,
2388 prec
, dx
, prec
, dy
, prec
, dist
, angle
);
2391 ms
= XmStringCreatePCB (buf
);
2393 stdarg (XmNlabelString
, ms
);
2394 XtSetValues (w
, args
, n
);
2399 cursor_pos_to_widget (Coord x
, Coord y
, Widget w
, int prev_state
)
2401 int this_state
= prev_state
;
2403 double g
= coord_to_unit (Settings
.grid_unit
, PCB
->Grid
);
2407 /* Determine necessary precision (and state) based
2408 * on the user's grid setting */
2409 if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2412 this_state
= Settings
.grid_unit
->allow
;
2416 prec
= Settings
.grid_unit
->default_prec
;
2417 this_state
= -Settings
.grid_unit
->allow
;
2421 buf
= g_strdup ("");
2423 buf
= pcb_g_strdup_printf ("%m+%.*mS, %.*mS", UUNIT
, prec
, x
, prec
, y
);
2425 ms
= XmStringCreatePCB (buf
);
2427 stdarg (XmNlabelString
, ms
);
2428 XtSetValues (w
, args
, n
);
2436 lesstif_update_status_line ()
2439 char *s45
= cur_clip ();
2442 switch (Settings
.Mode
)
2445 buf
= pcb_g_strdup_printf ("%m+%.2mS/%.2mS \370=%.2mS", UUNIT
,
2446 S
.ViaThickness
, S
.Keepaway
, S
.ViaDrillingHole
);
2450 buf
= pcb_g_strdup_printf ("%m+%.2mS/%.2mS %s", UUNIT
,
2451 S
.LineThickness
, S
.Keepaway
, s45
);
2453 case RECTANGLE_MODE
:
2455 buf
= pcb_g_strdup_printf ("%m+%.2mS %s", UUNIT
, S
.Keepaway
, s45
);
2458 buf
= g_strdup_printf ("%d %%", S
.TextScale
);
2462 case INSERTPOINT_MODE
:
2463 case RUBBERBANDMOVE_MODE
:
2464 buf
= g_strdup_printf ("%s", s45
);
2467 case PASTEBUFFER_MODE
:
2478 xs
= XmStringCreatePCB (buf
);
2480 stdarg (XmNlabelString
, xs
);
2481 XtSetValues (m_status
, args
, n
);
2487 static int idle_proc_set
= 0;
2488 static int need_redraw
= 0;
2491 idle_proc (XtPointer dummy
)
2497 lesstif_use_mask (0);
2498 pixmap
= main_pixmap
;
2503 region
.X2
= Px (view_width
);
2504 region
.Y2
= Py (view_height
);
2507 Coord tmp
= region
.X1
;
2508 region
.X1
= region
.X2
;
2513 Coord tmp
= region
.Y1
;
2514 region
.Y1
= region
.Y2
;
2517 XSetForeground (display
, bg_gc
, bgcolor
);
2518 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0, mx
, my
);
2520 if (region
.X1
< 0 || region
.Y1
< 0
2521 || region
.X2
> PCB
->MaxWidth
|| region
.Y2
> PCB
->MaxHeight
)
2523 int leftmost
, rightmost
, topmost
, bottommost
;
2526 rightmost
= Vx (PCB
->MaxWidth
);
2528 bottommost
= Vy (PCB
->MaxHeight
);
2529 if (leftmost
> rightmost
) {
2531 leftmost
= rightmost
;
2534 if (topmost
> bottommost
) {
2536 topmost
= bottommost
;
2543 if (rightmost
> view_width
)
2544 rightmost
= view_width
;
2545 if (bottommost
> view_height
)
2546 bottommost
= view_height
;
2548 XSetForeground (display
, bg_gc
, offlimit_color
);
2556 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0,
2557 leftmost
, view_height
);
2559 if (rightmost
< view_width
)
2561 XFillRectangle (display
, main_pixmap
, bg_gc
, rightmost
+1, 0,
2562 view_width
-rightmost
+1, view_height
);
2566 XFillRectangle (display
, main_pixmap
, bg_gc
, leftmost
, 0,
2567 rightmost
-leftmost
+1, topmost
);
2569 if (bottommost
< view_height
)
2571 XFillRectangle (display
, main_pixmap
, bg_gc
, leftmost
, bottommost
+1,
2572 rightmost
-leftmost
+1, view_height
-bottommost
+1);
2575 DrawBackgroundImage();
2576 hid_expose_callback (&lesstif_hid
, ®ion
, 0);
2578 lesstif_use_mask (0);
2579 show_crosshair (0); /* To keep the drawn / not drawn info correct */
2580 XSetFunction (display
, my_gc
, GXcopy
);
2581 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
2593 static int c_x
= -2, c_y
= -2;
2594 static MarkType saved_mark
;
2595 static const Unit
*old_grid_unit
= NULL
;
2596 if (crosshair_x
!= c_x
|| crosshair_y
!= c_y
2597 || Settings
.grid_unit
!= old_grid_unit
2598 || memcmp (&saved_mark
, &Marked
, sizeof (MarkType
)))
2600 static int last_state
= 0;
2601 static int this_state
= 0;
2607 cursor_pos_to_widget (crosshair_x
, crosshair_y
, m_crosshair
,
2610 mark_delta_to_widget (crosshair_x
- Marked
.X
, crosshair_y
- Marked
.Y
,
2613 if (Marked
.status
!= saved_mark
.status
)
2617 XtManageChild (XtParent (m_mark
));
2618 XtManageChild (m_mark
);
2620 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
2621 stdarg (XmNleftWidget
, XtParent (m_mark
));
2622 XtSetValues (XtParent (m_crosshair
), args
, n
);
2627 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
2628 XtSetValues (XtParent (m_crosshair
), args
, n
);
2629 XtUnmanageChild (XtParent (m_mark
));
2631 last_state
= this_state
+ 100;
2633 memcpy (&saved_mark
, &Marked
, sizeof (MarkType
));
2635 if (old_grid_unit
!= Settings
.grid_unit
)
2637 old_grid_unit
= Settings
.grid_unit
;
2638 /* Force a resize on units change. */
2642 /* This is obtuse. We want to enable XmRESIZE_ANY long enough
2643 to shrink to fit the new format (if any), then switch it
2644 back to XmRESIZE_GROW to prevent it from shrinking due to
2645 changes in the number of actual digits printed. Thus, when
2646 you switch from a small grid and %.2f formats to a large
2647 grid and %d formats, you aren't punished with a wide and
2648 mostly white-space label widget. "this_state" indicates
2649 which of the above formats we're using. "last_state" is
2650 either zero (when resizing) or the same as "this_state"
2651 (when grow-only), or a non-zero but not "this_state" which
2652 means we need to start a resize cycle. */
2653 if (this_state
!= last_state
&& last_state
)
2656 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
2657 XtSetValues (XtParent (m_mark
), args
, n
);
2658 XtSetValues (XtParent (m_crosshair
), args
, n
);
2661 else if (this_state
!= last_state
)
2664 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
2665 XtSetValues (XtParent (m_mark
), args
, n
);
2666 XtSetValues (XtParent (m_crosshair
), args
, n
);
2667 last_state
= this_state
;
2673 static Coord old_grid
= -1;
2674 static Coord old_gx
, old_gy
;
2675 static const Unit
*old_unit
;
2677 if (PCB
->Grid
!= old_grid
2678 || PCB
->GridOffsetX
!= old_gx
2679 || PCB
->GridOffsetY
!= old_gy
|| Settings
.grid_unit
!= old_unit
)
2681 static char buf
[100];
2682 old_grid
= PCB
->Grid
;
2683 old_unit
= Settings
.grid_unit
;
2684 old_gx
= PCB
->GridOffsetX
;
2685 old_gy
= PCB
->GridOffsetY
;
2688 strcpy (buf
, "No Grid");
2692 if (old_gx
|| old_gy
)
2693 pcb_sprintf (buf
, "%m+%$mS @%mS,%mS", UUNIT
, old_grid
, old_gx
, old_gy
);
2695 pcb_sprintf (buf
, "%m+%$mS", UUNIT
, old_grid
);
2697 ms
= XmStringCreatePCB (buf
);
2699 stdarg (XmNlabelString
, ms
);
2700 XtSetValues (m_grid
, args
, n
);
2705 static double old_zoom
= -1;
2706 static const Unit
*old_grid_unit
= NULL
;
2707 if (view_zoom
!= old_zoom
|| Settings
.grid_unit
!= old_grid_unit
)
2709 gchar
*buf
= pcb_g_strdup_printf ("%m+%$mS/pix",
2710 Settings
.grid_unit
->allow
, (Coord
) view_zoom
);
2713 old_zoom
= view_zoom
;
2714 old_grid_unit
= Settings
.grid_unit
;
2716 ms
= XmStringCreatePCB (buf
);
2718 stdarg (XmNlabelString
, ms
);
2719 XtSetValues (m_zoom
, args
, n
);
2725 if (old_cursor_mode
!= Settings
.Mode
)
2730 static int free_cursor
= 0;
2732 old_cursor_mode
= Settings
.Mode
;
2733 switch (Settings
.Mode
)
2737 cursor
= XC_X_cursor
;
2747 case RECTANGLE_MODE
:
2749 cursor
= XC_ul_angle
;
2753 cursor
= XC_sb_up_arrow
;
2755 case POLYGONHOLE_MODE
:
2757 cursor
= XC_sb_up_arrow
;
2759 case PASTEBUFFER_MODE
:
2769 cursor
= XC_exchange
;
2777 cursor
= XC_crosshair
;
2781 cursor
= XC_crosshair
;
2783 case INSERTPOINT_MODE
:
2787 case RUBBERBANDMOVE_MODE
:
2789 cursor
= XC_top_left_corner
;
2793 cursor
= XC_iron_cross
;
2797 cursor
= XC_question_arrow
;
2802 cursor
= XC_draped_box
;
2804 cursor
= XC_left_ptr
;
2811 ms
= XmStringCreatePCB (s
);
2813 stdarg (XmNlabelString
, ms
);
2814 XtSetValues (m_mode
, args
, n
);
2818 XFreeCursor (display
, my_cursor
);
2823 static Pixmap nocur_source
= 0;
2824 static Pixmap nocur_mask
= 0;
2825 static Cursor nocursor
= 0;
2826 if (nocur_source
== 0)
2830 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2832 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2834 fg
.red
= fg
.green
= fg
.blue
= 65535;
2835 bg
.red
= bg
.green
= bg
.blue
= 0;
2836 fg
.flags
= bg
.flags
= DoRed
| DoGreen
| DoBlue
;
2837 nocursor
= XCreatePixmapCursor (display
, nocur_source
,
2838 nocur_mask
, &fg
, &bg
, 0, 0);
2840 my_cursor
= nocursor
;
2844 my_cursor
= XCreateFontCursor (display
, cursor
);
2847 XDefineCursor (display
, window
, my_cursor
);
2848 lesstif_update_status_line ();
2852 static char *old_clip
= 0;
2853 static int old_tscale
= -1;
2854 char *new_clip
= cur_clip ();
2856 if (new_clip
!= old_clip
|| Settings
.TextScale
!= old_tscale
)
2858 lesstif_update_status_line ();
2859 old_clip
= new_clip
;
2860 old_tscale
= Settings
.TextScale
;
2865 static int old_nrats
= -1;
2866 static char buf
[20];
2868 if (old_nrats
!= PCB
->Data
->RatN
)
2870 old_nrats
= PCB
->Data
->RatN
;
2871 sprintf(buf
, "%d rat%s", PCB
->Data
->RatN
, PCB
->Data
->RatN
== 1 ? "" : "s");
2872 if (PCB
->Data
->RatN
)
2874 XtManageChild(XtParent(m_rats
));
2875 XtManageChild(m_rats
);
2877 stdarg (XmNleftWidget
, m_rats
);
2878 XtSetValues (XtParent (m_status
), args
, n
);
2882 stdarg (XmNlabelString
, XmStringCreatePCB (buf
));
2883 XtSetValues (m_rats
, args
, n
);
2885 if (!PCB
->Data
->RatN
)
2888 stdarg (XmNleftWidget
, m_mode
);
2889 XtSetValues (XtParent (m_status
), args
, n
);
2890 XtUnmanageChild(XtParent(m_rats
));
2895 lesstif_update_widget_flags ();
2903 lesstif_need_idle_proc ()
2905 if (idle_proc_set
|| window
== 0)
2907 XtAppAddWorkProc (app_context
, idle_proc
, 0);
2912 lesstif_invalidate_lr (int l
, int r
, int t
, int b
)
2922 lesstif_invalidate_all (void)
2924 lesstif_invalidate_lr (0, PCB
->MaxWidth
, 0, PCB
->MaxHeight
);
2928 lesstif_notify_crosshair_change (bool changes_complete
)
2930 static int invalidate_depth
= 0;
2936 if (changes_complete
)
2937 invalidate_depth
--;
2939 if (invalidate_depth
< 0)
2941 invalidate_depth
= 0;
2942 /* A mismatch of changes_complete == false and == true notifications
2943 * is not expected to occur, but we will try to handle it gracefully.
2944 * As we know the crosshair will have been shown already, we must
2945 * repaint the entire view to be sure not to leave an artaefact.
2951 if (invalidate_depth
== 0 && crosshair_on
)
2953 save_pixmap
= pixmap
;
2956 pixmap
= save_pixmap
;
2959 if (!changes_complete
)
2960 invalidate_depth
++;
2964 lesstif_notify_mark_change (bool changes_complete
)
2966 static int invalidate_depth
= 0;
2969 if (changes_complete
)
2970 invalidate_depth
--;
2972 if (invalidate_depth
< 0)
2974 invalidate_depth
= 0;
2975 /* A mismatch of changes_complete == false and == true notifications
2976 * is not expected to occur, but we will try to handle it gracefully.
2977 * As we know the mark will have been shown already, we must
2978 * repaint the entire view to be sure not to leave an artaefact.
2984 if (invalidate_depth
== 0 && crosshair_on
)
2986 save_pixmap
= pixmap
;
2989 pixmap
= save_pixmap
;
2992 if (!changes_complete
)
2993 invalidate_depth
++;
2997 lesstif_set_layer (const char *name
, int group
, int empty
)
3000 if (idx
>= 0 && idx
< max_group
)
3002 int n
= PCB
->LayerGroups
.Number
[group
];
3003 for (idx
= 0; idx
< n
-1; idx
++)
3005 int ni
= PCB
->LayerGroups
.Entries
[group
][idx
];
3006 if (ni
>= 0 && ni
< max_copper_layer
+ 2
3007 && PCB
->Data
->Layer
[ni
].On
)
3010 idx
= PCB
->LayerGroups
.Entries
[group
][idx
];
3012 if (idx
== LayerStack
[0]
3013 || GetLayerGroupNumberByNumber (idx
) ==
3014 GetLayerGroupNumberByNumber (LayerStack
[0]))
3024 if (idx
>= 0 && idx
< max_copper_layer
+ 2)
3025 return pinout
? 1 : PCB
->Data
->Layer
[idx
].On
;
3028 switch (SL_TYPE (idx
))
3031 return pinout
? 0 : PCB
->InvisibleObjectsOn
;
3033 if (SL_MYSIDE (idx
) && !pinout
)
3034 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
3037 if (SL_MYSIDE (idx
) || pinout
)
3038 return PCB
->ElementOn
;
3053 lesstif_make_gc (void)
3055 hidGC rv
= (hid_gc_struct
*) malloc (sizeof (hid_gc_struct
));
3056 memset (rv
, 0, sizeof (hid_gc_struct
));
3057 rv
->me_pointer
= &lesstif_hid
;
3062 lesstif_destroy_gc (hidGC gc
)
3068 lesstif_use_mask (int use_it
)
3070 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) &&
3073 if ((use_it
== 0) == (use_mask
== 0))
3080 /* printf("use_mask(%d)\n", use_it); */
3084 XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
,
3085 XDefaultDepth (display
, screen
));
3086 mask_bitmap
= XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
, 1);
3090 pixmap
= mask_pixmap
;
3091 XSetForeground (display
, my_gc
, 0);
3092 XSetFunction (display
, my_gc
, GXcopy
);
3093 XFillRectangle (display
, mask_pixmap
, my_gc
,
3094 0, 0, view_width
, view_height
);
3095 XFillRectangle (display
, mask_bitmap
, bclear_gc
,
3096 0, 0, view_width
, view_height
);
3100 pixmap
= main_pixmap
;
3104 XRenderPictureAttributes pa
;
3106 pa
.clip_mask
= mask_bitmap
;
3107 XRenderChangePicture(display
, main_picture
, CPClipMask
, &pa
);
3108 XRenderComposite(display
, PictOpOver
, mask_picture
, pale_picture
,
3109 main_picture
, 0, 0, 0, 0, 0, 0, view_width
, view_height
);
3112 #endif /* HAVE_XRENDER */
3114 XSetClipMask (display
, clip_gc
, mask_bitmap
);
3115 XCopyArea (display
, mask_pixmap
, main_pixmap
, clip_gc
,
3116 0, 0, view_width
, view_height
, 0, 0);
3122 lesstif_set_color (hidGC gc
, const char *name
)
3124 static void *cache
= 0;
3126 static XColor color
, exact_color
;
3132 gc
->colorname
= name
;
3133 if (strcmp (name
, "erase") == 0)
3135 gc
->color
= bgcolor
;
3138 else if (strcmp (name
, "drill") == 0)
3140 gc
->color
= offlimit_color
;
3143 else if (hid_cache_color (0, name
, &cval
, &cache
))
3145 gc
->color
= cval
.lval
;
3150 if (!XAllocNamedColor (display
, colormap
, name
, &color
, &exact_color
))
3151 color
.pixel
= WhitePixel (display
, screen
);
3153 printf ("lesstif_set_color `%s' %08x rgb/%d/%d/%d\n",
3154 name
, color
.pixel
, color
.red
, color
.green
, color
.blue
);
3156 cval
.lval
= gc
->color
= color
.pixel
;
3157 hid_cache_color (1, name
, &cval
, &cache
);
3162 static int lastcolor
= -1, lastfade
= -1;
3163 if (gc
->color
== lastcolor
)
3164 gc
->color
= lastfade
;
3167 lastcolor
= gc
->color
;
3168 color
.pixel
= gc
->color
;
3170 XQueryColor (display
, colormap
, &color
);
3171 color
.red
= (bgred
+ color
.red
) / 2;
3172 color
.green
= (bggreen
+ color
.green
) / 2;
3173 color
.blue
= (bgblue
+ color
.blue
) / 2;
3174 XAllocColor (display
, colormap
, &color
);
3175 lastfade
= gc
->color
= color
.pixel
;
3183 int cap
, join
, width
;
3184 if (gc
->me_pointer
!= &lesstif_hid
)
3186 fprintf (stderr
, "Fatal: GC from another HID passed to lesstif HID\n");
3190 pcb_printf ("set_gc c%s %08lx w%#mS c%d x%d e%d\n",
3191 gc
->colorname
, gc
->color
, gc
->width
, gc
->cap
, gc
->xor_set
, gc
->erase
);
3196 cap
= CapProjecting
;
3205 cap
= CapProjecting
;
3209 cap
= CapProjecting
;
3215 XSetFunction (display
, my_gc
, GXxor
);
3216 XSetForeground (display
, my_gc
, gc
->color
^ bgcolor
);
3220 XSetFunction (display
, my_gc
, GXcopy
);
3221 XSetForeground (display
, my_gc
, offlimit_color
);
3225 XSetFunction (display
, my_gc
, GXcopy
);
3226 XSetForeground (display
, my_gc
, gc
->color
);
3228 width
= Vz (gc
->width
);
3231 XSetLineAttributes (display
, my_gc
, width
, LineSolid
, cap
,
3236 mask_gc
= bclear_gc
;
3239 XSetLineAttributes (display
, mask_gc
, Vz (gc
->width
), LineSolid
, cap
,
3245 lesstif_set_line_cap (hidGC gc
, EndCapStyle style
)
3251 lesstif_set_line_width (hidGC gc
, Coord width
)
3257 lesstif_set_draw_xor (hidGC gc
, int xor_set
)
3259 gc
->xor_set
= xor_set
;
3262 #define ISORT(a,b) if (a>b) { a^=b; b^=a; a^=b; }
3265 lesstif_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3267 double dx1
, dy1
, dx2
, dy2
;
3268 int vw
= Vz (gc
->width
);
3269 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && gc
->erase
)
3272 pcb_printf ("draw_line %#mD-%#mD @%#mS", x1
, y1
, x2
, y2
, gc
->width
);
3279 pcb_printf (" = %#mD-%#mD %s\n", x1
, y1
, x2
, y2
, gc
->colorname
);
3283 if (! ClipLine (0, 0, view_width
, view_height
,
3284 &dx1
, &dy1
, &dx2
, &dy2
, vw
))
3294 if (gc
->cap
== Square_Cap
&& x1
== x2
&& y1
== y2
)
3296 XFillRectangle (display
, pixmap
, my_gc
, x1
- vw
/ 2, y1
- vw
/ 2, vw
,
3299 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
- vw
/ 2,
3300 y1
- vw
/ 2, vw
, vw
);
3304 XDrawLine (display
, pixmap
, my_gc
, x1
, y1
, x2
, y2
);
3306 XDrawLine (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
, y2
);
3311 lesstif_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord width
, Coord height
,
3312 Angle start_angle
, Angle delta_angle
)
3314 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3317 pcb_printf ("draw_arc %#mD %#mSx%#mS s %d d %d", cx
, cy
, width
, height
, start_angle
, delta_angle
);
3320 height
= Vz (height
);
3321 cx
= Vx (cx
) - width
;
3322 cy
= Vy (cy
) - height
;
3325 start_angle
= 180 - start_angle
;
3326 delta_angle
= - delta_angle
;
3330 start_angle
= - start_angle
;
3331 delta_angle
= - delta_angle
;
3333 start_angle
= NormalizeAngle (start_angle
);
3334 if (start_angle
>= 180)
3337 pcb_printf (" = %#mD %#mSx%#mS %d %s\n", cx
, cy
, width
, height
, gc
->width
,
3341 XDrawArc (display
, pixmap
, my_gc
, cx
, cy
,
3342 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3344 if (use_mask
&& !TEST_FLAG (THINDRAWFLAG
, PCB
))
3345 XDrawArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3346 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3349 /* Enable this if you want to see the center and radii of drawn
3350 arcs, for debugging. */
3351 if (TEST_FLAG (THINDRAWFLAG
, PCB
)
3352 && delta_angle
!= 360)
3356 XDrawLine (display
, pixmap
, arc1_gc
, cx
, cy
,
3357 cx
- width
*cos(start_angle
*M_PI
/180),
3358 cy
+ width
*sin(start_angle
*M_PI
/180));
3359 XDrawLine (display
, pixmap
, arc2_gc
, cx
, cy
,
3360 cx
- width
*cos((start_angle
+delta_angle
)*M_PI
/180),
3361 cy
+ width
*sin((start_angle
+delta_angle
)*M_PI
/180));
3367 lesstif_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3369 int vw
= Vz (gc
->width
);
3370 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3376 if (x1
< -vw
&& x2
< -vw
)
3378 if (y1
< -vw
&& y2
< -vw
)
3380 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3382 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3384 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3385 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3387 XDrawRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1, y2
- y1
+ 1);
3389 XDrawRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3394 lesstif_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
3396 if (pinout
&& use_mask
&& gc
->erase
)
3398 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && gc
->erase
)
3401 pcb_printf ("fill_circle %#mD %#mS", cx
, cy
, radius
);
3403 radius
= Vz (radius
);
3404 cx
= Vx (cx
) - radius
;
3405 cy
= Vy (cy
) - radius
;
3406 if (cx
< -2 * radius
|| cx
> view_width
)
3408 if (cy
< -2 * radius
|| cy
> view_height
)
3411 pcb_printf (" = %#mD %#mS %lx %s\n", cx
, cy
, radius
, gc
->color
, gc
->colorname
);
3414 XFillArc (display
, pixmap
, my_gc
, cx
, cy
,
3415 radius
* 2, radius
* 2, 0, 360 * 64);
3417 XFillArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3418 radius
* 2, radius
* 2, 0, 360 * 64);
3422 lesstif_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
3424 static XPoint
*p
= 0;
3425 static int maxp
= 0;
3428 if (maxp
< n_coords
)
3430 maxp
= n_coords
+ 10;
3432 p
= (XPoint
*) realloc (p
, maxp
* sizeof (XPoint
));
3434 p
= (XPoint
*) malloc (maxp
* sizeof (XPoint
));
3437 for (i
= 0; i
< n_coords
; i
++)
3443 printf ("fill_polygon %d pts\n", n_coords
);
3446 XFillPolygon (display
, pixmap
, my_gc
, p
, n_coords
, Complex
,
3449 XFillPolygon (display
, mask_bitmap
, mask_gc
, p
, n_coords
, Complex
,
3454 lesstif_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3456 int vw
= Vz (gc
->width
);
3457 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3463 if (x1
< -vw
&& x2
< -vw
)
3465 if (y1
< -vw
&& y2
< -vw
)
3467 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3469 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3471 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3472 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3474 XFillRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1,
3477 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3482 lesstif_calibrate (double xval
, double yval
)
3488 lesstif_shift_is_pressed (void)
3490 return shift_pressed
;
3494 lesstif_control_is_pressed (void)
3496 return ctrl_pressed
;
3500 lesstif_mod1_is_pressed (void)
3505 extern void lesstif_get_coords (const char *msg
, Coord
*x
, Coord
*y
);
3508 lesstif_set_crosshair (int x
, int y
, int action
)
3510 if (crosshair_x
!= x
|| crosshair_y
!= y
)
3512 lesstif_show_crosshair(0);
3520 || x
> view_left_x
+ view_width
* view_zoom
3521 || y
< view_top_y
|| y
> view_top_y
+ view_height
* view_zoom
))
3523 view_left_x
= x
- (view_width
* view_zoom
) / 2;
3524 view_top_y
= y
- (view_height
* view_zoom
) / 2;
3525 lesstif_pan_fixup ();
3530 if (action
== HID_SC_PAN_VIEWPORT
)
3533 unsigned int keys_buttons
;
3534 int pos_x
, pos_y
, root_x
, root_y
;
3535 XQueryPointer (display
, window
, &root
, &child
,
3536 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
3538 view_left_x
= x
- (view_width
-pos_x
) * view_zoom
;
3540 view_left_x
= x
- pos_x
* view_zoom
;
3542 view_top_y
= y
- (view_height
-pos_y
) * view_zoom
;
3544 view_top_y
= y
- pos_y
* view_zoom
;
3545 lesstif_pan_fixup();
3546 action
= HID_SC_WARP_POINTER
;
3548 if (action
== HID_SC_WARP_POINTER
)
3551 XWarpPointer (display
, None
, window
, 0, 0, 0, 0, Vx(x
), Vy(y
));
3558 void (*func
) (hidval
);
3564 lesstif_timer_cb (XtPointer
* p
, XtIntervalId
* id
)
3566 TimerStruct
*ts
= (TimerStruct
*) p
;
3567 ts
->func (ts
->user_data
);
3572 lesstif_add_timer (void (*func
) (hidval user_data
),
3573 unsigned long milliseconds
, hidval user_data
)
3577 t
= (TimerStruct
*) malloc (sizeof (TimerStruct
));
3580 t
->user_data
= user_data
;
3581 t
->id
= XtAppAddTimeOut (app_context
, milliseconds
, (XtTimerCallbackProc
)lesstif_timer_cb
, t
);
3586 lesstif_stop_timer (hidval hv
)
3588 TimerStruct
*ts
= (TimerStruct
*) hv
.ptr
;
3589 XtRemoveTimeOut (ts
->id
);
3596 void (*func
) ( hidval
, int, unsigned int, hidval
);
3603 /* We need a wrapper around the hid file watch because to pass the correct flags
3606 lesstif_watch_cb (XtPointer client_data
, int *fid
, XtInputId
* id
)
3608 unsigned int pcb_condition
= 0;
3612 WatchStruct
*watch
= (WatchStruct
*)client_data
;
3615 fds
.events
= POLLIN
| POLLOUT
;
3617 condition
= fds
.revents
;
3619 // Should we only include those we were asked to watch?
3620 if (condition
& POLLIN
)
3621 pcb_condition
|= PCB_WATCH_READABLE
;
3622 if (condition
& POLLOUT
)
3623 pcb_condition
|= PCB_WATCH_WRITABLE
;
3624 if (condition
& POLLERR
)
3625 pcb_condition
|= PCB_WATCH_ERROR
;
3626 if (condition
& POLLHUP
)
3627 pcb_condition
|= PCB_WATCH_HANGUP
;
3629 x
.ptr
= (void *) watch
;
3630 watch
->func (x
, watch
->fd
, pcb_condition
, watch
->user_data
);
3636 lesstif_watch_file (int fd
, unsigned int condition
, void (*func
) (hidval watch
, int fd
, unsigned int condition
, hidval user_data
),
3639 WatchStruct
*watch
= (WatchStruct
*) malloc (sizeof(WatchStruct
));
3641 unsigned int xt_condition
= 0;
3643 if (condition
& PCB_WATCH_READABLE
)
3644 xt_condition
|= XtInputReadMask
;
3645 if (condition
& PCB_WATCH_WRITABLE
)
3646 xt_condition
|= XtInputWriteMask
;
3647 if (condition
& PCB_WATCH_ERROR
)
3648 xt_condition
|= XtInputExceptMask
;
3649 if (condition
& PCB_WATCH_HANGUP
)
3650 xt_condition
|= XtInputExceptMask
;
3653 watch
->user_data
= user_data
;
3655 watch
->id
= XtAppAddInput( app_context
, fd
, (XtPointer
) (size_t) xt_condition
, lesstif_watch_cb
, watch
);
3657 ret
.ptr
= (void *) watch
;
3662 lesstif_unwatch_file (hidval data
)
3664 WatchStruct
*watch
= (WatchStruct
*)data
.ptr
;
3665 XtRemoveInput( watch
->id
);
3672 void (*func
) (hidval user_data
);
3676 static void lesstif_block_hook_cb(XtPointer user_data
);
3679 lesstif_block_hook_cb (XtPointer user_data
)
3681 BlockHookStruct
*block_hook
= (BlockHookStruct
*)user_data
;
3682 block_hook
->func( block_hook
->user_data
);
3686 lesstif_add_block_hook (void (*func
) (hidval data
), hidval user_data
)
3689 BlockHookStruct
*block_hook
= (BlockHookStruct
*) malloc( sizeof( BlockHookStruct
));
3691 block_hook
->func
= func
;
3692 block_hook
->user_data
= user_data
;
3694 block_hook
->id
= XtAppAddBlockHook( app_context
, lesstif_block_hook_cb
, (XtPointer
)block_hook
);
3696 ret
.ptr
= (void *) block_hook
;
3701 lesstif_stop_block_hook (hidval mlpoll
)
3703 BlockHookStruct
*block_hook
= (BlockHookStruct
*)mlpoll
.ptr
;
3704 XtRemoveBlockHook( block_hook
->id
);
3709 extern void lesstif_logv (const char *fmt
, va_list ap
);
3711 extern int lesstif_confirm_dialog (char *msg
, ...);
3713 extern int lesstif_close_confirm_dialog ();
3715 extern void lesstif_report_dialog (char *title
, char *msg
);
3718 lesstif_attribute_dialog (HID_Attribute
* attrs
,
3719 int n_attrs
, HID_Attr_Val
* results
,
3720 const char * title
, const char * descr
);
3723 pinout_callback (Widget da
, PinoutData
* pd
,
3724 XmDrawingAreaCallbackStruct
* cbs
)
3727 int save_vx
, save_vy
, save_vw
, save_vh
;
3728 int save_fx
, save_fy
;
3731 int reason
= cbs
? cbs
->reason
: 0;
3733 if (pd
->window
== 0 && reason
== XmCR_RESIZE
)
3735 if (pd
->window
== 0 || reason
== XmCR_RESIZE
)
3741 stdarg (XmNwidth
, &w
);
3742 stdarg (XmNheight
, &h
);
3743 XtGetValues (da
, args
, n
);
3745 pd
->window
= XtWindow (da
);
3748 pd
->zoom
= (pd
->right
- pd
->left
+ 1) / (double) w
;
3749 z
= (pd
->bottom
- pd
->top
+ 1) / (double) h
;
3753 pd
->x
= (pd
->left
+ pd
->right
) / 2 - pd
->v_width
* pd
->zoom
/ 2;
3754 pd
->y
= (pd
->top
+ pd
->bottom
) / 2 - pd
->v_height
* pd
->zoom
/ 2;
3757 save_vx
= view_left_x
;
3758 save_vy
= view_top_y
;
3759 save_vz
= view_zoom
;
3760 save_vw
= view_width
;
3761 save_vh
= view_height
;
3766 pixmap
= pd
->window
;
3767 view_left_x
= pd
->x
;
3769 view_zoom
= pd
->zoom
;
3770 view_width
= pd
->v_width
;
3771 view_height
= pd
->v_height
;
3773 flip_x
= flip_y
= 0;
3777 region
.X2
= PCB
->MaxWidth
;
3778 region
.Y2
= PCB
->MaxHeight
;
3780 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, pd
->v_width
, pd
->v_height
);
3781 hid_expose_callback (&lesstif_hid
, ®ion
, pd
->item
);
3784 view_left_x
= save_vx
;
3785 view_top_y
= save_vy
;
3786 view_zoom
= save_vz
;
3787 view_width
= save_vw
;
3788 view_height
= save_vh
;
3795 pinout_unmap (Widget w
, PinoutData
* pd
, void *v
)
3798 pd
->prev
->next
= pd
->next
;
3802 pd
->next
->prev
= pd
->prev
;
3803 XtDestroyWidget (XtParent (pd
->form
));
3808 lesstif_show_item (void *item
)
3815 for (pd
= pinouts
; pd
; pd
= pd
->next
)
3816 if (pd
->item
== item
)
3821 pd
= (PinoutData
*) calloc (1, sizeof (PinoutData
));
3825 extents
= hid_get_extents (item
);
3826 pd
->left
= extents
->X1
;
3827 pd
->right
= extents
->X2
;
3828 pd
->top
= extents
->Y1
;
3829 pd
->bottom
= extents
->Y2
;
3831 if (pd
->left
> pd
->right
)
3839 pd
->next
->prev
= pd
;
3844 pd
->form
= XmCreateFormDialog (mainwind
, "pinout", args
, n
);
3846 XtAddCallback (pd
->form
, XmNunmapCallback
, (XtCallbackProc
) pinout_unmap
,
3850 sqrt (200.0 * 200.0 /
3851 ((pd
->right
- pd
->left
+ 1.0) * (pd
->bottom
- pd
->top
+ 1.0)));
3854 stdarg (XmNwidth
, (int) (scale
* (pd
->right
- pd
->left
+ 1)));
3855 stdarg (XmNheight
, (int) (scale
* (pd
->bottom
- pd
->top
+ 1)));
3856 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
3857 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
3858 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
3859 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
3860 da
= XmCreateDrawingArea (pd
->form
, "pinout", args
, n
);
3863 XtAddCallback (da
, XmNexposeCallback
, (XtCallbackProc
) pinout_callback
,
3865 XtAddCallback (da
, XmNresizeCallback
, (XtCallbackProc
) pinout_callback
,
3868 XtManageChild (pd
->form
);
3880 static bool progress_cancelled
= false;
3883 progress_cancel_callback (Widget w
, void *v
, void *cbs
)
3885 progress_cancelled
= true;
3888 static Widget progress_dialog
= 0;
3889 static Widget progress_cancel
, progress_label
;
3890 static Widget progress_scale
;
3893 lesstif_progress_dialog (int so_far
, int total
, const char *msg
)
3900 if (progress_dialog
== 0)
3905 stdarg (XmNdefaultButtonType
, XmDIALOG_CANCEL_BUTTON
);
3906 stdarg (XmNtitle
, "Progress");
3907 stdarg (XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
);
3908 stdarg (XmNdialogStyle
, XmDIALOG_FULL_APPLICATION_MODAL
);
3909 progress_dialog
= XmCreateInformationDialog (mainwind
, "progress", args
, n
);
3910 XtAddCallback (progress_dialog
, XmNcancelCallback
,
3911 (XtCallbackProc
) progress_cancel_callback
, NULL
);
3913 progress_cancel
= XmMessageBoxGetChild (progress_dialog
, XmDIALOG_CANCEL_BUTTON
);
3914 progress_label
= XmMessageBoxGetChild (progress_dialog
, XmDIALOG_MESSAGE_LABEL
);
3916 XtUnmanageChild (XmMessageBoxGetChild (progress_dialog
, XmDIALOG_OK_BUTTON
));
3917 XtUnmanageChild (XmMessageBoxGetChild (progress_dialog
, XmDIALOG_HELP_BUTTON
));
3919 stdarg (XmNdefaultPosition
, False
);
3920 XtSetValues (progress_dialog
, args
, n
);
3923 stdarg(XmNminimum
, 0);
3924 stdarg(XmNvalue
, 0);
3925 stdarg(XmNmaximum
, total
> 0 ? total
: 1);
3926 stdarg(XmNorientation
, XmHORIZONTAL
);
3927 stdarg(XmNshowArrows
, false);
3928 progress_scale
= XmCreateScrollBar (progress_dialog
, "scale", args
, n
);
3929 XtManageChild (progress_scale
);
3931 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
3932 XmAddWMProtocolCallback (XtParent (progress_dialog
), close_atom
,
3933 (XtCallbackProc
) progress_cancel_callback
, 0);
3937 stdarg(XmNvalue
, 0);
3938 stdarg(XmNsliderSize
, (so_far
<= total
) ? (so_far
< 0) ? 0 : so_far
: total
);
3939 stdarg(XmNmaximum
, total
> 0 ? total
: 1);
3940 XtSetValues (progress_scale
, args
, n
);
3943 xs
= XmStringCreatePCB ((char *)msg
);
3944 stdarg (XmNmessageString
, xs
);
3945 XtSetValues (progress_dialog
, args
, n
);
3950 #define MIN_TIME_SEPARATION 0.1 /* seconds */
3953 lesstif_progress (int so_far
, int total
, const char *message
)
3955 static bool visible
= false;
3956 static bool started
= false;
3958 struct timeval time
;
3959 double time_delta
, time_now
;
3960 static double time_then
= 0.0;
3963 if (so_far
== 0 && total
== 0 && message
== NULL
)
3965 XtUnmanageChild (progress_dialog
);
3968 progress_cancelled
= false;
3972 gettimeofday (&time
, NULL
);
3973 time_now
= time
.tv_sec
+ time
.tv_usec
/ 1000000.0;
3975 time_delta
= time_now
- time_then
;
3977 if (started
&& time_delta
< MIN_TIME_SEPARATION
)
3980 /* Create or update the progress dialog */
3981 lesstif_progress_dialog (so_far
, total
, message
);
3985 XtManageChild (progress_dialog
);
3989 /* Dispatch pending events */
3990 while (XtAppPending (app_context
))
3992 XtAppNextEvent (app_context
, &e
);
3993 XtDispatchEvent (&e
);
3997 /* If rendering takes a while, make sure the core has enough time to
3999 gettimeofday (&time
, NULL
);
4000 time_then
= time
.tv_sec
+ time
.tv_usec
/ 1000000.0;
4002 return progress_cancelled
;
4006 lesstif_request_debug_draw (void)
4008 /* Send drawing to the backing pixmap */
4009 pixmap
= main_pixmap
;
4010 return lesstif_hid
.graphics
;
4014 lesstif_flush_debug_draw (void)
4016 /* Copy the backing pixmap to the display and redraw any attached objects */
4017 XSetFunction (display
, my_gc
, GXcopy
);
4018 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
4026 pixmap
= main_pixmap
;
4030 lesstif_finish_debug_draw (void)
4032 lesstif_flush_debug_draw ();
4033 /* No special tear down requirements
4037 #include "dolists.h"
4042 memset (&lesstif_hid
, 0, sizeof (HID
));
4043 memset (&lesstif_graphics
, 0, sizeof (HID_DRAW
));
4045 common_nogui_init (&lesstif_hid
);
4046 common_draw_helpers_init (&lesstif_graphics
);
4048 lesstif_hid
.struct_size
= sizeof (HID
);
4049 lesstif_hid
.name
= "lesstif";
4050 lesstif_hid
.description
= "LessTif - a Motif clone for X/Unix";
4051 lesstif_hid
.gui
= 1;
4052 lesstif_hid
.poly_before
= 1;
4054 lesstif_hid
.get_export_options
= lesstif_get_export_options
;
4055 lesstif_hid
.do_export
= lesstif_do_export
;
4056 lesstif_hid
.parse_arguments
= lesstif_parse_arguments
;
4057 lesstif_hid
.invalidate_lr
= lesstif_invalidate_lr
;
4058 lesstif_hid
.invalidate_all
= lesstif_invalidate_all
;
4059 lesstif_hid
.notify_crosshair_change
= lesstif_notify_crosshair_change
;
4060 lesstif_hid
.notify_mark_change
= lesstif_notify_mark_change
;
4061 lesstif_hid
.set_layer
= lesstif_set_layer
;
4063 lesstif_hid
.calibrate
= lesstif_calibrate
;
4064 lesstif_hid
.shift_is_pressed
= lesstif_shift_is_pressed
;
4065 lesstif_hid
.control_is_pressed
= lesstif_control_is_pressed
;
4066 lesstif_hid
.mod1_is_pressed
= lesstif_mod1_is_pressed
;
4067 lesstif_hid
.get_coords
= lesstif_get_coords
;
4068 lesstif_hid
.set_crosshair
= lesstif_set_crosshair
;
4069 lesstif_hid
.add_timer
= lesstif_add_timer
;
4070 lesstif_hid
.stop_timer
= lesstif_stop_timer
;
4071 lesstif_hid
.watch_file
= lesstif_watch_file
;
4072 lesstif_hid
.unwatch_file
= lesstif_unwatch_file
;
4073 lesstif_hid
.add_block_hook
= lesstif_add_block_hook
;
4074 lesstif_hid
.stop_block_hook
= lesstif_stop_block_hook
;
4076 lesstif_hid
.log
= lesstif_log
;
4077 lesstif_hid
.logv
= lesstif_logv
;
4078 lesstif_hid
.confirm_dialog
= lesstif_confirm_dialog
;
4079 lesstif_hid
.close_confirm_dialog
= lesstif_close_confirm_dialog
;
4080 lesstif_hid
.report_dialog
= lesstif_report_dialog
;
4081 lesstif_hid
.prompt_for
= lesstif_prompt_for
;
4082 lesstif_hid
.fileselect
= lesstif_fileselect
;
4083 lesstif_hid
.attribute_dialog
= lesstif_attribute_dialog
;
4084 lesstif_hid
.show_item
= lesstif_show_item
;
4085 lesstif_hid
.beep
= lesstif_beep
;
4086 lesstif_hid
.progress
= lesstif_progress
;
4087 lesstif_hid
.edit_attributes
= lesstif_attributes_dialog
;
4089 lesstif_hid
.request_debug_draw
= lesstif_request_debug_draw
;
4090 lesstif_hid
.flush_debug_draw
= lesstif_flush_debug_draw
;
4091 lesstif_hid
.finish_debug_draw
= lesstif_finish_debug_draw
;
4093 lesstif_hid
.graphics
= &lesstif_graphics
;
4095 lesstif_graphics
.make_gc
= lesstif_make_gc
;
4096 lesstif_graphics
.destroy_gc
= lesstif_destroy_gc
;
4097 lesstif_graphics
.use_mask
= lesstif_use_mask
;
4098 lesstif_graphics
.set_color
= lesstif_set_color
;
4099 lesstif_graphics
.set_line_cap
= lesstif_set_line_cap
;
4100 lesstif_graphics
.set_line_width
= lesstif_set_line_width
;
4101 lesstif_graphics
.set_draw_xor
= lesstif_set_draw_xor
;
4102 lesstif_graphics
.draw_line
= lesstif_draw_line
;
4103 lesstif_graphics
.draw_arc
= lesstif_draw_arc
;
4104 lesstif_graphics
.draw_rect
= lesstif_draw_rect
;
4105 lesstif_graphics
.fill_circle
= lesstif_fill_circle
;
4106 lesstif_graphics
.fill_polygon
= lesstif_fill_polygon
;
4107 lesstif_graphics
.fill_rect
= lesstif_fill_rect
;
4109 lesstif_graphics
.draw_pcb_polygon
= common_gui_draw_pcb_polygon
;
4111 hid_register_hid (&lesstif_hid
);
4112 #include "lesstif_lists.h"