Update at Wed Oct 24 21:17:23 EDT 2018 by tim
[xcircuit.git] / xcwin32.c
blob735c0ce9eb96aaf69bcb03dbc2985f7abe8ceccc
1 #define WINVER 0x0500
2 #define _WIN32_WINNT 0x0500
4 #include <stdio.h>
5 #include <sys/stat.h>
6 #include <errno.h>
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"
16 #include "xcwin32-colors.h"
18 #ifndef MK_XBUTTON1
19 #define MK_XBUTTON1 32
20 #define MK_XBUTTON2 64
21 #endif
23 #if 0
24 #define W32DEBUG(x) printf##x
25 #else
26 #define W32DEBUG(x)
27 #endif
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"
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;
60 static HWND corner = NULL, statusBar = NULL;
61 static Widget toolBar = NULL;
62 static int statusBarWidth[2] = { 100, -1 };
64 HWND topwin = NULL;
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);
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();
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
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)
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)
98 #define STATUSBAR_ID 10000
99 #define TOOLBAR_ID 10001
101 typedef struct __WinCallback {
102 int action;
103 void(*proc)();
104 void* data;
105 struct __WinCallback *next;
106 } WinCallback;
107 typedef WinCallback WinEventHandler;
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;
120 #define HAS_HANDLER(win,themask) (win->handler_mask & themask)
121 #define WM_BITBLT (WM_USER+1)
123 struct __WinMenu {
124 int type;
125 HMENU handle;
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;
140 struct __WinStatusItem {
141 int type;
142 HWND handle;
143 int position;
146 struct __WinToolItem {
147 int type;
148 struct __WinWidget *toolbar;
149 int ID;
150 char *name;
151 WinCallback *callbacks;
154 typedef struct __WinMenu* Menu;
155 typedef struct __WinMenuItem* MenuItem;
156 typedef struct __WinStatusItem* StatusItem;
157 typedef struct __WinToolItem* ToolItem;
159 void execute_callback(int action, Widget w, void *calldata)
161 WinCallback *cb;
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;
176 while (cb != NULL) {
177 if (cb->action == action) {
178 (*cb->proc)(w, cb->data, calldata);
180 cb = cb->next;
184 void execute_handler(int mask, Widget w, void *calldata)
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;
196 void update_event_mask(Widget win)
198 WinEventHandler *h = win->handlers;
199 win->handler_mask = 0;
200 for (; h!= NULL; h=h->next)
201 win->handler_mask |= h->action;
204 Widget get_widget(HWND win)
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;
213 return (Widget)GetWindowLong(win, GWL_USERDATA);
216 static void get_value(Widget w, Arg *a)
218 RECT rect;
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];
230 } else {
231 if (GetClientRect(w->handle, &rect))
232 *(int*)(a->data) = rect.right - rect.left;
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;
245 goto GETDEFAULT;
246 GETDEFAULT:
247 default:
248 W32DEBUG(("Unsupported get value: %d\n", a->type));
249 break;
253 static void set_value(Widget w, Arg *a)
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;
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;
277 break;
278 case XtNlabel:
279 switch (w->type) {
280 case WIN_MENUITEM:
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;
290 case WIN_WIDGET:
291 SetWindowText(w->handle, (char*)a->data);
292 break;
293 default:
294 goto SETDEFAULT;
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;
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;
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));
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));
326 break;
327 default:
328 goto SETDEFAULT;
330 break;
331 SETDEFAULT:
332 default:
333 W32DEBUG(("Unsupported set value: %d\n", a->type));
334 /*exit(-1);*/
335 break;
339 void WinGetValues(Widget w, Arg *args, int n)
341 int i;
343 if (w != NULL)
344 for (i=0; i<n; i++)
345 get_value(w, args+i);
348 void WinSetValues(Widget w, Arg *args, int n)
350 int i;
352 if (w != NULL)
353 for (i=0; i<n; i++)
354 set_value(w, args+i);
357 HBITMAP WinCreatePixmap(HWND w, int width, int height)
359 HDC hdc;
360 HBITMAP hBitmap;
362 hdc = GetDC(w);
363 hBitmap = CreateCompatibleBitmap(hdc, width, height);
364 ReleaseDC(w, hdc);
365 return hBitmap;
368 Widget WinParent(Widget child)
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;
379 return NULL;
382 void WinFreePixmap(Pixmap pix)
384 DeleteObject(pix);
387 void WinDestroyImage(XImage *img)
389 if (img->handle != NULL)
390 DeleteObject(img->handle);
391 free(img->data);
392 free(img);
395 XImage* WinCreateImage(int width, int height)
397 HWND h = GetDesktopWindow();
398 HDC hdc = GetDC(h);
399 XImage *img = (XImage*)malloc(sizeof(XImage));
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);
408 return img;
411 int WinGetPixel(XImage *img, int x, int y)
413 unsigned char *src;
414 if (img->bits_per_pixel != 32) {
415 W32DEBUG(("WinGetPixel only supported on 32bpp\n"));
416 return -1;
418 src = img->data + (y * img->bytes_per_line) + (x * img->bits_per_pixel) / 8;
419 return RGB(src[0], src[1], src[2]);
422 void WinPutPixel(XImage *img, int x, int y, Pixel pix)
424 unsigned char *src;
425 if (img->bits_per_pixel != 32) {
426 W32DEBUG(("WinPutPixel only supported on 32bpp\n"));
427 return;
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);
435 DIR* opendir(const char *name)
437 DIR *d = (DIR*)malloc(sizeof(DIR));
438 static char buffer[MAX_PATH];
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;
449 void closedir(DIR *d)
451 free(d);
454 struct direct* readdir(DIR *d)
456 if (!d->dirty)
458 if (!FindNextFile(d->hnd, &(d->fd)))
459 return NULL;
461 d->d.d_name = d->fd.cFileName;
462 d->dirty = 0;
463 return &(d->d);
466 int WinDesktopWidth(void)
468 RECT r;
469 GetWindowRect(GetDesktopWindow(), &r);
470 return r.right-r.left;
473 int WinDesktopHeight(void)
475 RECT r;
476 GetWindowRect(GetDesktopWindow(), &r);
477 return r.bottom-r.top;
480 void WinSetCursor(HWND win, HCURSOR cursor)
482 SetClassLong(win, GCL_HCURSOR, (LONG)cursor);
485 HDC cached_hdc = NULL;
486 HWND cached_win = NULL;
488 static HPEN create_pen(GC gc)
490 HPEN hPen = NULL;
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;
498 logBrush.lbStyle = BS_SOLID;
499 logBrush.lbColor = gc->foreground;
500 logBrush.lbHatch = 0;
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);
513 return hPen;
516 static HBRUSH create_brush(GC gc)
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);
525 static HDC get_hdc(HWND win, GC gc)
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;
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);
553 return hdc;
556 static release_hdc(HWND win, HDC hdc)
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);
567 else {
568 //DeleteDC(hdc);
572 void WinDrawLine(HWND win, GC gc, int x1, int y1, int x2, int y2)
574 HDC hdc = get_hdc(win, gc);
575 MoveToEx(hdc, x1, y1, NULL);
576 LineTo(hdc, x2, y2);
577 release_hdc(win, hdc);
580 void WinFillPolygon(HWND win, GC gc, XPoint* pathlist, int number)
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;
587 DeleteObject(SelectObject(hdc, CreatePen(PS_NULL, 0, 0)));
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);
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);
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;
611 Polygon(tmphdc, pts, number);
612 BitBlt(hdc, rect.left, rect.top, width, height, tmphdc, 0, 0, 0x00AC0744);
614 DeleteDC(tmphdc);
615 DeleteObject(tmpbmp);
616 DeleteObject(tmpbrush);
617 } else {
618 Polygon(hdc, pts, number);
621 release_hdc(win, hdc);
622 free(pts);
625 void WinDrawArc(HWND win, GC gc, int x, int y, int width, int height, int angle, int span)
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);
635 void WinClearArea(HWND win, int x, int y, int w, int h)
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);
647 void WinFillRectangle(HWND win, GC gc, int x, int y, int w, int h)
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);
659 void WinSetFunction(GC gc, int op)
661 gc->function = op;
664 void WinSetForeground(GC gc, int color)
666 gc->foreground = color;
669 void WinSetBackground(GC gc, int rgb)
671 gc->background = rgb;
674 void WinCopyArea(Pixmap pix, HWND win, GC gc, int x, int y, int width, int height, int offx, int offy)
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);
682 void WinDrawPoint(HWND win, GC gc, int x, int y)
684 HDC hdc = get_hdc(win, gc);
685 SetPixelV(hdc, x, y, gc->foreground);
686 release_hdc(win, hdc);
689 void WinSetLineAttributes(GC gc, int width, int style, int capstyle, int joinstyle)
691 gc->line_style = style;
692 gc->line_width = width;
693 gc->line_cap = capstyle;
694 gc->line_join = joinstyle;
697 void WinWarpPointer(HWND w, int x, int y)
699 POINT pt;
701 pt.x = x;
702 pt.y = y;
703 ClientToScreen(w, &pt);
704 SetCursorPos(pt.x, pt.y);
707 void WinDrawLines(HWND win, GC gc, XPoint* pathlist, int number)
709 LPPOINT pts = (LPPOINT)malloc(sizeof(POINT)*number);
710 HDC hdc = get_hdc(win, gc);
711 int i;
713 for (i=0; i<number; i++) {
714 pts[i].x = pathlist[i].x;
715 pts[i].y = pathlist[i].y;
717 Polyline(hdc, pts, number);
718 release_hdc(win, hdc);
719 free(pts);
722 void WinQueryPointer(HWND win, int *x, int *y)
724 POINT pt;
726 if (GetCursorPos(&pt)) {
727 ScreenToClient(win, &pt);
728 *x = pt.x;
729 *y = pt.y;
733 void WinDrawRectangle(HWND win, GC gc, int x, int y, int width, int height)
735 HDC hdc = get_hdc(win, gc);
736 Rectangle(hdc, x, y, x+width, y+height);
737 release_hdc(win, hdc);
740 GC WinCreateGC(HWND win, int mask, XGCValues *values)
742 GC gc = (GC)malloc(sizeof(struct __GC));
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;
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;
770 return gc;
773 void WinFreeGC(GC gc)
775 free(gc);
778 void WinSetDashes(GC gc, int offset, char *dash, int n)
780 if (gc->line_dash) {
781 free(gc->line_dash);
782 gc->line_dash = NULL;
783 gc->line_dash_len = 0;
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;
792 void WinSetFillStyle(GC gc, int style)
794 gc->fill_style = style;
797 void WinSetStipple(GC gc, Pixmap pattern)
799 gc->fill_stipple = pattern;
802 HCURSOR WinCreateStandardCursor(char *cur)
804 return LoadCursor(NULL, cur);
807 void WinDrawString(HWND win, GC gc, int x, int y, const char *str, int len)
809 HDC hdc = get_hdc(win, gc);
810 SIZE sz;
811 RECT r;
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);
821 SetTextAlign(hdc, TA_LEFT|TA_BASELINE);
822 TextOut(hdc, x, y, str, len);
823 release_hdc(win, hdc);
826 int WinTextWidth(XFontStruct *fn, char *s, int len)
828 HWND w = GetDesktopWindow();
829 HDC hdc = GetDC(w);
830 SIZE sz;
832 SelectObject(hdc, fn->fid);
833 GetTextExtentPoint32(hdc, s, len, &sz);
834 ReleaseDC(w, hdc);
836 return sz.cx;
839 void WinTextExtents(XFontStruct *fn, char *str, int len, int *width, int *height)
841 HWND w = GetDesktopWindow();
842 HDC hdc = GetDC(w);
843 SIZE sz;
845 SelectObject(hdc, fn->fid);
846 GetTextExtentPoint32(hdc, str, len, &sz);
847 ReleaseDC(w, hdc);
849 *width = sz.cy;
850 *height = 0;
853 #define DUPBITS(x) (((x)<<8)|(x))
855 void WinQueryColors(XColor *colors, int n)
857 int i;
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));
866 void WinAppMainLoop(void)
868 MSG msg;
869 BOOL bRet;
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);
881 DispatchMessage(&msg);
885 #ifdef USE_WIN32_COM
886 COM_terminate();
887 #endif
890 void WinPutImage(HWND win, GC gc, XImage *img, int srcx, int srcy, int destx, int desty, int width, int height)
892 HDC pixhdc, hdc;
894 if (img->handle == NULL) {
895 W32DEBUG(("Invalid image handle\n"));
896 return;
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);
909 void WinSetClipMask(GC gc, Pixmap pix)
911 gc->clipMask = pix;
914 typedef struct __win32_timer { int ID; void(*proc)(); void *data; struct __win32_timer *next; } win32_timer;
915 static win32_timer *timers = NULL;
917 VOID CALLBACK WinTimerProc(HWND hwnd, UINT umsg, UINT id, DWORD dwtime)
919 win32_timer *t = timers, *prev = NULL;
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;
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);
935 int WinAddTimeOut(int delay, void(*proc)(), void *data)
937 win32_timer* t = (win32_timer*)malloc(sizeof(win32_timer));
939 t->proc = proc;
940 t->data = data;
941 t->ID = SetTimer(NULL, 0, delay, WinTimerProc);
943 if (t->ID == 0) {
944 free(t);
945 return -1;
946 } else {
947 t->next = timers;
948 timers = t;
949 return t->ID;
953 void WinRemoveTimeOut(int id)
955 win32_timer *t = timers, *prev = NULL;
957 for (; t!=NULL && t->ID != id; prev=t, t=t->next);
958 if (t == NULL) {
959 return;
961 if (prev == NULL)
962 timers = t->next;
963 else
964 prev->next = t->next;
965 KillTimer(NULL, t->ID);
966 free(t);
969 void WinTranslateCoords(Widget win, short x, short y, short *rx, short *ry)
971 POINT pt;
973 pt.x = x;
974 pt.y = y;
975 ClientToScreen(win->handle, &pt);
976 *rx = pt.x;
977 *ry = pt.y;
980 typedef struct {
981 char *request;
982 char *current;
983 } InputDlgData;
985 BOOL CALLBACK InputDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
987 switch (msg) {
988 case WM_INITDIALOG:
990 RECT r1, r2;
991 int w1, w2, h1, h2;
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;
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;
1017 break;
1019 return FALSE;
1022 #define HELP_MARGIN 10
1024 BOOL CALLBACK HelpDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1026 switch (msg) {
1027 case WM_INITDIALOG:
1029 RECT br, r, cr, pr, pcr;
1030 int sbwidth;
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));
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;
1057 break;
1058 default:
1059 break;
1061 return FALSE;
1064 void popupprompt(Widget button, char *request, char *current, void (*function)(), buttonsave *datastruct, const char *filter)
1066 if (current != NULL && filter == NULL) {
1067 InputDlgData data;
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};
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);
1096 } else {
1097 if (MessageBox(areawin->window, request, "XCircuit", MB_YESNO|MB_ICONQUESTION) == IDYES)
1098 (*function)(button, datastruct->dataptr);
1101 if (datastruct != NULL) free(datastruct);
1104 static void get_vkey_name(int key, char *str, int len)
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;
1127 GetKeyNameText(scan, str, len);
1130 char *WinKeyToString(int key)
1132 static char buffer[1024];
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;
1142 if (key & KPMOD) {
1143 strcpy(buffer, "Keypad_");
1144 offset = 7;
1146 if (key & VKMOD)
1147 get_vkey_name(key&0x00ff, buffer+offset, 1024-offset);
1148 else
1149 buffer[offset] = key&0x00ff;
1152 return buffer;
1155 int WinStringToKey(const char *str)
1157 int key;
1158 char buf[256];
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;
1166 return 0;
1169 static Widget WndFound;
1171 BOOL CALLBACK WndLookupProc(HWND hwnd, LPARAM lParam)
1173 Widget w = (Widget)get_widget(hwnd);
1175 if (w != NULL && strcmp((char*)lParam, w->name) == 0) {
1176 WndFound = w;
1177 W32DEBUG(("widget name: '%s'\n", w->name));
1178 return FALSE;
1180 W32DEBUG(("widget name: '%s' (%p)\n", (w ? w->name : (char*)w)));
1181 return TRUE;
1184 const char* WinName(Widget w)
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;
1198 Widget WinNameToWindow(Widget parent, const char *name)
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;
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:
1229 int i, n = GetMenuItemCount((HMENU)parent->handle);
1230 MENUITEMINFO mi_info;
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;
1245 break;
1247 return WndFound;
1250 void outputpopup(Widget button, caddr_t clientdata, caddr_t calldata)
1252 if (is_page(topobject) == -1) {
1253 Wprintf("Can only save a top-level page!");
1254 return;
1256 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_OUTPUTDLG), top->handle, OutputDlgProc);
1259 typedef struct {
1260 char *bits;
1261 int width, height;
1262 } cursor_bits;
1264 static u_char reverse_byte(u_char c)
1266 u_char rc = 0;
1267 int i;
1269 for (i=(sizeof(char)*8-1); i>=0; i--, c>>=1)
1270 rc |= (c&0x01) << i;
1271 return rc;
1274 static void compute_cursor_src_mask(u_char *src, u_char *mask)
1276 u_char pixsrc = *src, pixmask = *mask;
1277 *src = ~(reverse_byte(pixmask));
1278 *mask = reverse_byte((u_char)((~pixsrc&0xff)&pixmask));
1281 static HBITMAP create_stipple(char *stipdata)
1283 HBITMAP hBitmap;
1284 BYTE data[8];
1285 int i;
1287 for (i=0; i<4; i++) {
1288 data[2*i] = 0xff & ~reverse_byte(stipdata[i]);
1290 hBitmap = CreateBitmap(4, 4, 1, 1, data);
1291 return hBitmap;
1294 HBITMAP WinCreateBitmapFromData(HWND w, char *data, int width, int height)
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;
1307 HCURSOR WinCreateCursor(HBITMAP _src, HBITMAP _mask, int xhot, int yhot)
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;
1317 new_src = (u_char*)malloc(sizeof(char)*nb2*height2);
1318 new_mask = (u_char*)malloc(sizeof(char)*nb2*height2);
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]);
1326 for (i=0; i<(nb2-nb); i++, idx2++) {
1327 new_src[idx2] = 0xff;
1328 new_mask[idx2] = 0x00;
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;
1338 hCursor = CreateCursor(GetModuleHandle(NULL), xhot, yhot, nb2*8, height2, new_src, new_mask);
1340 free(new_src);
1341 free(new_mask);
1342 free(_src);
1343 free(_mask);
1345 return hCursor;
1348 static Widget create_widget(HWND handle, char *name)
1350 Widget w = (Widget)malloc(sizeof(struct __WinWidget));
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);
1363 SetWindowLong(handle, GWL_USERDATA, (LONG)w);
1364 return w;
1367 static void destroy_widget(HWND handle)
1369 Widget w = (Widget)get_widget(handle);
1370 WinCallback *cb = w->callbacks, *free_cb;
1371 WinEventHandler *eh = w->handlers, *free_eh;
1373 free(w->name);
1374 while (cb != NULL) {
1375 free_cb = cb;
1376 cb = cb->next;
1377 free(free_cb);
1379 while (eh != NULL) {
1380 free_eh = eh;
1381 eh = eh->next;
1382 free(free_eh);
1384 if (w->wndproc != NULL)
1385 SetWindowLong(handle, GWL_WNDPROC, (LONG)w->wndproc);
1386 free(w);
1389 LRESULT CALLBACK XcTopWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
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;
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);
1409 MENUITEMINFO mi_info;
1410 HMENU hMenu = GetMenu(hwnd);
1411 int i;
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);
1425 SetFocus(areawin->window);
1427 return 0;
1428 case WM_SIZE:
1430 int width = LOWORD(lParam), th, sh, height = HIWORD(lParam), nbrows = 1;
1431 DWORD sz;
1432 RECT sr;
1434 SetWindowPos(toolBar->handle, HWND_TOP, 0, 0, width, 25, 0);
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;
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);
1451 return DefWindowProc(hwnd, msg, wParam, lParam);
1452 case WM_MENUCOMMAND:
1454 MENUITEMINFO mi_info;
1455 MenuItem item;
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);
1462 if ((item = (MenuItem)mi_info.dwItemData) != NULL && item->callbacks != NULL) {
1463 W32DEBUG(("Calling callback\n"));
1464 execute_callback(XtNselect, (Widget)item, NULL);
1467 return 0;
1468 case WM_COMMAND:
1469 if ((HWND)lParam == toolBar->handle) {
1470 TBBUTTONINFO tbi;
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);
1481 return 0;
1482 default:
1483 return DefWindowProc(hwnd, msg, wParam, lParam);
1487 void button_event(Widget win, int type, int button, short x, short y)
1489 XButtonEvent event;
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);
1503 if (win == areawin->scrollbarh || win == areawin->scrollbarv)
1504 if (type == ButtonPress)
1505 SetCapture(win->handle);
1506 else if (type == ButtonRelease)
1507 ReleaseCapture();
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;
1529 void key_event(Widget win, int type, int key, int scan)
1531 POINT pt;
1532 static BYTE keys[256];
1533 WORD c = 0x0000;
1534 XKeyEvent event;
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;
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;
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;
1591 event.keycode |= key;
1592 W32DEBUG(("non char: %d\n", event.keycode));
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;
1605 LRESULT CALLBACK XcWidgetProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1607 Widget win = (Widget)get_widget(hwnd);
1609 switch (msg) {
1610 case WM_DESTROY:
1611 destroy_widget(hwnd);
1612 return 0;
1613 case WM_PAINT:
1615 RECT r;
1616 GetUpdateRect(hwnd, &r, FALSE);
1617 if (win != NULL)
1618 execute_callback(XtNexpose, win, NULL);
1619 ValidateRect(hwnd, &r);
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);
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:
1669 SHORT delta = HIWORD(wParam);
1670 panbutton((delta > 0 ? 3 : 4), 0, 0, 0.05);
1671 refresh(NULL, NULL, NULL);
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;
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;
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);
1701 LRESULT CALLBACK XcHelppixProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
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:
1713 SCROLLINFO si;
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;
1724 case WM_PAINT:
1726 HDC hdc, pixhdc;
1727 PAINTSTRUCT ps;
1728 RECT r;
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;
1738 break;
1739 case WM_VSCROLL:
1741 SCROLLINFO si;
1742 int pos;
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;
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);
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;
1786 return 0;
1787 default:
1788 return DefWindowProc(hwnd, msg, wParam, lParam);
1792 static XFontStruct* create_font_struct(HFONT hFont)
1794 TEXTMETRIC tm;
1795 XFontStruct *fs = NULL;
1796 HDC hdc = GetDC(NULL);
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"));
1807 ReleaseDC(NULL, hdc);
1809 return fs;
1812 static menuID = 100;
1814 static Menu create_win_menu(HMENU menu)
1816 Menu wmenu = (Menu)malloc(sizeof(struct __WinMenu));
1817 MENUINFO minfo;
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);
1827 return wmenu;
1830 static MenuItem insert_win_menuitem(Menu menu, MENUITEMINFO* mi_info, menustruct *ms, int pos)
1832 MenuItem item = (MenuItem)malloc(sizeof(struct __WinMenuItem));
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;
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)){
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);
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;
1870 return item;
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
1881 static HBITMAP create_color_icon(int color, int width, int height)
1883 HDC hdc = GetDC(NULL);
1884 HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
1885 HBRUSH hBrush = CreateSolidBrush(color);
1886 RECT r = {0, 0};
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);
1897 return hBitmap;
1900 static HBITMAP create_stipple_icon(int stipdata, int width, int height)
1902 HDC hdc = GetDC(NULL);
1903 HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
1904 HBRUSH hBrush = CreatePatternBrush(STIPPLE[stipdata]);
1905 RECT r = {0, 0};
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);
1916 return hBitmap;
1919 static char* color_string(int c)
1921 static char buf[256];
1922 char *cname = WinColorName(c);
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;
1931 static void makesubmenu(Menu menu, menustruct *items, int n);
1932 static void make_color_submenu(Menu menu, menustruct *items, int n)
1934 if (dpy == NULL)
1935 makesubmenu(menu, items, n);
1936 else {
1937 int i;
1938 MENUITEMINFO mi_info;
1939 MenuItem item;
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;
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);
1961 static void makesubmenu(Menu menu, menustruct *items, int n)
1963 int i;
1964 MENUITEMINFO mi_info;
1965 int is_color = -1;
1966 MenuItem mitem;
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;
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;
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;
2011 mitem = insert_win_menuitem(menu, &mi_info, &items[i], -1);
2012 if (is_color != -1 && dpy == NULL)
2013 addtocolorlist((Widget)mitem, is_color);
2017 static HMENU create_menus()
2019 Menu menu;
2020 MENUITEMINFO mi_info;
2021 int i;
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;
2039 insert_win_menuitem(menu, &mi_info, &TopButtons[i], -1);
2042 return menu->handle;
2045 static void create_statusbar()
2047 HDC hdc;
2048 SIZE sz;
2049 StatusItem msg2, msg3;
2051 hdc = GetDC(NULL);
2052 GetTextExtentPoint32(hdc, "Editing: filename (Page 1)", 26, &sz);
2053 statusBarWidth[0] = sz.cx;
2054 ReleaseDC(NULL, hdc);
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");
2062 msg2 = (StatusItem)malloc(sizeof(struct __WinStatusItem));
2063 msg2->handle = statusBar;
2064 msg2->type = WIN_STATUS;
2065 msg2->position = 0;
2066 message2 = (Widget)msg2;
2068 msg3 = (StatusItem)malloc(sizeof(struct __WinStatusItem));
2069 msg3->handle = statusBar;
2070 msg3->type = WIN_STATUS;
2071 msg3->position = 1;
2072 message3 = (Widget)msg3;
2075 typedef struct { int c; RGBQUAD color; } xpm_color;
2077 static HBITMAP create_bitmap_from_xpm(char **xpm)
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;
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;
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);
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;
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);
2140 ReleaseDC(NULL, hdc);
2141 free(bmi);
2142 free(colors);
2144 return hBitmap;
2147 static void create_toolbar()
2149 TBBUTTON *buttons;
2150 TBADDBITMAP bitmap;
2151 int i;
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));
2158 buttons = (TBBUTTON*)malloc(sizeof(TBBUTTON) * toolbuttons);
2159 for (i=0; i<toolbuttons; i++) {
2160 ToolItem item;
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);
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;
2179 menuwidgets[item->ID-100] = (Widget)item;
2180 XtAddCallback((Widget)item, XtNselect, (XtCallbackProc)ToolBar[i].func, ToolBar[i].passeddata);
2183 if (ToolBar[i].func == changetool ||
2184 ToolBar[i].func == exec_or_changetool)
2185 buttons[i].fsStyle |= TBSTYLE_CHECK;
2188 SendMessage(toolBar->handle, TB_ADDBUTTONS, toolbuttons, (LPARAM)buttons);
2189 free(buttons);
2192 static void register_win32_classes()
2194 WNDCLASS wndClass;
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);
2203 /* Main area */
2204 ZeroMemory(&wndClass, sizeof(wndClass));
2205 wndClass.lpfnWndProc = XcWidgetProc;
2206 wndClass.lpszClassName = "XcWidget";
2207 wndClass.cbWndExtra = sizeof(void*);
2208 RegisterClass(&wndClass);
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);
2218 /* Help widget */
2219 ZeroMemory(&wndClass, sizeof(wndClass));
2220 wndClass.lpfnWndProc = XcHelppixProc;
2221 wndClass.lpszClassName = "XcHelp";
2222 RegisterClass(&wndClass);
2224 /* Popup */
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);
2235 XCWindowData* GUI_init(int argc, char *argv[])
2237 int i;
2238 XGCValues values;
2239 Arg wargs[2];
2240 RECT clientRect = { 0, 0, 0, 0 };
2241 XCWindowData *newwin;
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
2251 if (dpy == NULL) {
2252 register_win32_classes();
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));
2294 for (i=0; i<STIPPLES; i++) {
2295 STIPPLE[i] = WinCreateBitmapFromData(NULL, STIPDATA[i], 4, 4);
2298 number_colors = NUMBER_OF_COLORS;
2299 colorlist = (colorindex *)malloc(NUMBER_OF_COLORS * sizeof(colorindex));
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);
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;
2311 dpy = XtDisplay(top);
2312 newwin = create_new_window();
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);
2323 create_statusbar();
2324 create_toolbar();
2326 XtAddCallback(newwin->area, XtNexpose, (XtCallbackProc)drawarea, NULL);
2327 XtAddCallback(newwin->area, XtNresize, (XtCallbackProc)resizearea, NULL);
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);
2334 XtAddEventHandler(newwin->area, Button1MotionMask | Button2MotionMask,
2335 False, (XtEventHandler)xlib_drag, NULL);
2337 XtAddEventHandler(newwin->scrollbarh, ButtonMotionMask, False,
2338 (XtEventHandler)panhbar, NULL);
2339 XtAddEventHandler(newwin->scrollbarv, ButtonMotionMask, False,
2340 (XtEventHandler)panvbar, NULL);
2342 XtAddCallback(newwin->scrollbarh, XtNrelease, (XtCallbackProc)endhbar, NULL);
2343 XtAddCallback(newwin->scrollbarv, XtNrelease, (XtCallbackProc)endvbar, NULL);
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);
2350 values.foreground = RGB(0, 0, 0);
2351 values.background = RGB(255, 255, 255);
2352 values.font = appdata.xcfont->fid;
2354 newwin->gc = XCreateGC(dpy, newwin->window,
2355 GCForeground | GCBackground | GCFont, &values);
2357 XtSetArg(wargs[0], XtNwidth, &newwin->width);
2358 XtSetArg(wargs[1], XtNheight, &newwin->height);
2359 XtGetValues(newwin->area, wargs, 2);
2361 SendMessage(((ToolItem)WireToolButton)->toolbar->handle, TB_CHECKBUTTON, ((ToolItem)WireToolButton)->ID, MAKELONG(TRUE, 0));
2363 #ifdef USE_WIN32_COM
2364 if (!COM_initialize())
2365 printf("Failed to initialize COM interface\n");
2366 #endif
2368 return newwin;
2371 void WinAddEventHandler(Widget win, int event, void(*proc)(), void *data)
2373 WinEventHandler *h = win->handlers;
2375 if (win->type != WIN_WIDGET) {
2376 W32DEBUG(("Can't add event handler to non widget\n"));
2377 return;
2380 while (h != NULL) {
2381 if (h->proc == proc && h->data == data) {
2382 h->action |= event;
2383 break;
2384 } else
2385 h = h->next;
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;
2397 update_event_mask(win);
2400 void WinRemoveEventHandler(Widget win, int event, void(*proc)(), void *data)
2402 WinEventHandler *h, *prev = NULL;
2404 if (win->type != WIN_WIDGET) {
2405 W32DEBUG(("Can't remove event handler from non widget\n"));
2406 return;
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);
2421 } else {
2422 prev = h;
2423 h = h->next;
2425 update_event_mask(win);
2428 void WinAddCallback(Widget win, int event, void(*proc)(), void *data)
2430 WinCallback *cb, **root, *prev = NULL;
2432 if (win == NULL)
2433 return;
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;
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;
2451 cb = *root;
2452 while (cb) {
2453 prev = cb;
2454 cb = cb->next;
2457 cb = (WinCallback*)malloc(sizeof(WinCallback));
2458 cb->action = event;
2459 cb->proc = proc;
2460 cb->data = data;
2461 cb->next = NULL;
2463 if (prev)
2464 prev->next = cb;
2465 else
2466 *root = cb;
2469 int WinFindCallback(Widget win, int event, void(**proc)(), void **data)
2471 WinCallback *cb;
2473 if (win == NULL)
2474 return 0;
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;
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;
2496 cb = cb->next;
2499 return 0;
2502 void WinRemoveCallback(Widget win, int event, void(*proc)(), void *data)
2504 WinCallback *cb;
2505 WinCallback *prev = NULL, **root;
2507 if (win == NULL)
2508 return;
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;
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;
2539 void WinRemoveAllCallbacks(Widget win, int event)
2541 if (win == NULL)
2542 return;
2544 WinRemoveCallback(win, event, NULL, NULL);
2547 static Arg* look_arg(Arg *args, int type, int n)
2549 int i;
2550 for (i=0; i<n; i++)
2551 if (args[i].type == type)
2552 return &args[i];
2553 return NULL;
2556 static void get_window_location(Arg *args, int n, POINT *pt, SIZE *sz)
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;
2568 Widget WinCreateWidget(const char *name, int cls, Widget parent, Arg *args, int n, int show)
2570 int i;
2571 Widget win;
2573 switch (cls) {
2574 case XwcascadeWidgetClass:
2576 MENUITEMINFO mi_info;
2577 MenuItem item;
2578 Menu popup = create_win_menu(CreatePopupMenu());
2579 Arg *a;
2580 int pos = -1;
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;
2594 item = insert_win_menuitem((Menu)parent, &mi_info, NULL, pos);
2595 item->name = strdup(name);
2596 DrawMenuBar(topwin);
2597 return (Widget)item;
2599 case XwmenubuttonWidgetClass:
2601 MENUITEMINFO mi_info;
2602 Arg *a;
2603 MenuItem item;
2604 int pos = -1;
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;
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;
2626 item = insert_win_menuitem((Menu)parent, &mi_info, NULL, pos);
2627 item->name = strdup(name);
2628 DrawMenuBar(topwin);
2629 return (Widget)item;
2631 break;
2633 case XwstaticTextWidgetClass:
2635 POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
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);
2643 break;
2644 case XwtextEditWidgetClass:
2646 POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
2647 SIZE sz = {CW_USEDEFAULT, CW_USEDEFAULT};
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);
2654 break;
2655 case XwpushButtonWidgetClass:
2656 case XwmenuButtonWidgetClass:
2658 POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
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);
2666 break;
2667 case XwtoggleWidgetClass:
2669 POINT pt = {CW_USEDEFAULT, CW_USEDEFAULT};
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);
2677 break;
2678 case XwbulletinWidgetClass:
2679 win = parent;
2680 break;
2682 default:
2683 W32DEBUG(("Should create widget: %02x, %s\n", cls, name));
2684 win = NULL;
2685 break;
2688 if (show)
2689 ShowWindow(win->handle, SW_SHOW);
2690 else
2691 ShowWindow(win->handle, SW_HIDE);
2693 return win;
2696 Widget WinCreatePopup(const char *name, Arg *args, int n)
2698 HWND hwnd;
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);
2705 void WinPopup(Widget popup)
2707 ShowWindow(popup->handle, SW_SHOWNORMAL);
2710 char* WinGetText(Widget win)
2712 static char buffer[1024];
2714 GetWindowText(win->handle, buffer, 1024);
2715 return buffer;
2718 void WinClearText(Widget win)
2720 SetWindowText(win->handle, "");
2723 int WinNamedColor(const char *cname)
2725 int i;
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);
2731 W32DEBUG(("Unknown color: %s\n", cname));
2732 return -1;
2735 int WinLookupColor(const char *cname, XColor *color)
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;
2747 char *WinColorName(int c)
2749 int red = GetRValue(c), green = GetGValue(c), blue = GetBValue(c);
2750 int i;
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;
2758 HWND WinWindow(Widget w)
2760 return (w ? w->handle : NULL);
2763 void WinManageChild(Widget w)
2765 if (w != NULL)
2766 ShowWindow(w->handle, SW_SHOW);
2769 void WinUnmanageChild(Widget w)
2771 if (w != NULL)
2772 ShowWindow(w->handle, SW_HIDE);
2775 void WinDebug(char *c)
2777 W32DEBUG(("%s", c));
2780 void WinLookupString(XKeyEvent *event, KeySym *key)
2782 XKeyEvent *kevent = (XKeyEvent*)event;
2783 int vk = kevent->keycode & 0xff;
2785 if (vk == 0)
2786 *key = 0;
2787 else {
2788 W32DEBUG(("Translating key event: %d\n", vk));
2789 *key = kevent->keycode;
2793 void WinPostPopup(Widget _menu, Widget _button, int dx, int dy)
2795 Menu menu = (Menu)_menu;
2796 ToolItem button = (ToolItem)_button;
2797 RECT bRect = { 0, 0, 0, 0 };
2798 POINT pt;
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));
2809 void overdrawpixmap(Widget button)
2811 MenuItem mitem = (MenuItem)button;
2812 ToolItem titem = NULL;
2813 int idx;
2815 if (button == NULL) return;
2816 idx = mitem->toolbar_idx;
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;
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);
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);
2849 W32DEBUG(("%s: %d\n", titem->name, idx));
2850 if (idx > 0) {
2851 SendMessage(titem->toolbar->handle, TB_CHANGEBITMAP, titem->ID, MAKELPARAM(idx, 0));
2855 void starthelp(xcWidget button, caddr_t clientdata, caddr_t calldata)
2857 DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_HELPDLG), areawin->window, HelpDlgProc, (LPARAM)NULL);
2861 static void get_text_size(HWND hwnd, HFONT hfont, SIZE *sz)
2863 HDC hdc = GetDC(hwnd);
2864 char str[64];
2865 int n;
2867 SelectObject(hdc, hfont);
2868 n = GetWindowText(hwnd, str, 64);
2869 GetTextExtentPoint32(hdc, str, n, sz);
2870 ReleaseDC(hwnd, hdc);
2873 LRESULT CALLBACK XcStaticProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2875 Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
2877 switch (msg) {
2878 case WM_SETFONT:
2880 SIZE sz;
2881 get_text_size(hwnd, (HFONT)wParam, &sz);
2882 SetWindowPos(hwnd, HWND_TOP, 0, 0, sz.cx, sz.cy, SWP_NOMOVE);
2884 break;
2887 return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2890 LRESULT CALLBACK XcEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2892 Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
2894 switch (msg) {
2895 case WM_KEYDOWN:
2896 if (wParam == VK_RETURN) {
2897 execute_callback(XtNexecute, w, NULL);
2898 return 0;
2900 break;
2903 return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2906 LRESULT CALLBACK XcButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2908 Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
2910 switch (msg) {
2911 case WM_SETFONT:
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);
2918 break;
2919 case WM_SETTEXT:
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;
2927 case WM_LBUTTONDOWN:
2928 execute_callback(XtNselect, w, NULL);
2929 break;
2932 return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2935 LRESULT CALLBACK XcToggleProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2937 Widget w = (Widget)GetWindowLong(hwnd, GWL_USERDATA);
2939 switch (msg) {
2940 case WM_SETFONT:
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);
2946 break;
2947 case WM_LBUTTONUP:
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);
2955 break;
2958 return CallWindowProc(w->wndproc, hwnd, msg, wParam, lParam);
2961 LRESULT CALLBACK XcPopupProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2963 return DefDlgProc(hwnd, msg, wParam, lParam);
2967 static void change_char(char *str, char cfrom, char cto)
2969 char *c = str;
2970 for (; *c; c++)
2971 if (*c == cfrom)
2972 *c = cto;
2975 LRESULT CALLBACK OutputDlgEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2977 Widget win = get_widget (hwnd);
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;
2986 break;
2987 case WM_KEYDOWN:
2988 switch (wParam) {
2989 case VK_RETURN:
2990 execute_callback(XtNexecute, win, NULL);
2991 break;
2993 break;
2995 return CallWindowProc(win->wndproc, hwnd, msg, wParam, lParam);
2998 LRESULT CALLBACK OutputDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
3000 Widget popup = get_widget(hwnd);
3002 switch (msg) {
3003 case WM_INITDIALOG:
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;
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);
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");
3034 curpage = xobjs.pagelist[areawin->page];
3035 entertext = (Widget*)malloc(sizeof(Widget)*MAXPROPS);
3036 memset(okstruct, 0, sizeof(propstruct)*MAXPROPS);
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);
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");
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):");
3067 sprintf(statics[5], "Orientation:");
3068 sprintf(statics[6], "Mode:");
3069 SetDlgItemText(hwnd, IDC_PSINFO, request);
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(" ");
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]);
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);
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);
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]);
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);
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);
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);
3143 WinAddCallback(get_widget(GetDlgItem(hwnd, IDOK)), XtNselect, setfile, entertext[0]);
3145 if (curpage->pmode > 0) {
3146 XtManageChild(get_widget(GetDlgItem(hwnd, IDC_AUTOFIT)));
3147 XtManageChild(fpokstruct.textw);
3148 XtManageChild(fpokstruct.buttonw);
3151 if (pagelinks(areawin->page) > 1)
3152 XtManageChild(get_widget(GetDlgItem(hwnd, IDC_PAGENUM)));
3154 SetFocus(entertext[0]->handle);
3156 return FALSE;
3157 case WM_DESTROY:
3158 if (popup->bufhdc)
3159 free((Widget*)popup->bufhdc);
3160 destroy_widget(hwnd);
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;
3167 for (i=0; ID[i]!=-1; i++)
3168 destroy_widget(GetDlgItem(hwnd, ID[i]));
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);
3178 break;
3179 case IDCANCEL:
3180 if (HIWORD(wParam) == BN_CLICKED)
3181 EndDialog(hwnd, 0);
3182 break;
3183 case IDC_FILEOPEN:
3185 OPENFILENAME ofn;
3186 int len;
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);
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);
3225 break;
3226 case IDC_MODE:
3227 if (HIWORD(wParam) == CBN_SELENDOK)
3228 execute_callback(XtNselect, get_widget((HWND)lParam), NULL);
3229 break;
3231 break;
3232 default:
3233 return FALSE;
3236 return TRUE;
3239 extern int main(int argc, char **argv);
3241 int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
3243 LPWSTR *wargv;
3244 char **argv;
3245 int argc, i;
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], '\\', '/');
3257 LocalFree(wargv);
3258 return main(argc, argv);
3261 const char* WinBuiltinsDir()
3263 static char buffer[MAX_PATH] = {0};
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, '\\', '/');
3276 return buffer;
3279 static Widget find_menu_from_name(Menu menu, const char *name)
3281 int count, i;
3282 MENUITEMINFO mi_info;
3283 MenuItem item;
3284 Widget found = NULL;
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);
3300 return found;
3303 Widget WinGetMenu(const char *name)
3305 MENUINFO minfo;
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);
3317 return NULL;
3320 int WinIsPopupMenu(Widget w)
3322 if (IS_MENU(w) ||
3323 (IS_MENUITEM(w) && TOMENUITEM(w)->popup != NULL))
3324 return 1;
3325 return 0;
3328 void exec_script_command(void *button, void *data)
3330 #ifdef USE_WIN32_COM
3331 COM_execute(_STR2);
3332 #endif
3335 void docommand()
3337 popupprompt(NULL, "Enter command to execute:", "", exec_script_command, NULL, NULL);
3340 #ifdef USE_WIN32_COM
3342 void win32_comscript()
3344 COM_runscript(_STR2);
3347 void win32_comdotnet()
3349 COM_load_dotnet(_STR2);
3352 #endif
3354 void win32_new_window(Widget w, void *clientData, void *callData)
3356 XCWindowData *newwin = GUI_init(0, NULL);
3358 newwin->page = areawin->page;
3359 newwin->vscale = areawin->vscale;
3360 newwin->pcorner = areawin->pcorner;
3361 newwin->topinstance = areawin->topinstance;
3363 areawin = newwin;
3364 ShowWindow(top->handle, SW_SHOW);