1 #define WINVER 0x0500
2 #define _WIN32_WINNT 0x0500
3
4 #include <stdio.h>
5 #include <sys/stat.h>
6 #include <errno.h>
7
8 #include "xcwin32.h"
9 #include "xcircuit.h"
10 #include "colordefs.h"
11 #include "resource.h"
12 #include "menudep.h"
13 #include "prototypes.h"
14 #include "tool_bar.h"
15
16 #include "xcwin32-colors.h"
17
18 #ifndef MK_XBUTTON1
19 #define MK_XBUTTON1 32
20 #define MK_XBUTTON2 64
21 #endif
22
23 #if 0
24 #define W32DEBUG(x) printf##x
25 #else
26 #define W32DEBUG(x)
27 #endif
28
29 extern XCWindowData *areawin;
30 extern Globaldata xobjs;
31 extern char _STR2[250];
32 extern Pixmap STIPPLE[STIPPLES]; /* Polygon fill-style stipple patterns */
33 static char STIPDATA[STIPPLES][4] = {
34 "\000\004\000\001",
35 "\000\005\000\012",
36 "\001\012\005\010",
37 "\005\012\005\012",
38 "\016\005\012\007",
39 "\017\012\017\005",
40 "\017\012\017\016",
41 "\000\000\000\000"
42 };
43 extern xcWidget top, message2, message3;
44 extern ApplicationData appdata;
45 extern int number_colors;
46 extern colorindex *colorlist;
47 extern menustruct TopButtons[];
48 extern short maxbuttons;
49 extern xcWidget menuwidgets[MaxMenuWidgets];
50 extern Display *dpy;
51 extern toolbarstruct ToolBar[];
52 extern short toolbuttons;
53 extern Pixmap dbuf, helppix;
54 extern Dimension helpwidth, helpheight;
55 extern int helptop;
56 extern GC hgc;
57 #define MAXPROPS 7
58 extern propstruct okstruct[MAXPROPS], fpokstruct;
59
60 static HWND corner = NULL, statusBar = NULL;
61 static Widget toolBar = NULL;
62 static int statusBarWidth[2] = { 100, -1 };
63
64 HWND topwin = NULL;
65
66 /*
67 LRESULT CALLBACK XcStaticProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
68 LRESULT CALLBACK XcEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
69 LRESULT CALLBACK XcButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
70 LRESULT CALLBACK XcToggleProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
71 LRESULT CALLBACK XcPopupProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
72 */
73
74 INT_PTR CALLBACK OutputDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
75 void updatename(xcWidget button, xcWidgetList callstruct, caddr_t calldata);
76 void linkset(xcWidget button, propstruct *callstruct, caddr_t calldata);
77 extern int COM_initialize();
78 extern int COM_terminate();
79
80 #define WIN_WIDGET 0
81 #define WIN_MENUITEM 1
82 #define WIN_MENU 2
83 #define WIN_STATUS 3
84 #define WIN_TOOLITEM 4
85
86 #define IS_WIDGET(w) (w->type == WIN_WIDGET)
87 #define IS_MENU(w) (w->type == WIN_MENU)
88 #define IS_MENUITEM(w) (w->type == WIN_MENUITEM)
89 #define IS_STATUS(w) (w->type == WIN_STATUS)
90 #define IS_TOOLITEM(w) (w->type == WIN_TOOLITEM)
91
92 #define TOWIDGET(w) ((Widget)w)
93 #define TOMENU(w) ((Menu)w)
94 #define TOMENUITEM(w) ((MenuItem)w)
95 #define TOSTATUS(w) ((StatusItem)w)
96 #define TOTOOLITEM(w) ((ToolItem)w)
97
98 #define STATUSBAR_ID 10000
99 #define TOOLBAR_ID 10001
100
101 typedef struct __WinCallback {
102 int action;
103 void(*proc)();
104 void* data;
105 struct __WinCallback *next;
106 } WinCallback;
107 typedef WinCallback WinEventHandler;
108
109 struct __WinWidget {
110 int type;
111 HWND handle;
112 char *name;
113 WinCallback *callbacks;
114 WinEventHandler *handlers;
115 int handler_mask;
116 HBITMAP buffer;
117 HDC bufhdc;
118 WNDPROC wndproc;
119 };
120 #define HAS_HANDLER(win,themask) (win->handler_mask & themask)
121 #define WM_BITBLT (WM_USER+1)
122
123 struct __WinMenu {
124 int type;
125 HMENU handle;
126 };
127
128 struct __WinMenuItem {
129 int type;
130 struct __WinMenu *parentMenu;
131 struct __WinMenu *popup;
132 int ID;
133 int position;
134 char *name;
135 WinCallback *callbacks;
136 int menudata;
137 int toolbar_idx;
138 };
139
140 struct __WinStatusItem {
141 int type;
142 HWND handle;
143 int position;
144 };
145
146 struct __WinToolItem {
147 int type;
148 struct __WinWidget *toolbar;
149 int ID;
150 char *name;
151 WinCallback *callbacks;
152 };
153
154 typedef struct __WinMenu* Menu;
155 typedef struct __WinMenuItem* MenuItem;
156 typedef struct __WinStatusItem* StatusItem;
157 typedef struct __WinToolItem* ToolItem;
158
execute_callback(int action,Widget w,void * calldata)159 void execute_callback(int action, Widget w, void *calldata)
160 {
161 WinCallback *cb;
162
163 switch (w->type) {
164 case WIN_WIDGET:
165 cb = w->callbacks;
166 break;
167 case WIN_MENUITEM:
168 cb = ((MenuItem)w)->callbacks;
169 break;
170 case WIN_TOOLITEM:
171 cb = ((ToolItem)w)->callbacks;
172 break;
173 default:
174 return;
175 }
176 while (cb != NULL) {
177 if (cb->action == action) {
178 (*cb->proc)(w, cb->data, calldata);
179 }
180 cb = cb->next;
181 }
182 }
183
execute_handler(int mask,Widget w,void * calldata)184 void execute_handler(int mask, Widget w, void *calldata)
185 {
186 WinCallback *h = w->handlers;
187 if (!HAS_HANDLER(w,mask))
188 return;
189 while (h != NULL) {
190 if (h->action & mask)
191 (*h->proc)(w, h->data, calldata);
192 h = h->next;
193 }
194 }
195
update_event_mask(Widget win)196 void update_event_mask(Widget win)
197 {
198 WinEventHandler *h = win->handlers;
199 win->handler_mask = 0;
200 for (; h!= NULL; h=h->next)
201 win->handler_mask |= h->action;
202 }
203
get_widget(HWND win)204 Widget get_widget(HWND win)
205 {
206 /*
207 int nbytes = GetClassLong(win, GCL_CBWNDEXTRA);
208 if (nbytes >= sizeof(Widget))
209 return (Widget)GetWindowLong(win, nbytes-sizeof(Widget));
210 else
211 return NULL;
212 */
213 return (Widget)GetWindowLong(win, GWL_USERDATA);
214 }
215
get_value(Widget w,Arg * a)216 static void get_value(Widget w, Arg *a)
217 {
218 RECT rect;
219
220 switch (a->type) {
221 case XtNwidth:
222 if (w->type == WIN_STATUS) {
223 StatusItem item = (StatusItem)w;
224 if (item->position < 1)
225 *(int*)(a->data) = statusBarWidth[item->position];
226 else {
227 GetClientRect(w->handle, &rect);
228 *(int*)(a->data) = rect.right - rect.left - statusBarWidth[0];
229 }
230 } else {
231 if (GetClientRect(w->handle, &rect))
232 *(int*)(a->data) = rect.right - rect.left;
233 }
234 break;
235 case XtNheight:
236 if (GetClientRect(w->handle, &rect))
237 *(int*)(a->data) = rect.bottom - rect.top;
238 break;
239 case XtNrectColor:
240 case XtNrectStipple:
241 if (w->type == WIN_MENUITEM) {
242 *(int*)(a->data) = ((MenuItem)w)->menudata;
243 break;
244 }
245 goto GETDEFAULT;
246 GETDEFAULT:
247 default:
248 W32DEBUG(("Unsupported get value: %d\n", a->type));
249 break;
250 }
251 }
252
set_value(Widget w,Arg * a)253 static void set_value(Widget w, Arg *a)
254 {
255 switch (a->type) {
256 case XtNstring:
257 switch (w->type) {
258 case WIN_STATUS:
259 SendMessage(TOSTATUS(w)->handle, SB_SETTEXT, TOSTATUS(w)->position, (LPARAM)(char*)a->data);
260 break;
261 case WIN_WIDGET:
262 SetWindowText(w->handle, (char*)a->data);
263 break;
264 default:
265 goto SETDEFAULT;
266 }
267 break;
268 case XtNsetMark:
269 switch (w->type) {
270 case WIN_MENUITEM:
271 CheckMenuItem(TOMENUITEM(w)->parentMenu->handle, TOMENUITEM(w)->position,
272 MF_BYPOSITION|(a->data == NULL ? MF_UNCHECKED : MF_CHECKED));
273 break;
274 default:
275 goto SETDEFAULT;
276 }
277 break;
278 case XtNlabel:
279 switch (w->type) {
280 case WIN_MENUITEM:
281 {
282 MENUITEMINFO mi_info;
283 ZeroMemory(&mi_info, sizeof(mi_info));
284 mi_info.cbSize = sizeof(mi_info);
285 mi_info.fMask = MIIM_STRING;
286 mi_info.dwTypeData = a->data;
287 SetMenuItemInfo(TOMENUITEM(w)->parentMenu->handle, TOMENUITEM(w)->position, MF_BYPOSITION, &mi_info);
288 break;
289 }
290 case WIN_WIDGET:
291 SetWindowText(w->handle, (char*)a->data);
292 break;
293 default:
294 goto SETDEFAULT;
295 }
296 break;
297 case XtNfont:
298 switch (w->type) {
299 case WIN_WIDGET:
300 SendMessage(w->handle, WM_SETFONT, (WPARAM)((XFontStruct*)a->data)->fid, MAKELONG(TRUE, 0));
301 break;
302 default:
303 goto SETDEFAULT;
304 }
305 break;
306 case XtNset:
307 switch (w->type) {
308 case WIN_WIDGET:
309 SendMessage(w->handle, BM_SETCHECK, ((int)a->data == True ? BST_CHECKED : BST_UNCHECKED), 0);
310 break;
311 default:
312 goto SETDEFAULT;
313 }
314 break;
315 case XtNborderColor:
316 switch (w->type) {
317 case WIN_TOOLITEM:
318 if ((int)a->data == RATSNESTCOLOR) {
319 W32DEBUG(("Check button: %s\n", ((ToolItem)w)->name));
320 SendMessage(TOTOOLITEM(w)->toolbar->handle, TB_CHECKBUTTON, TOTOOLITEM(w)->ID, MAKELONG(TRUE, 0));
321 }
322 else {
323 W32DEBUG(("Uncheck button: %s\n", ((ToolItem)w)->name));
324 SendMessage(TOTOOLITEM(w)->toolbar->handle, TB_CHECKBUTTON, TOTOOLITEM(w)->ID, MAKELONG(FALSE, 0));
325 }
326 break;
327 default:
328 goto SETDEFAULT;
329 }
330 break;
331 SETDEFAULT:
332 default:
333 W32DEBUG(("Unsupported set value: %d\n", a->type));
334 /*exit(-1);*/
335 break;
336 }
337 }
338
WinGetValues(Widget w,Arg * args,int n)339 void WinGetValues(Widget w, Arg *args, int n)
340 {
341 int i;
342
343 if (w != NULL)
344 for (i=0; i<n; i++)
345 get_value(w, args+i);
346 }
347
WinSetValues(Widget w,Arg * args,int n)348 void WinSetValues(Widget w, Arg *args, int n)
349 {
350 int i;
351
352 if (w != NULL)
353 for (i=0; i<n; i++)
354 set_value(w, args+i);
355 }
356
WinCreatePixmap(HWND w,int width,int height)357 HBITMAP WinCreatePixmap(HWND w, int width, int height)
358 {
359 HDC hdc;
360 HBITMAP hBitmap;
361
362 hdc = GetDC(w);
363 hBitmap = CreateCompatibleBitmap(hdc, width, height);
364 ReleaseDC(w, hdc);
365 return hBitmap;
366 }
367
WinParent(Widget child)368 Widget WinParent(Widget child)
369 {
370 if (child)
371 switch (child->type) {
372 case WIN_WIDGET:
373 return (Widget)get_widget(GetParent(child->handle));
374 case WIN_MENUITEM:
375 return (Widget)((MenuItem)child)->parentMenu;
376 case WIN_TOOLITEM:
377 return (Widget)((ToolItem)child)->toolbar;
378 }
379 return NULL;
380 }
381
WinFreePixmap(Pixmap pix)382 void WinFreePixmap(Pixmap pix)
383 {
384 DeleteObject(pix);
385 }
386
WinDestroyImage(XImage * img)387 void WinDestroyImage(XImage *img)
388 {
389 if (img->handle != NULL)
390 DeleteObject(img->handle);
391 free(img->data);
392 free(img);
393 }
394
WinCreateImage(int width,int height)395 XImage* WinCreateImage(int width, int height)
396 {
397 HWND h = GetDesktopWindow();
398 HDC hdc = GetDC(h);
399 XImage *img = (XImage*)malloc(sizeof(XImage));
400
401 img->bits_per_pixel = GetDeviceCaps(hdc, BITSPIXEL);
402 img->bytes_per_line = width * img->bits_per_pixel / 8;
403 img->width = width;
404 img->height = height;
405 img->data = NULL;
406 ReleaseDC(h, hdc);
407
408 return img;
409 }
410
WinGetPixel(XImage * img,int x,int y)411 int WinGetPixel(XImage *img, int x, int y)
412 {
413 unsigned char *src;
414 if (img->bits_per_pixel != 32) {
415 W32DEBUG(("WinGetPixel only supported on 32bpp\n"));
416 return -1;
417 }
418 src = img->data + (y * img->bytes_per_line) + (x * img->bits_per_pixel) / 8;
419 return RGB(src[0], src[1], src[2]);
420 }
421
WinPutPixel(XImage * img,int x,int y,Pixel pix)422 void WinPutPixel(XImage *img, int x, int y, Pixel pix)
423 {
424 unsigned char *src;
425 if (img->bits_per_pixel != 32) {
426 W32DEBUG(("WinPutPixel only supported on 32bpp\n"));
427 return;
428 }
429 src = img->data + (y * img->bytes_per_line) + (x * img->bits_per_pixel) / 8;
430 src[0] = GetRValue(pix);
431 src[1] = GetGValue(pix);
432 src[2] = GetBValue(pix);
433 }
434
opendir(const char * name)435 DIR* opendir(const char *name)
436 {
437 DIR *d = (DIR*)malloc(sizeof(DIR));
438 static char buffer[MAX_PATH];
439
440 strncpy(buffer, name, MAX_PATH);
441 strncat(buffer, "\\*", MAX_PATH);
442 d->hnd = FindFirstFile(buffer, &(d->fd));
443 if (d->hnd == INVALID_HANDLE_VALUE)
444 return NULL;
445 d->dirty = 1;
446 return d;
447 }
448
closedir(DIR * d)449 void closedir(DIR *d)
450 {
451 free(d);
452 }
453
readdir(DIR * d)454 struct direct* readdir(DIR *d)
455 {
456 if (!d->dirty)
457 {
458 if (!FindNextFile(d->hnd, &(d->fd)))
459 return NULL;
460 }
461 d->d.d_name = d->fd.cFileName;
462 d->dirty = 0;
463 return &(d->d);
464 }
465
WinDesktopWidth(void)466 int WinDesktopWidth(void)
467 {
468 RECT r;
469 GetWindowRect(GetDesktopWindow(), &r);
470 return r.right-r.left;
471 }
472
WinDesktopHeight(void)473 int WinDesktopHeight(void)
474 {
475 RECT r;
476 GetWindowRect(GetDesktopWindow(), &r);
477 return r.bottom-r.top;
478 }
479
WinSetCursor(HWND win,HCURSOR cursor)480 void WinSetCursor(HWND win, HCURSOR cursor)
481 {
482 SetClassLong(win, GCL_HCURSOR, (LONG)cursor);
483 }
484
485 HDC cached_hdc = NULL;
486 HWND cached_win = NULL;
487
create_pen(GC gc)488 static HPEN create_pen(GC gc)
489 {
490 HPEN hPen = NULL;
491
492 if (gc->line_style != LineSolid && gc->line_dash_len > 0 && gc->line_dash != NULL) {
493 DWORD *dashes = NULL;
494 DWORD style = 0;
495 LOGBRUSH logBrush;
496 int i;
497
498 logBrush.lbStyle = BS_SOLID;
499 logBrush.lbColor = gc->foreground;
500 logBrush.lbHatch = 0;
501
502 style |= PS_GEOMETRIC | PS_USERSTYLE | gc->line_cap | gc->line_join;
503 dashes = (DWORD*)malloc(sizeof(DWORD)*gc->line_dash_len);
504 for (i=0; i<gc->line_dash_len; i++)
505 dashes[i] = gc->line_dash[i];
506 hPen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE | gc->line_cap | gc->line_join,
507 gc->line_width, &logBrush, gc->line_dash_len, dashes);
508 free(dashes);
509 } else {
510 hPen = CreatePen(PS_SOLID, gc->line_width, gc->foreground);
511 }
512
513 return hPen;
514 }
515
create_brush(GC gc)516 static HBRUSH create_brush(GC gc)
517 {
518 LOGBRUSH logBrush;
519 logBrush.lbStyle = (gc->fill_style == FillSolid ? BS_SOLID : BS_PATTERN);
520 logBrush.lbColor = gc->foreground;
521 logBrush.lbHatch = (LONG)(gc->fill_style != FillSolid ? gc->fill_stipple : NULL);
522 return CreateBrushIndirect(&logBrush);
523 }
524
get_hdc(HWND win,GC gc)525 static HDC get_hdc(HWND win, GC gc)
526 {
527 HDC hdc;
528 if (IsWindow(win)) {
529 Widget winwidget = (Widget)get_widget(win);
530 if (winwidget == NULL || winwidget->buffer == NULL)
531 hdc = GetDC(win);
532 else
533 hdc = winwidget->bufhdc;
534 } else if (win == cached_win && cached_hdc != NULL) {
535 hdc = cached_hdc;
536 } else {
537 hdc = CreateCompatibleDC(NULL);
538 SelectObject(hdc, win);
539 if (cached_hdc != NULL)
540 DeleteDC(cached_hdc);
541 cached_hdc = hdc;
542 cached_win = win;
543 }
544 if (gc != NULL) {
545 SetROP2(hdc, gc->function);
546 SetBkColor(hdc, gc->background);
547 SetTextColor(hdc, gc->foreground);
548 SetBkMode(hdc, TRANSPARENT);
549 SelectObject(hdc, create_pen(gc));
550 SelectObject(hdc, create_brush(gc));
551 SelectObject(hdc, gc->font);
552 }
553 return hdc;
554 }
555
release_hdc(HWND win,HDC hdc)556 static release_hdc(HWND win, HDC hdc)
557 {
558 DeleteObject(SelectObject(hdc, GetStockObject(BLACK_PEN)));
559 DeleteObject(SelectObject(hdc, GetStockObject(NULL_BRUSH)));
560 if (IsWindow(win)) {
561 Widget winwidget = (Widget)get_widget(win);
562 if (winwidget == NULL || winwidget->buffer == NULL)
563 ReleaseDC(win, hdc);
564 else
565 PostMessage(win, WM_BITBLT, 0, 0);
566 }
567 else {
568 //DeleteDC(hdc);
569 }
570 }
571
WinDrawLine(HWND win,GC gc,int x1,int y1,int x2,int y2)572 void WinDrawLine(HWND win, GC gc, int x1, int y1, int x2, int y2)
573 {
574 HDC hdc = get_hdc(win, gc);
575 MoveToEx(hdc, x1, y1, NULL);
576 LineTo(hdc, x2, y2);
577 release_hdc(win, hdc);
578 }
579
WinFillPolygon(HWND win,GC gc,XPoint * pathlist,int number)580 void WinFillPolygon(HWND win, GC gc, XPoint* pathlist, int number)
581 {
582 LPPOINT pts = (LPPOINT)malloc(sizeof(POINT)*number);
583 HDC hdc = get_hdc(win, gc);
584 RECT rect = { 0x0000ffff, 0x0000ffff, -0x0000ffff, -0x0000ffff };
585 int i;
586
587 DeleteObject(SelectObject(hdc, CreatePen(PS_NULL, 0, 0)));
588
589 for (i=0; i<number; i++) {
590 pts[i].x = pathlist[i].x;
591 pts[i].y = pathlist[i].y;
592 rect.left = min(rect.left, pts[i].x);
593 rect.top = min(rect.top, pts[i].y);
594 rect.right = max(rect.right, pts[i].x);
595 rect.bottom = max(rect.bottom, pts[i].y);
596 }
597 if (gc->fill_style == FillStippled) {
598 int width = rect.right-rect.left, height = rect.bottom-rect.top;
599 HDC tmphdc = CreateCompatibleDC(hdc);
600 HBITMAP tmpbmp = CreateCompatibleBitmap(hdc, width, height);
601 HBRUSH tmpbrush = CreateSolidBrush(gc->foreground);
602
603 SelectObject(tmphdc, tmpbmp);
604 SelectObject(tmphdc, tmpbrush);
605 SetROP2(tmphdc, gc->function);
606 BitBlt(tmphdc, 0, 0, width, height, hdc, rect.left, rect.top, SRCCOPY);
607 for (i=0; i<number; i++) {
608 pts[i].x -= rect.left;
609 pts[i].y -= rect.top;
610 }
611 Polygon(tmphdc, pts, number);
612 BitBlt(hdc, rect.left, rect.top, width, height, tmphdc, 0, 0, 0x00AC0744);
613
614 DeleteDC(tmphdc);
615 DeleteObject(tmpbmp);
616 DeleteObject(tmpbrush);
617 } else {
618 Polygon(hdc, pts, number);
619 }
620
621 release_hdc(win, hdc);
622 free(pts);
623 }
624
WinDrawArc(HWND win,GC gc,int x,int y,int width,int height,int angle,int span)625 void WinDrawArc(HWND win, GC gc, int x, int y, int width, int height, int angle, int span)
626 {
627 HDC hdc = get_hdc(win, gc);
628 if (span != (360*64)) {
629 W32DEBUG(("Unimplemented\n"));
630 } else
631 Ellipse(hdc, x, y, width, height);
632 release_hdc(win, hdc);
633 }
634
WinClearArea(HWND win,int x,int y,int w,int h)635 void WinClearArea(HWND win, int x, int y, int w, int h)
636 {
637 HDC hdc = get_hdc(win, NULL);
638 RECT r;
639 r.left = x;
640 r.top = y;
641 r.right = x+w;
642 r.bottom = y+h;
643 FillRect(hdc, &r, (HBRUSH)(COLOR_WINDOW+1));
644 release_hdc(win, hdc);
645 }
646
WinFillRectangle(HWND win,GC gc,int x,int y,int w,int h)647 void WinFillRectangle(HWND win, GC gc, int x, int y, int w, int h)
648 {
649 HDC hdc = get_hdc(win, gc);
650 RECT r;
651 r.left = x;
652 r.top = y;
653 r.right = x+w;
654 r.bottom = y+h;
655 FillRect(hdc, &r, (HBRUSH)GetCurrentObject(hdc, OBJ_BRUSH));
656 release_hdc(win, hdc);
657 }
658
WinSetFunction(GC gc,int op)659 void WinSetFunction(GC gc, int op)
660 {
661 gc->function = op;
662 }
663
WinSetForeground(GC gc,int color)664 void WinSetForeground(GC gc, int color)
665 {
666 gc->foreground = color;
667 }
668
WinSetBackground(GC gc,int rgb)669 void WinSetBackground(GC gc, int rgb)
670 {
671 gc->background = rgb;
672 }
673
WinCopyArea(Pixmap pix,HWND win,GC gc,int x,int y,int width,int height,int offx,int offy)674 void WinCopyArea(Pixmap pix, HWND win, GC gc, int x, int y, int width, int height, int offx, int offy)
675 {
676 HDC pixhdc = get_hdc((HWND)pix, gc), hdc = get_hdc(win, gc);
677 BitBlt(hdc, offx, offy, width, height, pixhdc, x, y, SRCCOPY);
678 release_hdc((HWND)pix, pixhdc);
679 release_hdc(win, hdc);
680 }
681
WinDrawPoint(HWND win,GC gc,int x,int y)682 void WinDrawPoint(HWND win, GC gc, int x, int y)
683 {
684 HDC hdc = get_hdc(win, gc);
685 SetPixelV(hdc, x, y, gc->foreground);
686 release_hdc(win, hdc);
687 }
688
WinSetLineAttributes(GC gc,int width,int style,int capstyle,int joinstyle)689 void WinSetLineAttributes(GC gc, int width, int style, int capstyle, int joinstyle)
690 {
691 gc->line_style = style;
692 gc->line_width = width;
693 gc->line_cap = capstyle;
694 gc->line_join = joinstyle;
695 }
696
WinWarpPointer(HWND w,int x,int y)697 void WinWarpPointer(HWND w, int x, int y)
698 {
699 POINT pt;
700
701 pt.x = x;
702 pt.y = y;
703 ClientToScreen(w, &pt);
704 SetCursorPos(pt.x, pt.y);
705 }
706
WinDrawLines(HWND win,GC gc,XPoint * pathlist,int number)707 void WinDrawLines(HWND win, GC gc, XPoint* pathlist, int number)
708 {
709 LPPOINT pts = (LPPOINT)malloc(sizeof(POINT)*number);
710 HDC hdc = get_hdc(win, gc);
711 int i;
712
713 for (i=0; i<number; i++) {
714 pts[i].x = pathlist[i].x;
715 pts[i].y = pathlist[i].y;
716 }
717 Polyline(hdc, pts, number);
718 release_hdc(win, hdc);
719 free(pts);
720 }
721
WinQueryPointer(HWND win,int * x,int * y)722 void WinQueryPointer(HWND win, int *x, int *y)
723 {
724 POINT pt;
725
726 if (GetCursorPos(&pt)) {
727 ScreenToClient(win, &pt);
728 *x = pt.x;
729 *y = pt.y;
730 }
731 }
732
WinDrawRectangle(HWND win,GC gc,int x,int y,int width,int height)733 void WinDrawRectangle(HWND win, GC gc, int x, int y, int width, int height)
734 {
735 HDC hdc = get_hdc(win, gc);
736 Rectangle(hdc, x, y, x+width, y+height);
737 release_hdc(win, hdc);
738 }
739
WinCreateGC(HWND win,int mask,XGCValues * values)740 GC WinCreateGC(HWND win, int mask, XGCValues *values)
741 {
742 GC gc = (GC)malloc(sizeof(struct __GC));
743
744 gc->foreground = RGB(0, 0, 0);
745 gc->background = RGB(255, 255, 255);
746 gc->function = R2_COPYPEN;
747 gc->font = NULL;
748 gc->graphics_exposures = False;
749 gc->fill_style = BS_SOLID;
750 gc->fill_stipple = NULL;
751 gc->line_width = 0;
752 gc->line_style = PS_SOLID;
753 gc->line_cap = PS_ENDCAP_ROUND;
754 gc->line_join = PS_JOIN_BEVEL;
755 gc->line_dash_len = 0;
756 gc->line_dash = NULL;
757 gc->clipMask = NULL;
758
759 if (mask & GCForeground)
760 gc->foreground = values->foreground;
761 if (mask & GCBackground)
762 gc->background = values->background;
763 if (mask & GCFont)
764 gc->font = values->font;
765 if (mask & GCFunction)
766 gc->function = values->function;
767 if (mask & GCGraphicsExposures)
768 gc->graphics_exposures = values->graphics_exposures;
769
770 return gc;
771 }
772
WinFreeGC(GC gc)773 void WinFreeGC(GC gc)
774 {
775 free(gc);
776 }
777
WinSetDashes(GC gc,int offset,char * dash,int n)778 void WinSetDashes(GC gc, int offset, char *dash, int n)
779 {
780 if (gc->line_dash) {
781 free(gc->line_dash);
782 gc->line_dash = NULL;
783 gc->line_dash_len = 0;
784 }
785 if (n > 0 && dash != NULL) {
786 gc->line_dash = (char*)malloc(sizeof(char)*n);
787 memcpy(gc->line_dash, dash+offset, n);
788 gc->line_dash_len = n;
789 }
790 }
791
WinSetFillStyle(GC gc,int style)792 void WinSetFillStyle(GC gc, int style)
793 {
794 gc->fill_style = style;
795 }
796
WinSetStipple(GC gc,Pixmap pattern)797 void WinSetStipple(GC gc, Pixmap pattern)
798 {
799 gc->fill_stipple = pattern;
800 }
801
WinCreateStandardCursor(char * cur)802 HCURSOR WinCreateStandardCursor(char *cur)
803 {
804 return LoadCursor(NULL, cur);
805 }
806
WinDrawString(HWND win,GC gc,int x,int y,const char * str,int len)807 void WinDrawString(HWND win, GC gc, int x, int y, const char *str, int len)
808 {
809 HDC hdc = get_hdc(win, gc);
810 SIZE sz;
811 RECT r;
812
813 /*
814 GetTextExtentPoint32(hdc, str, len, &sz);
815 r.left = x;
816 r.right = x+sz.cx;
817 r.top = y-sz.cy;
818 r.bottom = y;
819 TextOut(hdc, r.left, r.top, str, len);
820 */
821 SetTextAlign(hdc, TA_LEFT|TA_BASELINE);
822 TextOut(hdc, x, y, str, len);
823 release_hdc(win, hdc);
824 }
825
WinTextWidth(XFontStruct * fn,char * s,int len)826 int WinTextWidth(XFontStruct *fn, char *s, int len)
827 {
828 HWND w = GetDesktopWindow();
829 HDC hdc = GetDC(w);
830 SIZE sz;
831
832 SelectObject(hdc, fn->fid);
833 GetTextExtentPoint32(hdc, s, len, &sz);
834 ReleaseDC(w, hdc);
835
836 return sz.cx;
837 }
838
WinTextExtents(XFontStruct * fn,char * str,int len,int * width,int * height)839 void WinTextExtents(XFontStruct *fn, char *str, int len, int *width, int *height)
840 {
841 HWND w = GetDesktopWindow();
842 HDC hdc = GetDC(w);
843 SIZE sz;
844
845 SelectObject(hdc, fn->fid);
846 GetTextExtentPoint32(hdc, str, len, &sz);
847 ReleaseDC(w, hdc);
848
849 *width = sz.cy;
850 *height = 0;
851 }
852
853 #define DUPBITS(x) (((x)<<8)|(x))
854
WinQueryColors(XColor * colors,int n)855 void WinQueryColors(XColor *colors, int n)
856 {
857 int i;
858
859 for (i=0; i<n; i++) {
860 colors[i].red = DUPBITS(GetRValue(colors[i].pixel));
861 colors[i].green = DUPBITS(GetGValue(colors[i].pixel));
862 colors[i].blue = DUPBITS(GetBValue(colors[i].pixel));
863 }
864 }
865
WinAppMainLoop(void)866 void WinAppMainLoop(void)
867 {
868 MSG msg;
869 BOOL bRet;
870
871 DrawMenuBar(top->handle);
872 ShowWindow(top->handle, SW_SHOWNORMAL);
873 while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
874 if (bRet == -1) {
875 W32DEBUG(("Loop error\n"));
876 break;
877 } else {
878 if (GetAncestor(msg.hwnd, GA_ROOT) != topwin) {
879 TranslateMessage(&msg);
880 }
881 DispatchMessage(&msg);
882 }
883 }
884
885 #ifdef USE_WIN32_COM
886 COM_terminate();
887 #endif
888 }
889
WinPutImage(HWND win,GC gc,XImage * img,int srcx,int srcy,int destx,int desty,int width,int height)890 void WinPutImage(HWND win, GC gc, XImage *img, int srcx, int srcy, int destx, int desty, int width, int height)
891 {
892 HDC pixhdc, hdc;
893
894 if (img->handle == NULL) {
895 W32DEBUG(("Invalid image handle\n"));
896 return;
897 }
898
899 pixhdc = get_hdc((HWND)img->handle, gc);
900 hdc = get_hdc(win, gc);
901 if (gc->clipMask == NULL)
902 BitBlt(hdc, destx, desty, width, height, pixhdc, srcx, srcy, SRCCOPY);
903 else
904 MaskBlt(hdc, destx, desty, width, height, pixhdc, srcx, srcy, gc->clipMask, 0, 0, SRCCOPY);
905 release_hdc((HWND)img->handle, pixhdc);
906 release_hdc(win, hdc);
907 }
908
WinSetClipMask(GC gc,Pixmap pix)909 void WinSetClipMask(GC gc, Pixmap pix)
910 {
911 gc->clipMask = pix;
912 }
913
914 typedef struct __win32_timer { int ID; void(*proc)(); void *data; struct __win32_timer *next; } win32_timer;
915 static win32_timer *timers = NULL;
916
WinTimerProc(HWND hwnd,UINT umsg,UINT id,DWORD dwtime)917 VOID CALLBACK WinTimerProc(HWND hwnd, UINT umsg, UINT id, DWORD dwtime)
918 {
919 win32_timer *t = timers, *prev = NULL;
920
921 for (; t!=NULL && t->ID != id; prev=t, t=t->next);
922 if (t == NULL) {
923 W32DEBUG(("Timer %d not found\n", id));
924 return;
925 }
926 if (prev == NULL)
927 timers = t->next;
928 else
929 prev->next = t->next;
930 KillTimer(NULL, t->ID);
931 (*t->proc)(t->data, &(t->ID));
932 free(t);
933 }
934
WinAddTimeOut(int delay,void (* proc)(),void * data)935 int WinAddTimeOut(int delay, void(*proc)(), void *data)
936 {
937 win32_timer* t = (win32_timer*)malloc(sizeof(win32_timer));
938
939 t->proc = proc;
940 t->data = data;
941 t->ID = SetTimer(NULL, 0, delay, WinTimerProc);
942
943 if (t->ID == 0) {
944 free(t);
945 return -1;
946 } else {
947 t->next = timers;
948 timers = t;
949 return t->ID;
950 }
951 }
952
WinRemoveTimeOut(int id)953 void WinRemoveTimeOut(int id)
954 {
955 win32_timer *t = timers, *prev = NULL;
956
957 for (; t!=NULL && t->ID != id; prev=t, t=t->next);
958 if (t == NULL) {
959 return;
960 }
961 if (prev == NULL)
962 timers = t->next;
963 else
964 prev->next = t->next;
965 KillTimer(NULL, t->ID);
966 free(t);
967 }
968
WinTranslateCoords(Widget win,short x,short y,short * rx,short * ry)969 void WinTranslateCoords(Widget win, short x, short y, short *rx, short *ry)
970 {
971 POINT pt;
972
973 pt.x = x;
974 pt.y = y;
975 ClientToScreen(win->handle, &pt);
976 *rx = pt.x;
977 *ry = pt.y;
978 }
979
980 typedef struct {
981 char *request;
982 char *current;
983 } InputDlgData;
984
InputDlgProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)985 BOOL CALLBACK InputDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
986 {
987 switch (msg) {
988 case WM_INITDIALOG:
989 {
990 RECT r1, r2;
991 int w1, w2, h1, h2;
992
993 SetDlgItemText(hwnd, IDC_EDIT1, ((InputDlgData*)lParam)->current);
994 SetDlgItemText(hwnd, IDC_INFOTEXT, ((InputDlgData*)lParam)->request);
995 GetWindowRect(GetParent(hwnd), &r1);
996 GetWindowRect(hwnd, &r2);
997 w1 = r1.right-r1.left;
998 w2 = r2.right-r2.left;
999 h1 = r1.bottom-r1.top;
1000 h2 = r2.bottom-r2.top;
1001 SetWindowPos(hwnd, HWND_TOP, r1.left+(w1-w2)/2, r1.top+(h1-h2)/2, 0, 0, SWP_NOSIZE);
1002 SendMessage(GetDlgItem(hwnd, IDC_EDIT1), EM_SETSEL, 0, -1);
1003 SetFocus(GetDlgItem(hwnd, IDC_EDIT1));
1004 return FALSE;
1005 }
1006 case WM_COMMAND:
1007 if (HIWORD(wParam) == BN_CLICKED)
1008 switch (LOWORD(wParam)) {
1009 case IDOK:
1010 GetDlgItemText(hwnd, IDC_EDIT1, _STR2, sizeof(_STR2));
1011 EndDialog(hwnd, 1);
1012 return TRUE;
1013 case IDCANCEL:
1014 EndDialog(hwnd, 0);
1015 return TRUE;
1016 }
1017 break;
1018 }
1019 return FALSE;
1020 }
1021
1022 #define HELP_MARGIN 10
1023
HelpDlgProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)1024 BOOL CALLBACK HelpDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1025 {
1026 switch (msg) {
1027 case WM_INITDIALOG:
1028 {
1029 RECT br, r, cr, pr, pcr;
1030 int sbwidth;
1031
1032 GetWindowRect(hwnd, &r);
1033 GetClientRect(hwnd, &cr);
1034 GetClientRect(GetDlgItem(hwnd, IDOK), &br);
1035 GetWindowRect(GetDlgItem(hwnd, IDC_HELPPIX), &pr);
1036 GetClientRect(GetDlgItem(hwnd, IDC_HELPPIX), &pcr);
1037 sbwidth = (pr.right-pr.left)-(pcr.right-pcr.left);
1038 SetWindowPos(hwnd, HWND_TOP, 0, 0, sbwidth+helpwidth+2*HELP_MARGIN+(r.right-r.left)-(cr.right-cr.left),
1039 r.bottom-r.top, SWP_NOMOVE);
1040 GetClientRect(hwnd, &cr);
1041 SetWindowPos(GetDlgItem(hwnd, IDC_HELPPIX), HWND_TOP, HELP_MARGIN, HELP_MARGIN, helpwidth+sbwidth,
1042 (cr.bottom-cr.top)-(br.bottom-br.top)-3*HELP_MARGIN, 0);
1043 SetWindowPos(GetDlgItem(hwnd, IDOK), HWND_TOP,
1044 HELP_MARGIN+((cr.right-cr.left)-(br.right-br.left))/2, cr.bottom-HELP_MARGIN-(br.bottom-br.top),
1045 br.right-br.left, br.bottom-br.top, 0);
1046 SetFocus(GetDlgItem(hwnd, IDC_HELPPIX));
1047 }
1048 return FALSE;
1049 case WM_COMMAND:
1050 if (HIWORD(wParam) == BN_CLICKED)
1051 switch (LOWORD(wParam)) {
1052 case IDCANCEL:
1053 case IDOK:
1054 EndDialog(hwnd, 1);
1055 return TRUE;
1056 }
1057 break;
1058 default:
1059 break;
1060 }
1061 return FALSE;
1062 }
1063
popupprompt(Widget button,char * request,char * current,void (* function)(),buttonsave * datastruct,const char * filter)1064 void popupprompt(Widget button, char *request, char *current, void (*function)(), buttonsave *datastruct, const char *filter)
1065 {
1066 if (current != NULL && filter == NULL) {
1067 InputDlgData data;
1068
1069 data.request = request;
1070 data.current = current;
1071 if (DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_INPUTDIALOG), areawin->window, InputDlgProc, (LPARAM)&data))
1072 (*function)(button, (datastruct != NULL ? datastruct->dataptr : NULL));
1073 } else if (filter != NULL) {
1074 OPENFILENAME ofn;
1075 char filename[1024] = {0};
1076 char filterspec[1024] = {0};
1077
1078 ZeroMemory(&ofn, sizeof(ofn));
1079 ofn.lStructSize = sizeof(ofn);
1080 ofn.hwndOwner = areawin->window;
1081 if (*filter) {
1082 _snprintf(filterspec, 1024, "Enable Filter (*%s)%c*%s%cDisable Filter (*.*)%c*.*%c%c%c",
1083 filter, 0, filter, 0, 0, 0, 0, 0);
1084 ofn.lpstrFilter = filterspec;
1085 } else
1086 ofn.lpstrFilter = "All Files (*.*)\000*.*\000\000\000";
1087 ofn.lpstrFile = filename;
1088 ofn.nMaxFile = 1024;
1089 if (GetOpenFileName(&ofn)) {
1090 char *c;
1091 strcpy(_STR2, ofn.lpstrFile);
1092 for (c=_STR2; *c; c++)
1093 if (*c == '\\') *c = '/';
1094 (*function)(button, datastruct->dataptr);
1095 }
1096 } else {
1097 if (MessageBox(areawin->window, request, "XCircuit", MB_YESNO|MB_ICONQUESTION) == IDYES)
1098 (*function)(button, datastruct->dataptr);
1099 }
1100
1101 if (datastruct != NULL) free(datastruct);
1102 }
1103
get_vkey_name(int key,char * str,int len)1104 static void get_vkey_name(int key, char *str, int len)
1105 {
1106 UINT scan = MapVirtualKey(key, 0);
1107 scan = (scan&0xff)<<16;
1108 switch (key) {
1109 case VK_HOME:
1110 case VK_PRIOR:
1111 case VK_NEXT:
1112 case VK_END:
1113 case VK_DELETE:
1114 case VK_INSERT:
1115 case VK_LEFT:
1116 case VK_RIGHT:
1117 case VK_UP:
1118 case VK_DOWN:
1119 scan |= (1<<24);
1120 break;
1121 case VK_CLEAR:
1122 memcpy(str, "CLEAR", 5);
1123 return;
1124 default:
1125 break;
1126 }
1127 GetKeyNameText(scan, str, len);
1128 }
1129
WinKeyToString(int key)1130 char *WinKeyToString(int key)
1131 {
1132 static char buffer[1024];
1133
1134 memset(buffer, 0, 1024);
1135 if (key >= XK_a && key <= XK_z)
1136 buffer[0] = (char)key;
1137 else if (key >= XK_A && key <= XK_Z)
1138 buffer[0] = (char)key;
1139 else {
1140 int offset = 0;
1141
1142 if (key & KPMOD) {
1143 strcpy(buffer, "Keypad_");
1144 offset = 7;
1145 }
1146 if (key & VKMOD)
1147 get_vkey_name(key&0x00ff, buffer+offset, 1024-offset);
1148 else
1149 buffer[offset] = key&0x00ff;
1150 }
1151
1152 return buffer;
1153 }
1154
WinStringToKey(const char * str)1155 int WinStringToKey(const char *str)
1156 {
1157 int key;
1158 char buf[256];
1159
1160 for (key=1; key<256; key++) {
1161 memset(buf, 0, 256);
1162 get_vkey_name(key, buf, 256);
1163 if (strcmp(str, buf) == 0)
1164 return key;
1165 }
1166 return 0;
1167 }
1168
1169 static Widget WndFound;
1170
WndLookupProc(HWND hwnd,LPARAM lParam)1171 BOOL CALLBACK WndLookupProc(HWND hwnd, LPARAM lParam)
1172 {
1173 Widget w = (Widget)get_widget(hwnd);
1174
1175 if (w != NULL && strcmp((char*)lParam, w->name) == 0) {
1176 WndFound = w;
1177 W32DEBUG(("widget name: '%s'\n", w->name));
1178 return FALSE;
1179 }
1180 W32DEBUG(("widget name: '%s' (%p)\n", (w ? w->name : (char*)w)));
1181 return TRUE;
1182 }
1183
WinName(Widget w)1184 const char* WinName(Widget w)
1185 {
1186 switch (w->type) {
1187 case WIN_WIDGET:
1188 return w->name;
1189 case WIN_MENUITEM:
1190 return TOMENUITEM(w)->name;
1191 case WIN_TOOLITEM:
1192 return TOTOOLITEM(w)->name;
1193 default:
1194 return NULL;
1195 }
1196 }
1197
WinNameToWindow(Widget parent,const char * name)1198 Widget WinNameToWindow(Widget parent, const char *name)
1199 {
1200 W32DEBUG(("Looking for '%s' in %p\n", name, parent));
1201 WndFound = NULL;
1202 if (parent != NULL)
1203 switch (parent->type) {
1204 case WIN_WIDGET:
1205 if (parent == toolBar) {
1206 TBBUTTON tb;
1207 int nbuttons = SendMessage(toolBar->handle, TB_BUTTONCOUNT, 0, 0), i;
1208 for (i=0; i<nbuttons; i++) {
1209 ZeroMemory(&tb, sizeof(tb));
1210 SendMessage(toolBar->handle, TB_GETBUTTON, i, (LPARAM)&tb);
1211 if (tb.dwData != 0) {
1212 ToolItem item = (ToolItem)tb.dwData;
1213 if (item->name && strcmp(item->name, name) == 0) {
1214 WndFound = (Widget)item;
1215 break;
1216 }
1217 }
1218 }
1219 } else
1220 EnumChildWindows(parent->handle, WndLookupProc, (LPARAM)name);
1221 break;
1222 case WIN_MENUITEM:
1223 if (TOMENUITEM(parent)->popup != NULL)
1224 parent = (Widget)TOMENUITEM(parent)->popup;
1225 else
1226 break;
1227 case WIN_MENU:
1228 {
1229 int i, n = GetMenuItemCount((HMENU)parent->handle);
1230 MENUITEMINFO mi_info;
1231
1232 ZeroMemory(&mi_info, sizeof(mi_info));
1233 mi_info.cbSize = sizeof(mi_info);
1234 mi_info.fMask = MIIM_DATA;
1235 for (i=0; i<n; i++) {
1236 mi_info.dwItemData = (LONG)NULL;
1237 if (GetMenuItemInfo((HMENU)parent->handle, i, MF_BYPOSITION, &mi_info)
1238 && mi_info.dwItemData && ((MenuItem)mi_info.dwItemData)->name
1239 && strcmp(((MenuItem)mi_info.dwItemData)->name, name) == 0) {
1240 WndFound = (Widget)mi_info.dwItemData;
1241 break;
1242 }
1243 }
1244 }
1245 break;
1246 }
1247 return WndFound;
1248 }
1249
outputpopup(Widget button,caddr_t clientdata,caddr_t calldata)1250 void outputpopup(Widget button, caddr_t clientdata, caddr_t calldata)
1251 {
1252 if (is_page(topobject) == -1) {
1253 Wprintf("Can only save a top-level page!");
1254 return;
1255 }
1256 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_OUTPUTDLG), top->handle, OutputDlgProc);
1257 }
1258
1259 typedef struct {
1260 char *bits;
1261 int width, height;
1262 } cursor_bits;
1263
reverse_byte(u_char c)1264 static u_char reverse_byte(u_char c)
1265 {
1266 u_char rc = 0;
1267 int i;
1268
1269 for (i=(sizeof(char)*8-1); i>=0; i--, c>>=1)
1270 rc |= (c&0x01) << i;
1271 return rc;
1272 }
1273
compute_cursor_src_mask(u_char * src,u_char * mask)1274 static void compute_cursor_src_mask(u_char *src, u_char *mask)
1275 {
1276 u_char pixsrc = *src, pixmask = *mask;
1277 *src = ~(reverse_byte(pixmask));
1278 *mask = reverse_byte((u_char)((~pixsrc&0xff)&pixmask));
1279 }
1280
create_stipple(char * stipdata)1281 static HBITMAP create_stipple(char *stipdata)
1282 {
1283 HBITMAP hBitmap;
1284 BYTE data[8];
1285 int i;
1286
1287 for (i=0; i<4; i++) {
1288 data[2*i] = 0xff & ~reverse_byte(stipdata[i]);
1289 }
1290 hBitmap = CreateBitmap(4, 4, 1, 1, data);
1291 return hBitmap;
1292 }
1293
WinCreateBitmapFromData(HWND w,char * data,int width,int height)1294 HBITMAP WinCreateBitmapFromData(HWND w, char *data, int width, int height)
1295 {
1296 if (width == 4 && height == 4) {
1297 return create_stipple(data);
1298 } else {
1299 cursor_bits *cbits = (cursor_bits*)malloc(sizeof(cursor_bits));
1300 cbits->bits = data;
1301 cbits->width = width;
1302 cbits->height = height;
1303 return (HBITMAP)cbits;
1304 }
1305 }
1306
WinCreateCursor(HBITMAP _src,HBITMAP _mask,int xhot,int yhot)1307 HCURSOR WinCreateCursor(HBITMAP _src, HBITMAP _mask, int xhot, int yhot)
1308 {
1309 HCURSOR hCursor = NULL;
1310 u_char *src = ((cursor_bits*)_src)->bits, *mask = ((cursor_bits*)_mask)->bits;
1311 u_char *new_src, *new_mask;
1312 int width = ((cursor_bits*)_src)->width, height = ((cursor_bits*)_src)->height;
1313 int nb = (width-1)/(8*sizeof(char))+1;
1314 int nb2 = (GetSystemMetrics(SM_CXCURSOR)-1)/(8*sizeof(char))+1, height2 = GetSystemMetrics(SM_CYCURSOR);
1315 int i, j, idx1 = 0, idx2 = 0;
1316
1317 new_src = (u_char*)malloc(sizeof(char)*nb2*height2);
1318 new_mask = (u_char*)malloc(sizeof(char)*nb2*height2);
1319
1320 for (j=0; j<height; j++) {
1321 for (i=0; i<nb; i++, idx1++, idx2++) {
1322 new_src[idx2] = src[idx1];
1323 new_mask[idx2] = mask[idx1];
1324 compute_cursor_src_mask(&new_src[idx2], &new_mask[idx2]);
1325 }
1326 for (i=0; i<(nb2-nb); i++, idx2++) {
1327 new_src[idx2] = 0xff;
1328 new_mask[idx2] = 0x00;
1329 }
1330 }
1331 for (j=0; j<(height2-height); j++) {
1332 for (i=0; i<nb2; i++, idx2++) {
1333 new_src[idx2] = 0xff;
1334 new_mask[idx2] = 0x00;
1335 }
1336 }
1337
1338 hCursor = CreateCursor(GetModuleHandle(NULL), xhot, yhot, nb2*8, height2, new_src, new_mask);
1339
1340 free(new_src);
1341 free(new_mask);
1342 free(_src);
1343 free(_mask);
1344
1345 return hCursor;
1346 }
1347
create_widget(HWND handle,char * name)1348 static Widget create_widget(HWND handle, char *name)
1349 {
1350 Widget w = (Widget)malloc(sizeof(struct __WinWidget));
1351
1352 ZeroMemory(w, sizeof(struct __WinWidget));
1353 w->type = WIN_WIDGET;
1354 w->handle = handle;
1355 w->name = strdup(name);
1356 if (strcmp(name, "Area") == 0) {
1357 RECT r;
1358 GetWindowRect(handle, &r);
1359 w->buffer = WinCreatePixmap(handle, r.right-r.left, r.bottom-r.top);
1360 w->bufhdc = CreateCompatibleDC(NULL);
1361 SelectObject(w->bufhdc, w->buffer);
1362 }
1363 SetWindowLong(handle, GWL_USERDATA, (LONG)w);
1364 return w;
1365 }
1366
destroy_widget(HWND handle)1367 static void destroy_widget(HWND handle)
1368 {
1369 Widget w = (Widget)get_widget(handle);
1370 WinCallback *cb = w->callbacks, *free_cb;
1371 WinEventHandler *eh = w->handlers, *free_eh;
1372
1373 free(w->name);
1374 while (cb != NULL) {
1375 free_cb = cb;
1376 cb = cb->next;
1377 free(free_cb);
1378 }
1379 while (eh != NULL) {
1380 free_eh = eh;
1381 eh = eh->next;
1382 free(free_eh);
1383 }
1384 if (w->wndproc != NULL)
1385 SetWindowLong(handle, GWL_WNDPROC, (LONG)w->wndproc);
1386 free(w);
1387 }
1388
XcTopWindowProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)1389 LRESULT CALLBACK XcTopWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1390 {
1391 switch (msg) {
1392 case WM_CLOSE:
1393 quitcheck(NULL, NULL, NULL);
1394 return 0;
1395 case WM_ACTIVATE:
1396 if (wParam != 0) {
1397 XCWindowData *w;
1398
1399 for (w=xobjs.windowlist; w!=NULL; w=w->next)
1400 if (GetAncestor(w->window, GA_ROOT) == hwnd)
1401 break;
1402 if (w != NULL && areawin != w) {
1403 areawin = w;
1404 top = get_widget(GetAncestor(areawin->window, GA_ROOT));
1405 topwin = top->handle;
1406 toolBar = get_widget(GetDlgItem(topwin, TOOLBAR_ID));
1407 statusBar = GetDlgItem(topwin, STATUSBAR_ID);
1408 {
1409 MENUITEMINFO mi_info;
1410 HMENU hMenu = GetMenu(hwnd);
1411 int i;
1412
1413 ZeroMemory(&mi_info, sizeof(mi_info));
1414 mi_info.cbSize = sizeof(mi_info);
1415 for (i=0; i<MaxMenuWidgets; i++) {
1416 mi_info.fMask = MIIM_DATA;
1417 mi_info.dwItemData = (LONG)NULL;
1418 if (GetMenuItemInfo(hMenu, 100+i, FALSE, &mi_info))
1419 menuwidgets[i] = (Widget)mi_info.dwItemData;
1420 else
1421 printf("menu not found: %d\n", i);
1422 }
1423 }
1424 }
1425 SetFocus(areawin->window);
1426 }
1427 return 0;
1428 case WM_SIZE:
1429 {
1430 int width = LOWORD(lParam), th, sh, height = HIWORD(lParam), nbrows = 1;
1431 DWORD sz;
1432 RECT sr;
1433
1434 SetWindowPos(toolBar->handle, HWND_TOP, 0, 0, width, 25, 0);
1435
1436 sz = SendMessage(toolBar->handle, TB_GETBUTTONSIZE, 0, 0);
1437 nbrows = SendMessage(toolBar->handle, TB_GETROWS, 0, 0);
1438 th = nbrows*HIWORD(sz)+6;
1439 GetWindowRect(statusBar, &sr);
1440 sh = sr.bottom-sr.top;
1441
1442 SetWindowPos(areawin->area->handle, HWND_TOP, SBARSIZE, th, width-SBARSIZE, height-sh-th-SBARSIZE, 0);
1443 SetWindowPos(areawin->scrollbarh->handle, HWND_TOP, SBARSIZE, height-sh-SBARSIZE, width-SBARSIZE, SBARSIZE, 0);
1444 SetWindowPos(areawin->scrollbarv->handle, HWND_TOP, 0, th, SBARSIZE, height-sh-th-SBARSIZE, 0);
1445 SetWindowPos(corner, HWND_TOP, 0, height-sh-SBARSIZE, 0, 0, SWP_NOSIZE);
1446 SetWindowPos(statusBar, HWND_TOP, 0, height-sh, width, sh, 0);
1447 InvalidateRect(statusBar, NULL, FALSE);
1448 SetWindowPos(toolBar->handle, HWND_TOP, 0, 0, width, th, 0);
1449 InvalidateRect(toolBar->handle, NULL, FALSE);
1450 }
1451 return DefWindowProc(hwnd, msg, wParam, lParam);
1452 case WM_MENUCOMMAND:
1453 {
1454 MENUITEMINFO mi_info;
1455 MenuItem item;
1456
1457 ZeroMemory(&mi_info, sizeof(mi_info));
1458 mi_info.cbSize = sizeof(mi_info);
1459 mi_info.fMask = MIIM_DATA;
1460 GetMenuItemInfo((HMENU)lParam, wParam, MF_BYPOSITION, &mi_info);
1461
1462 if ((item = (MenuItem)mi_info.dwItemData) != NULL && item->callbacks != NULL) {
1463 W32DEBUG(("Calling callback\n"));
1464 execute_callback(XtNselect, (Widget)item, NULL);
1465 }
1466 }
1467 return 0;
1468 case WM_COMMAND:
1469 if ((HWND)lParam == toolBar->handle) {
1470 TBBUTTONINFO tbi;
1471
1472 ZeroMemory(&tbi, sizeof(tbi));
1473 tbi.cbSize = sizeof(tbi);
1474 tbi.dwMask = TBIF_LPARAM;
1475 if (SendMessage(toolBar->handle, TB_GETBUTTONINFO, LOWORD(wParam), (LPARAM)&tbi) != -1) {
1476 ToolItem item = (ToolItem)tbi.lParam;
1477 W32DEBUG(("Tool button: %s\n", item->name));
1478 execute_callback(XtNselect, (Widget)item, NULL);
1479 }
1480 }
1481 return 0;
1482 default:
1483 return DefWindowProc(hwnd, msg, wParam, lParam);
1484 }
1485 }
1486
button_event(Widget win,int type,int button,short x,short y)1487 void button_event(Widget win, int type, int button, short x, short y)
1488 {
1489 XButtonEvent event;
1490
1491 event.type = type;
1492 event.x = x;
1493 event.y = y;
1494 event.button = (button & MK_LBUTTON ? Button1 : 0) |
1495 (button & MK_RBUTTON ? Button3 : 0) |
1496 (button & MK_MBUTTON ? Button2 : 0) |
1497 (button & MK_XBUTTON1 ? Button4 : 0) |
1498 (button & MK_XBUTTON2 ? Button5 : 0);
1499 event.state = (GetKeyState(VK_CONTROL) & 0x8000 ? ControlMask : 0) |
1500 (GetKeyState(VK_SHIFT) & 0x8000 ? ShiftMask : 0) |
1501 (GetKeyState(VK_MENU) & 0x8000 ? Mod1Mask : 0);
1502
1503 if (win == areawin->scrollbarh || win == areawin->scrollbarv)
1504 if (type == ButtonPress)
1505 SetCapture(win->handle);
1506 else if (type == ButtonRelease)
1507 ReleaseCapture();
1508
1509 switch (type) {
1510 case ButtonPress:
1511 execute_callback(XtNselect, win, &event);
1512 break;
1513 case ButtonRelease:
1514 execute_callback(XtNrelease, win, &event);
1515 break;
1516 case MotionNotify:
1517 if (event.button && HAS_HANDLER(win, ButtonMotionMask))
1518 execute_handler(ButtonMotionMask, win, &event);
1519 if ((event.button & Button1Mask) && HAS_HANDLER(win, Button1MotionMask))
1520 execute_handler(Button1MotionMask, win, &event);
1521 if ((event.button & Button2Mask) && HAS_HANDLER(win, Button2MotionMask))
1522 execute_handler(Button2MotionMask, win, &event);
1523 if (HAS_HANDLER(win, PointerMotionMask))
1524 execute_handler(PointerMotionMask, win, &event);
1525 break;
1526 }
1527 }
1528
key_event(Widget win,int type,int key,int scan)1529 void key_event(Widget win, int type, int key, int scan)
1530 {
1531 POINT pt;
1532 static BYTE keys[256];
1533 WORD c = 0x0000;
1534 XKeyEvent event;
1535
1536 GetCursorPos(&pt);
1537 ScreenToClient(win->handle, &pt);
1538 event.type = type;
1539 event.x = pt.x;
1540 event.y = pt.y;
1541 event.state = 0;
1542 event.keycode = 0;
1543
1544 GetKeyboardState(keys);
1545 if (keys[VK_CONTROL] & 0x80) { event.state |= ControlMask; keys[VK_CONTROL] &= ~0x80; }
1546 if (keys[VK_MENU] & 0x80) { event.state |= Mod1Mask; keys[VK_MENU] &= ~0x80; }
1547 keys[VK_NUMLOCK] &= 0x01;
1548 if (ToAscii(key, scan, keys, &c, 0) == 1 && c >= ' ' && c <= '~') {
1549 W32DEBUG(("char: %c (%08x)\n", c, c));
1550 event.keycode = 0xff & c;
1551 switch (c) {
1552 case '/':
1553 if (scan & 0x1000000) event.keycode |= KPMOD;
1554 break;
1555 case '*':
1556 case '-':
1557 case '+':
1558 if ((VkKeyScan(c)&0xff) != key)
1559 event.keycode |= KPMOD;
1560 break;
1561 default:
1562 break;
1563 }
1564 } else {
1565 if (keys[VK_SHIFT] & 0x80) event.state |= ShiftMask;
1566 event.keycode |= VKMOD;
1567 switch (key) {
1568 case VK_RETURN:
1569 if (scan & 0x1000000) event.keycode |= KPMOD;
1570 else event.keycode |= VKMOD;
1571 break;
1572 case VK_HOME:
1573 case VK_UP:
1574 case VK_PRIOR:
1575 case VK_LEFT:
1576 case VK_RIGHT:
1577 case VK_END:
1578 case VK_DOWN:
1579 case VK_NEXT:
1580 case VK_DELETE:
1581 if (!(scan & 0x1000000)) event.keycode |= KPMOD;
1582 else event.keycode |= VKMOD;
1583 break;
1584 case VK_CLEAR:
1585 if (scan == 0x004c0001 || scan == 0xc04c0001) event.keycode |= KPMOD;
1586 break;
1587 default:
1588 event.keycode |= VKMOD;
1589 break;
1590 }
1591 event.keycode |= key;
1592 W32DEBUG(("non char: %d\n", event.keycode));
1593 }
1594
1595 switch (type) {
1596 case KeyPress:
1597 execute_callback(XtNkeyDown, win, &event);
1598 break;
1599 case KeyRelease:
1600 execute_callback(XtNkeyUp, win, &event);
1601 break;
1602 }
1603 }
1604
XcWidgetProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)1605 LRESULT CALLBACK XcWidgetProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1606 {
1607 Widget win = (Widget)get_widget(hwnd);
1608
1609 switch (msg) {
1610 case WM_DESTROY:
1611 destroy_widget(hwnd);
1612 return 0;
1613 case WM_PAINT:
1614 {
1615 RECT r;
1616 GetUpdateRect(hwnd, &r, FALSE);
1617 if (win != NULL)
1618 execute_callback(XtNexpose, win, NULL);
1619 ValidateRect(hwnd, &r);
1620 }
1621 return 0;
1622 case WM_SIZE:
1623 InvalidateRect(hwnd, NULL, FALSE);
1624 if (win != NULL) {
1625 execute_callback(XtNresize, win, NULL);
1626 if (win->buffer != NULL) {
1627 WinFreePixmap(win->buffer);
1628 win->buffer = WinCreatePixmap(hwnd, LOWORD(lParam), HIWORD(lParam));
1629 SelectObject(win->bufhdc, win->buffer);
1630 }
1631 }
1632 return 0;
1633 case WM_CHAR:
1634 W32DEBUG(("WM_CHAR: %08x %08x\n", wParam, lParam));
1635 return 0;
1636 case WM_SYSKEYDOWN:
1637 if (wParam == VK_MENU || (wParam == VK_F4 && GetKeyState(VK_MENU) && 0x8000))
1638 return DefWindowProc(hwnd, msg, wParam, lParam);
1639 case WM_KEYDOWN:
1640 W32DEBUG(("WM_KEYDOWN: %08x %08x %08x\n", wParam, lParam, MapVirtualKey((0x00ff0000&lParam)>>16, 1)));
1641 key_event(win, KeyPress, MapVirtualKey((0x00ff0000&lParam)>>16, 1), lParam);
1642 return 0;
1643 case WM_SYSKEYUP:
1644 if (wParam == VK_MENU)
1645 return DefWindowProc(hwnd, msg, wParam, lParam);
1646 case WM_KEYUP:
1647 W32DEBUG(("WM_KEYUP: %08x %08x\n", wParam, lParam));
1648 key_event(win, KeyRelease, MapVirtualKey((0x00ff0000&lParam)>>16, 1), lParam);
1649 return 0;
1650 case WM_MOUSEMOVE:
1651 button_event(win, MotionNotify, wParam, LOWORD(lParam), HIWORD(lParam));
1652 return 0;
1653 case WM_RBUTTONDOWN:
1654 case WM_MBUTTONDOWN:
1655 case WM_LBUTTONDOWN:
1656 button_event(win, ButtonPress, wParam, LOWORD(lParam), HIWORD(lParam));
1657 return 0;
1658 case WM_RBUTTONUP:
1659 button_event(win, ButtonRelease, MK_RBUTTON, LOWORD(lParam), HIWORD(lParam));
1660 return 0;
1661 case WM_MBUTTONUP:
1662 button_event(win, ButtonRelease, MK_MBUTTON, LOWORD(lParam), HIWORD(lParam));
1663 return 0;
1664 case WM_LBUTTONUP:
1665 button_event(win, ButtonRelease, MK_LBUTTON, LOWORD(lParam), HIWORD(lParam));
1666 return 0;
1667 case WM_MOUSEWHEEL:
1668 {
1669 SHORT delta = HIWORD(wParam);
1670 panbutton((delta > 0 ? 3 : 4), 0, 0, 0.05);
1671 refresh(NULL, NULL, NULL);
1672 }
1673 return 0;
1674 case WM_HSCROLL:
1675 switch (LOWORD(wParam)) {
1676 case SB_LINELEFT:
1677 panbutton(1, 0, 0, 0.03);
1678 break;
1679 case SB_LINERIGHT:
1680 panbutton(2, 0, 0, 0.03);
1681 break;
1682 }
1683 refresh(NULL, NULL, NULL);
1684 return 0;
1685 default:
1686 if (msg == WM_BITBLT && win != NULL && win->buffer != NULL) {
1687 HDC winhdc = GetDC(hwnd);
1688 RECT r;
1689 MSG pmsg;
1690
1691 while (PeekMessage(&pmsg, hwnd, WM_BITBLT, WM_BITBLT, PM_REMOVE));
1692 GetWindowRect(hwnd, &r);
1693 BitBlt(winhdc, 0, 0, r.right-r.left, r.bottom-r.top, win->bufhdc, 0, 0, SRCCOPY);
1694 ReleaseDC(hwnd, winhdc);
1695 return 0;
1696 } else
1697 return DefWindowProc(hwnd, msg, wParam, lParam);
1698 }
1699 }
1700
XcHelppixProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)1701 LRESULT CALLBACK XcHelppixProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1702 {
1703 switch (msg) {
1704 case WM_GETDLGCODE:
1705 return DLGC_WANTARROWS;
1706 case WM_CREATE:
1707 if (helppix == NULL)
1708 printhelppix();
1709 helptop = 0;
1710 return 0;
1711 case WM_SIZE:
1712 {
1713 SCROLLINFO si;
1714
1715 si.cbSize = sizeof(SCROLLINFO);
1716 si.fMask = SIF_ALL;
1717 si.nMin = 0;
1718 si.nMax = (helpheight-HIWORD(lParam)+400-1);
1719 si.nPage = 400;
1720 si.nPos = 0;
1721 SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
1722 return 0;
1723 }
1724 case WM_PAINT:
1725 {
1726 HDC hdc, pixhdc;
1727 PAINTSTRUCT ps;
1728 RECT r;
1729
1730 hdc = BeginPaint(hwnd, &ps);
1731 pixhdc = get_hdc(helppix, hgc);
1732 GetClientRect(hwnd, &r);
1733 BitBlt(hdc, 0, 0, r.right-r.left, r.bottom-r.top, pixhdc, 0, helptop, SRCCOPY);
1734 release_hdc(helppix, pixhdc);
1735 EndPaint(hwnd, &ps);
1736 return 0;
1737 }
1738 break;
1739 case WM_VSCROLL:
1740 {
1741 SCROLLINFO si;
1742 int pos;
1743
1744 si.cbSize = sizeof(si);
1745 si.fMask = SIF_ALL;
1746 GetScrollInfo(hwnd, SB_VERT, &si);
1747 switch (LOWORD(wParam)) {
1748 case SB_PAGEUP:
1749 si.nPos -= si.nPage;
1750 break;
1751 case SB_PAGEDOWN:
1752 si.nPos += si.nPage;
1753 break;
1754 case SB_LINEUP:
1755 si.nPos -= 15;
1756 break;
1757 case SB_LINEDOWN:
1758 si.nPos += 15;
1759 break;
1760 case SB_THUMBTRACK:
1761 si.nPos = si.nTrackPos;
1762 break;
1763 }
1764 si.fMask = SIF_POS;
1765 SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
1766 GetScrollInfo(hwnd, SB_VERT, &si);
1767 helptop = si.nPos;
1768 InvalidateRect(hwnd, NULL, FALSE);
1769 }
1770 return 0;
1771 case WM_KEYDOWN:
1772 switch (wParam) {
1773 case VK_NEXT:
1774 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
1775 break;
1776 case VK_PRIOR:
1777 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
1778 break;
1779 case VK_DOWN:
1780 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
1781 break;
1782 case VK_UP:
1783 SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
1784 break;
1785 }
1786 return 0;
1787 default:
1788 return DefWindowProc(hwnd, msg, wParam, lParam);
1789 }
1790 }
1791
create_font_struct(HFONT hFont)1792 static XFontStruct* create_font_struct(HFONT hFont)
1793 {
1794 TEXTMETRIC tm;
1795 XFontStruct *fs = NULL;
1796 HDC hdc = GetDC(NULL);
1797
1798 SelectObject(hdc, hFont);
1799 if (GetTextMetrics(hdc, &tm)) {
1800 fs = (XFontStruct*)malloc(sizeof(XFontStruct));
1801 fs->ascent = tm.tmAscent;
1802 fs->descent = tm.tmDescent;
1803 fs->fid = hFont;
1804 } else {
1805 W32DEBUG(("Failed to create font structure\n"));
1806 }
1807 ReleaseDC(NULL, hdc);
1808
1809 return fs;
1810 }
1811
1812 static menuID = 100;
1813
create_win_menu(HMENU menu)1814 static Menu create_win_menu(HMENU menu)
1815 {
1816 Menu wmenu = (Menu)malloc(sizeof(struct __WinMenu));
1817 MENUINFO minfo;
1818
1819 wmenu->type = WIN_MENU;
1820 wmenu->handle = menu;
1821 minfo.cbSize = sizeof(MENUINFO);
1822 minfo.fMask = MIM_MENUDATA | MIM_STYLE;
1823 minfo.dwStyle = MNS_NOTIFYBYPOS;
1824 minfo.dwMenuData = (DWORD)wmenu;
1825 SetMenuInfo(menu, &minfo);
1826
1827 return wmenu;
1828 }
1829
insert_win_menuitem(Menu menu,MENUITEMINFO * mi_info,menustruct * ms,int pos)1830 static MenuItem insert_win_menuitem(Menu menu, MENUITEMINFO* mi_info, menustruct *ms, int pos)
1831 {
1832 MenuItem item = (MenuItem)malloc(sizeof(struct __WinMenuItem));
1833
1834 ZeroMemory(item, sizeof(struct __WinMenuItem));
1835 item->type = WIN_MENUITEM;
1836 item->parentMenu = menu;
1837 if (mi_info->fMask & MIIM_SUBMENU && mi_info->hSubMenu != NULL) {
1838 MENUINFO popup_info;
1839 ZeroMemory(&popup_info, sizeof(popup_info));
1840 popup_info.cbSize = sizeof(popup_info);
1841 popup_info.fMask = MIM_MENUDATA;
1842 if (GetMenuInfo(mi_info->hSubMenu, &popup_info))
1843 item->popup = (Menu)popup_info.dwMenuData;
1844 }
1845 else if (mi_info->fMask & MIIM_ID) {
1846 item->ID = mi_info->wID;
1847 menuwidgets[mi_info->wID-100] = (Widget)item;
1848 } else if (!(mi_info->fMask & MIIM_FTYPE && mi_info->fType == MFT_SEPARATOR)){
1849 }
1850 if (ms != NULL) {
1851 if (ms->func != NULL && ms->func != DoNothing)
1852 WinAddCallback((Widget)item, XtNselect, ms->func, ms->passeddata);
1853 item->name = strdup(ms->name);
1854 }
1855 if (pos < 0)
1856 pos = GetMenuItemCount(menu->handle);
1857 item->position = pos;
1858 item->menudata = mi_info->dwItemData;
1859 mi_info->fMask |= MIIM_DATA;
1860 mi_info->dwItemData = (DWORD)item;
1861 InsertMenuItem(menu->handle, item->position, MF_BYPOSITION, mi_info);
1862 for (pos++; pos<GetMenuItemCount(menu->handle); pos++) {
1863 MENUITEMINFO info;
1864 ZeroMemory(&info, sizeof(info));
1865 info.cbSize = sizeof(info);
1866 info.fMask = MIIM_DATA;
1867 GetMenuItemInfo(menu->handle, pos, MF_BYPOSITION, &info);
1868 TOMENUITEM(info.dwItemData)->position = pos;
1869 }
1870 return item;
1871 }
1872
1873 #if 0
1874 #define MENUICON_WIDTH GetSystemMetrics(SM_CXMENUCHECK)
1875 #define MENUICON_HEIGHT GetSystemMetrics(SM_CYMENUCHECK)
1876 #else
1877 #define MENUICON_WIDTH 12
1878 #define MENUICON_HEIGHT 12
1879 #endif
1880
create_color_icon(int color,int width,int height)1881 static HBITMAP create_color_icon(int color, int width, int height)
1882 {
1883 HDC hdc = GetDC(NULL);
1884 HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
1885 HBRUSH hBrush = CreateSolidBrush(color);
1886 RECT r = {0, 0};
1887
1888 ReleaseDC(NULL, hdc);
1889 r.right = width;
1890 r.bottom = height;
1891 hdc = CreateCompatibleDC(NULL);
1892 SelectObject(hdc, hBitmap);
1893 FillRect(hdc, &r, hBrush);
1894 DeleteObject(hBrush);
1895 DeleteDC(hdc);
1896
1897 return hBitmap;
1898 }
1899
create_stipple_icon(int stipdata,int width,int height)1900 static HBITMAP create_stipple_icon(int stipdata, int width, int height)
1901 {
1902 HDC hdc = GetDC(NULL);
1903 HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
1904 HBRUSH hBrush = CreatePatternBrush(STIPPLE[stipdata]);
1905 RECT r = {0, 0};
1906
1907 ReleaseDC(NULL, hdc);
1908 r.right = width;
1909 r.bottom = height;
1910 hdc = CreateCompatibleDC(NULL);
1911 SelectObject(hdc, hBitmap);
1912 FillRect(hdc, &r, hBrush);
1913 DeleteObject(hBrush);
1914 DeleteDC(hdc);
1915
1916 return hBitmap;
1917 }
1918
color_string(int c)1919 static char* color_string(int c)
1920 {
1921 static char buf[256];
1922 char *cname = WinColorName(c);
1923
1924 if (cname)
1925 _snprintf(buf, 256, " %s", cname);
1926 else
1927 _snprintf(buf, 256, " %3d, %3d, %3d", GetRValue(c), GetGValue(c), GetBValue(c));
1928 return buf;
1929 }
1930
1931 static void makesubmenu(Menu menu, menustruct *items, int n);
make_color_submenu(Menu menu,menustruct * items,int n)1932 static void make_color_submenu(Menu menu, menustruct *items, int n)
1933 {
1934 if (dpy == NULL)
1935 makesubmenu(menu, items, n);
1936 else {
1937 int i;
1938 MENUITEMINFO mi_info;
1939 MenuItem item;
1940
1941 makesubmenu(menu, items, 3);
1942 menuID += (n-3);
1943 for (i=0; i<number_colors; i++) {
1944 int color = colorlist[i].color.pixel;
1945 HBITMAP hBitmap = create_color_icon(color, MENUICON_WIDTH, MENUICON_HEIGHT);
1946 ZeroMemory(&mi_info, sizeof(mi_info));
1947 mi_info.cbSize = sizeof(mi_info);
1948 mi_info.fMask = MIIM_BITMAP | MIIM_STRING;
1949 mi_info.hbmpItem = hBitmap;
1950 mi_info.dwTypeData = color_string(color);
1951 mi_info.dwItemData = color;
1952
1953 item = insert_win_menuitem(menu, &mi_info, NULL, -1);
1954 item->name = strdup(mi_info.dwTypeData);
1955 WinAddCallback((Widget)item, XtNselect, (XtCallbackProc)setcolor, NULL);
1956 }
1957 }
1958
1959 }
1960
makesubmenu(Menu menu,menustruct * items,int n)1961 static void makesubmenu(Menu menu, menustruct *items, int n)
1962 {
1963 int i;
1964 MENUITEMINFO mi_info;
1965 int is_color = -1;
1966 MenuItem mitem;
1967
1968 for (i=0; i<n; i++) {
1969 ZeroMemory(&mi_info, sizeof(mi_info));
1970 mi_info.cbSize = sizeof(mi_info);
1971 if (items[i].submenu == NULL) {
1972 if (items[i].name[0] == ' ') {
1973 mi_info.fMask = MIIM_FTYPE;
1974 mi_info.fType = MFT_SEPARATOR;
1975 }
1976 else if (items[i].name[0] == '_') {
1977 int color = WinNamedColor(items[i].name+1);
1978 HBITMAP hBitmap = create_color_icon(color, MENUICON_WIDTH, MENUICON_HEIGHT);
1979 mi_info.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID;
1980 mi_info.wID = menuID++;
1981 mi_info.hbmpItem = hBitmap;
1982 mi_info.dwTypeData = color_string(color);
1983 mi_info.dwItemData = color;
1984 is_color = color;;
1985 } else if (items[i].name[0] == ':') {
1986 HBITMAP hBitmap;
1987 if ((int)items[i].passeddata == (OPAQUE | FILLED | FILLSOLID))
1988 hBitmap = create_color_icon(RGB(0, 0, 0), MENUICON_WIDTH, MENUICON_HEIGHT);
1989 else
1990 hBitmap = create_stipple_icon(((int)items[i].passeddata & FILLSOLID)>>5, MENUICON_WIDTH, MENUICON_HEIGHT);
1991 mi_info.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID;
1992 mi_info.wID = menuID++;
1993 mi_info.hbmpItem = hBitmap;
1994 mi_info.dwTypeData = items[i].name;
1995 mi_info.dwItemData = (DWORD)items[i].passeddata;
1996 } else {
1997 mi_info.fMask = MIIM_STRING | MIIM_ID;
1998 mi_info.wID = menuID++;
1999 mi_info.dwTypeData = items[i].name;
2000 }
2001 } else {
2002 Menu popup = create_win_menu(CreatePopupMenu());
2003 if (strncmp(items[i].name, "Color", 5) == 0)
2004 make_color_submenu(popup, items[i].submenu, items[i].size);
2005 else
2006 makesubmenu(popup, items[i].submenu, items[i].size);
2007 mi_info.fMask = MIIM_SUBMENU | MIIM_STRING;
2008 mi_info.hSubMenu = popup->handle;
2009 mi_info.dwTypeData = items[i].name;
2010 }
2011 mitem = insert_win_menuitem(menu, &mi_info, &items[i], -1);
2012 if (is_color != -1 && dpy == NULL)
2013 addtocolorlist((Widget)mitem, is_color);
2014 }
2015 }
2016
create_menus()2017 static HMENU create_menus()
2018 {
2019 Menu menu;
2020 MENUITEMINFO mi_info;
2021 int i;
2022
2023 menuID = 100;
2024 menu = create_win_menu(CreateMenu());
2025 for (i=0; i<maxbuttons; i++) {
2026 ZeroMemory(&mi_info, sizeof(mi_info));
2027 mi_info.cbSize = sizeof(mi_info);
2028 if (TopButtons[i].submenu == NULL) {
2029 mi_info.fMask = MIIM_STRING | MIIM_ID;
2030 mi_info.wID = menuID++;
2031 mi_info.dwTypeData = TopButtons[i].name;
2032 } else {
2033 Menu popup = create_win_menu(CreatePopupMenu());
2034 makesubmenu(popup, TopButtons[i].submenu, TopButtons[i].size);
2035 mi_info.fMask = MIIM_SUBMENU | MIIM_STRING;
2036 mi_info.hSubMenu = popup->handle;
2037 mi_info.dwTypeData = TopButtons[i].name;
2038 }
2039 insert_win_menuitem(menu, &mi_info, &TopButtons[i], -1);
2040 }
2041
2042 return menu->handle;
2043 }
2044
create_statusbar()2045 static void create_statusbar()
2046 {
2047 HDC hdc;
2048 SIZE sz;
2049 StatusItem msg2, msg3;
2050
2051 hdc = GetDC(NULL);
2052 GetTextExtentPoint32(hdc, "Editing: filename (Page 1)", 26, &sz);
2053 statusBarWidth[0] = sz.cx;
2054 ReleaseDC(NULL, hdc);
2055
2056 statusBar = CreateWindow(STATUSCLASSNAME, "", WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP,
2057 0, 0, 100, 100, top->handle, (HMENU)STATUSBAR_ID, NULL, NULL);
2058 SendMessage(statusBar, SB_SETPARTS, 2, (LPARAM)statusBarWidth);
2059 SendMessage(statusBar, SB_SETTEXT, 0, (LPARAM)"Editing: Page 1");
2060 SendMessage(statusBar, SB_SETTEXT, 1, (LPARAM)"Don't Panic");
2061
2062 msg2 = (StatusItem)malloc(sizeof(struct __WinStatusItem));
2063 msg2->handle = statusBar;
2064 msg2->type = WIN_STATUS;
2065 msg2->position = 0;
2066 message2 = (Widget)msg2;
2067
2068 msg3 = (StatusItem)malloc(sizeof(struct __WinStatusItem));
2069 msg3->handle = statusBar;
2070 msg3->type = WIN_STATUS;
2071 msg3->position = 1;
2072 message3 = (Widget)msg3;
2073 }
2074
2075 typedef struct { int c; RGBQUAD color; } xpm_color;
2076
create_bitmap_from_xpm(char ** xpm)2077 static HBITMAP create_bitmap_from_xpm(char **xpm)
2078 {
2079 int width, height, ncolors, nchar;
2080 int i, j, k;
2081 BITMAPINFO *bmi;
2082 HBITMAP hBitmap = NULL;
2083 xpm_color *colors;
2084 BYTE *data;
2085 HDC hdc;
2086
2087 if (sscanf(xpm[0], "%d %d %d %d", &width, &height, &ncolors, &nchar) != 4)
2088 return NULL;
2089 if (nchar != 1) {
2090 W32DEBUG(("(XPM) Unsupported number of char per data\n"));
2091 return NULL;
2092 }
2093 colors = (xpm_color*)malloc(sizeof(xpm_color)*ncolors);
2094 for (i=0; i<ncolors; i++) {
2095 char *str = xpm[i+1];
2096 char snum[5];
2097 colors[i].c = str[0]; str++;
2098 for (; *str!='c'; str++); str+=2;
2099 if (*str == '#') {
2100 str++;
2101 strncpy(snum, str, 4); snum[4] = 0; str+=4;
2102 colors[i].color.rgbRed = 0xff&(strtol(snum, NULL, 16)>>8);
2103 strncpy(snum, str, 4); snum[4] = 0; str+=4;
2104 colors[i].color.rgbGreen = 0xff&(strtol(snum, NULL, 16)>>8);
2105 strncpy(snum, str, 4); snum[4] = 0; str+=4;
2106 colors[i].color.rgbBlue = 0xff&(strtol(snum, NULL, 16)>>8);
2107 } else {
2108 COLORREF cr = WinNamedColor(str);
2109 colors[i].color.rgbRed = GetRValue(cr);
2110 colors[i].color.rgbGreen = GetGValue(cr);
2111 colors[i].color.rgbBlue = GetBValue(cr);
2112 }
2113 }
2114
2115 data = (BYTE*)malloc(sizeof(BYTE)*width*height);
2116 for (j=k=0; j<height; j++) {
2117 for (i=0; i<width; i++, k++) {
2118 char pix = xpm[j+ncolors+1][i];
2119 int idx;
2120 for (idx=0; idx<ncolors; idx++)
2121 if (pix == colors[idx].c) break;
2122 data[k] = idx;
2123 }
2124 }
2125
2126 bmi = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+(ncolors-1)*sizeof(RGBQUAD));
2127 ZeroMemory(bmi, sizeof(BITMAPINFO));
2128 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2129 bmi->bmiHeader.biWidth = width;
2130 bmi->bmiHeader.biHeight = -height;
2131 bmi->bmiHeader.biPlanes = 1;
2132 bmi->bmiHeader.biBitCount = 8;
2133 bmi->bmiHeader.biCompression = BI_RGB;
2134 bmi->bmiHeader.biClrUsed = ncolors;
2135 for (i=0; i<ncolors; i++)
2136 memcpy(bmi->bmiColors+i, &colors[i].color, sizeof(RGBQUAD));
2137 hdc = GetDC(NULL);
2138 hBitmap = CreateDIBitmap(hdc, &bmi->bmiHeader, CBM_INIT, data, bmi, DIB_RGB_COLORS);
2139
2140 ReleaseDC(NULL, hdc);
2141 free(bmi);
2142 free(colors);
2143
2144 return hBitmap;
2145 }
2146
create_toolbar()2147 static void create_toolbar()
2148 {
2149 TBBUTTON *buttons;
2150 TBADDBITMAP bitmap;
2151 int i;
2152
2153 toolBar = create_widget(CreateWindow(TOOLBARCLASSNAME, NULL, WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT|TBSTYLE_WRAPABLE, 0, 0, 0, 0,
2154 top->handle, (HMENU)TOOLBAR_ID, NULL, NULL), "ToolBar");
2155 SendMessage(toolBar->handle, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
2156 SendMessage(toolBar->handle, TB_SETBITMAPSIZE, 0, MAKELONG(20, 20));
2157
2158 buttons = (TBBUTTON*)malloc(sizeof(TBBUTTON) * toolbuttons);
2159 for (i=0; i<toolbuttons; i++) {
2160 ToolItem item;
2161
2162 buttons[i].iBitmap = i;
2163 buttons[i].idCommand = menuID++;
2164 buttons[i].fsState = TBSTATE_ENABLED;
2165 buttons[i].fsStyle = TBSTYLE_BUTTON;
2166 buttons[i].iString = 0;
2167 bitmap.hInst = NULL;
2168 bitmap.nID = (INT_PTR)create_bitmap_from_xpm(ToolBar[i].icon_data);
2169 SendMessage(toolBar->handle, TB_ADDBITMAP, 1, (LPARAM)&bitmap);
2170
2171 item = (ToolItem)malloc(sizeof(struct __WinToolItem));
2172 ZeroMemory(item, sizeof(struct __WinToolItem));
2173 item->type = WIN_TOOLITEM;
2174 item->toolbar = toolBar;
2175 item->ID = buttons[i].idCommand;
2176 item->name = strdup(ToolBar[i].name);
2177 buttons[i].dwData = (DWORD)item;
2178
2179 menuwidgets[item->ID-100] = (Widget)item;
2180 XtAddCallback((Widget)item, XtNselect, (XtCallbackProc)ToolBar[i].func, ToolBar[i].passeddata);
2181
2182 /*
2183 if (ToolBar[i].func == changetool ||
2184 ToolBar[i].func == exec_or_changetool)
2185 buttons[i].fsStyle |= TBSTYLE_CHECK;
2186 */
2187 }
2188 SendMessage(toolBar->handle, TB_ADDBUTTONS, toolbuttons, (LPARAM)buttons);
2189 free(buttons);
2190 }
2191
register_win32_classes()2192 static void register_win32_classes()
2193 {
2194 WNDCLASS wndClass;
2195
2196 /* Top-level window */
2197 ZeroMemory(&wndClass, sizeof(wndClass));
2198 wndClass.lpfnWndProc = XcTopWindowProc;
2199 wndClass.lpszClassName = "XcTopLevel";
2200 wndClass.hIcon = LoadIcon(GetModuleHandle(NULL), "xcircuit");
2201 RegisterClass(&wndClass);
2202
2203 /* Main area */
2204 ZeroMemory(&wndClass, sizeof(wndClass));
2205 wndClass.lpfnWndProc = XcWidgetProc;
2206 wndClass.lpszClassName = "XcWidget";
2207 wndClass.cbWndExtra = sizeof(void*);
2208 RegisterClass(&wndClass);
2209
2210 /* Scroll bar */
2211 ZeroMemory(&wndClass, sizeof(wndClass));
2212 wndClass.lpfnWndProc = XcWidgetProc;
2213 wndClass.lpszClassName = "XcScrollBar";
2214 wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
2215 wndClass.cbWndExtra = sizeof(void*);
2216 RegisterClass(&wndClass);
2217
2218 /* Help widget */
2219 ZeroMemory(&wndClass, sizeof(wndClass));
2220 wndClass.lpfnWndProc = XcHelppixProc;
2221 wndClass.lpszClassName = "XcHelp";
2222 RegisterClass(&wndClass);
2223
2224 /* Popup */
2225 /*
2226 ZeroMemory(&wndClass, sizeof(wndClass));
2227 wndClass.lpfnWndProc = XcPopupProc;
2228 wndClass.lpszClassName = "XcPopup";
2229 wndClass.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
2230 wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
2231 RegisterClass(&wndClass);
2232 */
2233 }
2234
GUI_init(int argc,char * argv[])2235 XCWindowData* GUI_init(int argc, char *argv[])
2236 {
2237 int i;
2238 XGCValues values;
2239 Arg wargs[2];
2240 RECT clientRect = { 0, 0, 0, 0 };
2241 XCWindowData *newwin;
2242
2243 #if 0 && defined(USE_WIN32_COM)
2244 for (i=0; i<argc; i++)
2245 if (strcmp(argv[i], "-register") == 0)
2246 COM_register(1);
2247 else if (strcmp(argv[i], "-unregister") == 0)
2248 COM_register(0);
2249 #endif
2250
2251 if (dpy == NULL) {
2252 register_win32_classes();
2253
2254 appdata.globalcolor = WinNamedColor("Orange2");
2255 appdata.localcolor = WinNamedColor("Red");
2256 appdata.infocolor = WinNamedColor("SeaGreen");
2257 appdata.ratsnestcolor = WinNamedColor("Tan4");
2258 appdata.bboxpix = WinNamedColor("greenyellow");
2259 appdata.fixedbboxpix = WinNamedColor("Pink");
2260 appdata.clipcolor = WinNamedColor("powderblue");
2261 appdata.fg = WinNamedColor("Black");
2262 appdata.bg = WinNamedColor("White");
2263 appdata.gridpix = WinNamedColor("Gray95");
2264 appdata.snappix = WinNamedColor("Red");
2265 appdata.selectpix = WinNamedColor("Gold3");
2266 appdata.querypix = WinNamedColor("Turquoise");
2267 appdata.filterpix = WinNamedColor("SteelBlue3");
2268 appdata.axespix = WinNamedColor("Antique White");
2269 appdata.buttonpix = WinNamedColor("Gray85");
2270 appdata.auxpix = WinNamedColor("Green3");
2271 appdata.barpix = WinNamedColor("Tan");
2272 appdata.parampix = WinNamedColor("Plum3");
2273 appdata.fg2 = WinNamedColor("White");
2274 appdata.bg2 = WinNamedColor("DarkSlateGray");
2275 appdata.gridpix2 = WinNamedColor("Gray40");
2276 appdata.snappix2 = WinNamedColor("Red");
2277 appdata.selectpix2 = WinNamedColor("Gold");
2278 appdata.querypix2 = WinNamedColor("Turquoise");
2279 appdata.filterpix2 = WinNamedColor("SteelBlue1");
2280 appdata.axespix2 = WinNamedColor("NavajoWhite4");
2281 appdata.buttonpix2 = WinNamedColor("Gray50");
2282 appdata.auxpix2 = WinNamedColor("Green");
2283 appdata.barpix2 = WinNamedColor("Tan");
2284 appdata.parampix2 = WinNamedColor("Plum3");
2285 appdata.width = 950;
2286 appdata.height = 760;
2287 appdata.timeout = 10;
2288 appdata.xcfont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
2289 appdata.helpfont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
2290 appdata.filefont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
2291 appdata.textfont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
2292 appdata.titlefont = create_font_struct(GetStockObject(DEFAULT_GUI_FONT));
2293
2294 for (i=0; i<STIPPLES; i++) {
2295 STIPPLE[i] = WinCreateBitmapFromData(NULL, STIPDATA[i], 4, 4);
2296 }
2297
2298 number_colors = NUMBER_OF_COLORS;
2299 colorlist = (colorindex *)malloc(NUMBER_OF_COLORS * sizeof(colorindex));
2300 }
2301
2302 clientRect.right = appdata.width+SBARSIZE;
2303 clientRect.bottom = appdata.height+SBARSIZE;
2304 AdjustWindowRect(&clientRect, WS_TILEDWINDOW, TRUE);
2305 OffsetRect(&clientRect, -clientRect.left, -clientRect.top);
2306
2307 top = create_widget(CreateWindow("XcTopLevel", "XCircuit", WS_TILEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, clientRect.right, clientRect.bottom,
2308 NULL, create_menus(), NULL, NULL), "XCircuit");
2309 topwin = top->handle;
2310
2311 dpy = XtDisplay(top);
2312 newwin = create_new_window();
2313
2314 newwin->scrollbarv = create_widget(CreateWindow("XcScrollBar", "SBV", WS_VISIBLE|WS_CHILD,
2315 0, 0, SBARSIZE, appdata.height-SBARSIZE, top->handle, 0, NULL, NULL), "SBV");
2316 newwin->scrollbarh = create_widget(CreateWindow("XcScrollBar", "SBH", WS_VISIBLE|WS_CHILD,
2317 SBARSIZE, appdata.height-SBARSIZE, appdata.width-SBARSIZE, SBARSIZE, top->handle, 0, NULL, NULL), "SBH");
2318 newwin->area = create_widget(CreateWindow("XcWidget", "Area", WS_VISIBLE|WS_CHILD,
2319 SBARSIZE, 0, appdata.width, appdata.height, top->handle, 0, NULL, NULL), "Area");
2320 newwin->window = newwin->area->handle;
2321 corner = CreateWindow("BUTTON", "", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_FLAT, 0, appdata.height-SBARSIZE, SBARSIZE, SBARSIZE, top->handle, NULL, NULL, NULL);
2322
2323 create_statusbar();
2324 create_toolbar();
2325
2326 XtAddCallback(newwin->area, XtNexpose, (XtCallbackProc)drawarea, NULL);
2327 XtAddCallback(newwin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
2328
2329 XtAddCallback(newwin->area, XtNselect, (XtCallbackProc)buttonhandler, NULL);
2330 XtAddCallback(newwin->area, XtNrelease, (XtCallbackProc)buttonhandler, NULL);
2331 XtAddCallback(newwin->area, XtNkeyDown, (XtCallbackProc)keyhandler, NULL);
2332 XtAddCallback(newwin->area, XtNkeyUp, (XtCallbackProc)keyhandler, NULL);
2333
2334 XtAddEventHandler(newwin->area, Button1MotionMask | Button2MotionMask,
2335 False, (XtEventHandler)xlib_drag, NULL);
2336
2337 XtAddEventHandler(newwin->scrollbarh, ButtonMotionMask, False,
2338 (XtEventHandler)panhbar, NULL);
2339 XtAddEventHandler(newwin->scrollbarv, ButtonMotionMask, False,
2340 (XtEventHandler)panvbar, NULL);
2341
2342 XtAddCallback(newwin->scrollbarh, XtNrelease, (XtCallbackProc)endhbar, NULL);
2343 XtAddCallback(newwin->scrollbarv, XtNrelease, (XtCallbackProc)endvbar, NULL);
2344
2345 XtAddCallback(newwin->scrollbarh, XtNexpose, (XtCallbackProc)drawhbar, NULL);
2346 XtAddCallback(newwin->scrollbarv, XtNexpose, (XtCallbackProc)drawvbar, NULL);
2347 XtAddCallback(newwin->scrollbarh, XtNresize, (XtCallbackProc)drawhbar, NULL);
2348 XtAddCallback(newwin->scrollbarv, XtNresize, (XtCallbackProc)drawvbar, NULL);
2349
2350 values.foreground = RGB(0, 0, 0);
2351 values.background = RGB(255, 255, 255);
2352 values.font = appdata.xcfont->fid;
2353
2354 newwin->gc = XCreateGC(dpy, newwin->window,
2355 GCForeground | GCBackground | GCFont, &values);
2356
2357 XtSetArg(wargs[0], XtNwidth, &newwin->width);
2358 XtSetArg(wargs[1], XtNheight, &newwin->height);
2359 XtGetValues(newwin->area, wargs, 2);
2360
2361 SendMessage(((ToolItem)WireToolButton)->toolbar->handle, TB_CHECKBUTTON, ((ToolItem)WireToolButton)->ID, MAKELONG(TRUE, 0));
2362
2363 #ifdef USE_WIN32_COM
2364 if (!COM_initialize())
2365 printf("Failed to initialize COM interface\n");
2366 #endif
2367
2368 return newwin;
2369 }
2370
WinAddEventHandler(Widget win,int event,void (* proc)(),void * data)2371 void WinAddEventHandler(Widget win, int event, void(*proc)(), void *data)
2372 {
2373 WinEventHandler *h = win->handlers;
2374
2375 if (win->type != WIN_WIDGET) {
2376 W32DEBUG(("Can't add event handler to non widget\n"));
2377 return;
2378 }
2379
2380 while (h != NULL) {
2381 if (h->proc == proc && h->data == data) {
2382 h->action |= event;
2383 break;
2384 } else
2385 h = h->next;
2386 }
2387
2388 if (h == NULL) {
2389 h = (WinEventHandler*)malloc(sizeof(WinEventHandler));
2390 h->action = event;
2391 h->proc = proc;
2392 h->data = data;
2393 h->next = win->handlers;
2394 win->handlers = h;
2395 }
2396
2397 update_event_mask(win);
2398 }
2399
WinRemoveEventHandler(Widget win,int event,void (* proc)(),void * data)2400 void WinRemoveEventHandler(Widget win, int event, void(*proc)(), void *data)
2401 {
2402 WinEventHandler *h, *prev = NULL;
2403
2404 if (win->type != WIN_WIDGET) {
2405 W32DEBUG(("Can't remove event handler from non widget\n"));
2406 return;
2407 }
2408
2409 h = win->handlers;
2410 for (; h!=NULL;)
2411 if ((h->action & event) && h->proc == proc && h->data == data) {
2412 h->action &= ~event;
2413 if (h->action == 0) {
2414 WinEventHandler *old_h = h;
2415 if (prev == NULL)
2416 win->handlers = h = h->next;
2417 else
2418 prev->next = h = h->next;
2419 free(old_h);
2420 }
2421 } else {
2422 prev = h;
2423 h = h->next;
2424 }
2425 update_event_mask(win);
2426 }
2427
WinAddCallback(Widget win,int event,void (* proc)(),void * data)2428 void WinAddCallback(Widget win, int event, void(*proc)(), void *data)
2429 {
2430 WinCallback *cb, **root, *prev = NULL;
2431
2432 if (win == NULL)
2433 return;
2434
2435 switch (win->type) {
2436 case WIN_MENUITEM:
2437 if (TOMENUITEM(win)->popup != NULL) {
2438 Wprintf("Trying to add a callback to a popup menu");
2439 return;
2440 }
2441 root = &((MenuItem)win)->callbacks;
2442 break;
2443 case WIN_TOOLITEM:
2444 root = &((ToolItem)win)->callbacks;
2445 break;
2446 default:
2447 root = &win->callbacks;
2448 break;
2449 }
2450
2451 cb = *root;
2452 while (cb) {
2453 prev = cb;
2454 cb = cb->next;
2455 }
2456
2457 cb = (WinCallback*)malloc(sizeof(WinCallback));
2458 cb->action = event;
2459 cb->proc = proc;
2460 cb->data = data;
2461 cb->next = NULL;
2462
2463 if (prev)
2464 prev->next = cb;
2465 else
2466 *root = cb;
2467 }
2468
WinFindCallback(Widget win,int event,void (** proc)(),void ** data)2469 int WinFindCallback(Widget win, int event, void(**proc)(), void **data)
2470 {
2471 WinCallback *cb;
2472
2473 if (win == NULL)
2474 return 0;
2475
2476 switch (win->type) {
2477 case WIN_MENUITEM:
2478 cb = TOMENUITEM(win)->callbacks;
2479 break;
2480 case WIN_TOOLITEM:
2481 cb = TOTOOLITEM(win)->callbacks;
2482 break;
2483 default:
2484 cb = win->callbacks;
2485 break;
2486 }
2487
2488 while (cb) {
2489 if (cb->action == event) {
2490 if (proc == NULL || *proc == NULL || *proc == cb->proc) {
2491 if (proc != NULL) *proc = cb->proc;
2492 if (data != NULL) *data = cb->data;
2493 return 1;
2494 }
2495 }
2496 cb = cb->next;
2497 }
2498
2499 return 0;
2500 }
2501
WinRemoveCallback(Widget win,int event,void (* proc)(),void * data)2502 void WinRemoveCallback(Widget win, int event, void(*proc)(), void *data)
2503 {
2504 WinCallback *cb;
2505 WinCallback *prev = NULL, **root;
2506
2507 if (win == NULL)
2508 return;
2509
2510 switch (win->type) {
2511 case WIN_MENUITEM:
2512 cb = ((MenuItem)win)->callbacks;
2513 root = &((MenuItem)win)->callbacks;
2514 break;
2515 case WIN_TOOLITEM:
2516 cb = ((ToolItem)win)->callbacks;
2517 root = &((ToolItem)win)->callbacks;
2518 break;
2519 default:
2520 cb = win->callbacks;
2521 root = &win->callbacks;
2522 break;
2523 }
2524 while (cb != NULL) {
2525 if (cb->action == event && (proc == NULL || (cb->proc == proc && cb->data == data))) {
2526 WinCallback *old_cb = cb;
2527 if (prev == NULL)
2528 *root = cb = cb->next;
2529 else
2530 prev->next = cb = cb->next;
2531 free(old_cb);
2532 } else {
2533 prev = cb;
2534 cb = cb->next;
2535 }
2536 }
2537 }
2538
WinRemoveAllCallbacks(Widget win,int event)2539 void WinRemoveAllCallbacks(Widget win, int event)
2540 {
2541 if (win == NULL)
2542 return;
2543
2544 WinRemoveCallback(win, event, NULL, NULL);
2545 }
2546
look_arg(Arg * args,int type,int n)2547 static Arg* look_arg(Arg *args, int type, int n)
2548 {
2549 int i;
2550 for (i=0; i<n; i++)
2551 if (args[i].type == type)
2552 return &args[i];
2553 return NULL;
2554 }
2555
get_window_location(Arg * args,int n,POINT * pt,SIZE * sz)2556 static void get_window_location(Arg *args, int n, POINT *pt, SIZE *sz)
2557 {
2558 int i;
2559 for (i=0; i<n; i++)
2560 switch (args[i].type) {
2561 case XtNx: if (pt) pt->x = (int)args[i].data; break;
2562 case XtNy: if (pt) pt->y = (int)args[i].data; break;
2563 case XtNwidth: if (sz) sz->cx = (int)args[i].data; break;
2564 case XtNheight: if (sz) sz->cy = (int)args[i].data; break;
2565 }
2566 }
2567
WinCreateWidget(const char * name,int cls,Widget parent,Arg * args,int n,int show)2568 Widget WinCreateWidget(const char *name, int cls, Widget parent, Arg *args, int n, int show)
2569 {
2570 int i;
2571 Widget win;
2572
2573 switch (cls) {
2574 case XwcascadeWidgetClass:
2575 {
2576 MENUITEMINFO mi_info;
2577 MenuItem item;
2578 Menu popup = create_win_menu(CreatePopupMenu());
2579 Arg *a;
2580 int pos = -1;
2581
2582 ZeroMemory(&mi_info, sizeof(mi_info));
2583 mi_info.cbSize = sizeof(mi_info);
2584 mi_info.fMask = MIIM_SUBMENU | MIIM_STRING;
2585 mi_info.hSubMenu = popup->handle;
2586 mi_info.dwTypeData = (char*)name;
2587 if (IS_MENUITEM(parent))
2588 parent = (Widget)TOMENUITEM(parent)->popup;
2589 if ((a = look_arg(args, XtNattachTo, n)) != NULL) {
2590 Widget after = WinNameToWindow(parent, (char*)a->data);
2591 if (after != NULL)
2592 pos = TOMENUITEM(after)->position + 1;
2593 }
2594 item = insert_win_menuitem((Menu)parent, &mi_info, NULL, pos);
2595 item->name = strdup(name);
2596 DrawMenuBar(topwin);
2597 return (Widget)item;
2598 }
2599 case XwmenubuttonWidgetClass:
2600 {
2601 MENUITEMINFO mi_info;
2602 Arg *a;
2603 MenuItem item;
2604 int pos = -1;
2605
2606 ZeroMemory(&mi_info, sizeof(mi_info));
2607 mi_info.cbSize = sizeof(mi_info);
2608 if ((a=look_arg(args, XtNrectColor, n)) != NULL) {
2609 HBITMAP hBitmap = create_color_icon((int)a->data, MENUICON_WIDTH, MENUICON_HEIGHT);
2610 mi_info.fMask = MIIM_BITMAP | MIIM_STRING /*| MIIM_FTYPE*/;
2611 /*mi_info.fType = MFT_OWNERDRAW*/;
2612 mi_info.hbmpItem = hBitmap;
2613 mi_info.dwTypeData = color_string((int)a->data);
2614 mi_info.dwItemData = (int)a->data;
2615 } else {
2616 mi_info.fMask = MIIM_STRING;
2617 mi_info.dwTypeData = (char*)name;
2618 }
2619 if (IS_MENUITEM(parent))
2620 parent = (Widget)TOMENUITEM(parent)->popup;
2621 if ((a = look_arg(args, XtNattachTo, n)) != NULL) {
2622 Widget after = WinNameToWindow(parent, (char*)a->data);
2623 if (after != NULL)
2624 pos = TOMENUITEM(after)->position + 1;
2625 }
2626 item = insert_win_menuitem((Menu)parent, &mi_info, NULL, pos);
2627 item->name = strdup(name);
2628 DrawMenuBar(topwin);
2629 return (Widget)item;
2630 }
2631 break;
2632 /*
2633 case XwstaticTextWidgetClass:
2634 {
2635 POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
2636
2637 get_window_location(args, n, &pt, NULL);
2638 win = create_widget(CreateWindow("STATIC", "", WS_CHILD|WS_VISIBLE, pt.x, pt.y,
2639 CW_USEDEFAULT, CW_USEDEFAULT, parent->handle, NULL, NULL, NULL), (char*)name);
2640 win->wndproc = (WNDPROC)SetWindowLong(win->handle, GWL_WNDPROC, (LONG)XcStaticProc);
2641 WinSetValues(win, args, n);
2642 }
2643 break;
2644 case XwtextEditWidgetClass:
2645 {
2646 POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
2647 SIZE sz = {CW_USEDEFAULT, CW_USEDEFAULT};
2648
2649 get_window_location(args, n, &pt, &sz);
2650 win = create_widget(CreateWindow("EDIT", "", WS_BORDER|WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL|WS_TABSTOP, pt.x, pt.y, sz.cx, sz.cy,
2651 parent->handle, NULL, NULL, NULL), (char*)name);
2652 //win->wndproc = (WNDPROC)SetWindowLong(win->handle, GWL_WNDPROC, (LONG)XcEditProc);
2653 }
2654 break;
2655 case XwpushButtonWidgetClass:
2656 case XwmenuButtonWidgetClass:
2657 {
2658 POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
2659
2660 get_window_location(args, n, &pt, NULL);
2661 win = create_widget(CreateWindow("BUTTON", name, BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE, pt.x, pt.y,
2662 CW_USEDEFAULT, CW_USEDEFAULT, parent->handle, NULL, NULL, NULL), (char*)name);
2663 win->wndproc = (WNDPROC)SetWindowLong(win->handle, GWL_WNDPROC, (LONG)XcButtonProc);
2664 WinSetValues(win, args, n);
2665 }
2666 break;
2667 case XwtoggleWidgetClass:
2668 {
2669 POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
2670
2671 get_window_location(args, n, &pt, NULL);
2672 win = create_widget(CreateWindow("BUTTON", name, BS_CHECKBOX|WS_CHILD|WS_VISIBLE, pt.x, pt.y,
2673 CW_USEDEFAULT, CW_USEDEFAULT, parent->handle, NULL, NULL, NULL), (char*)name);
2674 win->wndproc = (WNDPROC)SetWindowLong(win->handle, GWL_WNDPROC, (LONG)XcToggleProc);
2675 WinSetValues(win, args, n);
2676 }
2677 break;
2678 case XwbulletinWidgetClass:
2679 win = parent;
2680 break;
2681 */
2682 default:
2683 W32DEBUG(("Should create widget: %02x, %s\n", cls, name));
2684 win = NULL;
2685 break;
2686 }
2687
2688 if (show)
2689 ShowWindow(win->handle, SW_SHOW);
2690 else
2691 ShowWindow(win->handle, SW_HIDE);
2692
2693 return win;
2694 }
2695
WinCreatePopup(const char * name,Arg * args,int n)2696 Widget WinCreatePopup(const char *name, Arg *args, int n)
2697 {
2698 HWND hwnd;
2699
2700 hwnd = CreateWindow("XcPopup", name, WS_TILEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
2701 300, 200, NULL, NULL, NULL, NULL);
2702 return create_widget(hwnd, (char*)name);
2703 }
2704
WinPopup(Widget popup)2705 void WinPopup(Widget popup)
2706 {
2707 ShowWindow(popup->handle, SW_SHOWNORMAL);
2708 }
2709
WinGetText(Widget win)2710 char* WinGetText(Widget win)
2711 {
2712 static char buffer[1024];
2713
2714 GetWindowText(win->handle, buffer, 1024);
2715 return buffer;
2716 }
2717
WinClearText(Widget win)2718 void WinClearText(Widget win)
2719 {
2720 SetWindowText(win->handle, "");
2721 }
2722
WinNamedColor(const char * cname)2723 int WinNamedColor(const char *cname)
2724 {
2725 int i;
2726
2727 for (i=0; X11Colors[i].name; i++) {
2728 if (_stricmp(X11Colors[i].name, cname) == 0)
2729 return RGB(X11Colors[i].red, X11Colors[i].green, X11Colors[i].blue);
2730 }
2731 W32DEBUG(("Unknown color: %s\n", cname));
2732 return -1;
2733 }
2734
WinLookupColor(const char * cname,XColor * color)2735 int WinLookupColor(const char *cname, XColor *color)
2736 {
2737 int cval = WinNamedColor(cname);
2738 if (cval == -1)
2739 return 0;
2740 else {
2741 color->pixel = cval;
2742 WinQueryColors(color, 1);
2743 return 1;
2744 }
2745 }
2746
WinColorName(int c)2747 char *WinColorName(int c)
2748 {
2749 int red = GetRValue(c), green = GetGValue(c), blue = GetBValue(c);
2750 int i;
2751
2752 for (i=0; X11Colors[i].name; i++)
2753 if (red == X11Colors[i].red && green == X11Colors[i].green && blue == X11Colors[i].blue)
2754 return X11Colors[i].name;
2755 return NULL;
2756 }
2757
WinWindow(Widget w)2758 HWND WinWindow(Widget w)
2759 {
2760 return (w ? w->handle : NULL);
2761 }
2762
WinManageChild(Widget w)2763 void WinManageChild(Widget w)
2764 {
2765 if (w != NULL)
2766 ShowWindow(w->handle, SW_SHOW);
2767 }
2768
WinUnmanageChild(Widget w)2769 void WinUnmanageChild(Widget w)
2770 {
2771 if (w != NULL)
2772 ShowWindow(w->handle, SW_HIDE);
2773 }
2774
WinDebug(char * c)2775 void WinDebug(char *c)
2776 {
2777 W32DEBUG(("%s", c));
2778 }
2779
WinLookupString(XKeyEvent * event,KeySym * key)2780 void WinLookupString(XKeyEvent *event, KeySym *key)
2781 {
2782 XKeyEvent *kevent = (XKeyEvent*)event;
2783 int vk = kevent->keycode & 0xff;
2784
2785 if (vk == 0)
2786 *key = 0;
2787 else {
2788 W32DEBUG(("Translating key event: %d\n", vk));
2789 *key = kevent->keycode;
2790 }
2791 }
2792
WinPostPopup(Widget _menu,Widget _button,int dx,int dy)2793 void WinPostPopup(Widget _menu, Widget _button, int dx, int dy)
2794 {
2795 Menu menu = (Menu)_menu;
2796 ToolItem button = (ToolItem)_button;
2797 RECT bRect = { 0, 0, 0, 0 };
2798 POINT pt;
2799
2800 SendMessage(button->toolbar->handle, TB_GETRECT, button->ID, (LPARAM)&bRect);
2801 pt.x = bRect.left;
2802 pt.y = bRect.bottom;
2803 ClientToScreen(button->toolbar->handle, &pt);
2804 SendMessage(button->toolbar->handle, TB_CHECKBUTTON, button->ID, MAKELONG(TRUE, 0));
2805 TrackPopupMenu(menu->handle, TPM_LEFTALIGN|TPM_TOPALIGN, pt.x, pt.y, 0, top->handle, NULL);
2806 SendMessage(button->toolbar->handle, TB_CHECKBUTTON, button->ID, MAKELONG(FALSE, 0));
2807 }
2808
overdrawpixmap(Widget button)2809 void overdrawpixmap(Widget button)
2810 {
2811 MenuItem mitem = (MenuItem)button;
2812 ToolItem titem = NULL;
2813 int idx;
2814
2815 if (button == NULL) return;
2816 idx = mitem->toolbar_idx;
2817
2818 if (mitem->parentMenu == ((MenuItem)ColorInheritColorButton)->parentMenu)
2819 titem = (ToolItem)ColorsToolButton;
2820 else if (mitem->parentMenu == ((MenuItem)FillBlackButton)->parentMenu)
2821 titem = (ToolItem)FillsToolButton;
2822 else
2823 return;
2824
2825 if (idx == 0) {
2826 if (mitem == (MenuItem)ColorInheritColorButton) {
2827 idx = ((ToolItem)ColorsToolButton)->ID-((ToolItem)PanToolButton)->ID;
2828 } else if (mitem == (MenuItem)FillWhiteButton) {
2829 idx = ((ToolItem)FillsToolButton)->ID-((ToolItem)PanToolButton)->ID;
2830 } else {
2831 HBITMAP hBitmap = NULL;
2832 TBADDBITMAP tb;
2833 if (titem == (ToolItem)ColorsToolButton)
2834 hBitmap = create_color_icon(mitem->menudata, 20, 20);
2835 else {
2836 if (mitem->menudata == (OPAQUE | FILLED | FILLSOLID))
2837 hBitmap = create_color_icon(RGB(0, 0, 0), 20, 20);
2838 else if (mitem != (MenuItem)FillOpaqueButton && mitem != (MenuItem)FillTransparentButton)
2839 hBitmap = create_stipple_icon((mitem->menudata & FILLSOLID) >> 5, 20, 20);
2840 }
2841 if (hBitmap != NULL) {
2842 tb.hInst = NULL;
2843 tb.nID = (INT_PTR)hBitmap;
2844 idx = mitem->toolbar_idx = SendMessage(titem->toolbar->handle, TB_ADDBITMAP, 1, (LPARAM)&tb);
2845 }
2846 }
2847 }
2848
2849 W32DEBUG(("%s: %d\n", titem->name, idx));
2850 if (idx > 0) {
2851 SendMessage(titem->toolbar->handle, TB_CHANGEBITMAP, titem->ID, MAKELPARAM(idx, 0));
2852 }
2853 }
2854
starthelp(xcWidget button,caddr_t clientdata,caddr_t calldata)2855 void starthelp(xcWidget button, caddr_t clientdata, caddr_t calldata)
2856 {
2857 DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_HELPDLG), areawin->window, HelpDlgProc, (LPARAM)NULL);
2858 }
2859
2860 /*
2861 static void get_text_size(HWND hwnd, HFONT hfont, SIZE *sz)
2862 {
2863 HDC hdc = GetDC(hwnd);
2864 char str[64];
2865 int n;
2866
2867 SelectObject(hdc, hfont);
2868 n = GetWindowText(hwnd, str, 64);
2869 GetTextExtentPoint32(hdc, str, n, sz);
2870 ReleaseDC(hwnd, hdc);
2871 }
2872
2873 LRESULT CALLBACK XcStaticProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2874 {
2875 Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
2876
2877 switch (msg) {
2878 case WM_SETFONT:
2879 {
2880 SIZE sz;
2881 get_text_size(hwnd, (HFONT)wParam, &sz);
2882 SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx, sz.cy, SWP_NOMOVE);
2883 }
2884 break;
2885 }
2886
2887 return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2888 }
2889
2890 LRESULT CALLBACK XcEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2891 {
2892 Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
2893
2894 switch (msg) {
2895 case WM_KEYDOWN:
2896 if (wParam == VK_RETURN) {
2897 execute_callback(XtNexecute, w, NULL);
2898 return 0;
2899 }
2900 break;
2901 }
2902
2903 return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2904 }
2905
2906 LRESULT CALLBACK XcButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2907 {
2908 Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
2909
2910 switch (msg) {
2911 case WM_SETFONT:
2912 {
2913 SIZE sz;
2914 get_text_size(hwnd, (HFONT)wParam, &sz);
2915 printf("%d %d\n", sz.cx, sz.cy);
2916 SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx+20, sz.cy+10, SWP_NOMOVE);
2917 }
2918 break;
2919 case WM_SETTEXT:
2920 {
2921 LRESULT result = CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2922 SIZE sz;
2923 get_text_size(hwnd, (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0), &sz);
2924 SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx+20, sz.cy+10, SWP_NOMOVE);
2925 return result;
2926 }
2927 case WM_LBUTTONDOWN:
2928 execute_callback(XtNselect, w, NULL);
2929 break;
2930 }
2931
2932 return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2933 }
2934
2935 LRESULT CALLBACK XcToggleProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2936 {
2937 Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
2938
2939 switch (msg) {
2940 case WM_SETFONT:
2941 {
2942 SIZE sz;
2943 get_text_size(hwnd, (HFONT)wParam, &sz);
2944 SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx+20, sz.cy+10, SWP_NOMOVE);
2945 }
2946 break;
2947 case WM_LBUTTONUP:
2948 {
2949 LRESULT result = CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2950 if (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED)
2951 execute_callback(XtNselect, w, NULL);
2952 else
2953 execute_callback(XtNrelease, w, NULL);
2954 }
2955 break;
2956 }
2957
2958 return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2959 }
2960
2961 LRESULT CALLBACK XcPopupProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2962 {
2963 return DefDlgProc(hwnd, msg, wParam, lParam);
2964 }
2965 */
2966
change_char(char * str,char cfrom,char cto)2967 static void change_char(char *str, char cfrom, char cto)
2968 {
2969 char *c = str;
2970 for (; *c; c++)
2971 if (*c == cfrom)
2972 *c = cto;
2973 }
2974
OutputDlgEditProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)2975 LRESULT CALLBACK OutputDlgEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2976 {
2977 Widget win = get_widget (hwnd);
2978
2979 switch (msg) {
2980 case WM_GETDLGCODE:
2981 if (lParam) {
2982 MSG *message = (MSG*)lParam;
2983 if (message->message == WM_KEYDOWN && message->wParam == VK_RETURN)
2984 return DLGC_WANTMESSAGE;
2985 }
2986 break;
2987 case WM_KEYDOWN:
2988 switch (wParam) {
2989 case VK_RETURN:
2990 execute_callback(XtNexecute, win, NULL);
2991 break;
2992 }
2993 break;
2994 }
2995 return CallWindowProc(win->wndproc, hwnd, msg, wParam, lParam);
2996 }
2997
OutputDlgProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)2998 LRESULT CALLBACK OutputDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2999 {
3000 Widget popup = get_widget(hwnd);
3001
3002 switch (msg) {
3003 case WM_INITDIALOG:
3004 {
3005 RECT r, pr;
3006 Widget win;
3007 Pagedata *curpage;
3008 Widget *entertext;
3009 int i;
3010 void (*function[MAXPROPS])() = { setfilename, setpagelabel, setfloat, setscalex, setscaley, setorient, setpmode };
3011 void (*update[MAXPROPS])() = { updatename, NULL, updatetext, updatetext, updatetext, updatetext, NULL };
3012 char statics[MAXPROPS][50], edit[MAXPROPS][75], request[150];
3013 void *data[MAXPROPS];
3014 struct {int edit; int apply; int label;} ID[MAXPROPS] = {
3015 { IDC_FILENAME, IDC_APPLY1, IDC_STATIC1 },
3016 { IDC_PAGELABEL, IDC_APPLY2, IDC_STATIC2 },
3017 { IDC_SCALE, IDC_APPLY3, IDC_STATIC3 },
3018 { IDC_WIDTH, IDC_APPLY4, IDC_STATIC4 },
3019 { IDC_HEIGHT, IDC_APPLY5, IDC_STATIC5 },
3020 { IDC_ORIENTATION, -1, IDC_STATIC6 },
3021 { IDC_MODE, -1, IDC_STATIC7 } };
3022 struct stat statbuf;
3023
3024 GetWindowRect(GetParent(hwnd), &pr);
3025 GetWindowRect(hwnd, &r);
3026 SetWindowPos(hwnd, HWND_TOP, pr.left+((pr.right-pr.left)-(r.right-r.left))/2,
3027 pr.top+((pr.bottom-pr.top)-(r.bottom-r.top))/2, 0, 0, SWP_NOSIZE);
3028
3029 SendDlgItemMessage(hwnd, IDC_ORIENTATION, CB_ADDSTRING, 0, (LPARAM)"Landscape");
3030 SendDlgItemMessage(hwnd, IDC_ORIENTATION, CB_ADDSTRING, 0, (LPARAM)"Portrait");
3031 SendDlgItemMessage(hwnd, IDC_MODE, CB_ADDSTRING, 0, (LPARAM)"Embedded (EPS)");
3032 SendDlgItemMessage(hwnd, IDC_MODE, CB_ADDSTRING, 0, (LPARAM)"Full page");
3033
3034 curpage = xobjs.pagelist[areawin->page];
3035 entertext = (Widget*)malloc(sizeof(Widget)*MAXPROPS);
3036 memset(okstruct, 0, sizeof(propstruct)*MAXPROPS);
3037
3038 sprintf(edit[0], "%s", curpage->filename);
3039 sprintf(edit[1], "%s", topobject->name);
3040 calcbbox(areawin->topinstance);
3041 if (curpage->pmode & 2) autoscale(areawin->page);
3042 writescalevalues(edit[2], edit[3], edit[4]);
3043 sprintf(edit[5], "%s", (curpage->orient == 0) ? "Portrait" : "Landscape");
3044 sprintf(edit[6], "%s", (curpage->pmode & 1) ? "Full page" : "Embedded (EPS)");
3045 data[0] = &(curpage->filename);
3046 data[1] = topobject->name;
3047 data[2] = data[3] = data[4] = &(curpage->outscale);
3048 data[5] = &(curpage->orient);
3049 data[6] = &(curpage->pmode);
3050
3051 popup = create_widget(hwnd, "outputpopup");
3052 popup->bufhdc = (HDC)entertext;
3053 create_widget(GetDlgItem(hwnd, IDOK), "Write File");
3054 create_widget(GetDlgItem(hwnd, IDCANCEL), "Close");
3055
3056 sprintf(request, "PostScript output properties (Page %d):", areawin->page + 1);
3057 sprintf(statics[0], "Filename:");
3058 sprintf(statics[1], "Page label:");
3059 sprintf(statics[2], "Scale:");
3060 if (curpage->coordstyle == CM) {
3061 sprintf(statics[3], "X Size (cm):");
3062 sprintf(statics[4], "Y Size (cm):");
3063 } else {
3064 sprintf(statics[3], "X Size (in):");
3065 sprintf(statics[4], "Y Size (in):");
3066 }
3067 sprintf(statics[5], "Orientation:");
3068 sprintf(statics[6], "Mode:");
3069 SetDlgItemText(hwnd, IDC_PSINFO, request);
3070
3071 strcpy(request, edit[0]);
3072 if (strstr(request, ".") == NULL)
3073 strcat(request, ".ps");
3074 if (stat(request, &statbuf) == 0) {
3075 SetWindowText(GetDlgItem(hwnd, IDOK), "Overwrite File");
3076 Wprintf(" Warning: File exists");
3077 } else {
3078 if (errno == ENOTDIR)
3079 Wprintf("Error: Incorrect pathname");
3080 else if (errno == EACCES)
3081 Wprintf("Error: Path not readable");
3082 else
3083 Wprintf(" ");
3084 }
3085
3086 for (i=0; i<MAXPROPS; i++) {
3087 SetDlgItemText(hwnd, ID[i].label, statics[i]);
3088 if (i<5) {
3089 okstruct[i].textw = entertext[i] = create_widget(GetDlgItem(hwnd, ID[i].edit), "Edit");
3090 okstruct[i].buttonw = create_widget(GetDlgItem(hwnd, ID[i].apply), "Apply");
3091 okstruct[i].setvalue = function[i];
3092 okstruct[i].dataptr = data[i];
3093 SetWindowText(okstruct[i].textw->handle, edit[i]);
3094
3095 WinAddCallback(okstruct[i].buttonw, XtNselect, getproptext, &okstruct[i]);
3096 WinAddCallback(okstruct[i].textw, XtNexecute, getproptext, &okstruct[i]);
3097 if (update[i] != NULL) {
3098 WinAddCallback(okstruct[i].buttonw, XtNselect, update[i], entertext);
3099 WinAddCallback(okstruct[i].textw, XtNexecute, update[i], entertext);
3100 }
3101
3102 okstruct[i].textw->wndproc = (WNDPROC)SetWindowLong(okstruct[i].textw->handle,
3103 GWL_WNDPROC, (LONG)OutputDlgEditProc);
3104 } else {
3105 entertext[i] = create_widget(GetDlgItem(hwnd, ID[i].edit), "Toggle");
3106 SendMessage(entertext[i]->handle, CB_SELECTSTRING, -1, (LPARAM)edit[i]);
3107 WinAddCallback(entertext[i], XtNselect, function[i], data[i]);
3108 if (update[i] != NULL)
3109 WinAddCallback(entertext[i], XtNselect, update[i], entertext);
3110 }
3111 }
3112
3113 sprintf(request, "%d Pages", pagelinks(areawin->page));
3114 win = create_widget(GetDlgItem(hwnd, IDC_PAGENUM), "LToggle");
3115 SetWindowText(win->handle, request);
3116 CheckDlgButton(hwnd, IDC_PAGENUM, BST_CHECKED);
3117 WinAddCallback(win, XtNrelease, linkset, &okstruct[0]);
3118
3119 win = create_widget(GetDlgItem(hwnd, IDC_AUTOFIT), "Auto-fit");
3120 SendMessage(win->handle, BM_SETCHECK, (curpage->pmode & 2 ? BST_CHECKED : BST_UNCHECKED), 0);
3121 WinAddCallback(win, XtNselect, autoset, entertext);
3122 WinAddCallback(win, XtNrelease, autostop, NULL);
3123
3124 if (curpage->coordstyle == CM) {
3125 sprintf(request, "%3.2f x %3.2f cm",
3126 (float)curpage->pagesize.x / IN_CM_CONVERT,
3127 (float)curpage->pagesize.y / IN_CM_CONVERT);
3128 } else {
3129 sprintf(request, "%3.2f x %3.2f in",
3130 (float)curpage->pagesize.x / 72.0,
3131 (float)curpage->pagesize.y / 72.0);
3132 }
3133 fpokstruct.textw = create_widget(GetDlgItem(hwnd, IDC_FPEDIT), "fpedit");
3134 SetWindowText(fpokstruct.textw->handle, request);
3135 fpokstruct.buttonw = create_widget(GetDlgItem(hwnd, IDC_APPLY6), "fpokay");
3136 fpokstruct.setvalue = setpagesize;
3137 fpokstruct.dataptr = &(curpage->pagesize);
3138 WinAddCallback(fpokstruct.buttonw, XtNselect, getproptext, &fpokstruct);
3139 WinAddCallback(fpokstruct.buttonw, XtNselect, updatetext, entertext);
3140 WinAddCallback(fpokstruct.textw, XtNexecute, getproptext, &fpokstruct);
3141 WinAddCallback(fpokstruct.textw, XtNexecute, updatetext, entertext);
3142
3143 WinAddCallback(get_widget(GetDlgItem(hwnd, IDOK)), XtNselect, setfile, entertext[0]);
3144
3145 if (curpage->pmode > 0) {
3146 XtManageChild(get_widget(GetDlgItem(hwnd, IDC_AUTOFIT)));
3147 XtManageChild(fpokstruct.textw);
3148 XtManageChild(fpokstruct.buttonw);
3149 }
3150
3151 if (pagelinks(areawin->page) > 1)
3152 XtManageChild(get_widget(GetDlgItem(hwnd, IDC_PAGENUM)));
3153
3154 SetFocus(entertext[0]->handle);
3155 }
3156 return FALSE;
3157 case WM_DESTROY:
3158 if (popup->bufhdc)
3159 free((Widget*)popup->bufhdc);
3160 destroy_widget(hwnd);
3161 {
3162 int ID[] = { IDOK, IDCANCEL, IDC_APPLY1, IDC_FILENAME, IDC_APPLY2, IDC_PAGELABEL,
3163 IDC_APPLY3, IDC_SCALE, IDC_APPLY4, IDC_WIDTH, IDC_APPLY5, IDC_HEIGHT,
3164 IDC_PAGENUM, IDC_AUTOFIT, IDC_FPEDIT, -1 };
3165 int i;
3166
3167 for (i=0; ID[i]!=-1; i++)
3168 destroy_widget(GetDlgItem(hwnd, ID[i]));
3169 }
3170 return FALSE;
3171 case WM_COMMAND:
3172 switch (LOWORD(wParam)) {
3173 case IDOK:
3174 if (HIWORD(wParam) == BN_CLICKED) {
3175 execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
3176 EndDialog(hwnd, 1);
3177 }
3178 break;
3179 case IDCANCEL:
3180 if (HIWORD(wParam) == BN_CLICKED)
3181 EndDialog(hwnd, 0);
3182 break;
3183 case IDC_FILEOPEN:
3184 {
3185 OPENFILENAME ofn;
3186 int len;
3187
3188 ZeroMemory(&ofn, sizeof(ofn));
3189 ofn.lStructSize = sizeof(ofn);
3190 ofn.hwndOwner = hwnd;
3191 ofn.lpstrFile = _STR2;
3192 ofn.nMaxFile = 250;
3193 ofn.lpstrFilter = "XCircuit Files (*.ps;*.eps)\000*.ps;*.eps\000All Files (*.*)\000*.*\000\000\000";
3194 GetDlgItemText(hwnd, IDC_FILENAME, _STR2, 250);
3195 change_char(_STR2, '/', '\\');
3196 if (strstr(_STR2, ".") == NULL)
3197 strncat(_STR2, ".ps", 250);
3198 if (GetSaveFileName(&ofn)) {
3199 change_char(_STR2, '\\', '/');
3200 len = strlen(_STR2);
3201 if (len >= 3 && strncmp(_STR2+len-3, ".ps", 3) == 0)
3202 _STR2[len-3] = '\0';
3203 SetDlgItemText(hwnd, IDC_FILENAME, _STR2);
3204 SendDlgItemMessage(hwnd, IDC_APPLY1, BM_CLICK, 0, 0);
3205 }
3206 }
3207 break;
3208 case IDC_APPLY1:
3209 case IDC_APPLY2:
3210 case IDC_APPLY3:
3211 case IDC_APPLY4:
3212 case IDC_APPLY5:
3213 case IDC_APPLY6:
3214 if (HIWORD(wParam) == BN_CLICKED)
3215 execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
3216 break;
3217 case IDC_PAGENUM:
3218 case IDC_AUTOFIT:
3219 if (HIWORD(wParam) == BN_CLICKED) {
3220 if (SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED)
3221 execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
3222 else
3223 execute_callback(XtNrelease, get_widget((HWND)lParam), NULL);
3224 }
3225 break;
3226 case IDC_MODE:
3227 if (HIWORD(wParam) == CBN_SELENDOK)
3228 execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
3229 break;
3230 }
3231 break;
3232 default:
3233 return FALSE;
3234 }
3235
3236 return TRUE;
3237 }
3238
3239 extern int main(int argc, char **argv);
3240
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR cmdLine,int cmdShow)3241 int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
3242 {
3243 LPWSTR *wargv;
3244 char **argv;
3245 int argc, i;
3246
3247 wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
3248 argv = (char**)malloc(sizeof(char*)*argc);
3249 for (i=0; i<argc; i++) {
3250 int len = wcslen(wargv[i]);
3251 argv[i] = (char*)malloc(sizeof(char)*2*(len+1));
3252 wcstombs(argv[i], wargv[i], 2*(len+1));
3253 if (argv[i][0] != '-')
3254 change_char(argv[i], '\\', '/');
3255 }
3256
3257 LocalFree(wargv);
3258 return main(argc, argv);
3259 }
3260
WinBuiltinsDir()3261 const char* WinBuiltinsDir()
3262 {
3263 static char buffer[MAX_PATH] = {0};
3264
3265 if (buffer[0] == 0) {
3266 char *c;
3267 GetModuleFileName(NULL, buffer, MAX_PATH);
3268 c = strrchr(buffer, '\\');
3269 if (c == NULL)
3270 c = strrchr(buffer, '/');
3271 if (c != NULL) {
3272 *c = '\0';
3273 change_char(buffer, '\\', '/');
3274 }
3275 }
3276 return buffer;
3277 }
3278
find_menu_from_name(Menu menu,const char * name)3279 static Widget find_menu_from_name(Menu menu, const char *name)
3280 {
3281 int count, i;
3282 MENUITEMINFO mi_info;
3283 MenuItem item;
3284 Widget found = NULL;
3285
3286 count = GetMenuItemCount((HMENU)menu->handle);
3287 ZeroMemory(&mi_info, sizeof(mi_info));
3288 mi_info.cbSize = sizeof(mi_info);
3289 mi_info.fMask = MIIM_DATA;
3290 for (i=0; found == NULL && i<count; i++) {
3291 mi_info.dwItemData = (LONG)NULL;
3292 if (GetMenuItemInfo((HMENU)menu->handle, i, MF_BYPOSITION, &mi_info) &&
3293 (item = (MenuItem)mi_info.dwItemData) != NULL) {
3294 if (item->name && strcmp(item->name, name) == 0)
3295 found = (Widget)item;
3296 else if (item->popup != NULL)
3297 found = find_menu_from_name(item->popup, name);
3298 }
3299 }
3300 return found;
3301 }
3302
WinGetMenu(const char * name)3303 Widget WinGetMenu(const char *name)
3304 {
3305 MENUINFO minfo;
3306
3307 ZeroMemory(&minfo, sizeof(minfo));
3308 minfo.cbSize = sizeof(minfo);
3309 minfo.fMask = MIM_MENUDATA;
3310 if (GetMenuInfo(GetMenu(topwin), &minfo)) {
3311 Menu menu = (Menu)minfo.dwMenuData;
3312 if (name == NULL || *name == '\0')
3313 return (Widget)menu;
3314 else
3315 return find_menu_from_name(menu, name);
3316 }
3317 return NULL;
3318 }
3319
WinIsPopupMenu(Widget w)3320 int WinIsPopupMenu(Widget w)
3321 {
3322 if (IS_MENU(w) ||
3323 (IS_MENUITEM(w) && TOMENUITEM(w)->popup != NULL))
3324 return 1;
3325 return 0;
3326 }
3327
exec_script_command(void * button,void * data)3328 void exec_script_command(void *button, void *data)
3329 {
3330 #ifdef USE_WIN32_COM
3331 COM_execute(_STR2);
3332 #endif
3333 }
3334
docommand()3335 void docommand()
3336 {
3337 popupprompt(NULL, "Enter command to execute:", "", exec_script_command, NULL, NULL);
3338 }
3339
3340 #ifdef USE_WIN32_COM
3341
win32_comscript()3342 void win32_comscript()
3343 {
3344 COM_runscript(_STR2);
3345 }
3346
win32_comdotnet()3347 void win32_comdotnet()
3348 {
3349 COM_load_dotnet(_STR2);
3350 }
3351
3352 #endif
3353
win32_new_window(Widget w,void * clientData,void * callData)3354 void win32_new_window(Widget w, void *clientData, void *callData)
3355 {
3356 XCWindowData *newwin = GUI_init(0, NULL);
3357
3358 newwin->page = areawin->page;
3359 newwin->vscale = areawin->vscale;
3360 newwin->pcorner = areawin->pcorner;
3361 newwin->topinstance = areawin->topinstance;
3362
3363 areawin = newwin;
3364 ShowWindow(top->handle, SW_SHOW);
3365 }
3366