screen-win.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. #include <windows.h>
  2. #undef Rectangle
  3. #define Rectangle _Rectangle
  4. #include "lib9.h"
  5. #include "sys.h"
  6. #include "error.h"
  7. #include "libdraw/draw.h"
  8. #include "libmemdraw/memdraw.h"
  9. #include "screen.h"
  10. #include "keyboard.h"
  11. Memimage *gscreen;
  12. Screeninfo screen;
  13. extern int mousequeue;
  14. extern int depth;
  15. static HINSTANCE inst;
  16. static HWND window;
  17. static HPALETTE palette;
  18. static LOGPALETTE *logpal;
  19. static Lock gdilock;
  20. static BITMAPINFO *bmi;
  21. static HCURSOR hcursor;
  22. static void winproc(void *);
  23. static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
  24. static void paletteinit(void);
  25. static void bmiinit(void);
  26. static void screenload2(Rectangle r, int ldepth, uchar *p, Point pt, int step);
  27. static int ready;
  28. static Rendez rend;
  29. Point ZP;
  30. static
  31. isready(void*a)
  32. {
  33. return ready;
  34. }
  35. void
  36. screeninit(void)
  37. {
  38. int fmt;
  39. int dx, dy;
  40. memimageinit();
  41. if(depth == 0)
  42. depth = GetDeviceCaps(GetDC(NULL), BITSPIXEL);
  43. switch(depth){
  44. case 32:
  45. screen.dibtype = DIB_RGB_COLORS;
  46. screen.depth = 32;
  47. fmt = XRGB32;
  48. break;
  49. case 24:
  50. screen.dibtype = DIB_RGB_COLORS;
  51. screen.depth = 24;
  52. fmt = RGB24;
  53. break;
  54. case 16:
  55. screen.dibtype = DIB_RGB_COLORS;
  56. screen.depth = 16;
  57. fmt = RGB15; /* [sic] */
  58. break;
  59. case 8:
  60. default:
  61. screen.dibtype = DIB_PAL_COLORS;
  62. screen.depth = 8;
  63. depth = 8;
  64. fmt = CMAP8;
  65. break;
  66. }
  67. dx = GetDeviceCaps(GetDC(NULL), HORZRES);
  68. dy = GetDeviceCaps(GetDC(NULL), VERTRES);
  69. gscreen = allocmemimage(Rect(0,0,dx,dy), fmt);
  70. thread("winscreen", winproc, 0);
  71. rendsleep(&rend, isready, 0);
  72. }
  73. uchar*
  74. attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X)
  75. {
  76. *r = gscreen->r;
  77. *chan = gscreen->chan;
  78. *depth = gscreen->depth;
  79. *width = gscreen->width;
  80. *softscreen = 1;
  81. return gscreen->data->bdata;
  82. }
  83. void
  84. flushmemscreen(Rectangle r)
  85. {
  86. screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP,
  87. gscreen->width*sizeof(ulong));
  88. // Sleep(100);
  89. }
  90. void
  91. screenload(Rectangle r, int depth, uchar *p, Point pt, int step)
  92. {
  93. int dx, dy, delx;
  94. HDC hdc;
  95. RECT winr;
  96. if(depth != gscreen->depth)
  97. panic("screenload: bad ldepth");
  98. /*
  99. * Sometimes we do get rectangles that are off the
  100. * screen to the negative axes, for example, when
  101. * dragging around a window border in a Move operation.
  102. */
  103. if(rectclip(&r, gscreen->r) == 0)
  104. return;
  105. if(step&3 != 0 || ((pt.x*depth)%32) != 0 || (ulong)p&3 != 0)
  106. panic("screenload: bad params %d %d %ux", step, pt.x, p);
  107. dx = r.max.x - r.min.x;
  108. dy = r.max.y - r.min.y;
  109. if(dx <= 0 || dy <= 0)
  110. return;
  111. if(depth == 24)
  112. delx = r.min.x % 4;
  113. else
  114. delx = r.min.x & (31/depth);
  115. p += (r.min.y-pt.y)*step;
  116. p += ((r.min.x-delx-pt.x)*depth)>>3;
  117. if(GetWindowRect(window, &winr)==0)
  118. return;
  119. if(rectclip(&r, Rect(0, 0, winr.right-winr.left, winr.bottom-winr.top))==0)
  120. return;
  121. lock(&gdilock);
  122. hdc = GetDC(window);
  123. SelectPalette(hdc, palette, 0);
  124. RealizePalette(hdc);
  125. //FillRect(hdc,(void*)&r, GetStockObject(BLACK_BRUSH));
  126. //GdiFlush();
  127. //Sleep(100);
  128. bmi->bmiHeader.biWidth = (step*8)/depth;
  129. bmi->bmiHeader.biHeight = -dy; /* - => origin upper left */
  130. StretchDIBits(hdc, r.min.x, r.min.y, dx, dy,
  131. delx, 0, dx, dy, p, bmi, screen.dibtype, SRCCOPY);
  132. ReleaseDC(window, hdc);
  133. GdiFlush();
  134. unlock(&gdilock);
  135. }
  136. static void
  137. winproc(void *a)
  138. {
  139. WNDCLASS wc;
  140. MSG msg;
  141. inst = GetModuleHandle(NULL);
  142. paletteinit();
  143. bmiinit();
  144. terminit();
  145. wc.style = 0;
  146. wc.lpfnWndProc = WindowProc;
  147. wc.cbClsExtra = 0;
  148. wc.cbWndExtra = 0;
  149. wc.hInstance = inst;
  150. wc.hIcon = LoadIcon(inst, NULL);
  151. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  152. wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  153. wc.lpszMenuName = 0;
  154. wc.lpszClassName = "9pmgraphics";
  155. RegisterClass(&wc);
  156. window = CreateWindowEx(
  157. 0, /* extended style */
  158. "9pmgraphics", /* class */
  159. "drawterm screen", /* caption */
  160. WS_OVERLAPPEDWINDOW, /* style */
  161. CW_USEDEFAULT, /* init. x pos */
  162. CW_USEDEFAULT, /* init. y pos */
  163. CW_USEDEFAULT, /* init. x size */
  164. CW_USEDEFAULT, /* init. y size */
  165. NULL, /* parent window (actually owner window for overlapped)*/
  166. NULL, /* menu handle */
  167. inst, /* program handle */
  168. NULL /* create parms */
  169. );
  170. if(window == nil)
  171. panic("can't make window\n");
  172. ShowWindow(window, SW_SHOWDEFAULT);
  173. UpdateWindow(window);
  174. ready = 1;
  175. rendwakeup(&rend);
  176. screen.reshaped = 0;
  177. while(GetMessage(&msg, NULL, 0, 0)) {
  178. TranslateMessage(&msg);
  179. DispatchMessage(&msg);
  180. }
  181. // MessageBox(0, "winproc", "exits", MB_OK);
  182. ExitProcess(0);
  183. }
  184. int
  185. col(int v, int n)
  186. {
  187. int i, c;
  188. c = 0;
  189. for(i = 0; i < 8; i += n)
  190. c |= v << (16-(n+i));
  191. return c >> 8;
  192. }
  193. void
  194. paletteinit(void)
  195. {
  196. PALETTEENTRY *pal;
  197. int r, g, b, cr, cg, cb, v;
  198. int num, den;
  199. int i, j;
  200. logpal = mallocz(sizeof(LOGPALETTE) + 256*sizeof(PALETTEENTRY));
  201. if(logpal == nil)
  202. panic("out of memory");
  203. logpal->palVersion = 0x300;
  204. logpal->palNumEntries = 256;
  205. pal = logpal->palPalEntry;
  206. for(r=0,i=0; r<4; r++) {
  207. for(v=0; v<4; v++,i+=16){
  208. for(g=0,j=v-r; g<4; g++) {
  209. for(b=0; b<4; b++,j++){
  210. den=r;
  211. if(g>den)
  212. den=g;
  213. if(b>den)
  214. den=b;
  215. /* divide check -- pick grey shades */
  216. if(den==0)
  217. cr=cg=cb=v*17;
  218. else{
  219. num=17*(4*den+v);
  220. cr=r*num/den;
  221. cg=g*num/den;
  222. cb=b*num/den;
  223. }
  224. pal[i+(j&15)].peRed = cr;
  225. pal[i+(j&15)].peGreen = cg;
  226. pal[i+(j&15)].peBlue = cb;
  227. pal[i+(j&15)].peFlags = 0;
  228. }
  229. }
  230. }
  231. }
  232. palette = CreatePalette(logpal);
  233. }
  234. void
  235. getcolor(ulong i, ulong *r, ulong *g, ulong *b)
  236. {
  237. PALETTEENTRY *pal;
  238. pal = logpal->palPalEntry;
  239. *r = pal[i].peRed;
  240. *g = pal[i].peGreen;
  241. *b = pal[i].peBlue;
  242. }
  243. void
  244. bmiinit(void)
  245. {
  246. ushort *p;
  247. int i;
  248. bmi = mallocz(sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD));
  249. if(bmi == 0)
  250. panic("out of memory");
  251. bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  252. bmi->bmiHeader.biWidth = 0;
  253. bmi->bmiHeader.biHeight = 0; /* - => origin upper left */
  254. bmi->bmiHeader.biPlanes = 1;
  255. bmi->bmiHeader.biBitCount = depth;
  256. bmi->bmiHeader.biCompression = BI_RGB;
  257. bmi->bmiHeader.biSizeImage = 0;
  258. bmi->bmiHeader.biXPelsPerMeter = 0;
  259. bmi->bmiHeader.biYPelsPerMeter = 0;
  260. bmi->bmiHeader.biClrUsed = 0;
  261. bmi->bmiHeader.biClrImportant = 0; /* number of important colors: 0 means all */
  262. p = (ushort*)bmi->bmiColors;
  263. for(i = 0; i < 256; i++)
  264. p[i] = i;
  265. }
  266. LRESULT CALLBACK
  267. WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
  268. {
  269. PAINTSTRUCT paint;
  270. HDC hdc;
  271. LONG x, y, b;
  272. int i;
  273. Rectangle r;
  274. switch(msg) {
  275. case WM_CREATE:
  276. break;
  277. case WM_SETCURSOR:
  278. /* User set */
  279. if(hcursor != NULL) {
  280. SetCursor(hcursor);
  281. return 1;
  282. }
  283. return DefWindowProc(hwnd, msg, wparam, lparam);
  284. case WM_MOUSEMOVE:
  285. case WM_LBUTTONUP:
  286. case WM_MBUTTONUP:
  287. case WM_RBUTTONUP:
  288. case WM_LBUTTONDOWN:
  289. case WM_MBUTTONDOWN:
  290. case WM_RBUTTONDOWN:
  291. x = LOWORD(lparam);
  292. y = HIWORD(lparam);
  293. b = 0;
  294. if(wparam & MK_LBUTTON)
  295. b = 1;
  296. if(wparam & MK_MBUTTON)
  297. b |= 2;
  298. if(wparam & MK_RBUTTON) {
  299. if(wparam & MK_SHIFT)
  300. b |= 2;
  301. else
  302. b |= 4;
  303. }
  304. lock(&mouse.lk);
  305. i = mouse.wi;
  306. if(mousequeue) {
  307. if(i == mouse.ri || mouse.lastb != b || mouse.trans) {
  308. mouse.wi = (i+1)%Mousequeue;
  309. if(mouse.wi == mouse.ri)
  310. mouse.ri = (mouse.ri+1)%Mousequeue;
  311. mouse.trans = mouse.lastb != b;
  312. } else {
  313. i = (i-1+Mousequeue)%Mousequeue;
  314. }
  315. } else {
  316. mouse.wi = (i+1)%Mousequeue;
  317. mouse.ri = i;
  318. }
  319. mouse.queue[i].xy.x = x;
  320. mouse.queue[i].xy.y = y;
  321. mouse.queue[i].buttons = b;
  322. mouse.queue[i].msec = ticks();
  323. mouse.lastb = b;
  324. unlock(&mouse.lk);
  325. rendwakeup(&mouse.r);
  326. break;
  327. case WM_CHAR:
  328. /* repeat count is lparam & 0xf */
  329. switch(wparam){
  330. case '\n':
  331. wparam = '\r';
  332. break;
  333. case '\r':
  334. wparam = '\n';
  335. break;
  336. }
  337. kbdputc(wparam);
  338. break;
  339. case WM_SYSKEYUP:
  340. break;
  341. case WM_SYSKEYDOWN:
  342. case WM_KEYDOWN:
  343. switch(wparam) {
  344. case VK_MENU:
  345. kbdputc(Kalt);
  346. break;
  347. case VK_INSERT:
  348. kbdputc(Kins);
  349. break;
  350. case VK_DELETE:
  351. kbdputc(Kdel);
  352. break;
  353. case VK_UP:
  354. kbdputc(Kup);
  355. break;
  356. case VK_DOWN:
  357. kbdputc(Kdown);
  358. break;
  359. case VK_LEFT:
  360. kbdputc(Kleft);
  361. break;
  362. case VK_RIGHT:
  363. kbdputc(Kright);
  364. break;
  365. }
  366. break;
  367. case WM_CLOSE:
  368. DestroyWindow(hwnd);
  369. break;
  370. case WM_DESTROY:
  371. PostQuitMessage(0);
  372. break;
  373. case WM_PALETTECHANGED:
  374. if((HWND)wparam == hwnd)
  375. break;
  376. /* fall through */
  377. case WM_QUERYNEWPALETTE:
  378. hdc = GetDC(hwnd);
  379. SelectPalette(hdc, palette, 0);
  380. if(RealizePalette(hdc) != 0)
  381. InvalidateRect(hwnd, nil, 0);
  382. ReleaseDC(hwnd, hdc);
  383. break;
  384. case WM_PAINT:
  385. hdc = BeginPaint(hwnd, &paint);
  386. r.min.x = paint.rcPaint.left;
  387. r.min.y = paint.rcPaint.top;
  388. r.max.x = paint.rcPaint.right;
  389. r.max.y = paint.rcPaint.bottom;
  390. flushmemscreen(r);
  391. EndPaint(hwnd, &paint);
  392. break;
  393. case WM_COMMAND:
  394. case WM_SETFOCUS:
  395. case WM_DEVMODECHANGE:
  396. case WM_WININICHANGE:
  397. case WM_INITMENU:
  398. default:
  399. return DefWindowProc(hwnd, msg, wparam, lparam);
  400. }
  401. return 0;
  402. }
  403. void
  404. mouseset(Point xy)
  405. {
  406. POINT pt;
  407. pt.x = xy.x;
  408. pt.y = xy.y;
  409. MapWindowPoints(window, 0, &pt, 1);
  410. SetCursorPos(pt.x, pt.y);
  411. }
  412. void
  413. setcursor(void)
  414. {
  415. HCURSOR nh;
  416. int x, y, h, w;
  417. uchar *sp, *cp;
  418. uchar *and, *xor;
  419. h = GetSystemMetrics(SM_CYCURSOR);
  420. w = (GetSystemMetrics(SM_CXCURSOR)+7)/8;
  421. and = mallocz(h*w);
  422. memset(and, 0xff, h*w);
  423. xor = mallocz(h*w);
  424. lock(&cursor.lk);
  425. for(y=0,sp=cursor.set,cp=cursor.clr; y<16; y++) {
  426. for(x=0; x<2; x++) {
  427. and[y*w+x] = ~(*sp|*cp);
  428. xor[y*w+x] = ~*sp & *cp;
  429. cp++;
  430. sp++;
  431. }
  432. }
  433. nh = CreateCursor(inst, -cursor.offset.x, -cursor.offset.y,
  434. GetSystemMetrics(SM_CXCURSOR), h,
  435. and, xor);
  436. if(nh != NULL) {
  437. SetCursor(nh);
  438. if(hcursor != NULL)
  439. DestroyCursor(hcursor);
  440. hcursor = nh;
  441. }
  442. unlock(&cursor.lk);
  443. free(and);
  444. free(xor);
  445. PostMessage(window, WM_SETCURSOR, (int)window, 0);
  446. }
  447. void
  448. cursorarrow(void)
  449. {
  450. if(hcursor != 0) {
  451. DestroyCursor(hcursor);
  452. hcursor = 0;
  453. }
  454. SetCursor(LoadCursor(0, IDC_ARROW));
  455. PostMessage(window, WM_SETCURSOR, (int)window, 0);
  456. }
  457. void
  458. setcolor(ulong index, ulong red, ulong green, ulong blue)
  459. {
  460. }
  461. uchar*
  462. clipreadunicode(HANDLE h)
  463. {
  464. Rune *p;
  465. int n;
  466. uchar *q;
  467. p = GlobalLock(h);
  468. n = wstrutflen(p)+1;
  469. q = malloc(n);
  470. wstrtoutf(q, p, n);
  471. GlobalUnlock(h);
  472. return q;
  473. }
  474. uchar *
  475. clipreadutf(HANDLE h)
  476. {
  477. uchar *p;
  478. p = GlobalLock(h);
  479. p = strdup(p);
  480. GlobalUnlock(h);
  481. return p;
  482. }
  483. uchar*
  484. clipread()
  485. {
  486. HANDLE h;
  487. uchar *p;
  488. if(!OpenClipboard(window)) {
  489. oserror();
  490. return strdup("");
  491. }
  492. if(h = GetClipboardData(CF_UNICODETEXT))
  493. p = clipreadunicode(h);
  494. else if(h = GetClipboardData(CF_TEXT))
  495. p = clipreadutf(h);
  496. else {
  497. oserror();
  498. p = strdup("");
  499. }
  500. CloseClipboard();
  501. return p;
  502. }
  503. int
  504. clipwrite(uchar *buf, int n)
  505. {
  506. HANDLE h;
  507. char *p, *e;
  508. Rune *rp;
  509. if(!OpenClipboard(window)) {
  510. oserror();
  511. return -1;
  512. }
  513. if(!EmptyClipboard()) {
  514. oserror();
  515. CloseClipboard();
  516. return -1;
  517. }
  518. h = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, (n+1)*sizeof(Rune));
  519. if(h == NULL)
  520. panic("out of memory");
  521. rp = GlobalLock(h);
  522. p = (char*)buf;
  523. e = p+n;
  524. while(p<e)
  525. p += chartorune(rp++, p);
  526. *rp = 0;
  527. GlobalUnlock(h);
  528. SetClipboardData(CF_UNICODETEXT, h);
  529. h = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, n+1);
  530. if(h == NULL)
  531. panic("out of memory");
  532. p = GlobalLock(h);
  533. memcpy(p, buf, n);
  534. p[n] = 0;
  535. GlobalUnlock(h);
  536. SetClipboardData(CF_TEXT, h);
  537. CloseClipboard();
  538. return n;
  539. }
  540. int
  541. atlocalconsole(void)
  542. {
  543. return 1;
  544. }