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 lesstif_gc_struct
51 struct hid_gc_struct hid_gc
/* Parent */;
54 const char *colorname
;
61 static HID lesstif_hid
;
62 static HID_DRAW lesstif_graphics
;
63 static HID_DRAW_CLASS lesstif_graphics_class
;
65 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented GUI function %s\n", __FUNCTION__), abort()
67 XtAppContext app_context
;
70 static Window window
= 0;
71 static Cursor my_cursor
= 0;
72 static int old_cursor_mode
= -1;
73 static int over_point
= 0;
75 /* The first is the "current" pixmap. The main_ is the real one we
76 usually use, the mask_ are the ones for doing polygon masks. The
77 pixmap is the saved pixels, the bitmap is for the "erase" color.
78 We set pixmap to point to main_pixmap or mask_pixmap as needed. */
79 static Pixmap pixmap
= 0;
80 static Pixmap main_pixmap
= 0;
81 static Pixmap mask_pixmap
= 0;
82 static Pixmap mask_bitmap
= 0;
83 static enum mask_mode use_mask
= HID_MASK_OFF
;
85 static int use_xrender
= 0;
87 static Picture main_picture
;
88 static Picture mask_picture
;
89 static Pixmap pale_pixmap
;
90 static Picture pale_picture
;
91 #endif /* HAVE_XRENDER */
93 static int pixmap_w
= 0, pixmap_h
= 0;
96 static Colormap colormap
;
97 static GC my_gc
= 0, bg_gc
, clip_gc
= 0, bset_gc
= 0, bclear_gc
= 0, mask_gc
=
99 static Pixel bgcolor
, offlimit_color
, grid_color
;
100 static int bgred
, bggreen
, bgblue
;
102 static GC arc1_gc
, arc2_gc
;
104 static hidGC crosshair_gc
;
106 /* These are for the pinout windows. */
107 typedef struct PinoutData
109 struct PinoutData
*prev
, *next
;
112 Coord left
, right
, top
, bottom
; /* PCB extents of item */
113 Coord x
, y
; /* PCB coordinates of upper right corner of window */
114 double zoom
; /* PCB units per screen pixel */
115 int v_width
, v_height
; /* pixels */
119 /* Linked list of all pinout windows. */
120 static PinoutData
*pinouts
= 0;
121 /* If set, we are currently updating this pinout window. */
122 static PinoutData
*pinout
= 0;
124 static int crosshair_x
= 0, crosshair_y
= 0;
125 static int in_move_event
= 0, crosshair_in_window
= 1;
128 Widget work_area
, messages
, command
, hscroll
, vscroll
;
129 static Widget m_mark
, m_crosshair
, m_grid
, m_zoom
, m_mode
, m_status
;
130 static Widget m_rats
;
131 Widget lesstif_m_layer
;
134 /* This is the size, in pixels, of the viewport. */
135 static int view_width
, view_height
;
136 /* This is the PCB location represented by the upper left corner of
137 the viewport. Note that PCB coordinates put 0,0 in the upper left,
139 static int view_left_x
= 0, view_top_y
= 0;
140 /* Denotes PCB units per screen pixel. Larger numbers mean zooming
141 out - the largest value means you are looking at the whole
143 static double view_zoom
= MIL_TO_COORD (10), prev_view_zoom
= MIL_TO_COORD (10);
144 static bool flip_x
= 0, flip_y
= 0;
145 static bool autofade
= 0;
146 static bool crosshair_on
= true;
148 /* ---------------------------------------------------------------------------
149 * some local prototypes
151 static hidGC
lesstif_make_gc (void);
154 ShowCrosshair (bool show
)
156 if (crosshair_on
== show
)
159 notify_crosshair_change (false);
161 notify_mark_change (false);
165 notify_crosshair_change (true);
167 notify_mark_change (true);
171 flag_flipx (void *data
)
176 flag_flipy (void *data
)
181 HID_Flag lesstif_main_flag_list
[] = {
182 {"flip_x", flag_flipx
, NULL
},
183 {"flip_y", flag_flipy
, NULL
}
186 REGISTER_FLAGS (lesstif_main_flag_list
)
188 /* This is the size of the current PCB work area. */
189 /* Use PCB->MaxWidth, PCB->MaxHeight. */
190 /* static int pcb_width, pcb_height; */
194 #define stdarg(t,v) XtSetArg(args[n], t, v), n++
197 static int use_private_colormap
= 0;
198 static int stdin_listen
= 0;
199 static char *background_image_file
= 0;
200 char *lesstif_pcbmenu_path
= "pcb-menu.res";
202 HID_Attribute lesstif_attribute_list
[] = {
203 {"install", "Install private colormap",
204 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &use_private_colormap
},
205 #define HA_colormap 0
207 /* %start-doc options "22 lesstif GUI Options"
210 Listen for actions on stdin.
214 {"listen", "Listen on standard input for actions",
215 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &stdin_listen
},
218 /* %start-doc options "22 lesstif GUI Options"
220 @item --bg-image <string>
221 File name of an image to put into the background of the GUI canvas. The image must
222 be a color PPM image, in binary (not ASCII) format. It can be any size, and will be
223 automatically scaled to fit the canvas.
227 {"bg-image", "Background Image",
228 HID_String
, 0, 0, {0, 0, 0}, 0, &background_image_file
},
229 #define HA_bg_image 2
231 /* %start-doc options "22 lesstif GUI Options"
233 @item --pcb-menu <string>
234 Location of the @file{pcb-menu.res} file which defines the menu for the lesstif GUI.
238 {"pcb-menu", "Location of pcb-menu.res file",
239 HID_String
, 0, 0, {0, PCBLIBDIR
"/pcb-menu.res", 0}, 0, &lesstif_pcbmenu_path
}
243 REGISTER_ATTRIBUTES (lesstif_attribute_list
)
245 static void lesstif_use_mask (enum mask_mode mode
);
246 static void zoom_max ();
247 static void zoom_to (double factor
, int x
, int y
);
248 static void zoom_by (double factor
, int x
, int y
);
249 static void zoom_toggle (int x
, int y
);
250 static void pinout_callback (Widget
, PinoutData
*,
251 XmDrawingAreaCallbackStruct
*);
252 static void pinout_unmap (Widget
, PinoutData
*, void *);
253 static void Pan (int mode
, int x
, int y
);
255 /* Px converts view->pcb, Vx converts pcb->view */
260 int rv
= (x
- view_left_x
) / view_zoom
+ 0.5;
262 rv
= view_width
- rv
;
269 int rv
= (y
- view_top_y
) / view_zoom
+ 0.5;
271 rv
= view_height
- rv
;
278 return z
/ view_zoom
+ 0.5;
286 return x
* view_zoom
+ view_left_x
;
294 return y
* view_zoom
+ view_top_y
;
300 return z
* view_zoom
;
304 lesstif_coords_to_pcb (int vx
, int vy
, Coord
*px
, Coord
*py
)
311 lesstif_parse_color (char *value
)
314 if (XParseColor (display
, colormap
, value
, &color
))
315 if (XAllocColor (display
, colormap
, &color
))
321 do_color (char *value
, char *which
)
324 if (XParseColor (display
, colormap
, value
, &color
))
325 if (XAllocColor (display
, colormap
, &color
))
327 stdarg (which
, color
.pixel
);
331 /* ------------------------------------------------------------ */
336 if (TEST_FLAG (ORTHOMOVEFLAG
, PCB
))
338 if (TEST_FLAG (ALLDIRECTIONFLAG
, PCB
))
340 if (PCB
->Clipping
== 0)
342 if (PCB
->Clipping
== 1)
347 /* Called from the core when it's busy doing something and we need to
348 indicate that to the user. */
350 Busy(int argc
, char **argv
, Coord x
, Coord y
)
352 static Cursor busy_cursor
= 0;
353 if (busy_cursor
== 0)
354 busy_cursor
= XCreateFontCursor (display
, XC_watch
);
355 XDefineCursor (display
, window
, busy_cursor
);
357 old_cursor_mode
= -1;
361 /* ---------------------------------------------------------------------- */
366 PointCursor (int argc
, char **argv
, Coord x
, Coord y
)
372 old_cursor_mode
= -1;
377 PCBChanged (int argc
, char **argv
, Coord x
, Coord y
)
381 /*pcb_printf("PCB Changed! %$mD\n", PCB->MaxWidth, PCB->MaxHeight); */
383 stdarg (XmNminimum
, 0);
384 stdarg (XmNvalue
, 0);
385 stdarg (XmNsliderSize
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
386 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
387 XtSetValues (hscroll
, args
, n
);
389 stdarg (XmNminimum
, 0);
390 stdarg (XmNvalue
, 0);
391 stdarg (XmNsliderSize
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
392 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
393 XtSetValues (vscroll
, args
, n
);
396 hid_action ("NetlistChanged");
397 hid_action ("LayersChanged");
398 hid_action ("RouteStylesChanged");
399 lesstif_sizes_reset ();
400 lesstif_update_layer_groups ();
402 pinout_unmap (0, pinouts
, 0);
405 char *cp
= strrchr (PCB
->Filename
, '/');
407 stdarg (XmNtitle
, cp
? cp
+ 1 : PCB
->Filename
);
408 XtSetValues (appwidget
, args
, n
);
414 static const char setunits_syntax
[] =
417 static const char setunits_help
[] =
418 "Set the default measurement units.";
420 /* %start-doc actions SetUnits
425 Sets the display units to mils (1/1000 inch).
428 Sets the display units to millimeters.
435 SetUnits (int argc
, char **argv
, Coord x
, Coord y
)
437 const Unit
*new_unit
;
440 new_unit
= get_unit_struct (argv
[0]);
441 if (new_unit
!= NULL
&& new_unit
->allow
!= NO_PRINT
)
443 Settings
.grid_unit
= new_unit
;
444 Settings
.increments
= get_increments_struct (Settings
.grid_unit
->family
);
445 AttributePut (PCB
, "PCB::grid::unit", argv
[0]);
447 lesstif_sizes_reset ();
448 lesstif_styles_update_values ();
452 static const char zoom_syntax
[] =
456 static const char zoom_help
[] =
457 "Various zoom factor changes.";
459 /* %start-doc actions Zoom
461 Changes the zoom (magnification) of the view of the board. If no
462 arguments are passed, the view is scaled such that the board just fits
463 inside the visible window (i.e. ``view all''). Otherwise,
464 @var{factor} specifies a change in zoom factor. It may be prefixed by
465 @code{+}, @code{-}, or @code{=} to change how the zoom factor is
466 modified. The @var{factor} is a floating point number, such as
467 @code{1.5} or @code{0.75}.
472 Values greater than 1.0 cause the board to be drawn smaller; more of
473 the board will be visible. Values between 0.0 and 1.0 cause the board
474 to be drawn bigger; less of the board will be visible.
477 Values greater than 1.0 cause the board to be drawn bigger; less of
478 the board will be visible. Values between 0.0 and 1.0 cause the board
479 to be drawn smaller; more of the board will be visible.
483 The @var{factor} is an absolute zoom factor; the unit for this value
484 is "PCB units per screen pixel". Since PCB units are 0.01 mil, a
485 @var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI,
486 about the actual resolution of most screens - resulting in an "actual
487 size" board. Similarly, a @var{factor} of 100 gives you a 10x actual
492 Note that zoom factors of zero are silently ignored.
497 ZoomAction (int argc
, char **argv
, Coord x
, Coord y
)
501 if (x
== 0 && y
== 0)
517 if (strcasecmp (vp
, "toggle") == 0)
522 if (*vp
== '+' || *vp
== '-' || *vp
== '=')
524 v
= g_ascii_strtod (vp
, 0);
530 zoom_by (1 / v
, x
, y
);
543 static int pan_thumb_mode
;
546 PanAction (int argc
, char **argv
, Coord x
, Coord y
)
555 pan_thumb_mode
= (strcasecmp (argv
[0], "thumb") == 0) ? 1 : 0;
556 mode
= atoi (argv
[1]);
561 mode
= atoi (argv
[0]);
563 Pan (mode
, Vx(x
), Vy(y
));
568 static const char swapsides_syntax
[] =
571 static const char swapsides_help
[] =
572 "Swaps the side of the board you're looking at.";
574 /* %start-doc actions SwapSides
576 This action changes the way you view the board.
581 Flips the board over vertically (up/down).
584 Flips the board over horizontally (left/right), like flipping pages in
588 Rotates the board 180 degrees without changing sides.
592 If no argument is given, the board isn't moved but the opposite side
595 Normally, this action changes which pads and silk layer are drawn as
596 true silk, and which are drawn as the "invisible" layer. It also
597 determines which solder mask you see.
599 As a special case, if the layer group for the side you're looking at
600 is visible and currently active, and the layer group for the opposite
601 is not visible (i.e. disabled), then this action will also swap which
602 layer group is visible and active, effectively swapping the ``working
608 group_showing (int g
, int *c
)
611 *c
= PCB
->LayerGroups
.Entries
[g
][0];
612 for (i
=0; i
<PCB
->LayerGroups
.Number
[g
]; i
++)
614 l
= PCB
->LayerGroups
.Entries
[g
][i
];
615 if (l
>= 0 && l
< max_copper_layer
)
618 if (PCB
->Data
->Layer
[l
].On
)
626 SwapSides (int argc
, char **argv
, Coord x
, Coord y
)
628 int old_shown_side
= Settings
.ShowBottomSide
;
629 int top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
630 int bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
631 int active_group
= GetLayerGroupNumberByNumber (LayerStack
[0]);
634 int top_showing
= group_showing (top_group
, &top_layer
);
635 int bottom_showing
= group_showing (bottom_group
, &bottom_layer
);
639 switch (argv
[0][0]) {
656 /* SwapSides will swap this */
657 Settings
.ShowBottomSide
= (flip_x
== flip_y
);
662 stdarg (XmNprocessingDirection
, XmMAX_ON_LEFT
);
664 stdarg (XmNprocessingDirection
, XmMAX_ON_RIGHT
);
665 XtSetValues (hscroll
, args
, n
);
669 stdarg (XmNprocessingDirection
, XmMAX_ON_TOP
);
671 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
672 XtSetValues (vscroll
, args
, n
);
674 Settings
.ShowBottomSide
= !Settings
.ShowBottomSide
;
676 /* The idea is that if we're looking at the front side and the front
677 layer is active (or visa versa), switching sides should switch
678 layers too. We used to only do this if the other layer wasn't
679 shown, but we now do it always. Change it back if users get
681 if (Settings
.ShowBottomSide
!= old_shown_side
)
683 if (Settings
.ShowBottomSide
)
685 if (active_group
== top_group
)
687 if (top_showing
&& !bottom_showing
)
688 ChangeGroupVisibility (top_layer
, 0, 0);
689 ChangeGroupVisibility (bottom_layer
, 1, 1);
694 if (active_group
== bottom_group
)
696 if (bottom_showing
&& !top_showing
)
697 ChangeGroupVisibility (bottom_layer
, 0, 0);
698 ChangeGroupVisibility (top_layer
, 1, 1);
702 lesstif_invalidate_all ();
706 static Widget m_cmd
= 0, m_cmd_label
;
709 command_callback (Widget w
, XtPointer uptr
, XmTextVerifyCallbackStruct
* cbs
)
715 s
= XmTextGetString (w
);
716 lesstif_show_crosshair (0);
717 hid_parse_command (s
);
719 XmTextSetString (w
, "");
720 case XmCR_LOSING_FOCUS
:
721 XtUnmanageChild (m_cmd
);
722 XtUnmanageChild (m_cmd_label
);
728 command_event_handler (Widget w
, XtPointer p
, XEvent
* e
, Boolean
* cont
)
736 XLookupString ((XKeyEvent
*)e
, buf
, sizeof (buf
), &sym
, NULL
);
740 XtUnmanageChild (m_cmd
);
741 XtUnmanageChild (m_cmd_label
);
742 XmTextSetString (w
, "");
750 static const char command_syntax
[] =
753 static const char command_help
[] =
754 "Displays the command line input window.";
756 /* %start-doc actions Command
758 The command window allows the user to manually enter actions to be
759 executed. Action syntax can be done one of two ways:
764 Follow the action name by an open parenthesis, arguments separated by
765 commas, end with a close parenthesis. Example: @code{Abc(1,2,3)}
768 Separate the action name and arguments by spaces. Example: @code{Abc
773 The first option allows you to have arguments with spaces in them,
774 but the second is more ``natural'' to type for most people.
776 Note that action names are not case sensitive, but arguments normally
777 are. However, most actions will check for ``keywords'' in a case
780 There are three ways to finish with the command window. If you press
781 the @code{Enter} key, the command is invoked, the window goes away,
782 and the next time you bring up the command window it's empty. If you
783 press the @code{Esc} key, the window goes away without invoking
784 anything, and the next time you bring up the command window it's
785 empty. If you change focus away from the command window (i.e. click
786 on some other window), the command window goes away but the next time
787 you bring it up it resumes entering the command you were entering
793 Command (int argc
, char **argv
, Coord x
, Coord y
)
795 XtManageChild (m_cmd_label
);
796 XtManageChild (m_cmd
);
797 XmProcessTraversal (m_cmd
, XmTRAVERSE_CURRENT
);
801 static const char benchmark_syntax
[] =
804 static const char benchmark_help
[] =
805 "Benchmark the GUI speed.";
807 /* %start-doc actions Benchmark
809 This action is used to speed-test the Lesstif graphics subsystem. It
810 redraws the current screen as many times as possible in ten seconds.
811 It reports the amount of time needed to draw the screen once.
816 Benchmark (int argc
, char **argv
, Coord x
, Coord y
)
823 save_main
= main_pixmap
;
824 main_pixmap
= window
;
828 region
.X2
= PCB
->MaxWidth
;
829 region
.Y2
= PCB
->MaxHeight
;
836 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, view_width
, view_height
);
837 hid_expose_callback (&lesstif_graphics
, ®ion
, 0);
842 while (end
- start
< 10);
844 printf ("%g redraws per second\n", i
/ 10.0);
846 main_pixmap
= save_main
;
851 Center(int argc
, char **argv
, Coord x
, Coord y
)
853 x
= GridFit (x
, PCB
->Grid
, PCB
->GridOffsetX
);
854 y
= GridFit (y
, PCB
->Grid
, PCB
->GridOffsetY
);
855 view_left_x
= x
- (view_width
* view_zoom
) / 2;
856 view_top_y
= y
- (view_height
* view_zoom
) / 2;
857 lesstif_pan_fixup ();
858 /* Move the pointer to the center of the window, but only if it's
859 currently within the window already. Watch out for edges,
861 XWarpPointer (display
, window
, window
, 0, 0, view_width
, view_height
,
866 static const char cursor_syntax
[] =
867 "Cursor(Type,DeltaUp,DeltaRight,Units)";
869 static const char cursor_help
[] =
872 /* %start-doc actions Cursor
874 This action moves the mouse cursor. Unlike other actions which take
875 coordinates, this action's coordinates are always relative to the
876 user's view of the board. Thus, a positive @var{DeltaUp} may move the
877 cursor towards the board origin if the board is inverted.
879 Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the
880 viewport to move such that the crosshair is under the mouse cursor.
881 @samp{Warp} causes the mouse cursor to move to be above the crosshair.
883 @var{Units} can be one of the following:
889 The cursor is moved by that amount, in board units.
892 The cursor is moved by that many grid points.
895 The values are percentages of the viewport's view. Thus, a pan of
896 @samp{100} would scroll the viewport by exactly the width of the
900 The values are percentages of the board size. Thus, a move of
901 @samp{50,50} moves you halfway across the board.
908 CursorAction(int argc
, char **argv
, Coord x
, Coord y
)
910 UnitList extra_units_x
= {
911 { "grid", PCB
->Grid
, 0 },
912 { "view", Pz(view_width
), UNIT_PERCENT
},
913 { "board", PCB
->MaxWidth
, UNIT_PERCENT
},
916 UnitList extra_units_y
= {
917 { "grid", PCB
->Grid
, 0 },
918 { "view", Pz(view_height
), UNIT_PERCENT
},
919 { "board", PCB
->MaxHeight
, UNIT_PERCENT
},
922 int pan_warp
= HID_SC_DO_NOTHING
;
928 if (strcasecmp (argv
[0], "pan") == 0)
929 pan_warp
= HID_SC_PAN_VIEWPORT
;
930 else if (strcasecmp (argv
[0], "warp") == 0)
931 pan_warp
= HID_SC_WARP_POINTER
;
935 dx
= GetValueEx (argv
[1], argv
[3], NULL
, extra_units_x
, "mil");
938 dy
= GetValueEx (argv
[2], argv
[3], NULL
, extra_units_y
, "mil");
942 EventMoveCrosshair (Crosshair
.X
+ dx
, Crosshair
.Y
+ dy
);
943 gui
->set_crosshair (Crosshair
.X
, Crosshair
.Y
, pan_warp
);
948 HID_Action lesstif_main_action_list
[] = {
949 {"PCBChanged", 0, PCBChanged
,
950 pcbchanged_help
, pcbchanged_syntax
},
951 {"SetUnits", 0, SetUnits
,
952 setunits_help
, setunits_syntax
},
953 {"Zoom", "Click on a place to zoom in", ZoomAction
,
954 zoom_help
, zoom_syntax
},
955 {"Pan", "Click on a place to pan", PanAction
,
956 zoom_help
, zoom_syntax
},
957 {"SwapSides", 0, SwapSides
,
958 swapsides_help
, swapsides_syntax
},
959 {"Command", 0, Command
,
960 command_help
, command_syntax
},
961 {"Benchmark", 0, Benchmark
,
962 benchmark_help
, benchmark_syntax
},
963 {"PointCursor", 0, PointCursor
},
964 {"Center", "Click on a location to center", Center
},
966 {"Cursor", 0, CursorAction
,
967 cursor_help
, cursor_syntax
},
970 REGISTER_ACTIONS (lesstif_main_action_list
)
973 /* ----------------------------------------------------------------------
974 * redraws the background image
977 static int bg_w
, bg_h
, bgi_w
, bgi_h
;
978 static Pixel
**bg
= 0;
979 static XImage
*bgi
= 0;
984 } pixel_type
= PT_unknown
;
987 LoadBackgroundFile (FILE *f
, char *filename
)
989 XVisualInfo vinfot
, *vinfo
;
993 int p
[3], rows
, cols
, maxval
;
997 printf("bgimage: %s signature not P6\n", filename
);
1000 if (fgetc(f
) != '6')
1002 printf("bgimage: %s signature not P6\n", filename
);
1012 while (!feof(f
) && b
!= '\n')
1014 } while (!isdigit(b
));
1016 while (isdigit(b
= fgetc(f
)))
1017 p
[i
] = p
[i
]*10 + b
- '0';
1024 bg
= (Pixel
**) malloc (rows
* sizeof (Pixel
*));
1027 printf("Out of memory loading %s\n", filename
);
1030 for (i
=0; i
<rows
; i
++)
1032 bg
[i
] = (Pixel
*) malloc (cols
* sizeof (Pixel
));
1035 printf("Out of memory loading %s\n", filename
);
1044 vis
= DefaultVisual (display
, DefaultScreen(display
));
1046 vinfot
.visualid
= XVisualIDFromVisual(vis
);
1047 vinfo
= XGetVisualInfo (display
, VisualIDMask
, &vinfot
, &nret
);
1050 /* If you want to support more visuals below, you'll probably need
1052 printf("vinfo: rm %04x gm %04x bm %04x depth %d class %d\n",
1053 vinfo
->red_mask
, vinfo
->green_mask
, vinfo
->blue_mask
,
1054 vinfo
->depth
, vinfo
->class);
1057 #if !defined(__cplusplus)
1058 #define c_class class
1061 if (vinfo
->c_class
== TrueColor
1062 && vinfo
->depth
== 16
1063 && vinfo
->red_mask
== 0xf800
1064 && vinfo
->green_mask
== 0x07e0
1065 && vinfo
->blue_mask
== 0x001f)
1066 pixel_type
= PT_RGB565
;
1068 if (vinfo
->c_class
== TrueColor
1069 && vinfo
->depth
== 24
1070 && vinfo
->red_mask
== 0xff0000
1071 && vinfo
->green_mask
== 0x00ff00
1072 && vinfo
->blue_mask
== 0x0000ff)
1073 pixel_type
= PT_RGB888
;
1075 for (r
=0; r
<rows
; r
++)
1077 for (c
=0; c
<cols
; c
++)
1080 unsigned int pr
= (unsigned)fgetc(f
);
1081 unsigned int pg
= (unsigned)fgetc(f
);
1082 unsigned int pb
= (unsigned)fgetc(f
);
1087 pix
.red
= pr
* 65535 / maxval
;
1088 pix
.green
= pg
* 65535 / maxval
;
1089 pix
.blue
= pb
* 65535 / maxval
;
1090 pix
.flags
= DoRed
| DoGreen
| DoBlue
;
1091 XAllocColor (display
, colormap
, &pix
);
1092 bg
[r
][c
] = pix
.pixel
;
1095 bg
[r
][c
] = (pr
>>3)<<11 | (pg
>>2)<<5 | (pb
>>3);
1098 bg
[r
][c
] = (pr
<< 16) | (pg
<< 8) | (pb
);
1106 LoadBackgroundImage (char *filename
)
1108 FILE *f
= fopen(filename
, "rb");
1111 if (NSTRCMP (filename
, "pcb-background.ppm"))
1115 LoadBackgroundFile (f
, filename
);
1120 DrawBackgroundImage ()
1123 double xscale
, yscale
;
1124 int pcbwidth
= PCB
->MaxWidth
/ view_zoom
;
1125 int pcbheight
= PCB
->MaxHeight
/ view_zoom
;
1130 if (!bgi
|| view_width
!= bgi_w
|| view_height
!= bgi_h
)
1133 XDestroyImage (bgi
);
1134 /* Cheat - get the image, which sets up the format too. */
1135 bgi
= XGetImage (XtDisplay(work_area
),
1137 0, 0, view_width
, view_height
,
1140 bgi_h
= view_height
;
1143 w
= MIN (view_width
, pcbwidth
);
1144 h
= MIN (view_height
, pcbheight
);
1146 xscale
= (double)bg_w
/ PCB
->MaxWidth
;
1147 yscale
= (double)bg_h
/ PCB
->MaxHeight
;
1152 int ir
= pr
* yscale
;
1156 int ic
= pc
* xscale
;
1157 XPutPixel (bgi
, x
, y
, bg
[ir
][ic
]);
1160 XPutImage(display
, main_pixmap
, bg_gc
,
1164 /* ---------------------------------------------------------------------- */
1166 static HID_Attribute
*
1167 lesstif_get_export_options (int *n
)
1169 *n
= sizeof (lesstif_attribute_list
) / sizeof (HID_Attribute
);
1170 return lesstif_attribute_list
;
1174 set_scroll (Widget s
, int pos
, int view
, int pcb
)
1176 int sz
= view
* view_zoom
;
1180 stdarg (XmNvalue
, pos
);
1181 stdarg (XmNsliderSize
, sz
);
1182 stdarg (XmNincrement
, view_zoom
);
1183 stdarg (XmNpageIncrement
, sz
);
1184 stdarg (XmNmaximum
, pcb
);
1185 XtSetValues (s
, args
, n
);
1189 lesstif_pan_fixup ()
1192 if (view_left_x
> PCB
->MaxWidth
- (view_width
* view_zoom
))
1193 view_left_x
= PCB
->MaxWidth
- (view_width
* view_zoom
);
1194 if (view_top_y
> PCB
->MaxHeight
- (view_height
* view_zoom
))
1195 view_top_y
= PCB
->MaxHeight
- (view_height
* view_zoom
);
1196 if (view_left_x
< 0)
1200 if (view_width
* view_zoom
> PCB
->MaxWidth
1201 && view_height
* view_zoom
> PCB
->MaxHeight
)
1208 set_scroll (hscroll
, view_left_x
, view_width
, PCB
->MaxWidth
);
1209 set_scroll (vscroll
, view_top_y
, view_height
, PCB
->MaxHeight
);
1211 lesstif_invalidate_all ();
1217 double new_zoom
= PCB
->MaxWidth
/ view_width
;
1218 if (new_zoom
< PCB
->MaxHeight
/ view_height
)
1219 new_zoom
= PCB
->MaxHeight
/ view_height
;
1221 view_left_x
= -(view_width
* new_zoom
- PCB
->MaxWidth
) / 2;
1222 view_top_y
= -(view_height
* new_zoom
- PCB
->MaxHeight
) / 2;
1223 view_zoom
= new_zoom
;
1224 pixel_slop
= view_zoom
;
1225 lesstif_pan_fixup ();
1229 zoom_to (double new_zoom
, int x
, int y
)
1231 double max_zoom
, xfrac
, yfrac
;
1234 xfrac
= (double) x
/ (double) view_width
;
1235 yfrac
= (double) y
/ (double) view_height
;
1242 max_zoom
= PCB
->MaxWidth
/ view_width
;
1243 if (max_zoom
< PCB
->MaxHeight
/ view_height
)
1244 max_zoom
= PCB
->MaxHeight
/ view_height
;
1246 max_zoom
*= MAX_ZOOM_SCALE
;
1250 if (new_zoom
> max_zoom
)
1251 new_zoom
= max_zoom
;
1253 cx
= view_left_x
+ view_width
* xfrac
* view_zoom
;
1254 cy
= view_top_y
+ view_height
* yfrac
* view_zoom
;
1256 if (view_zoom
!= new_zoom
)
1258 view_zoom
= new_zoom
;
1259 pixel_slop
= view_zoom
;
1261 view_left_x
= cx
- view_width
* xfrac
* view_zoom
;
1262 view_top_y
= cy
- view_height
* yfrac
* view_zoom
;
1264 lesstif_pan_fixup ();
1268 zoom_toggle(int x
, int y
)
1272 tmp
= prev_view_zoom
;
1273 prev_view_zoom
= view_zoom
;
1278 zoom_by (double factor
, int x
, int y
)
1280 zoom_to (view_zoom
* factor
, x
, y
);
1283 static int panning
= 0;
1284 static int shift_pressed
;
1285 static int ctrl_pressed
;
1286 static int alt_pressed
;
1288 /* X and Y are in screen coordinates. */
1290 Pan (int mode
, int x
, int y
)
1293 static int opx
, opy
;
1296 /* This is for ctrl-pan, where the viewport's position is directly
1297 proportional to the cursor position in the window (like the Xaw
1301 opx
= x
* PCB
->MaxWidth
/ view_width
;
1302 opy
= y
* PCB
->MaxHeight
/ view_height
;
1304 opx
= PCB
->MaxWidth
- opx
;
1306 opy
= PCB
->MaxHeight
- opy
;
1307 view_left_x
= opx
- view_width
/ 2 * view_zoom
;
1308 view_top_y
= opy
- view_height
/ 2 * view_zoom
;
1309 lesstif_pan_fixup ();
1311 /* This is the start of a regular pan. On the first click, we
1312 remember the coordinates where we "grabbed" the screen. */
1320 /* continued drag, we calculate how far we've moved the cursor and
1321 set the position accordingly. */
1325 view_left_x
= opx
+ (x
- ox
) * view_zoom
;
1327 view_left_x
= opx
- (x
- ox
) * view_zoom
;
1329 view_top_y
= opy
+ (y
- oy
) * view_zoom
;
1331 view_top_y
= opy
- (y
- oy
) * view_zoom
;
1332 lesstif_pan_fixup ();
1337 mod_changed (XKeyEvent
* e
, int set
)
1339 switch (XKeycodeToKeysym (display
, e
->keycode
, 0))
1343 shift_pressed
= set
;
1350 case XK_Mode_switch
:
1358 // to include the Apple keyboard left and right command keys use XK_Meta_L and XK_Meta_R respectivly.
1362 notify_crosshair_change (false);
1364 Pan (2, e
->x
, e
->y
);
1365 EventMoveCrosshair (Px (e
->x
), Py (e
->y
));
1366 AdjustAttachedObjects ();
1367 notify_crosshair_change (true);
1372 work_area_input (Widget w
, XtPointer v
, XEvent
* e
, Boolean
* ctd
)
1374 static int pressed_button
= 0;
1380 mod_changed (&(e
->xkey
), 1);
1381 if (lesstif_key_event (&(e
->xkey
)))
1386 mod_changed (&(e
->xkey
), 0);
1394 /*printf("click %d\n", e->xbutton.button); */
1395 if (lesstif_button_event (w
, e
))
1398 notify_crosshair_change (false);
1399 pressed_button
= e
->xbutton
.button
;
1400 mods
= ((e
->xbutton
.state
& ShiftMask
) ? M_Shift
: 0)
1401 + ((e
->xbutton
.state
& ControlMask
) ? M_Ctrl
: 0)
1403 + ((e
->xbutton
.state
& (1<<13)) ? M_Alt
: 0);
1405 + ((e
->xbutton
.state
& Mod1Mask
) ? M_Alt
: 0);
1407 do_mouse_action(e
->xbutton
.button
, mods
);
1408 notify_crosshair_change (true);
1415 if (e
->xbutton
.button
!= pressed_button
)
1417 lesstif_button_event (w
, e
);
1418 notify_crosshair_change (false);
1420 mods
= ((e
->xbutton
.state
& ShiftMask
) ? M_Shift
: 0)
1421 + ((e
->xbutton
.state
& ControlMask
) ? M_Ctrl
: 0)
1423 + ((e
->xbutton
.state
& (1<<13)) ? M_Alt
: 0)
1425 + ((e
->xbutton
.state
& Mod1Mask
) ? M_Alt
: 0)
1428 do_mouse_action (e
->xbutton
.button
, mods
);
1429 notify_crosshair_change (true);
1436 unsigned int keys_buttons
;
1437 int root_x
, root_y
, pos_x
, pos_y
;
1438 while (XCheckMaskEvent (display
, PointerMotionMask
, e
));
1439 XQueryPointer (display
, e
->xmotion
.window
, &root
, &child
,
1440 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
1441 shift_pressed
= (keys_buttons
& ShiftMask
);
1442 ctrl_pressed
= (keys_buttons
& ControlMask
);
1444 alt_pressed
= (keys_buttons
& (1<<13));
1446 alt_pressed
= (keys_buttons
& Mod1Mask
);
1448 /*pcb_printf("m %#mS %#mS\n", Px(e->xmotion.x), Py(e->xmotion.y)); */
1449 crosshair_in_window
= 1;
1452 Pan (2, pos_x
, pos_y
);
1453 EventMoveCrosshair (Px (pos_x
), Py (pos_y
));
1459 crosshair_in_window
= 0;
1460 ShowCrosshair (false);
1465 crosshair_in_window
= 1;
1467 EventMoveCrosshair (Px (e
->xcrossing
.x
), Py (e
->xcrossing
.y
));
1468 ShowCrosshair (true);
1474 printf ("work_area: unknown event %d\n", e
->type
);
1480 draw_right_cross (GC xor_gc
, int x
, int y
,
1481 int view_width
, int view_height
)
1483 XDrawLine (display
, window
, xor_gc
, 0, y
, view_width
, y
);
1484 XDrawLine (display
, window
, xor_gc
, x
, 0, x
, view_height
);
1488 draw_slanted_cross (GC xor_gc
, int x
, int y
,
1489 int view_width
, int view_height
)
1493 x0
= x
+ (view_height
- y
);
1494 x0
= MAX(0, MIN (x0
, view_width
));
1496 x1
= MAX(0, MIN (x1
, view_width
));
1497 y0
= y
+ (view_width
- x
);
1498 y0
= MAX(0, MIN (y0
, view_height
));
1500 y1
= MAX(0, MIN (y1
, view_height
));
1501 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1502 x0
= x
- (view_height
- y
);
1503 x0
= MAX(0, MIN (x0
, view_width
));
1505 x1
= MAX(0, MIN (x1
, view_width
));
1507 y0
= MAX(0, MIN (y0
, view_height
));
1508 y1
= y
- (view_width
- x
);
1509 y1
= MAX(0, MIN (y1
, view_height
));
1510 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1514 draw_dozen_cross (GC xor_gc
, int x
, int y
,
1515 int view_width
, int view_height
)
1518 double tan60
= sqrt (3);
1520 x0
= x
+ (view_height
- y
) / tan60
;
1521 x0
= MAX(0, MIN (x0
, view_width
));
1523 x1
= MAX(0, MIN (x1
, view_width
));
1524 y0
= y
+ (view_width
- x
) * tan60
;
1525 y0
= MAX(0, MIN (y0
, view_height
));
1527 y1
= MAX(0, MIN (y1
, view_height
));
1528 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1530 x0
= x
+ (view_height
- y
) * tan60
;
1531 x0
= MAX(0, MIN (x0
, view_width
));
1533 x1
= MAX(0, MIN (x1
, view_width
));
1534 y0
= y
+ (view_width
- x
) / tan60
;
1535 y0
= MAX(0, MIN (y0
, view_height
));
1537 y1
= MAX(0, MIN (y1
, view_height
));
1538 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1540 x0
= x
- (view_height
- y
) / tan60
;
1541 x0
= MAX(0, MIN (x0
, view_width
));
1543 x1
= MAX(0, MIN (x1
, view_width
));
1545 y0
= MAX(0, MIN (y0
, view_height
));
1546 y1
= y
- (view_width
- x
) * tan60
;
1547 y1
= MAX(0, MIN (y1
, view_height
));
1548 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1550 x0
= x
- (view_height
- y
) * tan60
;
1551 x0
= MAX(0, MIN (x0
, view_width
));
1553 x1
= MAX(0, MIN (x1
, view_width
));
1555 y0
= MAX(0, MIN (y0
, view_height
));
1556 y1
= y
- (view_width
- x
) / tan60
;
1557 y1
= MAX(0, MIN (y1
, view_height
));
1558 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1562 draw_crosshair (GC xor_gc
, int x
, int y
,
1563 int view_width
, int view_height
)
1565 draw_right_cross (xor_gc
, x
, y
, view_width
, view_height
);
1566 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
1567 draw_slanted_cross (xor_gc
, x
, y
, view_width
, view_height
);
1568 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
1569 draw_dozen_cross (xor_gc
, x
, y
, view_width
, view_height
);
1572 lesstif_show_crosshair (int show
)
1574 static int showing
= 0;
1576 static GC xor_gc
= 0;
1577 Pixel crosshair_color
;
1579 if (!crosshair_in_window
|| !window
)
1583 crosshair_color
= lesstif_parse_color (Settings
.CrosshairColor
) ^ bgcolor
;
1584 xor_gc
= XCreateGC (display
, window
, 0, 0);
1585 XSetFunction (display
, xor_gc
, GXxor
);
1586 XSetForeground (display
, xor_gc
, crosshair_color
);
1588 if (show
== showing
)
1592 sx
= Vx (crosshair_x
);
1593 sy
= Vy (crosshair_y
);
1597 draw_crosshair (xor_gc
, sx
, sy
, view_width
, view_height
);
1602 work_area_expose (Widget work_area
, void *me
,
1603 XmDrawingAreaCallbackStruct
* cbs
)
1608 e
= &(cbs
->event
->xexpose
);
1609 XSetFunction (display
, my_gc
, GXcopy
);
1610 XCopyArea (display
, main_pixmap
, window
, my_gc
,
1611 e
->x
, e
->y
, e
->width
, e
->height
, e
->x
, e
->y
);
1616 scroll_callback (Widget scroll
, int *view_dim
,
1617 XmScrollBarCallbackStruct
* cbs
)
1619 *view_dim
= cbs
->value
;
1620 lesstif_invalidate_all ();
1624 work_area_make_pixmaps (Dimension width
, Dimension height
)
1627 XFreePixmap (display
, main_pixmap
);
1629 XCreatePixmap (display
, window
, width
, height
,
1630 XDefaultDepth (display
, screen
));
1633 XFreePixmap (display
, mask_pixmap
);
1635 XCreatePixmap (display
, window
, width
, height
,
1636 XDefaultDepth (display
, screen
));
1640 XRenderFreePicture (display
, main_picture
);
1645 XRenderFreePicture (display
, mask_picture
);
1650 main_picture
= XRenderCreatePicture (display
, main_pixmap
,
1651 XRenderFindVisualFormat(display
,
1652 DefaultVisual(display
, screen
)), 0, 0);
1653 mask_picture
= XRenderCreatePicture (display
, mask_pixmap
,
1654 XRenderFindVisualFormat(display
,
1655 DefaultVisual(display
, screen
)), 0, 0);
1656 if (!main_picture
|| !mask_picture
)
1659 #endif /* HAVE_XRENDER */
1662 XFreePixmap (display
, mask_bitmap
);
1663 mask_bitmap
= XCreatePixmap (display
, window
, width
, height
, 1);
1665 pixmap
= use_mask
? main_pixmap
: mask_pixmap
;
1671 work_area_resize (Widget work_area
, void *me
,
1672 XmDrawingAreaCallbackStruct
* cbs
)
1675 Dimension width
, height
;
1680 stdarg (XtNwidth
, &width
);
1681 stdarg (XtNheight
, &height
);
1682 stdarg (XmNbackground
, &bgcolor
);
1683 XtGetValues (work_area
, args
, n
);
1685 view_height
= height
;
1687 color
.pixel
= bgcolor
;
1688 XQueryColor (display
, colormap
, &color
);
1690 bggreen
= color
.green
;
1691 bgblue
= color
.blue
;
1696 work_area_make_pixmaps (view_width
, view_height
);
1702 work_area_first_expose (Widget work_area
, void *me
,
1703 XmDrawingAreaCallbackStruct
* cbs
)
1706 Dimension width
, height
;
1707 static char dashes
[] = { 4, 4 };
1709 window
= XtWindow (work_area
);
1710 my_gc
= XCreateGC (display
, window
, 0, 0);
1712 arc1_gc
= XCreateGC (display
, window
, 0, 0);
1713 c
= lesstif_parse_color ("#804000");
1714 XSetForeground (display
, arc1_gc
, c
);
1715 arc2_gc
= XCreateGC (display
, window
, 0, 0);
1716 c
= lesstif_parse_color ("#004080");
1717 XSetForeground (display
, arc2_gc
, c
);
1718 XSetLineAttributes (display
, arc1_gc
, 1, LineOnOffDash
, 0, 0);
1719 XSetLineAttributes (display
, arc2_gc
, 1, LineOnOffDash
, 0, 0);
1720 XSetDashes (display
, arc1_gc
, 0, dashes
, 2);
1721 XSetDashes (display
, arc2_gc
, 0, dashes
, 2);
1724 stdarg (XtNwidth
, &width
);
1725 stdarg (XtNheight
, &height
);
1726 stdarg (XmNbackground
, &bgcolor
);
1727 XtGetValues (work_area
, args
, n
);
1729 view_height
= height
;
1731 offlimit_color
= lesstif_parse_color (Settings
.OffLimitColor
);
1732 grid_color
= lesstif_parse_color (Settings
.GridColor
);
1734 bg_gc
= XCreateGC (display
, window
, 0, 0);
1735 XSetForeground (display
, bg_gc
, bgcolor
);
1737 work_area_make_pixmaps (width
, height
);
1742 XRenderPictureAttributes pa
;
1743 XRenderColor a
= {0, 0, 0, 0x8000};
1745 pale_pixmap
= XCreatePixmap (display
, window
, 1, 1, 8);
1747 pale_picture
= XRenderCreatePicture (display
, pale_pixmap
,
1748 XRenderFindStandardFormat(display
, PictStandardA8
),
1751 XRenderFillRectangle(display
, PictOpSrc
, pale_picture
, &a
, 0, 0, 1, 1);
1755 #endif /* HAVE_XRENDER */
1757 clip_gc
= XCreateGC (display
, window
, 0, 0);
1758 bset_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1759 XSetForeground (display
, bset_gc
, 1);
1760 bclear_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1761 XSetForeground (display
, bclear_gc
, 0);
1763 XtRemoveCallback (work_area
, XmNexposeCallback
,
1764 (XtCallbackProc
) work_area_first_expose
, 0);
1765 XtAddCallback (work_area
, XmNexposeCallback
,
1766 (XtCallbackProc
) work_area_expose
, 0);
1767 lesstif_invalidate_all ();
1771 make_message (char *name
, Widget left
, int resizeable
)
1777 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1778 stdarg (XmNleftWidget
, XtParent(left
));
1782 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1784 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1785 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1786 stdarg (XmNshadowType
, XmSHADOW_IN
);
1787 stdarg (XmNshadowThickness
, 1);
1788 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1789 stdarg (XmNmarginWidth
, 4);
1790 stdarg (XmNmarginHeight
, 1);
1792 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
1793 f
= XmCreateForm (messages
, name
, args
, n
);
1796 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1797 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1798 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1799 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1800 w
= XmCreateLabel (f
, name
, args
, n
);
1806 lesstif_do_export (HID_Attr_Val
* options
)
1808 Dimension width
, height
;
1810 Widget work_area_frame
;
1812 crosshair_gc
= lesstif_make_gc ();
1815 stdarg (XtNwidth
, &width
);
1816 stdarg (XtNheight
, &height
);
1817 XtGetValues (appwidget
, args
, n
);
1821 if (width
> XDisplayWidth (display
, screen
))
1822 width
= XDisplayWidth (display
, screen
);
1825 if (height
> XDisplayHeight (display
, screen
))
1826 height
= XDisplayHeight (display
, screen
);
1829 stdarg (XmNwidth
, width
);
1830 stdarg (XmNheight
, height
);
1831 XtSetValues (appwidget
, args
, n
);
1833 stdarg (XmNspacing
, 0);
1834 mainwind
= XmCreateMainWindow (appwidget
, "mainWind", args
, n
);
1835 XtManageChild (mainwind
);
1838 stdarg (XmNmarginWidth
, 0);
1839 stdarg (XmNmarginHeight
, 0);
1840 menu
= lesstif_menu (mainwind
, "menubar", args
, n
);
1841 XtManageChild (menu
);
1844 stdarg (XmNshadowType
, XmSHADOW_IN
);
1846 XmCreateFrame (mainwind
, "work_area_frame", args
, n
);
1847 XtManageChild (work_area_frame
);
1850 do_color (Settings
.BackgroundColor
, XmNbackground
);
1851 work_area
= XmCreateDrawingArea (work_area_frame
, "work_area", args
, n
);
1852 XtManageChild (work_area
);
1853 XtAddCallback (work_area
, XmNexposeCallback
,
1854 (XtCallbackProc
) work_area_first_expose
, 0);
1855 XtAddCallback (work_area
, XmNresizeCallback
,
1856 (XtCallbackProc
) work_area_resize
, 0);
1857 /* A regular callback won't work here, because lesstif swallows any
1858 Ctrl<Button>1 event. */
1859 XtAddEventHandler (work_area
,
1860 ButtonPressMask
| ButtonReleaseMask
1861 | PointerMotionMask
| PointerMotionHintMask
1862 | KeyPressMask
| KeyReleaseMask
1863 | EnterWindowMask
| LeaveWindowMask
,
1864 0, work_area_input
, 0);
1867 stdarg (XmNorientation
, XmVERTICAL
);
1868 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
1869 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
1870 vscroll
= XmCreateScrollBar (mainwind
, "vscroll", args
, n
);
1871 XtAddCallback (vscroll
, XmNvalueChangedCallback
,
1872 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_top_y
);
1873 XtAddCallback (vscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1874 (XtPointer
) & view_top_y
);
1875 XtManageChild (vscroll
);
1878 stdarg (XmNorientation
, XmHORIZONTAL
);
1879 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
1880 hscroll
= XmCreateScrollBar (mainwind
, "hscroll", args
, n
);
1881 XtAddCallback (hscroll
, XmNvalueChangedCallback
,
1882 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_left_x
);
1883 XtAddCallback (hscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1884 (XtPointer
) & view_left_x
);
1885 XtManageChild (hscroll
);
1888 stdarg (XmNresize
, True
);
1889 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
1890 messages
= XmCreateForm (mainwind
, "messages", args
, n
);
1891 XtManageChild (messages
);
1894 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1895 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1896 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1897 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1898 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1899 stdarg (XmNshadowThickness
, 2);
1900 m_click
= XmCreateLabel (messages
, "click", args
, n
);
1903 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1904 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1905 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1906 stdarg (XmNlabelString
, XmStringCreatePCB ("Command: "));
1907 m_cmd_label
= XmCreateLabel (messages
, "command", args
, n
);
1910 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1911 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1912 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1913 stdarg (XmNleftWidget
, m_cmd_label
);
1914 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1915 stdarg (XmNshadowThickness
, 1);
1916 stdarg (XmNhighlightThickness
, 0);
1917 stdarg (XmNmarginWidth
, 2);
1918 stdarg (XmNmarginHeight
, 2);
1919 m_cmd
= XmCreateTextField (messages
, "command", args
, n
);
1920 XtAddCallback (m_cmd
, XmNactivateCallback
,
1921 (XtCallbackProc
) command_callback
, 0);
1922 XtAddCallback (m_cmd
, XmNlosingFocusCallback
,
1923 (XtCallbackProc
) command_callback
, 0);
1924 XtAddEventHandler (m_cmd
, KeyPressMask
, 0, command_event_handler
, 0);
1926 m_mark
= make_message ("m_mark", 0, 0);
1927 m_crosshair
= make_message ("m_crosshair", m_mark
, 0);
1928 m_grid
= make_message ("m_grid", m_crosshair
, 1);
1929 m_zoom
= make_message ("m_zoom", m_grid
, 1);
1930 lesstif_m_layer
= make_message ("m_layer", m_zoom
, 0);
1931 m_mode
= make_message ("m_mode", lesstif_m_layer
, 1);
1932 m_rats
= make_message ("m_rats", m_mode
, 1);
1933 m_status
= make_message ("m_status", m_mode
, 1);
1935 XtUnmanageChild (XtParent (m_mark
));
1936 XtUnmanageChild (XtParent (m_rats
));
1939 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1940 XtSetValues (XtParent (m_status
), args
, n
);
1942 /* We'll use this later. */
1944 stdarg (XmNleftWidget
, XtParent (m_mark
));
1945 XtSetValues (XtParent (m_crosshair
), args
, n
);
1948 stdarg (XmNmessageWindow
, messages
);
1949 XtSetValues (mainwind
, args
, n
);
1951 if (background_image_file
)
1952 LoadBackgroundImage (background_image_file
);
1954 XtRealizeWidget (appwidget
);
1959 XtAppNextEvent (app_context
, &e
);
1960 XtDispatchEvent (&e
);
1963 PCBChanged (0, 0, 0, 0);
1965 XtAppMainLoop (app_context
);
1969 XrmOptionDescRec lesstif_options
[] = {
1972 XtResource lesstif_resources
[] = {
1985 pcb_cvt_string_to_double (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
1986 XrmValue
* from
, XrmValue
* to
, XtPointer
* data
)
1989 rv
= strtod ((char *) from
->addr
, 0);
1991 *(double *) to
->addr
= rv
;
1993 to
->addr
= (XPointer
) & rv
;
1994 to
->size
= sizeof (rv
);
1999 pcb_cvt_string_to_coord (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
2000 XrmValue
* from
, XrmValue
* to
, XtPointer
*data
)
2003 rv
= GetValue ((char *) from
->addr
, NULL
, NULL
);
2005 *(Coord
*) to
->addr
= rv
;
2007 to
->addr
= (XPointer
) &rv
;
2008 to
->size
= sizeof (rv
);
2013 mainwind_delete_cb ()
2015 hid_action ("Quit");
2019 lesstif_listener_cb (XtPointer client_data
, int *fid
, XtInputId
*id
)
2024 if ((nbytes
= read (*fid
, buf
, BUFSIZ
)) == -1)
2025 perror ("lesstif_listener_cb");
2030 hid_parse_actions (buf
);
2035 lesstif_parse_arguments (int *argc
, char ***argv
)
2039 int acount
= 0, amax
;
2040 int rcount
= 0, rmax
;
2042 XrmOptionDescRec
*new_options
;
2043 XtResource
*new_resources
;
2044 val_union
*new_values
;
2045 int render_event
, render_error
;
2047 XtSetTypeConverter (XtRString
,
2049 pcb_cvt_string_to_double
, NULL
, 0, XtCacheAll
, NULL
);
2050 XtSetTypeConverter (XtRString
,
2052 pcb_cvt_string_to_coord
, NULL
, 0, XtCacheAll
, NULL
);
2055 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2056 for (i
= 0; i
< ha
->n
; i
++)
2058 HID_Attribute
*a
= ha
->attributes
+ i
;
2076 amax
= acount
+ XtNumber (lesstif_options
);
2081 new_options
= (XrmOptionDescRec
*) malloc ((amax
+ 1) * sizeof (XrmOptionDescRec
));
2084 memcpy (new_options
+ acount
, lesstif_options
, sizeof (lesstif_options
));
2089 rmax
= rcount
+ XtNumber (lesstif_resources
);
2094 new_resources
= (XtResource
*) malloc ((rmax
+ 1) * sizeof (XtResource
));
2095 new_values
= (val_union
*) malloc ((rmax
+ 1) * sizeof (val_union
));
2097 memcpy (new_resources
+ acount
, lesstif_resources
,
2098 sizeof (lesstif_resources
));
2102 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2103 for (i
= 0; i
< ha
->n
; i
++)
2105 HID_Attribute
*a
= ha
->attributes
+ i
;
2106 XrmOptionDescRec
*o
= new_options
+ acount
;
2107 char *tmpopt
, *tmpres
;
2108 XtResource
*r
= new_resources
+ rcount
;
2110 tmpopt
= (char *) malloc (strlen (a
->name
) + 3);
2111 tmpopt
[0] = tmpopt
[1] = '-';
2112 strcpy (tmpopt
+ 2, a
->name
);
2115 tmpres
= (char *) malloc (strlen (a
->name
) + 2);
2117 strcpy (tmpres
+ 1, a
->name
);
2118 o
->specifier
= tmpres
;
2127 o
->argKind
= XrmoptionSepArg
;
2132 o
->argKind
= XrmoptionNoArg
;
2140 r
->resource_name
= a
->name
;
2141 r
->resource_class
= a
->name
;
2142 r
->resource_offset
= sizeof (val_union
) * rcount
;
2147 r
->resource_type
= XtRInt
;
2148 r
->default_type
= XtRInt
;
2149 r
->resource_size
= sizeof (int);
2150 r
->default_addr
= &(a
->default_val
.int_value
);
2154 r
->resource_type
= XtRPCBCoord
;
2155 r
->default_type
= XtRPCBCoord
;
2156 r
->resource_size
= sizeof (Coord
);
2157 r
->default_addr
= &(a
->default_val
.coord_value
);
2161 r
->resource_type
= XtRDouble
;
2162 r
->default_type
= XtRDouble
;
2163 r
->resource_size
= sizeof (double);
2164 r
->default_addr
= &(a
->default_val
.real_value
);
2169 r
->resource_type
= XtRString
;
2170 r
->default_type
= XtRString
;
2171 r
->resource_size
= sizeof (char *);
2172 r
->default_addr
= (char *) a
->default_val
.str_value
;
2176 r
->resource_type
= XtRBoolean
;
2177 r
->default_type
= XtRInt
;
2178 r
->resource_size
= sizeof (int);
2179 r
->default_addr
= &(a
->default_val
.int_value
);
2187 for (i
= 0; i
< XtNumber (lesstif_resources
); i
++)
2189 XtResource
*r
= new_resources
+ rcount
;
2190 r
->resource_offset
= sizeof (val_union
) * rcount
;
2196 stdarg (XmNdeleteResponse
, XmDO_NOTHING
);
2198 appwidget
= XtAppInitialize (&app_context
,
2200 new_options
, amax
, argc
, *argv
, 0, args
, n
);
2202 display
= XtDisplay (appwidget
);
2203 screen_s
= XtScreen (appwidget
);
2204 screen
= XScreenNumberOfScreen (screen_s
);
2205 colormap
= XDefaultColormap (display
, screen
);
2207 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
2208 XmAddWMProtocolCallback (appwidget
, close_atom
,
2209 (XtCallbackProc
) mainwind_delete_cb
, 0);
2211 /* XSynchronize(display, True); */
2213 XtGetApplicationResources (appwidget
, new_values
, new_resources
,
2217 use_xrender
= XRenderQueryExtension (display
, &render_event
, &render_error
) &&
2218 XRenderFindVisualFormat (display
, DefaultVisual(display
, screen
));
2219 #ifdef HAVE_XINERAMA
2220 /* Xinerama and XRender don't get along well */
2221 if (XineramaQueryExtension (display
, &render_event
, &render_error
)
2222 && XineramaIsActive (display
))
2224 #endif /* HAVE_XINERAMA */
2225 #endif /* HAVE_XRENDER */
2228 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2229 for (i
= 0; i
< ha
->n
; i
++)
2231 HID_Attribute
*a
= ha
->attributes
+ i
;
2232 val_union
*v
= new_values
+ rcount
;
2237 *(int *) a
->value
= v
->i
;
2239 a
->default_val
.int_value
= v
->i
;
2244 *(Coord
*) a
->value
= v
->c
;
2246 a
->default_val
.coord_value
= v
->c
;
2251 *(char *) a
->value
= v
->i
;
2253 a
->default_val
.int_value
= v
->i
;
2258 *(double *) a
->value
= v
->f
;
2260 a
->default_val
.real_value
= v
->f
;
2266 *(char **) a
->value
= v
->s
;
2268 a
->default_val
.str_value
= v
->s
;
2276 /* redefine colormap, if requested via "-install" */
2277 if (use_private_colormap
)
2279 colormap
= XCopyColormapAndFree (display
, colormap
);
2280 XtVaSetValues (appwidget
, XtNcolormap
, colormap
, NULL
);
2283 /* listen on standard input for actions */
2286 XtAppAddInput (app_context
, fileno (stdin
), (XtPointer
) XtInputReadMask
,
2287 lesstif_listener_cb
, NULL
);
2294 static XPoint
*points
= 0;
2295 static int npoints
= 0;
2296 Coord x1
, y1
, x2
, y2
, prevx
;
2299 static GC grid_gc
= 0;
2301 if (!Settings
.DrawGrid
)
2303 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
2307 grid_gc
= XCreateGC (display
, window
, 0, 0);
2308 XSetFunction (display
, grid_gc
, GXxor
);
2309 XSetForeground (display
, grid_gc
, grid_color
);
2313 x2
= GridFit (Px (0), PCB
->Grid
, PCB
->GridOffsetX
);
2314 x1
= GridFit (Px (view_width
), PCB
->Grid
, PCB
->GridOffsetX
);
2317 if (Vx (x1
) >= view_width
)
2322 x1
= GridFit (Px (0), PCB
->Grid
, PCB
->GridOffsetX
);
2323 x2
= GridFit (Px (view_width
), PCB
->Grid
, PCB
->GridOffsetX
);
2326 if (Vx (x2
) >= view_width
)
2331 y2
= GridFit (Py (0), PCB
->Grid
, PCB
->GridOffsetY
);
2332 y1
= GridFit (Py (view_height
), PCB
->Grid
, PCB
->GridOffsetY
);
2335 if (Vy (y1
) >= view_height
)
2340 y1
= GridFit (Py (0), PCB
->Grid
, PCB
->GridOffsetY
);
2341 y2
= GridFit (Py (view_height
), PCB
->Grid
, PCB
->GridOffsetY
);
2344 if (Vy (y2
) >= view_height
)
2347 n
= (x2
- x1
) / PCB
->Grid
+ 1;
2351 points
= (XPoint
*) realloc (points
, npoints
* sizeof (XPoint
));
2355 for (x
= x1
; x
<= x2
; x
+= PCB
->Grid
)
2361 points
[n
].x
-= prevx
;
2367 for (y
= y1
; y
<= y2
; y
+= PCB
->Grid
)
2371 XDrawPoints (display
, pixmap
, grid_gc
, points
, n
, CoordModePrevious
);
2376 mark_delta_to_widget (Coord dx
, Coord dy
, Widget w
)
2379 double g
= coord_to_unit (Settings
.grid_unit
, PCB
->Grid
);
2383 /* Integer-sized grid? */
2384 if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2387 prec
= Settings
.grid_unit
->default_prec
;
2389 if (dx
== 0 && dy
== 0)
2390 buf
= pcb_g_strdup_printf ("%m+%+.*mS, %+.*mS", UUNIT
, prec
, dx
, prec
, dy
);
2393 Angle angle
= atan2 (dy
, -dx
) * 180 / M_PI
;
2394 Coord dist
= Distance (0, 0, dx
, dy
);
2396 buf
= pcb_g_strdup_printf ("%m+%+.*mS, %+.*mS (%.*mS, %d\260)", UUNIT
,
2397 prec
, dx
, prec
, dy
, prec
, dist
, angle
);
2400 ms
= XmStringCreatePCB (buf
);
2402 stdarg (XmNlabelString
, ms
);
2403 XtSetValues (w
, args
, n
);
2408 cursor_pos_to_widget (Coord x
, Coord y
, Widget w
, int prev_state
)
2410 int this_state
= prev_state
;
2412 double g
= coord_to_unit (Settings
.grid_unit
, PCB
->Grid
);
2416 /* Determine necessary precision (and state) based
2417 * on the user's grid setting */
2418 if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2421 this_state
= Settings
.grid_unit
->allow
;
2425 prec
= Settings
.grid_unit
->default_prec
;
2426 this_state
= -Settings
.grid_unit
->allow
;
2430 buf
= g_strdup ("");
2432 buf
= pcb_g_strdup_printf ("%m+%.*mS, %.*mS", UUNIT
, prec
, x
, prec
, y
);
2434 ms
= XmStringCreatePCB (buf
);
2436 stdarg (XmNlabelString
, ms
);
2437 XtSetValues (w
, args
, n
);
2445 lesstif_update_status_line ()
2448 char *s45
= cur_clip ();
2451 switch (Settings
.Mode
)
2454 buf
= pcb_g_strdup_printf ("%m+%.2mS/%.2mS \370=%.2mS", UUNIT
,
2455 S
.ViaThickness
, S
.Keepaway
, S
.ViaDrillingHole
);
2459 buf
= pcb_g_strdup_printf ("%m+%.2mS/%.2mS %s", UUNIT
,
2460 S
.LineThickness
, S
.Keepaway
, s45
);
2462 case RECTANGLE_MODE
:
2464 buf
= pcb_g_strdup_printf ("%m+%.2mS %s", UUNIT
, S
.Keepaway
, s45
);
2467 buf
= g_strdup_printf ("%d %%", S
.TextScale
);
2471 case INSERTPOINT_MODE
:
2472 case RUBBERBANDMOVE_MODE
:
2473 buf
= g_strdup_printf ("%s", s45
);
2476 case PASTEBUFFER_MODE
:
2487 xs
= XmStringCreatePCB (buf
);
2489 stdarg (XmNlabelString
, xs
);
2490 XtSetValues (m_status
, args
, n
);
2496 static int idle_proc_set
= 0;
2497 static int need_redraw
= 0;
2500 idle_proc (XtPointer dummy
)
2506 lesstif_use_mask (HID_MASK_OFF
);
2507 pixmap
= main_pixmap
;
2512 region
.X2
= Px (view_width
);
2513 region
.Y2
= Py (view_height
);
2516 Coord tmp
= region
.X1
;
2517 region
.X1
= region
.X2
;
2522 Coord tmp
= region
.Y1
;
2523 region
.Y1
= region
.Y2
;
2526 XSetForeground (display
, bg_gc
, bgcolor
);
2527 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0, mx
, my
);
2529 if (region
.X1
< 0 || region
.Y1
< 0
2530 || region
.X2
> PCB
->MaxWidth
|| region
.Y2
> PCB
->MaxHeight
)
2532 int leftmost
, rightmost
, topmost
, bottommost
;
2535 rightmost
= Vx (PCB
->MaxWidth
);
2537 bottommost
= Vy (PCB
->MaxHeight
);
2538 if (leftmost
> rightmost
) {
2540 leftmost
= rightmost
;
2543 if (topmost
> bottommost
) {
2545 topmost
= bottommost
;
2552 if (rightmost
> view_width
)
2553 rightmost
= view_width
;
2554 if (bottommost
> view_height
)
2555 bottommost
= view_height
;
2557 XSetForeground (display
, bg_gc
, offlimit_color
);
2565 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0,
2566 leftmost
, view_height
);
2568 if (rightmost
< view_width
)
2570 XFillRectangle (display
, main_pixmap
, bg_gc
, rightmost
+1, 0,
2571 view_width
-rightmost
+1, view_height
);
2575 XFillRectangle (display
, main_pixmap
, bg_gc
, leftmost
, 0,
2576 rightmost
-leftmost
+1, topmost
);
2578 if (bottommost
< view_height
)
2580 XFillRectangle (display
, main_pixmap
, bg_gc
, leftmost
, bottommost
+1,
2581 rightmost
-leftmost
+1, view_height
-bottommost
+1);
2584 DrawBackgroundImage();
2585 hid_expose_callback (&lesstif_graphics
, ®ion
, 0);
2587 lesstif_use_mask (HID_MASK_OFF
);
2588 show_crosshair (0); /* To keep the drawn / not drawn info correct */
2589 XSetFunction (display
, my_gc
, GXcopy
);
2590 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
2595 DrawAttached (crosshair_gc
);
2596 DrawMark (crosshair_gc
);
2602 static int c_x
= -2, c_y
= -2;
2603 static MarkType saved_mark
;
2604 static const Unit
*old_grid_unit
= NULL
;
2605 if (crosshair_x
!= c_x
|| crosshair_y
!= c_y
2606 || Settings
.grid_unit
!= old_grid_unit
2607 || memcmp (&saved_mark
, &Marked
, sizeof (MarkType
)))
2609 static int last_state
= 0;
2610 static int this_state
= 0;
2616 cursor_pos_to_widget (crosshair_x
, crosshair_y
, m_crosshair
,
2619 mark_delta_to_widget (crosshair_x
- Marked
.X
, crosshair_y
- Marked
.Y
,
2622 if (Marked
.status
!= saved_mark
.status
)
2626 XtManageChild (XtParent (m_mark
));
2627 XtManageChild (m_mark
);
2629 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
2630 stdarg (XmNleftWidget
, XtParent (m_mark
));
2631 XtSetValues (XtParent (m_crosshair
), args
, n
);
2636 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
2637 XtSetValues (XtParent (m_crosshair
), args
, n
);
2638 XtUnmanageChild (XtParent (m_mark
));
2640 last_state
= this_state
+ 100;
2642 memcpy (&saved_mark
, &Marked
, sizeof (MarkType
));
2644 if (old_grid_unit
!= Settings
.grid_unit
)
2646 old_grid_unit
= Settings
.grid_unit
;
2647 /* Force a resize on units change. */
2651 /* This is obtuse. We want to enable XmRESIZE_ANY long enough
2652 to shrink to fit the new format (if any), then switch it
2653 back to XmRESIZE_GROW to prevent it from shrinking due to
2654 changes in the number of actual digits printed. Thus, when
2655 you switch from a small grid and %.2f formats to a large
2656 grid and %d formats, you aren't punished with a wide and
2657 mostly white-space label widget. "this_state" indicates
2658 which of the above formats we're using. "last_state" is
2659 either zero (when resizing) or the same as "this_state"
2660 (when grow-only), or a non-zero but not "this_state" which
2661 means we need to start a resize cycle. */
2662 if (this_state
!= last_state
&& last_state
)
2665 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
2666 XtSetValues (XtParent (m_mark
), args
, n
);
2667 XtSetValues (XtParent (m_crosshair
), args
, n
);
2670 else if (this_state
!= last_state
)
2673 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
2674 XtSetValues (XtParent (m_mark
), args
, n
);
2675 XtSetValues (XtParent (m_crosshair
), args
, n
);
2676 last_state
= this_state
;
2682 static Coord old_grid
= -1;
2683 static Coord old_gx
, old_gy
;
2684 static const Unit
*old_unit
;
2686 if (PCB
->Grid
!= old_grid
2687 || PCB
->GridOffsetX
!= old_gx
2688 || PCB
->GridOffsetY
!= old_gy
|| Settings
.grid_unit
!= old_unit
)
2690 static char buf
[100];
2691 old_grid
= PCB
->Grid
;
2692 old_unit
= Settings
.grid_unit
;
2693 old_gx
= PCB
->GridOffsetX
;
2694 old_gy
= PCB
->GridOffsetY
;
2697 strcpy (buf
, "No Grid");
2701 if (old_gx
|| old_gy
)
2702 pcb_snprintf (buf
, sizeof (buf
), "%m+%$mS @%mS,%mS",
2703 UUNIT
, old_grid
, old_gx
, old_gy
);
2705 pcb_snprintf (buf
, sizeof (buf
), "%m+%$mS", UUNIT
, old_grid
);
2707 ms
= XmStringCreatePCB (buf
);
2709 stdarg (XmNlabelString
, ms
);
2710 XtSetValues (m_grid
, args
, n
);
2715 static double old_zoom
= -1;
2716 static const Unit
*old_grid_unit
= NULL
;
2717 if (view_zoom
!= old_zoom
|| Settings
.grid_unit
!= old_grid_unit
)
2719 gchar
*buf
= pcb_g_strdup_printf ("%m+%$mS/pix",
2720 Settings
.grid_unit
->allow
, (Coord
) view_zoom
);
2723 old_zoom
= view_zoom
;
2724 old_grid_unit
= Settings
.grid_unit
;
2726 ms
= XmStringCreatePCB (buf
);
2728 stdarg (XmNlabelString
, ms
);
2729 XtSetValues (m_zoom
, args
, n
);
2735 if (old_cursor_mode
!= Settings
.Mode
)
2740 static int free_cursor
= 0;
2742 old_cursor_mode
= Settings
.Mode
;
2743 switch (Settings
.Mode
)
2747 cursor
= XC_X_cursor
;
2757 case RECTANGLE_MODE
:
2759 cursor
= XC_ul_angle
;
2763 cursor
= XC_sb_up_arrow
;
2765 case POLYGONHOLE_MODE
:
2767 cursor
= XC_sb_up_arrow
;
2769 case PASTEBUFFER_MODE
:
2779 cursor
= XC_exchange
;
2787 cursor
= XC_crosshair
;
2791 cursor
= XC_crosshair
;
2793 case INSERTPOINT_MODE
:
2797 case RUBBERBANDMOVE_MODE
:
2799 cursor
= XC_top_left_corner
;
2803 cursor
= XC_iron_cross
;
2807 cursor
= XC_question_arrow
;
2812 cursor
= XC_draped_box
;
2814 cursor
= XC_left_ptr
;
2821 ms
= XmStringCreatePCB (s
);
2823 stdarg (XmNlabelString
, ms
);
2824 XtSetValues (m_mode
, args
, n
);
2828 XFreeCursor (display
, my_cursor
);
2833 static Pixmap nocur_source
= 0;
2834 static Pixmap nocur_mask
= 0;
2835 static Cursor nocursor
= 0;
2836 if (nocur_source
== 0)
2840 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2842 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2844 fg
.red
= fg
.green
= fg
.blue
= 65535;
2845 bg
.red
= bg
.green
= bg
.blue
= 0;
2846 fg
.flags
= bg
.flags
= DoRed
| DoGreen
| DoBlue
;
2847 nocursor
= XCreatePixmapCursor (display
, nocur_source
,
2848 nocur_mask
, &fg
, &bg
, 0, 0);
2850 my_cursor
= nocursor
;
2854 my_cursor
= XCreateFontCursor (display
, cursor
);
2857 XDefineCursor (display
, window
, my_cursor
);
2858 lesstif_update_status_line ();
2862 static char *old_clip
= 0;
2863 static int old_tscale
= -1;
2864 char *new_clip
= cur_clip ();
2866 if (new_clip
!= old_clip
|| Settings
.TextScale
!= old_tscale
)
2868 lesstif_update_status_line ();
2869 old_clip
= new_clip
;
2870 old_tscale
= Settings
.TextScale
;
2875 static int old_nrats
= -1;
2876 static char buf
[20];
2878 if (old_nrats
!= PCB
->Data
->RatN
)
2880 old_nrats
= PCB
->Data
->RatN
;
2881 sprintf(buf
, "%d rat%s", PCB
->Data
->RatN
, PCB
->Data
->RatN
== 1 ? "" : "s");
2882 if (PCB
->Data
->RatN
)
2884 XtManageChild(XtParent(m_rats
));
2885 XtManageChild(m_rats
);
2887 stdarg (XmNleftWidget
, m_rats
);
2888 XtSetValues (XtParent (m_status
), args
, n
);
2892 stdarg (XmNlabelString
, XmStringCreatePCB (buf
));
2893 XtSetValues (m_rats
, args
, n
);
2895 if (!PCB
->Data
->RatN
)
2898 stdarg (XmNleftWidget
, m_mode
);
2899 XtSetValues (XtParent (m_status
), args
, n
);
2900 XtUnmanageChild(XtParent(m_rats
));
2905 lesstif_update_widget_flags ();
2913 lesstif_need_idle_proc ()
2915 if (idle_proc_set
|| window
== 0)
2917 XtAppAddWorkProc (app_context
, idle_proc
, 0);
2922 lesstif_invalidate_lr (int l
, int r
, int t
, int b
)
2932 lesstif_invalidate_all (void)
2934 lesstif_invalidate_lr (0, PCB
->MaxWidth
, 0, PCB
->MaxHeight
);
2938 lesstif_notify_crosshair_change (bool changes_complete
)
2940 static int invalidate_depth
= 0;
2946 if (changes_complete
)
2947 invalidate_depth
--;
2949 if (invalidate_depth
< 0)
2951 invalidate_depth
= 0;
2952 /* A mismatch of changes_complete == false and == true notifications
2953 * is not expected to occur, but we will try to handle it gracefully.
2954 * As we know the crosshair will have been shown already, we must
2955 * repaint the entire view to be sure not to leave an artaefact.
2961 if (invalidate_depth
== 0 && crosshair_on
)
2963 save_pixmap
= pixmap
;
2965 DrawAttached (crosshair_gc
);
2966 pixmap
= save_pixmap
;
2969 if (!changes_complete
)
2970 invalidate_depth
++;
2974 lesstif_notify_mark_change (bool changes_complete
)
2976 static int invalidate_depth
= 0;
2979 if (changes_complete
)
2980 invalidate_depth
--;
2982 if (invalidate_depth
< 0)
2984 invalidate_depth
= 0;
2985 /* A mismatch of changes_complete == false and == true notifications
2986 * is not expected to occur, but we will try to handle it gracefully.
2987 * As we know the mark will have been shown already, we must
2988 * repaint the entire view to be sure not to leave an artaefact.
2994 if (invalidate_depth
== 0 && crosshair_on
)
2996 save_pixmap
= pixmap
;
2998 DrawMark (crosshair_gc
);
2999 pixmap
= save_pixmap
;
3002 if (!changes_complete
)
3003 invalidate_depth
++;
3007 lesstif_set_layer (const char *name
, int group
, int empty
)
3010 if (idx
>= 0 && idx
< max_group
)
3012 int n
= PCB
->LayerGroups
.Number
[group
];
3013 for (idx
= 0; idx
< n
-1; idx
++)
3015 int ni
= PCB
->LayerGroups
.Entries
[group
][idx
];
3016 if (ni
>= 0 && ni
< max_copper_layer
+ EXTRA_LAYERS
3017 && PCB
->Data
->Layer
[ni
].On
)
3020 idx
= PCB
->LayerGroups
.Entries
[group
][idx
];
3022 if (idx
== LayerStack
[0]
3023 || GetLayerGroupNumberByNumber (idx
) ==
3024 GetLayerGroupNumberByNumber (LayerStack
[0]))
3034 if (idx
>= 0 && idx
< max_copper_layer
+ EXTRA_LAYERS
)
3035 return pinout
? 1 : PCB
->Data
->Layer
[idx
].On
;
3038 switch (SL_TYPE (idx
))
3041 return pinout
? 0 : PCB
->InvisibleObjectsOn
;
3043 if (SL_MYSIDE (idx
) && !pinout
)
3044 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
3047 if (SL_MYSIDE (idx
) || pinout
)
3048 return PCB
->ElementOn
;
3063 lesstif_make_gc (void)
3065 hidGC gc
= (hidGC
)calloc (1, sizeof (struct lesstif_gc_struct
));
3067 gc
->hid
= &lesstif_hid
;
3068 gc
->hid_draw
= &lesstif_graphics
;
3074 lesstif_destroy_gc (hidGC gc
)
3080 lesstif_use_mask (enum mask_mode mode
)
3082 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) &&
3084 mode
= HID_MASK_OFF
;
3085 if ((mode
== HID_MASK_OFF
) == (use_mask
== HID_MASK_OFF
))
3092 /* printf("use_mask(%d)\n", use_it); */
3096 XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
,
3097 XDefaultDepth (display
, screen
));
3098 mask_bitmap
= XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
, 1);
3100 if (mode
!= HID_MASK_OFF
)
3102 pixmap
= mask_pixmap
;
3103 XSetForeground (display
, my_gc
, 0);
3104 XSetFunction (display
, my_gc
, GXcopy
);
3105 XFillRectangle (display
, mask_pixmap
, my_gc
,
3106 0, 0, view_width
, view_height
);
3107 XFillRectangle (display
, mask_bitmap
, bclear_gc
,
3108 0, 0, view_width
, view_height
);
3112 pixmap
= main_pixmap
;
3116 XRenderPictureAttributes pa
;
3118 pa
.clip_mask
= mask_bitmap
;
3119 XRenderChangePicture(display
, main_picture
, CPClipMask
, &pa
);
3120 XRenderComposite(display
, PictOpOver
, mask_picture
, pale_picture
,
3121 main_picture
, 0, 0, 0, 0, 0, 0, view_width
, view_height
);
3124 #endif /* HAVE_XRENDER */
3126 XSetClipMask (display
, clip_gc
, mask_bitmap
);
3127 XCopyArea (display
, mask_pixmap
, main_pixmap
, clip_gc
,
3128 0, 0, view_width
, view_height
, 0, 0);
3134 lesstif_set_color (hidGC gc
, const char *name
)
3136 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3137 static void *cache
= 0;
3139 static XColor color
, exact_color
;
3145 lesstif_gc
->colorname
= name
;
3146 if (strcmp (name
, "erase") == 0)
3148 lesstif_gc
->color
= bgcolor
;
3149 lesstif_gc
->erase
= 1;
3151 else if (strcmp (name
, "drill") == 0)
3153 lesstif_gc
->color
= offlimit_color
;
3154 lesstif_gc
->erase
= 0;
3156 else if (hid_cache_color (0, name
, &cval
, &cache
))
3158 lesstif_gc
->color
= cval
.lval
;
3159 lesstif_gc
->erase
= 0;
3163 if (!XAllocNamedColor (display
, colormap
, name
, &color
, &exact_color
))
3164 color
.pixel
= WhitePixel (display
, screen
);
3166 printf ("lesstif_set_color `%s' %08x rgb/%d/%d/%d\n",
3167 name
, color
.pixel
, color
.red
, color
.green
, color
.blue
);
3169 cval
.lval
= lesstif_gc
->color
= color
.pixel
;
3170 hid_cache_color (1, name
, &cval
, &cache
);
3171 lesstif_gc
->erase
= 0;
3175 static int lastcolor
= -1, lastfade
= -1;
3176 if (lesstif_gc
->color
== lastcolor
)
3177 lesstif_gc
->color
= lastfade
;
3180 lastcolor
= lesstif_gc
->color
;
3181 color
.pixel
= lesstif_gc
->color
;
3183 XQueryColor (display
, colormap
, &color
);
3184 color
.red
= (bgred
+ color
.red
) / 2;
3185 color
.green
= (bggreen
+ color
.green
) / 2;
3186 color
.blue
= (bgblue
+ color
.blue
) / 2;
3187 XAllocColor (display
, colormap
, &color
);
3188 lastfade
= lesstif_gc
->color
= color
.pixel
;
3196 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3197 int cap
, join
, width
;
3198 if (gc
->hid
!= &lesstif_hid
)
3200 fprintf (stderr
, "Fatal: GC from another HID passed to lesstif HID\n");
3204 pcb_printf ("set_gc c%s %08lx w%#mS c%d x%d e%d\n",
3205 lesstif_gc
->colorname
, lesstif_gc
->color
, lesstif_gc
->width
, lesstif_gc
->cap
, lesstif_gc
->xor_set
, lesstif_gc
->erase
);
3207 switch (lesstif_gc
->cap
)
3210 cap
= CapProjecting
;
3219 cap
= CapProjecting
;
3223 cap
= CapProjecting
;
3227 if (lesstif_gc
->xor_set
)
3229 XSetFunction (display
, my_gc
, GXxor
);
3230 XSetForeground (display
, my_gc
, lesstif_gc
->color
^ bgcolor
);
3232 else if (lesstif_gc
->erase
)
3234 XSetFunction (display
, my_gc
, GXcopy
);
3235 XSetForeground (display
, my_gc
, offlimit_color
);
3239 XSetFunction (display
, my_gc
, GXcopy
);
3240 XSetForeground (display
, my_gc
, lesstif_gc
->color
);
3242 width
= Vz (lesstif_gc
->width
);
3245 XSetLineAttributes (display
, my_gc
, width
, LineSolid
, cap
,
3249 if (lesstif_gc
->erase
)
3250 mask_gc
= bclear_gc
;
3253 XSetLineAttributes (display
, mask_gc
, Vz (lesstif_gc
->width
), LineSolid
, cap
,
3259 lesstif_set_line_cap (hidGC gc
, EndCapStyle style
)
3261 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3263 lesstif_gc
->cap
= style
;
3267 lesstif_set_line_width (hidGC gc
, Coord width
)
3269 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3271 lesstif_gc
->width
= width
;
3275 lesstif_set_draw_xor (hidGC gc
, int xor_set
)
3277 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3279 lesstif_gc
->xor_set
= xor_set
;
3282 #define ISORT(a,b) if (a>b) { a^=b; b^=a; a^=b; }
3285 lesstif_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3287 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3288 double dx1
, dy1
, dx2
, dy2
;
3289 int vw
= Vz (lesstif_gc
->width
);
3290 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && lesstif_gc
->erase
)
3293 pcb_printf ("draw_line %#mD-%#mD @%#mS", x1
, y1
, x2
, y2
, lesstif_gc
->width
);
3300 pcb_printf (" = %#mD-%#mD %s\n", x1
, y1
, x2
, y2
, lesstif_gc
->colorname
);
3304 if (! ClipLine (0, 0, view_width
, view_height
,
3305 &dx1
, &dy1
, &dx2
, &dy2
, vw
))
3315 if (lesstif_gc
->cap
== Square_Cap
&& x1
== x2
&& y1
== y2
)
3317 XFillRectangle (display
, pixmap
, my_gc
, x1
- vw
/ 2, y1
- vw
/ 2, vw
,
3320 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
- vw
/ 2,
3321 y1
- vw
/ 2, vw
, vw
);
3325 XDrawLine (display
, pixmap
, my_gc
, x1
, y1
, x2
, y2
);
3327 XDrawLine (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
, y2
);
3332 lesstif_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord width
, Coord height
,
3333 Angle start_angle
, Angle delta_angle
)
3335 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3337 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && lesstif_gc
->erase
)
3340 pcb_printf ("draw_arc %#mD %#mSx%#mS s %d d %d", cx
, cy
, width
, height
, start_angle
, delta_angle
);
3343 height
= Vz (height
);
3344 cx
= Vx (cx
) - width
;
3345 cy
= Vy (cy
) - height
;
3348 start_angle
= 180 - start_angle
;
3349 delta_angle
= - delta_angle
;
3353 start_angle
= - start_angle
;
3354 delta_angle
= - delta_angle
;
3356 start_angle
= NormalizeAngle (start_angle
);
3357 if (start_angle
>= 180)
3360 pcb_printf (" = %#mD %#mSx%#mS %d %s\n", cx
, cy
, width
, height
, lesstif_gc
->width
,
3361 lesstif_gc
->colorname
);
3364 XDrawArc (display
, pixmap
, my_gc
, cx
, cy
,
3365 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3367 if (use_mask
&& !TEST_FLAG (THINDRAWFLAG
, PCB
))
3368 XDrawArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3369 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3372 /* Enable this if you want to see the center and radii of drawn
3373 arcs, for debugging. */
3374 if (TEST_FLAG (THINDRAWFLAG
, PCB
)
3375 && delta_angle
!= 360)
3379 XDrawLine (display
, pixmap
, arc1_gc
, cx
, cy
,
3380 cx
- width
*cos(start_angle
*M_PI
/180),
3381 cy
+ width
*sin(start_angle
*M_PI
/180));
3382 XDrawLine (display
, pixmap
, arc2_gc
, cx
, cy
,
3383 cx
- width
*cos((start_angle
+delta_angle
)*M_PI
/180),
3384 cy
+ width
*sin((start_angle
+delta_angle
)*M_PI
/180));
3390 lesstif_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3392 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3393 int vw
= Vz (lesstif_gc
->width
);
3395 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && lesstif_gc
->erase
)
3401 if (x1
< -vw
&& x2
< -vw
)
3403 if (y1
< -vw
&& y2
< -vw
)
3405 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3407 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3409 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3410 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3412 XDrawRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1, y2
- y1
+ 1);
3414 XDrawRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3419 lesstif_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
3421 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3423 if (pinout
&& use_mask
&& lesstif_gc
->erase
)
3425 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && lesstif_gc
->erase
)
3428 pcb_printf ("fill_circle %#mD %#mS", cx
, cy
, radius
);
3430 radius
= Vz (radius
);
3431 cx
= Vx (cx
) - radius
;
3432 cy
= Vy (cy
) - radius
;
3433 if (cx
< -2 * radius
|| cx
> view_width
)
3435 if (cy
< -2 * radius
|| cy
> view_height
)
3438 pcb_printf (" = %#mD %#mS %lx %s\n", cx
, cy
, radius
, lesstif_gc
->color
, lesstif_gc
->colorname
);
3441 XFillArc (display
, pixmap
, my_gc
, cx
, cy
,
3442 radius
* 2, radius
* 2, 0, 360 * 64);
3444 XFillArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3445 radius
* 2, radius
* 2, 0, 360 * 64);
3449 lesstif_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
3451 static XPoint
*p
= 0;
3452 static int maxp
= 0;
3455 if (maxp
< n_coords
)
3457 maxp
= n_coords
+ 10;
3459 p
= (XPoint
*) realloc (p
, maxp
* sizeof (XPoint
));
3461 p
= (XPoint
*) malloc (maxp
* sizeof (XPoint
));
3464 for (i
= 0; i
< n_coords
; i
++)
3470 printf ("fill_polygon %d pts\n", n_coords
);
3473 XFillPolygon (display
, pixmap
, my_gc
, p
, n_coords
, Complex
,
3476 XFillPolygon (display
, mask_bitmap
, mask_gc
, p
, n_coords
, Complex
,
3481 lesstif_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3483 lesstifGC lesstif_gc
= (lesstifGC
)gc
;
3484 int vw
= Vz (lesstif_gc
->width
);
3486 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && lesstif_gc
->erase
)
3492 if (x1
< -vw
&& x2
< -vw
)
3494 if (y1
< -vw
&& y2
< -vw
)
3496 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3498 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3500 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3501 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3503 XFillRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1,
3506 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3511 lesstif_calibrate (double xval
, double yval
)
3517 lesstif_shift_is_pressed (void)
3519 return shift_pressed
;
3523 lesstif_control_is_pressed (void)
3525 return ctrl_pressed
;
3529 lesstif_mod1_is_pressed (void)
3534 extern void lesstif_get_coords (const char *msg
, Coord
*x
, Coord
*y
);
3537 lesstif_set_crosshair (int x
, int y
, int action
)
3539 if (crosshair_x
!= x
|| crosshair_y
!= y
)
3541 lesstif_show_crosshair(0);
3549 || x
> view_left_x
+ view_width
* view_zoom
3550 || y
< view_top_y
|| y
> view_top_y
+ view_height
* view_zoom
))
3552 view_left_x
= x
- (view_width
* view_zoom
) / 2;
3553 view_top_y
= y
- (view_height
* view_zoom
) / 2;
3554 lesstif_pan_fixup ();
3559 if (action
== HID_SC_PAN_VIEWPORT
)
3562 unsigned int keys_buttons
;
3563 int pos_x
, pos_y
, root_x
, root_y
;
3564 XQueryPointer (display
, window
, &root
, &child
,
3565 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
3567 view_left_x
= x
- (view_width
-pos_x
) * view_zoom
;
3569 view_left_x
= x
- pos_x
* view_zoom
;
3571 view_top_y
= y
- (view_height
-pos_y
) * view_zoom
;
3573 view_top_y
= y
- pos_y
* view_zoom
;
3574 lesstif_pan_fixup();
3575 action
= HID_SC_WARP_POINTER
;
3577 if (action
== HID_SC_WARP_POINTER
)
3580 XWarpPointer (display
, None
, window
, 0, 0, 0, 0, Vx(x
), Vy(y
));
3587 void (*func
) (hidval
);
3593 lesstif_timer_cb (XtPointer
* p
, XtIntervalId
* id
)
3595 TimerStruct
*ts
= (TimerStruct
*) p
;
3596 ts
->func (ts
->user_data
);
3601 lesstif_add_timer (void (*func
) (hidval user_data
),
3602 unsigned long milliseconds
, hidval user_data
)
3606 t
= (TimerStruct
*) malloc (sizeof (TimerStruct
));
3609 t
->user_data
= user_data
;
3610 t
->id
= XtAppAddTimeOut (app_context
, milliseconds
, (XtTimerCallbackProc
)lesstif_timer_cb
, t
);
3615 lesstif_stop_timer (hidval hv
)
3617 TimerStruct
*ts
= (TimerStruct
*) hv
.ptr
;
3618 XtRemoveTimeOut (ts
->id
);
3625 void (*func
) ( hidval
, int, unsigned int, hidval
);
3632 /* We need a wrapper around the hid file watch because to pass the correct flags
3635 lesstif_watch_cb (XtPointer client_data
, int *fid
, XtInputId
* id
)
3637 unsigned int pcb_condition
= 0;
3641 WatchStruct
*watch
= (WatchStruct
*)client_data
;
3644 fds
.events
= POLLIN
| POLLOUT
;
3646 condition
= fds
.revents
;
3648 // Should we only include those we were asked to watch?
3649 if (condition
& POLLIN
)
3650 pcb_condition
|= PCB_WATCH_READABLE
;
3651 if (condition
& POLLOUT
)
3652 pcb_condition
|= PCB_WATCH_WRITABLE
;
3653 if (condition
& POLLERR
)
3654 pcb_condition
|= PCB_WATCH_ERROR
;
3655 if (condition
& POLLHUP
)
3656 pcb_condition
|= PCB_WATCH_HANGUP
;
3658 x
.ptr
= (void *) watch
;
3659 watch
->func (x
, watch
->fd
, pcb_condition
, watch
->user_data
);
3665 lesstif_watch_file (int fd
, unsigned int condition
, void (*func
) (hidval watch
, int fd
, unsigned int condition
, hidval user_data
),
3668 WatchStruct
*watch
= (WatchStruct
*) malloc (sizeof(WatchStruct
));
3670 unsigned int xt_condition
= 0;
3672 if (condition
& PCB_WATCH_READABLE
)
3673 xt_condition
|= XtInputReadMask
;
3674 if (condition
& PCB_WATCH_WRITABLE
)
3675 xt_condition
|= XtInputWriteMask
;
3676 if (condition
& PCB_WATCH_ERROR
)
3677 xt_condition
|= XtInputExceptMask
;
3678 if (condition
& PCB_WATCH_HANGUP
)
3679 xt_condition
|= XtInputExceptMask
;
3682 watch
->user_data
= user_data
;
3684 watch
->id
= XtAppAddInput( app_context
, fd
, (XtPointer
) (size_t) xt_condition
, lesstif_watch_cb
, watch
);
3686 ret
.ptr
= (void *) watch
;
3691 lesstif_unwatch_file (hidval data
)
3693 WatchStruct
*watch
= (WatchStruct
*)data
.ptr
;
3694 XtRemoveInput( watch
->id
);
3701 void (*func
) (hidval user_data
);
3705 static void lesstif_block_hook_cb(XtPointer user_data
);
3708 lesstif_block_hook_cb (XtPointer user_data
)
3710 BlockHookStruct
*block_hook
= (BlockHookStruct
*)user_data
;
3711 block_hook
->func( block_hook
->user_data
);
3715 lesstif_add_block_hook (void (*func
) (hidval data
), hidval user_data
)
3718 BlockHookStruct
*block_hook
= (BlockHookStruct
*) malloc( sizeof( BlockHookStruct
));
3720 block_hook
->func
= func
;
3721 block_hook
->user_data
= user_data
;
3723 block_hook
->id
= XtAppAddBlockHook( app_context
, lesstif_block_hook_cb
, (XtPointer
)block_hook
);
3725 ret
.ptr
= (void *) block_hook
;
3730 lesstif_stop_block_hook (hidval mlpoll
)
3732 BlockHookStruct
*block_hook
= (BlockHookStruct
*)mlpoll
.ptr
;
3733 XtRemoveBlockHook( block_hook
->id
);
3738 extern void lesstif_logv (const char *fmt
, va_list ap
);
3740 extern int lesstif_confirm_dialog (char *msg
, ...);
3742 extern int lesstif_close_confirm_dialog ();
3744 extern void lesstif_report_dialog (char *title
, char *msg
);
3747 lesstif_attribute_dialog (HID_Attribute
* attrs
,
3748 int n_attrs
, HID_Attr_Val
* results
,
3749 const char * title
, const char * descr
);
3752 pinout_callback (Widget da
, PinoutData
* pd
,
3753 XmDrawingAreaCallbackStruct
* cbs
)
3756 int save_vx
, save_vy
, save_vw
, save_vh
;
3757 int save_fx
, save_fy
;
3760 int reason
= cbs
? cbs
->reason
: 0;
3762 if (pd
->window
== 0 && reason
== XmCR_RESIZE
)
3764 if (pd
->window
== 0 || reason
== XmCR_RESIZE
)
3770 stdarg (XmNwidth
, &w
);
3771 stdarg (XmNheight
, &h
);
3772 XtGetValues (da
, args
, n
);
3774 pd
->window
= XtWindow (da
);
3777 pd
->zoom
= (pd
->right
- pd
->left
+ 1) / (double) w
;
3778 z
= (pd
->bottom
- pd
->top
+ 1) / (double) h
;
3782 pd
->x
= (pd
->left
+ pd
->right
) / 2 - pd
->v_width
* pd
->zoom
/ 2;
3783 pd
->y
= (pd
->top
+ pd
->bottom
) / 2 - pd
->v_height
* pd
->zoom
/ 2;
3786 save_vx
= view_left_x
;
3787 save_vy
= view_top_y
;
3788 save_vz
= view_zoom
;
3789 save_vw
= view_width
;
3790 save_vh
= view_height
;
3795 pixmap
= pd
->window
;
3796 view_left_x
= pd
->x
;
3798 view_zoom
= pd
->zoom
;
3799 view_width
= pd
->v_width
;
3800 view_height
= pd
->v_height
;
3802 flip_x
= flip_y
= 0;
3806 region
.X2
= PCB
->MaxWidth
;
3807 region
.Y2
= PCB
->MaxHeight
;
3809 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, pd
->v_width
, pd
->v_height
);
3810 hid_expose_callback (&lesstif_graphics
, ®ion
, pd
->item
);
3813 view_left_x
= save_vx
;
3814 view_top_y
= save_vy
;
3815 view_zoom
= save_vz
;
3816 view_width
= save_vw
;
3817 view_height
= save_vh
;
3824 pinout_unmap (Widget w
, PinoutData
* pd
, void *v
)
3827 pd
->prev
->next
= pd
->next
;
3831 pd
->next
->prev
= pd
->prev
;
3832 XtDestroyWidget (XtParent (pd
->form
));
3837 lesstif_show_item (void *item
)
3844 for (pd
= pinouts
; pd
; pd
= pd
->next
)
3845 if (pd
->item
== item
)
3850 pd
= (PinoutData
*) calloc (1, sizeof (PinoutData
));
3854 extents
= hid_get_extents (item
);
3855 pd
->left
= extents
->X1
;
3856 pd
->right
= extents
->X2
;
3857 pd
->top
= extents
->Y1
;
3858 pd
->bottom
= extents
->Y2
;
3860 if (pd
->left
> pd
->right
)
3868 pd
->next
->prev
= pd
;
3873 pd
->form
= XmCreateFormDialog (mainwind
, "pinout", args
, n
);
3875 XtAddCallback (pd
->form
, XmNunmapCallback
, (XtCallbackProc
) pinout_unmap
,
3879 sqrt (200.0 * 200.0 /
3880 ((pd
->right
- pd
->left
+ 1.0) * (pd
->bottom
- pd
->top
+ 1.0)));
3883 stdarg (XmNwidth
, (int) (scale
* (pd
->right
- pd
->left
+ 1)));
3884 stdarg (XmNheight
, (int) (scale
* (pd
->bottom
- pd
->top
+ 1)));
3885 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
3886 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
3887 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
3888 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
3889 da
= XmCreateDrawingArea (pd
->form
, "pinout", args
, n
);
3892 XtAddCallback (da
, XmNexposeCallback
, (XtCallbackProc
) pinout_callback
,
3894 XtAddCallback (da
, XmNresizeCallback
, (XtCallbackProc
) pinout_callback
,
3897 XtManageChild (pd
->form
);
3909 static bool progress_cancelled
= false;
3912 progress_cancel_callback (Widget w
, void *v
, void *cbs
)
3914 progress_cancelled
= true;
3917 static Widget progress_dialog
= 0;
3918 static Widget progress_cancel
, progress_label
;
3919 static Widget progress_scale
;
3922 lesstif_progress_dialog (int so_far
, int total
, const char *msg
)
3929 if (progress_dialog
== 0)
3934 stdarg (XmNdefaultButtonType
, XmDIALOG_CANCEL_BUTTON
);
3935 stdarg (XmNtitle
, "Progress");
3936 stdarg (XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
);
3937 stdarg (XmNdialogStyle
, XmDIALOG_FULL_APPLICATION_MODAL
);
3938 progress_dialog
= XmCreateInformationDialog (mainwind
, "progress", args
, n
);
3939 XtAddCallback (progress_dialog
, XmNcancelCallback
,
3940 (XtCallbackProc
) progress_cancel_callback
, NULL
);
3942 progress_cancel
= XmMessageBoxGetChild (progress_dialog
, XmDIALOG_CANCEL_BUTTON
);
3943 progress_label
= XmMessageBoxGetChild (progress_dialog
, XmDIALOG_MESSAGE_LABEL
);
3945 XtUnmanageChild (XmMessageBoxGetChild (progress_dialog
, XmDIALOG_OK_BUTTON
));
3946 XtUnmanageChild (XmMessageBoxGetChild (progress_dialog
, XmDIALOG_HELP_BUTTON
));
3948 stdarg (XmNdefaultPosition
, False
);
3949 XtSetValues (progress_dialog
, args
, n
);
3952 stdarg(XmNminimum
, 0);
3953 stdarg(XmNvalue
, 0);
3954 stdarg(XmNmaximum
, total
> 0 ? total
: 1);
3955 stdarg(XmNorientation
, XmHORIZONTAL
);
3956 stdarg(XmNshowArrows
, false);
3957 progress_scale
= XmCreateScrollBar (progress_dialog
, "scale", args
, n
);
3958 XtManageChild (progress_scale
);
3960 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
3961 XmAddWMProtocolCallback (XtParent (progress_dialog
), close_atom
,
3962 (XtCallbackProc
) progress_cancel_callback
, 0);
3966 stdarg(XmNvalue
, 0);
3967 stdarg(XmNsliderSize
, (so_far
<= total
) ? (so_far
< 0) ? 0 : so_far
: total
);
3968 stdarg(XmNmaximum
, total
> 0 ? total
: 1);
3969 XtSetValues (progress_scale
, args
, n
);
3972 xs
= XmStringCreatePCB ((char *)msg
);
3973 stdarg (XmNmessageString
, xs
);
3974 XtSetValues (progress_dialog
, args
, n
);
3979 #define MIN_TIME_SEPARATION 0.1 /* seconds */
3982 lesstif_progress (int so_far
, int total
, const char *message
)
3984 static bool started
= false;
3986 struct timeval time
;
3987 double time_delta
, time_now
;
3988 static double time_then
= 0.0;
3991 if (so_far
== 0 && total
== 0 && message
== NULL
)
3993 XtUnmanageChild (progress_dialog
);
3995 progress_cancelled
= false;
3999 gettimeofday (&time
, NULL
);
4000 time_now
= time
.tv_sec
+ time
.tv_usec
/ 1000000.0;
4002 time_delta
= time_now
- time_then
;
4004 if (started
&& time_delta
< MIN_TIME_SEPARATION
)
4007 /* Create or update the progress dialog */
4008 lesstif_progress_dialog (so_far
, total
, message
);
4012 XtManageChild (progress_dialog
);
4016 /* Dispatch pending events */
4017 while (XtAppPending (app_context
))
4019 XtAppNextEvent (app_context
, &e
);
4020 XtDispatchEvent (&e
);
4024 /* If rendering takes a while, make sure the core has enough time to
4026 gettimeofday (&time
, NULL
);
4027 time_then
= time
.tv_sec
+ time
.tv_usec
/ 1000000.0;
4029 return progress_cancelled
;
4033 lesstif_request_debug_draw (void)
4035 /* Send drawing to the backing pixmap */
4036 pixmap
= main_pixmap
;
4037 return &lesstif_graphics
;
4041 lesstif_flush_debug_draw (void)
4043 /* Copy the backing pixmap to the display and redraw any attached objects */
4044 XSetFunction (display
, my_gc
, GXcopy
);
4045 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
4050 DrawAttached (crosshair_gc
);
4051 DrawMark (crosshair_gc
);
4053 pixmap
= main_pixmap
;
4057 lesstif_finish_debug_draw (void)
4059 lesstif_flush_debug_draw ();
4060 /* No special tear down requirements
4064 #include "dolists.h"
4069 memset (&lesstif_hid
, 0, sizeof (HID
));
4070 memset (&lesstif_graphics
, 0, sizeof (HID_DRAW
));
4071 memset (&lesstif_graphics_class
, 0, sizeof (HID_DRAW_CLASS
));
4073 common_nogui_init (&lesstif_hid
);
4075 lesstif_hid
.struct_size
= sizeof (HID
);
4076 lesstif_hid
.name
= "lesstif";
4077 lesstif_hid
.description
= "LessTif - a Motif clone for X/Unix";
4078 lesstif_hid
.gui
= 1;
4080 lesstif_hid
.get_export_options
= lesstif_get_export_options
;
4081 lesstif_hid
.do_export
= lesstif_do_export
;
4082 lesstif_hid
.parse_arguments
= lesstif_parse_arguments
;
4083 lesstif_hid
.invalidate_lr
= lesstif_invalidate_lr
;
4084 lesstif_hid
.invalidate_all
= lesstif_invalidate_all
;
4085 lesstif_hid
.notify_crosshair_change
= lesstif_notify_crosshair_change
;
4086 lesstif_hid
.notify_mark_change
= lesstif_notify_mark_change
;
4088 lesstif_hid
.calibrate
= lesstif_calibrate
;
4089 lesstif_hid
.shift_is_pressed
= lesstif_shift_is_pressed
;
4090 lesstif_hid
.control_is_pressed
= lesstif_control_is_pressed
;
4091 lesstif_hid
.mod1_is_pressed
= lesstif_mod1_is_pressed
;
4092 lesstif_hid
.get_coords
= lesstif_get_coords
;
4093 lesstif_hid
.set_crosshair
= lesstif_set_crosshair
;
4094 lesstif_hid
.add_timer
= lesstif_add_timer
;
4095 lesstif_hid
.stop_timer
= lesstif_stop_timer
;
4096 lesstif_hid
.watch_file
= lesstif_watch_file
;
4097 lesstif_hid
.unwatch_file
= lesstif_unwatch_file
;
4098 lesstif_hid
.add_block_hook
= lesstif_add_block_hook
;
4099 lesstif_hid
.stop_block_hook
= lesstif_stop_block_hook
;
4101 lesstif_hid
.log
= lesstif_log
;
4102 lesstif_hid
.logv
= lesstif_logv
;
4103 lesstif_hid
.confirm_dialog
= lesstif_confirm_dialog
;
4104 lesstif_hid
.close_confirm_dialog
= lesstif_close_confirm_dialog
;
4105 lesstif_hid
.report_dialog
= lesstif_report_dialog
;
4106 lesstif_hid
.prompt_for
= lesstif_prompt_for
;
4107 lesstif_hid
.fileselect
= lesstif_fileselect
;
4108 lesstif_hid
.attribute_dialog
= lesstif_attribute_dialog
;
4109 lesstif_hid
.show_item
= lesstif_show_item
;
4110 lesstif_hid
.beep
= lesstif_beep
;
4111 lesstif_hid
.progress
= lesstif_progress
;
4112 lesstif_hid
.edit_attributes
= lesstif_attributes_dialog
;
4114 lesstif_hid
.request_debug_draw
= lesstif_request_debug_draw
;
4115 lesstif_hid
.flush_debug_draw
= lesstif_flush_debug_draw
;
4116 lesstif_hid
.finish_debug_draw
= lesstif_finish_debug_draw
;
4118 common_nogui_graphics_class_init (&lesstif_graphics_class
);
4119 common_draw_helpers_class_init (&lesstif_graphics_class
);
4121 lesstif_graphics_class
.set_layer
= lesstif_set_layer
;
4122 lesstif_graphics_class
.make_gc
= lesstif_make_gc
;
4123 lesstif_graphics_class
.destroy_gc
= lesstif_destroy_gc
;
4124 lesstif_graphics_class
.use_mask
= lesstif_use_mask
;
4125 lesstif_graphics_class
.set_color
= lesstif_set_color
;
4126 lesstif_graphics_class
.set_line_cap
= lesstif_set_line_cap
;
4127 lesstif_graphics_class
.set_line_width
= lesstif_set_line_width
;
4128 lesstif_graphics_class
.set_draw_xor
= lesstif_set_draw_xor
;
4129 lesstif_graphics_class
.draw_line
= lesstif_draw_line
;
4130 lesstif_graphics_class
.draw_arc
= lesstif_draw_arc
;
4131 lesstif_graphics_class
.draw_rect
= lesstif_draw_rect
;
4132 lesstif_graphics_class
.fill_circle
= lesstif_fill_circle
;
4133 lesstif_graphics_class
.fill_polygon
= lesstif_fill_polygon
;
4134 lesstif_graphics_class
.fill_rect
= lesstif_fill_rect
;
4136 lesstif_graphics_class
.draw_pcb_polygon
= common_gui_draw_pcb_polygon
;
4138 lesstif_graphics_class
.can_draw_in_mask_clear
= true;
4140 lesstif_graphics
.klass
= &lesstif_graphics_class
;
4141 lesstif_graphics
.poly_before
= true;
4142 common_nogui_graphics_init (&lesstif_graphics
);
4143 common_draw_helpers_init (&lesstif_graphics
);
4145 hid_register_hid (&lesstif_hid
);
4146 #include "lesstif_lists.h"