3 Minimum Profit - Programmer Text Editor
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
54 /* font handlers and metrics */
55 HFONT font_normal
= NULL
;
56 HFONT font_underline
= NULL
;
60 /* height of the tab set */
63 /* height of the status bar */
64 int status_height
= 16;
66 int is_wm_keydown
= 0;
69 static COLORREF
*inks
= NULL
;
70 static COLORREF
*papers
= NULL
;
71 int *underlines
= NULL
;
74 /* code for the 'normal' attribute */
75 static int normal_attr
= 0;
78 static HMENU menu
= NULL
;
80 /* mp.drv.form() controls */
82 static mpdm_t form_args
= NULL
;
83 static mpdm_t form_values
= NULL
;
86 static int mouse_down
= 0;
89 static mpdm_t timer_func
= NULL
;
93 static void update_window_size(void)
94 /* updates the viewport size in characters */
100 /* no font information? go */
101 if (font_width
== 0 || font_height
== 0)
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 */
123 char *font_face
= "Lucida Console";
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
);
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
;
144 mpdm_hset_s(c
, L
"font_face", MPDM_MBS(font_face
));
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
);
160 font_height
= tm
.tmHeight
;
161 font_width
= tm
.tmAveCharWidth
;
163 update_window_size();
169 static void build_colors(void)
170 /* builds the colors */
177 /* gets the color definitions and attribute names */
178 colors
= mpdm_hget_s(mp
, L
"colors");
179 l
= mpdm_ref(mpdm_keys(colors
));
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");
193 /* store the 'normal' attribute */
194 if (wcscmp(mpdm_string(c
), L
"normal") == 0)
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);
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) {
223 /* create the background brush */
224 bgbrush
= CreateSolidBrush(papers
[normal_attr
]);
228 static void build_menu(void)
229 /* builds the menu */
233 int win32_menu_id
= 1000;
235 /* gets the current menu */
236 if ((m
= mpdm_hget_s(mp
, L
"menu")) == NULL
)
244 for (n
= 0; n
< mpdm_size(m
); n
++) {
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
++) {
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
);
265 mpdm_t d
= mpdm_ref(mp_menu_label(v
));
268 ptr
= mpdm_wcstombs(mpdm_string(d
), NULL
);
269 AppendMenu(submenu
, MF_STRING
, win32_menu_id
, ptr
);
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
);
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
);
296 static void draw_filetabs(void)
297 /* draws the filetabs */
299 static mpdm_t last
= NULL
;
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
++) {
315 mpdm_t v
= mpdm_aget(names
, n
);
318 ptr
= mpdm_wcstombs(v
->data
, NULL
);
324 TabCtrl_InsertItem(hwtabs
, n
, &ti
);
329 /* store for the next time */
331 last
= mpdm_ref(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 */
349 /* gets the active document */
350 if ((d
= mp_active()) == NULL
)
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
);
368 SetScrollInfo(hwnd
, SB_VERT
, &si
, TRUE
);
372 void draw_status(void)
373 /* draws the status line */
377 if (hwstatus
!= NULL
&& (t
= mpdm_ref(mp_build_status_line())) != NULL
) {
378 mpdm_t v
= mpdm_ref(MPDM_2MBS(t
->data
));
381 SetWindowText(hwstatus
, v
->data
);
389 static void win32_draw(HWND hwnd
, mpdm_t doc
)
390 /* win32 document draw function */
400 hdc
= BeginPaint(hwnd
, &ps
);
402 /* no font? construct it */
403 if (font_normal
== NULL
) {
408 /* no document? end */
409 if ((d
= mp_draw(doc
, 0)) == NULL
) {
416 /* select defaults to start painting */
417 SelectObject(hdc
, font_normal
);
419 GetClientRect(hwnd
, &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
);
430 for (m
= 0; m
< mpdm_size(l
); m
++) {
434 /* get the attribute and the string */
435 attr
= mpdm_ival(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
;
465 static void redraw(void)
467 InvalidateRect(hwnd
, NULL
, TRUE
);
471 static void win32_vkey(int c
)
472 /* win32 virtual key processing */
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) {
484 ptr
= L
"ctrl-cursor-up";
487 ptr
= L
"ctrl-cursor-down";
490 ptr
= L
"ctrl-cursor-left";
493 ptr
= L
"ctrl-cursor-right";
496 ptr
= L
"ctrl-page-up";
499 ptr
= L
"ctrl-page-down";
511 ptr
= L
"ctrl-kp-divide";
514 ptr
= L
"ctrl-kp-multiply";
517 ptr
= L
"ctrl-kp-minus";
520 ptr
= L
"ctrl-kp-plus";
559 SendMessage(hwnd
, WM_SYSCOMMAND
,
560 maxed
? SC_RESTORE
: SC_MAXIMIZE
, 0);
568 if (GetKeyState(VK_LMENU
) & 0x8000) {
571 ptr
= L
"alt-cursor-up";
574 ptr
= L
"alt-cursor-down";
577 ptr
= L
"alt-cursor-left";
580 ptr
= L
"alt-cursor-right";
583 ptr
= L
"alt-page-up";
586 ptr
= L
"alt-page-down";
598 ptr
= L
"alt-kp-divide";
601 ptr
= L
"alt-kp-multiply";
604 ptr
= L
"alt-kp-minus";
607 ptr
= L
"alt-kp-plus";
656 ptr
= L
"cursor-down";
659 ptr
= L
"cursor-left";
662 ptr
= L
"cursor-right";
692 ptr
= L
"kp-multiply";
740 mp_process_event(MPDM_S(ptr
));
745 if (mp_keypress_throttle(1))
751 #define ctrl(c) ((c) & 31)
753 static void win32_akey(int k
)
754 /* win32 alphanumeric key processing */
759 /* set mp.shift_pressed */
760 if (GetKeyState(VK_SHIFT
) & 0x8000)
761 mpdm_hset_s(mp
, L
"shift_pressed", MPDM_I(1));
788 case ctrl('h'): /* same as backspace */
790 case ctrl('i'): /* same as tab */
791 ptr
= (GetKeyState(VK_SHIFT
) & 0x8000) ? L
"shift-tab" : L
"tab";
802 case ctrl('m'): /* same as ENTER */
851 /* this is probably very bad */
860 mp_process_event(MPDM_S(ptr
));
868 static void win32_vscroll(UINT wparam
)
869 /* scrollbar messages handler */
874 switch (LOWORD(wparam
)) {
885 ptr
= L
"cursor-down";
887 case SB_THUMBPOSITION
:
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
)));
898 mp_process_event(MPDM_S(ptr
));
905 static void action_by_menu(int item
)
906 /* execute an action triggered by the menu */
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
);
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);
932 n
= DragQueryFile(hDrop
, 0xffffffff, NULL
, sizeof(tmp
) - 1);
935 DragQueryFile(hDrop
, n
, tmp
, sizeof(tmp
) - 1);
936 mpdm_push(a
, MPDM_MBS(tmp
));
941 mpdm_hset_s(mp
, L
"dropped_files", a
);
945 mp_process_event(MPDM_LS(L
"dropped-files"));
951 #ifndef WM_MOUSEWHEEL
952 #define WM_MOUSEWHEEL 0x020A
955 long STDCALL
WndProc(HWND hwnd
, UINT msg
, UINT wparam
, LONG lparam
)
956 /* main window Proc */
966 DragAcceptFiles(hwnd
, TRUE
);
971 dropped_files((HDROP
) wparam
);
979 if (mp_keypress_throttle(0))
997 win32_vscroll(wparam
);
1002 if (mpdm_size(mpdm_hget_s(mp
, L
"docs")))
1003 win32_draw(hwnd
, mp_active());
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
);
1022 case WM_LBUTTONDOWN
:
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
));
1037 case WM_LBUTTONDOWN
:
1038 ptr
= L
"mouse-left-button";
1040 case WM_RBUTTONDOWN
:
1041 ptr
= L
"mouse-right-button";
1043 case WM_MBUTTONDOWN
:
1044 ptr
= L
"mouse-middle-button";
1049 mp_process_event(MPDM_S(ptr
));
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"));
1079 if ((int) wparam
> 0)
1080 ptr
= L
"mouse-wheel-up";
1082 ptr
= L
"mouse-wheel-down";
1085 mp_process_event(MPDM_S(ptr
));
1094 action_by_menu(LOWORD(wparam
));
1101 if (!mp_exit_requested
)
1102 mp_process_event(MPDM_LS(L
"close-window"));
1104 if (mp_exit_requested
)
1105 DestroyWindow(hwnd
);
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
));
1129 mpdm_void(mpdm_exec(timer_func
, NULL
, NULL
));
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 */
1151 /* convert the clipboard to DOS text */
1152 d
= mpdm_hget_s(mp
, L
"clipboard");
1154 if (mpdm_size(d
) == 0)
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
);
1169 OpenClipboard(NULL
);
1171 SetClipboardData(CF_TEXT
, hclp
);
1180 static mpdm_t
win32_drv_sys_to_clip(mpdm_t a
, mpdm_t ctxt
)
1181 /* driver-dependent system to mp clipboard */
1186 OpenClipboard(NULL
);
1187 hclp
= GetClipboardData(CF_TEXT
);
1190 if (hclp
&& (ptr
= GlobalLock(hclp
)) != NULL
) {
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));
1211 static mpdm_t
win32_drv_main_loop(mpdm_t a
, mpdm_t ctxt
)
1215 if (!mp_exit_requested
) {
1218 while (GetMessage(&msg
, NULL
, 0, 0)) {
1219 TranslateMessage(&msg
);
1220 DispatchMessage(&msg
);
1228 static mpdm_t
win32_drv_shutdown(mpdm_t a
, mpdm_t ctxt
)
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
);
1244 static mpdm_t
win32_drv_alert(mpdm_t a
, mpdm_t ctxt
)
1245 /* alert driver function */
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
);
1262 static mpdm_t
win32_drv_confirm(mpdm_t a
, mpdm_t ctxt
)
1263 /* confirm driver function */
1269 /* 1# arg: prompt */
1270 wptr
= mpdm_string(mpdm_aget(a
, 0));
1272 if ((ptr
= mpdm_wcstombs(wptr
, NULL
)) != NULL
) {
1274 MessageBox(hwnd
, ptr
, "mp " VERSION
,
1275 MB_ICONQUESTION
| MB_YESNOCANCEL
);
1291 static LPWORD
lpwAlign(LPWORD lpIn
)
1292 /* aligns a pointer to DWORD boundary (for dialog templates) */
1304 #define LABEL_ID 1000
1305 #define CTRL_ID 2000
1307 BOOL CALLBACK
formDlgProc(HWND hwnd
, UINT msg
, WPARAM wparam
,
1309 /* mp.drv.form() dialog proc */
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
);
1326 int ctrl
= CTRL_ID
+ n
;
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
);
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
);
1352 /* store the history into combo_items */
1353 if ((t
= mpdm_hget_s(w
, L
"history")) != NULL
) {
1354 t
= mp_get_history(t
);
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
,
1371 if (wcscmp(type
, L
"password") == 0) {
1372 SendDlgItemMessage(hwnd
, ctrl
,
1373 EM_SETPASSWORDCHAR
, (WPARAM
) '*',
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);
1384 if (wcscmp(type
, L
"list") == 0) {
1387 t
= mpdm_hget_s(w
, L
"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
);
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));
1419 if (LOWORD(wparam
) == IDCANCEL
) {
1424 if (LOWORD(wparam
) != IDOK
)
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) {
1438 GetDlgItemText(hwnd
, ctrl
, tmp
, sizeof(tmp
) - 1);
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)
1452 if (wcscmp(type
, L
"password") == 0) {
1455 GetDlgItemText(hwnd
, ctrl
, tmp
, sizeof(tmp
) - 1);
1456 mpdm_aset(form_values
, MPDM_MBS(tmp
), n
);
1459 if (wcscmp(type
, L
"checkbox") == 0) {
1460 mpdm_aset(form_values
,
1461 MPDM_I(SendDlgItemMessage(hwnd
, ctrl
,
1462 BM_GETCHECK
, 0, 0)),
1466 if (wcscmp(type
, L
"list") == 0) {
1467 mpdm_aset(form_values
,
1468 MPDM_I(SendDlgItemMessage(hwnd
, ctrl
,
1469 LB_GETCURSEL
, 0, 0)),
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
;
1507 lpdit
->style
= style
;
1509 lpw
= (LPWORD
) (lpdit
+ 1);
1513 /* no text (will be set on dialog setup) */
1517 /* Align creation data on DWORD boundary */
1518 lpw
= lpwAlign(lpw
);
1519 /* No creation data */
1526 static mpdm_t
win32_drv_form(mpdm_t a
, mpdm_t ctxt
)
1527 /* mp.drv.form() function */
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
);
1547 WS_POPUP
| WS_BORDER
| WS_SYSMENU
| DS_MODALFRAME
| WS_CAPTION
;
1548 lpdt
->cdit
= (2 * mpdm_size(form_args
)) + 2;
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"));
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
);
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) {
1585 style
= WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
|
1586 CBS_DROPDOWN
| CBS_AUTOHSCROLL
| WS_VSCROLL
;
1592 if (wcscmp(type
, L
"password") == 0) {
1594 style
= WS_CHILD
| WS_VISIBLE
| WS_BORDER
| WS_TABSTOP
;
1597 if (wcscmp(type
, L
"checkbox") == 0) {
1599 style
= WS_CHILD
| WS_VISIBLE
| BS_AUTOCHECKBOX
| WS_TABSTOP
;
1602 if (wcscmp(type
, L
"list") == 0) {
1604 style
= WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_BORDER
|
1605 LBS_NOINTEGRALHEIGHT
| WS_VSCROLL
|
1606 LBS_NOTIFY
| LBS_USETABSTOPS
;
1613 lpw
= build_control(lpw
, 10 + lbl
* 3, 5 + p
* il
,
1614 245 - lbl
* 3, inc
* il
* sz
, CTRL_ID
+ n
,
1621 /* set total height */
1622 lpdt
->cy
= 30 + p
* il
;
1625 lpw
= build_control(lpw
, 170, 10 + p
* il
, 40, 15, IDOK
,
1627 WS_CHILD
| WS_VISIBLE
| BS_DEFPUSHBUTTON
|
1631 lpw
= build_control(lpw
, 215, 10 + p
* il
, 40, 15, IDCANCEL
,
1633 WS_CHILD
| WS_VISIBLE
| BS_PUSHBUTTON
|
1637 n
= DialogBoxIndirect(hinst
, (LPDLGTEMPLATE
) hgbl
,
1638 hwnd
, (DLGPROC
) formDlgProc
);
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 */
1652 char buf
[1024] = "";
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);*/
1676 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
|
1677 OFN_NOCHANGEDIR
| OFN_FILEMUSTEXIST
;
1679 r
= GetOpenFileName(&ofn
);
1682 ofn
.Flags
= OFN_HIDEREADONLY
;
1684 r
= GetSaveFileName(&ofn
);
1690 return MPDM_MBS(buf
);
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
));
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
)
1729 /* if msecs and func are set, program timer */
1730 if (msecs
> 0 && func
!= NULL
)
1731 SetTimer(hwnd
, 1, msecs
, NULL
);
1734 mpdm_unref(timer_func
);
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
));
1751 static void register_functions(void)
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
)
1777 register_functions();
1779 InitCommonControls();
1781 /* register the window */
1782 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1783 wc
.lpfnWndProc
= WndProc
;
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
,
1802 ShowWindow(hwnd
, SW_SHOW
);
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",
1820 0, r
.bottom
- r
.top
- status_height
,
1821 r
.right
- r
.left
, status_height
, hwnd
, 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);
1840 int win32_drv_detect(int *argc
, char ***argv
)
1845 for (n
= 0; n
< *argc
; n
++) {
1846 if (strcmp(argv
[0][n
], "-txt") == 0 ||
1847 strcmp(argv
[0][n
], "-h") == 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
));
1858 #endif /* CONFOPT_WIN32 */