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 enum mask_mode use_mask
= HID_MASK_OFF
;
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 static hidGC crosshair_gc
;
104 /* These are for the pinout windows. */
105 typedef struct PinoutData
107 struct PinoutData
*prev
, *next
;
110 Coord left
, right
, top
, bottom
; /* PCB extents of item */
111 Coord x
, y
; /* PCB coordinates of upper right corner of window */
112 double zoom
; /* PCB units per screen pixel */
113 int v_width
, v_height
; /* pixels */
117 /* Linked list of all pinout windows. */
118 static PinoutData
*pinouts
= 0;
119 /* If set, we are currently updating this pinout window. */
120 static PinoutData
*pinout
= 0;
122 static int crosshair_x
= 0, crosshair_y
= 0;
123 static int in_move_event
= 0, crosshair_in_window
= 1;
126 Widget work_area
, messages
, command
, hscroll
, vscroll
;
127 static Widget m_mark
, m_crosshair
, m_grid
, m_zoom
, m_mode
, m_status
;
128 static Widget m_rats
;
129 Widget lesstif_m_layer
;
132 /* This is the size, in pixels, of the viewport. */
133 static int view_width
, view_height
;
134 /* This is the PCB location represented by the upper left corner of
135 the viewport. Note that PCB coordinates put 0,0 in the upper left,
137 static int view_left_x
= 0, view_top_y
= 0;
138 /* Denotes PCB units per screen pixel. Larger numbers mean zooming
139 out - the largest value means you are looking at the whole
141 static double view_zoom
= MIL_TO_COORD (10), prev_view_zoom
= MIL_TO_COORD (10);
142 static bool flip_x
= 0, flip_y
= 0;
143 static bool autofade
= 0;
144 static bool crosshair_on
= true;
146 /* ---------------------------------------------------------------------------
147 * some local prototypes
149 static hidGC
lesstif_make_gc (void);
152 ShowCrosshair (bool show
)
154 if (crosshair_on
== show
)
157 notify_crosshair_change (false);
159 notify_mark_change (false);
163 notify_crosshair_change (true);
165 notify_mark_change (true);
169 flag_flipx (void *data
)
174 flag_flipy (void *data
)
179 HID_Flag lesstif_main_flag_list
[] = {
180 {"flip_x", flag_flipx
, NULL
},
181 {"flip_y", flag_flipy
, NULL
}
184 REGISTER_FLAGS (lesstif_main_flag_list
)
186 /* This is the size of the current PCB work area. */
187 /* Use PCB->MaxWidth, PCB->MaxHeight. */
188 /* static int pcb_width, pcb_height; */
192 #define stdarg(t,v) XtSetArg(args[n], t, v), n++
195 static int use_private_colormap
= 0;
196 static int stdin_listen
= 0;
197 static char *background_image_file
= 0;
198 char *lesstif_pcbmenu_path
= "pcb-menu.res";
200 HID_Attribute lesstif_attribute_list
[] = {
201 {"install", "Install private colormap",
202 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &use_private_colormap
},
203 #define HA_colormap 0
205 /* %start-doc options "22 lesstif GUI Options"
208 Listen for actions on stdin.
212 {"listen", "Listen on standard input for actions",
213 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &stdin_listen
},
216 /* %start-doc options "22 lesstif GUI Options"
218 @item --bg-image <string>
219 File name of an image to put into the background of the GUI canvas. The image must
220 be a color PPM image, in binary (not ASCII) format. It can be any size, and will be
221 automatically scaled to fit the canvas.
225 {"bg-image", "Background Image",
226 HID_String
, 0, 0, {0, 0, 0}, 0, &background_image_file
},
227 #define HA_bg_image 2
229 /* %start-doc options "22 lesstif GUI Options"
231 @item --pcb-menu <string>
232 Location of the @file{pcb-menu.res} file which defines the menu for the lesstif GUI.
236 {"pcb-menu", "Location of pcb-menu.res file",
237 HID_String
, 0, 0, {0, PCBLIBDIR
"/pcb-menu.res", 0}, 0, &lesstif_pcbmenu_path
}
241 REGISTER_ATTRIBUTES (lesstif_attribute_list
)
243 static void lesstif_use_mask (enum mask_mode mode
);
244 static void zoom_max ();
245 static void zoom_to (double factor
, int x
, int y
);
246 static void zoom_by (double factor
, int x
, int y
);
247 static void zoom_toggle (int x
, int y
);
248 static void pinout_callback (Widget
, PinoutData
*,
249 XmDrawingAreaCallbackStruct
*);
250 static void pinout_unmap (Widget
, PinoutData
*, void *);
251 static void Pan (int mode
, int x
, int y
);
253 /* Px converts view->pcb, Vx converts pcb->view */
258 int rv
= (x
- view_left_x
) / view_zoom
+ 0.5;
260 rv
= view_width
- rv
;
267 int rv
= (y
- view_top_y
) / view_zoom
+ 0.5;
269 rv
= view_height
- rv
;
276 return z
/ view_zoom
+ 0.5;
284 return x
* view_zoom
+ view_left_x
;
292 return y
* view_zoom
+ view_top_y
;
298 return z
* view_zoom
;
302 lesstif_coords_to_pcb (int vx
, int vy
, Coord
*px
, Coord
*py
)
309 lesstif_parse_color (char *value
)
312 if (XParseColor (display
, colormap
, value
, &color
))
313 if (XAllocColor (display
, colormap
, &color
))
319 do_color (char *value
, char *which
)
322 if (XParseColor (display
, colormap
, value
, &color
))
323 if (XAllocColor (display
, colormap
, &color
))
325 stdarg (which
, color
.pixel
);
329 /* ------------------------------------------------------------ */
334 if (TEST_FLAG (ORTHOMOVEFLAG
, PCB
))
336 if (TEST_FLAG (ALLDIRECTIONFLAG
, PCB
))
338 if (PCB
->Clipping
== 0)
340 if (PCB
->Clipping
== 1)
345 /* Called from the core when it's busy doing something and we need to
346 indicate that to the user. */
348 Busy(int argc
, char **argv
, Coord x
, Coord y
)
350 static Cursor busy_cursor
= 0;
351 if (busy_cursor
== 0)
352 busy_cursor
= XCreateFontCursor (display
, XC_watch
);
353 XDefineCursor (display
, window
, busy_cursor
);
355 old_cursor_mode
= -1;
359 /* ---------------------------------------------------------------------- */
364 PointCursor (int argc
, char **argv
, Coord x
, Coord y
)
370 old_cursor_mode
= -1;
375 PCBChanged (int argc
, char **argv
, Coord x
, Coord y
)
379 /*pcb_printf("PCB Changed! %$mD\n", PCB->MaxWidth, PCB->MaxHeight); */
381 stdarg (XmNminimum
, 0);
382 stdarg (XmNvalue
, 0);
383 stdarg (XmNsliderSize
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
384 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
385 XtSetValues (hscroll
, args
, n
);
387 stdarg (XmNminimum
, 0);
388 stdarg (XmNvalue
, 0);
389 stdarg (XmNsliderSize
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
390 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
391 XtSetValues (vscroll
, args
, n
);
394 hid_action ("NetlistChanged");
395 hid_action ("LayersChanged");
396 hid_action ("RouteStylesChanged");
397 lesstif_sizes_reset ();
398 lesstif_update_layer_groups ();
400 pinout_unmap (0, pinouts
, 0);
403 char *cp
= strrchr (PCB
->Filename
, '/');
405 stdarg (XmNtitle
, cp
? cp
+ 1 : PCB
->Filename
);
406 XtSetValues (appwidget
, args
, n
);
412 static const char setunits_syntax
[] =
415 static const char setunits_help
[] =
416 "Set the default measurement units.";
418 /* %start-doc actions SetUnits
423 Sets the display units to mils (1/1000 inch).
426 Sets the display units to millimeters.
433 SetUnits (int argc
, char **argv
, Coord x
, Coord y
)
435 const Unit
*new_unit
;
438 new_unit
= get_unit_struct (argv
[0]);
439 if (new_unit
!= NULL
&& new_unit
->allow
!= NO_PRINT
)
441 Settings
.grid_unit
= new_unit
;
442 Settings
.increments
= get_increments_struct (Settings
.grid_unit
->family
);
443 AttributePut (PCB
, "PCB::grid::unit", argv
[0]);
445 lesstif_sizes_reset ();
446 lesstif_styles_update_values ();
450 static const char zoom_syntax
[] =
454 static const char zoom_help
[] =
455 "Various zoom factor changes.";
457 /* %start-doc actions Zoom
459 Changes the zoom (magnification) of the view of the board. If no
460 arguments are passed, the view is scaled such that the board just fits
461 inside the visible window (i.e. ``view all''). Otherwise,
462 @var{factor} specifies a change in zoom factor. It may be prefixed by
463 @code{+}, @code{-}, or @code{=} to change how the zoom factor is
464 modified. The @var{factor} is a floating point number, such as
465 @code{1.5} or @code{0.75}.
470 Values greater than 1.0 cause the board to be drawn smaller; more of
471 the board will be visible. Values between 0.0 and 1.0 cause the board
472 to be drawn bigger; less of the board will be visible.
475 Values greater than 1.0 cause the board to be drawn bigger; less of
476 the board will be visible. Values between 0.0 and 1.0 cause the board
477 to be drawn smaller; more of the board will be visible.
481 The @var{factor} is an absolute zoom factor; the unit for this value
482 is "PCB units per screen pixel". Since PCB units are 0.01 mil, a
483 @var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI,
484 about the actual resolution of most screens - resulting in an "actual
485 size" board. Similarly, a @var{factor} of 100 gives you a 10x actual
490 Note that zoom factors of zero are silently ignored.
495 ZoomAction (int argc
, char **argv
, Coord x
, Coord y
)
499 if (x
== 0 && y
== 0)
515 if (strcasecmp (vp
, "toggle") == 0)
520 if (*vp
== '+' || *vp
== '-' || *vp
== '=')
522 v
= g_ascii_strtod (vp
, 0);
528 zoom_by (1 / v
, x
, y
);
541 static int pan_thumb_mode
;
544 PanAction (int argc
, char **argv
, Coord x
, Coord y
)
550 pan_thumb_mode
= (strcasecmp (argv
[0], "thumb") == 0) ? 1 : 0;
551 mode
= atoi (argv
[1]);
556 mode
= atoi (argv
[0]);
558 Pan (mode
, Vx(x
), Vy(y
));
563 static const char swapsides_syntax
[] =
566 static const char swapsides_help
[] =
567 "Swaps the side of the board you're looking at.";
569 /* %start-doc actions SwapSides
571 This action changes the way you view the board.
576 Flips the board over vertically (up/down).
579 Flips the board over horizontally (left/right), like flipping pages in
583 Rotates the board 180 degrees without changing sides.
587 If no argument is given, the board isn't moved but the opposite side
590 Normally, this action changes which pads and silk layer are drawn as
591 true silk, and which are drawn as the "invisible" layer. It also
592 determines which solder mask you see.
594 As a special case, if the layer group for the side you're looking at
595 is visible and currently active, and the layer group for the opposite
596 is not visible (i.e. disabled), then this action will also swap which
597 layer group is visible and active, effectively swapping the ``working
603 group_showing (int g
, int *c
)
606 *c
= PCB
->LayerGroups
.Entries
[g
][0];
607 for (i
=0; i
<PCB
->LayerGroups
.Number
[g
]; i
++)
609 l
= PCB
->LayerGroups
.Entries
[g
][i
];
610 if (l
>= 0 && l
< max_copper_layer
)
613 if (PCB
->Data
->Layer
[l
].On
)
621 SwapSides (int argc
, char **argv
, Coord x
, Coord y
)
623 int old_shown_side
= Settings
.ShowBottomSide
;
624 int top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
625 int bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
626 int active_group
= GetLayerGroupNumberByNumber (LayerStack
[0]);
629 int top_showing
= group_showing (top_group
, &top_layer
);
630 int bottom_showing
= group_showing (bottom_group
, &bottom_layer
);
634 switch (argv
[0][0]) {
651 /* SwapSides will swap this */
652 Settings
.ShowBottomSide
= (flip_x
== flip_y
);
657 stdarg (XmNprocessingDirection
, XmMAX_ON_LEFT
);
659 stdarg (XmNprocessingDirection
, XmMAX_ON_RIGHT
);
660 XtSetValues (hscroll
, args
, n
);
664 stdarg (XmNprocessingDirection
, XmMAX_ON_TOP
);
666 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
667 XtSetValues (vscroll
, args
, n
);
669 Settings
.ShowBottomSide
= !Settings
.ShowBottomSide
;
671 /* The idea is that if we're looking at the front side and the front
672 layer is active (or visa versa), switching sides should switch
673 layers too. We used to only do this if the other layer wasn't
674 shown, but we now do it always. Change it back if users get
676 if (Settings
.ShowBottomSide
!= old_shown_side
)
678 if (Settings
.ShowBottomSide
)
680 if (active_group
== top_group
)
682 if (top_showing
&& !bottom_showing
)
683 ChangeGroupVisibility (top_layer
, 0, 0);
684 ChangeGroupVisibility (bottom_layer
, 1, 1);
689 if (active_group
== bottom_group
)
691 if (bottom_showing
&& !top_showing
)
692 ChangeGroupVisibility (bottom_layer
, 0, 0);
693 ChangeGroupVisibility (top_layer
, 1, 1);
697 lesstif_invalidate_all ();
701 static Widget m_cmd
= 0, m_cmd_label
;
704 command_callback (Widget w
, XtPointer uptr
, XmTextVerifyCallbackStruct
* cbs
)
710 s
= XmTextGetString (w
);
711 lesstif_show_crosshair (0);
712 hid_parse_command (s
);
714 XmTextSetString (w
, "");
715 case XmCR_LOSING_FOCUS
:
716 XtUnmanageChild (m_cmd
);
717 XtUnmanageChild (m_cmd_label
);
723 command_event_handler (Widget w
, XtPointer p
, XEvent
* e
, Boolean
* cont
)
731 XLookupString ((XKeyEvent
*)e
, buf
, sizeof (buf
), &sym
, NULL
);
735 XtUnmanageChild (m_cmd
);
736 XtUnmanageChild (m_cmd_label
);
737 XmTextSetString (w
, "");
745 static const char command_syntax
[] =
748 static const char command_help
[] =
749 "Displays the command line input window.";
751 /* %start-doc actions Command
753 The command window allows the user to manually enter actions to be
754 executed. Action syntax can be done one of two ways:
759 Follow the action name by an open parenthesis, arguments separated by
760 commas, end with a close parenthesis. Example: @code{Abc(1,2,3)}
763 Separate the action name and arguments by spaces. Example: @code{Abc
768 The first option allows you to have arguments with spaces in them,
769 but the second is more ``natural'' to type for most people.
771 Note that action names are not case sensitive, but arguments normally
772 are. However, most actions will check for ``keywords'' in a case
775 There are three ways to finish with the command window. If you press
776 the @code{Enter} key, the command is invoked, the window goes away,
777 and the next time you bring up the command window it's empty. If you
778 press the @code{Esc} key, the window goes away without invoking
779 anything, and the next time you bring up the command window it's
780 empty. If you change focus away from the command window (i.e. click
781 on some other window), the command window goes away but the next time
782 you bring it up it resumes entering the command you were entering
788 Command (int argc
, char **argv
, Coord x
, Coord y
)
790 XtManageChild (m_cmd_label
);
791 XtManageChild (m_cmd
);
792 XmProcessTraversal (m_cmd
, XmTRAVERSE_CURRENT
);
796 static const char benchmark_syntax
[] =
799 static const char benchmark_help
[] =
800 "Benchmark the GUI speed.";
802 /* %start-doc actions Benchmark
804 This action is used to speed-test the Lesstif graphics subsystem. It
805 redraws the current screen as many times as possible in ten seconds.
806 It reports the amount of time needed to draw the screen once.
811 Benchmark (int argc
, char **argv
, Coord x
, Coord y
)
818 save_main
= main_pixmap
;
819 main_pixmap
= window
;
823 region
.X2
= PCB
->MaxWidth
;
824 region
.Y2
= PCB
->MaxHeight
;
831 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, view_width
, view_height
);
832 hid_expose_callback (&lesstif_hid
, ®ion
, 0);
837 while (end
- start
< 10);
839 printf ("%g redraws per second\n", i
/ 10.0);
841 main_pixmap
= save_main
;
846 Center(int argc
, char **argv
, Coord x
, Coord y
)
848 x
= GridFit (x
, PCB
->Grid
, PCB
->GridOffsetX
);
849 y
= GridFit (y
, PCB
->Grid
, PCB
->GridOffsetY
);
850 view_left_x
= x
- (view_width
* view_zoom
) / 2;
851 view_top_y
= y
- (view_height
* view_zoom
) / 2;
852 lesstif_pan_fixup ();
853 /* Move the pointer to the center of the window, but only if it's
854 currently within the window already. Watch out for edges,
856 XWarpPointer (display
, window
, window
, 0, 0, view_width
, view_height
,
861 static const char cursor_syntax
[] =
862 "Cursor(Type,DeltaUp,DeltaRight,Units)";
864 static const char cursor_help
[] =
867 /* %start-doc actions Cursor
869 This action moves the mouse cursor. Unlike other actions which take
870 coordinates, this action's coordinates are always relative to the
871 user's view of the board. Thus, a positive @var{DeltaUp} may move the
872 cursor towards the board origin if the board is inverted.
874 Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the
875 viewport to move such that the crosshair is under the mouse cursor.
876 @samp{Warp} causes the mouse cursor to move to be above the crosshair.
878 @var{Units} can be one of the following:
884 The cursor is moved by that amount, in board units.
887 The cursor is moved by that many grid points.
890 The values are percentages of the viewport's view. Thus, a pan of
891 @samp{100} would scroll the viewport by exactly the width of the
895 The values are percentages of the board size. Thus, a move of
896 @samp{50,50} moves you halfway across the board.
903 CursorAction(int argc
, char **argv
, Coord x
, Coord y
)
905 UnitList extra_units_x
= {
906 { "grid", PCB
->Grid
, 0 },
907 { "view", Pz(view_width
), UNIT_PERCENT
},
908 { "board", PCB
->MaxWidth
, UNIT_PERCENT
},
911 UnitList extra_units_y
= {
912 { "grid", PCB
->Grid
, 0 },
913 { "view", Pz(view_height
), UNIT_PERCENT
},
914 { "board", PCB
->MaxHeight
, UNIT_PERCENT
},
917 int pan_warp
= HID_SC_DO_NOTHING
;
923 if (strcasecmp (argv
[0], "pan") == 0)
924 pan_warp
= HID_SC_PAN_VIEWPORT
;
925 else if (strcasecmp (argv
[0], "warp") == 0)
926 pan_warp
= HID_SC_WARP_POINTER
;
930 dx
= GetValueEx (argv
[1], argv
[3], NULL
, extra_units_x
, "mil");
933 dy
= GetValueEx (argv
[2], argv
[3], NULL
, extra_units_y
, "mil");
937 EventMoveCrosshair (Crosshair
.X
+ dx
, Crosshair
.Y
+ dy
);
938 gui
->set_crosshair (Crosshair
.X
, Crosshair
.Y
, pan_warp
);
943 HID_Action lesstif_main_action_list
[] = {
944 {"PCBChanged", 0, PCBChanged
,
945 pcbchanged_help
, pcbchanged_syntax
},
946 {"SetUnits", 0, SetUnits
,
947 setunits_help
, setunits_syntax
},
948 {"Zoom", "Click on a place to zoom in", ZoomAction
,
949 zoom_help
, zoom_syntax
},
950 {"Pan", "Click on a place to pan", PanAction
,
951 zoom_help
, zoom_syntax
},
952 {"SwapSides", 0, SwapSides
,
953 swapsides_help
, swapsides_syntax
},
954 {"Command", 0, Command
,
955 command_help
, command_syntax
},
956 {"Benchmark", 0, Benchmark
,
957 benchmark_help
, benchmark_syntax
},
958 {"PointCursor", 0, PointCursor
},
959 {"Center", "Click on a location to center", Center
},
961 {"Cursor", 0, CursorAction
,
962 cursor_help
, cursor_syntax
},
965 REGISTER_ACTIONS (lesstif_main_action_list
)
968 /* ----------------------------------------------------------------------
969 * redraws the background image
972 static int bg_w
, bg_h
, bgi_w
, bgi_h
;
973 static Pixel
**bg
= 0;
974 static XImage
*bgi
= 0;
979 } pixel_type
= PT_unknown
;
982 LoadBackgroundFile (FILE *f
, char *filename
)
984 XVisualInfo vinfot
, *vinfo
;
988 int p
[3], rows
, cols
, maxval
;
992 printf("bgimage: %s signature not P6\n", filename
);
997 printf("bgimage: %s signature not P6\n", filename
);
1007 while (!feof(f
) && b
!= '\n')
1009 } while (!isdigit(b
));
1011 while (isdigit(b
= fgetc(f
)))
1012 p
[i
] = p
[i
]*10 + b
- '0';
1019 bg
= (Pixel
**) malloc (rows
* sizeof (Pixel
*));
1022 printf("Out of memory loading %s\n", filename
);
1025 for (i
=0; i
<rows
; i
++)
1027 bg
[i
] = (Pixel
*) malloc (cols
* sizeof (Pixel
));
1030 printf("Out of memory loading %s\n", filename
);
1039 vis
= DefaultVisual (display
, DefaultScreen(display
));
1041 vinfot
.visualid
= XVisualIDFromVisual(vis
);
1042 vinfo
= XGetVisualInfo (display
, VisualIDMask
, &vinfot
, &nret
);
1045 /* If you want to support more visuals below, you'll probably need
1047 printf("vinfo: rm %04x gm %04x bm %04x depth %d class %d\n",
1048 vinfo
->red_mask
, vinfo
->green_mask
, vinfo
->blue_mask
,
1049 vinfo
->depth
, vinfo
->class);
1052 #if !defined(__cplusplus)
1053 #define c_class class
1056 if (vinfo
->c_class
== TrueColor
1057 && vinfo
->depth
== 16
1058 && vinfo
->red_mask
== 0xf800
1059 && vinfo
->green_mask
== 0x07e0
1060 && vinfo
->blue_mask
== 0x001f)
1061 pixel_type
= PT_RGB565
;
1063 if (vinfo
->c_class
== TrueColor
1064 && vinfo
->depth
== 24
1065 && vinfo
->red_mask
== 0xff0000
1066 && vinfo
->green_mask
== 0x00ff00
1067 && vinfo
->blue_mask
== 0x0000ff)
1068 pixel_type
= PT_RGB888
;
1070 for (r
=0; r
<rows
; r
++)
1072 for (c
=0; c
<cols
; c
++)
1075 unsigned int pr
= (unsigned)fgetc(f
);
1076 unsigned int pg
= (unsigned)fgetc(f
);
1077 unsigned int pb
= (unsigned)fgetc(f
);
1082 pix
.red
= pr
* 65535 / maxval
;
1083 pix
.green
= pg
* 65535 / maxval
;
1084 pix
.blue
= pb
* 65535 / maxval
;
1085 pix
.flags
= DoRed
| DoGreen
| DoBlue
;
1086 XAllocColor (display
, colormap
, &pix
);
1087 bg
[r
][c
] = pix
.pixel
;
1090 bg
[r
][c
] = (pr
>>3)<<11 | (pg
>>2)<<5 | (pb
>>3);
1093 bg
[r
][c
] = (pr
<< 16) | (pg
<< 8) | (pb
);
1101 LoadBackgroundImage (char *filename
)
1103 FILE *f
= fopen(filename
, "rb");
1106 if (NSTRCMP (filename
, "pcb-background.ppm"))
1110 LoadBackgroundFile (f
, filename
);
1115 DrawBackgroundImage ()
1118 double xscale
, yscale
;
1119 int pcbwidth
= PCB
->MaxWidth
/ view_zoom
;
1120 int pcbheight
= PCB
->MaxHeight
/ view_zoom
;
1125 if (!bgi
|| view_width
!= bgi_w
|| view_height
!= bgi_h
)
1128 XDestroyImage (bgi
);
1129 /* Cheat - get the image, which sets up the format too. */
1130 bgi
= XGetImage (XtDisplay(work_area
),
1132 0, 0, view_width
, view_height
,
1135 bgi_h
= view_height
;
1138 w
= MIN (view_width
, pcbwidth
);
1139 h
= MIN (view_height
, pcbheight
);
1141 xscale
= (double)bg_w
/ PCB
->MaxWidth
;
1142 yscale
= (double)bg_h
/ PCB
->MaxHeight
;
1147 int ir
= pr
* yscale
;
1151 int ic
= pc
* xscale
;
1152 XPutPixel (bgi
, x
, y
, bg
[ir
][ic
]);
1155 XPutImage(display
, main_pixmap
, bg_gc
,
1159 /* ---------------------------------------------------------------------- */
1161 static HID_Attribute
*
1162 lesstif_get_export_options (int *n
)
1164 *n
= sizeof (lesstif_attribute_list
) / sizeof (HID_Attribute
);
1165 return lesstif_attribute_list
;
1169 set_scroll (Widget s
, int pos
, int view
, int pcb
)
1171 int sz
= view
* view_zoom
;
1175 stdarg (XmNvalue
, pos
);
1176 stdarg (XmNsliderSize
, sz
);
1177 stdarg (XmNincrement
, view_zoom
);
1178 stdarg (XmNpageIncrement
, sz
);
1179 stdarg (XmNmaximum
, pcb
);
1180 XtSetValues (s
, args
, n
);
1184 lesstif_pan_fixup ()
1187 if (view_left_x
> PCB
->MaxWidth
- (view_width
* view_zoom
))
1188 view_left_x
= PCB
->MaxWidth
- (view_width
* view_zoom
);
1189 if (view_top_y
> PCB
->MaxHeight
- (view_height
* view_zoom
))
1190 view_top_y
= PCB
->MaxHeight
- (view_height
* view_zoom
);
1191 if (view_left_x
< 0)
1195 if (view_width
* view_zoom
> PCB
->MaxWidth
1196 && view_height
* view_zoom
> PCB
->MaxHeight
)
1203 set_scroll (hscroll
, view_left_x
, view_width
, PCB
->MaxWidth
);
1204 set_scroll (vscroll
, view_top_y
, view_height
, PCB
->MaxHeight
);
1206 lesstif_invalidate_all ();
1212 double new_zoom
= PCB
->MaxWidth
/ view_width
;
1213 if (new_zoom
< PCB
->MaxHeight
/ view_height
)
1214 new_zoom
= PCB
->MaxHeight
/ view_height
;
1216 view_left_x
= -(view_width
* new_zoom
- PCB
->MaxWidth
) / 2;
1217 view_top_y
= -(view_height
* new_zoom
- PCB
->MaxHeight
) / 2;
1218 view_zoom
= new_zoom
;
1219 pixel_slop
= view_zoom
;
1220 lesstif_pan_fixup ();
1224 zoom_to (double new_zoom
, int x
, int y
)
1226 double max_zoom
, xfrac
, yfrac
;
1229 xfrac
= (double) x
/ (double) view_width
;
1230 yfrac
= (double) y
/ (double) view_height
;
1237 max_zoom
= PCB
->MaxWidth
/ view_width
;
1238 if (max_zoom
< PCB
->MaxHeight
/ view_height
)
1239 max_zoom
= PCB
->MaxHeight
/ view_height
;
1241 max_zoom
*= MAX_ZOOM_SCALE
;
1245 if (new_zoom
> max_zoom
)
1246 new_zoom
= max_zoom
;
1248 cx
= view_left_x
+ view_width
* xfrac
* view_zoom
;
1249 cy
= view_top_y
+ view_height
* yfrac
* view_zoom
;
1251 if (view_zoom
!= new_zoom
)
1253 view_zoom
= new_zoom
;
1254 pixel_slop
= view_zoom
;
1256 view_left_x
= cx
- view_width
* xfrac
* view_zoom
;
1257 view_top_y
= cy
- view_height
* yfrac
* view_zoom
;
1259 lesstif_pan_fixup ();
1263 zoom_toggle(int x
, int y
)
1267 tmp
= prev_view_zoom
;
1268 prev_view_zoom
= view_zoom
;
1273 zoom_by (double factor
, int x
, int y
)
1275 zoom_to (view_zoom
* factor
, x
, y
);
1278 static int panning
= 0;
1279 static int shift_pressed
;
1280 static int ctrl_pressed
;
1281 static int alt_pressed
;
1283 /* X and Y are in screen coordinates. */
1285 Pan (int mode
, int x
, int y
)
1288 static int opx
, opy
;
1291 /* This is for ctrl-pan, where the viewport's position is directly
1292 proportional to the cursor position in the window (like the Xaw
1296 opx
= x
* PCB
->MaxWidth
/ view_width
;
1297 opy
= y
* PCB
->MaxHeight
/ view_height
;
1299 opx
= PCB
->MaxWidth
- opx
;
1301 opy
= PCB
->MaxHeight
- opy
;
1302 view_left_x
= opx
- view_width
/ 2 * view_zoom
;
1303 view_top_y
= opy
- view_height
/ 2 * view_zoom
;
1304 lesstif_pan_fixup ();
1306 /* This is the start of a regular pan. On the first click, we
1307 remember the coordinates where we "grabbed" the screen. */
1315 /* continued drag, we calculate how far we've moved the cursor and
1316 set the position accordingly. */
1320 view_left_x
= opx
+ (x
- ox
) * view_zoom
;
1322 view_left_x
= opx
- (x
- ox
) * view_zoom
;
1324 view_top_y
= opy
+ (y
- oy
) * view_zoom
;
1326 view_top_y
= opy
- (y
- oy
) * view_zoom
;
1327 lesstif_pan_fixup ();
1332 mod_changed (XKeyEvent
* e
, int set
)
1334 switch (XKeycodeToKeysym (display
, e
->keycode
, 0))
1338 shift_pressed
= set
;
1345 case XK_Mode_switch
:
1353 // to include the Apple keyboard left and right command keys use XK_Meta_L and XK_Meta_R respectivly.
1357 notify_crosshair_change (false);
1359 Pan (2, e
->x
, e
->y
);
1360 EventMoveCrosshair (Px (e
->x
), Py (e
->y
));
1361 AdjustAttachedObjects ();
1362 notify_crosshair_change (true);
1367 work_area_input (Widget w
, XtPointer v
, XEvent
* e
, Boolean
* ctd
)
1369 static int pressed_button
= 0;
1375 mod_changed (&(e
->xkey
), 1);
1376 if (lesstif_key_event (&(e
->xkey
)))
1381 mod_changed (&(e
->xkey
), 0);
1389 /*printf("click %d\n", e->xbutton.button); */
1390 if (lesstif_button_event (w
, e
))
1393 notify_crosshair_change (false);
1394 pressed_button
= e
->xbutton
.button
;
1395 mods
= ((e
->xbutton
.state
& ShiftMask
) ? M_Shift
: 0)
1396 + ((e
->xbutton
.state
& ControlMask
) ? M_Ctrl
: 0)
1398 + ((e
->xbutton
.state
& (1<<13)) ? M_Alt
: 0);
1400 + ((e
->xbutton
.state
& Mod1Mask
) ? M_Alt
: 0);
1402 do_mouse_action(e
->xbutton
.button
, mods
);
1403 notify_crosshair_change (true);
1410 if (e
->xbutton
.button
!= pressed_button
)
1412 lesstif_button_event (w
, e
);
1413 notify_crosshair_change (false);
1415 mods
= ((e
->xbutton
.state
& ShiftMask
) ? M_Shift
: 0)
1416 + ((e
->xbutton
.state
& ControlMask
) ? M_Ctrl
: 0)
1418 + ((e
->xbutton
.state
& (1<<13)) ? M_Alt
: 0)
1420 + ((e
->xbutton
.state
& Mod1Mask
) ? M_Alt
: 0)
1423 do_mouse_action (e
->xbutton
.button
, mods
);
1424 notify_crosshair_change (true);
1431 unsigned int keys_buttons
;
1432 int root_x
, root_y
, pos_x
, pos_y
;
1433 while (XCheckMaskEvent (display
, PointerMotionMask
, e
));
1434 XQueryPointer (display
, e
->xmotion
.window
, &root
, &child
,
1435 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
1436 shift_pressed
= (keys_buttons
& ShiftMask
);
1437 ctrl_pressed
= (keys_buttons
& ControlMask
);
1439 alt_pressed
= (keys_buttons
& (1<<13));
1441 alt_pressed
= (keys_buttons
& Mod1Mask
);
1443 /*pcb_printf("m %#mS %#mS\n", Px(e->xmotion.x), Py(e->xmotion.y)); */
1444 crosshair_in_window
= 1;
1447 Pan (2, pos_x
, pos_y
);
1448 EventMoveCrosshair (Px (pos_x
), Py (pos_y
));
1454 crosshair_in_window
= 0;
1455 ShowCrosshair (false);
1460 crosshair_in_window
= 1;
1462 EventMoveCrosshair (Px (e
->xcrossing
.x
), Py (e
->xcrossing
.y
));
1463 ShowCrosshair (true);
1469 printf ("work_area: unknown event %d\n", e
->type
);
1475 draw_right_cross (GC xor_gc
, int x
, int y
,
1476 int view_width
, int view_height
)
1478 XDrawLine (display
, window
, xor_gc
, 0, y
, view_width
, y
);
1479 XDrawLine (display
, window
, xor_gc
, x
, 0, x
, view_height
);
1483 draw_slanted_cross (GC xor_gc
, int x
, int y
,
1484 int view_width
, int view_height
)
1488 x0
= x
+ (view_height
- y
);
1489 x0
= MAX(0, MIN (x0
, view_width
));
1491 x1
= MAX(0, MIN (x1
, view_width
));
1492 y0
= y
+ (view_width
- x
);
1493 y0
= MAX(0, MIN (y0
, view_height
));
1495 y1
= MAX(0, MIN (y1
, view_height
));
1496 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1497 x0
= x
- (view_height
- y
);
1498 x0
= MAX(0, MIN (x0
, view_width
));
1500 x1
= MAX(0, MIN (x1
, view_width
));
1502 y0
= MAX(0, MIN (y0
, view_height
));
1503 y1
= y
- (view_width
- x
);
1504 y1
= MAX(0, MIN (y1
, view_height
));
1505 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1509 draw_dozen_cross (GC xor_gc
, int x
, int y
,
1510 int view_width
, int view_height
)
1513 double tan60
= sqrt (3);
1515 x0
= x
+ (view_height
- y
) / tan60
;
1516 x0
= MAX(0, MIN (x0
, view_width
));
1518 x1
= MAX(0, MIN (x1
, view_width
));
1519 y0
= y
+ (view_width
- x
) * tan60
;
1520 y0
= MAX(0, MIN (y0
, view_height
));
1522 y1
= MAX(0, MIN (y1
, view_height
));
1523 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1525 x0
= x
+ (view_height
- y
) * tan60
;
1526 x0
= MAX(0, MIN (x0
, view_width
));
1528 x1
= MAX(0, MIN (x1
, view_width
));
1529 y0
= y
+ (view_width
- x
) / tan60
;
1530 y0
= MAX(0, MIN (y0
, view_height
));
1532 y1
= MAX(0, MIN (y1
, view_height
));
1533 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1535 x0
= x
- (view_height
- y
) / tan60
;
1536 x0
= MAX(0, MIN (x0
, view_width
));
1538 x1
= MAX(0, MIN (x1
, view_width
));
1540 y0
= MAX(0, MIN (y0
, view_height
));
1541 y1
= y
- (view_width
- x
) * tan60
;
1542 y1
= MAX(0, MIN (y1
, view_height
));
1543 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1545 x0
= x
- (view_height
- y
) * tan60
;
1546 x0
= MAX(0, MIN (x0
, view_width
));
1548 x1
= MAX(0, MIN (x1
, view_width
));
1550 y0
= MAX(0, MIN (y0
, view_height
));
1551 y1
= y
- (view_width
- x
) / tan60
;
1552 y1
= MAX(0, MIN (y1
, view_height
));
1553 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1557 draw_crosshair (GC xor_gc
, int x
, int y
,
1558 int view_width
, int view_height
)
1560 draw_right_cross (xor_gc
, x
, y
, view_width
, view_height
);
1561 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
1562 draw_slanted_cross (xor_gc
, x
, y
, view_width
, view_height
);
1563 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
1564 draw_dozen_cross (xor_gc
, x
, y
, view_width
, view_height
);
1567 lesstif_show_crosshair (int show
)
1569 static int showing
= 0;
1571 static GC xor_gc
= 0;
1572 Pixel crosshair_color
;
1574 if (!crosshair_in_window
|| !window
)
1578 crosshair_color
= lesstif_parse_color (Settings
.CrosshairColor
) ^ bgcolor
;
1579 xor_gc
= XCreateGC (display
, window
, 0, 0);
1580 XSetFunction (display
, xor_gc
, GXxor
);
1581 XSetForeground (display
, xor_gc
, crosshair_color
);
1583 if (show
== showing
)
1587 sx
= Vx (crosshair_x
);
1588 sy
= Vy (crosshair_y
);
1592 draw_crosshair (xor_gc
, sx
, sy
, view_width
, view_height
);
1597 work_area_expose (Widget work_area
, void *me
,
1598 XmDrawingAreaCallbackStruct
* cbs
)
1603 e
= &(cbs
->event
->xexpose
);
1604 XSetFunction (display
, my_gc
, GXcopy
);
1605 XCopyArea (display
, main_pixmap
, window
, my_gc
,
1606 e
->x
, e
->y
, e
->width
, e
->height
, e
->x
, e
->y
);
1611 scroll_callback (Widget scroll
, int *view_dim
,
1612 XmScrollBarCallbackStruct
* cbs
)
1614 *view_dim
= cbs
->value
;
1615 lesstif_invalidate_all ();
1619 work_area_make_pixmaps (Dimension width
, Dimension height
)
1622 XFreePixmap (display
, main_pixmap
);
1624 XCreatePixmap (display
, window
, width
, height
,
1625 XDefaultDepth (display
, screen
));
1628 XFreePixmap (display
, mask_pixmap
);
1630 XCreatePixmap (display
, window
, width
, height
,
1631 XDefaultDepth (display
, screen
));
1635 XRenderFreePicture (display
, main_picture
);
1640 XRenderFreePicture (display
, mask_picture
);
1645 main_picture
= XRenderCreatePicture (display
, main_pixmap
,
1646 XRenderFindVisualFormat(display
,
1647 DefaultVisual(display
, screen
)), 0, 0);
1648 mask_picture
= XRenderCreatePicture (display
, mask_pixmap
,
1649 XRenderFindVisualFormat(display
,
1650 DefaultVisual(display
, screen
)), 0, 0);
1651 if (!main_picture
|| !mask_picture
)
1654 #endif /* HAVE_XRENDER */
1657 XFreePixmap (display
, mask_bitmap
);
1658 mask_bitmap
= XCreatePixmap (display
, window
, width
, height
, 1);
1660 pixmap
= use_mask
? main_pixmap
: mask_pixmap
;
1666 work_area_resize (Widget work_area
, void *me
,
1667 XmDrawingAreaCallbackStruct
* cbs
)
1670 Dimension width
, height
;
1675 stdarg (XtNwidth
, &width
);
1676 stdarg (XtNheight
, &height
);
1677 stdarg (XmNbackground
, &bgcolor
);
1678 XtGetValues (work_area
, args
, n
);
1680 view_height
= height
;
1682 color
.pixel
= bgcolor
;
1683 XQueryColor (display
, colormap
, &color
);
1685 bggreen
= color
.green
;
1686 bgblue
= color
.blue
;
1691 work_area_make_pixmaps (view_width
, view_height
);
1697 work_area_first_expose (Widget work_area
, void *me
,
1698 XmDrawingAreaCallbackStruct
* cbs
)
1701 Dimension width
, height
;
1702 static char dashes
[] = { 4, 4 };
1704 window
= XtWindow (work_area
);
1705 my_gc
= XCreateGC (display
, window
, 0, 0);
1707 arc1_gc
= XCreateGC (display
, window
, 0, 0);
1708 c
= lesstif_parse_color ("#804000");
1709 XSetForeground (display
, arc1_gc
, c
);
1710 arc2_gc
= XCreateGC (display
, window
, 0, 0);
1711 c
= lesstif_parse_color ("#004080");
1712 XSetForeground (display
, arc2_gc
, c
);
1713 XSetLineAttributes (display
, arc1_gc
, 1, LineOnOffDash
, 0, 0);
1714 XSetLineAttributes (display
, arc2_gc
, 1, LineOnOffDash
, 0, 0);
1715 XSetDashes (display
, arc1_gc
, 0, dashes
, 2);
1716 XSetDashes (display
, arc2_gc
, 0, dashes
, 2);
1719 stdarg (XtNwidth
, &width
);
1720 stdarg (XtNheight
, &height
);
1721 stdarg (XmNbackground
, &bgcolor
);
1722 XtGetValues (work_area
, args
, n
);
1724 view_height
= height
;
1726 offlimit_color
= lesstif_parse_color (Settings
.OffLimitColor
);
1727 grid_color
= lesstif_parse_color (Settings
.GridColor
);
1729 bg_gc
= XCreateGC (display
, window
, 0, 0);
1730 XSetForeground (display
, bg_gc
, bgcolor
);
1732 work_area_make_pixmaps (width
, height
);
1737 XRenderPictureAttributes pa
;
1738 XRenderColor a
= {0, 0, 0, 0x8000};
1740 pale_pixmap
= XCreatePixmap (display
, window
, 1, 1, 8);
1742 pale_picture
= XRenderCreatePicture (display
, pale_pixmap
,
1743 XRenderFindStandardFormat(display
, PictStandardA8
),
1746 XRenderFillRectangle(display
, PictOpSrc
, pale_picture
, &a
, 0, 0, 1, 1);
1750 #endif /* HAVE_XRENDER */
1752 clip_gc
= XCreateGC (display
, window
, 0, 0);
1753 bset_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1754 XSetForeground (display
, bset_gc
, 1);
1755 bclear_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1756 XSetForeground (display
, bclear_gc
, 0);
1758 XtRemoveCallback (work_area
, XmNexposeCallback
,
1759 (XtCallbackProc
) work_area_first_expose
, 0);
1760 XtAddCallback (work_area
, XmNexposeCallback
,
1761 (XtCallbackProc
) work_area_expose
, 0);
1762 lesstif_invalidate_all ();
1766 make_message (char *name
, Widget left
, int resizeable
)
1772 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1773 stdarg (XmNleftWidget
, XtParent(left
));
1777 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1779 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1780 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1781 stdarg (XmNshadowType
, XmSHADOW_IN
);
1782 stdarg (XmNshadowThickness
, 1);
1783 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1784 stdarg (XmNmarginWidth
, 4);
1785 stdarg (XmNmarginHeight
, 1);
1787 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
1788 f
= XmCreateForm (messages
, name
, args
, n
);
1791 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1792 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1793 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1794 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1795 w
= XmCreateLabel (f
, name
, args
, n
);
1801 lesstif_do_export (HID_Attr_Val
* options
)
1803 Dimension width
, height
;
1805 Widget work_area_frame
;
1807 crosshair_gc
= lesstif_make_gc ();
1810 stdarg (XtNwidth
, &width
);
1811 stdarg (XtNheight
, &height
);
1812 XtGetValues (appwidget
, args
, n
);
1816 if (width
> XDisplayWidth (display
, screen
))
1817 width
= XDisplayWidth (display
, screen
);
1820 if (height
> XDisplayHeight (display
, screen
))
1821 height
= XDisplayHeight (display
, screen
);
1824 stdarg (XmNwidth
, width
);
1825 stdarg (XmNheight
, height
);
1826 XtSetValues (appwidget
, args
, n
);
1828 stdarg (XmNspacing
, 0);
1829 mainwind
= XmCreateMainWindow (appwidget
, "mainWind", args
, n
);
1830 XtManageChild (mainwind
);
1833 stdarg (XmNmarginWidth
, 0);
1834 stdarg (XmNmarginHeight
, 0);
1835 menu
= lesstif_menu (mainwind
, "menubar", args
, n
);
1836 XtManageChild (menu
);
1839 stdarg (XmNshadowType
, XmSHADOW_IN
);
1841 XmCreateFrame (mainwind
, "work_area_frame", args
, n
);
1842 XtManageChild (work_area_frame
);
1845 do_color (Settings
.BackgroundColor
, XmNbackground
);
1846 work_area
= XmCreateDrawingArea (work_area_frame
, "work_area", args
, n
);
1847 XtManageChild (work_area
);
1848 XtAddCallback (work_area
, XmNexposeCallback
,
1849 (XtCallbackProc
) work_area_first_expose
, 0);
1850 XtAddCallback (work_area
, XmNresizeCallback
,
1851 (XtCallbackProc
) work_area_resize
, 0);
1852 /* A regular callback won't work here, because lesstif swallows any
1853 Ctrl<Button>1 event. */
1854 XtAddEventHandler (work_area
,
1855 ButtonPressMask
| ButtonReleaseMask
1856 | PointerMotionMask
| PointerMotionHintMask
1857 | KeyPressMask
| KeyReleaseMask
1858 | EnterWindowMask
| LeaveWindowMask
,
1859 0, work_area_input
, 0);
1862 stdarg (XmNorientation
, XmVERTICAL
);
1863 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
1864 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
1865 vscroll
= XmCreateScrollBar (mainwind
, "vscroll", args
, n
);
1866 XtAddCallback (vscroll
, XmNvalueChangedCallback
,
1867 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_top_y
);
1868 XtAddCallback (vscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1869 (XtPointer
) & view_top_y
);
1870 XtManageChild (vscroll
);
1873 stdarg (XmNorientation
, XmHORIZONTAL
);
1874 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
1875 hscroll
= XmCreateScrollBar (mainwind
, "hscroll", args
, n
);
1876 XtAddCallback (hscroll
, XmNvalueChangedCallback
,
1877 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_left_x
);
1878 XtAddCallback (hscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1879 (XtPointer
) & view_left_x
);
1880 XtManageChild (hscroll
);
1883 stdarg (XmNresize
, True
);
1884 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
1885 messages
= XmCreateForm (mainwind
, "messages", args
, n
);
1886 XtManageChild (messages
);
1889 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1890 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1891 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1892 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1893 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1894 stdarg (XmNshadowThickness
, 2);
1895 m_click
= XmCreateLabel (messages
, "click", args
, n
);
1898 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1899 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1900 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1901 stdarg (XmNlabelString
, XmStringCreatePCB ("Command: "));
1902 m_cmd_label
= XmCreateLabel (messages
, "command", args
, n
);
1905 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1906 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1907 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1908 stdarg (XmNleftWidget
, m_cmd_label
);
1909 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1910 stdarg (XmNshadowThickness
, 1);
1911 stdarg (XmNhighlightThickness
, 0);
1912 stdarg (XmNmarginWidth
, 2);
1913 stdarg (XmNmarginHeight
, 2);
1914 m_cmd
= XmCreateTextField (messages
, "command", args
, n
);
1915 XtAddCallback (m_cmd
, XmNactivateCallback
,
1916 (XtCallbackProc
) command_callback
, 0);
1917 XtAddCallback (m_cmd
, XmNlosingFocusCallback
,
1918 (XtCallbackProc
) command_callback
, 0);
1919 XtAddEventHandler (m_cmd
, KeyPressMask
, 0, command_event_handler
, 0);
1921 m_mark
= make_message ("m_mark", 0, 0);
1922 m_crosshair
= make_message ("m_crosshair", m_mark
, 0);
1923 m_grid
= make_message ("m_grid", m_crosshair
, 1);
1924 m_zoom
= make_message ("m_zoom", m_grid
, 1);
1925 lesstif_m_layer
= make_message ("m_layer", m_zoom
, 0);
1926 m_mode
= make_message ("m_mode", lesstif_m_layer
, 1);
1927 m_rats
= make_message ("m_rats", m_mode
, 1);
1928 m_status
= make_message ("m_status", m_mode
, 1);
1930 XtUnmanageChild (XtParent (m_mark
));
1931 XtUnmanageChild (XtParent (m_rats
));
1934 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1935 XtSetValues (XtParent (m_status
), args
, n
);
1937 /* We'll use this later. */
1939 stdarg (XmNleftWidget
, XtParent (m_mark
));
1940 XtSetValues (XtParent (m_crosshair
), args
, n
);
1943 stdarg (XmNmessageWindow
, messages
);
1944 XtSetValues (mainwind
, args
, n
);
1946 if (background_image_file
)
1947 LoadBackgroundImage (background_image_file
);
1949 XtRealizeWidget (appwidget
);
1954 XtAppNextEvent (app_context
, &e
);
1955 XtDispatchEvent (&e
);
1958 PCBChanged (0, 0, 0, 0);
1960 XtAppMainLoop (app_context
);
1964 XrmOptionDescRec lesstif_options
[] = {
1967 XtResource lesstif_resources
[] = {
1980 pcb_cvt_string_to_double (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
1981 XrmValue
* from
, XrmValue
* to
, XtPointer
* data
)
1984 rv
= strtod ((char *) from
->addr
, 0);
1986 *(double *) to
->addr
= rv
;
1988 to
->addr
= (XPointer
) & rv
;
1989 to
->size
= sizeof (rv
);
1994 pcb_cvt_string_to_coord (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
1995 XrmValue
* from
, XrmValue
* to
, XtPointer
*data
)
1998 rv
= GetValue ((char *) from
->addr
, NULL
, NULL
);
2000 *(Coord
*) to
->addr
= rv
;
2002 to
->addr
= (XPointer
) &rv
;
2003 to
->size
= sizeof (rv
);
2008 mainwind_delete_cb ()
2010 hid_action ("Quit");
2014 lesstif_listener_cb (XtPointer client_data
, int *fid
, XtInputId
*id
)
2019 if ((nbytes
= read (*fid
, buf
, BUFSIZ
)) == -1)
2020 perror ("lesstif_listener_cb");
2025 hid_parse_actions (buf
);
2030 lesstif_parse_arguments (int *argc
, char ***argv
)
2034 int acount
= 0, amax
;
2035 int rcount
= 0, rmax
;
2037 XrmOptionDescRec
*new_options
;
2038 XtResource
*new_resources
;
2039 val_union
*new_values
;
2040 int render_event
, render_error
;
2042 XtSetTypeConverter (XtRString
,
2044 pcb_cvt_string_to_double
, NULL
, 0, XtCacheAll
, NULL
);
2045 XtSetTypeConverter (XtRString
,
2047 pcb_cvt_string_to_coord
, NULL
, 0, XtCacheAll
, NULL
);
2050 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2051 for (i
= 0; i
< ha
->n
; i
++)
2053 HID_Attribute
*a
= ha
->attributes
+ i
;
2071 amax
= acount
+ XtNumber (lesstif_options
);
2076 new_options
= (XrmOptionDescRec
*) malloc ((amax
+ 1) * sizeof (XrmOptionDescRec
));
2079 memcpy (new_options
+ acount
, lesstif_options
, sizeof (lesstif_options
));
2084 rmax
= rcount
+ XtNumber (lesstif_resources
);
2089 new_resources
= (XtResource
*) malloc ((rmax
+ 1) * sizeof (XtResource
));
2090 new_values
= (val_union
*) malloc ((rmax
+ 1) * sizeof (val_union
));
2092 memcpy (new_resources
+ acount
, lesstif_resources
,
2093 sizeof (lesstif_resources
));
2097 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2098 for (i
= 0; i
< ha
->n
; i
++)
2100 HID_Attribute
*a
= ha
->attributes
+ i
;
2101 XrmOptionDescRec
*o
= new_options
+ acount
;
2102 char *tmpopt
, *tmpres
;
2103 XtResource
*r
= new_resources
+ rcount
;
2105 tmpopt
= (char *) malloc (strlen (a
->name
) + 3);
2106 tmpopt
[0] = tmpopt
[1] = '-';
2107 strcpy (tmpopt
+ 2, a
->name
);
2110 tmpres
= (char *) malloc (strlen (a
->name
) + 2);
2112 strcpy (tmpres
+ 1, a
->name
);
2113 o
->specifier
= tmpres
;
2122 o
->argKind
= XrmoptionSepArg
;
2127 o
->argKind
= XrmoptionNoArg
;
2135 r
->resource_name
= a
->name
;
2136 r
->resource_class
= a
->name
;
2137 r
->resource_offset
= sizeof (val_union
) * rcount
;
2142 r
->resource_type
= XtRInt
;
2143 r
->default_type
= XtRInt
;
2144 r
->resource_size
= sizeof (int);
2145 r
->default_addr
= &(a
->default_val
.int_value
);
2149 r
->resource_type
= XtRPCBCoord
;
2150 r
->default_type
= XtRPCBCoord
;
2151 r
->resource_size
= sizeof (Coord
);
2152 r
->default_addr
= &(a
->default_val
.coord_value
);
2156 r
->resource_type
= XtRDouble
;
2157 r
->default_type
= XtRDouble
;
2158 r
->resource_size
= sizeof (double);
2159 r
->default_addr
= &(a
->default_val
.real_value
);
2164 r
->resource_type
= XtRString
;
2165 r
->default_type
= XtRString
;
2166 r
->resource_size
= sizeof (char *);
2167 r
->default_addr
= (char *) a
->default_val
.str_value
;
2171 r
->resource_type
= XtRBoolean
;
2172 r
->default_type
= XtRInt
;
2173 r
->resource_size
= sizeof (int);
2174 r
->default_addr
= &(a
->default_val
.int_value
);
2182 for (i
= 0; i
< XtNumber (lesstif_resources
); i
++)
2184 XtResource
*r
= new_resources
+ rcount
;
2185 r
->resource_offset
= sizeof (val_union
) * rcount
;
2191 stdarg (XmNdeleteResponse
, XmDO_NOTHING
);
2193 appwidget
= XtAppInitialize (&app_context
,
2195 new_options
, amax
, argc
, *argv
, 0, args
, n
);
2197 display
= XtDisplay (appwidget
);
2198 screen_s
= XtScreen (appwidget
);
2199 screen
= XScreenNumberOfScreen (screen_s
);
2200 colormap
= XDefaultColormap (display
, screen
);
2202 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
2203 XmAddWMProtocolCallback (appwidget
, close_atom
,
2204 (XtCallbackProc
) mainwind_delete_cb
, 0);
2206 /* XSynchronize(display, True); */
2208 XtGetApplicationResources (appwidget
, new_values
, new_resources
,
2212 use_xrender
= XRenderQueryExtension (display
, &render_event
, &render_error
) &&
2213 XRenderFindVisualFormat (display
, DefaultVisual(display
, screen
));
2214 #ifdef HAVE_XINERAMA
2215 /* Xinerama and XRender don't get along well */
2216 if (XineramaQueryExtension (display
, &render_event
, &render_error
)
2217 && XineramaIsActive (display
))
2219 #endif /* HAVE_XINERAMA */
2220 #endif /* HAVE_XRENDER */
2223 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2224 for (i
= 0; i
< ha
->n
; i
++)
2226 HID_Attribute
*a
= ha
->attributes
+ i
;
2227 val_union
*v
= new_values
+ rcount
;
2232 *(int *) a
->value
= v
->i
;
2234 a
->default_val
.int_value
= v
->i
;
2239 *(Coord
*) a
->value
= v
->c
;
2241 a
->default_val
.coord_value
= v
->c
;
2246 *(char *) a
->value
= v
->i
;
2248 a
->default_val
.int_value
= v
->i
;
2253 *(double *) a
->value
= v
->f
;
2255 a
->default_val
.real_value
= v
->f
;
2261 *(char **) a
->value
= v
->s
;
2263 a
->default_val
.str_value
= v
->s
;
2271 /* redefine colormap, if requested via "-install" */
2272 if (use_private_colormap
)
2274 colormap
= XCopyColormapAndFree (display
, colormap
);
2275 XtVaSetValues (appwidget
, XtNcolormap
, colormap
, NULL
);
2278 /* listen on standard input for actions */
2281 XtAppAddInput (app_context
, fileno (stdin
), (XtPointer
) XtInputReadMask
,
2282 lesstif_listener_cb
, NULL
);
2289 static XPoint
*points
= 0;
2290 static int npoints
= 0;
2291 Coord x1
, y1
, x2
, y2
, prevx
;
2294 static GC grid_gc
= 0;
2296 if (!Settings
.DrawGrid
)
2298 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
2302 grid_gc
= XCreateGC (display
, window
, 0, 0);
2303 XSetFunction (display
, grid_gc
, GXxor
);
2304 XSetForeground (display
, grid_gc
, grid_color
);
2308 x2
= GridFit (Px (0), PCB
->Grid
, PCB
->GridOffsetX
);
2309 x1
= GridFit (Px (view_width
), PCB
->Grid
, PCB
->GridOffsetX
);
2312 if (Vx (x1
) >= view_width
)
2317 x1
= GridFit (Px (0), PCB
->Grid
, PCB
->GridOffsetX
);
2318 x2
= GridFit (Px (view_width
), PCB
->Grid
, PCB
->GridOffsetX
);
2321 if (Vx (x2
) >= view_width
)
2326 y2
= GridFit (Py (0), PCB
->Grid
, PCB
->GridOffsetY
);
2327 y1
= GridFit (Py (view_height
), PCB
->Grid
, PCB
->GridOffsetY
);
2330 if (Vy (y1
) >= view_height
)
2335 y1
= GridFit (Py (0), PCB
->Grid
, PCB
->GridOffsetY
);
2336 y2
= GridFit (Py (view_height
), PCB
->Grid
, PCB
->GridOffsetY
);
2339 if (Vy (y2
) >= view_height
)
2342 n
= (x2
- x1
) / PCB
->Grid
+ 1;
2346 points
= (XPoint
*) realloc (points
, npoints
* sizeof (XPoint
));
2350 for (x
= x1
; x
<= x2
; x
+= PCB
->Grid
)
2356 points
[n
].x
-= prevx
;
2362 for (y
= y1
; y
<= y2
; y
+= PCB
->Grid
)
2366 XDrawPoints (display
, pixmap
, grid_gc
, points
, n
, CoordModePrevious
);
2371 mark_delta_to_widget (Coord dx
, Coord dy
, Widget w
)
2374 double g
= coord_to_unit (Settings
.grid_unit
, PCB
->Grid
);
2378 /* Integer-sized grid? */
2379 if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2382 prec
= Settings
.grid_unit
->default_prec
;
2384 if (dx
== 0 && dy
== 0)
2385 buf
= pcb_g_strdup_printf ("%m+%+.*mS, %+.*mS", UUNIT
, prec
, dx
, prec
, dy
);
2388 Angle angle
= atan2 (dy
, -dx
) * 180 / M_PI
;
2389 Coord dist
= Distance (0, 0, dx
, dy
);
2391 buf
= pcb_g_strdup_printf ("%m+%+.*mS, %+.*mS (%.*mS, %d\260)", UUNIT
,
2392 prec
, dx
, prec
, dy
, prec
, dist
, angle
);
2395 ms
= XmStringCreatePCB (buf
);
2397 stdarg (XmNlabelString
, ms
);
2398 XtSetValues (w
, args
, n
);
2403 cursor_pos_to_widget (Coord x
, Coord y
, Widget w
, int prev_state
)
2405 int this_state
= prev_state
;
2407 double g
= coord_to_unit (Settings
.grid_unit
, PCB
->Grid
);
2411 /* Determine necessary precision (and state) based
2412 * on the user's grid setting */
2413 if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2416 this_state
= Settings
.grid_unit
->allow
;
2420 prec
= Settings
.grid_unit
->default_prec
;
2421 this_state
= -Settings
.grid_unit
->allow
;
2425 buf
= g_strdup ("");
2427 buf
= pcb_g_strdup_printf ("%m+%.*mS, %.*mS", UUNIT
, prec
, x
, prec
, y
);
2429 ms
= XmStringCreatePCB (buf
);
2431 stdarg (XmNlabelString
, ms
);
2432 XtSetValues (w
, args
, n
);
2440 lesstif_update_status_line ()
2443 char *s45
= cur_clip ();
2446 switch (Settings
.Mode
)
2449 buf
= pcb_g_strdup_printf ("%m+%.2mS/%.2mS \370=%.2mS", UUNIT
,
2450 S
.ViaThickness
, S
.Keepaway
, S
.ViaDrillingHole
);
2454 buf
= pcb_g_strdup_printf ("%m+%.2mS/%.2mS %s", UUNIT
,
2455 S
.LineThickness
, S
.Keepaway
, s45
);
2457 case RECTANGLE_MODE
:
2459 buf
= pcb_g_strdup_printf ("%m+%.2mS %s", UUNIT
, S
.Keepaway
, s45
);
2462 buf
= g_strdup_printf ("%d %%", S
.TextScale
);
2466 case INSERTPOINT_MODE
:
2467 case RUBBERBANDMOVE_MODE
:
2468 buf
= g_strdup_printf ("%s", s45
);
2471 case PASTEBUFFER_MODE
:
2482 xs
= XmStringCreatePCB (buf
);
2484 stdarg (XmNlabelString
, xs
);
2485 XtSetValues (m_status
, args
, n
);
2491 static int idle_proc_set
= 0;
2492 static int need_redraw
= 0;
2495 idle_proc (XtPointer dummy
)
2501 lesstif_use_mask (HID_MASK_OFF
);
2502 pixmap
= main_pixmap
;
2507 region
.X2
= Px (view_width
);
2508 region
.Y2
= Py (view_height
);
2511 Coord tmp
= region
.X1
;
2512 region
.X1
= region
.X2
;
2517 Coord tmp
= region
.Y1
;
2518 region
.Y1
= region
.Y2
;
2521 XSetForeground (display
, bg_gc
, bgcolor
);
2522 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0, mx
, my
);
2524 if (region
.X1
< 0 || region
.Y1
< 0
2525 || region
.X2
> PCB
->MaxWidth
|| region
.Y2
> PCB
->MaxHeight
)
2527 int leftmost
, rightmost
, topmost
, bottommost
;
2530 rightmost
= Vx (PCB
->MaxWidth
);
2532 bottommost
= Vy (PCB
->MaxHeight
);
2533 if (leftmost
> rightmost
) {
2535 leftmost
= rightmost
;
2538 if (topmost
> bottommost
) {
2540 topmost
= bottommost
;
2547 if (rightmost
> view_width
)
2548 rightmost
= view_width
;
2549 if (bottommost
> view_height
)
2550 bottommost
= view_height
;
2552 XSetForeground (display
, bg_gc
, offlimit_color
);
2560 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0,
2561 leftmost
, view_height
);
2563 if (rightmost
< view_width
)
2565 XFillRectangle (display
, main_pixmap
, bg_gc
, rightmost
+1, 0,
2566 view_width
-rightmost
+1, view_height
);
2570 XFillRectangle (display
, main_pixmap
, bg_gc
, leftmost
, 0,
2571 rightmost
-leftmost
+1, topmost
);
2573 if (bottommost
< view_height
)
2575 XFillRectangle (display
, main_pixmap
, bg_gc
, leftmost
, bottommost
+1,
2576 rightmost
-leftmost
+1, view_height
-bottommost
+1);
2579 DrawBackgroundImage();
2580 hid_expose_callback (&lesstif_hid
, ®ion
, 0);
2582 lesstif_use_mask (HID_MASK_OFF
);
2583 show_crosshair (0); /* To keep the drawn / not drawn info correct */
2584 XSetFunction (display
, my_gc
, GXcopy
);
2585 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
2590 DrawAttached (crosshair_gc
);
2591 DrawMark (crosshair_gc
);
2597 static int c_x
= -2, c_y
= -2;
2598 static MarkType saved_mark
;
2599 static const Unit
*old_grid_unit
= NULL
;
2600 if (crosshair_x
!= c_x
|| crosshair_y
!= c_y
2601 || Settings
.grid_unit
!= old_grid_unit
2602 || memcmp (&saved_mark
, &Marked
, sizeof (MarkType
)))
2604 static int last_state
= 0;
2605 static int this_state
= 0;
2611 cursor_pos_to_widget (crosshair_x
, crosshair_y
, m_crosshair
,
2614 mark_delta_to_widget (crosshair_x
- Marked
.X
, crosshair_y
- Marked
.Y
,
2617 if (Marked
.status
!= saved_mark
.status
)
2621 XtManageChild (XtParent (m_mark
));
2622 XtManageChild (m_mark
);
2624 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
2625 stdarg (XmNleftWidget
, XtParent (m_mark
));
2626 XtSetValues (XtParent (m_crosshair
), args
, n
);
2631 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
2632 XtSetValues (XtParent (m_crosshair
), args
, n
);
2633 XtUnmanageChild (XtParent (m_mark
));
2635 last_state
= this_state
+ 100;
2637 memcpy (&saved_mark
, &Marked
, sizeof (MarkType
));
2639 if (old_grid_unit
!= Settings
.grid_unit
)
2641 old_grid_unit
= Settings
.grid_unit
;
2642 /* Force a resize on units change. */
2646 /* This is obtuse. We want to enable XmRESIZE_ANY long enough
2647 to shrink to fit the new format (if any), then switch it
2648 back to XmRESIZE_GROW to prevent it from shrinking due to
2649 changes in the number of actual digits printed. Thus, when
2650 you switch from a small grid and %.2f formats to a large
2651 grid and %d formats, you aren't punished with a wide and
2652 mostly white-space label widget. "this_state" indicates
2653 which of the above formats we're using. "last_state" is
2654 either zero (when resizing) or the same as "this_state"
2655 (when grow-only), or a non-zero but not "this_state" which
2656 means we need to start a resize cycle. */
2657 if (this_state
!= last_state
&& last_state
)
2660 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
2661 XtSetValues (XtParent (m_mark
), args
, n
);
2662 XtSetValues (XtParent (m_crosshair
), args
, n
);
2665 else if (this_state
!= last_state
)
2668 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
2669 XtSetValues (XtParent (m_mark
), args
, n
);
2670 XtSetValues (XtParent (m_crosshair
), args
, n
);
2671 last_state
= this_state
;
2677 static Coord old_grid
= -1;
2678 static Coord old_gx
, old_gy
;
2679 static const Unit
*old_unit
;
2681 if (PCB
->Grid
!= old_grid
2682 || PCB
->GridOffsetX
!= old_gx
2683 || PCB
->GridOffsetY
!= old_gy
|| Settings
.grid_unit
!= old_unit
)
2685 static char buf
[100];
2686 old_grid
= PCB
->Grid
;
2687 old_unit
= Settings
.grid_unit
;
2688 old_gx
= PCB
->GridOffsetX
;
2689 old_gy
= PCB
->GridOffsetY
;
2692 strcpy (buf
, "No Grid");
2696 if (old_gx
|| old_gy
)
2697 pcb_sprintf (buf
, "%m+%$mS @%mS,%mS", UUNIT
, old_grid
, old_gx
, old_gy
);
2699 pcb_sprintf (buf
, "%m+%$mS", UUNIT
, old_grid
);
2701 ms
= XmStringCreatePCB (buf
);
2703 stdarg (XmNlabelString
, ms
);
2704 XtSetValues (m_grid
, args
, n
);
2709 static double old_zoom
= -1;
2710 static const Unit
*old_grid_unit
= NULL
;
2711 if (view_zoom
!= old_zoom
|| Settings
.grid_unit
!= old_grid_unit
)
2713 gchar
*buf
= pcb_g_strdup_printf ("%m+%$mS/pix",
2714 Settings
.grid_unit
->allow
, (Coord
) view_zoom
);
2717 old_zoom
= view_zoom
;
2718 old_grid_unit
= Settings
.grid_unit
;
2720 ms
= XmStringCreatePCB (buf
);
2722 stdarg (XmNlabelString
, ms
);
2723 XtSetValues (m_zoom
, args
, n
);
2729 if (old_cursor_mode
!= Settings
.Mode
)
2734 static int free_cursor
= 0;
2736 old_cursor_mode
= Settings
.Mode
;
2737 switch (Settings
.Mode
)
2741 cursor
= XC_X_cursor
;
2751 case RECTANGLE_MODE
:
2753 cursor
= XC_ul_angle
;
2757 cursor
= XC_sb_up_arrow
;
2759 case POLYGONHOLE_MODE
:
2761 cursor
= XC_sb_up_arrow
;
2763 case PASTEBUFFER_MODE
:
2773 cursor
= XC_exchange
;
2781 cursor
= XC_crosshair
;
2785 cursor
= XC_crosshair
;
2787 case INSERTPOINT_MODE
:
2791 case RUBBERBANDMOVE_MODE
:
2793 cursor
= XC_top_left_corner
;
2797 cursor
= XC_iron_cross
;
2801 cursor
= XC_question_arrow
;
2806 cursor
= XC_draped_box
;
2808 cursor
= XC_left_ptr
;
2815 ms
= XmStringCreatePCB (s
);
2817 stdarg (XmNlabelString
, ms
);
2818 XtSetValues (m_mode
, args
, n
);
2822 XFreeCursor (display
, my_cursor
);
2827 static Pixmap nocur_source
= 0;
2828 static Pixmap nocur_mask
= 0;
2829 static Cursor nocursor
= 0;
2830 if (nocur_source
== 0)
2834 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2836 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2838 fg
.red
= fg
.green
= fg
.blue
= 65535;
2839 bg
.red
= bg
.green
= bg
.blue
= 0;
2840 fg
.flags
= bg
.flags
= DoRed
| DoGreen
| DoBlue
;
2841 nocursor
= XCreatePixmapCursor (display
, nocur_source
,
2842 nocur_mask
, &fg
, &bg
, 0, 0);
2844 my_cursor
= nocursor
;
2848 my_cursor
= XCreateFontCursor (display
, cursor
);
2851 XDefineCursor (display
, window
, my_cursor
);
2852 lesstif_update_status_line ();
2856 static char *old_clip
= 0;
2857 static int old_tscale
= -1;
2858 char *new_clip
= cur_clip ();
2860 if (new_clip
!= old_clip
|| Settings
.TextScale
!= old_tscale
)
2862 lesstif_update_status_line ();
2863 old_clip
= new_clip
;
2864 old_tscale
= Settings
.TextScale
;
2869 static int old_nrats
= -1;
2870 static char buf
[20];
2872 if (old_nrats
!= PCB
->Data
->RatN
)
2874 old_nrats
= PCB
->Data
->RatN
;
2875 sprintf(buf
, "%d rat%s", PCB
->Data
->RatN
, PCB
->Data
->RatN
== 1 ? "" : "s");
2876 if (PCB
->Data
->RatN
)
2878 XtManageChild(XtParent(m_rats
));
2879 XtManageChild(m_rats
);
2881 stdarg (XmNleftWidget
, m_rats
);
2882 XtSetValues (XtParent (m_status
), args
, n
);
2886 stdarg (XmNlabelString
, XmStringCreatePCB (buf
));
2887 XtSetValues (m_rats
, args
, n
);
2889 if (!PCB
->Data
->RatN
)
2892 stdarg (XmNleftWidget
, m_mode
);
2893 XtSetValues (XtParent (m_status
), args
, n
);
2894 XtUnmanageChild(XtParent(m_rats
));
2899 lesstif_update_widget_flags ();
2907 lesstif_need_idle_proc ()
2909 if (idle_proc_set
|| window
== 0)
2911 XtAppAddWorkProc (app_context
, idle_proc
, 0);
2916 lesstif_invalidate_lr (int l
, int r
, int t
, int b
)
2926 lesstif_invalidate_all (void)
2928 lesstif_invalidate_lr (0, PCB
->MaxWidth
, 0, PCB
->MaxHeight
);
2932 lesstif_notify_crosshair_change (bool changes_complete
)
2934 static int invalidate_depth
= 0;
2940 if (changes_complete
)
2941 invalidate_depth
--;
2943 if (invalidate_depth
< 0)
2945 invalidate_depth
= 0;
2946 /* A mismatch of changes_complete == false and == true notifications
2947 * is not expected to occur, but we will try to handle it gracefully.
2948 * As we know the crosshair will have been shown already, we must
2949 * repaint the entire view to be sure not to leave an artaefact.
2955 if (invalidate_depth
== 0 && crosshair_on
)
2957 save_pixmap
= pixmap
;
2959 DrawAttached (crosshair_gc
);
2960 pixmap
= save_pixmap
;
2963 if (!changes_complete
)
2964 invalidate_depth
++;
2968 lesstif_notify_mark_change (bool changes_complete
)
2970 static int invalidate_depth
= 0;
2973 if (changes_complete
)
2974 invalidate_depth
--;
2976 if (invalidate_depth
< 0)
2978 invalidate_depth
= 0;
2979 /* A mismatch of changes_complete == false and == true notifications
2980 * is not expected to occur, but we will try to handle it gracefully.
2981 * As we know the mark will have been shown already, we must
2982 * repaint the entire view to be sure not to leave an artaefact.
2988 if (invalidate_depth
== 0 && crosshair_on
)
2990 save_pixmap
= pixmap
;
2992 DrawMark (crosshair_gc
);
2993 pixmap
= save_pixmap
;
2996 if (!changes_complete
)
2997 invalidate_depth
++;
3001 lesstif_set_layer (const char *name
, int group
, int empty
)
3004 if (idx
>= 0 && idx
< max_group
)
3006 int n
= PCB
->LayerGroups
.Number
[group
];
3007 for (idx
= 0; idx
< n
-1; idx
++)
3009 int ni
= PCB
->LayerGroups
.Entries
[group
][idx
];
3010 if (ni
>= 0 && ni
< max_copper_layer
+ 2
3011 && PCB
->Data
->Layer
[ni
].On
)
3014 idx
= PCB
->LayerGroups
.Entries
[group
][idx
];
3016 if (idx
== LayerStack
[0]
3017 || GetLayerGroupNumberByNumber (idx
) ==
3018 GetLayerGroupNumberByNumber (LayerStack
[0]))
3028 if (idx
>= 0 && idx
< max_copper_layer
+ 2)
3029 return pinout
? 1 : PCB
->Data
->Layer
[idx
].On
;
3032 switch (SL_TYPE (idx
))
3035 return pinout
? 0 : PCB
->InvisibleObjectsOn
;
3037 if (SL_MYSIDE (idx
) && !pinout
)
3038 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
3041 if (SL_MYSIDE (idx
) || pinout
)
3042 return PCB
->ElementOn
;
3057 lesstif_make_gc (void)
3059 hidGC rv
= (hid_gc_struct
*) malloc (sizeof (hid_gc_struct
));
3060 memset (rv
, 0, sizeof (hid_gc_struct
));
3061 rv
->me_pointer
= &lesstif_hid
;
3066 lesstif_destroy_gc (hidGC gc
)
3072 lesstif_use_mask (enum mask_mode mode
)
3074 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) &&
3076 mode
= HID_MASK_OFF
;
3077 if ((mode
== HID_MASK_OFF
) == (use_mask
== HID_MASK_OFF
))
3084 /* printf("use_mask(%d)\n", use_it); */
3088 XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
,
3089 XDefaultDepth (display
, screen
));
3090 mask_bitmap
= XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
, 1);
3092 if (mode
!= HID_MASK_OFF
)
3094 pixmap
= mask_pixmap
;
3095 XSetForeground (display
, my_gc
, 0);
3096 XSetFunction (display
, my_gc
, GXcopy
);
3097 XFillRectangle (display
, mask_pixmap
, my_gc
,
3098 0, 0, view_width
, view_height
);
3099 XFillRectangle (display
, mask_bitmap
, bclear_gc
,
3100 0, 0, view_width
, view_height
);
3104 pixmap
= main_pixmap
;
3108 XRenderPictureAttributes pa
;
3110 pa
.clip_mask
= mask_bitmap
;
3111 XRenderChangePicture(display
, main_picture
, CPClipMask
, &pa
);
3112 XRenderComposite(display
, PictOpOver
, mask_picture
, pale_picture
,
3113 main_picture
, 0, 0, 0, 0, 0, 0, view_width
, view_height
);
3116 #endif /* HAVE_XRENDER */
3118 XSetClipMask (display
, clip_gc
, mask_bitmap
);
3119 XCopyArea (display
, mask_pixmap
, main_pixmap
, clip_gc
,
3120 0, 0, view_width
, view_height
, 0, 0);
3126 lesstif_set_color (hidGC gc
, const char *name
)
3128 static void *cache
= 0;
3130 static XColor color
, exact_color
;
3136 gc
->colorname
= name
;
3137 if (strcmp (name
, "erase") == 0)
3139 gc
->color
= bgcolor
;
3142 else if (strcmp (name
, "drill") == 0)
3144 gc
->color
= offlimit_color
;
3147 else if (hid_cache_color (0, name
, &cval
, &cache
))
3149 gc
->color
= cval
.lval
;
3154 if (!XAllocNamedColor (display
, colormap
, name
, &color
, &exact_color
))
3155 color
.pixel
= WhitePixel (display
, screen
);
3157 printf ("lesstif_set_color `%s' %08x rgb/%d/%d/%d\n",
3158 name
, color
.pixel
, color
.red
, color
.green
, color
.blue
);
3160 cval
.lval
= gc
->color
= color
.pixel
;
3161 hid_cache_color (1, name
, &cval
, &cache
);
3166 static int lastcolor
= -1, lastfade
= -1;
3167 if (gc
->color
== lastcolor
)
3168 gc
->color
= lastfade
;
3171 lastcolor
= gc
->color
;
3172 color
.pixel
= gc
->color
;
3174 XQueryColor (display
, colormap
, &color
);
3175 color
.red
= (bgred
+ color
.red
) / 2;
3176 color
.green
= (bggreen
+ color
.green
) / 2;
3177 color
.blue
= (bgblue
+ color
.blue
) / 2;
3178 XAllocColor (display
, colormap
, &color
);
3179 lastfade
= gc
->color
= color
.pixel
;
3187 int cap
, join
, width
;
3188 if (gc
->me_pointer
!= &lesstif_hid
)
3190 fprintf (stderr
, "Fatal: GC from another HID passed to lesstif HID\n");
3194 pcb_printf ("set_gc c%s %08lx w%#mS c%d x%d e%d\n",
3195 gc
->colorname
, gc
->color
, gc
->width
, gc
->cap
, gc
->xor_set
, gc
->erase
);
3200 cap
= CapProjecting
;
3209 cap
= CapProjecting
;
3213 cap
= CapProjecting
;
3219 XSetFunction (display
, my_gc
, GXxor
);
3220 XSetForeground (display
, my_gc
, gc
->color
^ bgcolor
);
3224 XSetFunction (display
, my_gc
, GXcopy
);
3225 XSetForeground (display
, my_gc
, offlimit_color
);
3229 XSetFunction (display
, my_gc
, GXcopy
);
3230 XSetForeground (display
, my_gc
, gc
->color
);
3232 width
= Vz (gc
->width
);
3235 XSetLineAttributes (display
, my_gc
, width
, LineSolid
, cap
,
3240 mask_gc
= bclear_gc
;
3243 XSetLineAttributes (display
, mask_gc
, Vz (gc
->width
), LineSolid
, cap
,
3249 lesstif_set_line_cap (hidGC gc
, EndCapStyle style
)
3255 lesstif_set_line_width (hidGC gc
, Coord width
)
3261 lesstif_set_draw_xor (hidGC gc
, int xor_set
)
3263 gc
->xor_set
= xor_set
;
3266 #define ISORT(a,b) if (a>b) { a^=b; b^=a; a^=b; }
3269 lesstif_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3271 double dx1
, dy1
, dx2
, dy2
;
3272 int vw
= Vz (gc
->width
);
3273 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && gc
->erase
)
3276 pcb_printf ("draw_line %#mD-%#mD @%#mS", x1
, y1
, x2
, y2
, gc
->width
);
3283 pcb_printf (" = %#mD-%#mD %s\n", x1
, y1
, x2
, y2
, gc
->colorname
);
3287 if (! ClipLine (0, 0, view_width
, view_height
,
3288 &dx1
, &dy1
, &dx2
, &dy2
, vw
))
3298 if (gc
->cap
== Square_Cap
&& x1
== x2
&& y1
== y2
)
3300 XFillRectangle (display
, pixmap
, my_gc
, x1
- vw
/ 2, y1
- vw
/ 2, vw
,
3303 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
- vw
/ 2,
3304 y1
- vw
/ 2, vw
, vw
);
3308 XDrawLine (display
, pixmap
, my_gc
, x1
, y1
, x2
, y2
);
3310 XDrawLine (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
, y2
);
3315 lesstif_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord width
, Coord height
,
3316 Angle start_angle
, Angle delta_angle
)
3318 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3321 pcb_printf ("draw_arc %#mD %#mSx%#mS s %d d %d", cx
, cy
, width
, height
, start_angle
, delta_angle
);
3324 height
= Vz (height
);
3325 cx
= Vx (cx
) - width
;
3326 cy
= Vy (cy
) - height
;
3329 start_angle
= 180 - start_angle
;
3330 delta_angle
= - delta_angle
;
3334 start_angle
= - start_angle
;
3335 delta_angle
= - delta_angle
;
3337 start_angle
= NormalizeAngle (start_angle
);
3338 if (start_angle
>= 180)
3341 pcb_printf (" = %#mD %#mSx%#mS %d %s\n", cx
, cy
, width
, height
, gc
->width
,
3345 XDrawArc (display
, pixmap
, my_gc
, cx
, cy
,
3346 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3348 if (use_mask
&& !TEST_FLAG (THINDRAWFLAG
, PCB
))
3349 XDrawArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3350 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3353 /* Enable this if you want to see the center and radii of drawn
3354 arcs, for debugging. */
3355 if (TEST_FLAG (THINDRAWFLAG
, PCB
)
3356 && delta_angle
!= 360)
3360 XDrawLine (display
, pixmap
, arc1_gc
, cx
, cy
,
3361 cx
- width
*cos(start_angle
*M_PI
/180),
3362 cy
+ width
*sin(start_angle
*M_PI
/180));
3363 XDrawLine (display
, pixmap
, arc2_gc
, cx
, cy
,
3364 cx
- width
*cos((start_angle
+delta_angle
)*M_PI
/180),
3365 cy
+ width
*sin((start_angle
+delta_angle
)*M_PI
/180));
3371 lesstif_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3373 int vw
= Vz (gc
->width
);
3374 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3380 if (x1
< -vw
&& x2
< -vw
)
3382 if (y1
< -vw
&& y2
< -vw
)
3384 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3386 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3388 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3389 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3391 XDrawRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1, y2
- y1
+ 1);
3393 XDrawRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3398 lesstif_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
3400 if (pinout
&& use_mask
&& gc
->erase
)
3402 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && gc
->erase
)
3405 pcb_printf ("fill_circle %#mD %#mS", cx
, cy
, radius
);
3407 radius
= Vz (radius
);
3408 cx
= Vx (cx
) - radius
;
3409 cy
= Vy (cy
) - radius
;
3410 if (cx
< -2 * radius
|| cx
> view_width
)
3412 if (cy
< -2 * radius
|| cy
> view_height
)
3415 pcb_printf (" = %#mD %#mS %lx %s\n", cx
, cy
, radius
, gc
->color
, gc
->colorname
);
3418 XFillArc (display
, pixmap
, my_gc
, cx
, cy
,
3419 radius
* 2, radius
* 2, 0, 360 * 64);
3421 XFillArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3422 radius
* 2, radius
* 2, 0, 360 * 64);
3426 lesstif_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
3428 static XPoint
*p
= 0;
3429 static int maxp
= 0;
3432 if (maxp
< n_coords
)
3434 maxp
= n_coords
+ 10;
3436 p
= (XPoint
*) realloc (p
, maxp
* sizeof (XPoint
));
3438 p
= (XPoint
*) malloc (maxp
* sizeof (XPoint
));
3441 for (i
= 0; i
< n_coords
; i
++)
3447 printf ("fill_polygon %d pts\n", n_coords
);
3450 XFillPolygon (display
, pixmap
, my_gc
, p
, n_coords
, Complex
,
3453 XFillPolygon (display
, mask_bitmap
, mask_gc
, p
, n_coords
, Complex
,
3458 lesstif_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3460 int vw
= Vz (gc
->width
);
3461 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3467 if (x1
< -vw
&& x2
< -vw
)
3469 if (y1
< -vw
&& y2
< -vw
)
3471 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3473 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3475 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3476 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3478 XFillRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1,
3481 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3486 lesstif_calibrate (double xval
, double yval
)
3492 lesstif_shift_is_pressed (void)
3494 return shift_pressed
;
3498 lesstif_control_is_pressed (void)
3500 return ctrl_pressed
;
3504 lesstif_mod1_is_pressed (void)
3509 extern void lesstif_get_coords (const char *msg
, Coord
*x
, Coord
*y
);
3512 lesstif_set_crosshair (int x
, int y
, int action
)
3514 if (crosshair_x
!= x
|| crosshair_y
!= y
)
3516 lesstif_show_crosshair(0);
3524 || x
> view_left_x
+ view_width
* view_zoom
3525 || y
< view_top_y
|| y
> view_top_y
+ view_height
* view_zoom
))
3527 view_left_x
= x
- (view_width
* view_zoom
) / 2;
3528 view_top_y
= y
- (view_height
* view_zoom
) / 2;
3529 lesstif_pan_fixup ();
3534 if (action
== HID_SC_PAN_VIEWPORT
)
3537 unsigned int keys_buttons
;
3538 int pos_x
, pos_y
, root_x
, root_y
;
3539 XQueryPointer (display
, window
, &root
, &child
,
3540 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
3542 view_left_x
= x
- (view_width
-pos_x
) * view_zoom
;
3544 view_left_x
= x
- pos_x
* view_zoom
;
3546 view_top_y
= y
- (view_height
-pos_y
) * view_zoom
;
3548 view_top_y
= y
- pos_y
* view_zoom
;
3549 lesstif_pan_fixup();
3550 action
= HID_SC_WARP_POINTER
;
3552 if (action
== HID_SC_WARP_POINTER
)
3555 XWarpPointer (display
, None
, window
, 0, 0, 0, 0, Vx(x
), Vy(y
));
3562 void (*func
) (hidval
);
3568 lesstif_timer_cb (XtPointer
* p
, XtIntervalId
* id
)
3570 TimerStruct
*ts
= (TimerStruct
*) p
;
3571 ts
->func (ts
->user_data
);
3576 lesstif_add_timer (void (*func
) (hidval user_data
),
3577 unsigned long milliseconds
, hidval user_data
)
3581 t
= (TimerStruct
*) malloc (sizeof (TimerStruct
));
3584 t
->user_data
= user_data
;
3585 t
->id
= XtAppAddTimeOut (app_context
, milliseconds
, (XtTimerCallbackProc
)lesstif_timer_cb
, t
);
3590 lesstif_stop_timer (hidval hv
)
3592 TimerStruct
*ts
= (TimerStruct
*) hv
.ptr
;
3593 XtRemoveTimeOut (ts
->id
);
3600 void (*func
) ( hidval
, int, unsigned int, hidval
);
3607 /* We need a wrapper around the hid file watch because to pass the correct flags
3610 lesstif_watch_cb (XtPointer client_data
, int *fid
, XtInputId
* id
)
3612 unsigned int pcb_condition
= 0;
3616 WatchStruct
*watch
= (WatchStruct
*)client_data
;
3619 fds
.events
= POLLIN
| POLLOUT
;
3621 condition
= fds
.revents
;
3623 // Should we only include those we were asked to watch?
3624 if (condition
& POLLIN
)
3625 pcb_condition
|= PCB_WATCH_READABLE
;
3626 if (condition
& POLLOUT
)
3627 pcb_condition
|= PCB_WATCH_WRITABLE
;
3628 if (condition
& POLLERR
)
3629 pcb_condition
|= PCB_WATCH_ERROR
;
3630 if (condition
& POLLHUP
)
3631 pcb_condition
|= PCB_WATCH_HANGUP
;
3633 x
.ptr
= (void *) watch
;
3634 watch
->func (x
, watch
->fd
, pcb_condition
, watch
->user_data
);
3640 lesstif_watch_file (int fd
, unsigned int condition
, void (*func
) (hidval watch
, int fd
, unsigned int condition
, hidval user_data
),
3643 WatchStruct
*watch
= (WatchStruct
*) malloc (sizeof(WatchStruct
));
3645 unsigned int xt_condition
= 0;
3647 if (condition
& PCB_WATCH_READABLE
)
3648 xt_condition
|= XtInputReadMask
;
3649 if (condition
& PCB_WATCH_WRITABLE
)
3650 xt_condition
|= XtInputWriteMask
;
3651 if (condition
& PCB_WATCH_ERROR
)
3652 xt_condition
|= XtInputExceptMask
;
3653 if (condition
& PCB_WATCH_HANGUP
)
3654 xt_condition
|= XtInputExceptMask
;
3657 watch
->user_data
= user_data
;
3659 watch
->id
= XtAppAddInput( app_context
, fd
, (XtPointer
) (size_t) xt_condition
, lesstif_watch_cb
, watch
);
3661 ret
.ptr
= (void *) watch
;
3666 lesstif_unwatch_file (hidval data
)
3668 WatchStruct
*watch
= (WatchStruct
*)data
.ptr
;
3669 XtRemoveInput( watch
->id
);
3676 void (*func
) (hidval user_data
);
3680 static void lesstif_block_hook_cb(XtPointer user_data
);
3683 lesstif_block_hook_cb (XtPointer user_data
)
3685 BlockHookStruct
*block_hook
= (BlockHookStruct
*)user_data
;
3686 block_hook
->func( block_hook
->user_data
);
3690 lesstif_add_block_hook (void (*func
) (hidval data
), hidval user_data
)
3693 BlockHookStruct
*block_hook
= (BlockHookStruct
*) malloc( sizeof( BlockHookStruct
));
3695 block_hook
->func
= func
;
3696 block_hook
->user_data
= user_data
;
3698 block_hook
->id
= XtAppAddBlockHook( app_context
, lesstif_block_hook_cb
, (XtPointer
)block_hook
);
3700 ret
.ptr
= (void *) block_hook
;
3705 lesstif_stop_block_hook (hidval mlpoll
)
3707 BlockHookStruct
*block_hook
= (BlockHookStruct
*)mlpoll
.ptr
;
3708 XtRemoveBlockHook( block_hook
->id
);
3713 extern void lesstif_logv (const char *fmt
, va_list ap
);
3715 extern int lesstif_confirm_dialog (char *msg
, ...);
3717 extern int lesstif_close_confirm_dialog ();
3719 extern void lesstif_report_dialog (char *title
, char *msg
);
3722 lesstif_attribute_dialog (HID_Attribute
* attrs
,
3723 int n_attrs
, HID_Attr_Val
* results
,
3724 const char * title
, const char * descr
);
3727 pinout_callback (Widget da
, PinoutData
* pd
,
3728 XmDrawingAreaCallbackStruct
* cbs
)
3731 int save_vx
, save_vy
, save_vw
, save_vh
;
3732 int save_fx
, save_fy
;
3735 int reason
= cbs
? cbs
->reason
: 0;
3737 if (pd
->window
== 0 && reason
== XmCR_RESIZE
)
3739 if (pd
->window
== 0 || reason
== XmCR_RESIZE
)
3745 stdarg (XmNwidth
, &w
);
3746 stdarg (XmNheight
, &h
);
3747 XtGetValues (da
, args
, n
);
3749 pd
->window
= XtWindow (da
);
3752 pd
->zoom
= (pd
->right
- pd
->left
+ 1) / (double) w
;
3753 z
= (pd
->bottom
- pd
->top
+ 1) / (double) h
;
3757 pd
->x
= (pd
->left
+ pd
->right
) / 2 - pd
->v_width
* pd
->zoom
/ 2;
3758 pd
->y
= (pd
->top
+ pd
->bottom
) / 2 - pd
->v_height
* pd
->zoom
/ 2;
3761 save_vx
= view_left_x
;
3762 save_vy
= view_top_y
;
3763 save_vz
= view_zoom
;
3764 save_vw
= view_width
;
3765 save_vh
= view_height
;
3770 pixmap
= pd
->window
;
3771 view_left_x
= pd
->x
;
3773 view_zoom
= pd
->zoom
;
3774 view_width
= pd
->v_width
;
3775 view_height
= pd
->v_height
;
3777 flip_x
= flip_y
= 0;
3781 region
.X2
= PCB
->MaxWidth
;
3782 region
.Y2
= PCB
->MaxHeight
;
3784 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, pd
->v_width
, pd
->v_height
);
3785 hid_expose_callback (&lesstif_hid
, ®ion
, pd
->item
);
3788 view_left_x
= save_vx
;
3789 view_top_y
= save_vy
;
3790 view_zoom
= save_vz
;
3791 view_width
= save_vw
;
3792 view_height
= save_vh
;
3799 pinout_unmap (Widget w
, PinoutData
* pd
, void *v
)
3802 pd
->prev
->next
= pd
->next
;
3806 pd
->next
->prev
= pd
->prev
;
3807 XtDestroyWidget (XtParent (pd
->form
));
3812 lesstif_show_item (void *item
)
3819 for (pd
= pinouts
; pd
; pd
= pd
->next
)
3820 if (pd
->item
== item
)
3825 pd
= (PinoutData
*) calloc (1, sizeof (PinoutData
));
3829 extents
= hid_get_extents (item
);
3830 pd
->left
= extents
->X1
;
3831 pd
->right
= extents
->X2
;
3832 pd
->top
= extents
->Y1
;
3833 pd
->bottom
= extents
->Y2
;
3835 if (pd
->left
> pd
->right
)
3843 pd
->next
->prev
= pd
;
3848 pd
->form
= XmCreateFormDialog (mainwind
, "pinout", args
, n
);
3850 XtAddCallback (pd
->form
, XmNunmapCallback
, (XtCallbackProc
) pinout_unmap
,
3854 sqrt (200.0 * 200.0 /
3855 ((pd
->right
- pd
->left
+ 1.0) * (pd
->bottom
- pd
->top
+ 1.0)));
3858 stdarg (XmNwidth
, (int) (scale
* (pd
->right
- pd
->left
+ 1)));
3859 stdarg (XmNheight
, (int) (scale
* (pd
->bottom
- pd
->top
+ 1)));
3860 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
3861 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
3862 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
3863 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
3864 da
= XmCreateDrawingArea (pd
->form
, "pinout", args
, n
);
3867 XtAddCallback (da
, XmNexposeCallback
, (XtCallbackProc
) pinout_callback
,
3869 XtAddCallback (da
, XmNresizeCallback
, (XtCallbackProc
) pinout_callback
,
3872 XtManageChild (pd
->form
);
3884 static bool progress_cancelled
= false;
3887 progress_cancel_callback (Widget w
, void *v
, void *cbs
)
3889 progress_cancelled
= true;
3892 static Widget progress_dialog
= 0;
3893 static Widget progress_cancel
, progress_label
;
3894 static Widget progress_scale
;
3897 lesstif_progress_dialog (int so_far
, int total
, const char *msg
)
3904 if (progress_dialog
== 0)
3909 stdarg (XmNdefaultButtonType
, XmDIALOG_CANCEL_BUTTON
);
3910 stdarg (XmNtitle
, "Progress");
3911 stdarg (XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
);
3912 stdarg (XmNdialogStyle
, XmDIALOG_FULL_APPLICATION_MODAL
);
3913 progress_dialog
= XmCreateInformationDialog (mainwind
, "progress", args
, n
);
3914 XtAddCallback (progress_dialog
, XmNcancelCallback
,
3915 (XtCallbackProc
) progress_cancel_callback
, NULL
);
3917 progress_cancel
= XmMessageBoxGetChild (progress_dialog
, XmDIALOG_CANCEL_BUTTON
);
3918 progress_label
= XmMessageBoxGetChild (progress_dialog
, XmDIALOG_MESSAGE_LABEL
);
3920 XtUnmanageChild (XmMessageBoxGetChild (progress_dialog
, XmDIALOG_OK_BUTTON
));
3921 XtUnmanageChild (XmMessageBoxGetChild (progress_dialog
, XmDIALOG_HELP_BUTTON
));
3923 stdarg (XmNdefaultPosition
, False
);
3924 XtSetValues (progress_dialog
, args
, n
);
3927 stdarg(XmNminimum
, 0);
3928 stdarg(XmNvalue
, 0);
3929 stdarg(XmNmaximum
, total
> 0 ? total
: 1);
3930 stdarg(XmNorientation
, XmHORIZONTAL
);
3931 stdarg(XmNshowArrows
, false);
3932 progress_scale
= XmCreateScrollBar (progress_dialog
, "scale", args
, n
);
3933 XtManageChild (progress_scale
);
3935 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
3936 XmAddWMProtocolCallback (XtParent (progress_dialog
), close_atom
,
3937 (XtCallbackProc
) progress_cancel_callback
, 0);
3941 stdarg(XmNvalue
, 0);
3942 stdarg(XmNsliderSize
, (so_far
<= total
) ? (so_far
< 0) ? 0 : so_far
: total
);
3943 stdarg(XmNmaximum
, total
> 0 ? total
: 1);
3944 XtSetValues (progress_scale
, args
, n
);
3947 xs
= XmStringCreatePCB ((char *)msg
);
3948 stdarg (XmNmessageString
, xs
);
3949 XtSetValues (progress_dialog
, args
, n
);
3954 #define MIN_TIME_SEPARATION 0.1 /* seconds */
3957 lesstif_progress (int so_far
, int total
, const char *message
)
3959 static bool started
= false;
3961 struct timeval time
;
3962 double time_delta
, time_now
;
3963 static double time_then
= 0.0;
3966 if (so_far
== 0 && total
== 0 && message
== NULL
)
3968 XtUnmanageChild (progress_dialog
);
3970 progress_cancelled
= false;
3974 gettimeofday (&time
, NULL
);
3975 time_now
= time
.tv_sec
+ time
.tv_usec
/ 1000000.0;
3977 time_delta
= time_now
- time_then
;
3979 if (started
&& time_delta
< MIN_TIME_SEPARATION
)
3982 /* Create or update the progress dialog */
3983 lesstif_progress_dialog (so_far
, total
, message
);
3987 XtManageChild (progress_dialog
);
3991 /* Dispatch pending events */
3992 while (XtAppPending (app_context
))
3994 XtAppNextEvent (app_context
, &e
);
3995 XtDispatchEvent (&e
);
3999 /* If rendering takes a while, make sure the core has enough time to
4001 gettimeofday (&time
, NULL
);
4002 time_then
= time
.tv_sec
+ time
.tv_usec
/ 1000000.0;
4004 return progress_cancelled
;
4008 lesstif_request_debug_draw (void)
4010 /* Send drawing to the backing pixmap */
4011 pixmap
= main_pixmap
;
4012 return lesstif_hid
.graphics
;
4016 lesstif_flush_debug_draw (void)
4018 /* Copy the backing pixmap to the display and redraw any attached objects */
4019 XSetFunction (display
, my_gc
, GXcopy
);
4020 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
4025 DrawAttached (crosshair_gc
);
4026 DrawMark (crosshair_gc
);
4028 pixmap
= main_pixmap
;
4032 lesstif_finish_debug_draw (void)
4034 lesstif_flush_debug_draw ();
4035 /* No special tear down requirements
4039 #include "dolists.h"
4044 memset (&lesstif_hid
, 0, sizeof (HID
));
4045 memset (&lesstif_graphics
, 0, sizeof (HID_DRAW
));
4047 common_nogui_init (&lesstif_hid
);
4048 common_draw_helpers_init (&lesstif_graphics
);
4050 lesstif_hid
.struct_size
= sizeof (HID
);
4051 lesstif_hid
.name
= "lesstif";
4052 lesstif_hid
.description
= "LessTif - a Motif clone for X/Unix";
4053 lesstif_hid
.gui
= 1;
4054 lesstif_hid
.poly_before
= 1;
4056 lesstif_hid
.get_export_options
= lesstif_get_export_options
;
4057 lesstif_hid
.do_export
= lesstif_do_export
;
4058 lesstif_hid
.parse_arguments
= lesstif_parse_arguments
;
4059 lesstif_hid
.invalidate_lr
= lesstif_invalidate_lr
;
4060 lesstif_hid
.invalidate_all
= lesstif_invalidate_all
;
4061 lesstif_hid
.notify_crosshair_change
= lesstif_notify_crosshair_change
;
4062 lesstif_hid
.notify_mark_change
= lesstif_notify_mark_change
;
4063 lesstif_hid
.set_layer
= lesstif_set_layer
;
4065 lesstif_hid
.calibrate
= lesstif_calibrate
;
4066 lesstif_hid
.shift_is_pressed
= lesstif_shift_is_pressed
;
4067 lesstif_hid
.control_is_pressed
= lesstif_control_is_pressed
;
4068 lesstif_hid
.mod1_is_pressed
= lesstif_mod1_is_pressed
;
4069 lesstif_hid
.get_coords
= lesstif_get_coords
;
4070 lesstif_hid
.set_crosshair
= lesstif_set_crosshair
;
4071 lesstif_hid
.add_timer
= lesstif_add_timer
;
4072 lesstif_hid
.stop_timer
= lesstif_stop_timer
;
4073 lesstif_hid
.watch_file
= lesstif_watch_file
;
4074 lesstif_hid
.unwatch_file
= lesstif_unwatch_file
;
4075 lesstif_hid
.add_block_hook
= lesstif_add_block_hook
;
4076 lesstif_hid
.stop_block_hook
= lesstif_stop_block_hook
;
4078 lesstif_hid
.log
= lesstif_log
;
4079 lesstif_hid
.logv
= lesstif_logv
;
4080 lesstif_hid
.confirm_dialog
= lesstif_confirm_dialog
;
4081 lesstif_hid
.close_confirm_dialog
= lesstif_close_confirm_dialog
;
4082 lesstif_hid
.report_dialog
= lesstif_report_dialog
;
4083 lesstif_hid
.prompt_for
= lesstif_prompt_for
;
4084 lesstif_hid
.fileselect
= lesstif_fileselect
;
4085 lesstif_hid
.attribute_dialog
= lesstif_attribute_dialog
;
4086 lesstif_hid
.show_item
= lesstif_show_item
;
4087 lesstif_hid
.beep
= lesstif_beep
;
4088 lesstif_hid
.progress
= lesstif_progress
;
4089 lesstif_hid
.edit_attributes
= lesstif_attributes_dialog
;
4091 lesstif_hid
.request_debug_draw
= lesstif_request_debug_draw
;
4092 lesstif_hid
.flush_debug_draw
= lesstif_flush_debug_draw
;
4093 lesstif_hid
.finish_debug_draw
= lesstif_finish_debug_draw
;
4095 lesstif_hid
.graphics
= &lesstif_graphics
;
4097 lesstif_graphics
.make_gc
= lesstif_make_gc
;
4098 lesstif_graphics
.destroy_gc
= lesstif_destroy_gc
;
4099 lesstif_graphics
.use_mask
= lesstif_use_mask
;
4100 lesstif_graphics
.set_color
= lesstif_set_color
;
4101 lesstif_graphics
.set_line_cap
= lesstif_set_line_cap
;
4102 lesstif_graphics
.set_line_width
= lesstif_set_line_width
;
4103 lesstif_graphics
.set_draw_xor
= lesstif_set_draw_xor
;
4104 lesstif_graphics
.draw_line
= lesstif_draw_line
;
4105 lesstif_graphics
.draw_arc
= lesstif_draw_arc
;
4106 lesstif_graphics
.draw_rect
= lesstif_draw_rect
;
4107 lesstif_graphics
.fill_circle
= lesstif_fill_circle
;
4108 lesstif_graphics
.fill_polygon
= lesstif_fill_polygon
;
4109 lesstif_graphics
.fill_rect
= lesstif_fill_rect
;
4111 lesstif_graphics
.draw_pcb_polygon
= common_gui_draw_pcb_polygon
;
4113 hid_register_hid (&lesstif_hid
);
4114 #include "lesstif_lists.h"