#include "gui_w48.c"
#include "guiw16rc.h"
#define WM_EXITSIZEMOVE 0x0232
#ifdef FEAT_TOOLBAR
# define CMD_TB_BASE (99)
# include <vimtbar.h>
#endif
#ifdef PROTO
# define WINAPI
#endif
#define HANDLE_WM_DROPFILES(hwnd, wParam, lParam, fn) \
((fn)((hwnd), (HDROP)(wParam)), 0L)
#ifdef FEAT_MENU
static UINT s_menu_id = 100;
#endif
#define VIM_NAME "vim"
#define VIM_CLASS "Vim"
#define DLG_ALLOC_SIZE 16 * 1024
#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
static BOOL CALLBACK dialog_callback(HWND, UINT, WPARAM, LPARAM);
static LPWORD
add_dialog_element(
LPWORD p,
DWORD lStyle,
WORD x,
WORD y,
WORD w,
WORD h,
WORD Id,
BYTE clss,
const char *caption);
static int dialog_default_button = -1;
#endif
static void get_dialog_font_metrics(void);
#ifdef FEAT_TOOLBAR
static void initialise_toolbar(void);
#endif
#ifdef FEAT_MENU
static int
gui_mswin_get_menu_height(
int fix_window)
{
static int old_menu_height = -1;
int num;
int menu_height;
if (gui.menu_is_active)
num = GetMenuItemCount(s_menuBar);
else
num = 0;
if (num == 0)
menu_height = 0;
else if (gui.starting)
menu_height = GetSystemMetrics(SM_CYMENU);
else
{
RECT r1, r2;
int frameht = GetSystemMetrics(SM_CYFRAME);
int capht = GetSystemMetrics(SM_CYCAPTION);
GetWindowRect(s_hwnd, &r1);
GetClientRect(s_hwnd, &r2);
menu_height = r1.bottom - r1.top - (r2.bottom-r2.top +
2 * frameht * (!IsZoomed(s_hwnd)) + capht);
}
if (fix_window && menu_height != old_menu_height)
{
old_menu_height = menu_height;
gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
}
return menu_height;
}
#endif
static BOOL
_OnWindowPosChanging(
HWND hwnd,
LPWINDOWPOS lpwpos)
{
if (!IsIconic(hwnd) && !(lpwpos->flags & SWP_NOSIZE))
{
gui_mswin_get_valid_dimensions(lpwpos->cx, lpwpos->cy,
&lpwpos->cx, &lpwpos->cy);
}
return 0;
}
static LRESULT CALLBACK
_WndProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
HandleMouseHide(uMsg, lParam);
s_uMsg = uMsg;
s_wParam = wParam;
s_lParam = lParam;
switch (uMsg)
{
HANDLE_MSG(hwnd, WM_DEADCHAR, _OnDeadChar);
HANDLE_MSG(hwnd, WM_SYSDEADCHAR, _OnDeadChar);
HANDLE_MSG(hwnd, WM_CHAR, _OnChar);
HANDLE_MSG(hwnd, WM_CLOSE, _OnClose);
HANDLE_MSG(hwnd, WM_DESTROY, _OnDestroy);
HANDLE_MSG(hwnd, WM_DROPFILES, _OnDropFiles);
HANDLE_MSG(hwnd, WM_HSCROLL, _OnScroll);
HANDLE_MSG(hwnd, WM_KILLFOCUS, _OnKillFocus);
#ifdef FEAT_MENU
HANDLE_MSG(hwnd, WM_COMMAND, _OnMenu);
#endif
HANDLE_MSG(hwnd, WM_SETFOCUS, _OnSetFocus);
HANDLE_MSG(hwnd, WM_SIZE, _OnSize);
HANDLE_MSG(hwnd, WM_VSCROLL, _OnScroll);
HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGING, _OnWindowPosChanging);
HANDLE_MSG(hwnd, WM_ACTIVATEAPP, _OnActivateApp);
case WM_QUERYENDSESSION:
gui_shell_closed();
return FALSE;
case WM_ENDSESSION:
if (wParam)
_OnEndSession();
break;
case WM_SYSCHAR:
#ifdef FEAT_MENU
if ( !gui.menu_is_active
|| p_wak[0] == 'n'
|| (p_wak[0] == 'm' && !gui_is_menu_shortcut((int)wParam))
)
#endif
return HANDLE_WM_SYSCHAR((hwnd), (wParam), (lParam), (_OnSysChar));
#ifdef FEAT_MENU
else
return MyWindowProc(hwnd, uMsg, wParam, lParam);
#endif
case WM_SYSKEYUP:
#ifdef FEAT_MENU
if (gui.menu_is_active)
{
return MyWindowProc(hwnd, uMsg, wParam, lParam);
}
else
#endif
return 0;
#if defined(MENUHINTS) && defined(FEAT_MENU)
case WM_MENUSELECT:
if (((UINT) LOWORD(lParam)
& (0xffff ^ (MF_MOUSESELECT + MF_BITMAP + MF_POPUP)))
== MF_HILITE
&& (State & CMDLINE) == 0)
{
UINT idButton;
int idx;
vimmenu_T *pMenu;
idButton = (UINT)LOWORD(wParam);
pMenu = gui_mswin_find_menu(root_menu, idButton);
if (pMenu)
{
idx = MENU_INDEX_TIP;
msg_clr_cmdline();
if (pMenu->strings[idx])
msg(pMenu->strings[idx]);
else
msg("");
setcursor();
out_flush();
}
}
break;
#endif
case WM_NCHITTEST:
{
LRESULT result;
int x, y;
int xPos = GET_X_LPARAM(lParam);
result = MyWindowProc(hwnd, uMsg, wParam, lParam);
if (result == HTCLIENT)
{
gui_mch_get_winpos(&x, &y);
xPos -= x;
if (xPos < 48)
return HTBOTTOMLEFT;
else
return HTBOTTOMRIGHT;
}
else
return result;
}
default:
#ifdef MSWIN_FIND_REPLACE
if (uMsg == s_findrep_msg && s_findrep_msg != 0)
{
_OnFindRepl();
}
#endif
return MyWindowProc(hwnd, uMsg, wParam, lParam);
}
return 1;
}
void
gui_mch_prepare(int *argc, char **argv)
{
}
int
gui_mch_init(void)
{
const char szVimWndClass[] = VIM_CLASS;
const char szTextAreaClass[] = "VimTextArea";
WNDCLASS wndclass;
#ifdef WIN16_3DLOOK
Ctl3dRegister(s_hinst);
Ctl3dAutoSubclass(s_hinst);
#endif
display_errors();
gui.scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
gui.scrollbar_height = GetSystemMetrics(SM_CYHSCROLL);
#ifdef FEAT_MENU
gui.menu_height = 0;
#endif
gui.border_width = 0;
gui.currBgColor = INVALCOLOR;
s_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
if (GetClassInfo(s_hinst, szVimWndClass, &wndclass) == 0) {
wndclass.style = 0;
wndclass.lpfnWndProc = _WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = s_hinst;
wndclass.hIcon = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(IDR_VIM));
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = s_brush;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szVimWndClass;
if ((
#ifdef GLOBAL_IME
atom =
#endif
RegisterClass(&wndclass)) == 0)
return FAIL;
}
s_hwnd = CreateWindow(
szVimWndClass, "Vim MSWindows GUI",
WS_OVERLAPPEDWINDOW,
gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
100,
100,
NULL, NULL,
s_hinst, NULL);
if (s_hwnd == NULL)
return FAIL;
#ifdef GLOBAL_IME
global_ime_init(atom, s_hwnd);
#endif
if (GetClassInfo(s_hinst, szTextAreaClass, &wndclass) == 0) {
wndclass.style = CS_OWNDC;
wndclass.lpfnWndProc = _TextAreaWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = s_hinst;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szTextAreaClass;
if (RegisterClass(&wndclass) == 0)
return FAIL;
}
s_textArea = CreateWindow(
szTextAreaClass, "Vim text area",
WS_CHILD | WS_VISIBLE, 0, 0,
100,
100,
s_hwnd, NULL,
s_hinst, NULL);
if (s_textArea == NULL)
return FAIL;
#ifdef FEAT_MENU
s_menuBar = CreateMenu();
#endif
s_hdc = GetDC(s_textArea);
#ifdef MSWIN16_FASTTEXT
SetBkMode(s_hdc, OPAQUE);
#endif
DragAcceptFiles(s_hwnd, TRUE);
gui_mch_def_colors();
set_normal_colors();
gui_check_colors();
gui.def_norm_pixel = gui.norm_pixel;
gui.def_back_pixel = gui.back_pixel;
highlight_gui_started();
gui.border_offset = gui.border_width;
get_dialog_font_metrics();
#ifdef FEAT_TOOLBAR
initialise_toolbar();
#endif
#ifdef MSWIN_FIND_REPLACE
s_findrep_msg = RegisterWindowMessage(FINDMSGSTRING);
s_findrep_struct.lStructSize = sizeof(s_findrep_struct);
s_findrep_struct.lpstrFindWhat = alloc(MSWIN_FR_BUFSIZE);
s_findrep_struct.lpstrFindWhat[0] = NUL;
s_findrep_struct.lpstrReplaceWith = alloc(MSWIN_FR_BUFSIZE);
s_findrep_struct.lpstrReplaceWith[0] = NUL;
s_findrep_struct.wFindWhatLen = MSWIN_FR_BUFSIZE;
s_findrep_struct.wReplaceWithLen = MSWIN_FR_BUFSIZE;
#endif
return OK;
}
void
gui_mch_set_shellsize(int width, int height,
int min_width, int min_height, int base_width, int base_height,
int direction)
{
RECT workarea_rect;
int win_width, win_height;
int win_xpos, win_ypos;
WINDOWPLACEMENT wndpl;
workarea_rect.left = 0;
workarea_rect.top = 0;
workarea_rect.right = GetSystemMetrics(SM_CXSCREEN);
workarea_rect.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
wndpl.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(s_hwnd, &wndpl);
if (wndpl.showCmd == SW_SHOWNORMAL)
{
win_xpos = wndpl.rcNormalPosition.left;
win_ypos = wndpl.rcNormalPosition.top;
}
else
{
win_xpos = workarea_rect.left;
win_ypos = workarea_rect.top;
}
win_width = width + GetSystemMetrics(SM_CXFRAME) * 2;
win_height = height + GetSystemMetrics(SM_CYFRAME) * 2
+ GetSystemMetrics(SM_CYCAPTION)
#ifdef FEAT_MENU
+ gui_mswin_get_menu_height(FALSE)
#endif
;
if ((direction & RESIZE_HOR) && win_xpos + win_width > workarea_rect.right)
win_xpos = workarea_rect.right - win_width;
if ((direction & RESIZE_HOR) && win_xpos < workarea_rect.left)
win_xpos = workarea_rect.left;
if ((direction & RESIZE_VERT)
&& win_ypos + win_height > workarea_rect.bottom)
win_ypos = workarea_rect.bottom - win_height;
if ((direction & RESIZE_VERT) && win_ypos < workarea_rect.top)
win_ypos = workarea_rect.top;
SetWindowPos(s_hwnd, NULL, win_xpos, win_ypos, win_width, win_height,
SWP_NOZORDER | SWP_NOACTIVATE);
#ifdef FEAT_MENU
gui_mswin_get_menu_height(!gui.starting);
#endif
}
void
gui_mch_set_scrollbar_thumb(
scrollbar_T *sb,
long val,
long size,
long max)
{
sb->scroll_shift = 0;
while (max > 32767)
{
max = (max + 1) >> 1;
val >>= 1;
size >>= 1;
++sb->scroll_shift;
}
if (sb->scroll_shift > 0)
++size;
SetScrollRange(sb->id, SB_CTL, 0, (int) max, FALSE);
SetScrollPos(sb->id, SB_CTL, (int) val, TRUE);
}
void
gui_mch_set_font(GuiFont font)
{
gui.currFont = font;
SelectFont(s_hdc, gui.currFont);
}
void
gui_mch_set_fg_color(guicolor_T color)
{
gui.currFgColor = color;
SetTextColor(s_hdc, gui.currFgColor);
}
void
gui_mch_set_bg_color(guicolor_T color)
{
if (gui.currBgColor == color)
return;
gui.currBgColor = color;
SetBkColor(s_hdc, gui.currBgColor);
}
void
gui_mch_set_sp_color(guicolor_T color)
{
}
void
gui_mch_draw_string(
int row,
int col,
char_u *text,
int len,
int flags)
{
#ifndef MSWIN16_FASTTEXT
static int *padding = NULL;
static int pad_size = 0;
int i;
#endif
HPEN hpen, old_pen;
int y;
#ifndef MSWIN16_FASTTEXT
HBRUSH hbr;
RECT rc;
if (!(flags & DRAW_TRANSP))
{
rc.left = FILL_X(col);
rc.top = FILL_Y(row);
#ifdef FEAT_MBYTE
if (has_mbyte)
{
rc.right = FILL_X(col + mb_string2cells(text, len));
}
else
#endif
rc.right = FILL_X(col + len);
rc.bottom = FILL_Y(row + 1);
hbr = CreateSolidBrush(gui.currBgColor);
FillRect(s_hdc, &rc, hbr);
DeleteBrush(hbr);
SetBkMode(s_hdc, TRANSPARENT);
if (flags & DRAW_CURSOR)
{
pcliprect = &rc;
foptions = ETO_CLIPPED;
}
}
#else
#endif
#ifndef MSWIN16_FASTTEXT
if (pad_size != Columns || padding == NULL || padding[0] != gui.char_width)
{
vim_free(padding);
pad_size = Columns;
padding = (int *)alloc(pad_size * sizeof(int));
if (padding != NULL)
for (i = 0; i < pad_size; i++)
padding[i] = gui.char_width;
}
#endif
#ifndef MSWIN16_FASTTEXT
ExtTextOut(s_hdc, TEXT_X(col), TEXT_Y(row), 0, NULL,
(char *)text, len, padding);
#else
TextOut(s_hdc, TEXT_X(col), TEXT_Y(row), (char *)text, len);
#endif
if (flags & DRAW_UNDERL)
{
hpen = CreatePen(PS_SOLID, 1, gui.currFgColor);
old_pen = SelectObject(s_hdc, hpen);
y = FILL_Y(row + 1) - 1;
#ifndef MSWIN16_FASTTEXT
if (p_linespace > 1)
y -= p_linespace - 1;
#endif
MoveToEx(s_hdc, FILL_X(col), y, NULL);
LineTo(s_hdc, FILL_X(col + len), y);
DeleteObject(SelectObject(s_hdc, old_pen));
}
}
void
gui_mch_flush(void)
{
}
static void
clear_rect(RECT *rcp)
{
gui_mch_set_bg_color(gui.back_pixel);
ExtTextOut(s_hdc, 0, 0, ETO_CLIPPED | ETO_OPAQUE, rcp, NULL, 0, NULL);
}
void
gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
{
*screen_w = GetSystemMetrics(SM_CXFULLSCREEN)
- GetSystemMetrics(SM_CXFRAME) * 2;
*screen_h = GetSystemMetrics(SM_CYFULLSCREEN)
- GetSystemMetrics(SM_CYFRAME) * 2
#ifdef FEAT_MENU
- gui_mswin_get_menu_height(FALSE)
#endif
;
}
#if defined(FEAT_MENU) || defined(PROTO)
void
gui_mch_add_menu(
vimmenu_T *menu,
int pos)
{
vimmenu_T *parent = menu->parent;
menu->submenu_id = CreatePopupMenu();
menu->id = s_menu_id++;
if (menu_is_menubar(menu->name))
{
InsertMenu((parent == NULL) ? s_menuBar : parent->submenu_id,
(UINT)pos, MF_POPUP | MF_STRING | MF_BYPOSITION,
(UINT)menu->submenu_id, menu->name);
}
if (parent == NULL)
gui_mswin_get_menu_height(!gui.starting);
}
void
gui_mch_show_popupmenu(vimmenu_T *menu)
{
POINT mp;
(void)GetCursorPos((LPPOINT)&mp);
gui_mch_show_popupmenu_at(menu, (int)mp.x, (int)mp.y);
}
void
gui_make_popup(char_u *path_name, int mouse_pos)
{
vimmenu_T *menu = gui_find_menu(path_name);
if (menu != NULL)
{
DWORD temp_p;
POINT p;
temp_p = GetDCOrg(s_hdc);
p.x = LOWORD(temp_p);
p.y = HIWORD(temp_p);
if (mouse_pos)
{
int mx, my;
gui_mch_getmouse(&mx, &my);
p.x += mx;
p.y += my;
}
else if (curwin != NULL)
{
p.x += TEXT_X(W_WINCOL(curwin) + curwin->w_wcol + 1);
p.y += TEXT_Y(W_WINROW(curwin) + curwin->w_wrow + 1);
}
msg_scroll = FALSE;
gui_mch_show_popupmenu_at(menu, (int)p.x, (int)p.y);
}
}
void
gui_mch_add_menu_item(
vimmenu_T *menu,
int idx)
{
vimmenu_T *parent = menu->parent;
menu->id = s_menu_id++;
menu->submenu_id = NULL;
#ifdef FEAT_TOOLBAR
if (menu_is_toolbar(parent->name))
{
TBBUTTON newtb;
vim_memset(&newtb, 0, sizeof(newtb));
if (menu_is_separator(menu->name))
{
newtb.iBitmap = 0;
newtb.fsStyle = TBSTYLE_SEP;
}
else
{
if (menu->iconidx >= TOOLBAR_BITMAP_COUNT)
newtb.iBitmap = -1;
else
newtb.iBitmap = menu->iconidx;
newtb.fsStyle = TBSTYLE_BUTTON;
}
newtb.idCommand = menu->id;
newtb.fsState = TBSTATE_ENABLED;
SendMessage(s_toolbarhwnd, TB_INSERTBUTTON, (WPARAM)idx,
(LPARAM)&newtb);
menu->submenu_id = (HMENU)-1;
}
else
#endif
{
InsertMenu(parent->submenu_id, (UINT)idx,
(menu_is_separator(menu->name) ? MF_SEPARATOR : MF_STRING)
| MF_BYPOSITION,
(UINT)menu->id, menu->name);
}
}
void
gui_mch_destroy_menu(vimmenu_T *menu)
{
UINT i, j;
char pants[80];
#ifdef FEAT_TOOLBAR
if (menu->submenu_id == (HMENU)-1)
{
int iButton;
iButton = SendMessage(s_toolbarhwnd, TB_COMMANDTOINDEX, (WPARAM)menu->id, 0);
SendMessage(s_toolbarhwnd, TB_DELETEBUTTON, (WPARAM)iButton, 0);
}
else
#endif
{
if (menu->parent != NULL
&& menu_is_popup(menu->parent->dname)
&& menu->parent->submenu_id != NULL)
RemoveMenu(menu->parent->submenu_id, menu->id, MF_BYCOMMAND);
else if (menu->submenu_id == NULL)
RemoveMenu(s_menuBar, menu->id, MF_BYCOMMAND);
else if (menu->parent != NULL)
{
i = GetMenuItemCount(menu->parent->submenu_id);
for (j = 0; j < i; ++j)
{
GetMenuString(menu->parent->submenu_id, j,
pants, 80, MF_BYPOSITION);
if (strcmp(pants, menu->name) == 0)
{
RemoveMenu(menu->parent->submenu_id, j, MF_BYPOSITION);
break;
}
}
}
else
{
i = GetMenuItemCount(s_menuBar);
for (j = 0; j < i; ++j)
{
GetMenuString(s_menuBar, j, pants, 80, MF_BYPOSITION);
if (strcmp(pants, menu->name) == 0)
{
RemoveMenu(s_menuBar, j, MF_BYPOSITION);
break;
}
}
}
if (menu->submenu_id != NULL)
DestroyMenu(menu->submenu_id);
}
DrawMenuBar(s_hwnd);
}
void
gui_mch_menu_grey(
vimmenu_T *menu,
int grey)
{
#ifdef FEAT_TOOLBAR
if (menu->submenu_id == (HMENU)-1)
{
SendMessage(s_toolbarhwnd, TB_ENABLEBUTTON,
(WPARAM)menu->id, (LPARAM) MAKELONG((grey ? FALSE : TRUE), 0) );
}
else
#endif
if (grey)
EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_GRAYED);
else
EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED);
}
#endif
#define add_string(s) strcpy((LPSTR)p, s); (LPSTR)p += (strlen((LPSTR)p) + 1)
#define add_word(x) *p++ = (x)
#define add_byte(x) *((LPSTR)p)++ = (x)
#define add_long(x) *((LPDWORD)p)++ = (x)
#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
static BOOL CALLBACK
dialog_callback(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
if (message == WM_INITDIALOG)
{
CenterWindow(hwnd, GetWindow(hwnd, GW_OWNER));
(void)SetFocus(hwnd);
if (dialog_default_button > IDCANCEL)
(void)SetFocus(GetDlgItem(hwnd, dialog_default_button));
return FALSE;
}
if (message == WM_COMMAND)
{
int button = LOWORD(wParam);
if (button >= DLG_NONBUTTON_CONTROL)
return TRUE;
if (s_textfield != NULL)
GetDlgItemText(hwnd, DLG_NONBUTTON_CONTROL + 2,
s_textfield, IOSIZE);
if (button == IDOK)
EndDialog(hwnd, dialog_default_button);
else
EndDialog(hwnd, button - IDCANCEL);
return TRUE;
}
if ((message == WM_SYSCOMMAND) && (wParam == SC_CLOSE))
{
EndDialog(hwnd, 0);
return TRUE;
}
return FALSE;
}
static const char_u dlg_icons[] =
{
IDR_VIM,
IDR_VIM_ERROR,
IDR_VIM_ALERT,
IDR_VIM_INFO,
IDR_VIM_QUESTION
};
int
gui_mch_dialog(
int type,
char_u *title,
char_u *message,
char_u *buttons,
int dfltbutton,
char_u *textfield)
{
FARPROC dp;
LPWORD p, pnumitems;
int numButtons;
int *buttonWidths, *buttonPositions;
int buttonYpos;
int nchar, i;
DWORD lStyle;
int dlgwidth = 0;
int dlgheight;
int editboxheight;
int horizWidth;
int msgheight;
char_u *pstart;
char_u *pend;
char_u *tbuffer;
RECT rect;
HWND hwnd;
HDC hdc;
HFONT oldFont;
TEXTMETRIC fontInfo;
int fontHeight;
int textWidth, minButtonWidth, messageWidth;
int maxDialogWidth;
int vertical;
int dlgPaddingX;
int dlgPaddingY;
HGLOBAL hglbDlgTemp;
#ifndef NO_CONSOLE
if (silent_mode)
return dfltbutton;
#endif
if (s_hwnd == NULL && gui_mch_init() == FAIL)
return dfltbutton;
if ((type < 0) || (type > VIM_LAST_TYPE))
type = 0;
hglbDlgTemp = GlobalAlloc(GHND, DLG_ALLOC_SIZE);
if (hglbDlgTemp == NULL)
return -1;
p = (LPWORD) GlobalLock(hglbDlgTemp);
if (p == NULL)
return -1;
tbuffer = vim_strsave(buttons);
if (tbuffer == NULL)
return -1;
--dfltbutton;
numButtons = 1;
for (i = 0; tbuffer[i] != '\0'; i++)
{
if (tbuffer[i] == DLG_BUTTON_SEP)
numButtons++;
}
if (dfltbutton >= numButtons)
dfltbutton = 0;
buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE);
if (buttonWidths == NULL)
return -1;
buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE);
if (buttonPositions == NULL)
return -1;
hwnd = GetDesktopWindow();
hdc = GetWindowDC(hwnd);
oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT));
dlgPaddingX = DLG_OLD_STYLE_PADDING_X;
dlgPaddingY = DLG_OLD_STYLE_PADDING_Y;
GetTextMetrics(hdc, &fontInfo);
fontHeight = fontInfo.tmHeight;
minButtonWidth = GetTextWidth(hdc, "Cancel", 6);
GetWindowRect(s_hwnd, &rect);
maxDialogWidth = rect.right - rect.left
- GetSystemMetrics(SM_CXFRAME) * 2;
if (maxDialogWidth < DLG_MIN_MAX_WIDTH)
maxDialogWidth = DLG_MIN_MAX_WIDTH;
pstart = message;
messageWidth = 0;
msgheight = 0;
do
{
pend = vim_strchr(pstart, DLG_BUTTON_SEP);
if (pend == NULL)
pend = pstart + STRLEN(pstart);
msgheight += fontHeight;
textWidth = GetTextWidth(hdc, pstart, pend - pstart);
if (textWidth > messageWidth)
messageWidth = textWidth;
pstart = pend + 1;
} while (*pend != NUL);
dlgwidth = messageWidth;
dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX;
if (msgheight < DLG_ICON_HEIGHT)
msgheight = DLG_ICON_HEIGHT;
vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
if (!vertical)
{
horizWidth = dlgPaddingX;
pstart = tbuffer;
i = 0;
do
{
pend = vim_strchr(pstart, DLG_BUTTON_SEP);
if (pend == NULL)
pend = pstart + STRLEN(pstart); textWidth = GetTextWidth(hdc, pstart, pend - pstart);
if (textWidth < minButtonWidth)
textWidth = minButtonWidth;
textWidth += dlgPaddingX;
buttonWidths[i] = textWidth;
buttonPositions[i++] = horizWidth;
horizWidth += textWidth + dlgPaddingX;
pstart = pend + 1;
} while (*pend != NUL);
if (horizWidth > maxDialogWidth)
vertical = TRUE; else if (horizWidth > dlgwidth)
dlgwidth = horizWidth;
}
if (vertical)
{
pstart = tbuffer;
do
{
pend = vim_strchr(pstart, DLG_BUTTON_SEP);
if (pend == NULL)
pend = pstart + STRLEN(pstart); textWidth = GetTextWidth(hdc, pstart, pend - pstart);
textWidth += dlgPaddingX;
textWidth += DLG_VERT_PADDING_X * 2;
if (textWidth > dlgwidth)
dlgwidth = textWidth;
pstart = pend + 1;
} while (*pend != NUL);
}
if (dlgwidth < DLG_MIN_WIDTH)
dlgwidth = DLG_MIN_WIDTH;
lStyle = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE ;
add_long(lStyle);
pnumitems = p;
add_byte(0); add_word(10); add_word(10); add_word(PixelToDialogX(dlgwidth));
if (vertical)
dlgheight = msgheight + 2 * dlgPaddingY +
DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons;
else
dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight;
editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y;
if (textfield != NULL)
dlgheight += editboxheight;
add_word(PixelToDialogY(dlgheight));
add_byte(0); add_byte(0);
add_string(title ? title : ("Vim"VIM_VERSION_MEDIUM));
buttonYpos = msgheight + 2 * dlgPaddingY;
if (textfield != NULL)
buttonYpos += editboxheight;
pstart = tbuffer; horizWidth = (dlgwidth - horizWidth) / 2;
for (i = 0; i < numButtons; i++)
{
for ( pend = pstart;
*pend && (*pend != DLG_BUTTON_SEP);
pend++)
;
if (*pend)
*pend = '\0';
if (vertical)
{
p = add_dialog_element(p,
((i == dfltbutton || dfltbutton < 0) && textfield != NULL
? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
PixelToDialogX(DLG_VERT_PADDING_X),
PixelToDialogY(buttonYpos
+ 2 * fontHeight * i),
PixelToDialogX(dlgwidth - 2 * DLG_VERT_PADDING_X),
(WORD)(PixelToDialogY(2 * fontHeight) - 1),
(WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
}
else
{
p = add_dialog_element(p,
((i == dfltbutton || dfltbutton < 0) && textfield != NULL
? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
PixelToDialogX(horizWidth + buttonPositions[i]),
PixelToDialogY(buttonYpos),
PixelToDialogX(buttonWidths[i]),
(WORD)(PixelToDialogY(2 * fontHeight) - 1),
(WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
}
pstart = pend + 1;
}
*pnumitems += numButtons;
p = add_dialog_element(p, SS_ICON,
PixelToDialogX(dlgPaddingX),
PixelToDialogY(dlgPaddingY),
PixelToDialogX(DLG_ICON_WIDTH),
PixelToDialogY(DLG_ICON_HEIGHT),
DLG_NONBUTTON_CONTROL + 0, (BYTE)0x82,
&dlg_icons[type]);
p = add_dialog_element(p, SS_LEFT,
PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
PixelToDialogY(dlgPaddingY),
(WORD)(PixelToDialogX(messageWidth) + 1),
PixelToDialogY(msgheight),
DLG_NONBUTTON_CONTROL + 1, (BYTE)0x82, message);
if (textfield != NULL)
{
p = add_dialog_element(p, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP | WS_BORDER,
PixelToDialogX(2 * dlgPaddingX),
PixelToDialogY(2 * dlgPaddingY + msgheight),
PixelToDialogX(dlgwidth - 4 * dlgPaddingX),
PixelToDialogY(fontHeight + dlgPaddingY),
DLG_NONBUTTON_CONTROL + 2, (BYTE)0x81, textfield);
*pnumitems += 1;
}
*pnumitems += 2;
SelectFont(hdc, oldFont);
ReleaseDC(hwnd, hdc);
dp = MakeProcInstance((FARPROC)dialog_callback, s_hinst);
if (textfield != NULL)
{
dialog_default_button = DLG_NONBUTTON_CONTROL + 2;
s_textfield = textfield;
}
else
{
dialog_default_button = IDCANCEL + 1 + dfltbutton;
s_textfield = NULL;
}
nchar = DialogBoxIndirect(
s_hinst,
(HGLOBAL) hglbDlgTemp,
s_hwnd,
(DLGPROC)dp);
FreeProcInstance( dp );
GlobalUnlock(hglbDlgTemp);
GlobalFree(hglbDlgTemp);
vim_free(tbuffer);
vim_free(buttonWidths);
vim_free(buttonPositions);
return nchar;
}
static LPWORD
add_dialog_element(
LPWORD p,
DWORD lStyle,
WORD x,
WORD y,
WORD w,
WORD h,
WORD Id,
BYTE clss,
const char *caption)
{
lStyle = lStyle | WS_VISIBLE | WS_CHILD;
add_word(x);
add_word(y);
add_word(w);
add_word(h);
add_word(Id);
add_long(lStyle);
add_byte(clss);
if (((lStyle & SS_ICON) != 0) && (clss == 0x82))
{
add_byte(0xff);
add_byte(*caption);
}
else
add_string(caption);
add_byte(0);
return p;
}
#undef add_byte
#undef add_string
#undef add_long
#undef add_word
#endif
static void
get_dialog_font_metrics(void)
{
DWORD dlgFontSize;
dlgFontSize = GetDialogBaseUnits();
s_dlgfntwidth = LOWORD(dlgFontSize);
s_dlgfntheight = HIWORD(dlgFontSize);
}
#if defined(FEAT_TOOLBAR) || defined(PROTO)
#include "gui_w3~1.h"
static void
initialise_toolbar(void)
{
s_toolbarhwnd = CreateToolbar(
s_hwnd,
WS_CHILD | WS_VISIBLE,
CMD_TB_BASE,
31, s_hinst,
IDR_TOOLBAR1, NULL,
0 );
gui_mch_show_toolbar(vim_strchr(p_go, GO_TOOLBAR) != NULL);
}
#endif
#if defined(FEAT_OLE) || defined(FEAT_EVAL) || defined(PROTO)
void
gui_mch_set_foreground(void)
{
if (IsIconic(s_hwnd))
SendMessage(s_hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
SetActiveWindow(s_hwnd);
}
#endif