14 #include "xincludes.h"
19 #include "crosshair.h"
22 #include "pcb-printf.h"
28 #include "../hidint.h"
29 #include "hid/common/hidnogui.h"
30 #include "hid/common/draw_helpers.h"
31 #include "hid/common/hid_resource.h"
34 #ifdef HAVE_LIBDMALLOC
41 #define XtRDouble "Double"
44 /* How big the viewport can be relative to the pcb size. */
45 #define MAX_ZOOM_SCALE 10
46 #define UUNIT Settings.grid_unit->allow
48 typedef struct hid_gc_struct
52 const char *colorname
;
59 static HID lesstif_hid
;
61 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented GUI function %s\n", __FUNCTION__), abort()
63 XtAppContext app_context
;
66 static Window window
= 0;
67 static Cursor my_cursor
= 0;
68 static int old_cursor_mode
= -1;
69 static int over_point
= 0;
71 /* The first is the "current" pixmap. The main_ is the real one we
72 usually use, the mask_ are the ones for doing polygon masks. The
73 pixmap is the saved pixels, the bitmap is for the "erase" color.
74 We set pixmap to point to main_pixmap or mask_pixmap as needed. */
75 static Pixmap pixmap
= 0;
76 static Pixmap main_pixmap
= 0;
77 static Pixmap mask_pixmap
= 0;
78 static Pixmap mask_bitmap
= 0;
79 static int use_mask
= 0;
81 static int use_xrender
= 0;
83 static Picture main_picture
;
84 static Picture mask_picture
;
85 static Pixmap pale_pixmap
;
86 static Picture pale_picture
;
87 #endif /* HAVE_XRENDER */
89 static int pixmap_w
= 0, pixmap_h
= 0;
92 static Colormap colormap
;
93 static GC my_gc
= 0, bg_gc
, clip_gc
= 0, bset_gc
= 0, bclear_gc
= 0, mask_gc
=
95 static Pixel bgcolor
, offlimit_color
, grid_color
;
96 static int bgred
, bggreen
, bgblue
;
98 static GC arc1_gc
, arc2_gc
;
100 /* These are for the pinout windows. */
101 typedef struct PinoutData
103 struct PinoutData
*prev
, *next
;
106 Coord left
, right
, top
, bottom
; /* PCB extents of item */
107 Coord x
, y
; /* PCB coordinates of upper right corner of window */
108 double zoom
; /* PCB units per screen pixel */
109 int v_width
, v_height
; /* pixels */
113 /* Linked list of all pinout windows. */
114 static PinoutData
*pinouts
= 0;
115 /* If set, we are currently updating this pinout window. */
116 static PinoutData
*pinout
= 0;
118 static int crosshair_x
= 0, crosshair_y
= 0;
119 static int in_move_event
= 0, crosshair_in_window
= 1;
122 Widget work_area
, messages
, command
, hscroll
, vscroll
;
123 static Widget m_mark
, m_crosshair
, m_grid
, m_zoom
, m_mode
, m_status
;
124 static Widget m_rats
;
125 Widget lesstif_m_layer
;
128 /* This is the size, in pixels, of the viewport. */
129 static int view_width
, view_height
;
130 /* This is the PCB location represented by the upper left corner of
131 the viewport. Note that PCB coordinates put 0,0 in the upper left,
133 static int view_left_x
= 0, view_top_y
= 0;
134 /* Denotes PCB units per screen pixel. Larger numbers mean zooming
135 out - the largest value means you are looking at the whole
137 static double view_zoom
= MIL_TO_COORD (10), prev_view_zoom
= MIL_TO_COORD (10);
138 static bool flip_x
= 0, flip_y
= 0;
139 static bool autofade
= 0;
140 static bool crosshair_on
= true;
143 ShowCrosshair (bool show
)
145 if (crosshair_on
== show
)
148 notify_crosshair_change (false);
150 notify_mark_change (false);
154 notify_crosshair_change (true);
156 notify_mark_change (true);
160 flag_flipx (void *data
)
165 flag_flipy (void *data
)
170 HID_Flag lesstif_main_flag_list
[] = {
171 {"flip_x", flag_flipx
, NULL
},
172 {"flip_y", flag_flipy
, NULL
}
175 REGISTER_FLAGS (lesstif_main_flag_list
)
177 /* This is the size of the current PCB work area. */
178 /* Use PCB->MaxWidth, PCB->MaxHeight. */
179 /* static int pcb_width, pcb_height; */
183 #define stdarg(t,v) XtSetArg(args[n], t, v), n++
186 static int use_private_colormap
= 0;
187 static int stdin_listen
= 0;
188 static char *background_image_file
= 0;
189 char *lesstif_pcbmenu_path
= "pcb-menu.res";
191 HID_Attribute lesstif_attribute_list
[] = {
192 {"install", "Install private colormap",
193 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &use_private_colormap
},
194 #define HA_colormap 0
196 /* %start-doc options "22 lesstif GUI Options"
199 Listen for actions on stdin.
203 {"listen", "Listen on standard input for actions",
204 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &stdin_listen
},
207 /* %start-doc options "22 lesstif GUI Options"
209 @item --bg-image <string>
210 File name of an image to put into the background of the GUI canvas. The image must
211 be a color PPM image, in binary (not ASCII) format. It can be any size, and will be
212 automatically scaled to fit the canvas.
216 {"bg-image", "Background Image",
217 HID_String
, 0, 0, {0, 0, 0}, 0, &background_image_file
},
218 #define HA_bg_image 2
220 /* %start-doc options "22 lesstif GUI Options"
222 @item --pcb-menu <string>
223 Location of the @file{pcb-menu.res} file which defines the menu for the lesstif GUI.
227 {"pcb-menu", "Location of pcb-menu.res file",
228 HID_String
, 0, 0, {0, PCBLIBDIR
"/pcb-menu.res", 0}, 0, &lesstif_pcbmenu_path
}
232 REGISTER_ATTRIBUTES (lesstif_attribute_list
)
234 static void lesstif_use_mask (int use_it
);
235 static void zoom_max ();
236 static void zoom_to (double factor
, int x
, int y
);
237 static void zoom_by (double factor
, int x
, int y
);
238 static void zoom_toggle (int x
, int y
);
239 static void pinout_callback (Widget
, PinoutData
*,
240 XmDrawingAreaCallbackStruct
*);
241 static void pinout_unmap (Widget
, PinoutData
*, void *);
242 static void Pan (int mode
, int x
, int y
);
244 /* Px converts view->pcb, Vx converts pcb->view */
249 int rv
= (x
- view_left_x
) / view_zoom
+ 0.5;
251 rv
= view_width
- rv
;
258 int rv
= (y
- view_top_y
) / view_zoom
+ 0.5;
260 rv
= view_height
- rv
;
267 return z
/ view_zoom
+ 0.5;
275 return x
* view_zoom
+ view_left_x
;
283 return y
* view_zoom
+ view_top_y
;
289 return z
* view_zoom
;
293 lesstif_coords_to_pcb (int vx
, int vy
, Coord
*px
, Coord
*py
)
300 lesstif_parse_color (char *value
)
303 if (XParseColor (display
, colormap
, value
, &color
))
304 if (XAllocColor (display
, colormap
, &color
))
310 do_color (char *value
, char *which
)
313 if (XParseColor (display
, colormap
, value
, &color
))
314 if (XAllocColor (display
, colormap
, &color
))
316 stdarg (which
, color
.pixel
);
320 /* ------------------------------------------------------------ */
325 if (TEST_FLAG (ORTHOMOVEFLAG
, PCB
))
327 if (TEST_FLAG (ALLDIRECTIONFLAG
, PCB
))
329 if (PCB
->Clipping
== 0)
331 if (PCB
->Clipping
== 1)
336 /* Called from the core when it's busy doing something and we need to
337 indicate that to the user. */
339 Busy(int argc
, char **argv
, Coord x
, Coord y
)
341 static Cursor busy_cursor
= 0;
342 if (busy_cursor
== 0)
343 busy_cursor
= XCreateFontCursor (display
, XC_watch
);
344 XDefineCursor (display
, window
, busy_cursor
);
346 old_cursor_mode
= -1;
350 /* ---------------------------------------------------------------------- */
355 PointCursor (int argc
, char **argv
, Coord x
, Coord y
)
361 old_cursor_mode
= -1;
366 PCBChanged (int argc
, char **argv
, Coord x
, Coord y
)
370 /*pcb_printf("PCB Changed! %$mD\n", PCB->MaxWidth, PCB->MaxHeight); */
372 stdarg (XmNminimum
, 0);
373 stdarg (XmNvalue
, 0);
374 stdarg (XmNsliderSize
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
375 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
376 XtSetValues (hscroll
, args
, n
);
378 stdarg (XmNminimum
, 0);
379 stdarg (XmNvalue
, 0);
380 stdarg (XmNsliderSize
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
381 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
382 XtSetValues (vscroll
, args
, n
);
385 hid_action ("NetlistChanged");
386 hid_action ("LayersChanged");
387 hid_action ("RouteStylesChanged");
388 lesstif_sizes_reset ();
389 lesstif_update_layer_groups ();
391 pinout_unmap (0, pinouts
, 0);
394 char *cp
= strrchr (PCB
->Filename
, '/');
396 stdarg (XmNtitle
, cp
? cp
+ 1 : PCB
->Filename
);
397 XtSetValues (appwidget
, args
, n
);
403 static const char setunits_syntax
[] =
406 static const char setunits_help
[] =
407 "Set the default measurement units.";
409 /* %start-doc actions SetUnits
414 Sets the display units to mils (1/1000 inch).
417 Sets the display units to millimeters.
424 SetUnits (int argc
, char **argv
, Coord x
, Coord y
)
426 const Unit
*new_unit
;
429 new_unit
= get_unit_struct (argv
[0]);
430 if (new_unit
!= NULL
&& new_unit
->allow
!= NO_PRINT
)
432 Settings
.grid_unit
= new_unit
;
433 Settings
.increments
= get_increments_struct (Settings
.grid_unit
->family
);
434 AttributePut (PCB
, "PCB::grid::unit", argv
[0]);
436 lesstif_sizes_reset ();
437 lesstif_styles_update_values ();
441 static const char zoom_syntax
[] =
445 static const char zoom_help
[] =
446 "Various zoom factor changes.";
448 /* %start-doc actions Zoom
450 Changes the zoom (magnification) of the view of the board. If no
451 arguments are passed, the view is scaled such that the board just fits
452 inside the visible window (i.e. ``view all''). Otherwise,
453 @var{factor} specifies a change in zoom factor. It may be prefixed by
454 @code{+}, @code{-}, or @code{=} to change how the zoom factor is
455 modified. The @var{factor} is a floating point number, such as
456 @code{1.5} or @code{0.75}.
461 Values greater than 1.0 cause the board to be drawn smaller; more of
462 the board will be visible. Values between 0.0 and 1.0 cause the board
463 to be drawn bigger; less of the board will be visible.
466 Values greater than 1.0 cause the board to be drawn bigger; less of
467 the board will be visible. Values between 0.0 and 1.0 cause the board
468 to be drawn smaller; more of the board will be visible.
472 The @var{factor} is an absolute zoom factor; the unit for this value
473 is "PCB units per screen pixel". Since PCB units are 0.01 mil, a
474 @var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI,
475 about the actual resolution of most screens - resulting in an "actual
476 size" board. Similarly, a @var{factor} of 100 gives you a 10x actual
481 Note that zoom factors of zero are silently ignored.
486 ZoomAction (int argc
, char **argv
, Coord x
, Coord y
)
490 if (x
== 0 && y
== 0)
506 if (strcasecmp (vp
, "toggle") == 0)
511 if (*vp
== '+' || *vp
== '-' || *vp
== '=')
513 v
= g_ascii_strtod (vp
, 0);
519 zoom_by (1 / v
, x
, y
);
532 static int pan_thumb_mode
;
535 PanAction (int argc
, char **argv
, Coord x
, Coord y
)
541 pan_thumb_mode
= (strcasecmp (argv
[0], "thumb") == 0) ? 1 : 0;
542 mode
= atoi (argv
[1]);
547 mode
= atoi (argv
[0]);
549 Pan (mode
, Vx(x
), Vy(y
));
554 static const char swapsides_syntax
[] =
557 static const char swapsides_help
[] =
558 "Swaps the side of the board you're looking at.";
560 /* %start-doc actions SwapSides
562 This action changes the way you view the board.
567 Flips the board over vertically (up/down).
570 Flips the board over horizontally (left/right), like flipping pages in
574 Rotates the board 180 degrees without changing sides.
578 If no argument is given, the board isn't moved but the opposite side
581 Normally, this action changes which pads and silk layer are drawn as
582 true silk, and which are drawn as the "invisible" layer. It also
583 determines which solder mask you see.
585 As a special case, if the layer group for the side you're looking at
586 is visible and currently active, and the layer group for the opposite
587 is not visible (i.e. disabled), then this action will also swap which
588 layer group is visible and active, effectively swapping the ``working
594 group_showing (int g
, int *c
)
597 *c
= PCB
->LayerGroups
.Entries
[g
][0];
598 for (i
=0; i
<PCB
->LayerGroups
.Number
[g
]; i
++)
600 l
= PCB
->LayerGroups
.Entries
[g
][i
];
601 if (l
>= 0 && l
< max_copper_layer
)
604 if (PCB
->Data
->Layer
[l
].On
)
612 SwapSides (int argc
, char **argv
, Coord x
, Coord y
)
614 int old_shown_side
= Settings
.ShowSolderSide
;
615 int comp_group
= GetLayerGroupNumberByNumber (component_silk_layer
);
616 int solder_group
= GetLayerGroupNumberByNumber (solder_silk_layer
);
617 int active_group
= GetLayerGroupNumberByNumber (LayerStack
[0]);
620 int comp_showing
= group_showing (comp_group
, &comp_layer
);
621 int solder_showing
= group_showing (solder_group
, &solder_layer
);
625 switch (argv
[0][0]) {
642 /* SwapSides will swap this */
643 Settings
.ShowSolderSide
= (flip_x
== flip_y
);
648 stdarg (XmNprocessingDirection
, XmMAX_ON_LEFT
);
650 stdarg (XmNprocessingDirection
, XmMAX_ON_RIGHT
);
651 XtSetValues (hscroll
, args
, n
);
655 stdarg (XmNprocessingDirection
, XmMAX_ON_TOP
);
657 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
658 XtSetValues (vscroll
, args
, n
);
660 Settings
.ShowSolderSide
= !Settings
.ShowSolderSide
;
662 /* The idea is that if we're looking at the front side and the front
663 layer is active (or visa versa), switching sides should switch
664 layers too. We used to only do this if the other layer wasn't
665 shown, but we now do it always. Change it back if users get
667 if (Settings
.ShowSolderSide
!= old_shown_side
)
669 if (Settings
.ShowSolderSide
)
671 if (active_group
== comp_group
)
673 if (comp_showing
&& !solder_showing
)
674 ChangeGroupVisibility (comp_layer
, 0, 0);
675 ChangeGroupVisibility (solder_layer
, 1, 1);
680 if (active_group
== solder_group
)
682 if (solder_showing
&& !comp_showing
)
683 ChangeGroupVisibility (solder_layer
, 0, 0);
684 ChangeGroupVisibility (comp_layer
, 1, 1);
688 lesstif_invalidate_all ();
692 static Widget m_cmd
= 0, m_cmd_label
;
695 command_callback (Widget w
, XtPointer uptr
, XmTextVerifyCallbackStruct
* cbs
)
701 s
= XmTextGetString (w
);
702 lesstif_show_crosshair (0);
703 hid_parse_command (s
);
705 XmTextSetString (w
, "");
706 case XmCR_LOSING_FOCUS
:
707 XtUnmanageChild (m_cmd
);
708 XtUnmanageChild (m_cmd_label
);
714 command_event_handler (Widget w
, XtPointer p
, XEvent
* e
, Boolean
* cont
)
723 slen
= XLookupString ((XKeyEvent
*)e
, buf
, sizeof (buf
), &sym
, NULL
);
727 XtUnmanageChild (m_cmd
);
728 XtUnmanageChild (m_cmd_label
);
729 XmTextSetString (w
, "");
737 static const char command_syntax
[] =
740 static const char command_help
[] =
741 "Displays the command line input window.";
743 /* %start-doc actions Command
745 The command window allows the user to manually enter actions to be
746 executed. Action syntax can be done one of two ways:
751 Follow the action name by an open parenthesis, arguments separated by
752 commas, end with a close parenthesis. Example: @code{Abc(1,2,3)}
755 Separate the action name and arguments by spaces. Example: @code{Abc
760 The first option allows you to have arguments with spaces in them,
761 but the second is more ``natural'' to type for most people.
763 Note that action names are not case sensitive, but arguments normally
764 are. However, most actions will check for ``keywords'' in a case
767 There are three ways to finish with the command window. If you press
768 the @code{Enter} key, the command is invoked, the window goes away,
769 and the next time you bring up the command window it's empty. If you
770 press the @code{Esc} key, the window goes away without invoking
771 anything, and the next time you bring up the command window it's
772 empty. If you change focus away from the command window (i.e. click
773 on some other window), the command window goes away but the next time
774 you bring it up it resumes entering the command you were entering
780 Command (int argc
, char **argv
, Coord x
, Coord y
)
782 XtManageChild (m_cmd_label
);
783 XtManageChild (m_cmd
);
784 XmProcessTraversal (m_cmd
, XmTRAVERSE_CURRENT
);
788 static const char benchmark_syntax
[] =
791 static const char benchmark_help
[] =
792 "Benchmark the GUI speed.";
794 /* %start-doc actions Benchmark
796 This action is used to speed-test the Lesstif graphics subsystem. It
797 redraws the current screen as many times as possible in ten seconds.
798 It reports the amount of time needed to draw the screen once.
803 Benchmark (int argc
, char **argv
, Coord x
, Coord y
)
810 save_main
= main_pixmap
;
811 main_pixmap
= window
;
815 region
.X2
= PCB
->MaxWidth
;
816 region
.Y2
= PCB
->MaxHeight
;
823 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, view_width
, view_height
);
824 hid_expose_callback (&lesstif_hid
, ®ion
, 0);
829 while (end
- start
< 10);
831 printf ("%g redraws per second\n", i
/ 10.0);
833 main_pixmap
= save_main
;
838 Center(int argc
, char **argv
, Coord x
, Coord y
)
840 x
= GridFit (x
, PCB
->Grid
, PCB
->GridOffsetX
);
841 y
= GridFit (y
, PCB
->Grid
, PCB
->GridOffsetY
);
842 view_left_x
= x
- (view_width
* view_zoom
) / 2;
843 view_top_y
= y
- (view_height
* view_zoom
) / 2;
844 lesstif_pan_fixup ();
845 /* Move the pointer to the center of the window, but only if it's
846 currently within the window already. Watch out for edges,
848 XWarpPointer (display
, window
, window
, 0, 0, view_width
, view_height
,
853 static const char cursor_syntax
[] =
854 "Cursor(Type,DeltaUp,DeltaRight,Units)";
856 static const char cursor_help
[] =
859 /* %start-doc actions Cursor
861 This action moves the mouse cursor. Unlike other actions which take
862 coordinates, this action's coordinates are always relative to the
863 user's view of the board. Thus, a positive @var{DeltaUp} may move the
864 cursor towards the board origin if the board is inverted.
866 Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the
867 viewport to move such that the crosshair is under the mouse cursor.
868 @samp{Warp} causes the mouse cursor to move to be above the crosshair.
870 @var{Units} can be one of the following:
876 The cursor is moved by that amount, in board units.
879 The cursor is moved by that many grid points.
882 The values are percentages of the viewport's view. Thus, a pan of
883 @samp{100} would scroll the viewport by exactly the width of the
887 The values are percentages of the board size. Thus, a move of
888 @samp{50,50} moves you halfway across the board.
895 CursorAction(int argc
, char **argv
, Coord x
, Coord y
)
897 UnitList extra_units_x
= {
898 { "grid", PCB
->Grid
, 0 },
899 { "view", Pz(view_width
), UNIT_PERCENT
},
900 { "board", PCB
->MaxWidth
, UNIT_PERCENT
},
903 UnitList extra_units_y
= {
904 { "grid", PCB
->Grid
, 0 },
905 { "view", Pz(view_height
), UNIT_PERCENT
},
906 { "board", PCB
->MaxHeight
, UNIT_PERCENT
},
909 int pan_warp
= HID_SC_DO_NOTHING
;
915 if (strcasecmp (argv
[0], "pan") == 0)
916 pan_warp
= HID_SC_PAN_VIEWPORT
;
917 else if (strcasecmp (argv
[0], "warp") == 0)
918 pan_warp
= HID_SC_WARP_POINTER
;
922 dx
= GetValueEx (argv
[1], argv
[3], NULL
, extra_units_x
, "mil");
925 dy
= GetValueEx (argv
[2], argv
[3], NULL
, extra_units_y
, "mil");
929 EventMoveCrosshair (Crosshair
.X
+ dx
, Crosshair
.Y
+ dy
);
930 gui
->set_crosshair (Crosshair
.X
, Crosshair
.Y
, pan_warp
);
935 HID_Action lesstif_main_action_list
[] = {
936 {"PCBChanged", 0, PCBChanged
,
937 pcbchanged_help
, pcbchanged_syntax
},
938 {"SetUnits", 0, SetUnits
,
939 setunits_help
, setunits_syntax
},
940 {"Zoom", "Click on a place to zoom in", ZoomAction
,
941 zoom_help
, zoom_syntax
},
942 {"Pan", "Click on a place to pan", PanAction
,
943 zoom_help
, zoom_syntax
},
944 {"SwapSides", 0, SwapSides
,
945 swapsides_help
, swapsides_syntax
},
946 {"Command", 0, Command
,
947 command_help
, command_syntax
},
948 {"Benchmark", 0, Benchmark
,
949 benchmark_help
, benchmark_syntax
},
950 {"PointCursor", 0, PointCursor
},
951 {"Center", "Click on a location to center", Center
},
953 {"Cursor", 0, CursorAction
,
954 cursor_help
, cursor_syntax
},
957 REGISTER_ACTIONS (lesstif_main_action_list
)
960 /* ----------------------------------------------------------------------
961 * redraws the background image
964 static int bg_w
, bg_h
, bgi_w
, bgi_h
;
965 static Pixel
**bg
= 0;
966 static XImage
*bgi
= 0;
971 } pixel_type
= PT_unknown
;
974 LoadBackgroundFile (FILE *f
, char *filename
)
976 XVisualInfo vinfot
, *vinfo
;
980 int p
[3], rows
, cols
, maxval
;
984 printf("bgimage: %s signature not P6\n", filename
);
989 printf("bgimage: %s signature not P6\n", filename
);
999 while (!feof(f
) && b
!= '\n')
1001 } while (!isdigit(b
));
1003 while (isdigit(b
= fgetc(f
)))
1004 p
[i
] = p
[i
]*10 + b
- '0';
1011 bg
= (Pixel
**) malloc (rows
* sizeof (Pixel
*));
1014 printf("Out of memory loading %s\n", filename
);
1017 for (i
=0; i
<rows
; i
++)
1019 bg
[i
] = (Pixel
*) malloc (cols
* sizeof (Pixel
));
1022 printf("Out of memory loading %s\n", filename
);
1031 vis
= DefaultVisual (display
, DefaultScreen(display
));
1033 vinfot
.visualid
= XVisualIDFromVisual(vis
);
1034 vinfo
= XGetVisualInfo (display
, VisualIDMask
, &vinfot
, &nret
);
1037 /* If you want to support more visuals below, you'll probably need
1039 printf("vinfo: rm %04x gm %04x bm %04x depth %d class %d\n",
1040 vinfo
->red_mask
, vinfo
->green_mask
, vinfo
->blue_mask
,
1041 vinfo
->depth
, vinfo
->class);
1044 #if !defined(__cplusplus)
1045 #define c_class class
1048 if (vinfo
->c_class
== TrueColor
1049 && vinfo
->depth
== 16
1050 && vinfo
->red_mask
== 0xf800
1051 && vinfo
->green_mask
== 0x07e0
1052 && vinfo
->blue_mask
== 0x001f)
1053 pixel_type
= PT_RGB565
;
1055 if (vinfo
->c_class
== TrueColor
1056 && vinfo
->depth
== 24
1057 && vinfo
->red_mask
== 0xff0000
1058 && vinfo
->green_mask
== 0x00ff00
1059 && vinfo
->blue_mask
== 0x0000ff)
1060 pixel_type
= PT_RGB888
;
1062 for (r
=0; r
<rows
; r
++)
1064 for (c
=0; c
<cols
; c
++)
1067 unsigned int pr
= (unsigned)fgetc(f
);
1068 unsigned int pg
= (unsigned)fgetc(f
);
1069 unsigned int pb
= (unsigned)fgetc(f
);
1074 pix
.red
= pr
* 65535 / maxval
;
1075 pix
.green
= pg
* 65535 / maxval
;
1076 pix
.blue
= pb
* 65535 / maxval
;
1077 pix
.flags
= DoRed
| DoGreen
| DoBlue
;
1078 XAllocColor (display
, colormap
, &pix
);
1079 bg
[r
][c
] = pix
.pixel
;
1082 bg
[r
][c
] = (pr
>>3)<<11 | (pg
>>2)<<5 | (pb
>>3);
1085 bg
[r
][c
] = (pr
<< 16) | (pg
<< 8) | (pb
);
1093 LoadBackgroundImage (char *filename
)
1095 FILE *f
= fopen(filename
, "rb");
1098 if (NSTRCMP (filename
, "pcb-background.ppm"))
1102 LoadBackgroundFile (f
, filename
);
1107 DrawBackgroundImage ()
1110 double xscale
, yscale
;
1111 int pcbwidth
= PCB
->MaxWidth
/ view_zoom
;
1112 int pcbheight
= PCB
->MaxHeight
/ view_zoom
;
1117 if (!bgi
|| view_width
!= bgi_w
|| view_height
!= bgi_h
)
1120 XDestroyImage (bgi
);
1121 /* Cheat - get the image, which sets up the format too. */
1122 bgi
= XGetImage (XtDisplay(work_area
),
1124 0, 0, view_width
, view_height
,
1127 bgi_h
= view_height
;
1130 w
= MIN (view_width
, pcbwidth
);
1131 h
= MIN (view_height
, pcbheight
);
1133 xscale
= (double)bg_w
/ PCB
->MaxWidth
;
1134 yscale
= (double)bg_h
/ PCB
->MaxHeight
;
1139 int ir
= pr
* yscale
;
1143 int ic
= pc
* xscale
;
1144 XPutPixel (bgi
, x
, y
, bg
[ir
][ic
]);
1147 XPutImage(display
, main_pixmap
, bg_gc
,
1151 /* ---------------------------------------------------------------------- */
1153 static HID_Attribute
*
1154 lesstif_get_export_options (int *n
)
1156 *n
= sizeof (lesstif_attribute_list
) / sizeof (HID_Attribute
);
1157 return lesstif_attribute_list
;
1161 set_scroll (Widget s
, int pos
, int view
, int pcb
)
1163 int sz
= view
* view_zoom
;
1167 stdarg (XmNvalue
, pos
);
1168 stdarg (XmNsliderSize
, sz
);
1169 stdarg (XmNincrement
, view_zoom
);
1170 stdarg (XmNpageIncrement
, sz
);
1171 stdarg (XmNmaximum
, pcb
);
1172 XtSetValues (s
, args
, n
);
1176 lesstif_pan_fixup ()
1179 if (view_left_x
> PCB
->MaxWidth
- (view_width
* view_zoom
))
1180 view_left_x
= PCB
->MaxWidth
- (view_width
* view_zoom
);
1181 if (view_top_y
> PCB
->MaxHeight
- (view_height
* view_zoom
))
1182 view_top_y
= PCB
->MaxHeight
- (view_height
* view_zoom
);
1183 if (view_left_x
< 0)
1187 if (view_width
* view_zoom
> PCB
->MaxWidth
1188 && view_height
* view_zoom
> PCB
->MaxHeight
)
1195 set_scroll (hscroll
, view_left_x
, view_width
, PCB
->MaxWidth
);
1196 set_scroll (vscroll
, view_top_y
, view_height
, PCB
->MaxHeight
);
1198 lesstif_invalidate_all ();
1204 double new_zoom
= PCB
->MaxWidth
/ view_width
;
1205 if (new_zoom
< PCB
->MaxHeight
/ view_height
)
1206 new_zoom
= PCB
->MaxHeight
/ view_height
;
1208 view_left_x
= -(view_width
* new_zoom
- PCB
->MaxWidth
) / 2;
1209 view_top_y
= -(view_height
* new_zoom
- PCB
->MaxHeight
) / 2;
1210 view_zoom
= new_zoom
;
1211 pixel_slop
= view_zoom
;
1212 lesstif_pan_fixup ();
1216 zoom_to (double new_zoom
, int x
, int y
)
1218 double max_zoom
, xfrac
, yfrac
;
1221 xfrac
= (double) x
/ (double) view_width
;
1222 yfrac
= (double) y
/ (double) view_height
;
1229 max_zoom
= PCB
->MaxWidth
/ view_width
;
1230 if (max_zoom
< PCB
->MaxHeight
/ view_height
)
1231 max_zoom
= PCB
->MaxHeight
/ view_height
;
1233 max_zoom
*= MAX_ZOOM_SCALE
;
1237 if (new_zoom
> max_zoom
)
1238 new_zoom
= max_zoom
;
1240 cx
= view_left_x
+ view_width
* xfrac
* view_zoom
;
1241 cy
= view_top_y
+ view_height
* yfrac
* view_zoom
;
1243 if (view_zoom
!= new_zoom
)
1245 view_zoom
= new_zoom
;
1246 pixel_slop
= view_zoom
;
1248 view_left_x
= cx
- view_width
* xfrac
* view_zoom
;
1249 view_top_y
= cy
- view_height
* yfrac
* view_zoom
;
1251 lesstif_pan_fixup ();
1255 zoom_toggle(int x
, int y
)
1259 tmp
= prev_view_zoom
;
1260 prev_view_zoom
= view_zoom
;
1265 zoom_by (double factor
, int x
, int y
)
1267 zoom_to (view_zoom
* factor
, x
, y
);
1270 static int panning
= 0;
1271 static int shift_pressed
;
1272 static int ctrl_pressed
;
1273 static int alt_pressed
;
1275 /* X and Y are in screen coordinates. */
1277 Pan (int mode
, int x
, int y
)
1280 static int opx
, opy
;
1283 /* This is for ctrl-pan, where the viewport's position is directly
1284 proportional to the cursor position in the window (like the Xaw
1288 opx
= x
* PCB
->MaxWidth
/ view_width
;
1289 opy
= y
* PCB
->MaxHeight
/ view_height
;
1291 opx
= PCB
->MaxWidth
- opx
;
1293 opy
= PCB
->MaxHeight
- opy
;
1294 view_left_x
= opx
- view_width
/ 2 * view_zoom
;
1295 view_top_y
= opy
- view_height
/ 2 * view_zoom
;
1296 lesstif_pan_fixup ();
1298 /* This is the start of a regular pan. On the first click, we
1299 remember the coordinates where we "grabbed" the screen. */
1307 /* continued drag, we calculate how far we've moved the cursor and
1308 set the position accordingly. */
1312 view_left_x
= opx
+ (x
- ox
) * view_zoom
;
1314 view_left_x
= opx
- (x
- ox
) * view_zoom
;
1316 view_top_y
= opy
+ (y
- oy
) * view_zoom
;
1318 view_top_y
= opy
- (y
- oy
) * view_zoom
;
1319 lesstif_pan_fixup ();
1324 mod_changed (XKeyEvent
* e
, int set
)
1326 switch (XKeycodeToKeysym (display
, e
->keycode
, 0))
1330 shift_pressed
= set
;
1337 case XK_Mode_switch
:
1345 // to include the Apple keyboard left and right command keys use XK_Meta_L and XK_Meta_R respectivly.
1349 notify_crosshair_change (false);
1351 Pan (2, e
->x
, e
->y
);
1352 EventMoveCrosshair (Px (e
->x
), Py (e
->y
));
1353 AdjustAttachedObjects ();
1354 notify_crosshair_change (true);
1359 work_area_input (Widget w
, XtPointer v
, XEvent
* e
, Boolean
* ctd
)
1361 static int pressed_button
= 0;
1362 static int ignore_release
= 0;
1368 mod_changed (&(e
->xkey
), 1);
1369 if (lesstif_key_event (&(e
->xkey
)))
1374 mod_changed (&(e
->xkey
), 0);
1382 /*printf("click %d\n", e->xbutton.button); */
1383 if (lesstif_button_event (w
, e
))
1390 notify_crosshair_change (false);
1391 pressed_button
= e
->xbutton
.button
;
1392 mods
= ((e
->xbutton
.state
& ShiftMask
) ? M_Shift
: 0)
1393 + ((e
->xbutton
.state
& ControlMask
) ? M_Ctrl
: 0)
1395 + ((e
->xbutton
.state
& (1<<13)) ? M_Alt
: 0);
1397 + ((e
->xbutton
.state
& Mod1Mask
) ? M_Alt
: 0);
1399 do_mouse_action(e
->xbutton
.button
, mods
);
1400 notify_crosshair_change (true);
1407 if (e
->xbutton
.button
!= pressed_button
)
1409 lesstif_button_event (w
, e
);
1410 notify_crosshair_change (false);
1412 mods
= ((e
->xbutton
.state
& ShiftMask
) ? M_Shift
: 0)
1413 + ((e
->xbutton
.state
& ControlMask
) ? M_Ctrl
: 0)
1415 + ((e
->xbutton
.state
& (1<<13)) ? M_Alt
: 0)
1417 + ((e
->xbutton
.state
& Mod1Mask
) ? M_Alt
: 0)
1420 do_mouse_action (e
->xbutton
.button
, mods
);
1421 notify_crosshair_change (true);
1428 unsigned int keys_buttons
;
1429 int root_x
, root_y
, pos_x
, pos_y
;
1430 while (XCheckMaskEvent (display
, PointerMotionMask
, e
));
1431 XQueryPointer (display
, e
->xmotion
.window
, &root
, &child
,
1432 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
1433 shift_pressed
= (keys_buttons
& ShiftMask
);
1434 ctrl_pressed
= (keys_buttons
& ControlMask
);
1436 alt_pressed
= (keys_buttons
& (1<<13));
1438 alt_pressed
= (keys_buttons
& Mod1Mask
);
1440 /*pcb_printf("m %#mS %#mS\n", Px(e->xmotion.x), Py(e->xmotion.y)); */
1441 crosshair_in_window
= 1;
1444 Pan (2, pos_x
, pos_y
);
1445 EventMoveCrosshair (Px (pos_x
), Py (pos_y
));
1451 crosshair_in_window
= 0;
1452 ShowCrosshair (false);
1457 crosshair_in_window
= 1;
1459 EventMoveCrosshair (Px (e
->xcrossing
.x
), Py (e
->xcrossing
.y
));
1460 ShowCrosshair (true);
1466 printf ("work_area: unknown event %d\n", e
->type
);
1472 draw_right_cross (GC xor_gc
, int x
, int y
,
1473 int view_width
, int view_height
)
1475 XDrawLine (display
, window
, xor_gc
, 0, y
, view_width
, y
);
1476 XDrawLine (display
, window
, xor_gc
, x
, 0, x
, view_height
);
1480 draw_slanted_cross (GC xor_gc
, int x
, int y
,
1481 int view_width
, int view_height
)
1485 x0
= x
+ (view_height
- y
);
1486 x0
= MAX(0, MIN (x0
, view_width
));
1488 x1
= MAX(0, MIN (x1
, view_width
));
1489 y0
= y
+ (view_width
- x
);
1490 y0
= MAX(0, MIN (y0
, view_height
));
1492 y1
= MAX(0, MIN (y1
, view_height
));
1493 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1494 x0
= x
- (view_height
- y
);
1495 x0
= MAX(0, MIN (x0
, view_width
));
1497 x1
= MAX(0, MIN (x1
, view_width
));
1499 y0
= MAX(0, MIN (y0
, view_height
));
1500 y1
= y
- (view_width
- x
);
1501 y1
= MAX(0, MIN (y1
, view_height
));
1502 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1506 draw_dozen_cross (GC xor_gc
, int x
, int y
,
1507 int view_width
, int view_height
)
1510 double tan60
= sqrt (3);
1512 x0
= x
+ (view_height
- y
) / tan60
;
1513 x0
= MAX(0, MIN (x0
, view_width
));
1515 x1
= MAX(0, MIN (x1
, view_width
));
1516 y0
= y
+ (view_width
- x
) * tan60
;
1517 y0
= MAX(0, MIN (y0
, view_height
));
1519 y1
= MAX(0, MIN (y1
, view_height
));
1520 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1522 x0
= x
+ (view_height
- y
) * tan60
;
1523 x0
= MAX(0, MIN (x0
, view_width
));
1525 x1
= MAX(0, MIN (x1
, view_width
));
1526 y0
= y
+ (view_width
- x
) / tan60
;
1527 y0
= MAX(0, MIN (y0
, view_height
));
1529 y1
= MAX(0, MIN (y1
, view_height
));
1530 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1532 x0
= x
- (view_height
- y
) / tan60
;
1533 x0
= MAX(0, MIN (x0
, view_width
));
1535 x1
= MAX(0, MIN (x1
, view_width
));
1537 y0
= MAX(0, MIN (y0
, view_height
));
1538 y1
= y
- (view_width
- x
) * tan60
;
1539 y1
= MAX(0, MIN (y1
, view_height
));
1540 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1542 x0
= x
- (view_height
- y
) * tan60
;
1543 x0
= MAX(0, MIN (x0
, view_width
));
1545 x1
= MAX(0, MIN (x1
, view_width
));
1547 y0
= MAX(0, MIN (y0
, view_height
));
1548 y1
= y
- (view_width
- x
) / tan60
;
1549 y1
= MAX(0, MIN (y1
, view_height
));
1550 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1554 draw_crosshair (GC xor_gc
, int x
, int y
,
1555 int view_width
, int view_height
)
1557 draw_right_cross (xor_gc
, x
, y
, view_width
, view_height
);
1558 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
1559 draw_slanted_cross (xor_gc
, x
, y
, view_width
, view_height
);
1560 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
1561 draw_dozen_cross (xor_gc
, x
, y
, view_width
, view_height
);
1564 lesstif_show_crosshair (int show
)
1566 static int showing
= 0;
1568 static GC xor_gc
= 0;
1569 Pixel crosshair_color
;
1571 if (!crosshair_in_window
|| !window
)
1575 crosshair_color
= lesstif_parse_color (Settings
.CrosshairColor
) ^ bgcolor
;
1576 xor_gc
= XCreateGC (display
, window
, 0, 0);
1577 XSetFunction (display
, xor_gc
, GXxor
);
1578 XSetForeground (display
, xor_gc
, crosshair_color
);
1580 if (show
== showing
)
1584 sx
= Vx (crosshair_x
);
1585 sy
= Vy (crosshair_y
);
1589 draw_crosshair (xor_gc
, sx
, sy
, view_width
, view_height
);
1594 work_area_expose (Widget work_area
, void *me
,
1595 XmDrawingAreaCallbackStruct
* cbs
)
1600 e
= &(cbs
->event
->xexpose
);
1601 XSetFunction (display
, my_gc
, GXcopy
);
1602 XCopyArea (display
, main_pixmap
, window
, my_gc
,
1603 e
->x
, e
->y
, e
->width
, e
->height
, e
->x
, e
->y
);
1608 scroll_callback (Widget scroll
, int *view_dim
,
1609 XmScrollBarCallbackStruct
* cbs
)
1611 *view_dim
= cbs
->value
;
1612 lesstif_invalidate_all ();
1616 work_area_make_pixmaps (Dimension width
, Dimension height
)
1619 XFreePixmap (display
, main_pixmap
);
1621 XCreatePixmap (display
, window
, width
, height
,
1622 XDefaultDepth (display
, screen
));
1625 XFreePixmap (display
, mask_pixmap
);
1627 XCreatePixmap (display
, window
, width
, height
,
1628 XDefaultDepth (display
, screen
));
1632 XRenderFreePicture (display
, main_picture
);
1637 XRenderFreePicture (display
, mask_picture
);
1642 main_picture
= XRenderCreatePicture (display
, main_pixmap
,
1643 XRenderFindVisualFormat(display
,
1644 DefaultVisual(display
, screen
)), 0, 0);
1645 mask_picture
= XRenderCreatePicture (display
, mask_pixmap
,
1646 XRenderFindVisualFormat(display
,
1647 DefaultVisual(display
, screen
)), 0, 0);
1648 if (!main_picture
|| !mask_picture
)
1651 #endif /* HAVE_XRENDER */
1654 XFreePixmap (display
, mask_bitmap
);
1655 mask_bitmap
= XCreatePixmap (display
, window
, width
, height
, 1);
1657 pixmap
= use_mask
? main_pixmap
: mask_pixmap
;
1663 work_area_resize (Widget work_area
, void *me
,
1664 XmDrawingAreaCallbackStruct
* cbs
)
1667 Dimension width
, height
;
1672 stdarg (XtNwidth
, &width
);
1673 stdarg (XtNheight
, &height
);
1674 stdarg (XmNbackground
, &bgcolor
);
1675 XtGetValues (work_area
, args
, n
);
1677 view_height
= height
;
1679 color
.pixel
= bgcolor
;
1680 XQueryColor (display
, colormap
, &color
);
1682 bggreen
= color
.green
;
1683 bgblue
= color
.blue
;
1688 work_area_make_pixmaps (view_width
, view_height
);
1694 work_area_first_expose (Widget work_area
, void *me
,
1695 XmDrawingAreaCallbackStruct
* cbs
)
1698 Dimension width
, height
;
1699 static char dashes
[] = { 4, 4 };
1701 window
= XtWindow (work_area
);
1702 my_gc
= XCreateGC (display
, window
, 0, 0);
1704 arc1_gc
= XCreateGC (display
, window
, 0, 0);
1705 c
= lesstif_parse_color ("#804000");
1706 XSetForeground (display
, arc1_gc
, c
);
1707 arc2_gc
= XCreateGC (display
, window
, 0, 0);
1708 c
= lesstif_parse_color ("#004080");
1709 XSetForeground (display
, arc2_gc
, c
);
1710 XSetLineAttributes (display
, arc1_gc
, 1, LineOnOffDash
, 0, 0);
1711 XSetLineAttributes (display
, arc2_gc
, 1, LineOnOffDash
, 0, 0);
1712 XSetDashes (display
, arc1_gc
, 0, dashes
, 2);
1713 XSetDashes (display
, arc2_gc
, 0, dashes
, 2);
1716 stdarg (XtNwidth
, &width
);
1717 stdarg (XtNheight
, &height
);
1718 stdarg (XmNbackground
, &bgcolor
);
1719 XtGetValues (work_area
, args
, n
);
1721 view_height
= height
;
1723 offlimit_color
= lesstif_parse_color (Settings
.OffLimitColor
);
1724 grid_color
= lesstif_parse_color (Settings
.GridColor
);
1726 bg_gc
= XCreateGC (display
, window
, 0, 0);
1727 XSetForeground (display
, bg_gc
, bgcolor
);
1729 work_area_make_pixmaps (width
, height
);
1734 XRenderPictureAttributes pa
;
1735 XRenderColor a
= {0, 0, 0, 0x8000};
1737 pale_pixmap
= XCreatePixmap (display
, window
, 1, 1, 8);
1739 pale_picture
= XRenderCreatePicture (display
, pale_pixmap
,
1740 XRenderFindStandardFormat(display
, PictStandardA8
),
1743 XRenderFillRectangle(display
, PictOpSrc
, pale_picture
, &a
, 0, 0, 1, 1);
1747 #endif /* HAVE_XRENDER */
1749 clip_gc
= XCreateGC (display
, window
, 0, 0);
1750 bset_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1751 XSetForeground (display
, bset_gc
, 1);
1752 bclear_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1753 XSetForeground (display
, bclear_gc
, 0);
1755 XtRemoveCallback (work_area
, XmNexposeCallback
,
1756 (XtCallbackProc
) work_area_first_expose
, 0);
1757 XtAddCallback (work_area
, XmNexposeCallback
,
1758 (XtCallbackProc
) work_area_expose
, 0);
1759 lesstif_invalidate_all ();
1763 make_message (char *name
, Widget left
, int resizeable
)
1769 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1770 stdarg (XmNleftWidget
, XtParent(left
));
1774 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1776 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1777 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1778 stdarg (XmNshadowType
, XmSHADOW_IN
);
1779 stdarg (XmNshadowThickness
, 1);
1780 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1781 stdarg (XmNmarginWidth
, 4);
1782 stdarg (XmNmarginHeight
, 1);
1784 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
1785 f
= XmCreateForm (messages
, name
, args
, n
);
1788 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1789 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1790 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1791 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1792 w
= XmCreateLabel (f
, name
, args
, n
);
1798 lesstif_do_export (HID_Attr_Val
* options
)
1800 Dimension width
, height
;
1802 Widget work_area_frame
;
1805 stdarg (XtNwidth
, &width
);
1806 stdarg (XtNheight
, &height
);
1807 XtGetValues (appwidget
, args
, n
);
1811 if (width
> XDisplayWidth (display
, screen
))
1812 width
= XDisplayWidth (display
, screen
);
1815 if (height
> XDisplayHeight (display
, screen
))
1816 height
= XDisplayHeight (display
, screen
);
1819 stdarg (XmNwidth
, width
);
1820 stdarg (XmNheight
, height
);
1821 XtSetValues (appwidget
, args
, n
);
1823 stdarg (XmNspacing
, 0);
1824 mainwind
= XmCreateMainWindow (appwidget
, "mainWind", args
, n
);
1825 XtManageChild (mainwind
);
1828 stdarg (XmNmarginWidth
, 0);
1829 stdarg (XmNmarginHeight
, 0);
1830 menu
= lesstif_menu (mainwind
, "menubar", args
, n
);
1831 XtManageChild (menu
);
1834 stdarg (XmNshadowType
, XmSHADOW_IN
);
1836 XmCreateFrame (mainwind
, "work_area_frame", args
, n
);
1837 XtManageChild (work_area_frame
);
1840 do_color (Settings
.BackgroundColor
, XmNbackground
);
1841 work_area
= XmCreateDrawingArea (work_area_frame
, "work_area", args
, n
);
1842 XtManageChild (work_area
);
1843 XtAddCallback (work_area
, XmNexposeCallback
,
1844 (XtCallbackProc
) work_area_first_expose
, 0);
1845 XtAddCallback (work_area
, XmNresizeCallback
,
1846 (XtCallbackProc
) work_area_resize
, 0);
1847 /* A regular callback won't work here, because lesstif swallows any
1848 Ctrl<Button>1 event. */
1849 XtAddEventHandler (work_area
,
1850 ButtonPressMask
| ButtonReleaseMask
1851 | PointerMotionMask
| PointerMotionHintMask
1852 | KeyPressMask
| KeyReleaseMask
1853 | EnterWindowMask
| LeaveWindowMask
,
1854 0, work_area_input
, 0);
1857 stdarg (XmNorientation
, XmVERTICAL
);
1858 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
1859 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
1860 vscroll
= XmCreateScrollBar (mainwind
, "vscroll", args
, n
);
1861 XtAddCallback (vscroll
, XmNvalueChangedCallback
,
1862 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_top_y
);
1863 XtAddCallback (vscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1864 (XtPointer
) & view_top_y
);
1865 XtManageChild (vscroll
);
1868 stdarg (XmNorientation
, XmHORIZONTAL
);
1869 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
1870 hscroll
= XmCreateScrollBar (mainwind
, "hscroll", args
, n
);
1871 XtAddCallback (hscroll
, XmNvalueChangedCallback
,
1872 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_left_x
);
1873 XtAddCallback (hscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1874 (XtPointer
) & view_left_x
);
1875 XtManageChild (hscroll
);
1878 stdarg (XmNresize
, True
);
1879 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
1880 messages
= XmCreateForm (mainwind
, "messages", args
, n
);
1881 XtManageChild (messages
);
1884 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1885 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1886 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1887 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1888 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1889 stdarg (XmNshadowThickness
, 2);
1890 m_click
= XmCreateLabel (messages
, "click", args
, n
);
1893 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1894 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1895 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1896 stdarg (XmNlabelString
, XmStringCreatePCB ("Command: "));
1897 m_cmd_label
= XmCreateLabel (messages
, "command", args
, n
);
1900 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1901 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1902 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1903 stdarg (XmNleftWidget
, m_cmd_label
);
1904 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1905 stdarg (XmNshadowThickness
, 1);
1906 stdarg (XmNhighlightThickness
, 0);
1907 stdarg (XmNmarginWidth
, 2);
1908 stdarg (XmNmarginHeight
, 2);
1909 m_cmd
= XmCreateTextField (messages
, "command", args
, n
);
1910 XtAddCallback (m_cmd
, XmNactivateCallback
,
1911 (XtCallbackProc
) command_callback
, 0);
1912 XtAddCallback (m_cmd
, XmNlosingFocusCallback
,
1913 (XtCallbackProc
) command_callback
, 0);
1914 XtAddEventHandler (m_cmd
, KeyPressMask
, 0, command_event_handler
, 0);
1916 m_mark
= make_message ("m_mark", 0, 0);
1917 m_crosshair
= make_message ("m_crosshair", m_mark
, 0);
1918 m_grid
= make_message ("m_grid", m_crosshair
, 1);
1919 m_zoom
= make_message ("m_zoom", m_grid
, 1);
1920 lesstif_m_layer
= make_message ("m_layer", m_zoom
, 0);
1921 m_mode
= make_message ("m_mode", lesstif_m_layer
, 1);
1922 m_rats
= make_message ("m_rats", m_mode
, 1);
1923 m_status
= make_message ("m_status", m_mode
, 1);
1925 XtUnmanageChild (XtParent (m_mark
));
1926 XtUnmanageChild (XtParent (m_rats
));
1929 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1930 XtSetValues (XtParent (m_status
), args
, n
);
1932 /* We'll use this later. */
1934 stdarg (XmNleftWidget
, XtParent (m_mark
));
1935 XtSetValues (XtParent (m_crosshair
), args
, n
);
1938 stdarg (XmNmessageWindow
, messages
);
1939 XtSetValues (mainwind
, args
, n
);
1941 if (background_image_file
)
1942 LoadBackgroundImage (background_image_file
);
1944 XtRealizeWidget (appwidget
);
1949 XtAppNextEvent (app_context
, &e
);
1950 XtDispatchEvent (&e
);
1953 PCBChanged (0, 0, 0, 0);
1955 XtAppMainLoop (app_context
);
1959 XrmOptionDescRec lesstif_options
[] = {
1962 XtResource lesstif_resources
[] = {
1975 pcb_cvt_string_to_double (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
1976 XrmValue
* from
, XrmValue
* to
, XtPointer
* data
)
1979 rv
= strtod ((char *) from
->addr
, 0);
1981 *(double *) to
->addr
= rv
;
1983 to
->addr
= (XPointer
) & rv
;
1984 to
->size
= sizeof (rv
);
1989 pcb_cvt_string_to_coord (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
1990 XrmValue
* from
, XrmValue
* to
, XtPointer
*data
)
1993 rv
= GetValue ((char *) from
->addr
, NULL
, NULL
);
1995 *(Coord
*) to
->addr
= rv
;
1997 to
->addr
= (XPointer
) &rv
;
1998 to
->size
= sizeof (rv
);
2003 mainwind_delete_cb ()
2005 hid_action ("Quit");
2009 lesstif_listener_cb (XtPointer client_data
, int *fid
, XtInputId
*id
)
2014 if ((nbytes
= read (*fid
, buf
, BUFSIZ
)) == -1)
2015 perror ("lesstif_listener_cb");
2020 hid_parse_actions (buf
);
2025 lesstif_parse_arguments (int *argc
, char ***argv
)
2029 int acount
= 0, amax
;
2030 int rcount
= 0, rmax
;
2032 XrmOptionDescRec
*new_options
;
2033 XtResource
*new_resources
;
2034 val_union
*new_values
;
2035 int render_event
, render_error
;
2037 XtSetTypeConverter (XtRString
,
2039 pcb_cvt_string_to_double
, NULL
, 0, XtCacheAll
, NULL
);
2040 XtSetTypeConverter (XtRString
,
2042 pcb_cvt_string_to_coord
, NULL
, 0, XtCacheAll
, NULL
);
2045 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2046 for (i
= 0; i
< ha
->n
; i
++)
2048 HID_Attribute
*a
= ha
->attributes
+ i
;
2066 amax
= acount
+ XtNumber (lesstif_options
);
2071 new_options
= (XrmOptionDescRec
*) malloc ((amax
+ 1) * sizeof (XrmOptionDescRec
));
2074 memcpy (new_options
+ acount
, lesstif_options
, sizeof (lesstif_options
));
2079 rmax
= rcount
+ XtNumber (lesstif_resources
);
2084 new_resources
= (XtResource
*) malloc ((rmax
+ 1) * sizeof (XtResource
));
2085 new_values
= (val_union
*) malloc ((rmax
+ 1) * sizeof (val_union
));
2087 memcpy (new_resources
+ acount
, lesstif_resources
,
2088 sizeof (lesstif_resources
));
2092 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2093 for (i
= 0; i
< ha
->n
; i
++)
2095 HID_Attribute
*a
= ha
->attributes
+ i
;
2096 XrmOptionDescRec
*o
= new_options
+ acount
;
2097 char *tmpopt
, *tmpres
;
2098 XtResource
*r
= new_resources
+ rcount
;
2100 tmpopt
= (char *) malloc (strlen (a
->name
) + 3);
2101 tmpopt
[0] = tmpopt
[1] = '-';
2102 strcpy (tmpopt
+ 2, a
->name
);
2105 tmpres
= (char *) malloc (strlen (a
->name
) + 2);
2107 strcpy (tmpres
+ 1, a
->name
);
2108 o
->specifier
= tmpres
;
2117 o
->argKind
= XrmoptionSepArg
;
2122 o
->argKind
= XrmoptionNoArg
;
2130 r
->resource_name
= a
->name
;
2131 r
->resource_class
= a
->name
;
2132 r
->resource_offset
= sizeof (val_union
) * rcount
;
2137 r
->resource_type
= XtRInt
;
2138 r
->default_type
= XtRInt
;
2139 r
->resource_size
= sizeof (int);
2140 r
->default_addr
= &(a
->default_val
.int_value
);
2144 r
->resource_type
= XtRPCBCoord
;
2145 r
->default_type
= XtRPCBCoord
;
2146 r
->resource_size
= sizeof (Coord
);
2147 r
->default_addr
= &(a
->default_val
.coord_value
);
2151 r
->resource_type
= XtRDouble
;
2152 r
->default_type
= XtRDouble
;
2153 r
->resource_size
= sizeof (double);
2154 r
->default_addr
= &(a
->default_val
.real_value
);
2159 r
->resource_type
= XtRString
;
2160 r
->default_type
= XtRString
;
2161 r
->resource_size
= sizeof (char *);
2162 r
->default_addr
= (char *) a
->default_val
.str_value
;
2166 r
->resource_type
= XtRBoolean
;
2167 r
->default_type
= XtRInt
;
2168 r
->resource_size
= sizeof (int);
2169 r
->default_addr
= &(a
->default_val
.int_value
);
2177 for (i
= 0; i
< XtNumber (lesstif_resources
); i
++)
2179 XtResource
*r
= new_resources
+ rcount
;
2180 r
->resource_offset
= sizeof (val_union
) * rcount
;
2186 stdarg (XmNdeleteResponse
, XmDO_NOTHING
);
2188 appwidget
= XtAppInitialize (&app_context
,
2190 new_options
, amax
, argc
, *argv
, 0, args
, n
);
2192 display
= XtDisplay (appwidget
);
2193 screen_s
= XtScreen (appwidget
);
2194 screen
= XScreenNumberOfScreen (screen_s
);
2195 colormap
= XDefaultColormap (display
, screen
);
2197 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
2198 XmAddWMProtocolCallback (appwidget
, close_atom
,
2199 (XtCallbackProc
) mainwind_delete_cb
, 0);
2201 /* XSynchronize(display, True); */
2203 XtGetApplicationResources (appwidget
, new_values
, new_resources
,
2207 use_xrender
= XRenderQueryExtension (display
, &render_event
, &render_error
) &&
2208 XRenderFindVisualFormat (display
, DefaultVisual(display
, screen
));
2209 #ifdef HAVE_XINERAMA
2210 /* Xinerama and XRender don't get along well */
2211 if (XineramaQueryExtension (display
, &render_event
, &render_error
)
2212 && XineramaIsActive (display
))
2214 #endif /* HAVE_XINERAMA */
2215 #endif /* HAVE_XRENDER */
2218 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2219 for (i
= 0; i
< ha
->n
; i
++)
2221 HID_Attribute
*a
= ha
->attributes
+ i
;
2222 val_union
*v
= new_values
+ rcount
;
2227 *(int *) a
->value
= v
->i
;
2229 a
->default_val
.int_value
= v
->i
;
2234 *(Coord
*) a
->value
= v
->c
;
2236 a
->default_val
.coord_value
= v
->c
;
2241 *(char *) a
->value
= v
->i
;
2243 a
->default_val
.int_value
= v
->i
;
2248 *(double *) a
->value
= v
->f
;
2250 a
->default_val
.real_value
= v
->f
;
2256 *(char **) a
->value
= v
->s
;
2258 a
->default_val
.str_value
= v
->s
;
2266 /* redefine colormap, if requested via "-install" */
2267 if (use_private_colormap
)
2269 colormap
= XCopyColormapAndFree (display
, colormap
);
2270 XtVaSetValues (appwidget
, XtNcolormap
, colormap
, NULL
);
2273 /* listen on standard input for actions */
2276 XtAppAddInput (app_context
, fileno (stdin
), (XtPointer
) XtInputReadMask
,
2277 lesstif_listener_cb
, NULL
);
2284 static XPoint
*points
= 0;
2285 static int npoints
= 0;
2286 Coord x1
, y1
, x2
, y2
, prevx
;
2289 static GC grid_gc
= 0;
2291 if (!Settings
.DrawGrid
)
2293 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
2297 grid_gc
= XCreateGC (display
, window
, 0, 0);
2298 XSetFunction (display
, grid_gc
, GXxor
);
2299 XSetForeground (display
, grid_gc
, grid_color
);
2303 x2
= GridFit (Px (0), PCB
->Grid
, PCB
->GridOffsetX
);
2304 x1
= GridFit (Px (view_width
), PCB
->Grid
, PCB
->GridOffsetX
);
2307 if (Vx (x1
) >= view_width
)
2312 x1
= GridFit (Px (0), PCB
->Grid
, PCB
->GridOffsetX
);
2313 x2
= GridFit (Px (view_width
), PCB
->Grid
, PCB
->GridOffsetX
);
2316 if (Vx (x2
) >= view_width
)
2321 y2
= GridFit (Py (0), PCB
->Grid
, PCB
->GridOffsetY
);
2322 y1
= GridFit (Py (view_height
), PCB
->Grid
, PCB
->GridOffsetY
);
2325 if (Vy (y1
) >= view_height
)
2330 y1
= GridFit (Py (0), PCB
->Grid
, PCB
->GridOffsetY
);
2331 y2
= GridFit (Py (view_height
), PCB
->Grid
, PCB
->GridOffsetY
);
2334 if (Vy (y2
) >= view_height
)
2337 n
= (x2
- x1
) / PCB
->Grid
+ 1;
2341 points
= (XPoint
*) realloc (points
, npoints
* sizeof (XPoint
));
2345 for (x
= x1
; x
<= x2
; x
+= PCB
->Grid
)
2351 points
[n
].x
-= prevx
;
2357 for (y
= y1
; y
<= y2
; y
+= PCB
->Grid
)
2361 XDrawPoints (display
, pixmap
, grid_gc
, points
, n
, CoordModePrevious
);
2366 mark_delta_to_widget (Coord dx
, Coord dy
, Widget w
)
2369 double g
= coord_to_unit (Settings
.grid_unit
, PCB
->Grid
);
2373 /* Integer-sized grid? */
2374 if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2377 prec
= Settings
.grid_unit
->default_prec
;
2379 if (dx
== 0 && dy
== 0)
2380 buf
= pcb_g_strdup_printf ("%m+%+.*mS, %+.*mS", UUNIT
, prec
, dx
, prec
, dy
);
2383 Angle angle
= atan2 (dy
, -dx
) * 180 / M_PI
;
2384 Coord dist
= Distance (0, 0, dx
, dy
);
2386 buf
= pcb_g_strdup_printf ("%m+%+.*mS, %+.*mS (%.*mS, %d\260)", UUNIT
,
2387 prec
, dx
, prec
, dy
, prec
, dist
, angle
);
2390 ms
= XmStringCreatePCB (buf
);
2392 stdarg (XmNlabelString
, ms
);
2393 XtSetValues (w
, args
, n
);
2398 cursor_pos_to_widget (Coord x
, Coord y
, Widget w
, int prev_state
)
2400 int this_state
= prev_state
;
2402 double g
= coord_to_unit (Settings
.grid_unit
, PCB
->Grid
);
2406 /* Determine necessary precision (and state) based
2407 * on the user's grid setting */
2408 if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2411 this_state
= Settings
.grid_unit
->allow
;
2415 prec
= Settings
.grid_unit
->default_prec
;
2416 this_state
= -Settings
.grid_unit
->allow
;
2420 buf
= g_strdup ("");
2422 buf
= pcb_g_strdup_printf ("%m+%.*mS, %.*mS", UUNIT
, prec
, x
, prec
, y
);
2424 ms
= XmStringCreatePCB (buf
);
2426 stdarg (XmNlabelString
, ms
);
2427 XtSetValues (w
, args
, n
);
2435 lesstif_update_status_line ()
2438 char *s45
= cur_clip ();
2441 switch (Settings
.Mode
)
2444 buf
= pcb_g_strdup_printf ("%m+%.2mS/%.2mS \370=%.2mS", UUNIT
,
2445 S
.ViaThickness
, S
.Keepaway
, S
.ViaDrillingHole
);
2449 buf
= pcb_g_strdup_printf ("%m+%.2mS/%.2mS %s", UUNIT
,
2450 S
.LineThickness
, S
.Keepaway
, s45
);
2452 case RECTANGLE_MODE
:
2454 buf
= pcb_g_strdup_printf ("%m+%.2mS %s", UUNIT
, S
.Keepaway
, s45
);
2457 buf
= g_strdup_printf ("%d %%", S
.TextScale
);
2461 case INSERTPOINT_MODE
:
2462 case RUBBERBANDMOVE_MODE
:
2463 buf
= g_strdup_printf ("%s", s45
);
2466 case PASTEBUFFER_MODE
:
2477 xs
= XmStringCreatePCB (buf
);
2479 stdarg (XmNlabelString
, xs
);
2480 XtSetValues (m_status
, args
, n
);
2486 static int idle_proc_set
= 0;
2487 static int need_redraw
= 0;
2490 idle_proc (XtPointer dummy
)
2496 lesstif_use_mask (0);
2497 pixmap
= main_pixmap
;
2502 region
.X2
= Px (view_width
);
2503 region
.Y2
= Py (view_height
);
2506 Coord tmp
= region
.X1
;
2507 region
.X1
= region
.X2
;
2512 Coord tmp
= region
.Y1
;
2513 region
.Y1
= region
.Y2
;
2516 XSetForeground (display
, bg_gc
, bgcolor
);
2517 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0, mx
, my
);
2519 if (region
.X1
< 0 || region
.Y1
< 0
2520 || region
.X2
> PCB
->MaxWidth
|| region
.Y2
> PCB
->MaxHeight
)
2522 int leftmost
, rightmost
, topmost
, bottommost
;
2525 rightmost
= Vx (PCB
->MaxWidth
);
2527 bottommost
= Vy (PCB
->MaxHeight
);
2528 if (leftmost
> rightmost
) {
2530 leftmost
= rightmost
;
2533 if (topmost
> bottommost
) {
2535 topmost
= bottommost
;
2542 if (rightmost
> view_width
)
2543 rightmost
= view_width
;
2544 if (bottommost
> view_height
)
2545 bottommost
= view_height
;
2547 XSetForeground (display
, bg_gc
, offlimit_color
);
2555 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0,
2556 leftmost
, view_height
);
2558 if (rightmost
< view_width
)
2560 XFillRectangle (display
, main_pixmap
, bg_gc
, rightmost
+1, 0,
2561 view_width
-rightmost
+1, view_height
);
2565 XFillRectangle (display
, main_pixmap
, bg_gc
, leftmost
, 0,
2566 rightmost
-leftmost
+1, topmost
);
2568 if (bottommost
< view_height
)
2570 XFillRectangle (display
, main_pixmap
, bg_gc
, leftmost
, bottommost
+1,
2571 rightmost
-leftmost
+1, view_height
-bottommost
+1);
2574 DrawBackgroundImage();
2575 hid_expose_callback (&lesstif_hid
, ®ion
, 0);
2577 lesstif_use_mask (0);
2578 show_crosshair (0); /* To keep the drawn / not drawn info correct */
2579 XSetFunction (display
, my_gc
, GXcopy
);
2580 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
2592 static int c_x
= -2, c_y
= -2;
2593 static MarkType saved_mark
;
2594 static const Unit
*old_grid_unit
= NULL
;
2595 if (crosshair_x
!= c_x
|| crosshair_y
!= c_y
2596 || Settings
.grid_unit
!= old_grid_unit
2597 || memcmp (&saved_mark
, &Marked
, sizeof (MarkType
)))
2599 static int last_state
= 0;
2600 static int this_state
= 0;
2606 cursor_pos_to_widget (crosshair_x
, crosshair_y
, m_crosshair
,
2609 mark_delta_to_widget (crosshair_x
- Marked
.X
, crosshair_y
- Marked
.Y
,
2612 if (Marked
.status
!= saved_mark
.status
)
2616 XtManageChild (XtParent (m_mark
));
2617 XtManageChild (m_mark
);
2619 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
2620 stdarg (XmNleftWidget
, XtParent (m_mark
));
2621 XtSetValues (XtParent (m_crosshair
), args
, n
);
2626 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
2627 XtSetValues (XtParent (m_crosshair
), args
, n
);
2628 XtUnmanageChild (XtParent (m_mark
));
2630 last_state
= this_state
+ 100;
2632 memcpy (&saved_mark
, &Marked
, sizeof (MarkType
));
2634 if (old_grid_unit
!= Settings
.grid_unit
)
2636 old_grid_unit
= Settings
.grid_unit
;
2637 /* Force a resize on units change. */
2641 /* This is obtuse. We want to enable XmRESIZE_ANY long enough
2642 to shrink to fit the new format (if any), then switch it
2643 back to XmRESIZE_GROW to prevent it from shrinking due to
2644 changes in the number of actual digits printed. Thus, when
2645 you switch from a small grid and %.2f formats to a large
2646 grid and %d formats, you aren't punished with a wide and
2647 mostly white-space label widget. "this_state" indicates
2648 which of the above formats we're using. "last_state" is
2649 either zero (when resizing) or the same as "this_state"
2650 (when grow-only), or a non-zero but not "this_state" which
2651 means we need to start a resize cycle. */
2652 if (this_state
!= last_state
&& last_state
)
2655 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
2656 XtSetValues (XtParent (m_mark
), args
, n
);
2657 XtSetValues (XtParent (m_crosshair
), args
, n
);
2660 else if (this_state
!= last_state
)
2663 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
2664 XtSetValues (XtParent (m_mark
), args
, n
);
2665 XtSetValues (XtParent (m_crosshair
), args
, n
);
2666 last_state
= this_state
;
2672 static Coord old_grid
= -1;
2673 static Coord old_gx
, old_gy
;
2674 static const Unit
*old_unit
;
2676 if (PCB
->Grid
!= old_grid
2677 || PCB
->GridOffsetX
!= old_gx
2678 || PCB
->GridOffsetY
!= old_gy
|| Settings
.grid_unit
!= old_unit
)
2680 static char buf
[100];
2681 old_grid
= PCB
->Grid
;
2682 old_unit
= Settings
.grid_unit
;
2683 old_gx
= PCB
->GridOffsetX
;
2684 old_gy
= PCB
->GridOffsetY
;
2687 strcpy (buf
, "No Grid");
2691 if (old_gx
|| old_gy
)
2692 pcb_sprintf (buf
, "%m+%$mS @%mS,%mS", UUNIT
, old_grid
, old_gx
, old_gy
);
2694 pcb_sprintf (buf
, "%m+%$mS", UUNIT
, old_grid
);
2696 ms
= XmStringCreatePCB (buf
);
2698 stdarg (XmNlabelString
, ms
);
2699 XtSetValues (m_grid
, args
, n
);
2704 static double old_zoom
= -1;
2705 static const Unit
*old_grid_unit
= NULL
;
2706 if (view_zoom
!= old_zoom
|| Settings
.grid_unit
!= old_grid_unit
)
2708 gchar
*buf
= pcb_g_strdup_printf ("%m+%$mS/pix",
2709 Settings
.grid_unit
->allow
, (Coord
) view_zoom
);
2712 old_zoom
= view_zoom
;
2713 old_grid_unit
= Settings
.grid_unit
;
2715 ms
= XmStringCreatePCB (buf
);
2717 stdarg (XmNlabelString
, ms
);
2718 XtSetValues (m_zoom
, args
, n
);
2724 if (old_cursor_mode
!= Settings
.Mode
)
2729 static int free_cursor
= 0;
2731 old_cursor_mode
= Settings
.Mode
;
2732 switch (Settings
.Mode
)
2736 cursor
= XC_X_cursor
;
2746 case RECTANGLE_MODE
:
2748 cursor
= XC_ul_angle
;
2752 cursor
= XC_sb_up_arrow
;
2754 case POLYGONHOLE_MODE
:
2756 cursor
= XC_sb_up_arrow
;
2758 case PASTEBUFFER_MODE
:
2768 cursor
= XC_exchange
;
2776 cursor
= XC_crosshair
;
2780 cursor
= XC_crosshair
;
2782 case INSERTPOINT_MODE
:
2786 case RUBBERBANDMOVE_MODE
:
2788 cursor
= XC_top_left_corner
;
2792 cursor
= XC_iron_cross
;
2796 cursor
= XC_question_arrow
;
2801 cursor
= XC_draped_box
;
2803 cursor
= XC_left_ptr
;
2810 ms
= XmStringCreatePCB (s
);
2812 stdarg (XmNlabelString
, ms
);
2813 XtSetValues (m_mode
, args
, n
);
2817 XFreeCursor (display
, my_cursor
);
2822 static Pixmap nocur_source
= 0;
2823 static Pixmap nocur_mask
= 0;
2824 static Cursor nocursor
= 0;
2825 if (nocur_source
== 0)
2829 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2831 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2833 fg
.red
= fg
.green
= fg
.blue
= 65535;
2834 bg
.red
= bg
.green
= bg
.blue
= 0;
2835 fg
.flags
= bg
.flags
= DoRed
| DoGreen
| DoBlue
;
2836 nocursor
= XCreatePixmapCursor (display
, nocur_source
,
2837 nocur_mask
, &fg
, &bg
, 0, 0);
2839 my_cursor
= nocursor
;
2843 my_cursor
= XCreateFontCursor (display
, cursor
);
2846 XDefineCursor (display
, window
, my_cursor
);
2847 lesstif_update_status_line ();
2851 static char *old_clip
= 0;
2852 static int old_tscale
= -1;
2853 char *new_clip
= cur_clip ();
2855 if (new_clip
!= old_clip
|| Settings
.TextScale
!= old_tscale
)
2857 lesstif_update_status_line ();
2858 old_clip
= new_clip
;
2859 old_tscale
= Settings
.TextScale
;
2864 static int old_nrats
= -1;
2865 static char buf
[20];
2867 if (old_nrats
!= PCB
->Data
->RatN
)
2869 old_nrats
= PCB
->Data
->RatN
;
2870 sprintf(buf
, "%d rat%s", PCB
->Data
->RatN
, PCB
->Data
->RatN
== 1 ? "" : "s");
2871 if (PCB
->Data
->RatN
)
2873 XtManageChild(XtParent(m_rats
));
2874 XtManageChild(m_rats
);
2876 stdarg (XmNleftWidget
, m_rats
);
2877 XtSetValues (XtParent (m_status
), args
, n
);
2881 stdarg (XmNlabelString
, XmStringCreatePCB (buf
));
2882 XtSetValues (m_rats
, args
, n
);
2884 if (!PCB
->Data
->RatN
)
2887 stdarg (XmNleftWidget
, m_mode
);
2888 XtSetValues (XtParent (m_status
), args
, n
);
2889 XtUnmanageChild(XtParent(m_rats
));
2894 lesstif_update_widget_flags ();
2902 lesstif_need_idle_proc ()
2904 if (idle_proc_set
|| window
== 0)
2906 XtAppAddWorkProc (app_context
, idle_proc
, 0);
2911 lesstif_invalidate_lr (int l
, int r
, int t
, int b
)
2921 lesstif_invalidate_all (void)
2923 lesstif_invalidate_lr (0, PCB
->MaxWidth
, 0, PCB
->MaxHeight
);
2927 lesstif_notify_crosshair_change (bool changes_complete
)
2929 static int invalidate_depth
= 0;
2935 if (changes_complete
)
2936 invalidate_depth
--;
2938 if (invalidate_depth
< 0)
2940 invalidate_depth
= 0;
2941 /* A mismatch of changes_complete == false and == true notifications
2942 * is not expected to occur, but we will try to handle it gracefully.
2943 * As we know the crosshair will have been shown already, we must
2944 * repaint the entire view to be sure not to leave an artaefact.
2950 if (invalidate_depth
== 0 && crosshair_on
)
2952 save_pixmap
= pixmap
;
2955 pixmap
= save_pixmap
;
2958 if (!changes_complete
)
2959 invalidate_depth
++;
2963 lesstif_notify_mark_change (bool changes_complete
)
2965 static int invalidate_depth
= 0;
2968 if (changes_complete
)
2969 invalidate_depth
--;
2971 if (invalidate_depth
< 0)
2973 invalidate_depth
= 0;
2974 /* A mismatch of changes_complete == false and == true notifications
2975 * is not expected to occur, but we will try to handle it gracefully.
2976 * As we know the mark will have been shown already, we must
2977 * repaint the entire view to be sure not to leave an artaefact.
2983 if (invalidate_depth
== 0 && crosshair_on
)
2985 save_pixmap
= pixmap
;
2988 pixmap
= save_pixmap
;
2991 if (!changes_complete
)
2992 invalidate_depth
++;
2996 lesstif_set_layer (const char *name
, int group
, int empty
)
2999 if (idx
>= 0 && idx
< max_group
)
3001 int n
= PCB
->LayerGroups
.Number
[group
];
3002 for (idx
= 0; idx
< n
-1; idx
++)
3004 int ni
= PCB
->LayerGroups
.Entries
[group
][idx
];
3005 if (ni
>= 0 && ni
< max_copper_layer
+ 2
3006 && PCB
->Data
->Layer
[ni
].On
)
3009 idx
= PCB
->LayerGroups
.Entries
[group
][idx
];
3011 if (idx
== LayerStack
[0]
3012 || GetLayerGroupNumberByNumber (idx
) ==
3013 GetLayerGroupNumberByNumber (LayerStack
[0]))
3023 if (idx
>= 0 && idx
< max_copper_layer
+ 2)
3024 return pinout
? 1 : PCB
->Data
->Layer
[idx
].On
;
3027 switch (SL_TYPE (idx
))
3030 return pinout
? 0 : PCB
->InvisibleObjectsOn
;
3032 if (SL_MYSIDE (idx
) && !pinout
)
3033 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
3036 if (SL_MYSIDE (idx
) || pinout
)
3037 return PCB
->ElementOn
;
3052 lesstif_make_gc (void)
3054 hidGC rv
= (hid_gc_struct
*) malloc (sizeof (hid_gc_struct
));
3055 memset (rv
, 0, sizeof (hid_gc_struct
));
3056 rv
->me_pointer
= &lesstif_hid
;
3061 lesstif_destroy_gc (hidGC gc
)
3067 lesstif_use_mask (int use_it
)
3069 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) &&
3072 if ((use_it
== 0) == (use_mask
== 0))
3079 /* printf("use_mask(%d)\n", use_it); */
3083 XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
,
3084 XDefaultDepth (display
, screen
));
3085 mask_bitmap
= XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
, 1);
3089 pixmap
= mask_pixmap
;
3090 XSetForeground (display
, my_gc
, 0);
3091 XSetFunction (display
, my_gc
, GXcopy
);
3092 XFillRectangle (display
, mask_pixmap
, my_gc
,
3093 0, 0, view_width
, view_height
);
3094 XFillRectangle (display
, mask_bitmap
, bclear_gc
,
3095 0, 0, view_width
, view_height
);
3099 pixmap
= main_pixmap
;
3103 XRenderPictureAttributes pa
;
3105 pa
.clip_mask
= mask_bitmap
;
3106 XRenderChangePicture(display
, main_picture
, CPClipMask
, &pa
);
3107 XRenderComposite(display
, PictOpOver
, mask_picture
, pale_picture
,
3108 main_picture
, 0, 0, 0, 0, 0, 0, view_width
, view_height
);
3111 #endif /* HAVE_XRENDER */
3113 XSetClipMask (display
, clip_gc
, mask_bitmap
);
3114 XCopyArea (display
, mask_pixmap
, main_pixmap
, clip_gc
,
3115 0, 0, view_width
, view_height
, 0, 0);
3121 lesstif_set_color (hidGC gc
, const char *name
)
3123 static void *cache
= 0;
3125 static XColor color
, exact_color
;
3131 gc
->colorname
= name
;
3132 if (strcmp (name
, "erase") == 0)
3134 gc
->color
= bgcolor
;
3137 else if (strcmp (name
, "drill") == 0)
3139 gc
->color
= offlimit_color
;
3142 else if (hid_cache_color (0, name
, &cval
, &cache
))
3144 gc
->color
= cval
.lval
;
3149 if (!XAllocNamedColor (display
, colormap
, name
, &color
, &exact_color
))
3150 color
.pixel
= WhitePixel (display
, screen
);
3152 printf ("lesstif_set_color `%s' %08x rgb/%d/%d/%d\n",
3153 name
, color
.pixel
, color
.red
, color
.green
, color
.blue
);
3155 cval
.lval
= gc
->color
= color
.pixel
;
3156 hid_cache_color (1, name
, &cval
, &cache
);
3161 static int lastcolor
= -1, lastfade
= -1;
3162 if (gc
->color
== lastcolor
)
3163 gc
->color
= lastfade
;
3166 lastcolor
= gc
->color
;
3167 color
.pixel
= gc
->color
;
3169 XQueryColor (display
, colormap
, &color
);
3170 color
.red
= (bgred
+ color
.red
) / 2;
3171 color
.green
= (bggreen
+ color
.green
) / 2;
3172 color
.blue
= (bgblue
+ color
.blue
) / 2;
3173 XAllocColor (display
, colormap
, &color
);
3174 lastfade
= gc
->color
= color
.pixel
;
3182 int cap
, join
, width
;
3183 if (gc
->me_pointer
!= &lesstif_hid
)
3185 fprintf (stderr
, "Fatal: GC from another HID passed to lesstif HID\n");
3189 pcb_printf ("set_gc c%s %08lx w%#mS c%d x%d e%d\n",
3190 gc
->colorname
, gc
->color
, gc
->width
, gc
->cap
, gc
->xor_set
, gc
->erase
);
3195 cap
= CapProjecting
;
3204 cap
= CapProjecting
;
3208 cap
= CapProjecting
;
3214 XSetFunction (display
, my_gc
, GXxor
);
3215 XSetForeground (display
, my_gc
, gc
->color
^ bgcolor
);
3219 XSetFunction (display
, my_gc
, GXcopy
);
3220 XSetForeground (display
, my_gc
, offlimit_color
);
3224 XSetFunction (display
, my_gc
, GXcopy
);
3225 XSetForeground (display
, my_gc
, gc
->color
);
3227 width
= Vz (gc
->width
);
3230 XSetLineAttributes (display
, my_gc
, width
, LineSolid
, cap
,
3235 mask_gc
= bclear_gc
;
3238 XSetLineAttributes (display
, mask_gc
, Vz (gc
->width
), LineSolid
, cap
,
3244 lesstif_set_line_cap (hidGC gc
, EndCapStyle style
)
3250 lesstif_set_line_width (hidGC gc
, Coord width
)
3256 lesstif_set_draw_xor (hidGC gc
, int xor_set
)
3258 gc
->xor_set
= xor_set
;
3261 #define ISORT(a,b) if (a>b) { a^=b; b^=a; a^=b; }
3264 lesstif_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3266 double dx1
, dy1
, dx2
, dy2
;
3267 int vw
= Vz (gc
->width
);
3268 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && gc
->erase
)
3271 pcb_printf ("draw_line %#mD-%#mD @%#mS", x1
, y1
, x2
, y2
, gc
->width
);
3278 pcb_printf (" = %#mD-%#mD %s\n", x1
, y1
, x2
, y2
, gc
->colorname
);
3282 if (! ClipLine (0, 0, view_width
, view_height
,
3283 &dx1
, &dy1
, &dx2
, &dy2
, vw
))
3293 if (gc
->cap
== Square_Cap
&& x1
== x2
&& y1
== y2
)
3295 XFillRectangle (display
, pixmap
, my_gc
, x1
- vw
/ 2, y1
- vw
/ 2, vw
,
3298 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
- vw
/ 2,
3299 y1
- vw
/ 2, vw
, vw
);
3303 XDrawLine (display
, pixmap
, my_gc
, x1
, y1
, x2
, y2
);
3305 XDrawLine (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
, y2
);
3310 lesstif_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord width
, Coord height
,
3311 Angle start_angle
, Angle delta_angle
)
3313 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3316 pcb_printf ("draw_arc %#mD %#mSx%#mS s %d d %d", cx
, cy
, width
, height
, start_angle
, delta_angle
);
3319 height
= Vz (height
);
3320 cx
= Vx (cx
) - width
;
3321 cy
= Vy (cy
) - height
;
3324 start_angle
= 180 - start_angle
;
3325 delta_angle
= - delta_angle
;
3329 start_angle
= - start_angle
;
3330 delta_angle
= - delta_angle
;
3332 start_angle
= NormalizeAngle (start_angle
);
3333 if (start_angle
>= 180)
3336 pcb_printf (" = %#mD %#mSx%#mS %d %s\n", cx
, cy
, width
, height
, gc
->width
,
3340 XDrawArc (display
, pixmap
, my_gc
, cx
, cy
,
3341 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3343 if (use_mask
&& !TEST_FLAG (THINDRAWFLAG
, PCB
))
3344 XDrawArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3345 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3348 /* Enable this if you want to see the center and radii of drawn
3349 arcs, for debugging. */
3350 if (TEST_FLAG (THINDRAWFLAG
, PCB
)
3351 && delta_angle
!= 360)
3355 XDrawLine (display
, pixmap
, arc1_gc
, cx
, cy
,
3356 cx
- width
*cos(start_angle
*M_PI
/180),
3357 cy
+ width
*sin(start_angle
*M_PI
/180));
3358 XDrawLine (display
, pixmap
, arc2_gc
, cx
, cy
,
3359 cx
- width
*cos((start_angle
+delta_angle
)*M_PI
/180),
3360 cy
+ width
*sin((start_angle
+delta_angle
)*M_PI
/180));
3366 lesstif_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3368 int vw
= Vz (gc
->width
);
3369 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3375 if (x1
< -vw
&& x2
< -vw
)
3377 if (y1
< -vw
&& y2
< -vw
)
3379 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3381 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3383 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3384 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3386 XDrawRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1, y2
- y1
+ 1);
3388 XDrawRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3393 lesstif_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
3395 if (pinout
&& use_mask
&& gc
->erase
)
3397 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && gc
->erase
)
3400 pcb_printf ("fill_circle %#mD %#mS", cx
, cy
, radius
);
3402 radius
= Vz (radius
);
3403 cx
= Vx (cx
) - radius
;
3404 cy
= Vy (cy
) - radius
;
3405 if (cx
< -2 * radius
|| cx
> view_width
)
3407 if (cy
< -2 * radius
|| cy
> view_height
)
3410 pcb_printf (" = %#mD %#mS %lx %s\n", cx
, cy
, radius
, gc
->color
, gc
->colorname
);
3413 XFillArc (display
, pixmap
, my_gc
, cx
, cy
,
3414 radius
* 2, radius
* 2, 0, 360 * 64);
3416 XFillArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3417 radius
* 2, radius
* 2, 0, 360 * 64);
3421 lesstif_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
3423 static XPoint
*p
= 0;
3424 static int maxp
= 0;
3427 if (maxp
< n_coords
)
3429 maxp
= n_coords
+ 10;
3431 p
= (XPoint
*) realloc (p
, maxp
* sizeof (XPoint
));
3433 p
= (XPoint
*) malloc (maxp
* sizeof (XPoint
));
3436 for (i
= 0; i
< n_coords
; i
++)
3442 printf ("fill_polygon %d pts\n", n_coords
);
3445 XFillPolygon (display
, pixmap
, my_gc
, p
, n_coords
, Complex
,
3448 XFillPolygon (display
, mask_bitmap
, mask_gc
, p
, n_coords
, Complex
,
3453 lesstif_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
3455 int vw
= Vz (gc
->width
);
3456 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3462 if (x1
< -vw
&& x2
< -vw
)
3464 if (y1
< -vw
&& y2
< -vw
)
3466 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3468 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3470 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3471 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3473 XFillRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1,
3476 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3481 lesstif_calibrate (double xval
, double yval
)
3487 lesstif_shift_is_pressed (void)
3489 return shift_pressed
;
3493 lesstif_control_is_pressed (void)
3495 return ctrl_pressed
;
3499 lesstif_mod1_is_pressed (void)
3504 extern void lesstif_get_coords (const char *msg
, Coord
*x
, Coord
*y
);
3507 lesstif_set_crosshair (int x
, int y
, int action
)
3509 if (crosshair_x
!= x
|| crosshair_y
!= y
)
3511 lesstif_show_crosshair(0);
3519 || x
> view_left_x
+ view_width
* view_zoom
3520 || y
< view_top_y
|| y
> view_top_y
+ view_height
* view_zoom
))
3522 view_left_x
= x
- (view_width
* view_zoom
) / 2;
3523 view_top_y
= y
- (view_height
* view_zoom
) / 2;
3524 lesstif_pan_fixup ();
3529 if (action
== HID_SC_PAN_VIEWPORT
)
3532 unsigned int keys_buttons
;
3533 int pos_x
, pos_y
, root_x
, root_y
;
3534 XQueryPointer (display
, window
, &root
, &child
,
3535 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
3537 view_left_x
= x
- (view_width
-pos_x
) * view_zoom
;
3539 view_left_x
= x
- pos_x
* view_zoom
;
3541 view_top_y
= y
- (view_height
-pos_y
) * view_zoom
;
3543 view_top_y
= y
- pos_y
* view_zoom
;
3544 lesstif_pan_fixup();
3545 action
= HID_SC_WARP_POINTER
;
3547 if (action
== HID_SC_WARP_POINTER
)
3550 XWarpPointer (display
, None
, window
, 0, 0, 0, 0, Vx(x
), Vy(y
));
3557 void (*func
) (hidval
);
3563 lesstif_timer_cb (XtPointer
* p
, XtIntervalId
* id
)
3565 TimerStruct
*ts
= (TimerStruct
*) p
;
3566 ts
->func (ts
->user_data
);
3571 lesstif_add_timer (void (*func
) (hidval user_data
),
3572 unsigned long milliseconds
, hidval user_data
)
3576 t
= (TimerStruct
*) malloc (sizeof (TimerStruct
));
3579 t
->user_data
= user_data
;
3580 t
->id
= XtAppAddTimeOut (app_context
, milliseconds
, (XtTimerCallbackProc
)lesstif_timer_cb
, t
);
3585 lesstif_stop_timer (hidval hv
)
3587 TimerStruct
*ts
= (TimerStruct
*) hv
.ptr
;
3588 XtRemoveTimeOut (ts
->id
);
3595 void (*func
) ( hidval
, int, unsigned int, hidval
);
3602 /* We need a wrapper around the hid file watch because to pass the correct flags
3605 lesstif_watch_cb (XtPointer client_data
, int *fid
, XtInputId
* id
)
3607 unsigned int pcb_condition
= 0;
3611 WatchStruct
*watch
= (WatchStruct
*)client_data
;
3614 fds
.events
= POLLIN
| POLLOUT
;
3616 condition
= fds
.revents
;
3618 // Should we only include those we were asked to watch?
3619 if (condition
& POLLIN
)
3620 pcb_condition
|= PCB_WATCH_READABLE
;
3621 if (condition
& POLLOUT
)
3622 pcb_condition
|= PCB_WATCH_WRITABLE
;
3623 if (condition
& POLLERR
)
3624 pcb_condition
|= PCB_WATCH_ERROR
;
3625 if (condition
& POLLHUP
)
3626 pcb_condition
|= PCB_WATCH_HANGUP
;
3628 x
.ptr
= (void *) watch
;
3629 watch
->func (x
, watch
->fd
, pcb_condition
, watch
->user_data
);
3635 lesstif_watch_file (int fd
, unsigned int condition
, void (*func
) (hidval watch
, int fd
, unsigned int condition
, hidval user_data
),
3638 WatchStruct
*watch
= (WatchStruct
*) malloc (sizeof(WatchStruct
));
3640 unsigned int xt_condition
= 0;
3642 if (condition
& PCB_WATCH_READABLE
)
3643 xt_condition
|= XtInputReadMask
;
3644 if (condition
& PCB_WATCH_WRITABLE
)
3645 xt_condition
|= XtInputWriteMask
;
3646 if (condition
& PCB_WATCH_ERROR
)
3647 xt_condition
|= XtInputExceptMask
;
3648 if (condition
& PCB_WATCH_HANGUP
)
3649 xt_condition
|= XtInputExceptMask
;
3652 watch
->user_data
= user_data
;
3654 watch
->id
= XtAppAddInput( app_context
, fd
, (XtPointer
) (size_t) xt_condition
, lesstif_watch_cb
, watch
);
3656 ret
.ptr
= (void *) watch
;
3661 lesstif_unwatch_file (hidval data
)
3663 WatchStruct
*watch
= (WatchStruct
*)data
.ptr
;
3664 XtRemoveInput( watch
->id
);
3671 void (*func
) (hidval user_data
);
3675 static void lesstif_block_hook_cb(XtPointer user_data
);
3678 lesstif_block_hook_cb (XtPointer user_data
)
3680 BlockHookStruct
*block_hook
= (BlockHookStruct
*)user_data
;
3681 block_hook
->func( block_hook
->user_data
);
3685 lesstif_add_block_hook (void (*func
) (hidval data
), hidval user_data
)
3688 BlockHookStruct
*block_hook
= (BlockHookStruct
*) malloc( sizeof( BlockHookStruct
));
3690 block_hook
->func
= func
;
3691 block_hook
->user_data
= user_data
;
3693 block_hook
->id
= XtAppAddBlockHook( app_context
, lesstif_block_hook_cb
, (XtPointer
)block_hook
);
3695 ret
.ptr
= (void *) block_hook
;
3700 lesstif_stop_block_hook (hidval mlpoll
)
3702 BlockHookStruct
*block_hook
= (BlockHookStruct
*)mlpoll
.ptr
;
3703 XtRemoveBlockHook( block_hook
->id
);
3708 extern void lesstif_logv (const char *fmt
, va_list ap
);
3710 extern int lesstif_confirm_dialog (char *msg
, ...);
3712 extern int lesstif_close_confirm_dialog ();
3714 extern void lesstif_report_dialog (char *title
, char *msg
);
3717 lesstif_attribute_dialog (HID_Attribute
* attrs
,
3718 int n_attrs
, HID_Attr_Val
* results
,
3719 const char * title
, const char * descr
);
3722 pinout_callback (Widget da
, PinoutData
* pd
,
3723 XmDrawingAreaCallbackStruct
* cbs
)
3726 int save_vx
, save_vy
, save_vw
, save_vh
;
3727 int save_fx
, save_fy
;
3730 int reason
= cbs
? cbs
->reason
: 0;
3732 if (pd
->window
== 0 && reason
== XmCR_RESIZE
)
3734 if (pd
->window
== 0 || reason
== XmCR_RESIZE
)
3740 stdarg (XmNwidth
, &w
);
3741 stdarg (XmNheight
, &h
);
3742 XtGetValues (da
, args
, n
);
3744 pd
->window
= XtWindow (da
);
3747 pd
->zoom
= (pd
->right
- pd
->left
+ 1) / (double) w
;
3748 z
= (pd
->bottom
- pd
->top
+ 1) / (double) h
;
3752 pd
->x
= (pd
->left
+ pd
->right
) / 2 - pd
->v_width
* pd
->zoom
/ 2;
3753 pd
->y
= (pd
->top
+ pd
->bottom
) / 2 - pd
->v_height
* pd
->zoom
/ 2;
3756 save_vx
= view_left_x
;
3757 save_vy
= view_top_y
;
3758 save_vz
= view_zoom
;
3759 save_vw
= view_width
;
3760 save_vh
= view_height
;
3765 pixmap
= pd
->window
;
3766 view_left_x
= pd
->x
;
3768 view_zoom
= pd
->zoom
;
3769 view_width
= pd
->v_width
;
3770 view_height
= pd
->v_height
;
3772 flip_x
= flip_y
= 0;
3776 region
.X2
= PCB
->MaxWidth
;
3777 region
.Y2
= PCB
->MaxHeight
;
3779 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, pd
->v_width
, pd
->v_height
);
3780 hid_expose_callback (&lesstif_hid
, ®ion
, pd
->item
);
3783 view_left_x
= save_vx
;
3784 view_top_y
= save_vy
;
3785 view_zoom
= save_vz
;
3786 view_width
= save_vw
;
3787 view_height
= save_vh
;
3794 pinout_unmap (Widget w
, PinoutData
* pd
, void *v
)
3797 pd
->prev
->next
= pd
->next
;
3801 pd
->next
->prev
= pd
->prev
;
3802 XtDestroyWidget (XtParent (pd
->form
));
3807 lesstif_show_item (void *item
)
3814 for (pd
= pinouts
; pd
; pd
= pd
->next
)
3815 if (pd
->item
== item
)
3820 pd
= (PinoutData
*) calloc (1, sizeof (PinoutData
));
3824 extents
= hid_get_extents (item
);
3825 pd
->left
= extents
->X1
;
3826 pd
->right
= extents
->X2
;
3827 pd
->top
= extents
->Y1
;
3828 pd
->bottom
= extents
->Y2
;
3830 if (pd
->left
> pd
->right
)
3838 pd
->next
->prev
= pd
;
3843 pd
->form
= XmCreateFormDialog (mainwind
, "pinout", args
, n
);
3845 XtAddCallback (pd
->form
, XmNunmapCallback
, (XtCallbackProc
) pinout_unmap
,
3849 sqrt (200.0 * 200.0 /
3850 ((pd
->right
- pd
->left
+ 1.0) * (pd
->bottom
- pd
->top
+ 1.0)));
3853 stdarg (XmNwidth
, (int) (scale
* (pd
->right
- pd
->left
+ 1)));
3854 stdarg (XmNheight
, (int) (scale
* (pd
->bottom
- pd
->top
+ 1)));
3855 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
3856 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
3857 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
3858 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
3859 da
= XmCreateDrawingArea (pd
->form
, "pinout", args
, n
);
3862 XtAddCallback (da
, XmNexposeCallback
, (XtCallbackProc
) pinout_callback
,
3864 XtAddCallback (da
, XmNresizeCallback
, (XtCallbackProc
) pinout_callback
,
3867 XtManageChild (pd
->form
);
3879 static bool progress_cancelled
= false;
3882 progress_cancel_callback (Widget w
, void *v
, void *cbs
)
3884 progress_cancelled
= true;
3887 static Widget progress_dialog
= 0;
3888 static Widget progress_cancel
, progress_label
;
3889 static Widget progress_scale
;
3892 lesstif_progress_dialog (int so_far
, int total
, const char *msg
)
3899 if (progress_dialog
== 0)
3904 stdarg (XmNdefaultButtonType
, XmDIALOG_CANCEL_BUTTON
);
3905 stdarg (XmNtitle
, "Progress");
3906 stdarg (XmNdialogStyle
, XmDIALOG_APPLICATION_MODAL
);
3907 stdarg (XmNdialogStyle
, XmDIALOG_FULL_APPLICATION_MODAL
);
3908 progress_dialog
= XmCreateInformationDialog (mainwind
, "progress", args
, n
);
3909 XtAddCallback (progress_dialog
, XmNcancelCallback
,
3910 (XtCallbackProc
) progress_cancel_callback
, NULL
);
3912 progress_cancel
= XmMessageBoxGetChild (progress_dialog
, XmDIALOG_CANCEL_BUTTON
);
3913 progress_label
= XmMessageBoxGetChild (progress_dialog
, XmDIALOG_MESSAGE_LABEL
);
3915 XtUnmanageChild (XmMessageBoxGetChild (progress_dialog
, XmDIALOG_OK_BUTTON
));
3916 XtUnmanageChild (XmMessageBoxGetChild (progress_dialog
, XmDIALOG_HELP_BUTTON
));
3918 stdarg (XmNdefaultPosition
, False
);
3919 XtSetValues (progress_dialog
, args
, n
);
3922 stdarg(XmNminimum
, 0);
3923 stdarg(XmNvalue
, 0);
3924 stdarg(XmNmaximum
, total
> 0 ? total
: 1);
3925 stdarg(XmNorientation
, XmHORIZONTAL
);
3926 stdarg(XmNshowArrows
, false);
3927 progress_scale
= XmCreateScrollBar (progress_dialog
, "scale", args
, n
);
3928 XtManageChild (progress_scale
);
3930 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
3931 XmAddWMProtocolCallback (XtParent (progress_dialog
), close_atom
,
3932 (XtCallbackProc
) progress_cancel_callback
, 0);
3936 stdarg(XmNvalue
, 0);
3937 stdarg(XmNsliderSize
, (so_far
<= total
) ? (so_far
< 0) ? 0 : so_far
: total
);
3938 stdarg(XmNmaximum
, total
> 0 ? total
: 1);
3939 XtSetValues (progress_scale
, args
, n
);
3942 xs
= XmStringCreatePCB ((char *)msg
);
3943 stdarg (XmNmessageString
, xs
);
3944 XtSetValues (progress_dialog
, args
, n
);
3949 #define MIN_TIME_SEPARATION 0.1 /* seconds */
3952 lesstif_progress (int so_far
, int total
, const char *message
)
3954 static bool visible
= false;
3955 static bool started
= false;
3957 struct timeval time
;
3958 double time_delta
, time_now
;
3959 static double time_then
= 0.0;
3962 if (so_far
== 0 && total
== 0 && message
== NULL
)
3964 XtUnmanageChild (progress_dialog
);
3967 progress_cancelled
= false;
3971 gettimeofday (&time
, NULL
);
3972 time_now
= time
.tv_sec
+ time
.tv_usec
/ 1000000.0;
3974 time_delta
= time_now
- time_then
;
3976 if (started
&& time_delta
< MIN_TIME_SEPARATION
)
3979 /* Create or update the progress dialog */
3980 lesstif_progress_dialog (so_far
, total
, message
);
3984 XtManageChild (progress_dialog
);
3988 /* Dispatch pending events */
3989 while (XtAppPending (app_context
))
3991 XtAppNextEvent (app_context
, &e
);
3992 XtDispatchEvent (&e
);
3996 /* If rendering takes a while, make sure the core has enough time to
3998 gettimeofday (&time
, NULL
);
3999 time_then
= time
.tv_sec
+ time
.tv_usec
/ 1000000.0;
4001 return progress_cancelled
;
4005 lesstif_request_debug_draw (void)
4007 /* Send drawing to the backing pixmap */
4008 pixmap
= main_pixmap
;
4009 return &lesstif_hid
;
4013 lesstif_flush_debug_draw (void)
4015 /* Copy the backing pixmap to the display and redraw any attached objects */
4016 XSetFunction (display
, my_gc
, GXcopy
);
4017 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
4025 pixmap
= main_pixmap
;
4029 lesstif_finish_debug_draw (void)
4031 lesstif_flush_debug_draw ();
4032 /* No special tear down requirements
4036 #include "dolists.h"
4041 memset (&lesstif_hid
, 0, sizeof (HID
));
4043 common_nogui_init (&lesstif_hid
);
4044 common_draw_helpers_init (&lesstif_hid
);
4046 lesstif_hid
.struct_size
= sizeof (HID
);
4047 lesstif_hid
.name
= "lesstif";
4048 lesstif_hid
.description
= "LessTif - a Motif clone for X/Unix";
4049 lesstif_hid
.gui
= 1;
4050 lesstif_hid
.poly_before
= 1;
4052 lesstif_hid
.get_export_options
= lesstif_get_export_options
;
4053 lesstif_hid
.do_export
= lesstif_do_export
;
4054 lesstif_hid
.parse_arguments
= lesstif_parse_arguments
;
4055 lesstif_hid
.invalidate_lr
= lesstif_invalidate_lr
;
4056 lesstif_hid
.invalidate_all
= lesstif_invalidate_all
;
4057 lesstif_hid
.notify_crosshair_change
= lesstif_notify_crosshair_change
;
4058 lesstif_hid
.notify_mark_change
= lesstif_notify_mark_change
;
4059 lesstif_hid
.set_layer
= lesstif_set_layer
;
4060 lesstif_hid
.make_gc
= lesstif_make_gc
;
4061 lesstif_hid
.destroy_gc
= lesstif_destroy_gc
;
4062 lesstif_hid
.use_mask
= lesstif_use_mask
;
4063 lesstif_hid
.set_color
= lesstif_set_color
;
4064 lesstif_hid
.set_line_cap
= lesstif_set_line_cap
;
4065 lesstif_hid
.set_line_width
= lesstif_set_line_width
;
4066 lesstif_hid
.set_draw_xor
= lesstif_set_draw_xor
;
4067 lesstif_hid
.draw_line
= lesstif_draw_line
;
4068 lesstif_hid
.draw_arc
= lesstif_draw_arc
;
4069 lesstif_hid
.draw_rect
= lesstif_draw_rect
;
4070 lesstif_hid
.fill_circle
= lesstif_fill_circle
;
4071 lesstif_hid
.fill_polygon
= lesstif_fill_polygon
;
4072 lesstif_hid
.fill_rect
= lesstif_fill_rect
;
4074 lesstif_hid
.calibrate
= lesstif_calibrate
;
4075 lesstif_hid
.shift_is_pressed
= lesstif_shift_is_pressed
;
4076 lesstif_hid
.control_is_pressed
= lesstif_control_is_pressed
;
4077 lesstif_hid
.mod1_is_pressed
= lesstif_mod1_is_pressed
;
4078 lesstif_hid
.get_coords
= lesstif_get_coords
;
4079 lesstif_hid
.set_crosshair
= lesstif_set_crosshair
;
4080 lesstif_hid
.add_timer
= lesstif_add_timer
;
4081 lesstif_hid
.stop_timer
= lesstif_stop_timer
;
4082 lesstif_hid
.watch_file
= lesstif_watch_file
;
4083 lesstif_hid
.unwatch_file
= lesstif_unwatch_file
;
4084 lesstif_hid
.add_block_hook
= lesstif_add_block_hook
;
4085 lesstif_hid
.stop_block_hook
= lesstif_stop_block_hook
;
4087 lesstif_hid
.log
= lesstif_log
;
4088 lesstif_hid
.logv
= lesstif_logv
;
4089 lesstif_hid
.confirm_dialog
= lesstif_confirm_dialog
;
4090 lesstif_hid
.close_confirm_dialog
= lesstif_close_confirm_dialog
;
4091 lesstif_hid
.report_dialog
= lesstif_report_dialog
;
4092 lesstif_hid
.prompt_for
= lesstif_prompt_for
;
4093 lesstif_hid
.fileselect
= lesstif_fileselect
;
4094 lesstif_hid
.attribute_dialog
= lesstif_attribute_dialog
;
4095 lesstif_hid
.show_item
= lesstif_show_item
;
4096 lesstif_hid
.beep
= lesstif_beep
;
4097 lesstif_hid
.progress
= lesstif_progress
;
4098 lesstif_hid
.edit_attributes
= lesstif_attributes_dialog
;
4100 lesstif_hid
.request_debug_draw
= lesstif_request_debug_draw
;
4101 lesstif_hid
.flush_debug_draw
= lesstif_flush_debug_draw
;
4102 lesstif_hid
.finish_debug_draw
= lesstif_finish_debug_draw
;
4104 hid_register_hid (&lesstif_hid
);
4105 #include "lesstif_lists.h"