2 /* 15 Oct 2008 Ineiev: add different crosshair shapes */
17 #include "xincludes.h"
22 #include "crosshair.h"
30 #include "../hidint.h"
31 #include "hid/common/draw_helpers.h"
34 #ifdef HAVE_LIBDMALLOC
43 #define XtRDouble "Double"
46 typedef struct hid_gc_struct
50 const char *colorname
;
57 extern HID lesstif_gui
;
58 extern HID lesstif_extents
;
60 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented GUI function %s\n", __FUNCTION__), abort()
62 XtAppContext app_context
;
65 static Window window
= 0;
66 static Cursor my_cursor
= 0;
67 static int old_cursor_mode
= -1;
68 static int over_point
= 0;
70 /* The first is the "current" pixmap. The main_ is the real one we
71 usually use, the mask_ are the ones for doing polygon masks. The
72 pixmap is the saved pixels, the bitmap is for the "erase" color.
73 We set pixmap to point to main_pixmap or mask_pixmap as needed. */
74 static Pixmap pixmap
= 0;
75 static Pixmap main_pixmap
= 0;
76 static Pixmap mask_pixmap
= 0;
77 static Pixmap mask_bitmap
= 0;
78 static int use_mask
= 0;
80 static int use_xrender
= 0;
82 static Picture main_picture
;
83 static Picture mask_picture
;
84 static Pixmap pale_pixmap
;
85 static Picture pale_picture
;
86 #endif /* HAVE_XRENDER */
88 static int pixmap_w
= 0, pixmap_h
= 0;
91 static Colormap colormap
;
92 static GC my_gc
= 0, bg_gc
, clip_gc
= 0, bset_gc
= 0, bclear_gc
= 0, mask_gc
=
94 static Pixel bgcolor
, offlimit_color
, grid_color
;
95 static int bgred
, bggreen
, bgblue
;
97 static GC arc1_gc
, arc2_gc
;
99 /* These are for the pinout windows. */
100 typedef struct PinoutData
102 struct PinoutData
*prev
, *next
;
105 int left
, right
, top
, bottom
; /* PCB extents of item */
106 int x
, y
; /* PCB coordinates of upper right corner of window */
107 double zoom
; /* PCB units per screen pixel */
108 int v_width
, v_height
; /* pixels */
112 /* Linked list of all pinout windows. */
113 static PinoutData
*pinouts
= 0;
114 /* If set, we are currently updating this pinout window. */
115 static PinoutData
*pinout
= 0;
117 static int crosshair_x
= 0, crosshair_y
= 0;
118 static int in_move_event
= 0, crosshair_in_window
= 1;
120 Widget work_area
, messages
, command
, hscroll
, vscroll
;
121 static Widget m_mark
, m_crosshair
, m_grid
, m_zoom
, m_mode
, m_status
;
122 static Widget m_rats
;
123 Widget lesstif_m_layer
;
126 /* This is the size, in pixels, of the viewport. */
127 static int view_width
, view_height
;
128 /* This is the PCB location represented by the upper left corner of
129 the viewport. Note that PCB coordinates put 0,0 in the upper left,
131 static int view_left_x
= 0, view_top_y
= 0;
132 /* Denotes PCB units per screen pixel. Larger numbers mean zooming
133 out - the largest value means you are looking at the whole
135 static double view_zoom
= 1000, prev_view_zoom
= 1000;
136 static int flip_x
= 0, flip_y
= 0;
137 static int autofade
= 0;
150 HID_Flag lesstif_main_flag_list
[] = {
151 {"flip_x", flag_flipx
, 0},
152 {"flip_y", flag_flipy
, 0}
155 REGISTER_FLAGS (lesstif_main_flag_list
)
157 /* This is the size of the current PCB work area. */
158 /* Use PCB->MaxWidth, PCB->MaxHeight. */
159 /* static int pcb_width, pcb_height; */
163 #define stdarg(t,v) XtSetArg(args[n], t, v), n++
166 static int use_private_colormap
= 0;
167 static int stdin_listen
= 0;
168 static char *background_image_file
= 0;
170 HID_Attribute lesstif_attribute_list
[] = {
171 {"install", "Install private colormap",
172 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &use_private_colormap
},
173 #define HA_colormap 0
175 {"listen", "Listen on standard input for actions",
176 HID_Boolean
, 0, 0, {0, 0, 0}, 0, &stdin_listen
},
179 {"bg-image", "Background Image",
180 HID_String
, 0, 0, {0, 0, 0}, 0, &background_image_file
},
181 #define HA_bg_image 1
185 REGISTER_ATTRIBUTES (lesstif_attribute_list
)
187 static void lesstif_use_mask (int use_it
);
188 static void zoom_to (double factor
, int x
, int y
);
189 static void zoom_by (double factor
, int x
, int y
);
190 static void zoom_toggle (int x
, int y
);
191 static void pinout_callback (Widget
, PinoutData
*,
192 XmDrawingAreaCallbackStruct
*);
193 static void pinout_unmap (Widget
, PinoutData
*, void *);
194 static void Pan (int mode
, int x
, int y
);
196 /* Px converts view->pcb, Vx converts pcb->view */
201 int rv
= (x
- view_left_x
) / view_zoom
+ 0.5;
203 rv
= view_width
- rv
;
210 int rv
= (y
- view_top_y
) / view_zoom
+ 0.5;
212 rv
= view_height
- rv
;
219 return z
/ view_zoom
+ 0.5;
227 return x
* view_zoom
+ view_left_x
;
235 return y
* view_zoom
+ view_top_y
;
241 return z
* view_zoom
;
245 lesstif_coords_to_pcb (int vx
, int vy
, int *px
, int *py
)
252 lesstif_parse_color (char *value
)
255 if (XParseColor (display
, colormap
, value
, &color
))
256 if (XAllocColor (display
, colormap
, &color
))
262 do_color (char *value
, char *which
)
265 if (XParseColor (display
, colormap
, value
, &color
))
266 if (XAllocColor (display
, colormap
, &color
))
268 stdarg (which
, color
.pixel
);
272 /* ------------------------------------------------------------ */
277 if (TEST_FLAG (ORTHOMOVEFLAG
, PCB
))
279 if (TEST_FLAG (ALLDIRECTIONFLAG
, PCB
))
281 if (PCB
->Clipping
== 0)
283 if (PCB
->Clipping
== 1)
288 /* Called from the core when it's busy doing something and we need to
289 indicate that to the user. */
291 Busy(int argc
, char **argv
, int x
, int y
)
293 static Cursor busy_cursor
= 0;
294 if (busy_cursor
== 0)
295 busy_cursor
= XCreateFontCursor (display
, XC_watch
);
296 XDefineCursor (display
, window
, busy_cursor
);
298 old_cursor_mode
= -1;
302 /* ---------------------------------------------------------------------- */
307 PointCursor (int argc
, char **argv
, int x
, int y
)
313 old_cursor_mode
= -1;
318 PCBChanged (int argc
, char **argv
, int x
, int y
)
322 /*printf("PCB Changed! %d x %d\n", PCB->MaxWidth, PCB->MaxHeight); */
324 stdarg (XmNminimum
, 0);
325 stdarg (XmNvalue
, 0);
326 stdarg (XmNsliderSize
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
327 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
328 XtSetValues (hscroll
, args
, n
);
330 stdarg (XmNminimum
, 0);
331 stdarg (XmNvalue
, 0);
332 stdarg (XmNsliderSize
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
333 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
334 XtSetValues (vscroll
, args
, n
);
335 zoom_by (1000000, 0, 0);
337 hid_action ("NetlistChanged");
338 hid_action ("LayersChanged");
339 hid_action ("RouteStylesChanged");
340 lesstif_sizes_reset ();
341 lesstif_update_layer_groups ();
343 pinout_unmap (0, pinouts
, 0);
346 char *cp
= strrchr (PCB
->Filename
, '/');
348 stdarg (XmNtitle
, cp
? cp
+ 1 : PCB
->Filename
);
349 XtSetValues (appwidget
, args
, n
);
355 static const char setunits_syntax
[] =
358 static const char setunits_help
[] =
359 "Set the default measurement units.";
361 /* %start-doc actions SetUnits
366 Sets the display units to mils (1/1000 inch).
369 Sets the display units to millimeters.
376 SetUnits (int argc
, char **argv
, int x
, int y
)
380 if (strcmp (argv
[0], "mil") == 0)
381 Settings
.grid_units_mm
= 0;
382 if (strcmp (argv
[0], "mm") == 0)
383 Settings
.grid_units_mm
= 1;
384 lesstif_sizes_reset ();
385 lesstif_styles_update_values ();
389 static const char zoom_syntax
[] =
393 static const char zoom_help
[] =
394 "Various zoom factor changes.";
396 /* %start-doc actions Zoom
398 Changes the zoom (magnification) of the view of the board. If no
399 arguments are passed, the view is scaled such that the board just fits
400 inside the visible window (i.e. ``view all''). Otherwise,
401 @var{factor} specifies a change in zoom factor. It may be prefixed by
402 @code{+}, @code{-}, or @code{=} to change how the zoom factor is
403 modified. The @var{factor} is a floating point number, such as
404 @code{1.5} or @code{0.75}.
409 Values greater than 1.0 cause the board to be drawn smaller; more of
410 the board will be visible. Values between 0.0 and 1.0 cause the board
411 to be drawn bigger; less of the board will be visible.
414 Values greater than 1.0 cause the board to be drawn bigger; less of
415 the board will be visible. Values between 0.0 and 1.0 cause the board
416 to be drawn smaller; more of the board will be visible.
420 The @var{factor} is an absolute zoom factor; the unit for this value
421 is "PCB units per screen pixel". Since PCB units are 0.01 mil, a
422 @var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI,
423 about the actual resolution of most screens - resulting in an "actual
424 size" board. Similarly, a @var{factor} of 100 gives you a 10x actual
429 Note that zoom factors of zero are silently ignored.
434 ZoomAction (int argc
, char **argv
, int x
, int y
)
438 if (x
== 0 && y
== 0)
450 zoom_to (1000000, 0, 0);
454 if (strcasecmp (vp
, "toggle") == 0)
459 if (*vp
== '+' || *vp
== '-' || *vp
== '=')
467 zoom_by (1 / v
, x
, y
);
480 static int pan_thumb_mode
;
483 PanAction (int argc
, char **argv
, int x
, int y
)
489 pan_thumb_mode
= (strcasecmp (argv
[0], "thumb") == 0) ? 1 : 0;
490 mode
= atoi (argv
[1]);
495 mode
= atoi (argv
[0]);
497 Pan (mode
, Vx(x
), Vy(y
));
502 static const char swapsides_syntax
[] =
505 static const char swapsides_help
[] =
506 "Swaps the side of the board you're looking at.";
508 /* %start-doc actions SwapSides
510 This action changes the way you view the board.
515 Flips the board over vertically (up/down).
518 Flips the board over horizontally (left/right), like flipping pages in
522 Rotates the board 180 degrees without changing sides.
526 If no argument is given, the board isn't moved but the opposite side
529 Normally, this action changes which pads and silk layer are drawn as
530 true silk, and which are drawn as the "invisible" layer. It also
531 determines which solder mask you see.
533 As a special case, if the layer group for the side you're looking at
534 is visible and currently active, and the layer group for the opposite
535 is not visible (i.e. disabled), then this action will also swap which
536 layer group is visible and active, effectively swapping the ``working
542 SwapSides (int argc
, char **argv
, int x
, int y
)
544 int old_shown_side
= Settings
.ShowSolderSide
;
545 int comp_group
= GetLayerGroupNumberByNumber (max_layer
+ COMPONENT_LAYER
);
546 int solder_group
= GetLayerGroupNumberByNumber (max_layer
+ SOLDER_LAYER
);
547 int active_group
= GetLayerGroupNumberByNumber (LayerStack
[0]);
549 PCB
->Data
->Layer
[PCB
->LayerGroups
.Entries
[comp_group
][0]].On
;
551 PCB
->Data
->Layer
[PCB
->LayerGroups
.Entries
[solder_group
][0]].On
;
555 switch (argv
[0][0]) {
572 /* SwapSides will swap this */
573 Settings
.ShowSolderSide
= (flip_x
== flip_y
);
578 stdarg (XmNprocessingDirection
, XmMAX_ON_LEFT
);
580 stdarg (XmNprocessingDirection
, XmMAX_ON_RIGHT
);
581 XtSetValues (hscroll
, args
, n
);
585 stdarg (XmNprocessingDirection
, XmMAX_ON_TOP
);
587 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
588 XtSetValues (vscroll
, args
, n
);
590 Settings
.ShowSolderSide
= !Settings
.ShowSolderSide
;
592 /* The idea is that if we're looking at the front side and the front
593 layer is active (or visa versa), switching sides should switch
594 layers too. We used to only do this if the other layer wasn't
595 shown, but we now do it always. Change it back if users get
597 if (Settings
.ShowSolderSide
!= old_shown_side
)
599 if (Settings
.ShowSolderSide
)
601 if (active_group
== comp_group
)
603 if (comp_showing
&& !solder_showing
)
604 ChangeGroupVisibility (PCB
->LayerGroups
.Entries
[comp_group
][0], 0,
606 ChangeGroupVisibility (PCB
->LayerGroups
.Entries
[solder_group
][0], 1,
612 if (active_group
== solder_group
)
614 if (solder_showing
&& !comp_showing
)
615 ChangeGroupVisibility (PCB
->LayerGroups
.Entries
[solder_group
][0], 0,
617 ChangeGroupVisibility (PCB
->LayerGroups
.Entries
[comp_group
][0], 1,
622 lesstif_invalidate_all ();
626 static Widget m_cmd
= 0, m_cmd_label
;
629 command_parse (char *s
)
635 for (cp
= s
; *cp
; cp
++)
637 if (isspace ((int) *cp
))
645 argv
= (char **) malloc ((n
+ 1) * sizeof (char *));
649 for (cp
= s
; *cp
; cp
++)
651 if (isspace ((int) *cp
))
666 lesstif_call_action (argv
[0], n
- 1, argv
+ 1);
670 command_callback (Widget w
, XtPointer uptr
, XmTextVerifyCallbackStruct
* cbs
)
676 s
= XmTextGetString (w
);
677 lesstif_show_crosshair (0);
679 hid_parse_actions (s
, lesstif_call_action
);
683 XmTextSetString (w
, "");
684 case XmCR_LOSING_FOCUS
:
685 XtUnmanageChild (m_cmd
);
686 XtUnmanageChild (m_cmd_label
);
692 command_event_handler (Widget w
, XtPointer p
, XEvent
* e
, Boolean
* cont
)
701 slen
= XLookupString ((XKeyEvent
*)e
, buf
, sizeof (buf
), &sym
, NULL
);
705 XtUnmanageChild (m_cmd
);
706 XtUnmanageChild (m_cmd_label
);
707 XmTextSetString (w
, "");
715 static const char command_syntax
[] =
718 static const char command_help
[] =
719 "Displays the command line input window.";
721 /* %start-doc actions Command
723 The command window allows the user to manually enter actions to be
724 executed. Action syntax can be done one of two ways:
729 Follow the action name by an open parenthesis, arguments separated by
730 commas, end with a close parenthesis. Example: @code{Abc(1,2,3)}
733 Separate the action name and arguments by spaces. Example: @code{Abc
738 The first option allows you to have arguments with spaces in them,
739 but the second is more ``natural'' to type for most people.
741 Note that action names are not case sensitive, but arguments normally
742 are. However, most actions will check for ``keywords'' in a case
745 There are three ways to finish with the command window. If you press
746 the @code{Enter} key, the command is invoked, the window goes away,
747 and the next time you bring up the command window it's empty. If you
748 press the @code{Esc} key, the window goes away without invoking
749 anything, and the next time you bring up the command window it's
750 empty. If you change focus away from the command window (i.e. click
751 on some other window), the command window goes away but the next time
752 you bring it up it resumes entering the command you were entering
758 Command (int argc
, char **argv
, int x
, int y
)
760 XtManageChild (m_cmd_label
);
761 XtManageChild (m_cmd
);
762 XmProcessTraversal (m_cmd
, XmTRAVERSE_CURRENT
);
766 static const char benchmark_syntax
[] =
769 static const char benchmark_help
[] =
770 "Benchmark the GUI speed.";
772 /* %start-doc actions Benchmark
774 This action is used to speed-test the Lesstif graphics subsystem. It
775 redraws the current screen as many times as possible in ten seconds.
776 It reports the amount of time needed to draw the screen once.
781 Benchmark (int argc
, char **argv
, int x
, int y
)
788 save_main
= main_pixmap
;
789 main_pixmap
= window
;
793 region
.X2
= PCB
->MaxWidth
;
794 region
.Y2
= PCB
->MaxHeight
;
801 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, view_width
, view_height
);
802 hid_expose_callback (&lesstif_gui
, ®ion
, 0);
807 while (end
- start
< 10);
809 printf ("%g redraws per second\n", i
/ 10.0);
811 main_pixmap
= save_main
;
816 Center(int argc
, char **argv
, int x
, int y
)
818 x
= GRIDFIT_X (x
, PCB
->Grid
);
819 y
= GRIDFIT_Y (y
, PCB
->Grid
);
820 view_left_x
= x
- (view_width
* view_zoom
) / 2;
821 view_top_y
= y
- (view_height
* view_zoom
) / 2;
822 lesstif_pan_fixup ();
823 /* Move the pointer to the center of the window, but only if it's
824 currently within the window already. Watch out for edges,
826 XWarpPointer (display
, window
, window
, 0, 0, view_width
, view_height
,
831 static const char cursor_syntax
[] =
832 "Cursor(Type,DeltaUp,DeltaRight,Units)";
834 static const char cursor_help
[] =
837 /* %start-doc actions Cursor
839 This action moves the mouse cursor. Unlike other actions which take
840 coordinates, this action's coordinates are always relative to the
841 user's view of the board. Thus, a positive @var{DeltaUp} may move the
842 cursor towards the board origin if the board is inverted.
844 Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the
845 viewport to move such that the crosshair is under the mouse cursor.
846 @samp{Warp} causes the mouse cursor to move to be above the crosshair.
848 @var{Units} can be one of the following:
854 The cursor is moved by that amount, in board units.
857 The cursor is moved by that many grid points.
860 The values are percentages of the viewport's view. Thus, a pan of
861 @samp{100} would scroll the viewport by exactly the width of the
865 The values are percentages of the board size. Thus, a move of
866 @samp{50,50} moves you halfway across the board.
873 CursorAction(int argc
, char **argv
, int x
, int y
)
875 int pan_warp
= HID_SC_DO_NOTHING
;
876 double dx
, dy
, xu
, yu
;
881 if (strcasecmp (argv
[0], "pan") == 0)
882 pan_warp
= HID_SC_PAN_VIEWPORT
;
883 else if (strcasecmp (argv
[0], "warp") == 0)
884 pan_warp
= HID_SC_WARP_POINTER
;
888 dx
= strtod (argv
[1], 0);
891 dy
= strtod (argv
[2], 0);
895 if (strncasecmp (argv
[3], "mm", 2) == 0)
896 xu
= yu
= MM_TO_COOR
;
897 else if (strncasecmp (argv
[3], "mil", 3) == 0)
899 else if (strncasecmp (argv
[3], "grid", 4) == 0)
901 else if (strncasecmp (argv
[3], "view", 4) == 0)
903 xu
= Pz(view_width
) / 100.0;
904 yu
= Pz(view_height
) / 100.0;
906 else if (strncasecmp (argv
[3], "board", 4) == 0)
908 xu
= PCB
->MaxWidth
/ 100.0;
909 yu
= PCB
->MaxHeight
/ 100.0;
914 EventMoveCrosshair (Crosshair
.X
+(int)(dx
*xu
), Crosshair
.Y
+(int)(dy
*yu
));
915 gui
->set_crosshair (Crosshair
.X
, Crosshair
.Y
, pan_warp
);
920 HID_Action lesstif_main_action_list
[] = {
921 {"PCBChanged", 0, PCBChanged
,
922 pcbchanged_help
, pcbchanged_syntax
},
923 {"SetUnits", 0, SetUnits
,
924 setunits_help
, setunits_syntax
},
925 {"Zoom", 0, ZoomAction
,
926 zoom_help
, zoom_syntax
},
927 {"Pan", 0, PanAction
,
928 zoom_help
, zoom_syntax
},
929 {"SwapSides", 0, SwapSides
,
930 swapsides_help
, swapsides_syntax
},
931 {"Command", 0, Command
,
932 command_help
, command_syntax
},
933 {"Benchmark", 0, Benchmark
,
934 benchmark_help
, benchmark_syntax
},
935 {"PointCursor", 0, PointCursor
},
936 {"Center", "Click on a location to center", Center
},
938 {"Cursor", 0, CursorAction
,
939 cursor_help
, cursor_syntax
},
942 REGISTER_ACTIONS (lesstif_main_action_list
)
945 /* ----------------------------------------------------------------------
946 * redraws the background image
949 static int bg_w
, bg_h
, bgi_w
, bgi_h
;
950 static Pixel
**bg
= 0;
951 static XImage
*bgi
= 0;
956 } pixel_type
= PT_unknown
;
959 LoadBackgroundFile (FILE *f
, char *filename
)
961 XVisualInfo vinfot
, *vinfo
;
965 int p
[3], rows
, cols
, maxval
;
969 printf("bgimage: %s signature not P6\n", filename
);
974 printf("bgimage: %s signature not P6\n", filename
);
984 while (!feof(f
) && b
!= '\n')
986 } while (!isdigit(b
));
988 while (isdigit(b
= fgetc(f
)))
989 p
[i
] = p
[i
]*10 + b
- '0';
996 bg
= (Pixel
**) malloc (rows
* sizeof (Pixel
*));
999 printf("Out of memory loading %s\n", filename
);
1002 for (i
=0; i
<rows
; i
++)
1004 bg
[i
] = (Pixel
*) malloc (cols
* sizeof (Pixel
));
1007 printf("Out of memory loading %s\n", filename
);
1016 vis
= DefaultVisual (display
, DefaultScreen(display
));
1018 vinfot
.visualid
= XVisualIDFromVisual(vis
);
1019 vinfo
= XGetVisualInfo (display
, VisualIDMask
, &vinfot
, &nret
);
1022 /* If you want to support more visuals below, you'll probably need
1024 printf("vinfo: rm %04x gm %04x bm %04x depth %d class %d\n",
1025 vinfo
->red_mask
, vinfo
->green_mask
, vinfo
->blue_mask
,
1026 vinfo
->depth
, vinfo
->class);
1029 if (vinfo
->class == TrueColor
1030 && vinfo
->depth
== 16
1031 && vinfo
->red_mask
== 0xf800
1032 && vinfo
->green_mask
== 0x07e0
1033 && vinfo
->blue_mask
== 0x001f)
1034 pixel_type
= PT_RGB565
;
1036 if (vinfo
->class == TrueColor
1037 && vinfo
->depth
== 24
1038 && vinfo
->red_mask
== 0xff0000
1039 && vinfo
->green_mask
== 0x00ff00
1040 && vinfo
->blue_mask
== 0x0000ff)
1041 pixel_type
= PT_RGB888
;
1043 for (r
=0; r
<rows
; r
++)
1045 for (c
=0; c
<cols
; c
++)
1048 unsigned int pr
= (unsigned)fgetc(f
);
1049 unsigned int pg
= (unsigned)fgetc(f
);
1050 unsigned int pb
= (unsigned)fgetc(f
);
1055 pix
.red
= pr
* 65535 / maxval
;
1056 pix
.green
= pg
* 65535 / maxval
;
1057 pix
.blue
= pb
* 65535 / maxval
;
1058 pix
.flags
= DoRed
| DoGreen
| DoBlue
;
1059 XAllocColor (display
, colormap
, &pix
);
1060 bg
[r
][c
] = pix
.pixel
;
1063 bg
[r
][c
] = (pr
>>3)<<11 | (pg
>>2)<<5 | (pb
>>3);
1066 bg
[r
][c
] = (pr
<< 16) | (pg
<< 8) | (pb
);
1074 LoadBackgroundImage (char *filename
)
1076 FILE *f
= fopen(filename
, "rb");
1079 if (NSTRCMP (filename
, "pcb-background.ppm"))
1083 LoadBackgroundFile (f
, filename
);
1088 DrawBackgroundImage ()
1091 double xscale
, yscale
;
1092 int pcbwidth
= PCB
->MaxWidth
/ view_zoom
;
1093 int pcbheight
= PCB
->MaxHeight
/ view_zoom
;
1098 if (!bgi
|| view_width
!= bgi_w
|| view_height
!= bgi_h
)
1101 XDestroyImage (bgi
);
1102 /* Cheat - get the image, which sets up the format too. */
1103 bgi
= XGetImage (XtDisplay(work_area
),
1105 0, 0, view_width
, view_height
,
1108 bgi_h
= view_height
;
1111 w
= MIN (view_width
, pcbwidth
);
1112 h
= MIN (view_height
, pcbheight
);
1114 xscale
= (double)bg_w
/ PCB
->MaxWidth
;
1115 yscale
= (double)bg_h
/ PCB
->MaxHeight
;
1120 int ir
= pr
* yscale
;
1124 int ic
= pc
* xscale
;
1125 XPutPixel (bgi
, x
, y
, bg
[ir
][ic
]);
1128 XPutImage(display
, main_pixmap
, bg_gc
,
1132 /* ---------------------------------------------------------------------- */
1134 static HID_Attribute
*
1135 lesstif_get_export_options (int *n
)
1141 set_scroll (Widget s
, int pos
, int view
, int pcb
)
1143 int sz
= view
* view_zoom
;
1147 stdarg (XmNvalue
, pos
);
1148 stdarg (XmNsliderSize
, sz
);
1149 stdarg (XmNincrement
, view_zoom
);
1150 stdarg (XmNpageIncrement
, sz
);
1151 stdarg (XmNmaximum
, pcb
);
1152 XtSetValues (s
, args
, n
);
1156 lesstif_pan_fixup ()
1158 if (view_left_x
> PCB
->MaxWidth
- (view_width
* view_zoom
))
1159 view_left_x
= PCB
->MaxWidth
- (view_width
* view_zoom
);
1160 if (view_top_y
> PCB
->MaxHeight
- (view_height
* view_zoom
))
1161 view_top_y
= PCB
->MaxHeight
- (view_height
* view_zoom
);
1162 if (view_left_x
< 0)
1166 if (view_width
* view_zoom
> PCB
->MaxWidth
1167 && view_height
* view_zoom
> PCB
->MaxHeight
)
1173 set_scroll (hscroll
, view_left_x
, view_width
, PCB
->MaxWidth
);
1174 set_scroll (vscroll
, view_top_y
, view_height
, PCB
->MaxHeight
);
1176 lesstif_invalidate_all ();
1180 zoom_to (double new_zoom
, int x
, int y
)
1182 double max_zoom
, xfrac
, yfrac
;
1185 xfrac
= (double) x
/ (double) view_width
;
1186 yfrac
= (double) y
/ (double) view_height
;
1193 max_zoom
= PCB
->MaxWidth
/ view_width
;
1194 if (max_zoom
< PCB
->MaxHeight
/ view_height
)
1195 max_zoom
= PCB
->MaxHeight
/ view_height
;
1199 if (new_zoom
> max_zoom
)
1200 new_zoom
= max_zoom
;
1202 cx
= view_left_x
+ view_width
* xfrac
* view_zoom
;
1203 cy
= view_top_y
+ view_height
* yfrac
* view_zoom
;
1205 if (view_zoom
!= new_zoom
)
1207 view_zoom
= new_zoom
;
1208 pixel_slop
= view_zoom
;
1210 view_left_x
= cx
- view_width
* xfrac
* view_zoom
;
1211 view_top_y
= cy
- view_height
* yfrac
* view_zoom
;
1213 lesstif_pan_fixup ();
1217 zoom_toggle(int x
, int y
)
1221 tmp
= prev_view_zoom
;
1222 prev_view_zoom
= view_zoom
;
1227 zoom_by (double factor
, int x
, int y
)
1229 zoom_to (view_zoom
* factor
, x
, y
);
1232 static int panning
= 0;
1233 static int shift_pressed
;
1234 static int ctrl_pressed
;
1235 static int alt_pressed
;
1237 /* X and Y are in screen coordinates. */
1239 Pan (int mode
, int x
, int y
)
1242 static int opx
, opy
;
1245 /* This is for ctrl-pan, where the viewport's position is directly
1246 proportional to the cursor position in the window (like the Xaw
1250 opx
= x
* PCB
->MaxWidth
/ view_width
;
1251 opy
= y
* PCB
->MaxHeight
/ view_height
;
1253 opx
= PCB
->MaxWidth
- opx
;
1255 opy
= PCB
->MaxHeight
- opy
;
1256 view_left_x
= opx
- view_width
/ 2 * view_zoom
;
1257 view_top_y
= opy
- view_height
/ 2 * view_zoom
;
1258 lesstif_pan_fixup ();
1260 /* This is the start of a regular pan. On the first click, we
1261 remember the coordinates where we "grabbed" the screen. */
1269 /* continued drag, we calculate how far we've moved the cursor and
1270 set the position accordingly. */
1274 view_left_x
= opx
+ (x
- ox
) * view_zoom
;
1276 view_left_x
= opx
- (x
- ox
) * view_zoom
;
1278 view_top_y
= opy
+ (y
- oy
) * view_zoom
;
1280 view_top_y
= opy
- (y
- oy
) * view_zoom
;
1281 lesstif_pan_fixup ();
1286 mod_changed (XKeyEvent
* e
, int set
)
1288 switch (XKeycodeToKeysym (display
, e
->keycode
, 0))
1292 shift_pressed
= set
;
1304 Pan (2, e
->x
, e
->y
);
1305 EventMoveCrosshair (Px (e
->x
), Py (e
->y
));
1306 AdjustAttachedObjects ();
1307 RestoreCrosshair (1);
1312 #define MAX_MOUSE_BUTTON 5
1313 Resource
*mouse_actions
[MAX_MOUSE_BUTTON
+2][16];
1316 do_mouse_action (int button
, int rel_mask
)
1319 int mods
= (shift_pressed
? M_Shift
: 0)
1320 + (ctrl_pressed
? M_Ctrl
: 0)
1321 + (alt_pressed
? M_Alt
: 0)
1323 Resource
*node
= mouse_actions
[button
][mods
];
1328 for (i
= 0; i
< node
->c
; i
++)
1329 if (node
->v
[i
].value
)
1330 if (hid_parse_actions (node
->v
[i
].value
, lesstif_call_action
))
1335 work_area_input (Widget w
, XtPointer v
, XEvent
* e
, Boolean
* ctd
)
1337 static int pressed_button
= 0;
1338 static int ignore_release
= 0;
1344 mod_changed (&(e
->xkey
), 1);
1345 if (lesstif_key_event (&(e
->xkey
)))
1350 mod_changed (&(e
->xkey
), 0);
1356 /*printf("click %d\n", e->xbutton.button); */
1357 if (lesstif_button_event (w
, e
))
1364 HideCrosshair (True
);
1365 pressed_button
= e
->xbutton
.button
;
1366 shift_pressed
= (e
->xbutton
.state
& ShiftMask
);
1367 ctrl_pressed
= (e
->xbutton
.state
& ControlMask
);
1368 alt_pressed
= (e
->xbutton
.state
& Mod1Mask
);
1370 do_mouse_action(e
->xbutton
.button
, 0);
1371 RestoreCrosshair (True
);
1375 if (e
->xbutton
.button
!= pressed_button
)
1377 lesstif_button_event (w
, e
);
1378 HideCrosshair (True
);
1380 do_mouse_action (e
->xbutton
.button
, M_Release
);
1381 RestoreCrosshair (True
);
1387 unsigned int keys_buttons
;
1388 int root_x
, root_y
, pos_x
, pos_y
;
1389 while (XCheckMaskEvent (display
, PointerMotionMask
, e
));
1390 XQueryPointer (display
, e
->xmotion
.window
, &root
, &child
,
1391 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
1392 shift_pressed
= (keys_buttons
& ShiftMask
);
1393 ctrl_pressed
= (keys_buttons
& ControlMask
);
1394 /*printf("m %d %d\n", Px(e->xmotion.x), Py(e->xmotion.y)); */
1395 crosshair_in_window
= 1;
1398 Pan (2, pos_x
, pos_y
);
1399 EventMoveCrosshair (Px (pos_x
), Py (pos_y
));
1405 crosshair_in_window
= 0;
1411 crosshair_in_window
= 1;
1413 EventMoveCrosshair (Px (e
->xcrossing
.x
), Py (e
->xcrossing
.y
));
1420 printf ("work_area: unknown event %d\n", e
->type
);
1426 res_wrap (char *value
)
1429 tmp
= resource_create (0);
1430 resource_add_val (tmp
, 0, value
, 0);
1435 parse_mods (char *value
)
1438 /* This works because "shift" and "alt" have no 'c' in them,
1440 if (strchr(value
, 's') || strchr(value
, 'S'))
1442 if (strchr(value
, 'c') || strchr(value
, 'C'))
1444 if (strchr(value
, 'a') || strchr(value
, 'A'))
1446 if (strchr(value
, 'u') || strchr(value
, 'U'))
1452 lesstif_note_mouse_resource (Resource
*res
)
1456 Resource
*orig_actions
[MAX_MOUSE_BUTTON
+2][16];
1458 fprintf(stderr
, "note mouse resource:\n");
1459 resource_dump (res
);
1462 for (bi
=0; bi
<res
->c
; bi
++)
1466 /* All mouse-related resources must be named. The name is the
1467 mouse button number. */
1468 if (!res
->v
[bi
].name
)
1470 else if (strcasecmp (res
->v
[bi
].name
, "left") == 0)
1472 else if (strcasecmp (res
->v
[bi
].name
, "middle") == 0)
1474 else if (strcasecmp (res
->v
[bi
].name
, "right") == 0)
1476 else if (strcasecmp (res
->v
[bi
].name
, "up") == 0)
1478 else if (strcasecmp (res
->v
[bi
].name
, "down") == 0)
1481 button_num
= atoi (res
->v
[bi
].name
);
1483 if (button_num
< 1 || button_num
> MAX_MOUSE_BUTTON
)
1486 if (res
->v
[bi
].value
)
1487 mouse_actions
[button_num
][0] = res_wrap (res
->v
[bi
].value
);
1489 if (res
->v
[bi
].subres
)
1491 Resource
*m
= res
->v
[bi
].subres
;
1494 for (mi
=0; mi
<m
->c
; mi
++)
1496 switch (resource_type (m
->v
[mi
]))
1498 case 1: /* subres only */
1499 mouse_actions
[button_num
][0] = m
->v
[mi
].subres
;
1502 case 10: /* value only */
1503 mouse_actions
[button_num
][0] = res_wrap (m
->v
[mi
].value
);
1506 case 101: /* name = subres */
1507 mods
= parse_mods (m
->v
[mi
].name
);
1508 mouse_actions
[button_num
][mods
] = m
->v
[mi
].subres
;
1511 case 110: /* name = value */
1512 mods
= parse_mods (m
->v
[mi
].name
);
1513 mouse_actions
[button_num
][mods
] = res_wrap (m
->v
[mi
].value
);
1521 printf("Configured mouse actions:\n");
1522 for (bi
=1; bi
<=MAX_MOUSE_BUTTON
; bi
++)
1523 for (mi
=0; mi
<16; mi
++)
1524 if (mouse_actions
[bi
][mi
])
1526 printf("\033[32m=== %c %c %c %c %d ===\033[0m\n",
1527 mi
& M_Release
? 'R' : '-',
1528 mi
& M_Alt
? 'A' : '-',
1529 mi
& M_Ctrl
? 'C' : '-',
1530 mi
& M_Shift
? 'S' : '-',
1532 resource_dump (mouse_actions
[bi
][mi
]);
1534 memcpy (orig_actions
, mouse_actions
, sizeof(mouse_actions
));
1537 for (bi
=0; bi
<=MAX_MOUSE_BUTTON
; bi
++)
1540 for (i
=15; i
>0; i
--)
1541 if (!mouse_actions
[bi
][i
])
1542 for (j
=i
-1; j
>=(i
&M_Release
?8:0); j
--)
1543 if (((i
& j
) == j
) && mouse_actions
[bi
][j
])
1545 mouse_actions
[bi
][i
] = mouse_actions
[bi
][j
];
1551 printf("Active mouse actions:\n");
1552 for (bi
=1; bi
<=MAX_MOUSE_BUTTON
; bi
++)
1553 for (mi
=0; mi
<16; mi
++)
1554 if (mouse_actions
[bi
][mi
])
1556 printf("\033[31m=== %c %c %c %c %d ===\033[0m",
1557 mi
& M_Release
? 'R' : '-',
1558 mi
& M_Alt
? 'A' : '-',
1559 mi
& M_Ctrl
? 'C' : '-',
1560 mi
& M_Shift
? 'S' : '-',
1562 if (!orig_actions
[bi
][mi
])
1564 resource_dump (mouse_actions
[bi
][mi
]);
1565 if (!orig_actions
[bi
][mi
])
1572 draw_right_cross (GC xor_gc
, int x
, int y
,
1573 int view_width
, int view_height
)
1575 XDrawLine (display
, window
, xor_gc
, 0, y
, view_width
, y
);
1576 XDrawLine (display
, window
, xor_gc
, x
, 0, x
, view_height
);
1580 draw_slanted_cross (GC xor_gc
, int x
, int y
,
1581 int view_width
, int view_height
)
1585 x0
= x
+ (view_height
- y
);
1586 x0
= MAX(0, MIN (x0
, view_width
));
1588 x1
= MAX(0, MIN (x1
, view_width
));
1589 y0
= y
+ (view_width
- x
);
1590 y0
= MAX(0, MIN (y0
, view_height
));
1592 y1
= MAX(0, MIN (y1
, view_height
));
1593 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1594 x0
= x
- (view_height
- y
);
1595 x0
= MAX(0, MIN (x0
, view_width
));
1597 x1
= MAX(0, MIN (x1
, view_width
));
1599 y0
= MAX(0, MIN (y0
, view_height
));
1600 y1
= y
- (view_width
- x
);
1601 y1
= MAX(0, MIN (y1
, view_height
));
1602 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1606 draw_dozen_cross (GC xor_gc
, int x
, int y
,
1607 int view_width
, int view_height
)
1610 double tan60
= sqrt (3);
1612 x0
= x
+ (view_height
- y
) / tan60
;
1613 x0
= MAX(0, MIN (x0
, view_width
));
1615 x1
= MAX(0, MIN (x1
, view_width
));
1616 y0
= y
+ (view_width
- x
) * tan60
;
1617 y0
= MAX(0, MIN (y0
, view_height
));
1619 y1
= MAX(0, MIN (y1
, view_height
));
1620 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1622 x0
= x
+ (view_height
- y
) * tan60
;
1623 x0
= MAX(0, MIN (x0
, view_width
));
1625 x1
= MAX(0, MIN (x1
, view_width
));
1626 y0
= y
+ (view_width
- x
) / tan60
;
1627 y0
= MAX(0, MIN (y0
, view_height
));
1629 y1
= MAX(0, MIN (y1
, view_height
));
1630 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1632 x0
= x
- (view_height
- y
) / tan60
;
1633 x0
= MAX(0, MIN (x0
, view_width
));
1635 x1
= MAX(0, MIN (x1
, view_width
));
1637 y0
= MAX(0, MIN (y0
, view_height
));
1638 y1
= y
- (view_width
- x
) * tan60
;
1639 y1
= MAX(0, MIN (y1
, view_height
));
1640 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1642 x0
= x
- (view_height
- y
) * tan60
;
1643 x0
= MAX(0, MIN (x0
, view_width
));
1645 x1
= MAX(0, MIN (x1
, view_width
));
1647 y0
= MAX(0, MIN (y0
, view_height
));
1648 y1
= y
- (view_width
- x
) / tan60
;
1649 y1
= MAX(0, MIN (y1
, view_height
));
1650 XDrawLine (display
, window
, xor_gc
, x0
, y0
, x1
, y1
);
1654 draw_crosshair (GC xor_gc
, int x
, int y
,
1655 int view_width
, int view_height
)
1657 draw_right_cross (xor_gc
, x
, y
, view_width
, view_height
);
1658 if (Crosshair
.shape
== Union_Jack_Crosshair_Shape
)
1659 draw_slanted_cross (xor_gc
, x
, y
, view_width
, view_height
);
1660 if (Crosshair
.shape
== Dozen_Crosshair_Shape
)
1661 draw_dozen_cross (xor_gc
, x
, y
, view_width
, view_height
);
1664 lesstif_show_crosshair (int show
)
1666 static int showing
= 0;
1668 static GC xor_gc
= 0;
1669 Pixel crosshair_color
;
1671 if (!crosshair_in_window
|| !window
)
1675 crosshair_color
= lesstif_parse_color (Settings
.CrosshairColor
) ^ bgcolor
;
1676 xor_gc
= XCreateGC (display
, window
, 0, 0);
1677 XSetFunction (display
, xor_gc
, GXxor
);
1678 XSetForeground (display
, xor_gc
, crosshair_color
);
1680 if (show
== showing
)
1684 sx
= Vx (crosshair_x
);
1685 sy
= Vy (crosshair_y
);
1689 draw_crosshair (xor_gc
, sx
, sy
, view_width
, view_height
);
1694 work_area_expose (Widget work_area
, void *me
,
1695 XmDrawingAreaCallbackStruct
* cbs
)
1700 e
= &(cbs
->event
->xexpose
);
1701 XSetFunction (display
, my_gc
, GXcopy
);
1702 XCopyArea (display
, main_pixmap
, window
, my_gc
,
1703 e
->x
, e
->y
, e
->width
, e
->height
, e
->x
, e
->y
);
1708 scroll_callback (Widget scroll
, int *view_dim
,
1709 XmScrollBarCallbackStruct
* cbs
)
1711 *view_dim
= cbs
->value
;
1712 lesstif_invalidate_all ();
1716 work_area_make_pixmaps (Dimension width
, Dimension height
)
1719 XFreePixmap (display
, main_pixmap
);
1721 XCreatePixmap (display
, window
, width
, height
,
1722 XDefaultDepth (display
, screen
));
1725 XFreePixmap (display
, mask_pixmap
);
1727 XCreatePixmap (display
, window
, width
, height
,
1728 XDefaultDepth (display
, screen
));
1732 XRenderFreePicture (display
, main_picture
);
1737 XRenderFreePicture (display
, mask_picture
);
1742 main_picture
= XRenderCreatePicture (display
, main_pixmap
,
1743 XRenderFindVisualFormat(display
,
1744 DefaultVisual(display
, screen
)), 0, 0);
1745 mask_picture
= XRenderCreatePicture (display
, mask_pixmap
,
1746 XRenderFindVisualFormat(display
,
1747 DefaultVisual(display
, screen
)), 0, 0);
1748 if (!main_picture
|| !mask_picture
)
1751 #endif /* HAVE_XRENDER */
1754 XFreePixmap (display
, mask_bitmap
);
1755 mask_bitmap
= XCreatePixmap (display
, window
, width
, height
, 1);
1757 pixmap
= use_mask
? main_pixmap
: mask_pixmap
;
1763 work_area_resize (Widget work_area
, void *me
,
1764 XmDrawingAreaCallbackStruct
* cbs
)
1767 Dimension width
, height
;
1772 stdarg (XtNwidth
, &width
);
1773 stdarg (XtNheight
, &height
);
1774 stdarg (XmNbackground
, &bgcolor
);
1775 XtGetValues (work_area
, args
, n
);
1777 view_height
= height
;
1779 color
.pixel
= bgcolor
;
1780 XQueryColor (display
, colormap
, &color
);
1782 bggreen
= color
.green
;
1783 bgblue
= color
.blue
;
1788 work_area_make_pixmaps (view_width
, view_height
);
1794 work_area_first_expose (Widget work_area
, void *me
,
1795 XmDrawingAreaCallbackStruct
* cbs
)
1798 Dimension width
, height
;
1799 static char dashes
[] = { 4, 4 };
1801 window
= XtWindow (work_area
);
1802 my_gc
= XCreateGC (display
, window
, 0, 0);
1804 arc1_gc
= XCreateGC (display
, window
, 0, 0);
1805 c
= lesstif_parse_color ("#804000");
1806 XSetForeground (display
, arc1_gc
, c
);
1807 arc2_gc
= XCreateGC (display
, window
, 0, 0);
1808 c
= lesstif_parse_color ("#004080");
1809 XSetForeground (display
, arc2_gc
, c
);
1810 XSetLineAttributes (display
, arc1_gc
, 1, LineOnOffDash
, 0, 0);
1811 XSetLineAttributes (display
, arc2_gc
, 1, LineOnOffDash
, 0, 0);
1812 XSetDashes (display
, arc1_gc
, 0, dashes
, 2);
1813 XSetDashes (display
, arc2_gc
, 0, dashes
, 2);
1816 stdarg (XtNwidth
, &width
);
1817 stdarg (XtNheight
, &height
);
1818 stdarg (XmNbackground
, &bgcolor
);
1819 XtGetValues (work_area
, args
, n
);
1821 view_height
= height
;
1823 offlimit_color
= lesstif_parse_color (Settings
.OffLimitColor
);
1824 grid_color
= lesstif_parse_color (Settings
.GridColor
);
1826 bg_gc
= XCreateGC (display
, window
, 0, 0);
1827 XSetForeground (display
, bg_gc
, bgcolor
);
1829 work_area_make_pixmaps (width
, height
);
1834 XRenderPictureAttributes pa
;
1835 XRenderColor a
= {0, 0, 0, 0x8000};
1837 pale_pixmap
= XCreatePixmap (display
, window
, 1, 1, 8);
1839 pale_picture
= XRenderCreatePicture (display
, pale_pixmap
,
1840 XRenderFindStandardFormat(display
, PictStandardA8
),
1843 XRenderFillRectangle(display
, PictOpSrc
, pale_picture
, &a
, 0, 0, 1, 1);
1847 #endif /* HAVE_XRENDER */
1849 clip_gc
= XCreateGC (display
, window
, 0, 0);
1850 bset_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1851 XSetForeground (display
, bset_gc
, 1);
1852 bclear_gc
= XCreateGC (display
, mask_bitmap
, 0, 0);
1853 XSetForeground (display
, bclear_gc
, 0);
1855 XtRemoveCallback (work_area
, XmNexposeCallback
,
1856 (XtCallbackProc
) work_area_first_expose
, 0);
1857 XtAddCallback (work_area
, XmNexposeCallback
,
1858 (XtCallbackProc
) work_area_expose
, 0);
1859 lesstif_invalidate_all ();
1863 make_message (char *name
, Widget left
, int resizeable
)
1869 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
1870 stdarg (XmNleftWidget
, XtParent(left
));
1874 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1876 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1877 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1878 stdarg (XmNshadowType
, XmSHADOW_IN
);
1879 stdarg (XmNshadowThickness
, 1);
1880 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1881 stdarg (XmNmarginWidth
, 4);
1882 stdarg (XmNmarginHeight
, 1);
1884 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
1885 f
= XmCreateForm (messages
, name
, args
, n
);
1888 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1889 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1890 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1891 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1892 w
= XmCreateLabel (f
, name
, args
, n
);
1898 lesstif_do_export (HID_Attr_Val
* options
)
1900 Dimension width
, height
;
1902 Widget work_area_frame
;
1905 stdarg (XtNwidth
, &width
);
1906 stdarg (XtNheight
, &height
);
1907 XtGetValues (appwidget
, args
, n
);
1911 if (width
> XDisplayWidth (display
, screen
))
1912 width
= XDisplayWidth (display
, screen
);
1915 if (height
> XDisplayHeight (display
, screen
))
1916 height
= XDisplayHeight (display
, screen
);
1919 stdarg (XmNwidth
, width
);
1920 stdarg (XmNheight
, height
);
1921 XtSetValues (appwidget
, args
, n
);
1923 stdarg (XmNspacing
, 0);
1924 mainwind
= XmCreateMainWindow (appwidget
, "mainWind", args
, n
);
1925 XtManageChild (mainwind
);
1928 stdarg (XmNmarginWidth
, 0);
1929 stdarg (XmNmarginHeight
, 0);
1930 menu
= lesstif_menu (mainwind
, "menubar", args
, n
);
1931 XtManageChild (menu
);
1934 stdarg (XmNshadowType
, XmSHADOW_IN
);
1936 XmCreateFrame (mainwind
, "work_area_frame", args
, n
);
1937 XtManageChild (work_area_frame
);
1940 do_color (Settings
.BackgroundColor
, XmNbackground
);
1941 work_area
= XmCreateDrawingArea (work_area_frame
, "work_area", args
, n
);
1942 XtManageChild (work_area
);
1943 XtAddCallback (work_area
, XmNexposeCallback
,
1944 (XtCallbackProc
) work_area_first_expose
, 0);
1945 XtAddCallback (work_area
, XmNresizeCallback
,
1946 (XtCallbackProc
) work_area_resize
, 0);
1947 /* A regular callback won't work here, because lesstif swallows any
1948 Ctrl<Button>1 event. */
1949 XtAddEventHandler (work_area
,
1950 ButtonPressMask
| ButtonReleaseMask
1951 | PointerMotionMask
| PointerMotionHintMask
1952 | KeyPressMask
| KeyReleaseMask
1953 | EnterWindowMask
| LeaveWindowMask
,
1954 0, work_area_input
, 0);
1957 stdarg (XmNorientation
, XmVERTICAL
);
1958 stdarg (XmNprocessingDirection
, XmMAX_ON_BOTTOM
);
1959 stdarg (XmNmaximum
, PCB
->MaxHeight
? PCB
->MaxHeight
: 1);
1960 vscroll
= XmCreateScrollBar (mainwind
, "vscroll", args
, n
);
1961 XtAddCallback (vscroll
, XmNvalueChangedCallback
,
1962 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_top_y
);
1963 XtAddCallback (vscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1964 (XtPointer
) & view_top_y
);
1965 XtManageChild (vscroll
);
1968 stdarg (XmNorientation
, XmHORIZONTAL
);
1969 stdarg (XmNmaximum
, PCB
->MaxWidth
? PCB
->MaxWidth
: 1);
1970 hscroll
= XmCreateScrollBar (mainwind
, "hscroll", args
, n
);
1971 XtAddCallback (hscroll
, XmNvalueChangedCallback
,
1972 (XtCallbackProc
) scroll_callback
, (XtPointer
) & view_left_x
);
1973 XtAddCallback (hscroll
, XmNdragCallback
, (XtCallbackProc
) scroll_callback
,
1974 (XtPointer
) & view_left_x
);
1975 XtManageChild (hscroll
);
1978 stdarg (XmNresize
, True
);
1979 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
1980 messages
= XmCreateForm (mainwind
, "messages", args
, n
);
1981 XtManageChild (messages
);
1984 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1985 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1986 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1987 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
1988 stdarg (XmNalignment
, XmALIGNMENT_CENTER
);
1989 stdarg (XmNshadowThickness
, 2);
1990 m_click
= XmCreateLabel (messages
, "click", args
, n
);
1993 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
1994 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
1995 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
1996 stdarg (XmNlabelString
, XmStringCreateLocalized ("Command: "));
1997 m_cmd_label
= XmCreateLabel (messages
, "command", args
, n
);
2000 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
2001 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
2002 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
2003 stdarg (XmNleftWidget
, m_cmd_label
);
2004 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
2005 stdarg (XmNshadowThickness
, 1);
2006 stdarg (XmNhighlightThickness
, 0);
2007 stdarg (XmNmarginWidth
, 2);
2008 stdarg (XmNmarginHeight
, 2);
2009 m_cmd
= XmCreateTextField (messages
, "command", args
, n
);
2010 XtAddCallback (m_cmd
, XmNactivateCallback
,
2011 (XtCallbackProc
) command_callback
, 0);
2012 XtAddCallback (m_cmd
, XmNlosingFocusCallback
,
2013 (XtCallbackProc
) command_callback
, 0);
2014 XtAddEventHandler (m_cmd
, KeyPressMask
, 0, command_event_handler
, 0);
2016 m_mark
= make_message ("m_mark", 0, 0);
2017 m_crosshair
= make_message ("m_crosshair", m_mark
, 0);
2018 m_grid
= make_message ("m_grid", m_crosshair
, 1);
2019 m_zoom
= make_message ("m_zoom", m_grid
, 1);
2020 lesstif_m_layer
= make_message ("m_layer", m_zoom
, 0);
2021 m_mode
= make_message ("m_mode", lesstif_m_layer
, 1);
2022 m_rats
= make_message ("m_rats", m_mode
, 1);
2023 m_status
= make_message ("m_status", m_mode
, 1);
2025 XtUnmanageChild (XtParent (m_mark
));
2026 XtUnmanageChild (XtParent (m_rats
));
2029 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
2030 XtSetValues (XtParent (m_status
), args
, n
);
2032 /* We'll use this later. */
2034 stdarg (XmNleftWidget
, XtParent (m_mark
));
2035 XtSetValues (XtParent (m_crosshair
), args
, n
);
2038 stdarg (XmNmessageWindow
, messages
);
2039 XtSetValues (mainwind
, args
, n
);
2041 if (background_image_file
)
2042 LoadBackgroundImage (background_image_file
);
2044 XtRealizeWidget (appwidget
);
2049 XtAppNextEvent (app_context
, &e
);
2050 XtDispatchEvent (&e
);
2053 PCBChanged (0, 0, 0, 0);
2055 XtAppMainLoop (app_context
);
2059 XrmOptionDescRec lesstif_options
[] = {
2062 XtResource lesstif_resources
[] = {
2074 cvtres_string_to_double (Display
* d
, XrmValue
* args
, Cardinal
* num_args
,
2075 XrmValue
* from
, XrmValue
* to
,
2076 XtPointer
* converter_data
)
2079 rv
= strtod ((char *) from
->addr
, 0);
2081 *(double *) to
->addr
= rv
;
2083 to
->addr
= (XPointer
) & rv
;
2084 to
->size
= sizeof (rv
);
2089 mainwind_delete_cb ()
2091 hid_action ("Quit");
2095 lesstif_listener_cb (XtPointer client_data
, int *fid
, XtInputId
*id
)
2100 if ((nbytes
= read (*fid
, buf
, BUFSIZ
)) == -1)
2101 perror ("lesstif_listener_cb");
2106 hid_parse_actions (buf
, NULL
);
2112 lesstif_parse_arguments (int *argc
, char ***argv
)
2116 int acount
= 0, amax
;
2117 int rcount
= 0, rmax
;
2119 XrmOptionDescRec
*new_options
;
2120 XtResource
*new_resources
;
2121 val_union
*new_values
;
2122 int render_event
, render_error
;
2124 XtSetTypeConverter (XtRString
,
2126 cvtres_string_to_double
, NULL
, 0, XtCacheAll
, NULL
);
2128 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2129 for (i
= 0; i
< ha
->n
; i
++)
2131 HID_Attribute
*a
= ha
->attributes
+ i
;
2148 amax
= acount
+ XtNumber (lesstif_options
);
2153 new_options
= malloc ((amax
+ 1) * sizeof (XrmOptionDescRec
));
2156 memcpy (new_options
+ acount
, lesstif_options
, sizeof (lesstif_options
));
2161 rmax
= rcount
+ XtNumber (lesstif_resources
);
2166 new_resources
= malloc ((rmax
+ 1) * sizeof (XtResource
));
2167 new_values
= malloc ((rmax
+ 1) * sizeof (val_union
));
2169 memcpy (new_resources
+ acount
, lesstif_resources
,
2170 sizeof (lesstif_resources
));
2174 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2175 for (i
= 0; i
< ha
->n
; i
++)
2177 HID_Attribute
*a
= ha
->attributes
+ i
;
2178 XrmOptionDescRec
*o
= new_options
+ acount
;
2179 char *tmpopt
, *tmpres
;
2180 XtResource
*r
= new_resources
+ rcount
;
2182 tmpopt
= (char *) malloc (strlen (a
->name
) + 3);
2183 tmpopt
[0] = tmpopt
[1] = '-';
2184 strcpy (tmpopt
+ 2, a
->name
);
2187 tmpres
= (char *) malloc (strlen (a
->name
) + 2);
2189 strcpy (tmpres
+ 1, a
->name
);
2190 o
->specifier
= tmpres
;
2198 o
->argKind
= XrmoptionSepArg
;
2203 o
->argKind
= XrmoptionNoArg
;
2211 r
->resource_name
= a
->name
;
2212 r
->resource_class
= a
->name
;
2213 r
->resource_offset
= sizeof (val_union
) * rcount
;
2218 r
->resource_type
= XtRInt
;
2219 r
->default_type
= XtRInt
;
2220 r
->resource_size
= sizeof (int);
2221 r
->default_addr
= &(a
->default_val
.int_value
);
2225 r
->resource_type
= XtRDouble
;
2226 r
->default_type
= XtRDouble
;
2227 r
->resource_size
= sizeof (double);
2228 r
->default_addr
= &(a
->default_val
.real_value
);
2233 r
->resource_type
= XtRString
;
2234 r
->default_type
= XtRString
;
2235 r
->resource_size
= sizeof (char *);
2236 r
->default_addr
= a
->default_val
.str_value
;
2240 r
->resource_type
= XtRBoolean
;
2241 r
->default_type
= XtRInt
;
2242 r
->resource_size
= sizeof (int);
2243 r
->default_addr
= &(a
->default_val
.int_value
);
2251 for (i
= 0; i
< XtNumber (lesstif_resources
); i
++)
2253 XtResource
*r
= new_resources
+ rcount
;
2254 r
->resource_offset
= sizeof (val_union
) * rcount
;
2260 stdarg (XmNdeleteResponse
, XmDO_NOTHING
);
2262 appwidget
= XtAppInitialize (&app_context
,
2264 new_options
, amax
, argc
, *argv
, 0, args
, n
);
2266 display
= XtDisplay (appwidget
);
2267 screen_s
= XtScreen (appwidget
);
2268 screen
= XScreenNumberOfScreen (screen_s
);
2269 colormap
= XDefaultColormap (display
, screen
);
2271 close_atom
= XmInternAtom (display
, "WM_DELETE_WINDOW", 0);
2272 XmAddWMProtocolCallback (appwidget
, close_atom
,
2273 (XtCallbackProc
) mainwind_delete_cb
, 0);
2275 /* XSynchronize(display, True); */
2277 XtGetApplicationResources (appwidget
, new_values
, new_resources
,
2281 use_xrender
= XRenderQueryExtension (display
, &render_event
, &render_error
) &&
2282 XRenderFindVisualFormat (display
, DefaultVisual(display
, screen
));
2283 #endif /* HAVE_XRENDER */
2286 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
2287 for (i
= 0; i
< ha
->n
; i
++)
2289 HID_Attribute
*a
= ha
->attributes
+ i
;
2290 val_union
*v
= new_values
+ rcount
;
2295 *(int *) a
->value
= v
->i
;
2297 a
->default_val
.int_value
= v
->i
;
2302 *(char *) a
->value
= v
->i
;
2304 a
->default_val
.int_value
= v
->i
;
2309 *(double *) a
->value
= v
->f
;
2311 a
->default_val
.real_value
= v
->f
;
2317 *(char **) a
->value
= v
->s
;
2319 a
->default_val
.str_value
= v
->s
;
2327 /* redefine colormap, if requested via "-install" */
2328 if (use_private_colormap
)
2330 colormap
= XCopyColormapAndFree (display
, colormap
);
2331 XtVaSetValues (appwidget
, XtNcolormap
, colormap
, NULL
);
2334 /* listen on standard input for actions */
2337 XtAppAddInput (app_context
, fileno (stdin
), (XtPointer
) XtInputReadMask
,
2338 lesstif_listener_cb
, NULL
);
2345 static XPoint
*points
= 0;
2346 static int npoints
= 0;
2347 int x1
, y1
, x2
, y2
, n
, prevx
;
2349 static GC grid_gc
= 0;
2351 if (!Settings
.DrawGrid
)
2353 if (Vz (PCB
->Grid
) < MIN_GRID_DISTANCE
)
2357 grid_gc
= XCreateGC (display
, window
, 0, 0);
2358 XSetFunction (display
, grid_gc
, GXxor
);
2359 XSetForeground (display
, grid_gc
, grid_color
);
2363 x2
= GRIDFIT_X (Px (0), PCB
->Grid
);
2364 x1
= GRIDFIT_X (Px (view_width
), PCB
->Grid
);
2367 if (Vx (x1
) >= view_width
)
2372 x1
= GRIDFIT_X (Px (0), PCB
->Grid
);
2373 x2
= GRIDFIT_X (Px (view_width
), PCB
->Grid
);
2376 if (Vx (x2
) >= view_width
)
2381 y2
= GRIDFIT_Y (Py (0), PCB
->Grid
);
2382 y1
= GRIDFIT_Y (Py (view_height
), PCB
->Grid
);
2385 if (Vy (y1
) >= view_height
)
2390 y1
= GRIDFIT_Y (Py (0), PCB
->Grid
);
2391 y2
= GRIDFIT_Y (Py (view_height
), PCB
->Grid
);
2394 if (Vy (y2
) >= view_height
)
2397 n
= (int) ((x2
- x1
) / PCB
->Grid
+ 0.5) + 1;
2402 MyRealloc (points
, npoints
* sizeof (XPoint
), "lesstif_draw_grid");
2406 for (x
= x1
; x
<= x2
; x
+= PCB
->Grid
)
2412 points
[n
].x
-= prevx
;
2418 for (y
= y1
; y
<= y2
; y
+= PCB
->Grid
)
2422 XDrawPoints (display
, pixmap
, grid_gc
, points
, n
, CoordModePrevious
);
2427 coords_to_widget (int x
, int y
, Widget w
, int prev_state
)
2429 int this_state
= prev_state
;
2430 static char buf
[60];
2435 if (Settings
.grid_units_mm
)
2440 g
= PCB_TO_MM (PCB
->Grid
);
2445 dx
= PCB_TO_MIL (x
);
2446 dy
= PCB_TO_MIL (y
);
2447 g
= PCB_TO_MIL (PCB
->Grid
);
2449 if (x
< 0 && prev_state
>= 0)
2451 else if (((int) (g
* 10000 + 0.5) % 10000) == 0)
2453 const char *fmt
= prev_state
< 0 ? "%+d, %+d" : "%d, %d";
2454 sprintf (buf
, fmt
, (int) (dx
+ 0.5), (int) (dy
+ 0.5));
2455 this_state
= 2 + Settings
.grid_units_mm
;
2458 else if (PCB
->Grid
<= 20 && Settings
.grid_units_mm
)
2460 const char *fmt
= prev_state
< 0 ? "%+.3f, %+.3f" : "%.3f, %.3f";
2461 sprintf (buf
, fmt
, dx
, dy
);
2462 this_state
= 4 + Settings
.grid_units_mm
;
2467 const char *fmt
= prev_state
< 0 ? "%+.2f, %+.2f" : "%.2f, %.2f";
2468 sprintf (buf
, fmt
, dx
, dy
);
2469 this_state
= 4 + Settings
.grid_units_mm
;
2472 if (prev_state
< 0 && (x
|| y
))
2474 int angle
= atan2 (dy
, -dx
) * 180 / M_PI
;
2475 double dist
= sqrt (dx
* dx
+ dy
* dy
);
2477 sprintf (buf
+ strlen (buf
), " (%.2f", dist
);
2479 sprintf (buf
+ strlen (buf
), " (%d", (int) (dist
+ 0.5));
2480 sprintf (buf
+ strlen (buf
), ", %d\260)", angle
);
2482 ms
= XmStringCreateLocalized (buf
);
2484 stdarg (XmNlabelString
, ms
);
2485 XtSetValues (w
, args
, n
);
2490 pcb2str (int pcbval
)
2492 static char buf
[20][20];
2493 static int bufp
= 0;
2496 bufp
= (bufp
+ 1) % 20;
2497 if (Settings
.grid_units_mm
)
2498 d
= PCB_TO_MM (pcbval
);
2500 d
= PCB_TO_MIL (pcbval
);
2502 if ((int) (d
* 100 + 0.5) == (int) (d
+ 0.005) * 100)
2503 sprintf (buf
[bufp
], "%d", (int) d
);
2505 sprintf (buf
[bufp
], "%.2f", d
);
2509 #define u(x) pcb2str(x)
2513 lesstif_update_status_line ()
2516 char *s45
= cur_clip ();
2520 switch (Settings
.Mode
)
2523 sprintf (buf
, "%s/%s \370=%s", u (S
.ViaThickness
),
2524 u (S
.Keepaway
), u (S
.ViaDrillingHole
));
2528 sprintf (buf
, "%s/%s %s", u (S
.LineThickness
), u (S
.Keepaway
), s45
);
2530 case RECTANGLE_MODE
:
2532 sprintf (buf
, "%s %s", u (S
.Keepaway
), s45
);
2535 sprintf (buf
, "%s", u (S
.TextScale
));
2539 case INSERTPOINT_MODE
:
2540 case RUBBERBANDMOVE_MODE
:
2541 sprintf (buf
, "%s", s45
);
2544 case PASTEBUFFER_MODE
:
2553 xs
= XmStringCreateLocalized (buf
);
2555 stdarg (XmNlabelString
, xs
);
2556 XtSetValues (m_status
, args
, n
);
2562 static int idle_proc_set
= 0;
2563 static int need_redraw
= 0;
2566 idle_proc (XtPointer dummy
)
2572 lesstif_use_mask (0);
2574 pixmap
= main_pixmap
;
2579 region
.X2
= Px (view_width
);
2580 region
.Y2
= Py (view_height
);
2583 int tmp
= region
.X1
;
2584 region
.X1
= region
.X2
;
2589 int tmp
= region
.Y1
;
2590 region
.Y1
= region
.Y2
;
2593 XSetForeground (display
, bg_gc
, bgcolor
);
2594 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0, mx
, my
);
2595 if (region
.X2
> PCB
->MaxWidth
|| region
.Y2
> PCB
->MaxHeight
)
2597 XSetForeground (display
, bg_gc
, offlimit_color
);
2598 if (region
.X2
> PCB
->MaxWidth
)
2600 mx
= Vx (PCB
->MaxWidth
);
2602 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0,
2605 XFillRectangle (display
, main_pixmap
, bg_gc
, mx
+1, 0,
2606 view_width
- mx
+ 1, my
);
2609 if (region
.Y2
> PCB
->MaxHeight
)
2611 my
= Vy (PCB
->MaxHeight
) + 1;
2613 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, 0, mx
,
2616 XFillRectangle (display
, main_pixmap
, bg_gc
, 0, my
, mx
,
2617 view_height
- my
+ 1);
2620 DrawBackgroundImage();
2621 hid_expose_callback (&lesstif_gui
, ®ion
, 0);
2623 lesstif_use_mask (0);
2624 XSetFunction (display
, my_gc
, GXcopy
);
2625 XCopyArea (display
, main_pixmap
, window
, my_gc
, 0, 0, view_width
,
2633 static int c_x
= -2, c_y
= -2;
2634 static MarkType saved_mark
;
2635 if (crosshair_x
!= c_x
|| crosshair_y
!= c_y
2636 || memcmp (&saved_mark
, &Marked
, sizeof (MarkType
)))
2638 static int last_state
= 0;
2639 static int this_state
= 0;
2645 coords_to_widget (crosshair_x
, crosshair_y
, m_crosshair
,
2648 coords_to_widget (crosshair_x
- Marked
.X
, crosshair_y
- Marked
.Y
,
2651 if (Marked
.status
!= saved_mark
.status
)
2655 XtManageChild (XtParent (m_mark
));
2656 XtManageChild (m_mark
);
2658 stdarg (XmNleftAttachment
, XmATTACH_WIDGET
);
2659 stdarg (XmNleftWidget
, XtParent (m_mark
));
2660 XtSetValues (XtParent (m_crosshair
), args
, n
);
2665 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
2666 XtSetValues (XtParent (m_crosshair
), args
, n
);
2667 XtUnmanageChild (XtParent (m_mark
));
2669 last_state
= this_state
+ 100;
2671 memcpy (&saved_mark
, &Marked
, sizeof (MarkType
));
2673 /* This is obtuse. We want to enable XmRESIZE_ANY long enough
2674 to shrink to fit the new format (if any), then switch it
2675 back to XmRESIZE_GROW to prevent it from shrinking due to
2676 changes in the number of actual digits printed. Thus, when
2677 you switch from a small grid and %.2f formats to a large
2678 grid and %d formats, you aren't punished with a wide and
2679 mostly white-space label widget. "this_state" indicates
2680 which of the above formats we're using. "last_state" is
2681 either zero (when resizing) or the same as "this_state"
2682 (when grow-only), or a non-zero but not "this_state" which
2683 means we need to start a resize cycle. */
2684 if (this_state
!= last_state
&& last_state
)
2687 stdarg (XmNresizePolicy
, XmRESIZE_ANY
);
2688 XtSetValues (XtParent (m_mark
), args
, n
);
2689 XtSetValues (XtParent (m_crosshair
), args
, n
);
2692 else if (this_state
!= last_state
)
2695 stdarg (XmNresizePolicy
, XmRESIZE_GROW
);
2696 XtSetValues (XtParent (m_mark
), args
, n
);
2697 XtSetValues (XtParent (m_crosshair
), args
, n
);
2698 last_state
= this_state
;
2704 static double old_grid
= -1;
2705 static int old_gx
, old_gy
, old_mm
;
2707 if (PCB
->Grid
!= old_grid
2708 || PCB
->GridOffsetX
!= old_gx
2709 || PCB
->GridOffsetY
!= old_gy
|| Settings
.grid_units_mm
!= old_mm
)
2711 static char buf
[100];
2714 old_grid
= PCB
->Grid
;
2715 old_gx
= PCB
->GridOffsetX
;
2716 old_gy
= PCB
->GridOffsetY
;
2717 old_mm
= Settings
.grid_units_mm
;
2720 strcpy (buf
, "No Grid");
2724 if (Settings
.grid_units_mm
)
2726 g
= PCB_TO_MM (old_grid
);
2727 x
= PCB_TO_MM (old_gx
);
2728 y
= PCB_TO_MM (old_gy
);
2733 g
= PCB_TO_MIL (old_grid
);
2734 x
= PCB_TO_MIL (old_gx
);
2735 y
= PCB_TO_MIL (old_gy
);
2739 sprintf (buf
, "%g %s @%g,%g", g
, u
, x
, y
);
2741 sprintf (buf
, "%g %s", g
, u
);
2743 ms
= XmStringCreateLocalized (buf
);
2745 stdarg (XmNlabelString
, ms
);
2746 XtSetValues (m_grid
, args
, n
);
2751 static double old_zoom
= -1;
2752 static int old_zoom_units
= -1;
2753 if (view_zoom
!= old_zoom
|| Settings
.grid_units_mm
!= old_zoom_units
)
2755 static char buf
[100];
2760 old_zoom
= view_zoom
;
2761 old_zoom_units
= Settings
.grid_units_mm
;
2763 if (Settings
.grid_units_mm
)
2765 g
= PCB_TO_MM (view_zoom
);
2770 g
= PCB_TO_MIL (view_zoom
);
2773 if ((int) (g
* 100 + 0.5) == (int) (g
+ 0.005) * 100)
2774 sprintf (buf
, "%d %s/pix", (int) (g
+ 0.005), units
);
2776 sprintf (buf
, "%.2f %s/pix", g
, units
);
2777 ms
= XmStringCreateLocalized (buf
);
2779 stdarg (XmNlabelString
, ms
);
2780 XtSetValues (m_zoom
, args
, n
);
2785 if (old_cursor_mode
!= Settings
.Mode
)
2790 static int free_cursor
= 0;
2792 old_cursor_mode
= Settings
.Mode
;
2793 switch (Settings
.Mode
)
2797 cursor
= XC_X_cursor
;
2807 case RECTANGLE_MODE
:
2809 cursor
= XC_ul_angle
;
2813 cursor
= XC_sb_up_arrow
;
2815 case PASTEBUFFER_MODE
:
2825 cursor
= XC_exchange
;
2833 cursor
= XC_crosshair
;
2837 cursor
= XC_crosshair
;
2839 case INSERTPOINT_MODE
:
2843 case RUBBERBANDMOVE_MODE
:
2845 cursor
= XC_top_left_corner
;
2849 cursor
= XC_iron_cross
;
2853 cursor
= XC_question_arrow
;
2858 cursor
= XC_draped_box
;
2860 cursor
= XC_left_ptr
;
2867 ms
= XmStringCreateLocalized (s
);
2869 stdarg (XmNlabelString
, ms
);
2870 XtSetValues (m_mode
, args
, n
);
2874 XFreeCursor (display
, my_cursor
);
2879 static Pixmap nocur_source
= 0;
2880 static Pixmap nocur_mask
= 0;
2881 static Cursor nocursor
= 0;
2882 if (nocur_source
== 0)
2886 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2888 XCreateBitmapFromData (display
, window
, "\0", 1, 1);
2890 fg
.red
= fg
.green
= fg
.blue
= 65535;
2891 bg
.red
= bg
.green
= bg
.blue
= 0;
2892 fg
.flags
= bg
.flags
= DoRed
| DoGreen
| DoBlue
;
2893 nocursor
= XCreatePixmapCursor (display
, nocur_source
,
2894 nocur_mask
, &fg
, &bg
, 0, 0);
2896 my_cursor
= nocursor
;
2900 my_cursor
= XCreateFontCursor (display
, cursor
);
2903 XDefineCursor (display
, window
, my_cursor
);
2904 lesstif_update_status_line ();
2908 static char *old_clip
= 0;
2909 static int old_tscale
= -1;
2910 char *new_clip
= cur_clip ();
2912 if (new_clip
!= old_clip
|| Settings
.TextScale
!= old_tscale
)
2914 lesstif_update_status_line ();
2915 old_clip
= new_clip
;
2916 old_tscale
= Settings
.TextScale
;
2921 static int old_nrats
= -1;
2922 static char buf
[20];
2924 if (old_nrats
!= PCB
->Data
->RatN
)
2926 old_nrats
= PCB
->Data
->RatN
;
2927 sprintf(buf
, "%d rat%s", PCB
->Data
->RatN
, PCB
->Data
->RatN
== 1 ? "" : "s");
2928 if (PCB
->Data
->RatN
)
2930 XtManageChild(XtParent(m_rats
));
2931 XtManageChild(m_rats
);
2933 stdarg (XmNleftWidget
, m_rats
);
2934 XtSetValues (XtParent (m_status
), args
, n
);
2938 stdarg (XmNlabelString
, XmStringCreateLocalized (buf
));
2939 XtSetValues (m_rats
, args
, n
);
2941 if (!PCB
->Data
->RatN
)
2944 stdarg (XmNleftWidget
, m_mode
);
2945 XtSetValues (XtParent (m_status
), args
, n
);
2946 XtUnmanageChild(XtParent(m_rats
));
2951 lesstif_update_widget_flags ();
2959 lesstif_need_idle_proc ()
2961 if (idle_proc_set
|| window
== 0)
2963 XtAppAddWorkProc (app_context
, idle_proc
, 0);
2968 lesstif_invalidate_wh (int x
, int y
, int width
, int height
, int last
)
2970 if (!last
|| !window
)
2978 lesstif_invalidate_lr (int l
, int r
, int t
, int b
, int last
)
2980 lesstif_invalidate_wh (l
, t
, r
- l
+ 1, b
- t
+ 1, last
);
2984 lesstif_invalidate_all (void)
2986 lesstif_invalidate_wh (0, 0, PCB
->MaxWidth
, PCB
->MaxHeight
, 1);
2990 lesstif_set_layer (const char *name
, int group
, int empty
)
2993 if (idx
>= 0 && idx
< max_layer
)
2995 idx
= PCB
->LayerGroups
.Entries
[idx
][0];
2997 if (idx
== LayerStack
[0]
2998 || GetLayerGroupNumberByNumber (idx
) ==
2999 GetLayerGroupNumberByNumber (LayerStack
[0]))
3009 if (idx
>= 0 && idx
< max_layer
+ 2)
3010 return pinout
? 1 : PCB
->Data
->Layer
[idx
].On
;
3013 switch (SL_TYPE (idx
))
3016 return pinout
? 0 : PCB
->InvisibleObjectsOn
;
3018 if (SL_MYSIDE (idx
) && !pinout
)
3019 return TEST_FLAG (SHOWMASKFLAG
, PCB
);
3022 if (SL_MYSIDE (idx
) || pinout
)
3023 return PCB
->ElementOn
;
3036 lesstif_make_gc (void)
3038 hidGC rv
= malloc (sizeof (hid_gc_struct
));
3039 memset (rv
, 0, sizeof (hid_gc_struct
));
3040 rv
->me_pointer
= &lesstif_gui
;
3045 lesstif_destroy_gc (hidGC gc
)
3051 lesstif_use_mask (int use_it
)
3053 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) &&
3056 if ((use_it
== 0) == (use_mask
== 0))
3063 /* printf("use_mask(%d)\n", use_it); */
3067 XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
,
3068 XDefaultDepth (display
, screen
));
3069 mask_bitmap
= XCreatePixmap (display
, window
, pixmap_w
, pixmap_h
, 1);
3073 pixmap
= mask_pixmap
;
3074 XSetForeground (display
, my_gc
, 0);
3075 XSetFunction (display
, my_gc
, GXcopy
);
3076 XFillRectangle (display
, mask_pixmap
, my_gc
,
3077 0, 0, view_width
, view_height
);
3078 XFillRectangle (display
, mask_bitmap
, bclear_gc
,
3079 0, 0, view_width
, view_height
);
3083 pixmap
= main_pixmap
;
3087 XRenderPictureAttributes pa
;
3089 pa
.clip_mask
= mask_bitmap
;
3090 XRenderChangePicture(display
, main_picture
, CPClipMask
, &pa
);
3091 XRenderComposite(display
, PictOpOver
, mask_picture
, pale_picture
,
3092 main_picture
, 0, 0, 0, 0, 0, 0, view_width
, view_height
);
3095 #endif /* HAVE_XRENDER */
3097 XSetClipMask (display
, clip_gc
, mask_bitmap
);
3098 XCopyArea (display
, mask_pixmap
, main_pixmap
, clip_gc
,
3099 0, 0, view_width
, view_height
, 0, 0);
3105 lesstif_set_color (hidGC gc
, const char *name
)
3107 static void *cache
= 0;
3109 static XColor color
, exact_color
;
3115 gc
->colorname
= name
;
3116 if (strcmp (name
, "erase") == 0)
3118 gc
->color
= bgcolor
;
3121 else if (strcmp (name
, "drill") == 0)
3123 gc
->color
= offlimit_color
;
3126 else if (hid_cache_color (0, name
, &cval
, &cache
))
3128 gc
->color
= cval
.lval
;
3133 if (!XAllocNamedColor (display
, colormap
, name
, &color
, &exact_color
))
3134 color
.pixel
= WhitePixel (display
, screen
);
3136 printf ("lesstif_set_color `%s' %08x rgb/%d/%d/%d\n",
3137 name
, color
.pixel
, color
.red
, color
.green
, color
.blue
);
3139 cval
.lval
= gc
->color
= color
.pixel
;
3140 hid_cache_color (1, name
, &cval
, &cache
);
3145 static int lastcolor
= -1, lastfade
= -1;
3146 if (gc
->color
== lastcolor
)
3147 gc
->color
= lastfade
;
3150 lastcolor
= gc
->color
;
3151 color
.pixel
= gc
->color
;
3153 XQueryColor (display
, colormap
, &color
);
3154 color
.red
= (bgred
+ color
.red
) / 2;
3155 color
.green
= (bggreen
+ color
.green
) / 2;
3156 color
.blue
= (bgblue
+ color
.blue
) / 2;
3157 XAllocColor (display
, colormap
, &color
);
3158 lastfade
= gc
->color
= color
.pixel
;
3166 int cap
, join
, width
;
3167 if (gc
->me_pointer
!= &lesstif_gui
)
3169 fprintf (stderr
, "Fatal: GC from another HID passed to lesstif HID\n");
3173 printf ("set_gc c%s %08lx w%d c%d x%d e%d\n",
3174 gc
->colorname
, gc
->color
, gc
->width
, gc
->cap
, gc
->xor, gc
->erase
);
3179 cap
= CapProjecting
;
3188 cap
= CapProjecting
;
3192 cap
= CapProjecting
;
3198 XSetFunction (display
, my_gc
, GXxor
);
3199 XSetForeground (display
, my_gc
, gc
->color
^ bgcolor
);
3203 XSetFunction (display
, my_gc
, GXcopy
);
3204 XSetForeground (display
, my_gc
, offlimit_color
);
3208 XSetFunction (display
, my_gc
, GXcopy
);
3209 XSetForeground (display
, my_gc
, gc
->color
);
3211 width
= Vz (gc
->width
);
3214 XSetLineAttributes (display
, my_gc
, width
, LineSolid
, cap
,
3219 mask_gc
= bclear_gc
;
3222 XSetLineAttributes (display
, mask_gc
, Vz (gc
->width
), LineSolid
, cap
,
3228 lesstif_set_line_cap (hidGC gc
, EndCapStyle style
)
3234 lesstif_set_line_width (hidGC gc
, int width
)
3240 lesstif_set_draw_xor (hidGC gc
, int xor)
3246 lesstif_set_draw_faded (hidGC gc
, int faded
)
3248 /* We don't use this */
3252 lesstif_set_line_cap_angle (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
3257 #define ISORT(a,b) if (a>b) { a^=b; b^=a; a^=b; }
3260 lesstif_draw_line (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
3262 double dx1
, dy1
, dx2
, dy2
;
3263 int vw
= Vz (gc
->width
);
3264 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && gc
->erase
)
3267 printf ("draw_line %d,%d %d,%d @%d", x1
, y1
, x2
, y2
, gc
->width
);
3274 printf (" = %d,%d %d,%d %s\n", x1
, y1
, x2
, y2
, gc
->colorname
);
3278 if (! ClipLine (0, 0, view_width
, view_height
,
3279 &dx1
, &dy1
, &dx2
, &dy2
, vw
))
3289 if (gc
->cap
== Square_Cap
&& x1
== x2
&& y1
== y2
)
3291 XFillRectangle (display
, pixmap
, my_gc
, x1
- vw
/ 2, y1
- vw
/ 2, vw
,
3294 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
- vw
/ 2,
3295 y1
- vw
/ 2, vw
, vw
);
3299 XDrawLine (display
, pixmap
, my_gc
, x1
, y1
, x2
, y2
);
3301 XDrawLine (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
, y2
);
3306 lesstif_draw_arc (hidGC gc
, int cx
, int cy
, int width
, int height
,
3307 int start_angle
, int delta_angle
)
3309 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3312 printf ("draw_arc %d,%d %dx%d s %d d %d", cx
, cy
, width
, height
, start_angle
, delta_angle
);
3315 height
= Vz (height
);
3316 cx
= Vx (cx
) - width
;
3317 cy
= Vy (cy
) - height
;
3320 start_angle
= 180 - start_angle
;
3321 delta_angle
= - delta_angle
;
3325 start_angle
= - start_angle
;
3326 delta_angle
= - delta_angle
;
3328 start_angle
= (start_angle
+ 360 + 180) % 360 - 180;
3330 printf (" = %d,%d %dx%d %d %s\n", cx
, cy
, width
, height
, gc
->width
,
3334 XDrawArc (display
, pixmap
, my_gc
, cx
, cy
,
3335 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3337 if (use_mask
&& !TEST_FLAG (THINDRAWFLAG
, PCB
))
3338 XDrawArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3339 width
* 2, height
* 2, (start_angle
+ 180) * 64,
3342 /* Enable this if you want to see the center and radii of drawn
3343 arcs, for debugging. */
3344 if (TEST_FLAG (THINDRAWFLAG
, PCB
)
3345 && delta_angle
!= 360)
3349 XDrawLine (display
, pixmap
, arc1_gc
, cx
, cy
,
3350 cx
- width
*cos(start_angle
*M_PI
/180),
3351 cy
+ width
*sin(start_angle
*M_PI
/180));
3352 XDrawLine (display
, pixmap
, arc2_gc
, cx
, cy
,
3353 cx
- width
*cos((start_angle
+delta_angle
)*M_PI
/180),
3354 cy
+ width
*sin((start_angle
+delta_angle
)*M_PI
/180));
3360 lesstif_draw_rect (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
3362 int vw
= Vz (gc
->width
);
3363 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3369 if (x1
< -vw
&& x2
< -vw
)
3371 if (y1
< -vw
&& y2
< -vw
)
3373 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3375 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3377 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3378 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3380 XDrawRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1, y2
- y1
+ 1);
3382 XDrawRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3387 lesstif_fill_circle (hidGC gc
, int cx
, int cy
, int radius
)
3389 if (pinout
&& use_mask
&& gc
->erase
)
3391 if ((TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
)) && gc
->erase
)
3394 printf ("fill_circle %d,%d %d", cx
, cy
, radius
);
3396 radius
= Vz (radius
);
3397 cx
= Vx (cx
) - radius
;
3398 cy
= Vy (cy
) - radius
;
3399 if (cx
< -2 * radius
|| cx
> view_width
)
3401 if (cy
< -2 * radius
|| cy
> view_height
)
3404 printf (" = %d,%d %d %lx %s\n", cx
, cy
, radius
, gc
->color
, gc
->colorname
);
3407 XFillArc (display
, pixmap
, my_gc
, cx
, cy
,
3408 radius
* 2, radius
* 2, 0, 360 * 64);
3410 XFillArc (display
, mask_bitmap
, mask_gc
, cx
, cy
,
3411 radius
* 2, radius
* 2, 0, 360 * 64);
3415 lesstif_fill_polygon (hidGC gc
, int n_coords
, int *x
, int *y
)
3417 static XPoint
*p
= 0;
3418 static int maxp
= 0;
3421 if (maxp
< n_coords
)
3423 maxp
= n_coords
+ 10;
3425 p
= (XPoint
*) realloc (p
, maxp
* sizeof (XPoint
));
3427 p
= (XPoint
*) malloc (maxp
* sizeof (XPoint
));
3430 for (i
= 0; i
< n_coords
; i
++)
3436 printf ("fill_polygon %d pts\n", n_coords
);
3439 XFillPolygon (display
, pixmap
, my_gc
, p
, n_coords
, Complex
,
3442 XFillPolygon (display
, mask_bitmap
, mask_gc
, p
, n_coords
, Complex
,
3447 lesstif_fill_rect (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
3449 int vw
= Vz (gc
->width
);
3450 if ((pinout
|| TEST_FLAG (THINDRAWFLAG
, PCB
)) && gc
->erase
)
3456 if (x1
< -vw
&& x2
< -vw
)
3458 if (y1
< -vw
&& y2
< -vw
)
3460 if (x1
> view_width
+ vw
&& x2
> view_width
+ vw
)
3462 if (y1
> view_height
+ vw
&& y2
> view_height
+ vw
)
3464 if (x1
> x2
) { int xt
= x1
; x1
= x2
; x2
= xt
; }
3465 if (y1
> y2
) { int yt
= y1
; y1
= y2
; y2
= yt
; }
3467 XFillRectangle (display
, pixmap
, my_gc
, x1
, y1
, x2
- x1
+ 1,
3470 XFillRectangle (display
, mask_bitmap
, mask_gc
, x1
, y1
, x2
- x1
+ 1,
3475 lesstif_calibrate (double xval
, double yval
)
3481 lesstif_shift_is_pressed (void)
3483 return shift_pressed
;
3487 lesstif_control_is_pressed (void)
3489 return ctrl_pressed
;
3492 extern void lesstif_get_coords (const char *msg
, int *x
, int *y
);
3495 lesstif_set_crosshair (int x
, int y
, int action
)
3497 if (crosshair_x
!= x
|| crosshair_y
!= y
)
3499 lesstif_show_crosshair(0);
3507 || x
> view_left_x
+ view_width
* view_zoom
3508 || y
< view_top_y
|| y
> view_top_y
+ view_height
* view_zoom
))
3510 view_left_x
= x
- (view_width
* view_zoom
) / 2;
3511 view_top_y
= y
- (view_height
* view_zoom
) / 2;
3512 lesstif_pan_fixup ();
3517 if (action
== HID_SC_PAN_VIEWPORT
)
3520 unsigned int keys_buttons
;
3521 int pos_x
, pos_y
, root_x
, root_y
;
3522 XQueryPointer (display
, window
, &root
, &child
,
3523 &root_x
, &root_y
, &pos_x
, &pos_y
, &keys_buttons
);
3525 view_left_x
= x
- (view_width
-pos_x
) * view_zoom
;
3527 view_left_x
= x
- pos_x
* view_zoom
;
3529 view_top_y
= y
- (view_height
-pos_y
) * view_zoom
;
3531 view_top_y
= y
- pos_y
* view_zoom
;
3532 lesstif_pan_fixup();
3533 action
= HID_SC_WARP_POINTER
;
3535 if (action
== HID_SC_WARP_POINTER
)
3538 XWarpPointer (display
, None
, window
, 0, 0, 0, 0, Vx(x
), Vy(y
));
3545 void (*func
) (hidval
);
3551 lesstif_timer_cb (XtPointer
* p
, XtIntervalId
* id
)
3553 TimerStruct
*ts
= (TimerStruct
*) p
;
3554 ts
->func (ts
->user_data
);
3559 lesstif_add_timer (void (*func
) (hidval user_data
),
3560 unsigned long milliseconds
, hidval user_data
)
3564 t
= (TimerStruct
*) malloc (sizeof (TimerStruct
));
3567 t
->user_data
= user_data
;
3568 t
->id
= XtAppAddTimeOut (app_context
, milliseconds
, (XtTimerCallbackProc
)lesstif_timer_cb
, t
);
3573 lesstif_stop_timer (hidval hv
)
3575 TimerStruct
*ts
= (TimerStruct
*) hv
.ptr
;
3576 XtRemoveTimeOut (ts
->id
);
3583 void (*func
) ( hidval
, int, unsigned int, hidval
);
3590 /* We need a wrapper around the hid file watch because to pass the correct flags
3593 lesstif_watch_cb (XtPointer client_data
, int *fid
, XtInputId
* id
)
3595 unsigned int pcb_condition
= 0;
3599 WatchStruct
*watch
= (WatchStruct
*)client_data
;
3602 fds
.events
= POLLIN
| POLLOUT
;
3604 condition
= fds
.revents
;
3606 // Should we only include those we were asked to watch?
3607 if (condition
& POLLIN
)
3608 pcb_condition
|= PCB_WATCH_READABLE
;
3609 if (condition
& POLLOUT
)
3610 pcb_condition
|= PCB_WATCH_WRITABLE
;
3611 if (condition
& POLLERR
)
3612 pcb_condition
|= PCB_WATCH_ERROR
;
3613 if (condition
& POLLHUP
)
3614 pcb_condition
|= PCB_WATCH_HANGUP
;
3616 x
.ptr
= (void *) watch
;
3617 watch
->func (x
, watch
->fd
, pcb_condition
, watch
->user_data
);
3623 lesstif_watch_file (int fd
, unsigned int condition
, void (*func
) (hidval watch
, int fd
, unsigned int condition
, hidval user_data
),
3626 WatchStruct
*watch
= malloc (sizeof(WatchStruct
));
3628 unsigned int xt_condition
= 0;
3630 if (condition
& PCB_WATCH_READABLE
)
3631 xt_condition
|= XtInputReadMask
;
3632 if (condition
& PCB_WATCH_WRITABLE
)
3633 xt_condition
|= XtInputWriteMask
;
3634 if (condition
& PCB_WATCH_ERROR
)
3635 xt_condition
|= XtInputExceptMask
;
3636 if (condition
& PCB_WATCH_HANGUP
)
3637 xt_condition
|= XtInputExceptMask
;
3640 watch
->user_data
= user_data
;
3642 watch
->id
= XtAppAddInput( app_context
, fd
, (XtPointer
) (size_t) xt_condition
, lesstif_watch_cb
, watch
);
3644 ret
.ptr
= (void *) watch
;
3649 lesstif_unwatch_file (hidval data
)
3651 WatchStruct
*watch
= (WatchStruct
*)data
.ptr
;
3652 XtRemoveInput( watch
->id
);
3659 void (*func
) (hidval user_data
);
3663 static void lesstif_block_hook_cb(XtPointer user_data
);
3666 lesstif_block_hook_cb (XtPointer user_data
)
3668 BlockHookStruct
*block_hook
= (BlockHookStruct
*)user_data
;
3669 block_hook
->func( block_hook
->user_data
);
3673 lesstif_add_block_hook (void (*func
) (hidval data
), hidval user_data
)
3676 BlockHookStruct
*block_hook
= malloc( sizeof( BlockHookStruct
));
3678 block_hook
->func
= func
;
3679 block_hook
->user_data
= user_data
;
3681 block_hook
->id
= XtAppAddBlockHook( app_context
, lesstif_block_hook_cb
, (XtPointer
)block_hook
);
3683 ret
.ptr
= (void *) block_hook
;
3688 lesstif_stop_block_hook (hidval mlpoll
)
3690 BlockHookStruct
*block_hook
= (BlockHookStruct
*)mlpoll
.ptr
;
3691 XtRemoveBlockHook( block_hook
->id
);
3696 extern void lesstif_logv (const char *fmt
, va_list ap
);
3698 extern int lesstif_confirm_dialog (char *msg
, ...);
3700 extern int lesstif_close_confirm_dialog ();
3702 extern void lesstif_report_dialog (char *title
, char *msg
);
3705 lesstif_attribute_dialog (HID_Attribute
* attrs
,
3706 int n_attrs
, HID_Attr_Val
* results
,
3707 const char * title
, const char * descr
);
3710 pinout_callback (Widget da
, PinoutData
* pd
,
3711 XmDrawingAreaCallbackStruct
* cbs
)
3714 int save_vx
, save_vy
, save_vw
, save_vh
;
3715 int save_fx
, save_fy
;
3718 int reason
= cbs
? cbs
->reason
: 0;
3720 if (pd
->window
== 0 && reason
== XmCR_RESIZE
)
3722 if (pd
->window
== 0 || reason
== XmCR_RESIZE
)
3728 stdarg (XmNwidth
, &w
);
3729 stdarg (XmNheight
, &h
);
3730 XtGetValues (da
, args
, n
);
3732 pd
->window
= XtWindow (da
);
3735 pd
->zoom
= (pd
->right
- pd
->left
+ 1) / (double) w
;
3736 z
= (pd
->bottom
- pd
->top
+ 1) / (double) h
;
3740 pd
->x
= (pd
->left
+ pd
->right
) / 2 - pd
->v_width
* pd
->zoom
/ 2;
3741 pd
->y
= (pd
->top
+ pd
->bottom
) / 2 - pd
->v_height
* pd
->zoom
/ 2;
3744 save_vx
= view_left_x
;
3745 save_vy
= view_top_y
;
3746 save_vz
= view_zoom
;
3747 save_vw
= view_width
;
3748 save_vh
= view_height
;
3753 pixmap
= pd
->window
;
3754 view_left_x
= pd
->x
;
3756 view_zoom
= pd
->zoom
;
3757 view_width
= pd
->v_width
;
3758 view_height
= pd
->v_height
;
3760 flip_x
= flip_y
= 0;
3764 region
.X2
= PCB
->MaxWidth
;
3765 region
.Y2
= PCB
->MaxHeight
;
3767 XFillRectangle (display
, pixmap
, bg_gc
, 0, 0, pd
->v_width
, pd
->v_height
);
3768 hid_expose_callback (&lesstif_gui
, ®ion
, pd
->item
);
3771 view_left_x
= save_vx
;
3772 view_top_y
= save_vy
;
3773 view_zoom
= save_vz
;
3774 view_width
= save_vw
;
3775 view_height
= save_vh
;
3782 pinout_unmap (Widget w
, PinoutData
* pd
, void *v
)
3785 pd
->prev
->next
= pd
->next
;
3789 pd
->next
->prev
= pd
->prev
;
3790 XtDestroyWidget (XtParent (pd
->form
));
3795 lesstif_show_item (void *item
)
3802 for (pd
= pinouts
; pd
; pd
= pd
->next
)
3803 if (pd
->item
== item
)
3808 pd
= (PinoutData
*) MyCalloc (1, sizeof (PinoutData
), "lesstif_show_item");
3812 extents
= hid_get_extents (item
);
3813 pd
->left
= extents
->X1
;
3814 pd
->right
= extents
->X2
;
3815 pd
->top
= extents
->Y1
;
3816 pd
->bottom
= extents
->Y2
;
3818 if (pd
->left
> pd
->right
)
3826 pd
->next
->prev
= pd
;
3831 pd
->form
= XmCreateFormDialog (mainwind
, "pinout", args
, n
);
3833 XtAddCallback (pd
->form
, XmNunmapCallback
, (XtCallbackProc
) pinout_unmap
,
3837 sqrt (200.0 * 200.0 /
3838 ((pd
->right
- pd
->left
+ 1.0) * (pd
->bottom
- pd
->top
+ 1.0)));
3841 stdarg (XmNwidth
, (int) (scale
* (pd
->right
- pd
->left
+ 1)));
3842 stdarg (XmNheight
, (int) (scale
* (pd
->bottom
- pd
->top
+ 1)));
3843 stdarg (XmNleftAttachment
, XmATTACH_FORM
);
3844 stdarg (XmNrightAttachment
, XmATTACH_FORM
);
3845 stdarg (XmNtopAttachment
, XmATTACH_FORM
);
3846 stdarg (XmNbottomAttachment
, XmATTACH_FORM
);
3847 da
= XmCreateDrawingArea (pd
->form
, "pinout", args
, n
);
3850 XtAddCallback (da
, XmNexposeCallback
, (XtCallbackProc
) pinout_callback
,
3852 XtAddCallback (da
, XmNresizeCallback
, (XtCallbackProc
) pinout_callback
,
3855 XtManageChild (pd
->form
);
3867 lesstif_progress (int so_far
, int total
, const char *message
)
3875 "LessTif - a Motif clone for X/Unix",
3879 1, /* poly before */
3883 lesstif_get_export_options
,
3885 lesstif_parse_arguments
,
3887 lesstif_invalidate_wh
,
3888 lesstif_invalidate_lr
,
3889 lesstif_invalidate_all
,
3895 lesstif_set_line_cap
,
3896 lesstif_set_line_width
,
3897 lesstif_set_draw_xor
,
3898 lesstif_set_draw_faded
,
3899 lesstif_set_line_cap_angle
,
3903 lesstif_fill_circle
,
3904 lesstif_fill_polygon
,
3905 common_fill_pcb_polygon
,
3906 common_thindraw_pcb_polygon
,
3910 lesstif_shift_is_pressed
,
3911 lesstif_control_is_pressed
,
3913 lesstif_set_crosshair
,
3917 lesstif_unwatch_file
,
3918 lesstif_add_block_hook
,
3919 lesstif_stop_block_hook
,
3923 lesstif_confirm_dialog
,
3924 lesstif_close_confirm_dialog
,
3925 lesstif_report_dialog
,
3928 lesstif_attribute_dialog
,
3934 #include "dolists.h"
3939 hid_register_hid (&lesstif_gui
);
3940 #include "lesstif_lists.h"