Fix crash in new on_close handler.
[mp-5.x.git] / mpv_win32.c
blob3fe7ebbfd1f038b37c4bf8e685e41ec05940b285
1 /*
3 Minimum Profit - Programmer Text Editor
5 Win32 driver.
7 Copyright (C) 1991-2010 Angel Ortega <angel@triptico.com>
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 http://www.triptico.com
27 #include "config.h"
29 #ifdef CONFOPT_WIN32
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
35 #include <windows.h>
36 #include <commctrl.h>
37 #include <shlobj.h>
39 #include "mpdm.h"
40 #include "mpsl.h"
42 #include "mp.h"
44 /** data **/
46 /* the instance */
47 HINSTANCE hinst;
49 /* the windows */
50 HWND hwnd = NULL;
51 HWND hwtabs = NULL;
52 HWND hwstatus = NULL;
54 /* font handlers and metrics */
55 HFONT font_normal = NULL;
56 HFONT font_underline = NULL;
57 int font_width = 0;
58 int font_height = 0;
60 /* height of the tab set */
61 int tab_height = 28;
63 /* height of the status bar */
64 int status_height = 16;
66 int is_wm_keydown = 0;
68 /* colors */
69 static COLORREF *inks = NULL;
70 static COLORREF *papers = NULL;
71 int *underlines = NULL;
72 HBRUSH bgbrush;
74 /* code for the 'normal' attribute */
75 static int normal_attr = 0;
77 /* the menu */
78 static HMENU menu = NULL;
80 /* mp.drv.form() controls */
82 static mpdm_t form_args = NULL;
83 static mpdm_t form_values = NULL;
85 /* mouse down flag */
86 static int mouse_down = 0;
88 /* timer function */
89 static mpdm_t timer_func = NULL;
91 /** code **/
93 static void update_window_size(void)
94 /* updates the viewport size in characters */
96 RECT rect;
97 int tx, ty;
98 mpdm_t v;
100 /* no font information? go */
101 if (font_width == 0 || font_height == 0)
102 return;
104 GetClientRect(hwnd, &rect);
106 /* calculate the size in chars */
107 tx = ((rect.right - rect.left) / font_width) + 1;
108 ty = (rect.bottom - rect.top - tab_height) / font_height;
110 /* store the 'window' size */
111 v = mpdm_hget_s(mp, L"window");
112 mpdm_hset_s(v, L"tx", MPDM_I(tx));
113 mpdm_hset_s(v, L"ty", MPDM_I(ty));
117 static void build_fonts(HDC hdc)
118 /* build the fonts */
120 TEXTMETRIC tm;
121 int n;
122 int font_size = 10;
123 char *font_face = "Lucida Console";
124 mpdm_t v = NULL;
125 mpdm_t c;
127 if (font_normal != NULL) {
128 SelectObject(hdc, GetStockObject(SYSTEM_FONT));
129 DeleteObject(font_normal);
132 /* get current configuration */
133 if ((c = mpdm_hget_s(mp, L"config")) != NULL) {
134 if ((v = mpdm_hget_s(c, L"font_size")) != NULL)
135 font_size = mpdm_ival(v);
136 else
137 mpdm_hset_s(c, L"font_size", MPDM_I(font_size));
139 if ((v = mpdm_hget_s(c, L"font_face")) != NULL) {
140 v = mpdm_ref(MPDM_2MBS(v->data));
141 font_face = (char *) v->data;
143 else
144 mpdm_hset_s(c, L"font_face", MPDM_MBS(font_face));
147 /* create fonts */
148 n = -MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72);
150 font_normal = CreateFont(n, 0, 0, 0, 0, 0, 0,
151 0, 0, 0, 0, 0, 0, font_face);
153 font_underline = CreateFont(n, 0, 0, 0, 0, 0, 1,
154 0, 0, 0, 0, 0, 0, font_face);
156 SelectObject(hdc, font_normal);
157 GetTextMetrics(hdc, &tm);
159 /* store sizes */
160 font_height = tm.tmHeight;
161 font_width = tm.tmAveCharWidth;
163 update_window_size();
165 mpdm_unref(v);
169 static void build_colors(void)
170 /* builds the colors */
172 mpdm_t colors;
173 mpdm_t l;
174 mpdm_t c;
175 int n, s;
177 /* gets the color definitions and attribute names */
178 colors = mpdm_hget_s(mp, L"colors");
179 l = mpdm_ref(mpdm_keys(colors));
180 s = mpdm_size(l);
182 /* redim the structures */
183 inks = realloc(inks, sizeof(COLORREF) * s);
184 papers = realloc(papers, sizeof(COLORREF) * s);
185 underlines = realloc(underlines, sizeof(int) * s);
187 /* loop the colors */
188 for (n = 0; n < s && (c = mpdm_aget(l, n)) != NULL; n++) {
189 mpdm_t d = mpdm_hget(colors, c);
190 mpdm_t v = mpdm_hget_s(d, L"gui");
191 int m;
193 /* store the 'normal' attribute */
194 if (wcscmp(mpdm_string(c), L"normal") == 0)
195 normal_attr = n;
197 /* store the attr */
198 mpdm_hset_s(d, L"attr", MPDM_I(n));
200 m = mpdm_ival(mpdm_aget(v, 0));
201 inks[n] = ((m & 0x000000ff) << 16) |
202 ((m & 0x0000ff00)) | ((m & 0x00ff0000) >> 16);
203 m = mpdm_ival(mpdm_aget(v, 1));
204 papers[n] = ((m & 0x000000ff) << 16) |
205 ((m & 0x0000ff00)) | ((m & 0x00ff0000) >> 16);
207 /* flags */
208 v = mpdm_hget_s(d, L"flags");
210 underlines[n] = mpdm_seek_s(v, L"underline", 1) != -1 ? 1 : 0;
212 if (mpdm_seek_s(v, L"reverse", 1) != -1) {
213 COLORREF t;
215 t = inks[n];
216 inks[n] = papers[n];
217 papers[n] = t;
221 mpdm_unref(l);
223 /* create the background brush */
224 bgbrush = CreateSolidBrush(papers[normal_attr]);
228 static void build_menu(void)
229 /* builds the menu */
231 int n;
232 mpdm_t m;
233 int win32_menu_id = 1000;
235 /* gets the current menu */
236 if ((m = mpdm_hget_s(mp, L"menu")) == NULL)
237 return;
239 if (menu != NULL)
240 DestroyMenu(menu);
242 menu = CreateMenu();
244 for (n = 0; n < mpdm_size(m); n++) {
245 char *ptr;
246 mpdm_t mi, v, l;
247 int i;
248 HMENU submenu = CreatePopupMenu();
250 /* get the label and the items */
251 mi = mpdm_aget(m, n);
252 v = mpdm_gettext(mpdm_aget(mi, 0));
253 l = mpdm_aget(mi, 1);
255 /* create the submenus */
256 for (i = 0; i < mpdm_size(l); i++) {
257 /* get the action */
258 mpdm_t v = mpdm_aget(l, i);
260 /* if the action is a separator... */
261 if (*((wchar_t *) v->data) == L'-')
262 AppendMenu(submenu, MF_SEPARATOR, 0, NULL);
263 else {
264 MENUITEMINFO mi;
265 mpdm_t d = mpdm_ref(mp_menu_label(v));
267 /* set the string */
268 ptr = mpdm_wcstombs(mpdm_string(d), NULL);
269 AppendMenu(submenu, MF_STRING, win32_menu_id, ptr);
270 free(ptr);
272 mpdm_unref(d);
274 /* store the action inside the menu */
275 memset(&mi, '\0', sizeof(mi));
276 mi.cbSize = sizeof(mi);
277 mi.fMask = MIIM_DATA;
278 mi.dwItemData = (unsigned long) v;
280 SetMenuItemInfo(submenu, win32_menu_id, FALSE, &mi);
282 win32_menu_id++;
286 /* now store the popup inside the menu */
287 ptr = mpdm_wcstombs(mpdm_string(v), NULL);
288 AppendMenu(menu, MF_STRING | MF_POPUP, (UINT) submenu, ptr);
289 free(ptr);
292 SetMenu(hwnd, menu);
296 static void draw_filetabs(void)
297 /* draws the filetabs */
299 static mpdm_t last = NULL;
300 mpdm_t names;
301 int n;
303 if (hwtabs == NULL)
304 return;
306 names = mpdm_ref(mp_get_doc_names());
308 /* is the list different from the previous one? */
309 if (mpdm_cmp(names, last) != 0) {
310 TabCtrl_DeleteAllItems(hwtabs);
312 for (n = 0; n < mpdm_size(names); n++) {
313 TCITEM ti;
314 char *ptr;
315 mpdm_t v = mpdm_aget(names, n);
317 /* convert to mbs */
318 ptr = mpdm_wcstombs(v->data, NULL);
320 ti.mask = TCIF_TEXT;
321 ti.pszText = ptr;
323 /* create it */
324 TabCtrl_InsertItem(hwtabs, n, &ti);
326 free(ptr);
329 /* store for the next time */
330 mpdm_unref(last);
331 last = mpdm_ref(names);
334 mpdm_unref(names);
336 /* set the active one */
337 TabCtrl_SetCurSel(hwtabs, mpdm_ival(mpdm_hget_s(mp, L"active_i")));
341 static void draw_scrollbar(void)
342 /* updates the scrollbar */
344 mpdm_t d;
345 mpdm_t v;
346 int pos, size, max;
347 SCROLLINFO si;
349 /* gets the active document */
350 if ((d = mp_active()) == NULL)
351 return;
353 /* get the coordinates */
354 v = mpdm_hget_s(d, L"txt");
355 pos = mpdm_ival(mpdm_hget_s(v, L"vy"));
356 max = mpdm_size(mpdm_hget_s(v, L"lines"));
358 v = mpdm_hget_s(mp, L"window");
359 size = mpdm_ival(mpdm_hget_s(v, L"ty"));
361 si.cbSize = sizeof(si);
362 si.fMask = SIF_ALL;
363 si.nMin = 0;
364 si.nMax = max;
365 si.nPage = size;
366 si.nPos = pos;
368 SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
372 void draw_status(void)
373 /* draws the status line */
375 mpdm_t t;
377 if (hwstatus != NULL && (t = mpdm_ref(mp_build_status_line())) != NULL) {
378 mpdm_t v = mpdm_ref(MPDM_2MBS(t->data));
380 if (v->data != NULL)
381 SetWindowText(hwstatus, v->data);
383 mpdm_unref(v);
384 mpdm_unref(t);
389 static void win32_draw(HWND hwnd, mpdm_t doc)
390 /* win32 document draw function */
392 HDC hdc;
393 PAINTSTRUCT ps;
394 RECT rect;
395 RECT r2;
396 mpdm_t d = NULL;
397 int n, m;
399 /* start painting */
400 hdc = BeginPaint(hwnd, &ps);
402 /* no font? construct it */
403 if (font_normal == NULL) {
404 build_fonts(hdc);
405 build_colors();
408 /* no document? end */
409 if ((d = mp_draw(doc, 0)) == NULL) {
410 EndPaint(hwnd, &ps);
411 return;
414 mpdm_ref(d);
416 /* select defaults to start painting */
417 SelectObject(hdc, font_normal);
419 GetClientRect(hwnd, &rect);
420 r2 = rect;
422 r2.top += tab_height;
423 r2.bottom = r2.top + font_height;
425 for (n = 0; n < mpdm_size(d); n++) {
426 mpdm_t l = mpdm_aget(d, n);
428 r2.left = rect.left;
430 for (m = 0; m < mpdm_size(l); m++) {
431 int attr;
432 mpdm_t s;
434 /* get the attribute and the string */
435 attr = mpdm_ival(mpdm_aget(l, m++));
436 s = mpdm_aget(l, m);
438 SetTextColor(hdc, inks[attr]);
439 SetBkColor(hdc, papers[attr]);
441 SelectObject(hdc, underlines[attr] ?
442 font_underline : font_normal);
444 TextOutW(hdc, r2.left, r2.top, s->data, mpdm_size(s));
445 r2.left += mpdm_size(s) * font_width;
448 /* fills the rest of the line */
449 FillRect(hdc, &r2, bgbrush);
451 r2.top += font_height;
452 r2.bottom += font_height;
455 EndPaint(hwnd, &ps);
457 mpdm_unref(d);
459 draw_filetabs();
460 draw_scrollbar();
461 draw_status();
465 static void redraw(void)
467 InvalidateRect(hwnd, NULL, TRUE);
471 static void win32_vkey(int c)
472 /* win32 virtual key processing */
474 wchar_t *ptr = NULL;
475 static int maxed = 0;
477 /* set mp.shift_pressed */
478 if (GetKeyState(VK_SHIFT) & 0x8000)
479 mpdm_hset_s(mp, L"shift_pressed", MPDM_I(1));
481 if (GetKeyState(VK_CONTROL) & 0x8000) {
482 switch (c) {
483 case VK_UP:
484 ptr = L"ctrl-cursor-up";
485 break;
486 case VK_DOWN:
487 ptr = L"ctrl-cursor-down";
488 break;
489 case VK_LEFT:
490 ptr = L"ctrl-cursor-left";
491 break;
492 case VK_RIGHT:
493 ptr = L"ctrl-cursor-right";
494 break;
495 case VK_PRIOR:
496 ptr = L"ctrl-page-up";
497 break;
498 case VK_NEXT:
499 ptr = L"ctrl-page-down";
500 break;
501 case VK_HOME:
502 ptr = L"ctrl-home";
503 break;
504 case VK_END:
505 ptr = L"ctrl-end";
506 break;
507 case VK_SPACE:
508 ptr = L"ctrl-space";
509 break;
510 case VK_DIVIDE:
511 ptr = L"ctrl-kp-divide";
512 break;
513 case VK_MULTIPLY:
514 ptr = L"ctrl-kp-multiply";
515 break;
516 case VK_SUBTRACT:
517 ptr = L"ctrl-kp-minus";
518 break;
519 case VK_ADD:
520 ptr = L"ctrl-kp-plus";
521 break;
522 case VK_RETURN:
523 ptr = L"ctrl-enter";
524 break;
525 case VK_F1:
526 ptr = L"ctrl-f1";
527 break;
528 case VK_F2:
529 ptr = L"ctrl-f2";
530 break;
531 case VK_F3:
532 ptr = L"ctrl-f3";
533 break;
534 case VK_F4:
535 ptr = L"ctrl-f4";
536 break;
537 case VK_F5:
538 ptr = L"ctrl-f5";
539 break;
540 case VK_F6:
541 ptr = L"ctrl-f6";
542 break;
543 case VK_F7:
544 ptr = L"ctrl-f7";
545 break;
546 case VK_F8:
547 ptr = L"ctrl-f8";
548 break;
549 case VK_F9:
550 ptr = L"ctrl-f9";
551 break;
552 case VK_F10:
553 ptr = L"ctrl-f10";
554 break;
555 case VK_F11:
556 ptr = L"ctrl-f11";
557 break;
558 case VK_F12:
559 SendMessage(hwnd, WM_SYSCOMMAND,
560 maxed ? SC_RESTORE : SC_MAXIMIZE, 0);
562 maxed ^= 1;
564 break;
567 else
568 if (GetKeyState(VK_LMENU) & 0x8000) {
569 switch (c) {
570 case VK_UP:
571 ptr = L"alt-cursor-up";
572 break;
573 case VK_DOWN:
574 ptr = L"alt-cursor-down";
575 break;
576 case VK_LEFT:
577 ptr = L"alt-cursor-left";
578 break;
579 case VK_RIGHT:
580 ptr = L"alt-cursor-right";
581 break;
582 case VK_PRIOR:
583 ptr = L"alt-page-up";
584 break;
585 case VK_NEXT:
586 ptr = L"alt-page-down";
587 break;
588 case VK_HOME:
589 ptr = L"alt-home";
590 break;
591 case VK_END:
592 ptr = L"alt-end";
593 break;
594 case VK_SPACE:
595 ptr = L"alt-space";
596 break;
597 case VK_DIVIDE:
598 ptr = L"alt-kp-divide";
599 break;
600 case VK_MULTIPLY:
601 ptr = L"alt-kp-multiply";
602 break;
603 case VK_SUBTRACT:
604 ptr = L"alt-kp-minus";
605 break;
606 case VK_ADD:
607 ptr = L"alt-kp-plus";
608 break;
609 case VK_RETURN:
610 ptr = L"alt-enter";
611 break;
612 case VK_F1:
613 ptr = L"alt-f1";
614 break;
615 case VK_F2:
616 ptr = L"alt-f2";
617 break;
618 case VK_F3:
619 ptr = L"alt-f3";
620 break;
621 case VK_F4:
622 ptr = L"alt-f4";
623 break;
624 case VK_F5:
625 ptr = L"alt-f5";
626 break;
627 case VK_F6:
628 ptr = L"alt-f6";
629 break;
630 case VK_F7:
631 ptr = L"alt-f7";
632 break;
633 case VK_F8:
634 ptr = L"alt-f8";
635 break;
636 case VK_F9:
637 ptr = L"alt-f9";
638 break;
639 case VK_F10:
640 ptr = L"alt-f10";
641 break;
642 case VK_F11:
643 ptr = L"alt-f11";
644 break;
645 case VK_F12:
646 ptr = L"alt-f12";
647 break;
650 else {
651 switch (c) {
652 case VK_UP:
653 ptr = L"cursor-up";
654 break;
655 case VK_DOWN:
656 ptr = L"cursor-down";
657 break;
658 case VK_LEFT:
659 ptr = L"cursor-left";
660 break;
661 case VK_RIGHT:
662 ptr = L"cursor-right";
663 break;
664 case VK_PRIOR:
665 ptr = L"page-up";
666 break;
667 case VK_NEXT:
668 ptr = L"page-down";
669 break;
670 case VK_HOME:
671 ptr = L"home";
672 break;
673 case VK_END:
674 ptr = L"end";
675 break;
676 case VK_RETURN:
677 ptr = L"enter";
678 break;
679 case VK_BACK:
680 ptr = L"backspace";
681 break;
682 case VK_DELETE:
683 ptr = L"delete";
684 break;
685 case VK_INSERT:
686 ptr = L"insert";
687 break;
688 case VK_DIVIDE:
689 ptr = L"kp-divide";
690 break;
691 case VK_MULTIPLY:
692 ptr = L"kp-multiply";
693 break;
694 case VK_SUBTRACT:
695 ptr = L"kp-minus";
696 break;
697 case VK_ADD:
698 ptr = L"kp-plus";
699 break;
700 case VK_F1:
701 ptr = L"f1";
702 break;
703 case VK_F2:
704 ptr = L"f2";
705 break;
706 case VK_F3:
707 ptr = L"f3";
708 break;
709 case VK_F4:
710 ptr = L"f4";
711 break;
712 case VK_F5:
713 ptr = L"f5";
714 break;
715 case VK_F6:
716 ptr = L"f6";
717 break;
718 case VK_F7:
719 ptr = L"f7";
720 break;
721 case VK_F8:
722 ptr = L"f8";
723 break;
724 case VK_F9:
725 ptr = L"f9";
726 break;
727 case VK_F10:
728 ptr = L"f10";
729 break;
730 case VK_F11:
731 ptr = L"f11";
732 break;
733 case VK_F12:
734 ptr = L"f12";
735 break;
739 if (ptr != NULL) {
740 mp_process_event(MPDM_S(ptr));
742 is_wm_keydown = 1;
743 mp_active();
745 if (mp_keypress_throttle(1))
746 redraw();
751 #define ctrl(c) ((c) & 31)
753 static void win32_akey(int k)
754 /* win32 alphanumeric key processing */
756 wchar_t c[2];
757 wchar_t *ptr = NULL;
759 /* set mp.shift_pressed */
760 if (GetKeyState(VK_SHIFT) & 0x8000)
761 mpdm_hset_s(mp, L"shift_pressed", MPDM_I(1));
763 switch (k) {
764 case ctrl(' '):
765 ptr = L"ctrl-space";
766 break;
767 case ctrl('a'):
768 ptr = L"ctrl-a";
769 break;
770 case ctrl('b'):
771 ptr = L"ctrl-b";
772 break;
773 case ctrl('c'):
774 ptr = L"ctrl-c";
775 break;
776 case ctrl('d'):
777 ptr = L"ctrl-d";
778 break;
779 case ctrl('e'):
780 ptr = L"ctrl-e";
781 break;
782 case ctrl('f'):
783 ptr = L"ctrl-f";
784 break;
785 case ctrl('g'):
786 ptr = L"ctrl-g";
787 break;
788 case ctrl('h'): /* same as backspace */
789 break;
790 case ctrl('i'): /* same as tab */
791 ptr = (GetKeyState(VK_SHIFT) & 0x8000) ? L"shift-tab" : L"tab";
792 break;
793 case ctrl('j'):
794 ptr = L"ctrl-j";
795 break;
796 case ctrl('k'):
797 ptr = L"ctrl-k";
798 break;
799 case ctrl('l'):
800 ptr = L"ctrl-l";
801 break;
802 case ctrl('m'): /* same as ENTER */
803 break;
804 case ctrl('n'):
805 ptr = L"ctrl-n";
806 break;
807 case ctrl('o'):
808 ptr = L"ctrl-o";
809 break;
810 case ctrl('p'):
811 ptr = L"ctrl-p";
812 break;
813 case ctrl('q'):
814 ptr = L"ctrl-q";
815 break;
816 case ctrl('r'):
817 ptr = L"ctrl-r";
818 break;
819 case ctrl('s'):
820 ptr = L"ctrl-s";
821 break;
822 case ctrl('t'):
823 ptr = L"ctrl-t";
824 break;
825 case ctrl('u'):
826 ptr = L"ctrl-u";
827 break;
828 case ctrl('v'):
829 ptr = L"ctrl-v";
830 break;
831 case ctrl('w'):
832 ptr = L"ctrl-w";
833 break;
834 case ctrl('x'):
835 ptr = L"ctrl-x";
836 break;
837 case ctrl('y'):
838 ptr = L"ctrl-y";
839 break;
840 case ctrl('z'):
841 ptr = L"ctrl-z";
842 break;
843 case ' ':
844 ptr = L"space";
845 break;
846 case 27:
847 ptr = L"escape";
848 break;
850 default:
851 /* this is probably very bad */
852 c[0] = (wchar_t) k;
853 c[1] = L'\0';
854 ptr = c;
856 break;
859 if (ptr != NULL) {
860 mp_process_event(MPDM_S(ptr));
862 mp_active();
863 redraw();
868 static void win32_vscroll(UINT wparam)
869 /* scrollbar messages handler */
871 wchar_t *ptr = NULL;
872 mpdm_t txt;
874 switch (LOWORD(wparam)) {
875 case SB_PAGEUP:
876 ptr = L"page-up";
877 break;
878 case SB_PAGEDOWN:
879 ptr = L"page-down";
880 break;
881 case SB_LINEUP:
882 ptr = L"cursor-up";
883 break;
884 case SB_LINEDOWN:
885 ptr = L"cursor-down";
886 break;
887 case SB_THUMBPOSITION:
888 case SB_THUMBTRACK:
889 /* set both y and vy */
890 txt = mpdm_hget_s(mp_active(), L"txt");
891 mp_set_y(mp_active(), HIWORD(wparam));
892 mpdm_hset_s(txt, L"vy", MPDM_I(HIWORD(wparam)));
893 redraw();
894 break;
897 if (ptr != NULL) {
898 mp_process_event(MPDM_S(ptr));
900 redraw();
905 static void action_by_menu(int item)
906 /* execute an action triggered by the menu */
908 MENUITEMINFO mi;
910 memset(&mi, '\0', sizeof(mi));
911 mi.cbSize = sizeof(mi);
912 mi.fMask = MIIM_DATA;
914 if (GetMenuItemInfo(menu, item, FALSE, &mi)) {
915 if (mi.dwItemData != 0) {
916 mp_process_action((mpdm_t) mi.dwItemData);
917 mp_active();
923 static void dropped_files(HDROP hDrop)
924 /* fill the mp.dropped_files array with the dropped files */
926 mpdm_t a = MPDM_A(0);
927 char tmp[1024];
928 int n;
930 mpdm_ref(a);
932 n = DragQueryFile(hDrop, 0xffffffff, NULL, sizeof(tmp) - 1);
934 while (--n >= 0) {
935 DragQueryFile(hDrop, n, tmp, sizeof(tmp) - 1);
936 mpdm_push(a, MPDM_MBS(tmp));
939 DragFinish(hDrop);
941 mpdm_hset_s(mp, L"dropped_files", a);
943 mpdm_unref(a);
945 mp_process_event(MPDM_LS(L"dropped-files"));
947 redraw();
951 #ifndef WM_MOUSEWHEEL
952 #define WM_MOUSEWHEEL 0x020A
953 #endif
955 long STDCALL WndProc(HWND hwnd, UINT msg, UINT wparam, LONG lparam)
956 /* main window Proc */
958 int x, y;
959 LPNMHDR p;
960 wchar_t *ptr = NULL;
962 switch (msg) {
963 case WM_CREATE:
965 is_wm_keydown = 0;
966 DragAcceptFiles(hwnd, TRUE);
967 return 0;
969 case WM_DROPFILES:
971 dropped_files((HDROP) wparam);
972 return 0;
974 case WM_SYSKEYUP:
975 case WM_KEYUP:
977 is_wm_keydown = 0;
979 if (mp_keypress_throttle(0))
980 redraw();
982 return 0;
984 case WM_SYSKEYDOWN:
985 case WM_KEYDOWN:
987 win32_vkey(wparam);
988 return 0;
990 case WM_CHAR:
992 win32_akey(wparam);
993 return 0;
995 case WM_VSCROLL:
997 win32_vscroll(wparam);
998 return 0;
1000 case WM_PAINT:
1002 if (mpdm_size(mpdm_hget_s(mp, L"docs")))
1003 win32_draw(hwnd, mp_active());
1005 return 0;
1007 case WM_SIZE:
1009 if (!IsIconic(hwnd)) {
1010 update_window_size();
1012 MoveWindow(hwtabs, 0, 0, LOWORD(lparam), tab_height, FALSE);
1014 MoveWindow(hwstatus, 0, HIWORD(lparam) - status_height,
1015 LOWORD(lparam), status_height, FALSE);
1017 redraw();
1020 return 0;
1022 case WM_LBUTTONDOWN:
1024 mouse_down = 1;
1025 /* fallthrough */
1027 case WM_RBUTTONDOWN:
1028 case WM_MBUTTONDOWN:
1030 x = (LOWORD(lparam)) / font_width;
1031 y = (HIWORD(lparam) - tab_height) / font_height;
1033 mpdm_hset_s(mp, L"mouse_x", MPDM_I(x));
1034 mpdm_hset_s(mp, L"mouse_y", MPDM_I(y));
1036 switch (msg) {
1037 case WM_LBUTTONDOWN:
1038 ptr = L"mouse-left-button";
1039 break;
1040 case WM_RBUTTONDOWN:
1041 ptr = L"mouse-right-button";
1042 break;
1043 case WM_MBUTTONDOWN:
1044 ptr = L"mouse-middle-button";
1045 break;
1048 if (ptr != NULL) {
1049 mp_process_event(MPDM_S(ptr));
1051 redraw();
1054 return 0;
1056 case WM_LBUTTONUP:
1058 mouse_down = 0;
1059 return 0;
1061 case WM_MOUSEMOVE:
1063 if (mouse_down) {
1064 x = (LOWORD(lparam)) / font_width;
1065 y = (HIWORD(lparam) - tab_height) / font_height;
1067 mpdm_hset_s(mp, L"mouse_to_x", MPDM_I(x));
1068 mpdm_hset_s(mp, L"mouse_to_y", MPDM_I(y));
1070 mp_process_event(MPDM_LS(L"mouse-drag"));
1072 redraw();
1075 return 0;
1077 case WM_MOUSEWHEEL:
1079 if ((int) wparam > 0)
1080 ptr = L"mouse-wheel-up";
1081 else
1082 ptr = L"mouse-wheel-down";
1084 if (ptr != NULL) {
1085 mp_process_event(MPDM_S(ptr));
1087 redraw();
1090 return 0;
1092 case WM_COMMAND:
1094 action_by_menu(LOWORD(wparam));
1095 redraw();
1097 return 0;
1099 case WM_CLOSE:
1101 if (!mp_exit_requested)
1102 mp_process_event(MPDM_LS(L"close-window"));
1104 if (mp_exit_requested)
1105 DestroyWindow(hwnd);
1107 return 0;
1109 case WM_DESTROY:
1110 PostQuitMessage(0);
1111 return 0;
1113 case WM_NOTIFY:
1114 p = (LPNMHDR) lparam;
1116 if (p->code == TCN_SELCHANGE) {
1117 /* tab selected by clicking on it */
1118 int n = TabCtrl_GetCurSel(hwtabs);
1120 /* set mp.active_i to this */
1121 mpdm_hset_s(mp, L"active_i", MPDM_I(n));
1123 redraw();
1126 return 0;
1128 case WM_TIMER:
1129 mpdm_void(mpdm_exec(timer_func, NULL, NULL));
1130 redraw();
1132 return 0;
1135 if (mp_exit_requested)
1136 PostMessage(hwnd, WM_CLOSE, 0, 0);
1138 return DefWindowProcW(hwnd, msg, wparam, lparam);
1142 static mpdm_t win32_drv_clip_to_sys(mpdm_t a, mpdm_t ctxt)
1143 /* driver-dependent mp to system clipboard */
1145 HGLOBAL hclp;
1146 mpdm_t d, v;
1147 char *ptr;
1148 char *clpptr;
1149 int s;
1151 /* convert the clipboard to DOS text */
1152 d = mpdm_hget_s(mp, L"clipboard");
1154 if (mpdm_size(d) == 0)
1155 return NULL;
1157 v = mpdm_ref(mpdm_join_s(d, L"\r\n"));
1158 ptr = mpdm_wcstombs(v->data, &s);
1160 /* allocates a handle and copies */
1161 hclp = GlobalAlloc(GHND, s + 1);
1162 clpptr = (char *) GlobalLock(hclp);
1163 memcpy(clpptr, ptr, s);
1164 clpptr[s] = '\0';
1165 GlobalUnlock(hclp);
1167 free(ptr);
1169 OpenClipboard(NULL);
1170 EmptyClipboard();
1171 SetClipboardData(CF_TEXT, hclp);
1172 CloseClipboard();
1174 mpdm_unref(v);
1176 return NULL;
1180 static mpdm_t win32_drv_sys_to_clip(mpdm_t a, mpdm_t ctxt)
1181 /* driver-dependent system to mp clipboard */
1183 HGLOBAL hclp;
1184 char *ptr;
1186 OpenClipboard(NULL);
1187 hclp = GetClipboardData(CF_TEXT);
1188 CloseClipboard();
1190 if (hclp && (ptr = GlobalLock(hclp)) != NULL) {
1191 mpdm_t d, v;
1193 /* create a value and split */
1194 v = mpdm_ref(MPDM_MBS(ptr));
1195 d = mpdm_ref(mpdm_split_s(v, L"\r\n"));
1197 /* and set as the clipboard */
1198 mpdm_hset_s(mp, L"clipboard", d);
1199 mpdm_hset_s(mp, L"clipboard_vertical", MPDM_I(0));
1201 GlobalUnlock(hclp);
1203 mpdm_unref(d);
1204 mpdm_unref(v);
1207 return NULL;
1211 static mpdm_t win32_drv_main_loop(mpdm_t a, mpdm_t ctxt)
1213 MSG msg;
1215 if (!mp_exit_requested) {
1216 mp_active();
1218 while (GetMessage(&msg, NULL, 0, 0)) {
1219 TranslateMessage(&msg);
1220 DispatchMessage(&msg);
1224 return NULL;
1228 static mpdm_t win32_drv_shutdown(mpdm_t a, mpdm_t ctxt)
1230 mpdm_t v;
1232 SendMessage(hwnd, WM_CLOSE, 0, 0);
1234 if ((v = mpdm_hget_s(mp, L"exit_message")) != NULL) {
1235 char *ptr = mpdm_wcstombs(mpdm_string(v), NULL);
1236 MessageBox(NULL, ptr, "mp " VERSION, MB_ICONWARNING | MB_OK);
1237 free(ptr);
1240 return NULL;
1244 static mpdm_t win32_drv_alert(mpdm_t a, mpdm_t ctxt)
1245 /* alert driver function */
1247 wchar_t *wptr;
1248 char *ptr;
1250 /* 1# arg: prompt */
1251 wptr = mpdm_string(mpdm_aget(a, 0));
1253 if ((ptr = mpdm_wcstombs(wptr, NULL)) != NULL) {
1254 MessageBox(hwnd, ptr, "mp " VERSION, MB_ICONWARNING | MB_OK);
1255 free(ptr);
1258 return NULL;
1262 static mpdm_t win32_drv_confirm(mpdm_t a, mpdm_t ctxt)
1263 /* confirm driver function */
1265 wchar_t *wptr;
1266 char *ptr;
1267 int ret = 0;
1269 /* 1# arg: prompt */
1270 wptr = mpdm_string(mpdm_aget(a, 0));
1272 if ((ptr = mpdm_wcstombs(wptr, NULL)) != NULL) {
1273 ret =
1274 MessageBox(hwnd, ptr, "mp " VERSION,
1275 MB_ICONQUESTION | MB_YESNOCANCEL);
1276 free(ptr);
1278 if (ret == IDYES)
1279 ret = 1;
1280 else
1281 if (ret == IDNO)
1282 ret = 2;
1283 else
1284 ret = 0;
1287 return MPDM_I(ret);
1291 static LPWORD lpwAlign(LPWORD lpIn)
1292 /* aligns a pointer to DWORD boundary (for dialog templates) */
1294 ULONG ul;
1296 ul = (ULONG) lpIn;
1297 ul++;
1298 ul >>= 1;
1299 ul <<= 1;
1300 return (LPWORD) ul;
1304 #define LABEL_ID 1000
1305 #define CTRL_ID 2000
1307 BOOL CALLBACK formDlgProc(HWND hwnd, UINT msg, WPARAM wparam,
1308 LPARAM lparam)
1309 /* mp.drv.form() dialog proc */
1311 int n;
1312 HFONT hf;
1314 switch (msg) {
1315 case WM_INITDIALOG:
1317 SetWindowText(hwnd, "mp " VERSION);
1319 hf = GetStockObject(DEFAULT_GUI_FONT);
1321 /* fill controls with its initial data */
1322 for (n = 0; n < mpdm_size(form_args); n++) {
1323 mpdm_t w = mpdm_aget(form_args, n);
1324 wchar_t *type;
1325 mpdm_t t;
1326 int ctrl = CTRL_ID + n;
1327 wchar_t *wptr;
1328 char *ptr;
1330 if ((t = mpdm_hget_s(w, L"label")) != NULL) {
1331 if ((ptr = mpdm_wcstombs(mpdm_string(t), NULL)) != NULL) {
1332 SetDlgItemText(hwnd, LABEL_ID + n, ptr);
1333 free(ptr);
1335 SendDlgItemMessage(hwnd, LABEL_ID + n, WM_SETFONT,
1336 (WPARAM) hf, MAKELPARAM(FALSE, 0));
1340 SendDlgItemMessage(hwnd, ctrl, WM_SETFONT,
1341 (WPARAM) hf, MAKELPARAM(FALSE, 0));
1343 type = mpdm_string(mpdm_hget_s(w, L"type"));
1345 if (wcscmp(type, L"text") == 0) {
1346 if ((t = mpdm_hget_s(w, L"value")) != NULL &&
1347 (ptr = mpdm_wcstombs(mpdm_string(t), NULL)) != NULL) {
1348 SetDlgItemText(hwnd, ctrl, ptr);
1349 free(ptr);
1352 /* store the history into combo_items */
1353 if ((t = mpdm_hget_s(w, L"history")) != NULL) {
1354 t = mp_get_history(t);
1355 int i;
1357 for (i = 0; i < mpdm_size(t); i++) {
1358 mpdm_t v = mpdm_aget(t, i);
1360 if ((ptr = mpdm_wcstombs(v->data, NULL)) != NULL) {
1361 SendDlgItemMessage(hwnd,
1362 ctrl,
1363 CB_INSERTSTRING, 0,
1364 (LPARAM) ptr);
1365 free(ptr);
1370 else
1371 if (wcscmp(type, L"password") == 0) {
1372 SendDlgItemMessage(hwnd, ctrl,
1373 EM_SETPASSWORDCHAR, (WPARAM) '*',
1374 (LPARAM) 0);
1376 else
1377 if (wcscmp(type, L"checkbox") == 0) {
1378 if ((t = mpdm_hget_s(w, L"value")) != NULL)
1379 SendDlgItemMessage(hwnd, ctrl,
1380 BM_SETCHECK, mpdm_ival(t) ?
1381 BST_CHECKED : BST_UNCHECKED, 0);
1383 else
1384 if (wcscmp(type, L"list") == 0) {
1385 int i;
1387 t = mpdm_hget_s(w, L"list");
1389 /* fill the list */
1390 for (i = 0; i < mpdm_size(t); i++) {
1391 wptr = mpdm_string(mpdm_aget(t, i));
1392 if ((ptr = mpdm_wcstombs(wptr, NULL)) != NULL) {
1393 SendDlgItemMessage(hwnd, ctrl,
1394 LB_ADDSTRING, 0, (LPARAM) ptr);
1395 free(ptr);
1399 /* set position */
1400 SendDlgItemMessage(hwnd, ctrl, LB_SETCURSEL,
1401 mpdm_ival(mpdm_hget_s(w, L"value")), 0);
1405 /* FIXME: untranslated strings */
1407 SetDlgItemText(hwnd, IDOK, "OK");
1408 SendDlgItemMessage(hwnd, IDOK, WM_SETFONT,
1409 (WPARAM) hf, MAKELPARAM(FALSE, 0));
1411 SetDlgItemText(hwnd, IDCANCEL, "Cancel");
1412 SendDlgItemMessage(hwnd, IDCANCEL, WM_SETFONT,
1413 (WPARAM) hf, MAKELPARAM(FALSE, 0));
1415 return TRUE;
1417 case WM_COMMAND:
1419 if (LOWORD(wparam) == IDCANCEL) {
1420 EndDialog(hwnd, 0);
1421 return TRUE;
1424 if (LOWORD(wparam) != IDOK)
1425 break;
1427 /* fill all return values */
1428 for (n = 0; n < mpdm_size(form_args); n++) {
1429 mpdm_t w = mpdm_aget(form_args, n);
1430 wchar_t *type = mpdm_string(mpdm_hget_s(w, L"type"));
1431 int ctrl = CTRL_ID + n;
1433 if (wcscmp(type, L"text") == 0) {
1434 char tmp[2048];
1435 mpdm_t v;
1436 mpdm_t h;
1438 GetDlgItemText(hwnd, ctrl, tmp, sizeof(tmp) - 1);
1439 v = MPDM_MBS(tmp);
1441 mpdm_aset(form_values, v, n);
1443 /* if it has history, fill it */
1444 if ((h = mpdm_hget_s(w, L"history")) != NULL &&
1445 v != NULL && mpdm_cmp_s(v, L"") != 0) {
1446 h = mp_get_history(h);
1448 if (mpdm_cmp(v, mpdm_aget(h, -1)) != 0)
1449 mpdm_push(h, v);
1452 if (wcscmp(type, L"password") == 0) {
1453 char tmp[2048];
1455 GetDlgItemText(hwnd, ctrl, tmp, sizeof(tmp) - 1);
1456 mpdm_aset(form_values, MPDM_MBS(tmp), n);
1458 else
1459 if (wcscmp(type, L"checkbox") == 0) {
1460 mpdm_aset(form_values,
1461 MPDM_I(SendDlgItemMessage(hwnd, ctrl,
1462 BM_GETCHECK, 0, 0)),
1465 else
1466 if (wcscmp(type, L"list") == 0) {
1467 mpdm_aset(form_values,
1468 MPDM_I(SendDlgItemMessage(hwnd, ctrl,
1469 LB_GETCURSEL, 0, 0)),
1474 EndDialog(hwnd, 1);
1475 return TRUE;
1478 return FALSE;
1482 static void build_form_data(mpdm_t widget_list)
1483 /* builds the necessary information for a list of widgets */
1485 mpdm_unref(form_args);
1486 form_args = mpdm_ref(widget_list);
1488 mpdm_unref(form_values);
1489 form_values = widget_list == NULL ? NULL :
1490 mpdm_ref(MPDM_A(mpdm_size(form_args)));
1494 LPWORD static build_control(LPWORD lpw, int x, int y,
1495 int cx, int cy, int id, int class, int style)
1496 /* fills a control structure in a hand-made dialog template */
1498 LPDLGITEMTEMPLATE lpdit;
1500 lpw = lpwAlign(lpw);
1501 lpdit = (LPDLGITEMTEMPLATE) lpw;
1502 lpdit->x = x;
1503 lpdit->y = y;
1504 lpdit->cx = cx;
1505 lpdit->cy = cy;
1506 lpdit->id = id;
1507 lpdit->style = style;
1509 lpw = (LPWORD) (lpdit + 1);
1510 *lpw++ = 0xFFFF;
1511 *lpw++ = class;
1513 /* no text (will be set on dialog setup) */
1514 *lpw++ = 0;
1515 *lpw++ = 0;
1517 /* Align creation data on DWORD boundary */
1518 lpw = lpwAlign(lpw);
1519 /* No creation data */
1520 *lpw++ = 0;
1522 return lpw;
1526 static mpdm_t win32_drv_form(mpdm_t a, mpdm_t ctxt)
1527 /* mp.drv.form() function */
1529 HGLOBAL hgbl;
1530 LPDLGTEMPLATE lpdt;
1531 LPWORD lpw;
1532 int n, p;
1533 int il = 10;
1534 int lbl = 0;
1536 /* first argument: list of widgets */
1537 build_form_data(mpdm_aget(a, 0));
1539 /* On-the-fly dialog template creation */
1540 /* Note: all this crap is taken from MSDN, no less */
1542 /* magic size; looking for problems */
1543 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
1544 lpdt = (LPDLGTEMPLATE) GlobalLock(hgbl);
1546 lpdt->style =
1547 WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION;
1548 lpdt->cdit = (2 * mpdm_size(form_args)) + 2;
1549 lpdt->x = 20;
1550 lpdt->y = 20;
1551 lpdt->cx = 260;
1553 lpw = (LPWORD) (lpdt + 1);
1554 *lpw++ = 0; /* No menu */
1555 *lpw++ = 0; /* Predefined dialog box class (by default) */
1556 *lpw++ = 0; /* No title */
1558 /* first pass: calculate maximum size of labels */
1559 for (n = 0; n < mpdm_size(form_args); n++) {
1560 mpdm_t w = mpdm_aget(form_args, n);
1561 int l = mpdm_size(mpdm_hget_s(w, L"label"));
1563 if (lbl < l)
1564 lbl = l;
1567 /* second pass: create the dialog controls */
1568 for (n = p = 0; n < mpdm_size(form_args); n++) {
1569 mpdm_t w = mpdm_aget(form_args, n);
1570 wchar_t *type;
1571 int class;
1572 int style;
1573 int inc = 1;
1574 int sz = 1;
1576 /* label control */
1577 lpw = build_control(lpw, 0, 5 + p * il,
1578 lbl * 3, 20, LABEL_ID + n, 0x0082,
1579 WS_CHILD | WS_VISIBLE | SS_RIGHT);
1581 type = mpdm_string(mpdm_hget_s(w, L"type"));
1583 if (wcscmp(type, L"text") == 0) {
1584 class = 0x0085;
1585 style = WS_CHILD | WS_VISIBLE | WS_TABSTOP |
1586 CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL;
1588 /* size */
1589 sz = 5;
1591 else
1592 if (wcscmp(type, L"password") == 0) {
1593 class = 0x0081;
1594 style = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP;
1596 else
1597 if (wcscmp(type, L"checkbox") == 0) {
1598 class = 0x0080;
1599 style = WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | WS_TABSTOP;
1601 else
1602 if (wcscmp(type, L"list") == 0) {
1603 class = 0x0083;
1604 style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER |
1605 LBS_NOINTEGRALHEIGHT | WS_VSCROLL |
1606 LBS_NOTIFY | LBS_USETABSTOPS;
1608 /* height */
1609 inc = 5;
1612 /* the control */
1613 lpw = build_control(lpw, 10 + lbl * 3, 5 + p * il,
1614 245 - lbl * 3, inc * il * sz, CTRL_ID + n,
1615 class, style);
1617 /* next position */
1618 p += inc;
1621 /* set total height */
1622 lpdt->cy = 30 + p * il;
1624 /* OK */
1625 lpw = build_control(lpw, 170, 10 + p * il, 40, 15, IDOK,
1626 0x0080,
1627 WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON |
1628 WS_TABSTOP);
1630 /* Cancel */
1631 lpw = build_control(lpw, 215, 10 + p * il, 40, 15, IDCANCEL,
1632 0x0080,
1633 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON |
1634 WS_TABSTOP);
1636 GlobalUnlock(hgbl);
1637 n = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
1638 hwnd, (DLGPROC) formDlgProc);
1640 GlobalFree(hgbl);
1642 return n ? form_values : NULL;
1646 static mpdm_t open_or_save(int o, mpdm_t a)
1647 /* manages an open or save file dialog */
1649 OPENFILENAME ofn;
1650 wchar_t *wptr;
1651 char *ptr;
1652 char buf[1024] = "";
1653 char buf2[1024];
1654 int r;
1656 /* 1# arg: prompt */
1657 wptr = mpdm_string(mpdm_aget(a, 0));
1658 ptr = mpdm_wcstombs(wptr, NULL);
1660 memset(&ofn, '\0', sizeof(OPENFILENAME));
1661 ofn.lStructSize = sizeof(OPENFILENAME);
1662 ofn.hwndOwner = hwnd;
1663 ofn.lpstrFilter = "*.*\0*.*\0";
1664 ofn.nFilterIndex = 1;
1665 ofn.lpstrFile = buf;
1666 ofn.nMaxFile = sizeof(buf);
1667 ofn.lpstrTitle = ptr;
1668 ofn.lpstrDefExt = "";
1670 GetCurrentDirectory(sizeof(buf2), buf2);
1671 ofn.lpstrInitialDir = buf2;
1673 /* ofn.lpstrDefExt=(def==NULL ? "" : def);*/
1675 if (o) {
1676 ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
1677 OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST;
1679 r = GetOpenFileName(&ofn);
1681 else {
1682 ofn.Flags = OFN_HIDEREADONLY;
1684 r = GetSaveFileName(&ofn);
1687 free(ptr);
1689 if (r)
1690 return MPDM_MBS(buf);
1692 return NULL;
1696 static mpdm_t win32_drv_openfile(mpdm_t a, mpdm_t ctxt)
1697 /* openfile driver function */
1699 return open_or_save(1, a);
1703 static mpdm_t win32_drv_savefile(mpdm_t a, mpdm_t ctxt)
1704 /* savefile driver function */
1706 return open_or_save(0, a);
1710 static mpdm_t win32_drv_update_ui(mpdm_t a, mpdm_t ctxt)
1712 build_fonts(GetDC(hwnd));
1713 build_colors();
1714 build_menu();
1716 return NULL;
1720 static mpdm_t win32_drv_timer(mpdm_t a, mpdm_t ctxt)
1722 int msecs = mpdm_ival(mpdm_aget(a, 0));
1723 mpdm_t func = mpdm_aget(a, 1);
1725 /* previously defined one? remove */
1726 if (timer_func != NULL)
1727 KillTimer(hwnd, 1);
1729 /* if msecs and func are set, program timer */
1730 if (msecs > 0 && func != NULL)
1731 SetTimer(hwnd, 1, msecs, NULL);
1733 mpdm_ref(func);
1734 mpdm_unref(timer_func);
1735 timer_func = func;
1737 return NULL;
1741 static mpdm_t win32_drv_busy(mpdm_t a, mpdm_t ctxt)
1743 int onoff = mpdm_ival(mpdm_aget(a, 0));
1745 SetCursor(LoadCursor(NULL, onoff ? IDC_WAIT : IDC_ARROW));
1747 return NULL;
1751 static void register_functions(void)
1753 mpdm_t drv;
1755 drv = mpdm_hget_s(mp, L"drv");
1756 mpdm_hset_s(drv, L"main_loop", MPDM_X(win32_drv_main_loop));
1757 mpdm_hset_s(drv, L"shutdown", MPDM_X(win32_drv_shutdown));
1758 mpdm_hset_s(drv, L"clip_to_sys", MPDM_X(win32_drv_clip_to_sys));
1759 mpdm_hset_s(drv, L"sys_to_clip", MPDM_X(win32_drv_sys_to_clip));
1760 mpdm_hset_s(drv, L"update_ui", MPDM_X(win32_drv_update_ui));
1761 mpdm_hset_s(drv, L"timer", MPDM_X(win32_drv_timer));
1762 mpdm_hset_s(drv, L"busy", MPDM_X(win32_drv_busy));
1763 mpdm_hset_s(drv, L"alert", MPDM_X(win32_drv_alert));
1764 mpdm_hset_s(drv, L"confirm", MPDM_X(win32_drv_confirm));
1765 mpdm_hset_s(drv, L"openfile", MPDM_X(win32_drv_openfile));
1766 mpdm_hset_s(drv, L"savefile", MPDM_X(win32_drv_savefile));
1767 mpdm_hset_s(drv, L"form", MPDM_X(win32_drv_form));
1771 static mpdm_t win32_drv_startup(mpdm_t a, mpdm_t ctxt)
1773 WNDCLASSW wc;
1774 RECT r;
1775 mpdm_t v;
1777 register_functions();
1779 InitCommonControls();
1781 /* register the window */
1782 wc.style = CS_HREDRAW | CS_VREDRAW;
1783 wc.lpfnWndProc = WndProc;
1784 wc.cbClsExtra = 0;
1785 wc.cbWndExtra = 0;
1786 wc.hInstance = hinst;
1787 wc.hIcon = LoadIcon(hinst, "MP_ICON");
1788 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1789 wc.hbrBackground = NULL;
1790 wc.lpszMenuName = NULL;
1791 wc.lpszClassName = L"minimumprofit5.x";
1793 RegisterClassW(&wc);
1795 /* create the window */
1796 hwnd = CreateWindowW(L"minimumprofit5.x", L"mp " VERSION,
1797 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
1798 WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT,
1799 CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst,
1800 NULL);
1802 ShowWindow(hwnd, SW_SHOW);
1803 UpdateWindow(hwnd);
1805 GetClientRect(hwnd, &r);
1807 hwtabs = CreateWindow(WC_TABCONTROL, "tab",
1808 WS_CHILD | TCS_TABS | TCS_SINGLELINE |
1809 TCS_FOCUSNEVER, 0, 0, r.right - r.left,
1810 tab_height, hwnd, NULL, hinst, NULL);
1812 SendMessage(hwtabs, WM_SETFONT,
1813 (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0);
1815 ShowWindow(hwtabs, SW_SHOW);
1816 UpdateWindow(hwtabs);
1818 hwstatus = CreateWindow(WC_STATIC, "status",
1819 WS_CHILD,
1820 0, r.bottom - r.top - status_height,
1821 r.right - r.left, status_height, hwnd, NULL,
1822 hinst, NULL);
1824 win32_drv_update_ui(NULL, NULL);
1826 SendMessage(hwstatus, WM_SETFONT,
1827 (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0);
1829 ShowWindow(hwstatus, SW_SHOW);
1830 UpdateWindow(hwstatus);
1832 if ((v = mpdm_hget_s(mp, L"config")) != NULL &&
1833 mpdm_ival(mpdm_hget_s(v, L"maximize")) > 0)
1834 SendMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
1836 return NULL;
1840 int win32_drv_detect(int *argc, char ***argv)
1842 mpdm_t drv;
1843 int n;
1845 for (n = 0; n < *argc; n++) {
1846 if (strcmp(argv[0][n], "-txt") == 0 ||
1847 strcmp(argv[0][n], "-h") == 0)
1848 return 0;
1851 drv = mpdm_hget_s(mp, L"drv");
1852 mpdm_hset_s(drv, L"id", MPDM_LS(L"win32"));
1853 mpdm_hset_s(drv, L"startup", MPDM_X(win32_drv_startup));
1855 return 1;
1858 #endif /* CONFOPT_WIN32 */