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