xref: /plan9/sys/src/cmd/unix/drawterm/gui-win32/screen.c (revision 353937820181d9ceece9f7e799bfae37fdcac66e)
1*35393782SDavid du Colombier #define _WIN32_WINNT 0x0500
28ccd4a63SDavid du Colombier #include	<windows.h>
38ccd4a63SDavid du Colombier 
48ccd4a63SDavid du Colombier #undef Rectangle
58ccd4a63SDavid du Colombier #define Rectangle _Rectangle
68ccd4a63SDavid du Colombier 
78ccd4a63SDavid du Colombier #include "u.h"
88ccd4a63SDavid du Colombier #include "lib.h"
98ccd4a63SDavid du Colombier #include "kern/dat.h"
108ccd4a63SDavid du Colombier #include "kern/fns.h"
118ccd4a63SDavid du Colombier #include "error.h"
128ccd4a63SDavid du Colombier #include "user.h"
138ccd4a63SDavid du Colombier #include <draw.h>
148ccd4a63SDavid du Colombier #include <memdraw.h>
158ccd4a63SDavid du Colombier #include "screen.h"
168ccd4a63SDavid du Colombier #include "keyboard.h"
178ccd4a63SDavid du Colombier 
188ccd4a63SDavid du Colombier Memimage	*gscreen;
198ccd4a63SDavid du Colombier Screeninfo	screen;
208ccd4a63SDavid du Colombier 
218ccd4a63SDavid du Colombier extern int mousequeue;
228ccd4a63SDavid du Colombier static int depth;
238ccd4a63SDavid du Colombier 
248ccd4a63SDavid du Colombier static	HINSTANCE	inst;
258ccd4a63SDavid du Colombier static	HWND		window;
268ccd4a63SDavid du Colombier static	HPALETTE	palette;
278ccd4a63SDavid du Colombier static	LOGPALETTE	*logpal;
288ccd4a63SDavid du Colombier static  Lock		gdilock;
298ccd4a63SDavid du Colombier static 	BITMAPINFO	*bmi;
308ccd4a63SDavid du Colombier static	HCURSOR		hcursor;
318ccd4a63SDavid du Colombier 
328ccd4a63SDavid du Colombier static void	winproc(void *);
338ccd4a63SDavid du Colombier static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
348ccd4a63SDavid du Colombier static void	paletteinit(void);
358ccd4a63SDavid du Colombier static void	bmiinit(void);
368ccd4a63SDavid du Colombier 
378ccd4a63SDavid du Colombier static int readybit;
388ccd4a63SDavid du Colombier static Rendez	rend;
398ccd4a63SDavid du Colombier 
408ccd4a63SDavid du Colombier Point	ZP;
418ccd4a63SDavid du Colombier 
428ccd4a63SDavid du Colombier static int
isready(void * a)438ccd4a63SDavid du Colombier isready(void*a)
448ccd4a63SDavid du Colombier {
458ccd4a63SDavid du Colombier 	return readybit;
468ccd4a63SDavid du Colombier }
478ccd4a63SDavid du Colombier 
488ccd4a63SDavid du Colombier void
screeninit(void)498ccd4a63SDavid du Colombier screeninit(void)
508ccd4a63SDavid du Colombier {
518ccd4a63SDavid du Colombier 	int fmt;
528ccd4a63SDavid du Colombier 	int dx, dy;
538ccd4a63SDavid du Colombier 
548ccd4a63SDavid du Colombier 	memimageinit();
558ccd4a63SDavid du Colombier 	if(depth == 0)
568ccd4a63SDavid du Colombier 		depth = GetDeviceCaps(GetDC(NULL), BITSPIXEL);
578ccd4a63SDavid du Colombier 	switch(depth){
588ccd4a63SDavid du Colombier 	case 32:
598ccd4a63SDavid du Colombier 		screen.dibtype = DIB_RGB_COLORS;
608ccd4a63SDavid du Colombier 		screen.depth = 32;
618ccd4a63SDavid du Colombier 		fmt = XRGB32;
628ccd4a63SDavid du Colombier 		break;
638ccd4a63SDavid du Colombier 	case 24:
648ccd4a63SDavid du Colombier 		screen.dibtype = DIB_RGB_COLORS;
658ccd4a63SDavid du Colombier 		screen.depth = 24;
668ccd4a63SDavid du Colombier 		fmt = RGB24;
678ccd4a63SDavid du Colombier 		break;
688ccd4a63SDavid du Colombier 	case 16:
698ccd4a63SDavid du Colombier 		screen.dibtype = DIB_RGB_COLORS;
708ccd4a63SDavid du Colombier 		screen.depth = 16;
718ccd4a63SDavid du Colombier 		fmt = RGB15;	/* [sic] */
728ccd4a63SDavid du Colombier 		break;
738ccd4a63SDavid du Colombier 	case 8:
748ccd4a63SDavid du Colombier 	default:
758ccd4a63SDavid du Colombier 		screen.dibtype = DIB_PAL_COLORS;
768ccd4a63SDavid du Colombier 		screen.depth = 8;
778ccd4a63SDavid du Colombier 		depth = 8;
788ccd4a63SDavid du Colombier 		fmt = CMAP8;
798ccd4a63SDavid du Colombier 		break;
808ccd4a63SDavid du Colombier 	}
818ccd4a63SDavid du Colombier 	dx = GetDeviceCaps(GetDC(NULL), HORZRES);
828ccd4a63SDavid du Colombier 	dy = GetDeviceCaps(GetDC(NULL), VERTRES);
838ccd4a63SDavid du Colombier 
848ccd4a63SDavid du Colombier 	gscreen = allocmemimage(Rect(0,0,dx,dy), fmt);
858ccd4a63SDavid du Colombier 	kproc("winscreen", winproc, 0);
868ccd4a63SDavid du Colombier 	ksleep(&rend, isready, 0);
878ccd4a63SDavid du Colombier }
888ccd4a63SDavid du Colombier 
898ccd4a63SDavid du Colombier uchar*
attachscreen(Rectangle * r,ulong * chan,int * depth,int * width,int * softscreen,void ** X)908ccd4a63SDavid du Colombier attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X)
918ccd4a63SDavid du Colombier {
928ccd4a63SDavid du Colombier 	*r = gscreen->r;
938ccd4a63SDavid du Colombier 	*chan = gscreen->chan;
948ccd4a63SDavid du Colombier 	*depth = gscreen->depth;
958ccd4a63SDavid du Colombier 	*width = gscreen->width;
968ccd4a63SDavid du Colombier 	*softscreen = 1;
978ccd4a63SDavid du Colombier 
988ccd4a63SDavid du Colombier 	return gscreen->data->bdata;
998ccd4a63SDavid du Colombier }
1008ccd4a63SDavid du Colombier 
1018ccd4a63SDavid du Colombier void
flushmemscreen(Rectangle r)1028ccd4a63SDavid du Colombier flushmemscreen(Rectangle r)
1038ccd4a63SDavid du Colombier {
1048ccd4a63SDavid du Colombier 	screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP,
1058ccd4a63SDavid du Colombier 		gscreen->width*sizeof(ulong));
1068ccd4a63SDavid du Colombier //	Sleep(100);
1078ccd4a63SDavid du Colombier }
1088ccd4a63SDavid du Colombier 
1098ccd4a63SDavid du Colombier void
screenload(Rectangle r,int depth,uchar * p,Point pt,int step)1108ccd4a63SDavid du Colombier screenload(Rectangle r, int depth, uchar *p, Point pt, int step)
1118ccd4a63SDavid du Colombier {
1128ccd4a63SDavid du Colombier 	int dx, dy, delx;
1138ccd4a63SDavid du Colombier 	HDC hdc;
1148ccd4a63SDavid du Colombier 	RECT winr;
1158ccd4a63SDavid du Colombier 
1168ccd4a63SDavid du Colombier 	if(depth != gscreen->depth)
1178ccd4a63SDavid du Colombier 		panic("screenload: bad ldepth");
1188ccd4a63SDavid du Colombier 
1198ccd4a63SDavid du Colombier 	/*
1208ccd4a63SDavid du Colombier 	 * Sometimes we do get rectangles that are off the
1218ccd4a63SDavid du Colombier 	 * screen to the negative axes, for example, when
1228ccd4a63SDavid du Colombier 	 * dragging around a window border in a Move operation.
1238ccd4a63SDavid du Colombier 	 */
1248ccd4a63SDavid du Colombier 	if(rectclip(&r, gscreen->r) == 0)
1258ccd4a63SDavid du Colombier 		return;
1268ccd4a63SDavid du Colombier 
1278ccd4a63SDavid du Colombier 	if((step&3) != 0 || ((pt.x*depth)%32) != 0 || ((ulong)p&3) != 0)
1288ccd4a63SDavid du Colombier 		panic("screenload: bad params %d %d %ux", step, pt.x, p);
1298ccd4a63SDavid du Colombier 	dx = r.max.x - r.min.x;
1308ccd4a63SDavid du Colombier 	dy = r.max.y - r.min.y;
1318ccd4a63SDavid du Colombier 
1328ccd4a63SDavid du Colombier 	if(dx <= 0 || dy <= 0)
1338ccd4a63SDavid du Colombier 		return;
1348ccd4a63SDavid du Colombier 
1358ccd4a63SDavid du Colombier 	if(depth == 24)
1368ccd4a63SDavid du Colombier 		delx = r.min.x % 4;
1378ccd4a63SDavid du Colombier 	else
1388ccd4a63SDavid du Colombier 		delx = r.min.x & (31/depth);
1398ccd4a63SDavid du Colombier 
1408ccd4a63SDavid du Colombier 	p += (r.min.y-pt.y)*step;
1418ccd4a63SDavid du Colombier 	p += ((r.min.x-delx-pt.x)*depth)>>3;
1428ccd4a63SDavid du Colombier 
1438ccd4a63SDavid du Colombier 	if(GetWindowRect(window, &winr)==0)
1448ccd4a63SDavid du Colombier 		return;
1458ccd4a63SDavid du Colombier 	if(rectclip(&r, Rect(0, 0, winr.right-winr.left, winr.bottom-winr.top))==0)
1468ccd4a63SDavid du Colombier 		return;
1478ccd4a63SDavid du Colombier 
1488ccd4a63SDavid du Colombier 	lock(&gdilock);
1498ccd4a63SDavid du Colombier 
1508ccd4a63SDavid du Colombier 	hdc = GetDC(window);
1518ccd4a63SDavid du Colombier 	SelectPalette(hdc, palette, 0);
1528ccd4a63SDavid du Colombier 	RealizePalette(hdc);
1538ccd4a63SDavid du Colombier 
1548ccd4a63SDavid du Colombier //FillRect(hdc,(void*)&r, GetStockObject(BLACK_BRUSH));
1558ccd4a63SDavid du Colombier //GdiFlush();
1568ccd4a63SDavid du Colombier //Sleep(100);
1578ccd4a63SDavid du Colombier 
1588ccd4a63SDavid du Colombier 	bmi->bmiHeader.biWidth = (step*8)/depth;
1598ccd4a63SDavid du Colombier 	bmi->bmiHeader.biHeight = -dy;	/* - => origin upper left */
1608ccd4a63SDavid du Colombier 
1618ccd4a63SDavid du Colombier 	StretchDIBits(hdc, r.min.x, r.min.y, dx, dy,
1628ccd4a63SDavid du Colombier 		delx, 0, dx, dy, p, bmi, screen.dibtype, SRCCOPY);
1638ccd4a63SDavid du Colombier 
1648ccd4a63SDavid du Colombier 	ReleaseDC(window, hdc);
1658ccd4a63SDavid du Colombier 
1668ccd4a63SDavid du Colombier 	GdiFlush();
1678ccd4a63SDavid du Colombier 
1688ccd4a63SDavid du Colombier 	unlock(&gdilock);
1698ccd4a63SDavid du Colombier }
1708ccd4a63SDavid du Colombier 
1718ccd4a63SDavid du Colombier static void
winproc(void * a)1728ccd4a63SDavid du Colombier winproc(void *a)
1738ccd4a63SDavid du Colombier {
1748ccd4a63SDavid du Colombier 	WNDCLASS wc;
1758ccd4a63SDavid du Colombier 	MSG msg;
1768ccd4a63SDavid du Colombier 
1778ccd4a63SDavid du Colombier 	inst = GetModuleHandle(NULL);
1788ccd4a63SDavid du Colombier 
1798ccd4a63SDavid du Colombier 	paletteinit();
1808ccd4a63SDavid du Colombier 	bmiinit();
1818ccd4a63SDavid du Colombier 	terminit();
1828ccd4a63SDavid du Colombier 
1838ccd4a63SDavid du Colombier 	wc.style = 0;
1848ccd4a63SDavid du Colombier 	wc.lpfnWndProc = WindowProc;
1858ccd4a63SDavid du Colombier 	wc.cbClsExtra = 0;
1868ccd4a63SDavid du Colombier 	wc.cbWndExtra = 0;
1878ccd4a63SDavid du Colombier 	wc.hInstance = inst;
1888ccd4a63SDavid du Colombier 	wc.hIcon = LoadIcon(inst, NULL);
1898ccd4a63SDavid du Colombier 	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1908ccd4a63SDavid du Colombier 	wc.hbrBackground = GetStockObject(WHITE_BRUSH);
1918ccd4a63SDavid du Colombier 	wc.lpszMenuName = 0;
192*35393782SDavid du Colombier 	wc.lpszClassName = L"9pmgraphics";
1938ccd4a63SDavid du Colombier 	RegisterClass(&wc);
1948ccd4a63SDavid du Colombier 
1958ccd4a63SDavid du Colombier 	window = CreateWindowEx(
1968ccd4a63SDavid du Colombier 		0,			/* extended style */
197*35393782SDavid du Colombier 		L"9pmgraphics",		/* class */
198*35393782SDavid du Colombier 		L"drawterm screen",		/* caption */
1998ccd4a63SDavid du Colombier 		WS_OVERLAPPEDWINDOW,    /* style */
2008ccd4a63SDavid du Colombier 		CW_USEDEFAULT,		/* init. x pos */
2018ccd4a63SDavid du Colombier 		CW_USEDEFAULT,		/* init. y pos */
2028ccd4a63SDavid du Colombier 		CW_USEDEFAULT,		/* init. x size */
2038ccd4a63SDavid du Colombier 		CW_USEDEFAULT,		/* init. y size */
2048ccd4a63SDavid du Colombier 		NULL,			/* parent window (actually owner window for overlapped)*/
2058ccd4a63SDavid du Colombier 		NULL,			/* menu handle */
2068ccd4a63SDavid du Colombier 		inst,			/* program handle */
2078ccd4a63SDavid du Colombier 		NULL			/* create parms */
2088ccd4a63SDavid du Colombier 		);
2098ccd4a63SDavid du Colombier 
2108ccd4a63SDavid du Colombier 	if(window == nil)
2118ccd4a63SDavid du Colombier 		panic("can't make window\n");
2128ccd4a63SDavid du Colombier 
2138ccd4a63SDavid du Colombier 	ShowWindow(window, SW_SHOWDEFAULT);
2148ccd4a63SDavid du Colombier 	UpdateWindow(window);
2158ccd4a63SDavid du Colombier 
2168ccd4a63SDavid du Colombier 	readybit = 1;
2178ccd4a63SDavid du Colombier 	wakeup(&rend);
2188ccd4a63SDavid du Colombier 
2198ccd4a63SDavid du Colombier 	screen.reshaped = 0;
2208ccd4a63SDavid du Colombier 
2218ccd4a63SDavid du Colombier 	while(GetMessage(&msg, NULL, 0, 0)) {
2228ccd4a63SDavid du Colombier 		TranslateMessage(&msg);
2238ccd4a63SDavid du Colombier 		DispatchMessage(&msg);
2248ccd4a63SDavid du Colombier 	}
2258ccd4a63SDavid du Colombier //	MessageBox(0, "winproc", "exits", MB_OK);
2268ccd4a63SDavid du Colombier 	ExitProcess(0);
2278ccd4a63SDavid du Colombier }
2288ccd4a63SDavid du Colombier 
2298ccd4a63SDavid du Colombier int
col(int v,int n)2308ccd4a63SDavid du Colombier col(int v, int n)
2318ccd4a63SDavid du Colombier {
2328ccd4a63SDavid du Colombier 	int i, c;
2338ccd4a63SDavid du Colombier 
2348ccd4a63SDavid du Colombier 	c = 0;
2358ccd4a63SDavid du Colombier 	for(i = 0; i < 8; i += n)
2368ccd4a63SDavid du Colombier 		c |= v << (16-(n+i));
2378ccd4a63SDavid du Colombier 	return c >> 8;
2388ccd4a63SDavid du Colombier }
2398ccd4a63SDavid du Colombier 
2408ccd4a63SDavid du Colombier 
2418ccd4a63SDavid du Colombier void
paletteinit(void)2428ccd4a63SDavid du Colombier paletteinit(void)
2438ccd4a63SDavid du Colombier {
2448ccd4a63SDavid du Colombier 	PALETTEENTRY *pal;
2458ccd4a63SDavid du Colombier 	int r, g, b, cr, cg, cb, v;
2468ccd4a63SDavid du Colombier 	int num, den;
2478ccd4a63SDavid du Colombier 	int i, j;
2488ccd4a63SDavid du Colombier 
2498ccd4a63SDavid du Colombier 	logpal = mallocz(sizeof(LOGPALETTE) + 256*sizeof(PALETTEENTRY), 1);
2508ccd4a63SDavid du Colombier 	if(logpal == nil)
2518ccd4a63SDavid du Colombier 		panic("out of memory");
2528ccd4a63SDavid du Colombier 	logpal->palVersion = 0x300;
2538ccd4a63SDavid du Colombier 	logpal->palNumEntries = 256;
2548ccd4a63SDavid du Colombier 	pal = logpal->palPalEntry;
2558ccd4a63SDavid du Colombier 
2568ccd4a63SDavid du Colombier 	for(r=0,i=0; r<4; r++) {
2578ccd4a63SDavid du Colombier 		for(v=0; v<4; v++,i+=16){
2588ccd4a63SDavid du Colombier 			for(g=0,j=v-r; g<4; g++) {
2598ccd4a63SDavid du Colombier 				for(b=0; b<4; b++,j++){
2608ccd4a63SDavid du Colombier 					den=r;
2618ccd4a63SDavid du Colombier 					if(g>den)
2628ccd4a63SDavid du Colombier 						den=g;
2638ccd4a63SDavid du Colombier 					if(b>den)
2648ccd4a63SDavid du Colombier 						den=b;
2658ccd4a63SDavid du Colombier 					/* divide check -- pick grey shades */
2668ccd4a63SDavid du Colombier 					if(den==0)
2678ccd4a63SDavid du Colombier 						cr=cg=cb=v*17;
2688ccd4a63SDavid du Colombier 					else{
2698ccd4a63SDavid du Colombier 						num=17*(4*den+v);
2708ccd4a63SDavid du Colombier 						cr=r*num/den;
2718ccd4a63SDavid du Colombier 						cg=g*num/den;
2728ccd4a63SDavid du Colombier 						cb=b*num/den;
2738ccd4a63SDavid du Colombier 					}
2748ccd4a63SDavid du Colombier 					pal[i+(j&15)].peRed = cr;
2758ccd4a63SDavid du Colombier 					pal[i+(j&15)].peGreen = cg;
2768ccd4a63SDavid du Colombier 					pal[i+(j&15)].peBlue = cb;
2778ccd4a63SDavid du Colombier 					pal[i+(j&15)].peFlags = 0;
2788ccd4a63SDavid du Colombier 				}
2798ccd4a63SDavid du Colombier 			}
2808ccd4a63SDavid du Colombier 		}
2818ccd4a63SDavid du Colombier 	}
2828ccd4a63SDavid du Colombier 	palette = CreatePalette(logpal);
2838ccd4a63SDavid du Colombier }
2848ccd4a63SDavid du Colombier 
2858ccd4a63SDavid du Colombier 
2868ccd4a63SDavid du Colombier void
getcolor(ulong i,ulong * r,ulong * g,ulong * b)2878ccd4a63SDavid du Colombier getcolor(ulong i, ulong *r, ulong *g, ulong *b)
2888ccd4a63SDavid du Colombier {
2898ccd4a63SDavid du Colombier 	PALETTEENTRY *pal;
2908ccd4a63SDavid du Colombier 
2918ccd4a63SDavid du Colombier 	pal = logpal->palPalEntry;
2928ccd4a63SDavid du Colombier 	*r = pal[i].peRed;
2938ccd4a63SDavid du Colombier 	*g = pal[i].peGreen;
2948ccd4a63SDavid du Colombier 	*b = pal[i].peBlue;
2958ccd4a63SDavid du Colombier }
2968ccd4a63SDavid du Colombier 
2978ccd4a63SDavid du Colombier void
bmiinit(void)2988ccd4a63SDavid du Colombier bmiinit(void)
2998ccd4a63SDavid du Colombier {
3008ccd4a63SDavid du Colombier 	ushort *p;
3018ccd4a63SDavid du Colombier 	int i;
3028ccd4a63SDavid du Colombier 
3038ccd4a63SDavid du Colombier 	bmi = mallocz(sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD), 1);
3048ccd4a63SDavid du Colombier 	if(bmi == 0)
3058ccd4a63SDavid du Colombier 		panic("out of memory");
3068ccd4a63SDavid du Colombier 	bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
3078ccd4a63SDavid du Colombier 	bmi->bmiHeader.biWidth = 0;
3088ccd4a63SDavid du Colombier 	bmi->bmiHeader.biHeight = 0;	/* - => origin upper left */
3098ccd4a63SDavid du Colombier 	bmi->bmiHeader.biPlanes = 1;
3108ccd4a63SDavid du Colombier 	bmi->bmiHeader.biBitCount = depth;
3118ccd4a63SDavid du Colombier 	bmi->bmiHeader.biCompression = BI_RGB;
3128ccd4a63SDavid du Colombier 	bmi->bmiHeader.biSizeImage = 0;
3138ccd4a63SDavid du Colombier 	bmi->bmiHeader.biXPelsPerMeter = 0;
3148ccd4a63SDavid du Colombier 	bmi->bmiHeader.biYPelsPerMeter = 0;
3158ccd4a63SDavid du Colombier 	bmi->bmiHeader.biClrUsed = 0;
3168ccd4a63SDavid du Colombier 	bmi->bmiHeader.biClrImportant = 0;	/* number of important colors: 0 means all */
3178ccd4a63SDavid du Colombier 
3188ccd4a63SDavid du Colombier 	p = (ushort*)bmi->bmiColors;
3198ccd4a63SDavid du Colombier 	for(i = 0; i < 256; i++)
3208ccd4a63SDavid du Colombier 		p[i] = i;
3218ccd4a63SDavid du Colombier }
3228ccd4a63SDavid du Colombier 
3238ccd4a63SDavid du Colombier LRESULT CALLBACK
WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)3248ccd4a63SDavid du Colombier WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
3258ccd4a63SDavid du Colombier {
3268ccd4a63SDavid du Colombier 	PAINTSTRUCT paint;
3278ccd4a63SDavid du Colombier 	HDC hdc;
3288ccd4a63SDavid du Colombier 	LONG x, y, b;
3298ccd4a63SDavid du Colombier 	int i;
3308ccd4a63SDavid du Colombier 	Rectangle r;
3318ccd4a63SDavid du Colombier 
3328ccd4a63SDavid du Colombier 	switch(msg) {
3338ccd4a63SDavid du Colombier 	case WM_CREATE:
3348ccd4a63SDavid du Colombier 		break;
3358ccd4a63SDavid du Colombier 	case WM_SETCURSOR:
3368ccd4a63SDavid du Colombier 		/* User set */
3378ccd4a63SDavid du Colombier 		if(hcursor != NULL) {
3388ccd4a63SDavid du Colombier 			SetCursor(hcursor);
3398ccd4a63SDavid du Colombier 			return 1;
3408ccd4a63SDavid du Colombier 		}
3418ccd4a63SDavid du Colombier 		return DefWindowProc(hwnd, msg, wparam, lparam);
342*35393782SDavid du Colombier 	case WM_MOUSEWHEEL:
343*35393782SDavid du Colombier 		if ((int)(wparam & 0xFFFF0000)>0)
344*35393782SDavid du Colombier 			b|=8;
345*35393782SDavid du Colombier 		else
346*35393782SDavid du Colombier 			b|=16;
3478ccd4a63SDavid du Colombier 	case WM_MOUSEMOVE:
3488ccd4a63SDavid du Colombier 	case WM_LBUTTONUP:
3498ccd4a63SDavid du Colombier 	case WM_MBUTTONUP:
3508ccd4a63SDavid du Colombier 	case WM_RBUTTONUP:
3518ccd4a63SDavid du Colombier 	case WM_LBUTTONDOWN:
3528ccd4a63SDavid du Colombier 	case WM_MBUTTONDOWN:
3538ccd4a63SDavid du Colombier 	case WM_RBUTTONDOWN:
3548ccd4a63SDavid du Colombier 		x = LOWORD(lparam);
3558ccd4a63SDavid du Colombier 		y = HIWORD(lparam);
3568ccd4a63SDavid du Colombier 		b = 0;
3578ccd4a63SDavid du Colombier 		if(wparam & MK_LBUTTON)
3588ccd4a63SDavid du Colombier 			b = 1;
3598ccd4a63SDavid du Colombier 		if(wparam & MK_MBUTTON)
3608ccd4a63SDavid du Colombier 			b |= 2;
3618ccd4a63SDavid du Colombier 		if(wparam & MK_RBUTTON) {
3628ccd4a63SDavid du Colombier 			if(wparam & MK_SHIFT)
3638ccd4a63SDavid du Colombier 				b |= 2;
3648ccd4a63SDavid du Colombier 			else
3658ccd4a63SDavid du Colombier 				b |= 4;
3668ccd4a63SDavid du Colombier 		}
3678ccd4a63SDavid du Colombier 		lock(&mouse.lk);
3688ccd4a63SDavid du Colombier 		i = mouse.wi;
3698ccd4a63SDavid du Colombier 		if(mousequeue) {
3708ccd4a63SDavid du Colombier 			if(i == mouse.ri || mouse.lastb != b || mouse.trans) {
3718ccd4a63SDavid du Colombier 				mouse.wi = (i+1)%Mousequeue;
3728ccd4a63SDavid du Colombier 				if(mouse.wi == mouse.ri)
3738ccd4a63SDavid du Colombier 					mouse.ri = (mouse.ri+1)%Mousequeue;
3748ccd4a63SDavid du Colombier 				mouse.trans = mouse.lastb != b;
3758ccd4a63SDavid du Colombier 			} else {
3768ccd4a63SDavid du Colombier 				i = (i-1+Mousequeue)%Mousequeue;
3778ccd4a63SDavid du Colombier 			}
3788ccd4a63SDavid du Colombier 		} else {
3798ccd4a63SDavid du Colombier 			mouse.wi = (i+1)%Mousequeue;
3808ccd4a63SDavid du Colombier 			mouse.ri = i;
3818ccd4a63SDavid du Colombier 		}
3828ccd4a63SDavid du Colombier 		mouse.queue[i].xy.x = x;
3838ccd4a63SDavid du Colombier 		mouse.queue[i].xy.y = y;
3848ccd4a63SDavid du Colombier 		mouse.queue[i].buttons = b;
3858ccd4a63SDavid du Colombier 		mouse.queue[i].msec = ticks();
3868ccd4a63SDavid du Colombier 		mouse.lastb = b;
3878ccd4a63SDavid du Colombier 		unlock(&mouse.lk);
3888ccd4a63SDavid du Colombier 		wakeup(&mouse.r);
3898ccd4a63SDavid du Colombier 		break;
3908ccd4a63SDavid du Colombier 
3918ccd4a63SDavid du Colombier 	case WM_CHAR:
3928ccd4a63SDavid du Colombier 		/* repeat count is lparam & 0xf */
3938ccd4a63SDavid du Colombier 		switch(wparam){
3948ccd4a63SDavid du Colombier 		case '\n':
3958ccd4a63SDavid du Colombier 			wparam = '\r';
3968ccd4a63SDavid du Colombier 			break;
3978ccd4a63SDavid du Colombier 		case '\r':
3988ccd4a63SDavid du Colombier 			wparam = '\n';
3998ccd4a63SDavid du Colombier 			break;
4008ccd4a63SDavid du Colombier 		}
4018ccd4a63SDavid du Colombier 		kbdputc(kbdq, wparam);
4028ccd4a63SDavid du Colombier 		break;
4038ccd4a63SDavid du Colombier 
4048ccd4a63SDavid du Colombier 	case WM_SYSKEYUP:
4058ccd4a63SDavid du Colombier 		break;
4068ccd4a63SDavid du Colombier 	case WM_SYSKEYDOWN:
4078ccd4a63SDavid du Colombier 	case WM_KEYDOWN:
4088ccd4a63SDavid du Colombier 		switch(wparam) {
4098ccd4a63SDavid du Colombier 		case VK_MENU:
4108ccd4a63SDavid du Colombier 			kbdputc(kbdq, Kalt);
4118ccd4a63SDavid du Colombier 			break;
4128ccd4a63SDavid du Colombier 		case VK_INSERT:
4138ccd4a63SDavid du Colombier 			kbdputc(kbdq, Kins);
4148ccd4a63SDavid du Colombier 			break;
4158ccd4a63SDavid du Colombier 		case VK_DELETE:
4168ccd4a63SDavid du Colombier //			kbdputc(kbdq, Kdel);
4178ccd4a63SDavid du Colombier 			kbdputc(kbdq, 0x7f);	// should have Kdel in keyboard.h
4188ccd4a63SDavid du Colombier 			break;
4198ccd4a63SDavid du Colombier 		case VK_UP:
4208ccd4a63SDavid du Colombier 			kbdputc(kbdq, Kup);
4218ccd4a63SDavid du Colombier 			break;
4228ccd4a63SDavid du Colombier 		case VK_DOWN:
4238ccd4a63SDavid du Colombier 			kbdputc(kbdq, Kdown);
4248ccd4a63SDavid du Colombier 			break;
4258ccd4a63SDavid du Colombier 		case VK_LEFT:
4268ccd4a63SDavid du Colombier 			kbdputc(kbdq, Kleft);
4278ccd4a63SDavid du Colombier 			break;
4288ccd4a63SDavid du Colombier 		case VK_RIGHT:
4298ccd4a63SDavid du Colombier 			kbdputc(kbdq, Kright);
4308ccd4a63SDavid du Colombier 			break;
4318ccd4a63SDavid du Colombier 		}
4328ccd4a63SDavid du Colombier 		break;
4338ccd4a63SDavid du Colombier 
4348ccd4a63SDavid du Colombier 	case WM_CLOSE:
4358ccd4a63SDavid du Colombier 		DestroyWindow(hwnd);
4368ccd4a63SDavid du Colombier 		break;
4378ccd4a63SDavid du Colombier 
4388ccd4a63SDavid du Colombier 	case WM_DESTROY:
4398ccd4a63SDavid du Colombier 		PostQuitMessage(0);
4408ccd4a63SDavid du Colombier 		break;
4418ccd4a63SDavid du Colombier 
4428ccd4a63SDavid du Colombier 	case WM_PALETTECHANGED:
4438ccd4a63SDavid du Colombier 		if((HWND)wparam == hwnd)
4448ccd4a63SDavid du Colombier 			break;
4458ccd4a63SDavid du Colombier 	/* fall through */
4468ccd4a63SDavid du Colombier 	case WM_QUERYNEWPALETTE:
4478ccd4a63SDavid du Colombier 		hdc = GetDC(hwnd);
4488ccd4a63SDavid du Colombier 		SelectPalette(hdc, palette, 0);
4498ccd4a63SDavid du Colombier 		if(RealizePalette(hdc) != 0)
4508ccd4a63SDavid du Colombier 			InvalidateRect(hwnd, nil, 0);
4518ccd4a63SDavid du Colombier 		ReleaseDC(hwnd, hdc);
4528ccd4a63SDavid du Colombier 		break;
4538ccd4a63SDavid du Colombier 
4548ccd4a63SDavid du Colombier 	case WM_PAINT:
4558ccd4a63SDavid du Colombier 		hdc = BeginPaint(hwnd, &paint);
4568ccd4a63SDavid du Colombier 		r.min.x = paint.rcPaint.left;
4578ccd4a63SDavid du Colombier 		r.min.y = paint.rcPaint.top;
4588ccd4a63SDavid du Colombier 		r.max.x = paint.rcPaint.right;
4598ccd4a63SDavid du Colombier 		r.max.y = paint.rcPaint.bottom;
4608ccd4a63SDavid du Colombier 		flushmemscreen(r);
4618ccd4a63SDavid du Colombier 		EndPaint(hwnd, &paint);
4628ccd4a63SDavid du Colombier 		break;
4638ccd4a63SDavid du Colombier 	case WM_COMMAND:
4648ccd4a63SDavid du Colombier 	case WM_SETFOCUS:
4658ccd4a63SDavid du Colombier 	case WM_DEVMODECHANGE:
4668ccd4a63SDavid du Colombier 	case WM_WININICHANGE:
4678ccd4a63SDavid du Colombier 	case WM_INITMENU:
4688ccd4a63SDavid du Colombier 	default:
4698ccd4a63SDavid du Colombier 		return DefWindowProc(hwnd, msg, wparam, lparam);
4708ccd4a63SDavid du Colombier 	}
4718ccd4a63SDavid du Colombier 	return 0;
4728ccd4a63SDavid du Colombier }
4738ccd4a63SDavid du Colombier 
4748ccd4a63SDavid du Colombier void
mouseset(Point xy)4758ccd4a63SDavid du Colombier mouseset(Point xy)
4768ccd4a63SDavid du Colombier {
4778ccd4a63SDavid du Colombier 	POINT pt;
4788ccd4a63SDavid du Colombier 
4798ccd4a63SDavid du Colombier 	pt.x = xy.x;
4808ccd4a63SDavid du Colombier 	pt.y = xy.y;
4818ccd4a63SDavid du Colombier 	MapWindowPoints(window, 0, &pt, 1);
4828ccd4a63SDavid du Colombier 	SetCursorPos(pt.x, pt.y);
4838ccd4a63SDavid du Colombier }
4848ccd4a63SDavid du Colombier 
4858ccd4a63SDavid du Colombier void
setcursor(void)4868ccd4a63SDavid du Colombier setcursor(void)
4878ccd4a63SDavid du Colombier {
4888ccd4a63SDavid du Colombier 	HCURSOR nh;
4898ccd4a63SDavid du Colombier 	int x, y, h, w;
4908ccd4a63SDavid du Colombier 	uchar *sp, *cp;
4918ccd4a63SDavid du Colombier 	uchar *and, *xor;
4928ccd4a63SDavid du Colombier 
4938ccd4a63SDavid du Colombier 	h = GetSystemMetrics(SM_CYCURSOR);
4948ccd4a63SDavid du Colombier 	w = (GetSystemMetrics(SM_CXCURSOR)+7)/8;
4958ccd4a63SDavid du Colombier 
4968ccd4a63SDavid du Colombier 	and = mallocz(h*w, 1);
4978ccd4a63SDavid du Colombier 	memset(and, 0xff, h*w);
4988ccd4a63SDavid du Colombier 	xor = mallocz(h*w, 1);
4998ccd4a63SDavid du Colombier 
5008ccd4a63SDavid du Colombier 	lock(&cursor.lk);
5018ccd4a63SDavid du Colombier 	for(y=0,sp=cursor.set,cp=cursor.clr; y<16; y++) {
5028ccd4a63SDavid du Colombier 		for(x=0; x<2; x++) {
5038ccd4a63SDavid du Colombier 			and[y*w+x] = ~(*sp|*cp);
5048ccd4a63SDavid du Colombier 			xor[y*w+x] = ~*sp & *cp;
5058ccd4a63SDavid du Colombier 			cp++;
5068ccd4a63SDavid du Colombier 			sp++;
5078ccd4a63SDavid du Colombier 		}
5088ccd4a63SDavid du Colombier 	}
5098ccd4a63SDavid du Colombier 	nh = CreateCursor(inst, -cursor.offset.x, -cursor.offset.y,
5108ccd4a63SDavid du Colombier 			GetSystemMetrics(SM_CXCURSOR), h,
5118ccd4a63SDavid du Colombier 			and, xor);
5128ccd4a63SDavid du Colombier 	if(nh != NULL) {
5138ccd4a63SDavid du Colombier 		SetCursor(nh);
5148ccd4a63SDavid du Colombier 		if(hcursor != NULL)
5158ccd4a63SDavid du Colombier 			DestroyCursor(hcursor);
5168ccd4a63SDavid du Colombier 		hcursor = nh;
5178ccd4a63SDavid du Colombier 	}
5188ccd4a63SDavid du Colombier 	unlock(&cursor.lk);
5198ccd4a63SDavid du Colombier 
5208ccd4a63SDavid du Colombier 	free(and);
5218ccd4a63SDavid du Colombier 	free(xor);
5228ccd4a63SDavid du Colombier 
5238ccd4a63SDavid du Colombier 	PostMessage(window, WM_SETCURSOR, (int)window, 0);
5248ccd4a63SDavid du Colombier }
5258ccd4a63SDavid du Colombier 
5268ccd4a63SDavid du Colombier void
cursorarrow(void)5278ccd4a63SDavid du Colombier cursorarrow(void)
5288ccd4a63SDavid du Colombier {
5298ccd4a63SDavid du Colombier 	if(hcursor != 0) {
5308ccd4a63SDavid du Colombier 		DestroyCursor(hcursor);
5318ccd4a63SDavid du Colombier 		hcursor = 0;
5328ccd4a63SDavid du Colombier 	}
5338ccd4a63SDavid du Colombier 	SetCursor(LoadCursor(0, IDC_ARROW));
5348ccd4a63SDavid du Colombier 	PostMessage(window, WM_SETCURSOR, (int)window, 0);
5358ccd4a63SDavid du Colombier }
5368ccd4a63SDavid du Colombier 
5378ccd4a63SDavid du Colombier 
5388ccd4a63SDavid du Colombier void
setcolor(ulong index,ulong red,ulong green,ulong blue)5398ccd4a63SDavid du Colombier setcolor(ulong index, ulong red, ulong green, ulong blue)
5408ccd4a63SDavid du Colombier {
5418ccd4a63SDavid du Colombier }
5428ccd4a63SDavid du Colombier 
5438ccd4a63SDavid du Colombier 
5448ccd4a63SDavid du Colombier uchar*
clipreadunicode(HANDLE h)5458ccd4a63SDavid du Colombier clipreadunicode(HANDLE h)
5468ccd4a63SDavid du Colombier {
5478ccd4a63SDavid du Colombier 	Rune *p;
5488ccd4a63SDavid du Colombier 	int n;
5498ccd4a63SDavid du Colombier 	uchar *q;
5508ccd4a63SDavid du Colombier 
5518ccd4a63SDavid du Colombier 	p = GlobalLock(h);
5528ccd4a63SDavid du Colombier 	n = wstrutflen(p)+1;
5538ccd4a63SDavid du Colombier 	q = malloc(n);
5548ccd4a63SDavid du Colombier 	wstrtoutf(q, p, n);
5558ccd4a63SDavid du Colombier 	GlobalUnlock(h);
5568ccd4a63SDavid du Colombier 
5578ccd4a63SDavid du Colombier 	return q;
5588ccd4a63SDavid du Colombier }
5598ccd4a63SDavid du Colombier 
5608ccd4a63SDavid du Colombier uchar *
clipreadutf(HANDLE h)5618ccd4a63SDavid du Colombier clipreadutf(HANDLE h)
5628ccd4a63SDavid du Colombier {
5638ccd4a63SDavid du Colombier 	uchar *p;
5648ccd4a63SDavid du Colombier 
5658ccd4a63SDavid du Colombier 	p = GlobalLock(h);
5668ccd4a63SDavid du Colombier 	p = strdup(p);
5678ccd4a63SDavid du Colombier 	GlobalUnlock(h);
5688ccd4a63SDavid du Colombier 
5698ccd4a63SDavid du Colombier 	return p;
5708ccd4a63SDavid du Colombier }
5718ccd4a63SDavid du Colombier 
5728ccd4a63SDavid du Colombier char*
clipread(void)5738ccd4a63SDavid du Colombier clipread(void)
5748ccd4a63SDavid du Colombier {
5758ccd4a63SDavid du Colombier 	HANDLE h;
5768ccd4a63SDavid du Colombier 	uchar *p;
5778ccd4a63SDavid du Colombier 
5788ccd4a63SDavid du Colombier 	if(!OpenClipboard(window)) {
5798ccd4a63SDavid du Colombier 		oserror();
5808ccd4a63SDavid du Colombier 		return strdup("");
5818ccd4a63SDavid du Colombier 	}
5828ccd4a63SDavid du Colombier 
5838ccd4a63SDavid du Colombier 	if((h = GetClipboardData(CF_UNICODETEXT)))
5848ccd4a63SDavid du Colombier 		p = clipreadunicode(h);
5858ccd4a63SDavid du Colombier 	else if((h = GetClipboardData(CF_TEXT)))
5868ccd4a63SDavid du Colombier 		p = clipreadutf(h);
5878ccd4a63SDavid du Colombier 	else {
5888ccd4a63SDavid du Colombier 		oserror();
5898ccd4a63SDavid du Colombier 		p = strdup("");
5908ccd4a63SDavid du Colombier 	}
5918ccd4a63SDavid du Colombier 
5928ccd4a63SDavid du Colombier 	CloseClipboard();
5938ccd4a63SDavid du Colombier 	return p;
5948ccd4a63SDavid du Colombier }
5958ccd4a63SDavid du Colombier 
5968ccd4a63SDavid du Colombier int
clipwrite(char * buf)5978ccd4a63SDavid du Colombier clipwrite(char *buf)
5988ccd4a63SDavid du Colombier {
5998ccd4a63SDavid du Colombier 	HANDLE h;
6008ccd4a63SDavid du Colombier 	char *p, *e;
6018ccd4a63SDavid du Colombier 	Rune *rp;
6028ccd4a63SDavid du Colombier 	int n = strlen(buf);
6038ccd4a63SDavid du Colombier 
6048ccd4a63SDavid du Colombier 	if(!OpenClipboard(window)) {
6058ccd4a63SDavid du Colombier 		oserror();
6068ccd4a63SDavid du Colombier 		return -1;
6078ccd4a63SDavid du Colombier 	}
6088ccd4a63SDavid du Colombier 
6098ccd4a63SDavid du Colombier 	if(!EmptyClipboard()) {
6108ccd4a63SDavid du Colombier 		oserror();
6118ccd4a63SDavid du Colombier 		CloseClipboard();
6128ccd4a63SDavid du Colombier 		return -1;
6138ccd4a63SDavid du Colombier 	}
6148ccd4a63SDavid du Colombier 
6158ccd4a63SDavid du Colombier 	h = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, (n+1)*sizeof(Rune));
6168ccd4a63SDavid du Colombier 	if(h == NULL)
6178ccd4a63SDavid du Colombier 		panic("out of memory");
6188ccd4a63SDavid du Colombier 	rp = GlobalLock(h);
6198ccd4a63SDavid du Colombier 	p = buf;
6208ccd4a63SDavid du Colombier 	e = p+n;
6218ccd4a63SDavid du Colombier 	while(p<e)
6228ccd4a63SDavid du Colombier 		p += chartorune(rp++, p);
6238ccd4a63SDavid du Colombier 	*rp = 0;
6248ccd4a63SDavid du Colombier 	GlobalUnlock(h);
6258ccd4a63SDavid du Colombier 
6268ccd4a63SDavid du Colombier 	SetClipboardData(CF_UNICODETEXT, h);
6278ccd4a63SDavid du Colombier 
6288ccd4a63SDavid du Colombier 	h = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, n+1);
6298ccd4a63SDavid du Colombier 	if(h == NULL)
6308ccd4a63SDavid du Colombier 		panic("out of memory");
6318ccd4a63SDavid du Colombier 	p = GlobalLock(h);
6328ccd4a63SDavid du Colombier 	memcpy(p, buf, n);
6338ccd4a63SDavid du Colombier 	p[n] = 0;
6348ccd4a63SDavid du Colombier 	GlobalUnlock(h);
6358ccd4a63SDavid du Colombier 
6368ccd4a63SDavid du Colombier 	SetClipboardData(CF_TEXT, h);
6378ccd4a63SDavid du Colombier 
6388ccd4a63SDavid du Colombier 	CloseClipboard();
6398ccd4a63SDavid du Colombier 	return n;
6408ccd4a63SDavid du Colombier }
6418ccd4a63SDavid du Colombier 
6428ccd4a63SDavid du Colombier int
atlocalconsole(void)6438ccd4a63SDavid du Colombier atlocalconsole(void)
6448ccd4a63SDavid du Colombier {
6458ccd4a63SDavid du Colombier 	return 1;
6468ccd4a63SDavid du Colombier }
647