To: vim_dev@googlegroups.com Subject: Patch 7.4.1364 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1364 Problem: The Win 16 code is not maintained and unused. Solution: Remove the Win 16 support. Files: src/gui_w16.c, src/gui_w32.c, src/gui_w48.c, src/Make_w16.mak, src/Makefile, src/Make_cyg_ming.mak, src/Make_mvc.mak, src/proto/gui_w16.pro, src/proto/os_win16.pro, src/guiw16rc.h, src/vim16.rc, src/vim16.def, src/tools16.bmp, src/eval.c, src/gui.c, src/misc2.c, src/option.c, src/os_msdos.c, src/os_mswin.c, src/os_win16.c, src/os_win16.h, src/version.c, src/winclip.c, src/feature.h, src/proto.h, src/vim.h, Filelist *** ../vim-7.4.1363/src/gui_w16.c 2015-08-11 19:13:55.138175689 +0200 --- src/gui_w16.c 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,1564 **** - /* vi:set ts=8 sts=4 sw=4: - * - * VIM - Vi IMproved by Bram Moolenaar - * GUI support by Robert Webb - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - /* - * gui_w16.c - * - * GUI support for Microsoft Windows 3.1x - * - * George V. Reilly wrote the original Win32 GUI. - * Robert Webb reworked it to use the existing GUI stuff and added menu, - * scrollbars, etc. - * - * Vince Negri then butchered the code to get it compiling for - * 16-bit windows. - * - */ - - /* Win16 doesn't use the "W" methods. */ - #define pDispatchMessage DispatchMessage - #define pGetMessage GetMessage - #define pIsDialogMessage IsDialogMessage - #define pPeekMessage PeekMessage - - /* - * Include the common stuff for MS-Windows GUI. - */ - #include "gui_w48.c" - - #include "guiw16rc.h" - - /* Undocumented Windows Message - not even defined in some SDK headers */ - #define WM_EXITSIZEMOVE 0x0232 - - - #ifdef FEAT_TOOLBAR - # define CMD_TB_BASE (99) - # include - #endif - - #ifdef PROTO - # define WINAPI - #endif - - #define HANDLE_WM_DROPFILES(hwnd, wParam, lParam, fn) \ - ((fn)((hwnd), (HDROP)(wParam)), 0L) - - - /* Local variables: */ - - #ifdef FEAT_MENU - static UINT s_menu_id = 100; - #endif - - - #define VIM_NAME "vim" - #define VIM_CLASS "Vim" - - #define DLG_ALLOC_SIZE 16 * 1024 - - /* - * stuff for dialogs, menus, tearoffs etc. - */ - #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 - /* - * Figure out how high the menu bar is at the moment. - */ - static int - gui_mswin_get_menu_height( - int fix_window) /* If TRUE, resize window if menu height changed */ - { - 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); - - /* get window rect of s_hwnd - * get client rect of s_hwnd - * get cap height - * subtract from window rect, the sum of client height, - * (if not maximized)frame thickness, and caption height. - */ - 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 /*FEAT_MENU*/ - - - /* - * Even though we have _DuringSizing() which makes the rubber band a valid - * size, we need this for when the user maximises the window. - * TODO: Doesn't seem to adjust the width though for some reason. - */ - 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) - { - /* - TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n", - hwnd, uMsg, wParam, 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_ACTIVATE, _OnActivate); */ - HANDLE_MSG(hwnd, WM_CHAR, _OnChar); - HANDLE_MSG(hwnd, WM_CLOSE, _OnClose); - /* HANDLE_MSG(hwnd, WM_COMMAND, _OnCommand); */ - 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_MOVE, _OnMove); */ - /* HANDLE_MSG(hwnd, WM_NCACTIVATE, _OnNCActivate); */ - HANDLE_MSG(hwnd, WM_SETFOCUS, _OnSetFocus); - HANDLE_MSG(hwnd, WM_SIZE, _OnSize); - /* HANDLE_MSG(hwnd, WM_SYSCOMMAND, _OnSysCommand); */ - /* HANDLE_MSG(hwnd, WM_SYSKEYDOWN, _OnAltKey); */ - HANDLE_MSG(hwnd, WM_VSCROLL, _OnScroll); - HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGING, _OnWindowPosChanging); - HANDLE_MSG(hwnd, WM_ACTIVATEAPP, _OnActivateApp); - - case WM_QUERYENDSESSION: /* System wants to go down. */ - gui_shell_closed(); /* Will exit when no changed buffers. */ - return FALSE; /* Do NOT allow system to go down. */ - - case WM_ENDSESSION: - if (wParam) /* system only really goes down when wParam is TRUE */ - _OnEndSession(); - break; - - case WM_SYSCHAR: - /* - * if 'winaltkeys' is "no", or it's "menu" and it's not a menu - * shortcut key, handle like a typed ALT key, otherwise call Windows - * ALT key handling. - */ - #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 - /* Only when menu is active, ALT key is used for that. */ - 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) - { - (void)gui_mch_get_winpos(&x, &y); - xPos -= x; - - if (xPos < 48) /* TODO should use system metric?*/ - return HTBOTTOMLEFT; - else - return HTBOTTOMRIGHT; - } - else - return result; - } - /* break; */ - default: - #ifdef MSWIN_FIND_REPLACE - if (uMsg == s_findrep_msg && s_findrep_msg != 0) - { - _OnFindRepl(); - } - #endif - return MyWindowProc(hwnd, uMsg, wParam, lParam); - } - - return 1; - } - - - - /* - * End of call-back routines - */ - - - /* - * Parse the GUI related command-line arguments. Any arguments used are - * deleted from argv, and *argc is decremented accordingly. This is called - * when vim is started, whether or not the GUI has been started. - */ - void - gui_mch_prepare(int *argc, char **argv) - { - /* No special args for win16 GUI at the moment. */ - - } - - /* - * Initialise the GUI. Create all the windows, set up all the call-backs - * etc. - */ - 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 any pending error messages */ - display_errors(); - - gui.scrollbar_width = GetSystemMetrics(SM_CXVSCROLL); - gui.scrollbar_height = GetSystemMetrics(SM_CYHSCROLL); - #ifdef FEAT_MENU - gui.menu_height = 0; /* Windows takes care of this */ - #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, /* Any value will do */ - 100, /* Any value will do */ - NULL, NULL, - s_hinst, NULL); - - if (s_hwnd == NULL) - return FAIL; - - #ifdef GLOBAL_IME - global_ime_init(atom, s_hwnd); - #endif - - /* Create the text area window */ - 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, /* Any value will do for now */ - 100, /* Any value will do for now */ - 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); - - /* Do we need to bother with this? */ - /* m_fMouseAvail = GetSystemMetrics(SM_MOUSEPRESENT); */ - - /* Get background/foreground colors from the system */ - gui_mch_def_colors(); - - /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc - * file) */ - set_normal_colors(); - - /* - * Check that none of the colors are the same as the background color. - * Then store the current values as the defaults. - */ - gui_check_colors(); - gui.def_norm_pixel = gui.norm_pixel; - gui.def_back_pixel = gui.back_pixel; - - /* Get the colors for the highlight groups (gui_check_colors() might have - * changed them) */ - highlight_gui_started(); - - /* - * Start out by adding the configured border width into the border offset - */ - gui.border_offset = gui.border_width; - - - /* - * compute a couple of metrics used for the dialogs - */ - get_dialog_font_metrics(); - #ifdef FEAT_TOOLBAR - /* - * Create the toolbar - */ - initialise_toolbar(); - #endif - #ifdef MSWIN_FIND_REPLACE - /* - * Initialise the dialog box stuff - */ - s_findrep_msg = RegisterWindowMessage(FINDMSGSTRING); - - /* Initialise the struct */ - 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; - } - - - /* - * Set the size of the window to the given width and height in pixels. - */ - 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; - - /* try to keep window completely on screen */ - /* get size of the screen work area - use SM_CYFULLSCREEN - * instead of SM_CYSCREEN so that we don't overlap the - * taskbar if someone fires us up on Win95/NT */ - workarea_rect.left = 0; - workarea_rect.top = 0; - workarea_rect.right = GetSystemMetrics(SM_CXSCREEN); - workarea_rect.bottom = GetSystemMetrics(SM_CYFULLSCREEN); - - /* get current position of our window */ - 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; - } - - /* compute the size of the outside of the window */ - 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 the window is going off the screen, move it on to the screen */ - 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; - - /* set window position */ - SetWindowPos(s_hwnd, NULL, win_xpos, win_ypos, win_width, win_height, - SWP_NOZORDER | SWP_NOACTIVATE); - - #ifdef FEAT_MENU - /* Menu may wrap differently now */ - 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); - } - - - /* - * Set the current text font. - */ - void - gui_mch_set_font(GuiFont font) - { - gui.currFont = font; - SelectFont(s_hdc, gui.currFont); - } - - /* - * Set the current text foreground color. - */ - void - gui_mch_set_fg_color(guicolor_T color) - { - gui.currFgColor = color; - SetTextColor(s_hdc, gui.currFgColor); - } - - /* - * Set the current text background color. - */ - void - gui_mch_set_bg_color(guicolor_T color) - { - if (gui.currBgColor == color) - return; - - gui.currBgColor = color; - SetBkColor(s_hdc, gui.currBgColor); - } - - /* - * Set the current text special color. - */ - void - gui_mch_set_sp_color(guicolor_T color) - { - /* TODO */ - } - - - - 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 - /* - * Italic and bold text seems to have an extra row of pixels at the bottom - * (below where the bottom of the character should be). If we draw the - * characters with a solid background, the top row of pixels in the - * character below will be overwritten. We can fix this by filling in the - * background ourselves, to the correct character proportions, and then - * writing the character in transparent mode. Still have a problem when - * the character is "_", which gets written on to the character below. - * New fix: set gui.char_ascent to -1. This shifts all characters up one - * pixel in their slots, which fixes the problem with the bottom row of - * pixels. We still need this code because otherwise the top row of pixels - * becomes a problem. - webb. - */ - HBRUSH hbr; - RECT rc; - - if (!(flags & DRAW_TRANSP)) - { - /* - * Clear background first. - * Note: FillRect() excludes right and bottom of rectangle. - */ - rc.left = FILL_X(col); - rc.top = FILL_Y(row); - #ifdef FEAT_MBYTE - if (has_mbyte) - { - /* Compute the length in display cells. */ - 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); - - /* - * When drawing block cursor, prevent inverted character spilling - * over character cell (can happen with bold/italic) - */ - if (flags & DRAW_CURSOR) - { - pcliprect = &rc; - foptions = ETO_CLIPPED; - } - } - #else - /* - * Alternative: write the characters in opaque mode, since we have blocked - * bold or italic fonts. - */ - /* The OPAQUE mode and backcolour have already been set */ - #endif - /* The forecolor and font have already been set */ - - #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 - - /* - * We have to provide the padding argument because italic and bold versions - * of fixed-width fonts are often one pixel or so wider than their normal - * versions. - * No check for DRAW_BOLD, Windows will have done it already. - */ - #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); - /* When p_linespace is 0, overwrite the bottom row of pixels. - * Otherwise put the line just below the character. */ - 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); - /* Note: LineTo() excludes the last pixel in the line. */ - LineTo(s_hdc, FILL_X(col + len), y); - DeleteObject(SelectObject(s_hdc, old_pen)); - } - } - - - /* - * Output routines. - */ - - /* Flush any output to the screen */ - void - gui_mch_flush(void) - { - /* Is anything needed here? */ - } - - static void - clear_rect(RECT *rcp) - { - /* Use trick for fast rect clear */ - 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; - /* FIXME: dirty trick: Because the gui_get_base_height() doesn't include - * the menubar for MSwin, we subtract it from the screen height, so that - * the window size can be made to fit on the screen. */ - *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) - /* - * Add a sub menu to the menu bar. - */ - 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); - } - - /* Fix window size if menu may have wrapped */ - 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) - { - /* Find the position of the current cursor */ - 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); - } - } - - /* - * Add a menu item to a menu - */ - 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); - } - } - - /* - * Destroy the machine specific menu widget. - */ - void - gui_mch_destroy_menu(vimmenu_T *menu) - { - UINT i, j; - char pants[80]; /* hack*/ - #ifdef FEAT_TOOLBAR - /* - * is this a toolbar button? - */ - 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 - { - /* - * negri: horrible API bug when running 16-bit programs under Win9x or - * NT means that we can't use MF_BYCOMMAND for menu items which have - * submenus, including the top-level headings. We have to find the menu - * item and use MF_BYPOSITION instead. :-p - */ - 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); - } - - - /* - * Make a menu either grey or not grey. - */ - void - gui_mch_menu_grey( - vimmenu_T *menu, - int grey) - { - #ifdef FEAT_TOOLBAR - /* - * is this a toolbar button? - */ - 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 /*FEAT_MENU*/ - - - /* define some macros used to make the dialogue creation more readable */ - - #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) - /* - * stuff for dialogs - */ - - /* - * The callback routine used by all the dialogs. Very simple. First, - * acknowledges the INITDIALOG message so that Windows knows to do standard - * dialog stuff (Return = default, Esc = cancel....) Second, if a button is - * pressed, return that button's ID - IDCANCEL (2), which is the button's - * number. - */ - static BOOL CALLBACK - dialog_callback( - HWND hwnd, - UINT message, - WPARAM wParam, - LPARAM lParam) - { - if (message == WM_INITDIALOG) - { - CenterWindow(hwnd, GetWindow(hwnd, GW_OWNER)); - /* Set focus to the dialog. Set the default button, if specified. */ - (void)SetFocus(hwnd); - if (dialog_default_button > IDCANCEL) - (void)SetFocus(GetDlgItem(hwnd, dialog_default_button)); - // if (dialog_default_button > 0) - // (void)SetFocus(GetDlgItem(hwnd, dialog_default_button + IDCANCEL)); - return FALSE; - } - - if (message == WM_COMMAND) - { - int button = LOWORD(wParam); - - /* Don't end the dialog if something was selected that was - * not a button. - */ - if (button >= DLG_NONBUTTON_CONTROL) - return TRUE; - - /* If the edit box exists, copy the string. */ - if (s_textfield != NULL) - GetDlgItemText(hwnd, DLG_NONBUTTON_CONTROL + 2, - s_textfield, IOSIZE); - - /* - * Need to check for IDOK because if the user just hits Return to - * accept the default value, some reason this is what we get. - */ - 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; - } - - /* - * Create a dialog dynamically from the parameter strings. - * type = type of dialog (question, alert, etc.) - * title = dialog title. may be NULL for default title. - * message = text to display. Dialog sizes to accommodate it. - * buttons = '\n' separated list of button captions, default first. - * dfltbutton = number of default button. - * - * This routine returns 1 if the first button is pressed, - * 2 for the second, etc. - * - * 0 indicates Esc was pressed. - * -1 for unexpected error - * - * If stubbing out this fn, return 1. - */ - - static const char_u dlg_icons[] = /* must match names in resource file */ - { - 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, - int ex_cmd) - { - 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 - /* Don't output anything in silent mode ("ex -s") */ - if (silent_mode) - return dfltbutton; /* return default option */ - #endif - - /* If there is no window yet, open it. */ - if (s_hwnd == NULL && gui_mch_init() == FAIL) - return dfltbutton; - - if ((type < 0) || (type > VIM_LAST_TYPE)) - type = 0; - - /* allocate some memory for dialog template */ - /* TODO should compute this really*/ - - hglbDlgTemp = GlobalAlloc(GHND, DLG_ALLOC_SIZE); - if (hglbDlgTemp == NULL) - return -1; - - p = (LPWORD) GlobalLock(hglbDlgTemp); - - if (p == NULL) - return -1; - - /* - * make a copy of 'buttons' to fiddle with it. compiler grizzles because - * vim_strsave() doesn't take a const arg (why not?), so cast away the - * const. - */ - tbuffer = vim_strsave(buttons); - if (tbuffer == NULL) - return -1; - - --dfltbutton; /* Change from one-based to zero-based */ - - /* Count buttons */ - numButtons = 1; - for (i = 0; tbuffer[i] != '\0'; i++) - { - if (tbuffer[i] == DLG_BUTTON_SEP) - numButtons++; - } - if (dfltbutton >= numButtons) - dfltbutton = 0; - - /* Allocate array to hold the width of each button */ - buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE); - if (buttonWidths == NULL) - return -1; - - /* Allocate array to hold the X position of each button */ - buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE); - if (buttonPositions == NULL) - return -1; - - /* - * Calculate how big the dialog must be. - */ - 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; - - /* Minimum width for horizontal button */ - minButtonWidth = GetTextWidth(hdc, "Cancel", 6); - - /* Maximum width of a dialog, if possible */ - GetWindowRect(s_hwnd, &rect); - maxDialogWidth = rect.right - rect.left - - GetSystemMetrics(SM_CXFRAME) * 2; - if (maxDialogWidth < DLG_MIN_MAX_WIDTH) - maxDialogWidth = DLG_MIN_MAX_WIDTH; - - /* Set dlgwidth to width of message */ - pstart = message; - messageWidth = 0; - msgheight = 0; - do - { - pend = vim_strchr(pstart, DLG_BUTTON_SEP); - if (pend == NULL) - pend = pstart + STRLEN(pstart); /* Last line of message. */ - msgheight += fontHeight; - textWidth = GetTextWidth(hdc, pstart, pend - pstart); - if (textWidth > messageWidth) - messageWidth = textWidth; - pstart = pend + 1; - } while (*pend != NUL); - dlgwidth = messageWidth; - - /* Add width of icon to dlgwidth, and some space */ - dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX; - - if (msgheight < DLG_ICON_HEIGHT) - msgheight = DLG_ICON_HEIGHT; - - /* - * Check button names. A long one will make the dialog wider. - */ - vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL); - if (!vertical) - { - // Place buttons horizontally if they fit. - horizWidth = dlgPaddingX; - pstart = tbuffer; - i = 0; - do - { - pend = vim_strchr(pstart, DLG_BUTTON_SEP); - if (pend == NULL) - pend = pstart + STRLEN(pstart); // Last button name. - textWidth = GetTextWidth(hdc, pstart, pend - pstart); - if (textWidth < minButtonWidth) - textWidth = minButtonWidth; - textWidth += dlgPaddingX; /* Padding within button */ - buttonWidths[i] = textWidth; - buttonPositions[i++] = horizWidth; - horizWidth += textWidth + dlgPaddingX; /* Pad between buttons */ - pstart = pend + 1; - } while (*pend != NUL); - - if (horizWidth > maxDialogWidth) - vertical = TRUE; // Too wide to fit on the screen. - else if (horizWidth > dlgwidth) - dlgwidth = horizWidth; - } - - if (vertical) - { - // Stack buttons vertically. - pstart = tbuffer; - do - { - pend = vim_strchr(pstart, DLG_BUTTON_SEP); - if (pend == NULL) - pend = pstart + STRLEN(pstart); // Last button name. - textWidth = GetTextWidth(hdc, pstart, pend - pstart); - textWidth += dlgPaddingX; /* Padding within button */ - textWidth += DLG_VERT_PADDING_X * 2; /* Padding around button */ - if (textWidth > dlgwidth) - dlgwidth = textWidth; - pstart = pend + 1; - } while (*pend != NUL); - } - - if (dlgwidth < DLG_MIN_WIDTH) - dlgwidth = DLG_MIN_WIDTH; /* Don't allow a really thin dialog!*/ - - /* start to fill in the dlgtemplate information. addressing by WORDs */ - lStyle = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE ; - - add_long(lStyle); - pnumitems = p; /*save where the number of items must be stored*/ - add_byte(0); // NumberOfItems(will change later) - add_word(10); // x - add_word(10); // y - add_word(PixelToDialogX(dlgwidth)); - - // Dialog height. - if (vertical) - dlgheight = msgheight + 2 * dlgPaddingY + - DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons; - else - dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight; - - // Dialog needs to be taller if contains an edit box. - editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y; - if (textfield != NULL) - dlgheight += editboxheight; - - add_word(PixelToDialogY(dlgheight)); - - add_byte(0); //menu - add_byte(0); //class - - /* copy the title of the dialog */ - add_string(title ? title : ("Vim"VIM_VERSION_MEDIUM)); - - buttonYpos = msgheight + 2 * dlgPaddingY; - - if (textfield != NULL) - buttonYpos += editboxheight; - - pstart = tbuffer; //dflt_text - horizWidth = (dlgwidth - horizWidth) / 2; /* Now it's X offset */ - for (i = 0; i < numButtons; i++) - { - /* get end of this button. */ - for ( pend = pstart; - *pend && (*pend != DLG_BUTTON_SEP); - pend++) - ; - - if (*pend) - *pend = '\0'; - - /* - * NOTE: - * setting the BS_DEFPUSHBUTTON style doesn't work because Windows sets - * the focus to the first tab-able button and in so doing makes that - * the default!! Grrr. Workaround: Make the default button the only - * one with WS_TABSTOP style. Means user can't tab between buttons, but - * he/she can use arrow keys. - * - * NOTE (Thore): Setting BS_DEFPUSHBUTTON works fine when it's the - * first one, so I changed the correct button to be this style. This - * is necessary because when an edit box is added, we need a button to - * be default. The edit box will be the default control, and when the - * user presses enter from the edit box we want the default button to - * be pressed. - */ - 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 /* TBK */ - + 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), /* TBK */ - PixelToDialogX(buttonWidths[i]), - (WORD)(PixelToDialogY(2 * fontHeight) - 1), - (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart); - } - - pstart = pend + 1; /*next button*/ - - } - *pnumitems += numButtons; - - /* Vim icon */ - 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]); - - - /* Dialog message */ - 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); - - /* Edit box */ - 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); - - - /* Let the dialog_callback() function know which button to make default - * If we have an edit box, make that the default. We also need to tell - * dialog_callback() if this dialog contains an edit box or not. We do - * this by setting s_textfield if it does. - */ - if (textfield != NULL) - { - dialog_default_button = DLG_NONBUTTON_CONTROL + 2; - s_textfield = textfield; - } - else - { - dialog_default_button = IDCANCEL + 1 + dfltbutton; - s_textfield = NULL; - } - - /*show the dialog box modally and get a return value*/ - 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; - } - - /* - * Put a simple element (basic class) onto a dialog template in memory. - * return a pointer to where the next item should be added. - * - * parameters: - * lStyle = additional style flags - * x,y = x & y positions IN DIALOG UNITS - * w,h = width and height IN DIALOG UNITS - * Id = ID used in messages - * clss = class ID, e.g 0x80 for a button, 0x82 for a static - * caption = usually text or resource name - * - * TODO: use the length information noted here to enable the dialog creation - * routines to work out more exactly how much memory they need to alloc. - */ - 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)) - { - /* Use resource ID */ - add_byte(0xff); - add_byte(*caption); - } - else - add_string(caption); - - add_byte(0); //# of extra bytes following - - - return p; - } - - #undef add_byte - #undef add_string - #undef add_long - #undef add_word - - #endif /* FEAT_GUI_DIALOG */ - - static void - get_dialog_font_metrics(void) - { - DWORD dlgFontSize; - dlgFontSize = GetDialogBaseUnits(); /* fall back to big old system*/ - s_dlgfntwidth = LOWORD(dlgFontSize); - s_dlgfntheight = HIWORD(dlgFontSize); - } - - - #if defined(FEAT_TOOLBAR) || defined(PROTO) - - /* cproto fails on missing include files */ - #ifndef PROTO - # include "gui_w3~1.h" - #endif - - /* - * Create the toolbar, initially unpopulated. - * (just like the menu, there are no defaults, it's all - * set up through menu.vim) - */ - static void - initialise_toolbar(void) - { - s_toolbarhwnd = CreateToolbar( - s_hwnd, - WS_CHILD | WS_VISIBLE, - CMD_TB_BASE, /**/ - 31, //number of images in initial bitmap - s_hinst, - IDR_TOOLBAR1, // id of initial bitmap - NULL, - 0 // initial number of buttons - ); - - gui_mch_show_toolbar(vim_strchr(p_go, GO_TOOLBAR) != NULL); - } - #endif - - #if defined(FEAT_OLE) || defined(FEAT_EVAL) || defined(PROTO) - /* - * Make the GUI window come to the foreground. - */ - void - gui_mch_set_foreground(void) - { - if (IsIconic(s_hwnd)) - SendMessage(s_hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); - SetActiveWindow(s_hwnd); - } - #endif --- 0 ---- *** ../vim-7.4.1363/src/gui_w32.c 2016-02-20 13:08:42.453801608 +0100 --- src/gui_w32.c 2016-02-20 13:23:27.412601524 +0100 *************** *** 10,16 **** /* * Windows GUI. * ! * GUI support for Microsoft Windows. Win32 initially; maybe Win16 later * * George V. Reilly wrote the original Win32 GUI. * Robert Webb reworked it to use the existing GUI stuff and added menu, --- 10,16 ---- /* * Windows GUI. * ! * GUI support for Microsoft Windows, aka Win32. Also for Win64. * * George V. Reilly wrote the original Win32 GUI. * Robert Webb reworked it to use the existing GUI stuff and added menu, *************** *** 185,194 **** ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L) #endif /* ! * Include the common stuff for MS-Windows GUI. */ ! #include "gui_w48.c" #ifdef FEAT_XPM_W32 # include "xpm_w32.h" --- 185,4279 ---- ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L) #endif + + #include "version.h" /* used by dialog box routine for default title */ + #ifdef DEBUG + # include + #endif + + /* cproto fails on missing include files */ + #ifndef PROTO + + #ifndef __MINGW32__ + # include + #endif + #if defined(FEAT_TOOLBAR) || defined(FEAT_BEVAL) || defined(FEAT_GUI_TABLINE) + # include + #endif + #include + + #ifdef GLOBAL_IME + # include "glbl_ime.h" + #endif + + #endif /* PROTO */ + + #ifdef FEAT_MENU + # define MENUHINTS /* show menu hints in command line */ + #endif + + /* Some parameters for dialog boxes. All in pixels. */ + #define DLG_PADDING_X 10 + #define DLG_PADDING_Y 10 + #define DLG_OLD_STYLE_PADDING_X 5 + #define DLG_OLD_STYLE_PADDING_Y 5 + #define DLG_VERT_PADDING_X 4 /* For vertical buttons */ + #define DLG_VERT_PADDING_Y 4 + #define DLG_ICON_WIDTH 34 + #define DLG_ICON_HEIGHT 34 + #define DLG_MIN_WIDTH 150 + #define DLG_FONT_NAME "MS Sans Serif" + #define DLG_FONT_POINT_SIZE 8 + #define DLG_MIN_MAX_WIDTH 400 + #define DLG_MIN_MAX_HEIGHT 400 + + #define DLG_NONBUTTON_CONTROL 5000 /* First ID of non-button controls */ + + #ifndef WM_XBUTTONDOWN /* For Win2K / winME ONLY */ + # define WM_XBUTTONDOWN 0x020B + # define WM_XBUTTONUP 0x020C + # define WM_XBUTTONDBLCLK 0x020D + # define MK_XBUTTON1 0x0020 + # define MK_XBUTTON2 0x0040 + #endif + + #ifdef PROTO + /* + * Define a few things for generating prototypes. This is just to avoid + * syntax errors, the defines do not need to be correct. + */ + # define APIENTRY + # define CALLBACK + # define CONST + # define FAR + # define NEAR + # define _cdecl + typedef int BOOL; + typedef int BYTE; + typedef int DWORD; + typedef int WCHAR; + typedef int ENUMLOGFONT; + typedef int FINDREPLACE; + typedef int HANDLE; + typedef int HBITMAP; + typedef int HBRUSH; + typedef int HDROP; + typedef int INT; + typedef int LOGFONT[]; + typedef int LPARAM; + typedef int LPCREATESTRUCT; + typedef int LPCSTR; + typedef int LPCTSTR; + typedef int LPRECT; + typedef int LPSTR; + typedef int LPWINDOWPOS; + typedef int LPWORD; + typedef int LRESULT; + typedef int HRESULT; + # undef MSG + typedef int MSG; + typedef int NEWTEXTMETRIC; + typedef int OSVERSIONINFO; + typedef int PWORD; + typedef int RECT; + typedef int UINT; + typedef int WORD; + typedef int WPARAM; + typedef int POINT; + typedef void *HINSTANCE; + typedef void *HMENU; + typedef void *HWND; + typedef void *HDC; + typedef void VOID; + typedef int LPNMHDR; + typedef int LONG; + typedef int WNDPROC; + #endif + + #ifndef GET_X_LPARAM + # define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) + #endif + + static void _OnPaint( HWND hwnd); + static void clear_rect(RECT *rcp); + + static WORD s_dlgfntheight; /* height of the dialog font */ + static WORD s_dlgfntwidth; /* width of the dialog font */ + + #ifdef FEAT_MENU + static HMENU s_menuBar = NULL; + #endif + #ifdef FEAT_TEAROFF + static void rebuild_tearoff(vimmenu_T *menu); + static HBITMAP s_htearbitmap; /* bitmap used to indicate tearoff */ + #endif + + /* Flag that is set while processing a message that must not be interrupted by + * processing another message. */ + static int s_busy_processing = FALSE; + + static int destroying = FALSE; /* call DestroyWindow() ourselves */ + + #ifdef MSWIN_FIND_REPLACE + static UINT s_findrep_msg = 0; /* set in gui_w[16/32].c */ + static FINDREPLACE s_findrep_struct; + # if defined(FEAT_MBYTE) && defined(WIN3264) + static FINDREPLACEW s_findrep_struct_w; + # endif + static HWND s_findrep_hwnd = NULL; + static int s_findrep_is_find; /* TRUE for find dialog, FALSE + for find/replace dialog */ + #endif + + static HINSTANCE s_hinst = NULL; + #if !defined(FEAT_SNIFF) && !defined(FEAT_GUI) + static + #endif + HWND s_hwnd = NULL; + static HDC s_hdc = NULL; + static HBRUSH s_brush = NULL; + + #ifdef FEAT_TOOLBAR + static HWND s_toolbarhwnd = NULL; + static WNDPROC s_toolbar_wndproc = NULL; + #endif + + #ifdef FEAT_GUI_TABLINE + static HWND s_tabhwnd = NULL; + static WNDPROC s_tabline_wndproc = NULL; + static int showing_tabline = 0; + #endif + + static WPARAM s_wParam = 0; + static LPARAM s_lParam = 0; + + static HWND s_textArea = NULL; + static UINT s_uMsg = 0; + + static char_u *s_textfield; /* Used by dialogs to pass back strings */ + + static int s_need_activate = FALSE; + + /* This variable is set when waiting for an event, which is the only moment + * scrollbar dragging can be done directly. It's not allowed while commands + * are executed, because it may move the cursor and that may cause unexpected + * problems (e.g., while ":s" is working). + */ + static int allow_scrollbar = FALSE; + + #ifdef GLOBAL_IME + # define MyTranslateMessage(x) global_ime_TranslateMessage(x) + #else + # define MyTranslateMessage(x) TranslateMessage(x) + #endif + + #if (defined(WIN3264) && defined(FEAT_MBYTE)) || defined(GLOBAL_IME) + /* use of WindowProc depends on wide_WindowProc */ + # define MyWindowProc vim_WindowProc + #else + /* use ordinary WindowProc */ + # define MyWindowProc DefWindowProc + #endif + + extern int current_font_height; /* this is in os_mswin.c */ + + static struct + { + UINT key_sym; + char_u vim_code0; + char_u vim_code1; + } special_keys[] = + { + {VK_UP, 'k', 'u'}, + {VK_DOWN, 'k', 'd'}, + {VK_LEFT, 'k', 'l'}, + {VK_RIGHT, 'k', 'r'}, + + {VK_F1, 'k', '1'}, + {VK_F2, 'k', '2'}, + {VK_F3, 'k', '3'}, + {VK_F4, 'k', '4'}, + {VK_F5, 'k', '5'}, + {VK_F6, 'k', '6'}, + {VK_F7, 'k', '7'}, + {VK_F8, 'k', '8'}, + {VK_F9, 'k', '9'}, + {VK_F10, 'k', ';'}, + + {VK_F11, 'F', '1'}, + {VK_F12, 'F', '2'}, + {VK_F13, 'F', '3'}, + {VK_F14, 'F', '4'}, + {VK_F15, 'F', '5'}, + {VK_F16, 'F', '6'}, + {VK_F17, 'F', '7'}, + {VK_F18, 'F', '8'}, + {VK_F19, 'F', '9'}, + {VK_F20, 'F', 'A'}, + + {VK_F21, 'F', 'B'}, + #ifdef FEAT_NETBEANS_INTG + {VK_PAUSE, 'F', 'B'}, /* Pause == F21 (see gui_gtk_x11.c) */ + #endif + {VK_F22, 'F', 'C'}, + {VK_F23, 'F', 'D'}, + {VK_F24, 'F', 'E'}, /* winuser.h defines up to F24 */ + + {VK_HELP, '%', '1'}, + {VK_BACK, 'k', 'b'}, + {VK_INSERT, 'k', 'I'}, + {VK_DELETE, 'k', 'D'}, + {VK_HOME, 'k', 'h'}, + {VK_END, '@', '7'}, + {VK_PRIOR, 'k', 'P'}, + {VK_NEXT, 'k', 'N'}, + {VK_PRINT, '%', '9'}, + {VK_ADD, 'K', '6'}, + {VK_SUBTRACT, 'K', '7'}, + {VK_DIVIDE, 'K', '8'}, + {VK_MULTIPLY, 'K', '9'}, + {VK_SEPARATOR, 'K', 'A'}, /* Keypad Enter */ + {VK_DECIMAL, 'K', 'B'}, + + {VK_NUMPAD0, 'K', 'C'}, + {VK_NUMPAD1, 'K', 'D'}, + {VK_NUMPAD2, 'K', 'E'}, + {VK_NUMPAD3, 'K', 'F'}, + {VK_NUMPAD4, 'K', 'G'}, + {VK_NUMPAD5, 'K', 'H'}, + {VK_NUMPAD6, 'K', 'I'}, + {VK_NUMPAD7, 'K', 'J'}, + {VK_NUMPAD8, 'K', 'K'}, + {VK_NUMPAD9, 'K', 'L'}, + + /* Keys that we want to be able to use any modifier with: */ + {VK_SPACE, ' ', NUL}, + {VK_TAB, TAB, NUL}, + {VK_ESCAPE, ESC, NUL}, + {NL, NL, NUL}, + {CAR, CAR, NUL}, + + /* End of list marker: */ + {0, 0, 0} + }; + + /* Local variables */ + static int s_button_pending = -1; + + /* s_getting_focus is set when we got focus but didn't see mouse-up event yet, + * so don't reset s_button_pending. */ + static int s_getting_focus = FALSE; + + static int s_x_pending; + static int s_y_pending; + static UINT s_kFlags_pending; + static UINT s_wait_timer = 0; /* Timer for get char from user */ + static int s_timed_out = FALSE; + static int dead_key = 0; /* 0: no dead key, 1: dead key pressed */ + + #ifdef WIN3264 + static OSVERSIONINFO os_version; /* like it says. Init in gui_mch_init() */ + #endif + + #ifdef FEAT_BEVAL + /* balloon-eval WM_NOTIFY_HANDLER */ + static void Handle_WM_Notify(HWND hwnd, LPNMHDR pnmh); + static void TrackUserActivity(UINT uMsg); + #endif + + /* + * For control IME. + * + * These LOGFONT used for IME. + */ + #ifdef FEAT_MBYTE + # ifdef USE_IM_CONTROL + /* holds LOGFONT for 'guifontwide' if available, otherwise 'guifont' */ + static LOGFONT norm_logfont; + /* holds LOGFONT for 'guifont' always. */ + static LOGFONT sub_logfont; + # endif + #endif + + #ifdef FEAT_MBYTE_IME + static LRESULT _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData); + #endif + + #if defined(FEAT_BROWSE) + static char_u *convert_filter(char_u *s); + #endif + + #ifdef DEBUG_PRINT_ERROR + /* + * Print out the last Windows error message + */ + static void + print_windows_error(void) + { + LPVOID lpMsgBuf; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL); + TRACE1("Error: %s\n", lpMsgBuf); + LocalFree(lpMsgBuf); + } + #endif + + /* + * Cursor blink functions. + * + * This is a simple state machine: + * BLINK_NONE not blinking at all + * BLINK_OFF blinking, cursor is not shown + * BLINK_ON blinking, cursor is shown + */ + + #define BLINK_NONE 0 + #define BLINK_OFF 1 + #define BLINK_ON 2 + + static int blink_state = BLINK_NONE; + static long_u blink_waittime = 700; + static long_u blink_ontime = 400; + static long_u blink_offtime = 250; + static UINT blink_timer = 0; + + void + gui_mch_set_blinking(long wait, long on, long off) + { + blink_waittime = wait; + blink_ontime = on; + blink_offtime = off; + } + + /* ARGSUSED */ + static VOID CALLBACK + _OnBlinkTimer( + HWND hwnd, + UINT uMsg, + UINT idEvent, + DWORD dwTime) + { + MSG msg; + + /* + TRACE2("Got timer event, id %d, blink_timer %d\n", idEvent, blink_timer); + */ + + KillTimer(NULL, idEvent); + + /* Eat spurious WM_TIMER messages */ + while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) + ; + + if (blink_state == BLINK_ON) + { + gui_undraw_cursor(); + blink_state = BLINK_OFF; + blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_offtime, + (TIMERPROC)_OnBlinkTimer); + } + else + { + gui_update_cursor(TRUE, FALSE); + blink_state = BLINK_ON; + blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime, + (TIMERPROC)_OnBlinkTimer); + } + } + + static void + gui_mswin_rm_blink_timer(void) + { + MSG msg; + + if (blink_timer != 0) + { + KillTimer(NULL, blink_timer); + /* Eat spurious WM_TIMER messages */ + while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) + ; + blink_timer = 0; + } + } + + /* + * Stop the cursor blinking. Show the cursor if it wasn't shown. + */ + void + gui_mch_stop_blink(void) + { + gui_mswin_rm_blink_timer(); + if (blink_state == BLINK_OFF) + gui_update_cursor(TRUE, FALSE); + blink_state = BLINK_NONE; + } + + /* + * Start the cursor blinking. If it was already blinking, this restarts the + * waiting time and shows the cursor. + */ + void + gui_mch_start_blink(void) + { + gui_mswin_rm_blink_timer(); + + /* Only switch blinking on if none of the times is zero */ + if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus) + { + blink_timer = (UINT)SetTimer(NULL, 0, (UINT)blink_waittime, + (TIMERPROC)_OnBlinkTimer); + blink_state = BLINK_ON; + gui_update_cursor(TRUE, FALSE); + } + } + + /* + * Call-back routines. + */ + + /*ARGSUSED*/ + static VOID CALLBACK + _OnTimer( + HWND hwnd, + UINT uMsg, + UINT idEvent, + DWORD dwTime) + { + MSG msg; + + /* + TRACE2("Got timer event, id %d, s_wait_timer %d\n", idEvent, s_wait_timer); + */ + KillTimer(NULL, idEvent); + s_timed_out = TRUE; + + /* Eat spurious WM_TIMER messages */ + while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) + ; + if (idEvent == s_wait_timer) + s_wait_timer = 0; + } + + /*ARGSUSED*/ + static void + _OnDeadChar( + HWND hwnd, + UINT ch, + int cRepeat) + { + dead_key = 1; + } + + /* + * Convert Unicode character "ch" to bytes in "string[slen]". + * When "had_alt" is TRUE the ALT key was included in "ch". + * Return the length. + */ + static int + char_to_string(int ch, char_u *string, int slen, int had_alt) + { + int len; + int i; + #ifdef FEAT_MBYTE + WCHAR wstring[2]; + char_u *ws = NULL;; + + if (os_version.dwPlatformId != VER_PLATFORM_WIN32_NT) + { + /* On Windows 95/98 we apparently get the character in the active + * codepage, not in UCS-2. If conversion is needed convert it to + * UCS-2 first. */ + if ((int)GetACP() == enc_codepage) + len = 0; /* no conversion required */ + else + { + string[0] = ch; + len = MultiByteToWideChar(GetACP(), 0, (LPCSTR)string, + 1, wstring, 2); + } + } + else + { + wstring[0] = ch; + len = 1; + } + + if (len > 0) + { + /* "ch" is a UTF-16 character. Convert it to a string of bytes. When + * "enc_codepage" is non-zero use the standard Win32 function, + * otherwise use our own conversion function (e.g., for UTF-8). */ + if (enc_codepage > 0) + { + len = WideCharToMultiByte(enc_codepage, 0, wstring, len, + (LPSTR)string, slen, 0, NULL); + /* If we had included the ALT key into the character but now the + * upper bit is no longer set, that probably means the conversion + * failed. Convert the original character and set the upper bit + * afterwards. */ + if (had_alt && len == 1 && ch >= 0x80 && string[0] < 0x80) + { + wstring[0] = ch & 0x7f; + len = WideCharToMultiByte(enc_codepage, 0, wstring, len, + (LPSTR)string, slen, 0, NULL); + if (len == 1) /* safety check */ + string[0] |= 0x80; + } + } + else + { + len = 1; + ws = utf16_to_enc(wstring, &len); + if (ws == NULL) + len = 0; + else + { + if (len > slen) /* just in case */ + len = slen; + mch_memmove(string, ws, len); + vim_free(ws); + } + } + } + + if (len == 0) + #endif + { + string[0] = ch; + len = 1; + } + + for (i = 0; i < len; ++i) + if (string[i] == CSI && len <= slen - 2) + { + /* Insert CSI as K_CSI. */ + mch_memmove(string + i + 3, string + i + 1, len - i - 1); + string[++i] = KS_EXTRA; + string[++i] = (int)KE_CSI; + len += 2; + } + + return len; + } + + /* + * Key hit, add it to the input buffer. + */ + /*ARGSUSED*/ + static void + _OnChar( + HWND hwnd, + UINT ch, + int cRepeat) + { + char_u string[40]; + int len = 0; + + dead_key = 0; + + len = char_to_string(ch, string, 40, FALSE); + if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts) + { + trash_input_buf(); + got_int = TRUE; + } + + add_to_input_buf(string, len); + } + + /* + * Alt-Key hit, add it to the input buffer. + */ + /*ARGSUSED*/ + static void + _OnSysChar( + HWND hwnd, + UINT cch, + int cRepeat) + { + char_u string[40]; /* Enough for multibyte character */ + int len; + int modifiers; + int ch = cch; /* special keys are negative */ + + dead_key = 0; + + /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */ + + /* OK, we have a character key (given by ch) which was entered with the + * ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note + * that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless + * CAPSLOCK is pressed) at this point. + */ + modifiers = MOD_MASK_ALT; + if (GetKeyState(VK_SHIFT) & 0x8000) + modifiers |= MOD_MASK_SHIFT; + if (GetKeyState(VK_CONTROL) & 0x8000) + modifiers |= MOD_MASK_CTRL; + + ch = simplify_key(ch, &modifiers); + /* remove the SHIFT modifier for keys where it's already included, e.g., + * '(' and '*' */ + if (ch < 0x100 && !isalpha(ch) && isprint(ch)) + modifiers &= ~MOD_MASK_SHIFT; + + /* Interpret the ALT key as making the key META, include SHIFT, etc. */ + ch = extract_modifiers(ch, &modifiers); + if (ch == CSI) + ch = K_CSI; + + len = 0; + if (modifiers) + { + string[len++] = CSI; + string[len++] = KS_MODIFIER; + string[len++] = modifiers; + } + + if (IS_SPECIAL((int)ch)) + { + string[len++] = CSI; + string[len++] = K_SECOND((int)ch); + string[len++] = K_THIRD((int)ch); + } + else + { + /* Although the documentation isn't clear about it, we assume "ch" is + * a Unicode character. */ + len += char_to_string(ch, string + len, 40 - len, TRUE); + } + + add_to_input_buf(string, len); + } + + static void + _OnMouseEvent( + int button, + int x, + int y, + int repeated_click, + UINT keyFlags) + { + int vim_modifiers = 0x0; + + s_getting_focus = FALSE; + + if (keyFlags & MK_SHIFT) + vim_modifiers |= MOUSE_SHIFT; + if (keyFlags & MK_CONTROL) + vim_modifiers |= MOUSE_CTRL; + if (GetKeyState(VK_MENU) & 0x8000) + vim_modifiers |= MOUSE_ALT; + + gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers); + } + + /*ARGSUSED*/ + static void + _OnMouseButtonDown( + HWND hwnd, + BOOL fDoubleClick, + int x, + int y, + UINT keyFlags) + { + static LONG s_prevTime = 0; + + LONG currentTime = GetMessageTime(); + int button = -1; + int repeated_click; + + /* Give main window the focus: this is so the cursor isn't hollow. */ + (void)SetFocus(s_hwnd); + + if (s_uMsg == WM_LBUTTONDOWN || s_uMsg == WM_LBUTTONDBLCLK) + button = MOUSE_LEFT; + else if (s_uMsg == WM_MBUTTONDOWN || s_uMsg == WM_MBUTTONDBLCLK) + button = MOUSE_MIDDLE; + else if (s_uMsg == WM_RBUTTONDOWN || s_uMsg == WM_RBUTTONDBLCLK) + button = MOUSE_RIGHT; + else if (s_uMsg == WM_XBUTTONDOWN || s_uMsg == WM_XBUTTONDBLCLK) + { + #ifndef GET_XBUTTON_WPARAM + # define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam)) + #endif + button = ((GET_XBUTTON_WPARAM(s_wParam) == 1) ? MOUSE_X1 : MOUSE_X2); + } + else if (s_uMsg == WM_CAPTURECHANGED) + { + /* on W95/NT4, somehow you get in here with an odd Msg + * if you press one button while holding down the other..*/ + if (s_button_pending == MOUSE_LEFT) + button = MOUSE_RIGHT; + else + button = MOUSE_LEFT; + } + if (button >= 0) + { + repeated_click = ((int)(currentTime - s_prevTime) < p_mouset); + + /* + * Holding down the left and right buttons simulates pushing the middle + * button. + */ + if (repeated_click + && ((button == MOUSE_LEFT && s_button_pending == MOUSE_RIGHT) + || (button == MOUSE_RIGHT + && s_button_pending == MOUSE_LEFT))) + { + /* + * Hmm, gui.c will ignore more than one button down at a time, so + * pretend we let go of it first. + */ + gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, 0x0); + button = MOUSE_MIDDLE; + repeated_click = FALSE; + s_button_pending = -1; + _OnMouseEvent(button, x, y, repeated_click, keyFlags); + } + else if ((repeated_click) + || (mouse_model_popup() && (button == MOUSE_RIGHT))) + { + if (s_button_pending > -1) + { + _OnMouseEvent(s_button_pending, x, y, FALSE, keyFlags); + s_button_pending = -1; + } + /* TRACE("Button down at x %d, y %d\n", x, y); */ + _OnMouseEvent(button, x, y, repeated_click, keyFlags); + } + else + { + /* + * If this is the first press (i.e. not a multiple click) don't + * action immediately, but store and wait for: + * i) button-up + * ii) mouse move + * iii) another button press + * before using it. + * This enables us to make left+right simulate middle button, + * without left or right being actioned first. The side-effect is + * that if you click and hold the mouse without dragging, the + * cursor doesn't move until you release the button. In practice + * this is hardly a problem. + */ + s_button_pending = button; + s_x_pending = x; + s_y_pending = y; + s_kFlags_pending = keyFlags; + } + + s_prevTime = currentTime; + } + } + + /*ARGSUSED*/ + static void + _OnMouseMoveOrRelease( + HWND hwnd, + int x, + int y, + UINT keyFlags) + { + int button; + + s_getting_focus = FALSE; + if (s_button_pending > -1) + { + /* Delayed action for mouse down event */ + _OnMouseEvent(s_button_pending, s_x_pending, + s_y_pending, FALSE, s_kFlags_pending); + s_button_pending = -1; + } + if (s_uMsg == WM_MOUSEMOVE) + { + /* + * It's only a MOUSE_DRAG if one or more mouse buttons are being held + * down. + */ + if (!(keyFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON + | MK_XBUTTON1 | MK_XBUTTON2))) + { + gui_mouse_moved(x, y); + return; + } + + /* + * While button is down, keep grabbing mouse move events when + * the mouse goes outside the window + */ + SetCapture(s_textArea); + button = MOUSE_DRAG; + /* TRACE(" move at x %d, y %d\n", x, y); */ + } + else + { + ReleaseCapture(); + button = MOUSE_RELEASE; + /* TRACE(" up at x %d, y %d\n", x, y); */ + } + + _OnMouseEvent(button, x, y, FALSE, keyFlags); + } + + #ifdef FEAT_MENU + /* + * Find the vimmenu_T with the given id + */ + static vimmenu_T * + gui_mswin_find_menu( + vimmenu_T *pMenu, + int id) + { + vimmenu_T *pChildMenu; + + while (pMenu) + { + if (pMenu->id == (UINT)id) + break; + if (pMenu->children != NULL) + { + pChildMenu = gui_mswin_find_menu(pMenu->children, id); + if (pChildMenu) + { + pMenu = pChildMenu; + break; + } + } + pMenu = pMenu->next; + } + return pMenu; + } + + /*ARGSUSED*/ + static void + _OnMenu( + HWND hwnd, + int id, + HWND hwndCtl, + UINT codeNotify) + { + vimmenu_T *pMenu; + + pMenu = gui_mswin_find_menu(root_menu, id); + if (pMenu) + gui_menu_cb(pMenu); + } + #endif + + #ifdef MSWIN_FIND_REPLACE + # if defined(FEAT_MBYTE) && defined(WIN3264) + /* + * copy useful data from structure LPFINDREPLACE to structure LPFINDREPLACEW + */ + static void + findrep_atow(LPFINDREPLACEW lpfrw, LPFINDREPLACE lpfr) + { + WCHAR *wp; + + lpfrw->hwndOwner = lpfr->hwndOwner; + lpfrw->Flags = lpfr->Flags; + + wp = enc_to_utf16((char_u *)lpfr->lpstrFindWhat, NULL); + wcsncpy(lpfrw->lpstrFindWhat, wp, lpfrw->wFindWhatLen - 1); + vim_free(wp); + + /* the field "lpstrReplaceWith" doesn't need to be copied */ + } + + /* + * copy useful data from structure LPFINDREPLACEW to structure LPFINDREPLACE + */ + static void + findrep_wtoa(LPFINDREPLACE lpfr, LPFINDREPLACEW lpfrw) + { + char_u *p; + + lpfr->Flags = lpfrw->Flags; + + p = utf16_to_enc((short_u*)lpfrw->lpstrFindWhat, NULL); + vim_strncpy((char_u *)lpfr->lpstrFindWhat, p, lpfr->wFindWhatLen - 1); + vim_free(p); + + p = utf16_to_enc((short_u*)lpfrw->lpstrReplaceWith, NULL); + vim_strncpy((char_u *)lpfr->lpstrReplaceWith, p, lpfr->wReplaceWithLen - 1); + vim_free(p); + } + # endif + + /* + * Handle a Find/Replace window message. + */ + static void + _OnFindRepl(void) + { + int flags = 0; + int down; + + # if defined(FEAT_MBYTE) && defined(WIN3264) + /* If the OS is Windows NT, and 'encoding' differs from active codepage: + * convert text from wide string. */ + if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT + && enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + findrep_wtoa(&s_findrep_struct, &s_findrep_struct_w); + } + # endif + + if (s_findrep_struct.Flags & FR_DIALOGTERM) + /* Give main window the focus back. */ + (void)SetFocus(s_hwnd); + + if (s_findrep_struct.Flags & FR_FINDNEXT) + { + flags = FRD_FINDNEXT; + + /* Give main window the focus back: this is so the cursor isn't + * hollow. */ + (void)SetFocus(s_hwnd); + } + else if (s_findrep_struct.Flags & FR_REPLACE) + { + flags = FRD_REPLACE; + + /* Give main window the focus back: this is so the cursor isn't + * hollow. */ + (void)SetFocus(s_hwnd); + } + else if (s_findrep_struct.Flags & FR_REPLACEALL) + { + flags = FRD_REPLACEALL; + } + + if (flags != 0) + { + /* Call the generic GUI function to do the actual work. */ + if (s_findrep_struct.Flags & FR_WHOLEWORD) + flags |= FRD_WHOLE_WORD; + if (s_findrep_struct.Flags & FR_MATCHCASE) + flags |= FRD_MATCH_CASE; + down = (s_findrep_struct.Flags & FR_DOWN) != 0; + gui_do_findrepl(flags, (char_u *)s_findrep_struct.lpstrFindWhat, + (char_u *)s_findrep_struct.lpstrReplaceWith, down); + } + } + #endif + + static void + HandleMouseHide(UINT uMsg, LPARAM lParam) + { + static LPARAM last_lParam = 0L; + + /* We sometimes get a mousemove when the mouse didn't move... */ + if (uMsg == WM_MOUSEMOVE || uMsg == WM_NCMOUSEMOVE) + { + if (lParam == last_lParam) + return; + last_lParam = lParam; + } + + /* Handle specially, to centralise coding. We need to be sure we catch all + * possible events which should cause us to restore the cursor (as it is a + * shared resource, we take full responsibility for it). + */ + switch (uMsg) + { + case WM_KEYUP: + case WM_CHAR: + /* + * blank out the pointer if necessary + */ + if (p_mh) + gui_mch_mousehide(TRUE); + break; + + case WM_SYSKEYUP: /* show the pointer when a system-key is pressed */ + case WM_SYSCHAR: + case WM_MOUSEMOVE: /* show the pointer on any mouse action */ + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: + case WM_NCMOUSEMOVE: + case WM_NCLBUTTONDOWN: + case WM_NCLBUTTONUP: + case WM_NCMBUTTONDOWN: + case WM_NCMBUTTONUP: + case WM_NCRBUTTONDOWN: + case WM_NCRBUTTONUP: + case WM_KILLFOCUS: + /* + * if the pointer is currently hidden, then we should show it. + */ + gui_mch_mousehide(FALSE); + break; + } + } + + static LRESULT CALLBACK + _TextAreaWndProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) + { + /* + TRACE("TextAreaWndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n", + hwnd, uMsg, wParam, lParam); + */ + + HandleMouseHide(uMsg, lParam); + + s_uMsg = uMsg; + s_wParam = wParam; + s_lParam = lParam; + + #ifdef FEAT_BEVAL + TrackUserActivity(uMsg); + #endif + + switch (uMsg) + { + HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK,_OnMouseButtonDown); + HANDLE_MSG(hwnd, WM_LBUTTONDOWN,_OnMouseButtonDown); + HANDLE_MSG(hwnd, WM_LBUTTONUP, _OnMouseMoveOrRelease); + HANDLE_MSG(hwnd, WM_MBUTTONDBLCLK,_OnMouseButtonDown); + HANDLE_MSG(hwnd, WM_MBUTTONDOWN,_OnMouseButtonDown); + HANDLE_MSG(hwnd, WM_MBUTTONUP, _OnMouseMoveOrRelease); + HANDLE_MSG(hwnd, WM_MOUSEMOVE, _OnMouseMoveOrRelease); + HANDLE_MSG(hwnd, WM_PAINT, _OnPaint); + HANDLE_MSG(hwnd, WM_RBUTTONDBLCLK,_OnMouseButtonDown); + HANDLE_MSG(hwnd, WM_RBUTTONDOWN,_OnMouseButtonDown); + HANDLE_MSG(hwnd, WM_RBUTTONUP, _OnMouseMoveOrRelease); + HANDLE_MSG(hwnd, WM_XBUTTONDBLCLK,_OnMouseButtonDown); + HANDLE_MSG(hwnd, WM_XBUTTONDOWN,_OnMouseButtonDown); + HANDLE_MSG(hwnd, WM_XBUTTONUP, _OnMouseMoveOrRelease); + + #ifdef FEAT_BEVAL + case WM_NOTIFY: Handle_WM_Notify(hwnd, (LPNMHDR)lParam); + return TRUE; + #endif + default: + return MyWindowProc(hwnd, uMsg, wParam, lParam); + } + } + + #if (defined(WIN3264) && defined(FEAT_MBYTE)) \ + || defined(GLOBAL_IME) \ + || defined(PROTO) + # ifdef PROTO + typedef int WINAPI; + # endif + + LRESULT WINAPI + vim_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + { + # ifdef GLOBAL_IME + return global_ime_DefWindowProc(hwnd, message, wParam, lParam); + # else + if (wide_WindowProc) + return DefWindowProcW(hwnd, message, wParam, lParam); + return DefWindowProc(hwnd, message, wParam, lParam); + #endif + } + #endif + + /* + * Called when the foreground or background color has been changed. + */ + void + gui_mch_new_colors(void) + { + /* nothing to do? */ + } + + /* + * Set the colors to their default values. + */ + void + gui_mch_def_colors(void) + { + gui.norm_pixel = GetSysColor(COLOR_WINDOWTEXT); + gui.back_pixel = GetSysColor(COLOR_WINDOW); + gui.def_norm_pixel = gui.norm_pixel; + gui.def_back_pixel = gui.back_pixel; + } + + /* + * Open the GUI window which was created by a call to gui_mch_init(). + */ + int + gui_mch_open(void) + { + #ifndef SW_SHOWDEFAULT + # define SW_SHOWDEFAULT 10 /* Borland 5.0 doesn't have it */ + #endif + /* Actually open the window, if not already visible + * (may be done already in gui_mch_set_shellsize) */ + if (!IsWindowVisible(s_hwnd)) + ShowWindow(s_hwnd, SW_SHOWDEFAULT); + + #ifdef MSWIN_FIND_REPLACE + /* Init replace string here, so that we keep it when re-opening the + * dialog. */ + s_findrep_struct.lpstrReplaceWith[0] = NUL; + #endif + + return OK; + } + + /* + * Get the position of the top left corner of the window. + */ + int + gui_mch_get_winpos(int *x, int *y) + { + RECT rect; + + GetWindowRect(s_hwnd, &rect); + *x = rect.left; + *y = rect.top; + return OK; + } + + /* + * Set the position of the top left corner of the window to the given + * coordinates. + */ + void + gui_mch_set_winpos(int x, int y) + { + SetWindowPos(s_hwnd, NULL, x, y, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + } + void + gui_mch_set_text_area_pos(int x, int y, int w, int h) + { + static int oldx = 0; + static int oldy = 0; + + SetWindowPos(s_textArea, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE); + + #ifdef FEAT_TOOLBAR + if (vim_strchr(p_go, GO_TOOLBAR) != NULL) + SendMessage(s_toolbarhwnd, WM_SIZE, + (WPARAM)0, (LPARAM)(w + ((long)(TOOLBAR_BUTTON_HEIGHT+8)<<16))); + #endif + #if defined(FEAT_GUI_TABLINE) + if (showing_tabline) + { + int top = 0; + RECT rect; + + # ifdef FEAT_TOOLBAR + if (vim_strchr(p_go, GO_TOOLBAR) != NULL) + top = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT; + # endif + GetClientRect(s_hwnd, &rect); + MoveWindow(s_tabhwnd, 0, top, rect.right, gui.tabline_height, TRUE); + } + #endif + + /* When side scroll bar is unshown, the size of window will change. + * then, the text area move left or right. thus client rect should be + * forcedly redrawn. (Yasuhiro Matsumoto) */ + if (oldx != x || oldy != y) + { + InvalidateRect(s_hwnd, NULL, FALSE); + oldx = x; + oldy = y; + } + } + + + /* + * Scrollbar stuff: + */ + + void + gui_mch_enable_scrollbar( + scrollbar_T *sb, + int flag) + { + ShowScrollBar(sb->id, SB_CTL, flag); + + /* TODO: When the window is maximized, the size of the window stays the + * same, thus the size of the text area changes. On Win98 it's OK, on Win + * NT 4.0 it's not... */ + } + + void + gui_mch_set_scrollbar_pos( + scrollbar_T *sb, + int x, + int y, + int w, + int h) + { + SetWindowPos(sb->id, NULL, x, y, w, h, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); + } + + void + gui_mch_create_scrollbar( + scrollbar_T *sb, + int orient) /* SBAR_VERT or SBAR_HORIZ */ + { + sb->id = CreateWindow( + "SCROLLBAR", "Scrollbar", + WS_CHILD | ((orient == SBAR_VERT) ? SBS_VERT : SBS_HORZ), 0, 0, + 10, /* Any value will do for now */ + 10, /* Any value will do for now */ + s_hwnd, NULL, + s_hinst, NULL); + } + + /* + * Find the scrollbar with the given hwnd. + */ + static scrollbar_T * + gui_mswin_find_scrollbar(HWND hwnd) + { + win_T *wp; + + if (gui.bottom_sbar.id == hwnd) + return &gui.bottom_sbar; + FOR_ALL_WINDOWS(wp) + { + if (wp->w_scrollbars[SBAR_LEFT].id == hwnd) + return &wp->w_scrollbars[SBAR_LEFT]; + if (wp->w_scrollbars[SBAR_RIGHT].id == hwnd) + return &wp->w_scrollbars[SBAR_RIGHT]; + } + return NULL; + } + + /* + * Get the character size of a font. + */ + static void + GetFontSize(GuiFont font) + { + HWND hwnd = GetDesktopWindow(); + HDC hdc = GetWindowDC(hwnd); + HFONT hfntOld = SelectFont(hdc, (HFONT)font); + TEXTMETRIC tm; + + GetTextMetrics(hdc, &tm); + gui.char_width = tm.tmAveCharWidth + tm.tmOverhang; + + gui.char_height = tm.tmHeight + p_linespace; + + SelectFont(hdc, hfntOld); + + ReleaseDC(hwnd, hdc); + } + + /* + * Adjust gui.char_height (after 'linespace' was changed). + */ + int + gui_mch_adjust_charheight(void) + { + GetFontSize(gui.norm_font); + return OK; + } + + static GuiFont + get_font_handle(LOGFONT *lf) + { + HFONT font = NULL; + + /* Load the font */ + font = CreateFontIndirect(lf); + + if (font == NULL) + return NOFONT; + + return (GuiFont)font; + } + + static int + pixels_to_points(int pixels, int vertical) + { + int points; + HWND hwnd; + HDC hdc; + + hwnd = GetDesktopWindow(); + hdc = GetWindowDC(hwnd); + + points = MulDiv(pixels, 72, + GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX)); + + ReleaseDC(hwnd, hdc); + + return points; + } + + GuiFont + gui_mch_get_font( + char_u *name, + int giveErrorIfMissing) + { + LOGFONT lf; + GuiFont font = NOFONT; + + if (get_logfont(&lf, name, NULL, giveErrorIfMissing) == OK) + font = get_font_handle(&lf); + if (font == NOFONT && giveErrorIfMissing) + EMSG2(_(e_font), name); + return font; + } + + #if defined(FEAT_EVAL) || defined(PROTO) + /* + * Return the name of font "font" in allocated memory. + * Don't know how to get the actual name, thus use the provided name. + */ + /*ARGSUSED*/ + char_u * + gui_mch_get_fontname(GuiFont font, char_u *name) + { + if (name == NULL) + return NULL; + return vim_strsave(name); + } + #endif + + void + gui_mch_free_font(GuiFont font) + { + if (font) + DeleteObject((HFONT)font); + } + + static int + hex_digit(int c) + { + if (VIM_ISDIGIT(c)) + return c - '0'; + c = TOLOWER_ASC(c); + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return -1000; + } + /* + * Return the Pixel value (color) for the given color name. + * Return INVALCOLOR for error. + */ + guicolor_T + gui_mch_get_color(char_u *name) + { + typedef struct guicolor_tTable + { + char *name; + COLORREF color; + } guicolor_tTable; + + static guicolor_tTable table[] = + { + {"Black", RGB(0x00, 0x00, 0x00)}, + {"DarkGray", RGB(0xA9, 0xA9, 0xA9)}, + {"DarkGrey", RGB(0xA9, 0xA9, 0xA9)}, + {"Gray", RGB(0xC0, 0xC0, 0xC0)}, + {"Grey", RGB(0xC0, 0xC0, 0xC0)}, + {"LightGray", RGB(0xD3, 0xD3, 0xD3)}, + {"LightGrey", RGB(0xD3, 0xD3, 0xD3)}, + {"Gray10", RGB(0x1A, 0x1A, 0x1A)}, + {"Grey10", RGB(0x1A, 0x1A, 0x1A)}, + {"Gray20", RGB(0x33, 0x33, 0x33)}, + {"Grey20", RGB(0x33, 0x33, 0x33)}, + {"Gray30", RGB(0x4D, 0x4D, 0x4D)}, + {"Grey30", RGB(0x4D, 0x4D, 0x4D)}, + {"Gray40", RGB(0x66, 0x66, 0x66)}, + {"Grey40", RGB(0x66, 0x66, 0x66)}, + {"Gray50", RGB(0x7F, 0x7F, 0x7F)}, + {"Grey50", RGB(0x7F, 0x7F, 0x7F)}, + {"Gray60", RGB(0x99, 0x99, 0x99)}, + {"Grey60", RGB(0x99, 0x99, 0x99)}, + {"Gray70", RGB(0xB3, 0xB3, 0xB3)}, + {"Grey70", RGB(0xB3, 0xB3, 0xB3)}, + {"Gray80", RGB(0xCC, 0xCC, 0xCC)}, + {"Grey80", RGB(0xCC, 0xCC, 0xCC)}, + {"Gray90", RGB(0xE5, 0xE5, 0xE5)}, + {"Grey90", RGB(0xE5, 0xE5, 0xE5)}, + {"White", RGB(0xFF, 0xFF, 0xFF)}, + {"DarkRed", RGB(0x80, 0x00, 0x00)}, + {"Red", RGB(0xFF, 0x00, 0x00)}, + {"LightRed", RGB(0xFF, 0xA0, 0xA0)}, + {"DarkBlue", RGB(0x00, 0x00, 0x80)}, + {"Blue", RGB(0x00, 0x00, 0xFF)}, + {"LightBlue", RGB(0xAD, 0xD8, 0xE6)}, + {"DarkGreen", RGB(0x00, 0x80, 0x00)}, + {"Green", RGB(0x00, 0xFF, 0x00)}, + {"LightGreen", RGB(0x90, 0xEE, 0x90)}, + {"DarkCyan", RGB(0x00, 0x80, 0x80)}, + {"Cyan", RGB(0x00, 0xFF, 0xFF)}, + {"LightCyan", RGB(0xE0, 0xFF, 0xFF)}, + {"DarkMagenta", RGB(0x80, 0x00, 0x80)}, + {"Magenta", RGB(0xFF, 0x00, 0xFF)}, + {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)}, + {"Brown", RGB(0x80, 0x40, 0x40)}, + {"Yellow", RGB(0xFF, 0xFF, 0x00)}, + {"LightYellow", RGB(0xFF, 0xFF, 0xE0)}, + {"DarkYellow", RGB(0xBB, 0xBB, 0x00)}, + {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, + {"Orange", RGB(0xFF, 0xA5, 0x00)}, + {"Purple", RGB(0xA0, 0x20, 0xF0)}, + {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, + {"Violet", RGB(0xEE, 0x82, 0xEE)}, + }; + + typedef struct SysColorTable + { + char *name; + int color; + } SysColorTable; + + static SysColorTable sys_table[] = + { + #ifdef WIN3264 + {"SYS_3DDKSHADOW", COLOR_3DDKSHADOW}, + {"SYS_3DHILIGHT", COLOR_3DHILIGHT}, + #ifndef __MINGW32__ + {"SYS_3DHIGHLIGHT", COLOR_3DHIGHLIGHT}, + #endif + {"SYS_BTNHILIGHT", COLOR_BTNHILIGHT}, + {"SYS_BTNHIGHLIGHT", COLOR_BTNHIGHLIGHT}, + {"SYS_3DLIGHT", COLOR_3DLIGHT}, + {"SYS_3DSHADOW", COLOR_3DSHADOW}, + {"SYS_DESKTOP", COLOR_DESKTOP}, + {"SYS_INFOBK", COLOR_INFOBK}, + {"SYS_INFOTEXT", COLOR_INFOTEXT}, + {"SYS_3DFACE", COLOR_3DFACE}, + #endif + {"SYS_BTNFACE", COLOR_BTNFACE}, + {"SYS_BTNSHADOW", COLOR_BTNSHADOW}, + {"SYS_ACTIVEBORDER", COLOR_ACTIVEBORDER}, + {"SYS_ACTIVECAPTION", COLOR_ACTIVECAPTION}, + {"SYS_APPWORKSPACE", COLOR_APPWORKSPACE}, + {"SYS_BACKGROUND", COLOR_BACKGROUND}, + {"SYS_BTNTEXT", COLOR_BTNTEXT}, + {"SYS_CAPTIONTEXT", COLOR_CAPTIONTEXT}, + {"SYS_GRAYTEXT", COLOR_GRAYTEXT}, + {"SYS_HIGHLIGHT", COLOR_HIGHLIGHT}, + {"SYS_HIGHLIGHTTEXT", COLOR_HIGHLIGHTTEXT}, + {"SYS_INACTIVEBORDER", COLOR_INACTIVEBORDER}, + {"SYS_INACTIVECAPTION", COLOR_INACTIVECAPTION}, + {"SYS_INACTIVECAPTIONTEXT", COLOR_INACTIVECAPTIONTEXT}, + {"SYS_MENU", COLOR_MENU}, + {"SYS_MENUTEXT", COLOR_MENUTEXT}, + {"SYS_SCROLLBAR", COLOR_SCROLLBAR}, + {"SYS_WINDOW", COLOR_WINDOW}, + {"SYS_WINDOWFRAME", COLOR_WINDOWFRAME}, + {"SYS_WINDOWTEXT", COLOR_WINDOWTEXT} + }; + + int r, g, b; + int i; + + if (name[0] == '#' && STRLEN(name) == 7) + { + /* Name is in "#rrggbb" format */ + r = hex_digit(name[1]) * 16 + hex_digit(name[2]); + g = hex_digit(name[3]) * 16 + hex_digit(name[4]); + b = hex_digit(name[5]) * 16 + hex_digit(name[6]); + if (r < 0 || g < 0 || b < 0) + return INVALCOLOR; + return RGB(r, g, b); + } + else + { + /* Check if the name is one of the colors we know */ + for (i = 0; i < sizeof(table) / sizeof(table[0]); i++) + if (STRICMP(name, table[i].name) == 0) + return table[i].color; + } + + /* + * Try to look up a system colour. + */ + for (i = 0; i < sizeof(sys_table) / sizeof(sys_table[0]); i++) + if (STRICMP(name, sys_table[i].name) == 0) + return GetSysColor(sys_table[i].color); + + /* + * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt". + */ + { + #define LINE_LEN 100 + FILE *fd; + char line[LINE_LEN]; + char_u *fname; + + fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt"); + if (fname == NULL) + return INVALCOLOR; + + fd = mch_fopen((char *)fname, "rt"); + vim_free(fname); + if (fd == NULL) + return INVALCOLOR; + + while (!feof(fd)) + { + int len; + int pos; + char *color; + + fgets(line, LINE_LEN, fd); + len = (int)STRLEN(line); + + if (len <= 1 || line[len-1] != '\n') + continue; + + line[len-1] = '\0'; + + i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos); + if (i != 3) + continue; + + color = line + pos; + + if (STRICMP(color, name) == 0) + { + fclose(fd); + return (guicolor_T) RGB(r, g, b); + } + } + + fclose(fd); + } + + return INVALCOLOR; + } + /* + * Return OK if the key with the termcap name "name" is supported. + */ + int + gui_mch_haskey(char_u *name) + { + int i; + + for (i = 0; special_keys[i].vim_code1 != NUL; i++) + if (name[0] == special_keys[i].vim_code0 && + name[1] == special_keys[i].vim_code1) + return OK; + return FAIL; + } + + void + gui_mch_beep(void) + { + MessageBeep(MB_OK); + } + /* + * Invert a rectangle from row r, column c, for nr rows and nc columns. + */ + void + gui_mch_invert_rectangle( + int r, + int c, + int nr, + int nc) + { + RECT rc; + + /* + * Note: InvertRect() excludes right and bottom of rectangle. + */ + rc.left = FILL_X(c); + rc.top = FILL_Y(r); + rc.right = rc.left + nc * gui.char_width; + rc.bottom = rc.top + nr * gui.char_height; + InvertRect(s_hdc, &rc); + } + + /* + * Iconify the GUI window. + */ + void + gui_mch_iconify(void) + { + ShowWindow(s_hwnd, SW_MINIMIZE); + } + + /* + * Draw a cursor without focus. + */ + void + gui_mch_draw_hollow_cursor(guicolor_T color) + { + HBRUSH hbr; + RECT rc; + + /* + * Note: FrameRect() excludes right and bottom of rectangle. + */ + rc.left = FILL_X(gui.col); + rc.top = FILL_Y(gui.row); + rc.right = rc.left + gui.char_width; + #ifdef FEAT_MBYTE + if (mb_lefthalve(gui.row, gui.col)) + rc.right += gui.char_width; + #endif + rc.bottom = rc.top + gui.char_height; + hbr = CreateSolidBrush(color); + FrameRect(s_hdc, &rc, hbr); + DeleteBrush(hbr); + } + /* + * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using + * color "color". + */ + void + gui_mch_draw_part_cursor( + int w, + int h, + guicolor_T color) + { + HBRUSH hbr; + RECT rc; + + /* + * Note: FillRect() excludes right and bottom of rectangle. + */ + rc.left = + #ifdef FEAT_RIGHTLEFT + /* vertical line should be on the right of current point */ + CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w : + #endif + FILL_X(gui.col); + rc.top = FILL_Y(gui.row) + gui.char_height - h; + rc.right = rc.left + w; + rc.bottom = rc.top + h; + hbr = CreateSolidBrush(color); + FillRect(s_hdc, &rc, hbr); + DeleteBrush(hbr); + } + + + /* + * Generates a VK_SPACE when the internal dead_key flag is set to output the + * dead key's nominal character and re-post the original message. + */ + static void + outputDeadKey_rePost(MSG originalMsg) + { + static MSG deadCharExpel; + + if (!dead_key) + return; + + dead_key = 0; + + /* Make Windows generate the dead key's character */ + deadCharExpel.message = originalMsg.message; + deadCharExpel.hwnd = originalMsg.hwnd; + deadCharExpel.wParam = VK_SPACE; + + MyTranslateMessage(&deadCharExpel); + + /* re-generate the current character free of the dead char influence */ + PostMessage(originalMsg.hwnd, originalMsg.message, originalMsg.wParam, + originalMsg.lParam); + } + + + /* + * Process a single Windows message. + * If one is not available we hang until one is. + */ + static void + process_message(void) + { + MSG msg; + UINT vk = 0; /* Virtual key */ + char_u string[40]; + int i; + int modifiers = 0; + int key; + #ifdef FEAT_MENU + static char_u k10[] = {K_SPECIAL, 'k', ';', 0}; + #endif + + pGetMessage(&msg, NULL, 0, 0); + + #ifdef FEAT_OLE + /* Look after OLE Automation commands */ + if (msg.message == WM_OLE) + { + char_u *str = (char_u *)msg.lParam; + if (str == NULL || *str == NUL) + { + /* Message can't be ours, forward it. Fixes problem with Ultramon + * 3.0.4 */ + pDispatchMessage(&msg); + } + else + { + add_to_input_buf(str, (int)STRLEN(str)); + vim_free(str); /* was allocated in CVim::SendKeys() */ + } + return; + } + #endif + + #ifdef FEAT_CHANNEL + if (msg.message == WM_NETBEANS) + { + int what; + channel_T *channel = channel_fd2channel((sock_T)msg.wParam, &what); + + if (channel != NULL) + { + /* Disable error messages, they can mess up the display and throw + * an exception. */ + ++emsg_off; + channel_read(channel, what, "process_message"); + --emsg_off; + } + return; + } + #endif + + #ifdef FEAT_SNIFF + if (sniff_request_waiting && want_sniff_request) + { + static char_u bytes[3] = {CSI, (char_u)KS_EXTRA, (char_u)KE_SNIFF}; + add_to_input_buf(bytes, 3); /* K_SNIFF */ + sniff_request_waiting = 0; + want_sniff_request = 0; + /* request is handled in normal.c */ + } + if (msg.message == WM_USER) + { + MyTranslateMessage(&msg); + pDispatchMessage(&msg); + return; + } + #endif + + #ifdef MSWIN_FIND_REPLACE + /* Don't process messages used by the dialog */ + if (s_findrep_hwnd != NULL && pIsDialogMessage(s_findrep_hwnd, &msg)) + { + HandleMouseHide(msg.message, msg.lParam); + return; + } + #endif + + /* + * Check if it's a special key that we recognise. If not, call + * TranslateMessage(). + */ + if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) + { + vk = (int) msg.wParam; + + /* + * Handle dead keys in special conditions in other cases we let Windows + * handle them and do not interfere. + * + * The dead_key flag must be reset on several occasions: + * - in _OnChar() (or _OnSysChar()) as any dead key was necessarily + * consumed at that point (This is when we let Windows combine the + * dead character on its own) + * + * - Before doing something special such as regenerating keypresses to + * expel the dead character as this could trigger an infinite loop if + * for some reason MyTranslateMessage() do not trigger a call + * immediately to _OnChar() (or _OnSysChar()). + */ + if (dead_key) + { + /* + * If a dead key was pressed and the user presses VK_SPACE, + * VK_BACK, or VK_ESCAPE it means that he actually wants to deal + * with the dead char now, so do nothing special and let Windows + * handle it. + * + * Note that VK_SPACE combines with the dead_key's character and + * only one WM_CHAR will be generated by TranslateMessage(), in + * the two other cases two WM_CHAR will be generated: the dead + * char and VK_BACK or VK_ESCAPE. That is most likely what the + * user expects. + */ + if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE)) + { + dead_key = 0; + MyTranslateMessage(&msg); + return; + } + /* In modes where we are not typing, dead keys should behave + * normally */ + else if (!(get_real_state() & (INSERT | CMDLINE | SELECTMODE))) + { + outputDeadKey_rePost(msg); + return; + } + } + + /* Check for CTRL-BREAK */ + if (vk == VK_CANCEL) + { + trash_input_buf(); + got_int = TRUE; + string[0] = Ctrl_C; + add_to_input_buf(string, 1); + } + + for (i = 0; special_keys[i].key_sym != 0; i++) + { + /* ignore VK_SPACE when ALT key pressed: system menu */ + if (special_keys[i].key_sym == vk + && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000))) + { + /* + * Behave as exected if we have a dead key and the special key + * is a key that would normally trigger the dead key nominal + * character output (such as a NUMPAD printable character or + * the TAB key, etc...). + */ + if (dead_key && (special_keys[i].vim_code0 == 'K' + || vk == VK_TAB || vk == CAR)) + { + outputDeadKey_rePost(msg); + return; + } + + #ifdef FEAT_MENU + /* Check for : Windows selects the menu. When is + * mapped we want to use the mapping instead. */ + if (vk == VK_F10 + && gui.menu_is_active + && check_map(k10, State, FALSE, TRUE, FALSE, + NULL, NULL) == NULL) + break; + #endif + if (GetKeyState(VK_SHIFT) & 0x8000) + modifiers |= MOD_MASK_SHIFT; + /* + * Don't use caps-lock as shift, because these are special keys + * being considered here, and we only want letters to get + * shifted -- webb + */ + /* + if (GetKeyState(VK_CAPITAL) & 0x0001) + modifiers ^= MOD_MASK_SHIFT; + */ + if (GetKeyState(VK_CONTROL) & 0x8000) + modifiers |= MOD_MASK_CTRL; + if (GetKeyState(VK_MENU) & 0x8000) + modifiers |= MOD_MASK_ALT; + + if (special_keys[i].vim_code1 == NUL) + key = special_keys[i].vim_code0; + else + key = TO_SPECIAL(special_keys[i].vim_code0, + special_keys[i].vim_code1); + key = simplify_key(key, &modifiers); + if (key == CSI) + key = K_CSI; + + if (modifiers) + { + string[0] = CSI; + string[1] = KS_MODIFIER; + string[2] = modifiers; + add_to_input_buf(string, 3); + } + + if (IS_SPECIAL(key)) + { + string[0] = CSI; + string[1] = K_SECOND(key); + string[2] = K_THIRD(key); + add_to_input_buf(string, 3); + } + else + { + int len; + + /* Handle "key" as a Unicode character. */ + len = char_to_string(key, string, 40, FALSE); + add_to_input_buf(string, len); + } + break; + } + } + if (special_keys[i].key_sym == 0) + { + /* Some keys need C-S- where they should only need C-. + * Ignore 0xff, Windows XP sends it when NUMLOCK has changed since + * system startup (Helmut Stiegler, 2003 Oct 3). */ + if (vk != 0xff + && (GetKeyState(VK_CONTROL) & 0x8000) + && !(GetKeyState(VK_SHIFT) & 0x8000) + && !(GetKeyState(VK_MENU) & 0x8000)) + { + /* CTRL-6 is '^'; Japanese keyboard maps '^' to vk == 0xDE */ + if (vk == '6' || MapVirtualKey(vk, 2) == (UINT)'^') + { + string[0] = Ctrl_HAT; + add_to_input_buf(string, 1); + } + /* vk == 0xBD AZERTY for CTRL-'-', but CTRL-[ for * QWERTY! */ + else if (vk == 0xBD) /* QWERTY for CTRL-'-' */ + { + string[0] = Ctrl__; + add_to_input_buf(string, 1); + } + /* CTRL-2 is '@'; Japanese keyboard maps '@' to vk == 0xC0 */ + else if (vk == '2' || MapVirtualKey(vk, 2) == (UINT)'@') + { + string[0] = Ctrl_AT; + add_to_input_buf(string, 1); + } + else + MyTranslateMessage(&msg); + } + else + MyTranslateMessage(&msg); + } + } + #ifdef FEAT_MBYTE_IME + else if (msg.message == WM_IME_NOTIFY) + _OnImeNotify(msg.hwnd, (DWORD)msg.wParam, (DWORD)msg.lParam); + else if (msg.message == WM_KEYUP && im_get_status()) + /* added for non-MS IME (Yasuhiro Matsumoto) */ + MyTranslateMessage(&msg); + #endif + #if !defined(FEAT_MBYTE_IME) && defined(GLOBAL_IME) + /* GIME_TEST */ + else if (msg.message == WM_IME_STARTCOMPOSITION) + { + POINT point; + + global_ime_set_font(&norm_logfont); + point.x = FILL_X(gui.col); + point.y = FILL_Y(gui.row); + MapWindowPoints(s_textArea, s_hwnd, &point, 1); + global_ime_set_position(&point); + } + #endif + + #ifdef FEAT_MENU + /* Check for : Default effect is to select the menu. When is + * mapped we need to stop it here to avoid strange effects (e.g., for the + * key-up event) */ + if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE, + NULL, NULL) == NULL) + #endif + pDispatchMessage(&msg); + } + + /* + * Catch up with any queued events. This may put keyboard input into the + * input buffer, call resize call-backs, trigger timers etc. If there is + * nothing in the event queue (& no timers pending), then we return + * immediately. + */ + void + gui_mch_update(void) + { + MSG msg; + + if (!s_busy_processing) + while (pPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) + && !vim_is_input_buf_full()) + process_message(); + } + + /* + * GUI input routine called by gui_wait_for_chars(). Waits for a character + * from the keyboard. + * wtime == -1 Wait forever. + * wtime == 0 This should never happen. + * wtime > 0 Wait wtime milliseconds for a character. + * Returns OK if a character was found to be available within the given time, + * or FAIL otherwise. + */ + int + gui_mch_wait_for_chars(int wtime) + { + MSG msg; + int focus; + + s_timed_out = FALSE; + + if (wtime > 0) + { + /* Don't do anything while processing a (scroll) message. */ + if (s_busy_processing) + return FAIL; + s_wait_timer = (UINT)SetTimer(NULL, 0, (UINT)wtime, + (TIMERPROC)_OnTimer); + } + + allow_scrollbar = TRUE; + + focus = gui.in_focus; + while (!s_timed_out) + { + /* Stop or start blinking when focus changes */ + if (gui.in_focus != focus) + { + if (gui.in_focus) + gui_mch_start_blink(); + else + gui_mch_stop_blink(); + focus = gui.in_focus; + } + + if (s_need_activate) + { + #ifdef WIN32 + (void)SetForegroundWindow(s_hwnd); + #else + (void)SetActiveWindow(s_hwnd); + #endif + s_need_activate = FALSE; + } + + #ifdef MESSAGE_QUEUE + parse_queued_messages(); + #endif + + #ifdef FEAT_CHANNEL + channel_handle_events(); + #endif + + /* + * Don't use gui_mch_update() because then we will spin-lock until a + * char arrives, instead we use GetMessage() to hang until an + * event arrives. No need to check for input_buf_full because we are + * returning as soon as it contains a single char -- webb + */ + process_message(); + + if (input_available()) + { + if (s_wait_timer != 0 && !s_timed_out) + { + KillTimer(NULL, s_wait_timer); + + /* Eat spurious WM_TIMER messages */ + while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) + ; + s_wait_timer = 0; + } + allow_scrollbar = FALSE; + + /* Clear pending mouse button, the release event may have been + * taken by the dialog window. But don't do this when getting + * focus, we need the mouse-up event then. */ + if (!s_getting_focus) + s_button_pending = -1; + + return OK; + } + } + allow_scrollbar = FALSE; + return FAIL; + } + + /* + * Clear a rectangular region of the screen from text pos (row1, col1) to + * (row2, col2) inclusive. + */ + void + gui_mch_clear_block( + int row1, + int col1, + int row2, + int col2) + { + RECT rc; + + /* + * Clear one extra pixel at the far right, for when bold characters have + * spilled over to the window border. + * Note: FillRect() excludes right and bottom of rectangle. + */ + rc.left = FILL_X(col1); + rc.top = FILL_Y(row1); + rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1); + rc.bottom = FILL_Y(row2 + 1); + clear_rect(&rc); + } + + /* + * Clear the whole text window. + */ + void + gui_mch_clear_all(void) + { + RECT rc; + + rc.left = 0; + rc.top = 0; + rc.right = Columns * gui.char_width + 2 * gui.border_width; + rc.bottom = Rows * gui.char_height + 2 * gui.border_width; + clear_rect(&rc); + } + /* + * Menu stuff. + */ + + void + gui_mch_enable_menu(int flag) + { + #ifdef FEAT_MENU + SetMenu(s_hwnd, flag ? s_menuBar : NULL); + #endif + } + + /*ARGSUSED*/ + void + gui_mch_set_menu_pos( + int x, + int y, + int w, + int h) + { + /* It will be in the right place anyway */ + } + + #if defined(FEAT_MENU) || defined(PROTO) + /* + * Make menu item hidden or not hidden + */ + void + gui_mch_menu_hidden( + vimmenu_T *menu, + int hidden) + { + /* + * This doesn't do what we want. Hmm, just grey the menu items for now. + */ + /* + if (hidden) + EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_DISABLED); + else + EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED); + */ + gui_mch_menu_grey(menu, hidden); + } + + /* + * This is called after setting all the menus to grey/hidden or not. + */ + void + gui_mch_draw_menubar(void) + { + DrawMenuBar(s_hwnd); + } + #endif /*FEAT_MENU*/ + + #ifndef PROTO + void + #ifdef VIMDLL + _export + #endif + _cdecl + SaveInst(HINSTANCE hInst) + { + s_hinst = hInst; + } + #endif + + /* + * Return the RGB value of a pixel as a long. + */ + long_u + gui_mch_get_rgb(guicolor_T pixel) + { + return (GetRValue(pixel) << 16) + (GetGValue(pixel) << 8) + + GetBValue(pixel); + } + + #if defined(FEAT_GUI_DIALOG) || defined(PROTO) + /* Convert pixels in X to dialog units */ + static WORD + PixelToDialogX(int numPixels) + { + return (WORD)((numPixels * 4) / s_dlgfntwidth); + } + + /* Convert pixels in Y to dialog units */ + static WORD + PixelToDialogY(int numPixels) + { + return (WORD)((numPixels * 8) / s_dlgfntheight); + } + + /* Return the width in pixels of the given text in the given DC. */ + static int + GetTextWidth(HDC hdc, char_u *str, int len) + { + SIZE size; + + GetTextExtentPoint(hdc, (LPCSTR)str, len, &size); + return size.cx; + } + + #ifdef FEAT_MBYTE + /* + * Return the width in pixels of the given text in the given DC, taking care + * of 'encoding' to active codepage conversion. + */ + static int + GetTextWidthEnc(HDC hdc, char_u *str, int len) + { + SIZE size; + WCHAR *wstr; + int n; + int wlen = len; + + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + /* 'encoding' differs from active codepage: convert text and use wide + * function */ + wstr = enc_to_utf16(str, &wlen); + if (wstr != NULL) + { + n = GetTextExtentPointW(hdc, wstr, wlen, &size); + vim_free(wstr); + if (n) + return size.cx; + } + } + + return GetTextWidth(hdc, str, len); + } + #else + # define GetTextWidthEnc(h, s, l) GetTextWidth((h), (s), (l)) + #endif + + /* + * A quick little routine that will center one window over another, handy for + * dialog boxes. Taken from the Win32SDK samples. + */ + static BOOL + CenterWindow( + HWND hwndChild, + HWND hwndParent) + { + RECT rChild, rParent; + int wChild, hChild, wParent, hParent; + int wScreen, hScreen, xNew, yNew; + HDC hdc; + + GetWindowRect(hwndChild, &rChild); + wChild = rChild.right - rChild.left; + hChild = rChild.bottom - rChild.top; + + /* If Vim is minimized put the window in the middle of the screen. */ + if (hwndParent == NULL || IsMinimized(hwndParent)) + SystemParametersInfo(SPI_GETWORKAREA, 0, &rParent, 0); + else + GetWindowRect(hwndParent, &rParent); + wParent = rParent.right - rParent.left; + hParent = rParent.bottom - rParent.top; + + hdc = GetDC(hwndChild); + wScreen = GetDeviceCaps (hdc, HORZRES); + hScreen = GetDeviceCaps (hdc, VERTRES); + ReleaseDC(hwndChild, hdc); + + xNew = rParent.left + ((wParent - wChild) /2); + if (xNew < 0) + { + xNew = 0; + } + else if ((xNew+wChild) > wScreen) + { + xNew = wScreen - wChild; + } + + yNew = rParent.top + ((hParent - hChild) /2); + if (yNew < 0) + yNew = 0; + else if ((yNew+hChild) > hScreen) + yNew = hScreen - hChild; + + return SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + } + #endif /* FEAT_GUI_DIALOG */ + + void + gui_mch_activate_window(void) + { + (void)SetActiveWindow(s_hwnd); + } + + #if defined(FEAT_TOOLBAR) || defined(PROTO) + void + gui_mch_show_toolbar(int showit) + { + if (s_toolbarhwnd == NULL) + return; + + if (showit) + { + # ifdef FEAT_MBYTE + # ifndef TB_SETUNICODEFORMAT + /* For older compilers. We assume this never changes. */ + # define TB_SETUNICODEFORMAT 0x2005 + # endif + /* Enable/disable unicode support */ + int uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage); + SendMessage(s_toolbarhwnd, TB_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0); + # endif + ShowWindow(s_toolbarhwnd, SW_SHOW); + } + else + ShowWindow(s_toolbarhwnd, SW_HIDE); + } + + /* Then number of bitmaps is fixed. Exit is missing! */ + #define TOOLBAR_BITMAP_COUNT 31 + + #endif + + #if defined(FEAT_GUI_TABLINE) || defined(PROTO) + static void + add_tabline_popup_menu_entry(HMENU pmenu, UINT item_id, char_u *item_text) + { + #ifdef FEAT_MBYTE + WCHAR *wn = NULL; + int n; + + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + /* 'encoding' differs from active codepage: convert menu name + * and use wide function */ + wn = enc_to_utf16(item_text, NULL); + if (wn != NULL) + { + MENUITEMINFOW infow; + + infow.cbSize = sizeof(infow); + infow.fMask = MIIM_TYPE | MIIM_ID; + infow.wID = item_id; + infow.fType = MFT_STRING; + infow.dwTypeData = wn; + infow.cch = (UINT)wcslen(wn); + n = InsertMenuItemW(pmenu, item_id, FALSE, &infow); + vim_free(wn); + if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + /* Failed, try using non-wide function. */ + wn = NULL; + } + } + + if (wn == NULL) + #endif + { + MENUITEMINFO info; + + info.cbSize = sizeof(info); + info.fMask = MIIM_TYPE | MIIM_ID; + info.wID = item_id; + info.fType = MFT_STRING; + info.dwTypeData = (LPTSTR)item_text; + info.cch = (UINT)STRLEN(item_text); + InsertMenuItem(pmenu, item_id, FALSE, &info); + } + } + + static void + show_tabline_popup_menu(void) + { + HMENU tab_pmenu; + long rval; + POINT pt; + + /* When ignoring events don't show the menu. */ + if (hold_gui_events + # ifdef FEAT_CMDWIN + || cmdwin_type != 0 + # endif + ) + return; + + tab_pmenu = CreatePopupMenu(); + if (tab_pmenu == NULL) + return; + + if (first_tabpage->tp_next != NULL) + add_tabline_popup_menu_entry(tab_pmenu, + TABLINE_MENU_CLOSE, (char_u *)_("Close tab")); + add_tabline_popup_menu_entry(tab_pmenu, + TABLINE_MENU_NEW, (char_u *)_("New tab")); + add_tabline_popup_menu_entry(tab_pmenu, + TABLINE_MENU_OPEN, (char_u *)_("Open tab...")); + + GetCursorPos(&pt); + rval = TrackPopupMenuEx(tab_pmenu, TPM_RETURNCMD, pt.x, pt.y, s_tabhwnd, + NULL); + + DestroyMenu(tab_pmenu); + + /* Add the string cmd into input buffer */ + if (rval > 0) + { + TCHITTESTINFO htinfo; + int idx; + + if (ScreenToClient(s_tabhwnd, &pt) == 0) + return; + + htinfo.pt.x = pt.x; + htinfo.pt.y = pt.y; + idx = TabCtrl_HitTest(s_tabhwnd, &htinfo); + if (idx == -1) + idx = 0; + else + idx += 1; + + send_tabline_menu_event(idx, (int)rval); + } + } + + /* + * Show or hide the tabline. + */ + void + gui_mch_show_tabline(int showit) + { + if (s_tabhwnd == NULL) + return; + + if (!showit != !showing_tabline) + { + if (showit) + ShowWindow(s_tabhwnd, SW_SHOW); + else + ShowWindow(s_tabhwnd, SW_HIDE); + showing_tabline = showit; + } + } + + /* + * Return TRUE when tabline is displayed. + */ + int + gui_mch_showing_tabline(void) + { + return s_tabhwnd != NULL && showing_tabline; + } + + /* + * Update the labels of the tabline. + */ + void + gui_mch_update_tabline(void) + { + tabpage_T *tp; + TCITEM tie; + int nr = 0; + int curtabidx = 0; + int tabadded = 0; + #ifdef FEAT_MBYTE + static int use_unicode = FALSE; + int uu; + WCHAR *wstr = NULL; + #endif + + if (s_tabhwnd == NULL) + return; + + #if defined(FEAT_MBYTE) + # ifndef CCM_SETUNICODEFORMAT + /* For older compilers. We assume this never changes. */ + # define CCM_SETUNICODEFORMAT 0x2005 + # endif + uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage); + if (uu != use_unicode) + { + /* Enable/disable unicode support */ + SendMessage(s_tabhwnd, CCM_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0); + use_unicode = uu; + } + #endif + + tie.mask = TCIF_TEXT; + tie.iImage = -1; + + /* Disable redraw for tab updates to eliminate O(N^2) draws. */ + SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)FALSE, 0); + + /* Add a label for each tab page. They all contain the same text area. */ + for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) + { + if (tp == curtab) + curtabidx = nr; + + if (nr >= TabCtrl_GetItemCount(s_tabhwnd)) + { + /* Add the tab */ + tie.pszText = "-Empty-"; + TabCtrl_InsertItem(s_tabhwnd, nr, &tie); + tabadded = 1; + } + + get_tabline_label(tp, FALSE); + tie.pszText = (LPSTR)NameBuff; + #ifdef FEAT_MBYTE + wstr = NULL; + if (use_unicode) + { + /* Need to go through Unicode. */ + wstr = enc_to_utf16(NameBuff, NULL); + if (wstr != NULL) + { + TCITEMW tiw; + + tiw.mask = TCIF_TEXT; + tiw.iImage = -1; + tiw.pszText = wstr; + SendMessage(s_tabhwnd, TCM_SETITEMW, (WPARAM)nr, (LPARAM)&tiw); + vim_free(wstr); + } + } + if (wstr == NULL) + #endif + { + TabCtrl_SetItem(s_tabhwnd, nr, &tie); + } + } + + /* Remove any old labels. */ + while (nr < TabCtrl_GetItemCount(s_tabhwnd)) + TabCtrl_DeleteItem(s_tabhwnd, nr); + + if (!tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx) + TabCtrl_SetCurSel(s_tabhwnd, curtabidx); + + /* Re-enable redraw and redraw. */ + SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)TRUE, 0); + RedrawWindow(s_tabhwnd, NULL, NULL, + RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); + + if (tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx) + TabCtrl_SetCurSel(s_tabhwnd, curtabidx); + } + + /* + * Set the current tab to "nr". First tab is 1. + */ + void + gui_mch_set_curtab(int nr) + { + if (s_tabhwnd == NULL) + return; + + if (TabCtrl_GetCurSel(s_tabhwnd) != nr - 1) + TabCtrl_SetCurSel(s_tabhwnd, nr - 1); + } + + #endif + + /* + * ":simalt" command. + */ + void + ex_simalt(exarg_T *eap) + { + char_u *keys = eap->arg; + + PostMessage(s_hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)0); + while (*keys) + { + if (*keys == '~') + *keys = ' '; /* for showing system menu */ + PostMessage(s_hwnd, WM_CHAR, (WPARAM)*keys, (LPARAM)0); + keys++; + } + } + + /* + * Create the find & replace dialogs. + * You can't have both at once: ":find" when replace is showing, destroys + * the replace dialog first, and the other way around. + */ + #ifdef MSWIN_FIND_REPLACE + static void + initialise_findrep(char_u *initial_string) + { + int wword = FALSE; + int mcase = !p_ic; + char_u *entry_text; + + /* Get the search string to use. */ + entry_text = get_find_dialog_text(initial_string, &wword, &mcase); + + s_findrep_struct.hwndOwner = s_hwnd; + s_findrep_struct.Flags = FR_DOWN; + if (mcase) + s_findrep_struct.Flags |= FR_MATCHCASE; + if (wword) + s_findrep_struct.Flags |= FR_WHOLEWORD; + if (entry_text != NULL && *entry_text != NUL) + vim_strncpy((char_u *)s_findrep_struct.lpstrFindWhat, entry_text, + s_findrep_struct.wFindWhatLen - 1); + vim_free(entry_text); + } + #endif + + static void + set_window_title(HWND hwnd, char *title) + { + #ifdef FEAT_MBYTE + if (title != NULL && enc_codepage >= 0 && enc_codepage != (int)GetACP()) + { + WCHAR *wbuf; + int n; + + /* Convert the title from 'encoding' to UTF-16. */ + wbuf = (WCHAR *)enc_to_utf16((char_u *)title, NULL); + if (wbuf != NULL) + { + n = SetWindowTextW(hwnd, wbuf); + vim_free(wbuf); + if (n != 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return; + /* Retry with non-wide function (for Windows 98). */ + } + } + #endif + (void)SetWindowText(hwnd, (LPCSTR)title); + } + + void + gui_mch_find_dialog(exarg_T *eap) + { + #ifdef MSWIN_FIND_REPLACE + if (s_findrep_msg != 0) + { + if (IsWindow(s_findrep_hwnd) && !s_findrep_is_find) + DestroyWindow(s_findrep_hwnd); + + if (!IsWindow(s_findrep_hwnd)) + { + initialise_findrep(eap->arg); + # if defined(FEAT_MBYTE) && defined(WIN3264) + /* If the OS is Windows NT, and 'encoding' differs from active + * codepage: convert text and use wide function. */ + if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT + && enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + findrep_atow(&s_findrep_struct_w, &s_findrep_struct); + s_findrep_hwnd = FindTextW( + (LPFINDREPLACEW) &s_findrep_struct_w); + } + else + # endif + s_findrep_hwnd = FindText((LPFINDREPLACE) &s_findrep_struct); + } + + set_window_title(s_findrep_hwnd, + _("Find string (use '\\\\' to find a '\\')")); + (void)SetFocus(s_findrep_hwnd); + + s_findrep_is_find = TRUE; + } + #endif + } + + + void + gui_mch_replace_dialog(exarg_T *eap) + { + #ifdef MSWIN_FIND_REPLACE + if (s_findrep_msg != 0) + { + if (IsWindow(s_findrep_hwnd) && s_findrep_is_find) + DestroyWindow(s_findrep_hwnd); + + if (!IsWindow(s_findrep_hwnd)) + { + initialise_findrep(eap->arg); + # if defined(FEAT_MBYTE) && defined(WIN3264) + if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT + && enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + findrep_atow(&s_findrep_struct_w, &s_findrep_struct); + s_findrep_hwnd = ReplaceTextW( + (LPFINDREPLACEW) &s_findrep_struct_w); + } + else + # endif + s_findrep_hwnd = ReplaceText( + (LPFINDREPLACE) &s_findrep_struct); + } + + set_window_title(s_findrep_hwnd, + _("Find & Replace (use '\\\\' to find a '\\')")); + (void)SetFocus(s_findrep_hwnd); + + s_findrep_is_find = FALSE; + } + #endif + } + + + /* + * Set visibility of the pointer. + */ + void + gui_mch_mousehide(int hide) + { + if (hide != gui.pointer_hidden) + { + ShowCursor(!hide); + gui.pointer_hidden = hide; + } + } + + #ifdef FEAT_MENU + static void + gui_mch_show_popupmenu_at(vimmenu_T *menu, int x, int y) + { + /* Unhide the mouse, we don't get move events here. */ + gui_mch_mousehide(FALSE); + + (void)TrackPopupMenu( + (HMENU)menu->submenu_id, + TPM_LEFTALIGN | TPM_LEFTBUTTON, + x, y, + (int)0, /*reserved param*/ + s_hwnd, + NULL); + /* + * NOTE: The pop-up menu can eat the mouse up event. + * We deal with this in normal.c. + */ + } + #endif + + /* + * Got a message when the system will go down. + */ + static void + _OnEndSession(void) + { + getout_preserve_modified(1); + } + + /* + * Get this message when the user clicks on the cross in the top right corner + * of a Windows95 window. + */ + /*ARGSUSED*/ + static void + _OnClose( + HWND hwnd) + { + gui_shell_closed(); + } + + /* + * Get a message when the window is being destroyed. + */ + static void + _OnDestroy( + HWND hwnd) + { + if (!destroying) + _OnClose(hwnd); + } + + static void + _OnPaint( + HWND hwnd) + { + if (!IsMinimized(hwnd)) + { + PAINTSTRUCT ps; + + out_flush(); /* make sure all output has been processed */ + (void)BeginPaint(hwnd, &ps); + #if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_BeginDraw(s_dwc); + #endif + + #ifdef FEAT_MBYTE + /* prevent multi-byte characters from misprinting on an invalid + * rectangle */ + if (has_mbyte) + { + RECT rect; + + GetClientRect(hwnd, &rect); + ps.rcPaint.left = rect.left; + ps.rcPaint.right = rect.right; + } + #endif + + if (!IsRectEmpty(&ps.rcPaint)) + { + #if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_BindDC(s_dwc, s_hdc, &ps.rcPaint); + #endif + gui_redraw(ps.rcPaint.left, ps.rcPaint.top, + ps.rcPaint.right - ps.rcPaint.left + 1, + ps.rcPaint.bottom - ps.rcPaint.top + 1); + } + + #if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_EndDraw(s_dwc); + #endif + EndPaint(hwnd, &ps); + } + } + + /*ARGSUSED*/ + static void + _OnSize( + HWND hwnd, + UINT state, + int cx, + int cy) + { + if (!IsMinimized(hwnd)) + { + gui_resize_shell(cx, cy); + + #ifdef FEAT_MENU + /* Menu bar may wrap differently now */ + gui_mswin_get_menu_height(TRUE); + #endif + } + } + + static void + _OnSetFocus( + HWND hwnd, + HWND hwndOldFocus) + { + gui_focus_change(TRUE); + s_getting_focus = TRUE; + (void)MyWindowProc(hwnd, WM_SETFOCUS, (WPARAM)hwndOldFocus, 0); + } + + static void + _OnKillFocus( + HWND hwnd, + HWND hwndNewFocus) + { + gui_focus_change(FALSE); + s_getting_focus = FALSE; + (void)MyWindowProc(hwnd, WM_KILLFOCUS, (WPARAM)hwndNewFocus, 0); + } + + /* + * Get a message when the user switches back to vim + */ + static LRESULT + _OnActivateApp( + HWND hwnd, + BOOL fActivate, + DWORD dwThreadId) + { + /* we call gui_focus_change() in _OnSetFocus() */ + /* gui_focus_change((int)fActivate); */ + return MyWindowProc(hwnd, WM_ACTIVATEAPP, fActivate, (DWORD)dwThreadId); + } + + #if defined(FEAT_WINDOWS) || defined(PROTO) + void + gui_mch_destroy_scrollbar(scrollbar_T *sb) + { + DestroyWindow(sb->id); + } + #endif + + /* + * Get current mouse coordinates in text window. + */ + void + gui_mch_getmouse(int *x, int *y) + { + RECT rct; + POINT mp; + + (void)GetWindowRect(s_textArea, &rct); + (void)GetCursorPos((LPPOINT)&mp); + *x = (int)(mp.x - rct.left); + *y = (int)(mp.y - rct.top); + } + + /* + * Move mouse pointer to character at (x, y). + */ + void + gui_mch_setmouse(int x, int y) + { + RECT rct; + + (void)GetWindowRect(s_textArea, &rct); + (void)SetCursorPos(x + gui.border_offset + rct.left, + y + gui.border_offset + rct.top); + } + + static void + gui_mswin_get_valid_dimensions( + int w, + int h, + int *valid_w, + int *valid_h) + { + int base_width, base_height; + + base_width = gui_get_base_width() + + (GetSystemMetrics(SM_CXFRAME) + + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2; + base_height = gui_get_base_height() + + (GetSystemMetrics(SM_CYFRAME) + + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2 + + GetSystemMetrics(SM_CYCAPTION) + #ifdef FEAT_MENU + + gui_mswin_get_menu_height(FALSE) + #endif + ; + *valid_w = base_width + + ((w - base_width) / gui.char_width) * gui.char_width; + *valid_h = base_height + + ((h - base_height) / gui.char_height) * gui.char_height; + } + + void + gui_mch_flash(int msec) + { + RECT rc; + + /* + * Note: InvertRect() excludes right and bottom of rectangle. + */ + rc.left = 0; + rc.top = 0; + rc.right = gui.num_cols * gui.char_width; + rc.bottom = gui.num_rows * gui.char_height; + InvertRect(s_hdc, &rc); + gui_mch_flush(); /* make sure it's displayed */ + + ui_delay((long)msec, TRUE); /* wait for a few msec */ + + InvertRect(s_hdc, &rc); + } + + /* + * Return flags used for scrolling. + * The SW_INVALIDATE is required when part of the window is covered or + * off-screen. Refer to MS KB Q75236. + */ + static int + get_scroll_flags(void) + { + HWND hwnd; + RECT rcVim, rcOther, rcDest; + + GetWindowRect(s_hwnd, &rcVim); + + /* Check if the window is partly above or below the screen. We don't care + * about partly left or right of the screen, it is not relevant when + * scrolling up or down. */ + if (rcVim.top < 0 || rcVim.bottom > GetSystemMetrics(SM_CYFULLSCREEN)) + return SW_INVALIDATE; + + /* Check if there is an window (partly) on top of us. */ + for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; ) + if (IsWindowVisible(hwnd)) + { + GetWindowRect(hwnd, &rcOther); + if (IntersectRect(&rcDest, &rcVim, &rcOther)) + return SW_INVALIDATE; + } + return 0; + } + + /* + * On some Intel GPUs, the regions drawn just prior to ScrollWindowEx() + * may not be scrolled out properly. + * For gVim, when _OnScroll() is repeated, the character at the + * previous cursor position may be left drawn after scroll. + * The problem can be avoided by calling GetPixel() to get a pixel in + * the region before ScrollWindowEx(). + */ + static void + intel_gpu_workaround(void) + { + GetPixel(s_hdc, FILL_X(gui.col), FILL_Y(gui.row)); + } + + /* + * Delete the given number of lines from the given row, scrolling up any + * text further down within the scroll region. + */ + void + gui_mch_delete_lines( + int row, + int num_lines) + { + RECT rc; + + intel_gpu_workaround(); + + rc.left = FILL_X(gui.scroll_region_left); + rc.right = FILL_X(gui.scroll_region_right + 1); + rc.top = FILL_Y(row); + rc.bottom = FILL_Y(gui.scroll_region_bot + 1); + + ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height, + &rc, &rc, NULL, NULL, get_scroll_flags()); + + UpdateWindow(s_textArea); + /* This seems to be required to avoid the cursor disappearing when + * scrolling such that the cursor ends up in the top-left character on + * the screen... But why? (Webb) */ + /* It's probably fixed by disabling drawing the cursor while scrolling. */ + /* gui.cursor_is_valid = FALSE; */ + + gui_clear_block(gui.scroll_region_bot - num_lines + 1, + gui.scroll_region_left, + gui.scroll_region_bot, gui.scroll_region_right); + } + + /* + * Insert the given number of lines before the given row, scrolling down any + * following text within the scroll region. + */ + void + gui_mch_insert_lines( + int row, + int num_lines) + { + RECT rc; + + intel_gpu_workaround(); + + rc.left = FILL_X(gui.scroll_region_left); + rc.right = FILL_X(gui.scroll_region_right + 1); + rc.top = FILL_Y(row); + rc.bottom = FILL_Y(gui.scroll_region_bot + 1); + /* The SW_INVALIDATE is required when part of the window is covered or + * off-screen. How do we avoid it when it's not needed? */ + ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height, + &rc, &rc, NULL, NULL, get_scroll_flags()); + + UpdateWindow(s_textArea); + + gui_clear_block(row, gui.scroll_region_left, + row + num_lines - 1, gui.scroll_region_right); + } + + + /*ARGSUSED*/ + void + gui_mch_exit(int rc) + { + #if defined(FEAT_DIRECTX) + DWriteContext_Close(s_dwc); + DWrite_Final(); + s_dwc = NULL; + #endif + + ReleaseDC(s_textArea, s_hdc); + DeleteObject(s_brush); + + #ifdef FEAT_TEAROFF + /* Unload the tearoff bitmap */ + (void)DeleteObject((HGDIOBJ)s_htearbitmap); + #endif + + /* Destroy our window (if we have one). */ + if (s_hwnd != NULL) + { + destroying = TRUE; /* ignore WM_DESTROY message now */ + DestroyWindow(s_hwnd); + } + + #ifdef GLOBAL_IME + global_ime_end(); + #endif + } + + static char_u * + logfont2name(LOGFONT lf) + { + char *p; + char *res; + char *charset_name; + char *font_name = lf.lfFaceName; + + charset_name = charset_id2name((int)lf.lfCharSet); + #ifdef FEAT_MBYTE + /* Convert a font name from the current codepage to 'encoding'. + * TODO: Use Wide APIs (including LOGFONTW) instead of ANSI APIs. */ + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + int len; + acp_to_enc((char_u *)lf.lfFaceName, (int)strlen(lf.lfFaceName), + (char_u **)&font_name, &len); + } + #endif + res = (char *)alloc((unsigned)(strlen(font_name) + 20 + + (charset_name == NULL ? 0 : strlen(charset_name) + 2))); + if (res != NULL) + { + p = res; + /* make a normal font string out of the lf thing:*/ + sprintf((char *)p, "%s:h%d", font_name, pixels_to_points( + lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight, TRUE)); + while (*p) + { + if (*p == ' ') + *p = '_'; + ++p; + } + if (lf.lfItalic) + STRCAT(p, ":i"); + if (lf.lfWeight >= FW_BOLD) + STRCAT(p, ":b"); + if (lf.lfUnderline) + STRCAT(p, ":u"); + if (lf.lfStrikeOut) + STRCAT(p, ":s"); + if (charset_name != NULL) + { + STRCAT(p, ":c"); + STRCAT(p, charset_name); + } + } + + #ifdef FEAT_MBYTE + if (font_name != lf.lfFaceName) + vim_free(font_name); + #endif + return (char_u *)res; + } + + + #ifdef FEAT_MBYTE_IME + /* + * Set correct LOGFONT to IME. Use 'guifontwide' if available, otherwise use + * 'guifont' + */ + static void + update_im_font(void) + { + LOGFONT lf_wide; + + if (p_guifontwide != NULL && *p_guifontwide != NUL + && gui.wide_font != NOFONT + && GetObject((HFONT)gui.wide_font, sizeof(lf_wide), &lf_wide)) + norm_logfont = lf_wide; + else + norm_logfont = sub_logfont; + im_set_font(&norm_logfont); + } + #endif + + #ifdef FEAT_MBYTE + /* + * Handler of gui.wide_font (p_guifontwide) changed notification. + */ + void + gui_mch_wide_font_changed(void) + { + LOGFONT lf; + + # ifdef FEAT_MBYTE_IME + update_im_font(); + # endif + + gui_mch_free_font(gui.wide_ital_font); + gui.wide_ital_font = NOFONT; + gui_mch_free_font(gui.wide_bold_font); + gui.wide_bold_font = NOFONT; + gui_mch_free_font(gui.wide_boldital_font); + gui.wide_boldital_font = NOFONT; + + if (gui.wide_font + && GetObject((HFONT)gui.wide_font, sizeof(lf), &lf)) + { + if (!lf.lfItalic) + { + lf.lfItalic = TRUE; + gui.wide_ital_font = get_font_handle(&lf); + lf.lfItalic = FALSE; + } + if (lf.lfWeight < FW_BOLD) + { + lf.lfWeight = FW_BOLD; + gui.wide_bold_font = get_font_handle(&lf); + if (!lf.lfItalic) + { + lf.lfItalic = TRUE; + gui.wide_boldital_font = get_font_handle(&lf); + } + } + } + } + #endif + + /* + * Initialise vim to use the font with the given name. + * Return FAIL if the font could not be loaded, OK otherwise. + */ + /*ARGSUSED*/ + int + gui_mch_init_font(char_u *font_name, int fontset) + { + LOGFONT lf; + GuiFont font = NOFONT; + char_u *p; + + /* Load the font */ + if (get_logfont(&lf, font_name, NULL, TRUE) == OK) + font = get_font_handle(&lf); + if (font == NOFONT) + return FAIL; + + if (font_name == NULL) + font_name = (char_u *)lf.lfFaceName; + #if defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME) + norm_logfont = lf; + sub_logfont = lf; + #endif + #ifdef FEAT_MBYTE_IME + update_im_font(); + #endif + gui_mch_free_font(gui.norm_font); + gui.norm_font = font; + current_font_height = lf.lfHeight; + GetFontSize(font); + + p = logfont2name(lf); + if (p != NULL) + { + hl_set_font_name(p); + + /* When setting 'guifont' to "*" replace it with the actual font name. + * */ + if (STRCMP(font_name, "*") == 0 && STRCMP(p_guifont, "*") == 0) + { + vim_free(p_guifont); + p_guifont = p; + } + else + vim_free(p); + } + + gui_mch_free_font(gui.ital_font); + gui.ital_font = NOFONT; + gui_mch_free_font(gui.bold_font); + gui.bold_font = NOFONT; + gui_mch_free_font(gui.boldital_font); + gui.boldital_font = NOFONT; + + if (!lf.lfItalic) + { + lf.lfItalic = TRUE; + gui.ital_font = get_font_handle(&lf); + lf.lfItalic = FALSE; + } + if (lf.lfWeight < FW_BOLD) + { + lf.lfWeight = FW_BOLD; + gui.bold_font = get_font_handle(&lf); + if (!lf.lfItalic) + { + lf.lfItalic = TRUE; + gui.boldital_font = get_font_handle(&lf); + } + } + + return OK; + } + + #ifndef WPF_RESTORETOMAXIMIZED + # define WPF_RESTORETOMAXIMIZED 2 /* just in case someone doesn't have it */ + #endif + + /* + * Return TRUE if the GUI window is maximized, filling the whole screen. + */ + int + gui_mch_maximized(void) + { + WINDOWPLACEMENT wp; + + wp.length = sizeof(WINDOWPLACEMENT); + if (GetWindowPlacement(s_hwnd, &wp)) + return wp.showCmd == SW_SHOWMAXIMIZED + || (wp.showCmd == SW_SHOWMINIMIZED + && wp.flags == WPF_RESTORETOMAXIMIZED); + + return 0; + } + + /* + * Called when the font changed while the window is maximized. Compute the + * new Rows and Columns. This is like resizing the window. + */ + void + gui_mch_newfont(void) + { + RECT rect; + + GetWindowRect(s_hwnd, &rect); + if (win_socket_id == 0) + { + gui_resize_shell(rect.right - rect.left + - (GetSystemMetrics(SM_CXFRAME) + + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2, + rect.bottom - rect.top + - (GetSystemMetrics(SM_CYFRAME) + + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2 + - GetSystemMetrics(SM_CYCAPTION) + #ifdef FEAT_MENU + - gui_mswin_get_menu_height(FALSE) + #endif + ); + } + else + { + /* Inside another window, don't use the frame and border. */ + gui_resize_shell(rect.right - rect.left, + rect.bottom - rect.top + #ifdef FEAT_MENU + - gui_mswin_get_menu_height(FALSE) + #endif + ); + } + } + + /* + * Set the window title + */ + /*ARGSUSED*/ + void + gui_mch_settitle( + char_u *title, + char_u *icon) + { + set_window_title(s_hwnd, (title == NULL ? "VIM" : (char *)title)); + } + + #ifdef FEAT_MOUSESHAPE + /* Table for shape IDCs. Keep in sync with the mshape_names[] table in + * misc2.c! */ + static LPCSTR mshape_idcs[] = + { + IDC_ARROW, /* arrow */ + MAKEINTRESOURCE(0), /* blank */ + IDC_IBEAM, /* beam */ + IDC_SIZENS, /* updown */ + IDC_SIZENS, /* udsizing */ + IDC_SIZEWE, /* leftright */ + IDC_SIZEWE, /* lrsizing */ + IDC_WAIT, /* busy */ + #ifdef WIN3264 + IDC_NO, /* no */ + #else + IDC_ICON, /* no */ + #endif + IDC_ARROW, /* crosshair */ + IDC_ARROW, /* hand1 */ + IDC_ARROW, /* hand2 */ + IDC_ARROW, /* pencil */ + IDC_ARROW, /* question */ + IDC_ARROW, /* right-arrow */ + IDC_UPARROW, /* up-arrow */ + IDC_ARROW /* last one */ + }; + + void + mch_set_mouse_shape(int shape) + { + LPCSTR idc; + + if (shape == MSHAPE_HIDE) + ShowCursor(FALSE); + else + { + if (shape >= MSHAPE_NUMBERED) + idc = IDC_ARROW; + else + idc = mshape_idcs[shape]; + #ifdef SetClassLongPtr + SetClassLongPtr(s_textArea, GCLP_HCURSOR, (__int3264)(LONG_PTR)LoadCursor(NULL, idc)); + #else + # ifdef WIN32 + SetClassLong(s_textArea, GCL_HCURSOR, (long_u)LoadCursor(NULL, idc)); + # else /* Win16 */ + SetClassWord(s_textArea, GCW_HCURSOR, (WORD)LoadCursor(NULL, idc)); + # endif + #endif + if (!p_mh) + { + POINT mp; + + /* Set the position to make it redrawn with the new shape. */ + (void)GetCursorPos((LPPOINT)&mp); + (void)SetCursorPos(mp.x, mp.y); + ShowCursor(TRUE); + } + } + } + #endif + + #ifdef FEAT_BROWSE + /* + * The file browser exists in two versions: with "W" uses wide characters, + * without "W" the current codepage. When FEAT_MBYTE is defined and on + * Windows NT/2000/XP the "W" functions are used. + */ + + # if defined(FEAT_MBYTE) && defined(WIN3264) + /* + * Wide version of convert_filter(). + */ + static WCHAR * + convert_filterW(char_u *s) + { + char_u *tmp; + int len; + WCHAR *res; + + tmp = convert_filter(s); + if (tmp == NULL) + return NULL; + len = (int)STRLEN(s) + 3; + res = enc_to_utf16(tmp, &len); + vim_free(tmp); + return res; + } + + /* + * Wide version of gui_mch_browse(). Keep in sync! + */ + static char_u * + gui_mch_browseW( + int saving, + char_u *title, + char_u *dflt, + char_u *ext, + char_u *initdir, + char_u *filter) + { + /* We always use the wide function. This means enc_to_utf16() must work, + * otherwise it fails miserably! */ + OPENFILENAMEW fileStruct; + WCHAR fileBuf[MAXPATHL]; + WCHAR *wp; + int i; + WCHAR *titlep = NULL; + WCHAR *extp = NULL; + WCHAR *initdirp = NULL; + WCHAR *filterp; + char_u *p; + + if (dflt == NULL) + fileBuf[0] = NUL; + else + { + wp = enc_to_utf16(dflt, NULL); + if (wp == NULL) + fileBuf[0] = NUL; + else + { + for (i = 0; wp[i] != NUL && i < MAXPATHL - 1; ++i) + fileBuf[i] = wp[i]; + fileBuf[i] = NUL; + vim_free(wp); + } + } + + /* Convert the filter to Windows format. */ + filterp = convert_filterW(filter); + + vim_memset(&fileStruct, 0, sizeof(OPENFILENAMEW)); + #ifdef OPENFILENAME_SIZE_VERSION_400 + /* be compatible with Windows NT 4.0 */ + /* TODO: what to use for OPENFILENAMEW??? */ + fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400; + #else + fileStruct.lStructSize = sizeof(fileStruct); + #endif + + if (title != NULL) + titlep = enc_to_utf16(title, NULL); + fileStruct.lpstrTitle = titlep; + + if (ext != NULL) + extp = enc_to_utf16(ext, NULL); + fileStruct.lpstrDefExt = extp; + + fileStruct.lpstrFile = fileBuf; + fileStruct.nMaxFile = MAXPATHL; + fileStruct.lpstrFilter = filterp; + fileStruct.hwndOwner = s_hwnd; /* main Vim window is owner*/ + /* has an initial dir been specified? */ + if (initdir != NULL && *initdir != NUL) + { + /* Must have backslashes here, no matter what 'shellslash' says */ + initdirp = enc_to_utf16(initdir, NULL); + if (initdirp != NULL) + { + for (wp = initdirp; *wp != NUL; ++wp) + if (*wp == '/') + *wp = '\\'; + } + fileStruct.lpstrInitialDir = initdirp; + } + + /* + * TODO: Allow selection of multiple files. Needs another arg to this + * function to ask for it, and need to use OFN_ALLOWMULTISELECT below. + * Also, should we use OFN_FILEMUSTEXIST when opening? Vim can edit on + * files that don't exist yet, so I haven't put it in. What about + * OFN_PATHMUSTEXIST? + * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog. + */ + fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY); + #ifdef FEAT_SHORTCUT + if (curbuf->b_p_bin) + fileStruct.Flags |= OFN_NODEREFERENCELINKS; + #endif + if (saving) + { + if (!GetSaveFileNameW(&fileStruct)) + return NULL; + } + else + { + if (!GetOpenFileNameW(&fileStruct)) + return NULL; + } + + vim_free(filterp); + vim_free(initdirp); + vim_free(titlep); + vim_free(extp); + + /* Convert from UCS2 to 'encoding'. */ + p = utf16_to_enc(fileBuf, NULL); + if (p != NULL) + /* when out of memory we get garbage for non-ASCII chars */ + STRCPY(fileBuf, p); + vim_free(p); + + /* Give focus back to main window (when using MDI). */ + SetFocus(s_hwnd); + + /* Shorten the file name if possible */ + return vim_strsave(shorten_fname1((char_u *)fileBuf)); + } + # endif /* FEAT_MBYTE */ + + + /* + * Convert the string s to the proper format for a filter string by replacing + * the \t and \n delimiters with \0. + * Returns the converted string in allocated memory. + * + * Keep in sync with convert_filterW() above! + */ + static char_u * + convert_filter(char_u *s) + { + char_u *res; + unsigned s_len = (unsigned)STRLEN(s); + unsigned i; + + res = alloc(s_len + 3); + if (res != NULL) + { + for (i = 0; i < s_len; ++i) + if (s[i] == '\t' || s[i] == '\n') + res[i] = '\0'; + else + res[i] = s[i]; + res[s_len] = NUL; + /* Add two extra NULs to make sure it's properly terminated. */ + res[s_len + 1] = NUL; + res[s_len + 2] = NUL; + } + return res; + } + + /* + * Select a directory. + */ + char_u * + gui_mch_browsedir(char_u *title, char_u *initdir) + { + /* We fake this: Use a filter that doesn't select anything and a default + * file name that won't be used. */ + return gui_mch_browse(0, title, (char_u *)_("Not Used"), NULL, + initdir, (char_u *)_("Directory\t*.nothing\n")); + } + + /* + * Pop open a file browser and return the file selected, in allocated memory, + * or NULL if Cancel is hit. + * saving - TRUE if the file will be saved to, FALSE if it will be opened. + * title - Title message for the file browser dialog. + * dflt - Default name of file. + * ext - Default extension to be added to files without extensions. + * initdir - directory in which to open the browser (NULL = current dir) + * filter - Filter for matched files to choose from. + * + * Keep in sync with gui_mch_browseW() above! + */ + char_u * + gui_mch_browse( + int saving, + char_u *title, + char_u *dflt, + char_u *ext, + char_u *initdir, + char_u *filter) + { + OPENFILENAME fileStruct; + char_u fileBuf[MAXPATHL]; + char_u *initdirp = NULL; + char_u *filterp; + char_u *p; + + # if defined(FEAT_MBYTE) && defined(WIN3264) + if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT) + return gui_mch_browseW(saving, title, dflt, ext, initdir, filter); + # endif + + if (dflt == NULL) + fileBuf[0] = NUL; + else + vim_strncpy(fileBuf, dflt, MAXPATHL - 1); + + /* Convert the filter to Windows format. */ + filterp = convert_filter(filter); + + vim_memset(&fileStruct, 0, sizeof(OPENFILENAME)); + #ifdef OPENFILENAME_SIZE_VERSION_400 + /* be compatible with Windows NT 4.0 */ + fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400; + #else + fileStruct.lStructSize = sizeof(fileStruct); + #endif + + fileStruct.lpstrTitle = (LPSTR)title; + fileStruct.lpstrDefExt = (LPSTR)ext; + + fileStruct.lpstrFile = (LPSTR)fileBuf; + fileStruct.nMaxFile = MAXPATHL; + fileStruct.lpstrFilter = (LPSTR)filterp; + fileStruct.hwndOwner = s_hwnd; /* main Vim window is owner*/ + /* has an initial dir been specified? */ + if (initdir != NULL && *initdir != NUL) + { + /* Must have backslashes here, no matter what 'shellslash' says */ + initdirp = vim_strsave(initdir); + if (initdirp != NULL) + for (p = initdirp; *p != NUL; ++p) + if (*p == '/') + *p = '\\'; + fileStruct.lpstrInitialDir = (LPSTR)initdirp; + } + + /* + * TODO: Allow selection of multiple files. Needs another arg to this + * function to ask for it, and need to use OFN_ALLOWMULTISELECT below. + * Also, should we use OFN_FILEMUSTEXIST when opening? Vim can edit on + * files that don't exist yet, so I haven't put it in. What about + * OFN_PATHMUSTEXIST? + * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog. + */ + fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY); + #ifdef FEAT_SHORTCUT + if (curbuf->b_p_bin) + fileStruct.Flags |= OFN_NODEREFERENCELINKS; + #endif + if (saving) + { + if (!GetSaveFileName(&fileStruct)) + return NULL; + } + else + { + if (!GetOpenFileName(&fileStruct)) + return NULL; + } + + vim_free(filterp); + vim_free(initdirp); + + /* Give focus back to main window (when using MDI). */ + SetFocus(s_hwnd); + + /* Shorten the file name if possible */ + return vim_strsave(shorten_fname1((char_u *)fileBuf)); + } + #endif /* FEAT_BROWSE */ + + /*ARGSUSED*/ + static void + _OnDropFiles( + HWND hwnd, + HDROP hDrop) + { + #ifdef FEAT_WINDOWS + #ifdef WIN3264 + # define BUFPATHLEN _MAX_PATH + # define DRAGQVAL 0xFFFFFFFF + #else + # define BUFPATHLEN MAXPATHL + # define DRAGQVAL 0xFFFF + #endif + #ifdef FEAT_MBYTE + WCHAR wszFile[BUFPATHLEN]; + #endif + char szFile[BUFPATHLEN]; + UINT cFiles = DragQueryFile(hDrop, DRAGQVAL, NULL, 0); + UINT i; + char_u **fnames; + POINT pt; + int_u modifiers = 0; + + /* TRACE("_OnDropFiles: %d files dropped\n", cFiles); */ + + /* Obtain dropped position */ + DragQueryPoint(hDrop, &pt); + MapWindowPoints(s_hwnd, s_textArea, &pt, 1); + + reset_VIsual(); + + fnames = (char_u **)alloc(cFiles * sizeof(char_u *)); + + if (fnames != NULL) + for (i = 0; i < cFiles; ++i) + { + #ifdef FEAT_MBYTE + if (DragQueryFileW(hDrop, i, wszFile, BUFPATHLEN) > 0) + fnames[i] = utf16_to_enc(wszFile, NULL); + else + #endif + { + DragQueryFile(hDrop, i, szFile, BUFPATHLEN); + fnames[i] = vim_strsave((char_u *)szFile); + } + } + + DragFinish(hDrop); + + if (fnames != NULL) + { + if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) + modifiers |= MOUSE_SHIFT; + if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) + modifiers |= MOUSE_CTRL; + if ((GetKeyState(VK_MENU) & 0x8000) != 0) + modifiers |= MOUSE_ALT; + + gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles); + + s_need_activate = TRUE; + } + #endif + } + + /*ARGSUSED*/ + static int + _OnScroll( + HWND hwnd, + HWND hwndCtl, + UINT code, + int pos) + { + static UINT prev_code = 0; /* code of previous call */ + scrollbar_T *sb, *sb_info; + long val; + int dragging = FALSE; + int dont_scroll_save = dont_scroll; + #ifndef WIN3264 + int nPos; + #else + SCROLLINFO si; + + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + #endif + + sb = gui_mswin_find_scrollbar(hwndCtl); + if (sb == NULL) + return 0; + + if (sb->wp != NULL) /* Left or right scrollbar */ + { + /* + * Careful: need to get scrollbar info out of first (left) scrollbar + * for window, but keep real scrollbar too because we must pass it to + * gui_drag_scrollbar(). + */ + sb_info = &sb->wp->w_scrollbars[0]; + } + else /* Bottom scrollbar */ + sb_info = sb; + val = sb_info->value; + + switch (code) + { + case SB_THUMBTRACK: + val = pos; + dragging = TRUE; + if (sb->scroll_shift > 0) + val <<= sb->scroll_shift; + break; + case SB_LINEDOWN: + val++; + break; + case SB_LINEUP: + val--; + break; + case SB_PAGEDOWN: + val += (sb_info->size > 2 ? sb_info->size - 2 : 1); + break; + case SB_PAGEUP: + val -= (sb_info->size > 2 ? sb_info->size - 2 : 1); + break; + case SB_TOP: + val = 0; + break; + case SB_BOTTOM: + val = sb_info->max; + break; + case SB_ENDSCROLL: + if (prev_code == SB_THUMBTRACK) + { + /* + * "pos" only gives us 16-bit data. In case of large file, + * use GetScrollPos() which returns 32-bit. Unfortunately it + * is not valid while the scrollbar is being dragged. + */ + val = GetScrollPos(hwndCtl, SB_CTL); + if (sb->scroll_shift > 0) + val <<= sb->scroll_shift; + } + break; + + default: + /* TRACE("Unknown scrollbar event %d\n", code); */ + return 0; + } + prev_code = code; + + #ifdef WIN3264 + si.nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val; + SetScrollInfo(hwndCtl, SB_CTL, &si, TRUE); + #else + nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val; + SetScrollPos(hwndCtl, SB_CTL, nPos, TRUE); + #endif + + /* + * When moving a vertical scrollbar, move the other vertical scrollbar too. + */ + if (sb->wp != NULL) + { + scrollbar_T *sba = sb->wp->w_scrollbars; + HWND id = sba[ (sb == sba + SBAR_LEFT) ? SBAR_RIGHT : SBAR_LEFT].id; + + #ifdef WIN3264 + SetScrollInfo(id, SB_CTL, &si, TRUE); + #else + SetScrollPos(id, SB_CTL, nPos, TRUE); + #endif + } + + /* Don't let us be interrupted here by another message. */ + s_busy_processing = TRUE; + + /* When "allow_scrollbar" is FALSE still need to remember the new + * position, but don't actually scroll by setting "dont_scroll". */ + dont_scroll = !allow_scrollbar; + + gui_drag_scrollbar(sb, val, dragging); + + s_busy_processing = FALSE; + dont_scroll = dont_scroll_save; + + return 0; + } + + /* ! * Get command line arguments. ! * Use "prog" as the name of the program and "cmdline" as the arguments. ! * Copy the arguments to allocated memory. ! * Return the number of arguments (including program name). ! * Return pointers to the arguments in "argvp". Memory is allocated with ! * malloc(), use free() instead of vim_free(). ! * Return pointer to buffer in "tofree". ! * Returns zero when out of memory. */ ! /*ARGSUSED*/ ! int ! get_cmd_args(char *prog, char *cmdline, char ***argvp, char **tofree) ! { ! int i; ! char *p; ! char *progp; ! char *pnew = NULL; ! char *newcmdline; ! int inquote; ! int argc; ! char **argv = NULL; ! int round; ! ! *tofree = NULL; ! ! #ifdef FEAT_MBYTE ! /* Try using the Unicode version first, it takes care of conversion when ! * 'encoding' is changed. */ ! argc = get_cmd_argsW(&argv); ! if (argc != 0) ! goto done; ! #endif ! ! /* Handle the program name. Remove the ".exe" extension, and find the 1st ! * non-space. */ ! p = strrchr(prog, '.'); ! if (p != NULL) ! *p = NUL; ! for (progp = prog; *progp == ' '; ++progp) ! ; ! ! /* The command line is copied to allocated memory, so that we can change ! * it. Add the size of the string, the separating NUL and a terminating ! * NUL. */ ! newcmdline = malloc(STRLEN(cmdline) + STRLEN(progp) + 2); ! if (newcmdline == NULL) ! return 0; ! ! /* ! * First round: count the number of arguments ("pnew" == NULL). ! * Second round: produce the arguments. ! */ ! for (round = 1; round <= 2; ++round) ! { ! /* First argument is the program name. */ ! if (pnew != NULL) ! { ! argv[0] = pnew; ! strcpy(pnew, progp); ! pnew += strlen(pnew); ! *pnew++ = NUL; ! } ! ! /* ! * Isolate each argument and put it in argv[]. ! */ ! p = cmdline; ! argc = 1; ! while (*p != NUL) ! { ! inquote = FALSE; ! if (pnew != NULL) ! argv[argc] = pnew; ! ++argc; ! while (*p != NUL && (inquote || (*p != ' ' && *p != '\t'))) ! { ! /* Backslashes are only special when followed by a double ! * quote. */ ! i = (int)strspn(p, "\\"); ! if (p[i] == '"') ! { ! /* Halve the number of backslashes. */ ! if (i > 1 && pnew != NULL) ! { ! vim_memset(pnew, '\\', i / 2); ! pnew += i / 2; ! } ! ! /* Even nr of backslashes toggles quoting, uneven copies ! * the double quote. */ ! if ((i & 1) == 0) ! inquote = !inquote; ! else if (pnew != NULL) ! *pnew++ = '"'; ! p += i + 1; ! } ! else if (i > 0) ! { ! /* Copy span of backslashes unmodified. */ ! if (pnew != NULL) ! { ! vim_memset(pnew, '\\', i); ! pnew += i; ! } ! p += i; ! } ! else ! { ! if (pnew != NULL) ! *pnew++ = *p; ! #ifdef FEAT_MBYTE ! /* Can't use mb_* functions, because 'encoding' is not ! * initialized yet here. */ ! if (IsDBCSLeadByte(*p)) ! { ! ++p; ! if (pnew != NULL) ! *pnew++ = *p; ! } ! #endif ! ++p; ! } ! } ! ! if (pnew != NULL) ! *pnew++ = NUL; ! while (*p == ' ' || *p == '\t') ! ++p; /* advance until a non-space */ ! } ! ! if (round == 1) ! { ! argv = (char **)malloc((argc + 1) * sizeof(char *)); ! if (argv == NULL ) ! { ! free(newcmdline); ! return 0; /* malloc error */ ! } ! pnew = newcmdline; ! *tofree = newcmdline; ! } ! } ! ! #ifdef FEAT_MBYTE ! done: ! #endif ! argv[argc] = NULL; /* NULL-terminated list */ ! *argvp = argv; ! return argc; ! } #ifdef FEAT_XPM_W32 # include "xpm_w32.h" *************** *** 1692,1701 **** #endif s_hdc = GetDC(s_textArea); - #ifdef MSWIN16_FASTTEXT - SetBkMode(s_hdc, OPAQUE); - #endif - #ifdef FEAT_WINDOWS DragAcceptFiles(s_hwnd, TRUE); #endif --- 5777,5782 ---- *************** *** 2410,2416 **** int font_is_ttf_or_vector = 0; #endif - #ifndef MSWIN16_FASTTEXT /* * Italic and bold text seems to have an extra row of pixels at the bottom * (below where the bottom of the character should be). If we draw the --- 6491,6496 ---- *************** *** 2484,2498 **** foptions = ETO_CLIPPED; } } - #else - /* - * The alternative would be to write the characters in opaque mode, but - * when the text is not exactly the same proportions as normal text, too - * big or too little a rectangle gets drawn for the background. - */ - SetBkMode(s_hdc, OPAQUE); - SetBkColor(s_hdc, gui.currBgColor); - #endif SetTextColor(s_hdc, gui.currFgColor); SelectFont(s_hdc, gui.currFont); --- 6564,6569 ---- *************** *** 2677,2686 **** /* When p_linespace is 0, overwrite the bottom row of pixels. * Otherwise put the line just below the character. */ 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); /* Note: LineTo() excludes the last pixel in the line. */ LineTo(s_hdc, FILL_X(col + len), y); --- 6748,6755 ---- *** ../vim-7.4.1363/src/gui_w48.c 2016-02-20 13:08:42.453801608 +0100 --- src/gui_w48.c 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,4155 **** - /* vi:set ts=8 sts=4 sw=4: - * - * VIM - Vi IMproved by Bram Moolenaar - * GUI support by Robert Webb - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - /* - * gui_w48.c: This file is included in gui_w16.c and gui_w32.c. - * - * GUI support for Microsoft Windows (Win16 + Win32 = Win48 :-) - * - * The combined efforts of: - * George V. Reilly - * Robert Webb - * Vince Negri - * ...and contributions from many others - * - */ - - #include "vim.h" - #include "version.h" /* used by dialog box routine for default title */ - #ifdef DEBUG - # include - #endif - - /* cproto fails on missing include files */ - #ifndef PROTO - - #ifndef __MINGW32__ - # include - #endif - #if defined(FEAT_TOOLBAR) || defined(FEAT_BEVAL) || defined(FEAT_GUI_TABLINE) - # include - #endif - #ifdef WIN16 - # include - # include - # ifdef WIN16_3DLOOK - # include - # endif - #endif - #include - - #ifdef GLOBAL_IME - # include "glbl_ime.h" - #endif - - #endif /* PROTO */ - - #ifdef FEAT_MENU - # define MENUHINTS /* show menu hints in command line */ - #endif - - /* Some parameters for dialog boxes. All in pixels. */ - #define DLG_PADDING_X 10 - #define DLG_PADDING_Y 10 - #define DLG_OLD_STYLE_PADDING_X 5 - #define DLG_OLD_STYLE_PADDING_Y 5 - #define DLG_VERT_PADDING_X 4 /* For vertical buttons */ - #define DLG_VERT_PADDING_Y 4 - #define DLG_ICON_WIDTH 34 - #define DLG_ICON_HEIGHT 34 - #define DLG_MIN_WIDTH 150 - #define DLG_FONT_NAME "MS Sans Serif" - #define DLG_FONT_POINT_SIZE 8 - #define DLG_MIN_MAX_WIDTH 400 - #define DLG_MIN_MAX_HEIGHT 400 - - #define DLG_NONBUTTON_CONTROL 5000 /* First ID of non-button controls */ - - #ifndef WM_XBUTTONDOWN /* For Win2K / winME ONLY */ - # define WM_XBUTTONDOWN 0x020B - # define WM_XBUTTONUP 0x020C - # define WM_XBUTTONDBLCLK 0x020D - # define MK_XBUTTON1 0x0020 - # define MK_XBUTTON2 0x0040 - #endif - - #ifdef PROTO - /* - * Define a few things for generating prototypes. This is just to avoid - * syntax errors, the defines do not need to be correct. - */ - # define APIENTRY - # define CALLBACK - # define CONST - # define FAR - # define NEAR - # define _cdecl - typedef int BOOL; - typedef int BYTE; - typedef int DWORD; - typedef int WCHAR; - typedef int ENUMLOGFONT; - typedef int FINDREPLACE; - typedef int HANDLE; - typedef int HBITMAP; - typedef int HBRUSH; - typedef int HDROP; - typedef int INT; - typedef int LOGFONT[]; - typedef int LPARAM; - typedef int LPCREATESTRUCT; - typedef int LPCSTR; - typedef int LPCTSTR; - typedef int LPRECT; - typedef int LPSTR; - typedef int LPWINDOWPOS; - typedef int LPWORD; - typedef int LRESULT; - typedef int HRESULT; - # undef MSG - typedef int MSG; - typedef int NEWTEXTMETRIC; - typedef int OSVERSIONINFO; - typedef int PWORD; - typedef int RECT; - typedef int UINT; - typedef int WORD; - typedef int WPARAM; - typedef int POINT; - typedef void *HINSTANCE; - typedef void *HMENU; - typedef void *HWND; - typedef void *HDC; - typedef void VOID; - typedef int LPNMHDR; - typedef int LONG; - typedef int WNDPROC; - #endif - - #ifndef GET_X_LPARAM - # define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) - #endif - - static void _OnPaint( HWND hwnd); - static void clear_rect(RECT *rcp); - - static WORD s_dlgfntheight; /* height of the dialog font */ - static WORD s_dlgfntwidth; /* width of the dialog font */ - - #ifdef FEAT_MENU - static HMENU s_menuBar = NULL; - #endif - #ifdef FEAT_TEAROFF - static void rebuild_tearoff(vimmenu_T *menu); - static HBITMAP s_htearbitmap; /* bitmap used to indicate tearoff */ - #endif - - /* Flag that is set while processing a message that must not be interrupted by - * processing another message. */ - static int s_busy_processing = FALSE; - - static int destroying = FALSE; /* call DestroyWindow() ourselves */ - - #ifdef MSWIN_FIND_REPLACE - static UINT s_findrep_msg = 0; /* set in gui_w[16/32].c */ - static FINDREPLACE s_findrep_struct; - # if defined(FEAT_MBYTE) && defined(WIN3264) - static FINDREPLACEW s_findrep_struct_w; - # endif - static HWND s_findrep_hwnd = NULL; - static int s_findrep_is_find; /* TRUE for find dialog, FALSE - for find/replace dialog */ - #endif - - static HINSTANCE s_hinst = NULL; - #if !defined(FEAT_SNIFF) && !defined(FEAT_GUI) - static - #endif - HWND s_hwnd = NULL; - static HDC s_hdc = NULL; - static HBRUSH s_brush = NULL; - - #ifdef FEAT_TOOLBAR - static HWND s_toolbarhwnd = NULL; - static WNDPROC s_toolbar_wndproc = NULL; - #endif - - #ifdef FEAT_GUI_TABLINE - static HWND s_tabhwnd = NULL; - static WNDPROC s_tabline_wndproc = NULL; - static int showing_tabline = 0; - #endif - - static WPARAM s_wParam = 0; - static LPARAM s_lParam = 0; - - static HWND s_textArea = NULL; - static UINT s_uMsg = 0; - - static char_u *s_textfield; /* Used by dialogs to pass back strings */ - - static int s_need_activate = FALSE; - - /* This variable is set when waiting for an event, which is the only moment - * scrollbar dragging can be done directly. It's not allowed while commands - * are executed, because it may move the cursor and that may cause unexpected - * problems (e.g., while ":s" is working). - */ - static int allow_scrollbar = FALSE; - - #ifdef GLOBAL_IME - # define MyTranslateMessage(x) global_ime_TranslateMessage(x) - #else - # define MyTranslateMessage(x) TranslateMessage(x) - #endif - - #if (defined(WIN3264) && defined(FEAT_MBYTE)) || defined(GLOBAL_IME) - /* use of WindowProc depends on wide_WindowProc */ - # define MyWindowProc vim_WindowProc - #else - /* use ordinary WindowProc */ - # define MyWindowProc DefWindowProc - #endif - - extern int current_font_height; /* this is in os_mswin.c */ - - static struct - { - UINT key_sym; - char_u vim_code0; - char_u vim_code1; - } special_keys[] = - { - {VK_UP, 'k', 'u'}, - {VK_DOWN, 'k', 'd'}, - {VK_LEFT, 'k', 'l'}, - {VK_RIGHT, 'k', 'r'}, - - {VK_F1, 'k', '1'}, - {VK_F2, 'k', '2'}, - {VK_F3, 'k', '3'}, - {VK_F4, 'k', '4'}, - {VK_F5, 'k', '5'}, - {VK_F6, 'k', '6'}, - {VK_F7, 'k', '7'}, - {VK_F8, 'k', '8'}, - {VK_F9, 'k', '9'}, - {VK_F10, 'k', ';'}, - - {VK_F11, 'F', '1'}, - {VK_F12, 'F', '2'}, - {VK_F13, 'F', '3'}, - {VK_F14, 'F', '4'}, - {VK_F15, 'F', '5'}, - {VK_F16, 'F', '6'}, - {VK_F17, 'F', '7'}, - {VK_F18, 'F', '8'}, - {VK_F19, 'F', '9'}, - {VK_F20, 'F', 'A'}, - - {VK_F21, 'F', 'B'}, - #ifdef FEAT_NETBEANS_INTG - {VK_PAUSE, 'F', 'B'}, /* Pause == F21 (see gui_gtk_x11.c) */ - #endif - {VK_F22, 'F', 'C'}, - {VK_F23, 'F', 'D'}, - {VK_F24, 'F', 'E'}, /* winuser.h defines up to F24 */ - - {VK_HELP, '%', '1'}, - {VK_BACK, 'k', 'b'}, - {VK_INSERT, 'k', 'I'}, - {VK_DELETE, 'k', 'D'}, - {VK_HOME, 'k', 'h'}, - {VK_END, '@', '7'}, - {VK_PRIOR, 'k', 'P'}, - {VK_NEXT, 'k', 'N'}, - {VK_PRINT, '%', '9'}, - {VK_ADD, 'K', '6'}, - {VK_SUBTRACT, 'K', '7'}, - {VK_DIVIDE, 'K', '8'}, - {VK_MULTIPLY, 'K', '9'}, - {VK_SEPARATOR, 'K', 'A'}, /* Keypad Enter */ - {VK_DECIMAL, 'K', 'B'}, - - {VK_NUMPAD0, 'K', 'C'}, - {VK_NUMPAD1, 'K', 'D'}, - {VK_NUMPAD2, 'K', 'E'}, - {VK_NUMPAD3, 'K', 'F'}, - {VK_NUMPAD4, 'K', 'G'}, - {VK_NUMPAD5, 'K', 'H'}, - {VK_NUMPAD6, 'K', 'I'}, - {VK_NUMPAD7, 'K', 'J'}, - {VK_NUMPAD8, 'K', 'K'}, - {VK_NUMPAD9, 'K', 'L'}, - - /* Keys that we want to be able to use any modifier with: */ - {VK_SPACE, ' ', NUL}, - {VK_TAB, TAB, NUL}, - {VK_ESCAPE, ESC, NUL}, - {NL, NL, NUL}, - {CAR, CAR, NUL}, - - /* End of list marker: */ - {0, 0, 0} - }; - - /* Local variables */ - static int s_button_pending = -1; - - /* s_getting_focus is set when we got focus but didn't see mouse-up event yet, - * so don't reset s_button_pending. */ - static int s_getting_focus = FALSE; - - static int s_x_pending; - static int s_y_pending; - static UINT s_kFlags_pending; - static UINT s_wait_timer = 0; /* Timer for get char from user */ - static int s_timed_out = FALSE; - static int dead_key = 0; /* 0: no dead key, 1: dead key pressed */ - - #ifdef WIN3264 - static OSVERSIONINFO os_version; /* like it says. Init in gui_mch_init() */ - #endif - - #ifdef FEAT_BEVAL - /* balloon-eval WM_NOTIFY_HANDLER */ - static void Handle_WM_Notify(HWND hwnd, LPNMHDR pnmh); - static void TrackUserActivity(UINT uMsg); - #endif - - /* - * For control IME. - * - * These LOGFONT used for IME. - */ - #ifdef FEAT_MBYTE - # ifdef USE_IM_CONTROL - /* holds LOGFONT for 'guifontwide' if available, otherwise 'guifont' */ - static LOGFONT norm_logfont; - /* holds LOGFONT for 'guifont' always. */ - static LOGFONT sub_logfont; - # endif - #endif - - #ifdef FEAT_MBYTE_IME - static LRESULT _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData); - #endif - - #if defined(FEAT_BROWSE) - static char_u *convert_filter(char_u *s); - #endif - - #ifdef DEBUG_PRINT_ERROR - /* - * Print out the last Windows error message - */ - static void - print_windows_error(void) - { - LPVOID lpMsgBuf; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, 0, NULL); - TRACE1("Error: %s\n", lpMsgBuf); - LocalFree(lpMsgBuf); - } - #endif - - /* - * Cursor blink functions. - * - * This is a simple state machine: - * BLINK_NONE not blinking at all - * BLINK_OFF blinking, cursor is not shown - * BLINK_ON blinking, cursor is shown - */ - - #define BLINK_NONE 0 - #define BLINK_OFF 1 - #define BLINK_ON 2 - - static int blink_state = BLINK_NONE; - static long_u blink_waittime = 700; - static long_u blink_ontime = 400; - static long_u blink_offtime = 250; - static UINT blink_timer = 0; - - void - gui_mch_set_blinking(long wait, long on, long off) - { - blink_waittime = wait; - blink_ontime = on; - blink_offtime = off; - } - - /* ARGSUSED */ - static VOID CALLBACK - _OnBlinkTimer( - HWND hwnd, - UINT uMsg, - UINT idEvent, - DWORD dwTime) - { - MSG msg; - - /* - TRACE2("Got timer event, id %d, blink_timer %d\n", idEvent, blink_timer); - */ - - KillTimer(NULL, idEvent); - - /* Eat spurious WM_TIMER messages */ - while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) - ; - - if (blink_state == BLINK_ON) - { - gui_undraw_cursor(); - blink_state = BLINK_OFF; - blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_offtime, - (TIMERPROC)_OnBlinkTimer); - } - else - { - gui_update_cursor(TRUE, FALSE); - blink_state = BLINK_ON; - blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime, - (TIMERPROC)_OnBlinkTimer); - } - } - - static void - gui_mswin_rm_blink_timer(void) - { - MSG msg; - - if (blink_timer != 0) - { - KillTimer(NULL, blink_timer); - /* Eat spurious WM_TIMER messages */ - while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) - ; - blink_timer = 0; - } - } - - /* - * Stop the cursor blinking. Show the cursor if it wasn't shown. - */ - void - gui_mch_stop_blink(void) - { - gui_mswin_rm_blink_timer(); - if (blink_state == BLINK_OFF) - gui_update_cursor(TRUE, FALSE); - blink_state = BLINK_NONE; - } - - /* - * Start the cursor blinking. If it was already blinking, this restarts the - * waiting time and shows the cursor. - */ - void - gui_mch_start_blink(void) - { - gui_mswin_rm_blink_timer(); - - /* Only switch blinking on if none of the times is zero */ - if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus) - { - blink_timer = (UINT)SetTimer(NULL, 0, (UINT)blink_waittime, - (TIMERPROC)_OnBlinkTimer); - blink_state = BLINK_ON; - gui_update_cursor(TRUE, FALSE); - } - } - - /* - * Call-back routines. - */ - - /*ARGSUSED*/ - static VOID CALLBACK - _OnTimer( - HWND hwnd, - UINT uMsg, - UINT idEvent, - DWORD dwTime) - { - MSG msg; - - /* - TRACE2("Got timer event, id %d, s_wait_timer %d\n", idEvent, s_wait_timer); - */ - KillTimer(NULL, idEvent); - s_timed_out = TRUE; - - /* Eat spurious WM_TIMER messages */ - while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) - ; - if (idEvent == s_wait_timer) - s_wait_timer = 0; - } - - /*ARGSUSED*/ - static void - _OnDeadChar( - HWND hwnd, - UINT ch, - int cRepeat) - { - dead_key = 1; - } - - /* - * Convert Unicode character "ch" to bytes in "string[slen]". - * When "had_alt" is TRUE the ALT key was included in "ch". - * Return the length. - */ - static int - char_to_string(int ch, char_u *string, int slen, int had_alt) - { - int len; - int i; - #ifdef FEAT_MBYTE - WCHAR wstring[2]; - char_u *ws = NULL;; - - if (os_version.dwPlatformId != VER_PLATFORM_WIN32_NT) - { - /* On Windows 95/98 we apparently get the character in the active - * codepage, not in UCS-2. If conversion is needed convert it to - * UCS-2 first. */ - if ((int)GetACP() == enc_codepage) - len = 0; /* no conversion required */ - else - { - string[0] = ch; - len = MultiByteToWideChar(GetACP(), 0, (LPCSTR)string, - 1, wstring, 2); - } - } - else - { - wstring[0] = ch; - len = 1; - } - - if (len > 0) - { - /* "ch" is a UTF-16 character. Convert it to a string of bytes. When - * "enc_codepage" is non-zero use the standard Win32 function, - * otherwise use our own conversion function (e.g., for UTF-8). */ - if (enc_codepage > 0) - { - len = WideCharToMultiByte(enc_codepage, 0, wstring, len, - (LPSTR)string, slen, 0, NULL); - /* If we had included the ALT key into the character but now the - * upper bit is no longer set, that probably means the conversion - * failed. Convert the original character and set the upper bit - * afterwards. */ - if (had_alt && len == 1 && ch >= 0x80 && string[0] < 0x80) - { - wstring[0] = ch & 0x7f; - len = WideCharToMultiByte(enc_codepage, 0, wstring, len, - (LPSTR)string, slen, 0, NULL); - if (len == 1) /* safety check */ - string[0] |= 0x80; - } - } - else - { - len = 1; - ws = utf16_to_enc(wstring, &len); - if (ws == NULL) - len = 0; - else - { - if (len > slen) /* just in case */ - len = slen; - mch_memmove(string, ws, len); - vim_free(ws); - } - } - } - - if (len == 0) - #endif - { - string[0] = ch; - len = 1; - } - - for (i = 0; i < len; ++i) - if (string[i] == CSI && len <= slen - 2) - { - /* Insert CSI as K_CSI. */ - mch_memmove(string + i + 3, string + i + 1, len - i - 1); - string[++i] = KS_EXTRA; - string[++i] = (int)KE_CSI; - len += 2; - } - - return len; - } - - /* - * Key hit, add it to the input buffer. - */ - /*ARGSUSED*/ - static void - _OnChar( - HWND hwnd, - UINT ch, - int cRepeat) - { - char_u string[40]; - int len = 0; - - dead_key = 0; - - len = char_to_string(ch, string, 40, FALSE); - if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts) - { - trash_input_buf(); - got_int = TRUE; - } - - add_to_input_buf(string, len); - } - - /* - * Alt-Key hit, add it to the input buffer. - */ - /*ARGSUSED*/ - static void - _OnSysChar( - HWND hwnd, - UINT cch, - int cRepeat) - { - char_u string[40]; /* Enough for multibyte character */ - int len; - int modifiers; - int ch = cch; /* special keys are negative */ - - dead_key = 0; - - /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */ - - /* OK, we have a character key (given by ch) which was entered with the - * ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note - * that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless - * CAPSLOCK is pressed) at this point. - */ - modifiers = MOD_MASK_ALT; - if (GetKeyState(VK_SHIFT) & 0x8000) - modifiers |= MOD_MASK_SHIFT; - if (GetKeyState(VK_CONTROL) & 0x8000) - modifiers |= MOD_MASK_CTRL; - - ch = simplify_key(ch, &modifiers); - /* remove the SHIFT modifier for keys where it's already included, e.g., - * '(' and '*' */ - if (ch < 0x100 && !isalpha(ch) && isprint(ch)) - modifiers &= ~MOD_MASK_SHIFT; - - /* Interpret the ALT key as making the key META, include SHIFT, etc. */ - ch = extract_modifiers(ch, &modifiers); - if (ch == CSI) - ch = K_CSI; - - len = 0; - if (modifiers) - { - string[len++] = CSI; - string[len++] = KS_MODIFIER; - string[len++] = modifiers; - } - - if (IS_SPECIAL((int)ch)) - { - string[len++] = CSI; - string[len++] = K_SECOND((int)ch); - string[len++] = K_THIRD((int)ch); - } - else - { - /* Although the documentation isn't clear about it, we assume "ch" is - * a Unicode character. */ - len += char_to_string(ch, string + len, 40 - len, TRUE); - } - - add_to_input_buf(string, len); - } - - static void - _OnMouseEvent( - int button, - int x, - int y, - int repeated_click, - UINT keyFlags) - { - int vim_modifiers = 0x0; - - s_getting_focus = FALSE; - - if (keyFlags & MK_SHIFT) - vim_modifiers |= MOUSE_SHIFT; - if (keyFlags & MK_CONTROL) - vim_modifiers |= MOUSE_CTRL; - if (GetKeyState(VK_MENU) & 0x8000) - vim_modifiers |= MOUSE_ALT; - - gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers); - } - - /*ARGSUSED*/ - static void - _OnMouseButtonDown( - HWND hwnd, - BOOL fDoubleClick, - int x, - int y, - UINT keyFlags) - { - static LONG s_prevTime = 0; - - LONG currentTime = GetMessageTime(); - int button = -1; - int repeated_click; - - /* Give main window the focus: this is so the cursor isn't hollow. */ - (void)SetFocus(s_hwnd); - - if (s_uMsg == WM_LBUTTONDOWN || s_uMsg == WM_LBUTTONDBLCLK) - button = MOUSE_LEFT; - else if (s_uMsg == WM_MBUTTONDOWN || s_uMsg == WM_MBUTTONDBLCLK) - button = MOUSE_MIDDLE; - else if (s_uMsg == WM_RBUTTONDOWN || s_uMsg == WM_RBUTTONDBLCLK) - button = MOUSE_RIGHT; - #ifndef WIN16 /**/ - else if (s_uMsg == WM_XBUTTONDOWN || s_uMsg == WM_XBUTTONDBLCLK) - { - #ifndef GET_XBUTTON_WPARAM - # define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam)) - #endif - button = ((GET_XBUTTON_WPARAM(s_wParam) == 1) ? MOUSE_X1 : MOUSE_X2); - } - else if (s_uMsg == WM_CAPTURECHANGED) - { - /* on W95/NT4, somehow you get in here with an odd Msg - * if you press one button while holding down the other..*/ - if (s_button_pending == MOUSE_LEFT) - button = MOUSE_RIGHT; - else - button = MOUSE_LEFT; - } - #endif - if (button >= 0) - { - repeated_click = ((int)(currentTime - s_prevTime) < p_mouset); - - /* - * Holding down the left and right buttons simulates pushing the middle - * button. - */ - if (repeated_click - && ((button == MOUSE_LEFT && s_button_pending == MOUSE_RIGHT) - || (button == MOUSE_RIGHT - && s_button_pending == MOUSE_LEFT))) - { - /* - * Hmm, gui.c will ignore more than one button down at a time, so - * pretend we let go of it first. - */ - gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, 0x0); - button = MOUSE_MIDDLE; - repeated_click = FALSE; - s_button_pending = -1; - _OnMouseEvent(button, x, y, repeated_click, keyFlags); - } - else if ((repeated_click) - || (mouse_model_popup() && (button == MOUSE_RIGHT))) - { - if (s_button_pending > -1) - { - _OnMouseEvent(s_button_pending, x, y, FALSE, keyFlags); - s_button_pending = -1; - } - /* TRACE("Button down at x %d, y %d\n", x, y); */ - _OnMouseEvent(button, x, y, repeated_click, keyFlags); - } - else - { - /* - * If this is the first press (i.e. not a multiple click) don't - * action immediately, but store and wait for: - * i) button-up - * ii) mouse move - * iii) another button press - * before using it. - * This enables us to make left+right simulate middle button, - * without left or right being actioned first. The side-effect is - * that if you click and hold the mouse without dragging, the - * cursor doesn't move until you release the button. In practice - * this is hardly a problem. - */ - s_button_pending = button; - s_x_pending = x; - s_y_pending = y; - s_kFlags_pending = keyFlags; - } - - s_prevTime = currentTime; - } - } - - /*ARGSUSED*/ - static void - _OnMouseMoveOrRelease( - HWND hwnd, - int x, - int y, - UINT keyFlags) - { - int button; - - s_getting_focus = FALSE; - if (s_button_pending > -1) - { - /* Delayed action for mouse down event */ - _OnMouseEvent(s_button_pending, s_x_pending, - s_y_pending, FALSE, s_kFlags_pending); - s_button_pending = -1; - } - if (s_uMsg == WM_MOUSEMOVE) - { - /* - * It's only a MOUSE_DRAG if one or more mouse buttons are being held - * down. - */ - if (!(keyFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON - | MK_XBUTTON1 | MK_XBUTTON2))) - { - gui_mouse_moved(x, y); - return; - } - - /* - * While button is down, keep grabbing mouse move events when - * the mouse goes outside the window - */ - SetCapture(s_textArea); - button = MOUSE_DRAG; - /* TRACE(" move at x %d, y %d\n", x, y); */ - } - else - { - ReleaseCapture(); - button = MOUSE_RELEASE; - /* TRACE(" up at x %d, y %d\n", x, y); */ - } - - _OnMouseEvent(button, x, y, FALSE, keyFlags); - } - - #ifdef FEAT_MENU - /* - * Find the vimmenu_T with the given id - */ - static vimmenu_T * - gui_mswin_find_menu( - vimmenu_T *pMenu, - int id) - { - vimmenu_T *pChildMenu; - - while (pMenu) - { - if (pMenu->id == (UINT)id) - break; - if (pMenu->children != NULL) - { - pChildMenu = gui_mswin_find_menu(pMenu->children, id); - if (pChildMenu) - { - pMenu = pChildMenu; - break; - } - } - pMenu = pMenu->next; - } - return pMenu; - } - - /*ARGSUSED*/ - static void - _OnMenu( - HWND hwnd, - int id, - HWND hwndCtl, - UINT codeNotify) - { - vimmenu_T *pMenu; - - pMenu = gui_mswin_find_menu(root_menu, id); - if (pMenu) - gui_menu_cb(pMenu); - } - #endif - - #ifdef MSWIN_FIND_REPLACE - # if defined(FEAT_MBYTE) && defined(WIN3264) - /* - * copy useful data from structure LPFINDREPLACE to structure LPFINDREPLACEW - */ - static void - findrep_atow(LPFINDREPLACEW lpfrw, LPFINDREPLACE lpfr) - { - WCHAR *wp; - - lpfrw->hwndOwner = lpfr->hwndOwner; - lpfrw->Flags = lpfr->Flags; - - wp = enc_to_utf16((char_u *)lpfr->lpstrFindWhat, NULL); - wcsncpy(lpfrw->lpstrFindWhat, wp, lpfrw->wFindWhatLen - 1); - vim_free(wp); - - /* the field "lpstrReplaceWith" doesn't need to be copied */ - } - - /* - * copy useful data from structure LPFINDREPLACEW to structure LPFINDREPLACE - */ - static void - findrep_wtoa(LPFINDREPLACE lpfr, LPFINDREPLACEW lpfrw) - { - char_u *p; - - lpfr->Flags = lpfrw->Flags; - - p = utf16_to_enc((short_u*)lpfrw->lpstrFindWhat, NULL); - vim_strncpy((char_u *)lpfr->lpstrFindWhat, p, lpfr->wFindWhatLen - 1); - vim_free(p); - - p = utf16_to_enc((short_u*)lpfrw->lpstrReplaceWith, NULL); - vim_strncpy((char_u *)lpfr->lpstrReplaceWith, p, lpfr->wReplaceWithLen - 1); - vim_free(p); - } - # endif - - /* - * Handle a Find/Replace window message. - */ - static void - _OnFindRepl(void) - { - int flags = 0; - int down; - - # if defined(FEAT_MBYTE) && defined(WIN3264) - /* If the OS is Windows NT, and 'encoding' differs from active codepage: - * convert text from wide string. */ - if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT - && enc_codepage >= 0 && (int)GetACP() != enc_codepage) - { - findrep_wtoa(&s_findrep_struct, &s_findrep_struct_w); - } - # endif - - if (s_findrep_struct.Flags & FR_DIALOGTERM) - /* Give main window the focus back. */ - (void)SetFocus(s_hwnd); - - if (s_findrep_struct.Flags & FR_FINDNEXT) - { - flags = FRD_FINDNEXT; - - /* Give main window the focus back: this is so the cursor isn't - * hollow. */ - (void)SetFocus(s_hwnd); - } - else if (s_findrep_struct.Flags & FR_REPLACE) - { - flags = FRD_REPLACE; - - /* Give main window the focus back: this is so the cursor isn't - * hollow. */ - (void)SetFocus(s_hwnd); - } - else if (s_findrep_struct.Flags & FR_REPLACEALL) - { - flags = FRD_REPLACEALL; - } - - if (flags != 0) - { - /* Call the generic GUI function to do the actual work. */ - if (s_findrep_struct.Flags & FR_WHOLEWORD) - flags |= FRD_WHOLE_WORD; - if (s_findrep_struct.Flags & FR_MATCHCASE) - flags |= FRD_MATCH_CASE; - down = (s_findrep_struct.Flags & FR_DOWN) != 0; - gui_do_findrepl(flags, (char_u *)s_findrep_struct.lpstrFindWhat, - (char_u *)s_findrep_struct.lpstrReplaceWith, down); - } - } - #endif - - static void - HandleMouseHide(UINT uMsg, LPARAM lParam) - { - static LPARAM last_lParam = 0L; - - /* We sometimes get a mousemove when the mouse didn't move... */ - if (uMsg == WM_MOUSEMOVE || uMsg == WM_NCMOUSEMOVE) - { - if (lParam == last_lParam) - return; - last_lParam = lParam; - } - - /* Handle specially, to centralise coding. We need to be sure we catch all - * possible events which should cause us to restore the cursor (as it is a - * shared resource, we take full responsibility for it). - */ - switch (uMsg) - { - case WM_KEYUP: - case WM_CHAR: - /* - * blank out the pointer if necessary - */ - if (p_mh) - gui_mch_mousehide(TRUE); - break; - - case WM_SYSKEYUP: /* show the pointer when a system-key is pressed */ - case WM_SYSCHAR: - case WM_MOUSEMOVE: /* show the pointer on any mouse action */ - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_XBUTTONDOWN: - case WM_XBUTTONUP: - case WM_NCMOUSEMOVE: - case WM_NCLBUTTONDOWN: - case WM_NCLBUTTONUP: - case WM_NCMBUTTONDOWN: - case WM_NCMBUTTONUP: - case WM_NCRBUTTONDOWN: - case WM_NCRBUTTONUP: - case WM_KILLFOCUS: - /* - * if the pointer is currently hidden, then we should show it. - */ - gui_mch_mousehide(FALSE); - break; - } - } - - static LRESULT CALLBACK - _TextAreaWndProc( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) - { - /* - TRACE("TextAreaWndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n", - hwnd, uMsg, wParam, lParam); - */ - - HandleMouseHide(uMsg, lParam); - - s_uMsg = uMsg; - s_wParam = wParam; - s_lParam = lParam; - - #ifdef FEAT_BEVAL - TrackUserActivity(uMsg); - #endif - - switch (uMsg) - { - HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK,_OnMouseButtonDown); - HANDLE_MSG(hwnd, WM_LBUTTONDOWN,_OnMouseButtonDown); - HANDLE_MSG(hwnd, WM_LBUTTONUP, _OnMouseMoveOrRelease); - HANDLE_MSG(hwnd, WM_MBUTTONDBLCLK,_OnMouseButtonDown); - HANDLE_MSG(hwnd, WM_MBUTTONDOWN,_OnMouseButtonDown); - HANDLE_MSG(hwnd, WM_MBUTTONUP, _OnMouseMoveOrRelease); - HANDLE_MSG(hwnd, WM_MOUSEMOVE, _OnMouseMoveOrRelease); - HANDLE_MSG(hwnd, WM_PAINT, _OnPaint); - HANDLE_MSG(hwnd, WM_RBUTTONDBLCLK,_OnMouseButtonDown); - HANDLE_MSG(hwnd, WM_RBUTTONDOWN,_OnMouseButtonDown); - HANDLE_MSG(hwnd, WM_RBUTTONUP, _OnMouseMoveOrRelease); - #ifndef WIN16 /**/ - HANDLE_MSG(hwnd, WM_XBUTTONDBLCLK,_OnMouseButtonDown); - HANDLE_MSG(hwnd, WM_XBUTTONDOWN,_OnMouseButtonDown); - HANDLE_MSG(hwnd, WM_XBUTTONUP, _OnMouseMoveOrRelease); - #endif - - #ifdef FEAT_BEVAL - case WM_NOTIFY: Handle_WM_Notify(hwnd, (LPNMHDR)lParam); - return TRUE; - #endif - default: - return MyWindowProc(hwnd, uMsg, wParam, lParam); - } - } - - #if (defined(WIN3264) && defined(FEAT_MBYTE)) \ - || defined(GLOBAL_IME) \ - || defined(PROTO) - # ifdef PROTO - typedef int WINAPI; - # endif - - LRESULT WINAPI - vim_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) - { - # ifdef GLOBAL_IME - return global_ime_DefWindowProc(hwnd, message, wParam, lParam); - # else - if (wide_WindowProc) - return DefWindowProcW(hwnd, message, wParam, lParam); - return DefWindowProc(hwnd, message, wParam, lParam); - #endif - } - #endif - - /* - * Called when the foreground or background color has been changed. - */ - void - gui_mch_new_colors(void) - { - /* nothing to do? */ - } - - /* - * Set the colors to their default values. - */ - void - gui_mch_def_colors(void) - { - gui.norm_pixel = GetSysColor(COLOR_WINDOWTEXT); - gui.back_pixel = GetSysColor(COLOR_WINDOW); - gui.def_norm_pixel = gui.norm_pixel; - gui.def_back_pixel = gui.back_pixel; - } - - /* - * Open the GUI window which was created by a call to gui_mch_init(). - */ - int - gui_mch_open(void) - { - #ifndef SW_SHOWDEFAULT - # define SW_SHOWDEFAULT 10 /* Borland 5.0 doesn't have it */ - #endif - /* Actually open the window, if not already visible - * (may be done already in gui_mch_set_shellsize) */ - if (!IsWindowVisible(s_hwnd)) - ShowWindow(s_hwnd, SW_SHOWDEFAULT); - - #ifdef MSWIN_FIND_REPLACE - /* Init replace string here, so that we keep it when re-opening the - * dialog. */ - s_findrep_struct.lpstrReplaceWith[0] = NUL; - #endif - - return OK; - } - - /* - * Get the position of the top left corner of the window. - */ - int - gui_mch_get_winpos(int *x, int *y) - { - RECT rect; - - GetWindowRect(s_hwnd, &rect); - *x = rect.left; - *y = rect.top; - return OK; - } - - /* - * Set the position of the top left corner of the window to the given - * coordinates. - */ - void - gui_mch_set_winpos(int x, int y) - { - SetWindowPos(s_hwnd, NULL, x, y, 0, 0, - SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); - } - void - gui_mch_set_text_area_pos(int x, int y, int w, int h) - { - static int oldx = 0; - static int oldy = 0; - - SetWindowPos(s_textArea, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE); - - #ifdef FEAT_TOOLBAR - if (vim_strchr(p_go, GO_TOOLBAR) != NULL) - SendMessage(s_toolbarhwnd, WM_SIZE, - (WPARAM)0, (LPARAM)(w + ((long)(TOOLBAR_BUTTON_HEIGHT+8)<<16))); - #endif - #if defined(FEAT_GUI_TABLINE) - if (showing_tabline) - { - int top = 0; - RECT rect; - - # ifdef FEAT_TOOLBAR - if (vim_strchr(p_go, GO_TOOLBAR) != NULL) - top = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT; - # endif - GetClientRect(s_hwnd, &rect); - MoveWindow(s_tabhwnd, 0, top, rect.right, gui.tabline_height, TRUE); - } - #endif - - /* When side scroll bar is unshown, the size of window will change. - * then, the text area move left or right. thus client rect should be - * forcedly redrawn. (Yasuhiro Matsumoto) */ - if (oldx != x || oldy != y) - { - InvalidateRect(s_hwnd, NULL, FALSE); - oldx = x; - oldy = y; - } - } - - - /* - * Scrollbar stuff: - */ - - void - gui_mch_enable_scrollbar( - scrollbar_T *sb, - int flag) - { - ShowScrollBar(sb->id, SB_CTL, flag); - - /* TODO: When the window is maximized, the size of the window stays the - * same, thus the size of the text area changes. On Win98 it's OK, on Win - * NT 4.0 it's not... */ - } - - void - gui_mch_set_scrollbar_pos( - scrollbar_T *sb, - int x, - int y, - int w, - int h) - { - SetWindowPos(sb->id, NULL, x, y, w, h, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); - } - - void - gui_mch_create_scrollbar( - scrollbar_T *sb, - int orient) /* SBAR_VERT or SBAR_HORIZ */ - { - sb->id = CreateWindow( - "SCROLLBAR", "Scrollbar", - WS_CHILD | ((orient == SBAR_VERT) ? SBS_VERT : SBS_HORZ), 0, 0, - 10, /* Any value will do for now */ - 10, /* Any value will do for now */ - s_hwnd, NULL, - s_hinst, NULL); - } - - /* - * Find the scrollbar with the given hwnd. - */ - static scrollbar_T * - gui_mswin_find_scrollbar(HWND hwnd) - { - win_T *wp; - - if (gui.bottom_sbar.id == hwnd) - return &gui.bottom_sbar; - FOR_ALL_WINDOWS(wp) - { - if (wp->w_scrollbars[SBAR_LEFT].id == hwnd) - return &wp->w_scrollbars[SBAR_LEFT]; - if (wp->w_scrollbars[SBAR_RIGHT].id == hwnd) - return &wp->w_scrollbars[SBAR_RIGHT]; - } - return NULL; - } - - /* - * Get the character size of a font. - */ - static void - GetFontSize(GuiFont font) - { - HWND hwnd = GetDesktopWindow(); - HDC hdc = GetWindowDC(hwnd); - HFONT hfntOld = SelectFont(hdc, (HFONT)font); - TEXTMETRIC tm; - - GetTextMetrics(hdc, &tm); - gui.char_width = tm.tmAveCharWidth + tm.tmOverhang; - - gui.char_height = tm.tmHeight - #ifndef MSWIN16_FASTTEXT - + p_linespace - #endif - ; - - SelectFont(hdc, hfntOld); - - ReleaseDC(hwnd, hdc); - } - - /* - * Adjust gui.char_height (after 'linespace' was changed). - */ - int - gui_mch_adjust_charheight(void) - { - GetFontSize(gui.norm_font); - return OK; - } - - static GuiFont - get_font_handle(LOGFONT *lf) - { - HFONT font = NULL; - - /* Load the font */ - font = CreateFontIndirect(lf); - - if (font == NULL) - return NOFONT; - - return (GuiFont)font; - } - - static int - pixels_to_points(int pixels, int vertical) - { - int points; - HWND hwnd; - HDC hdc; - - hwnd = GetDesktopWindow(); - hdc = GetWindowDC(hwnd); - - points = MulDiv(pixels, 72, - GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX)); - - ReleaseDC(hwnd, hdc); - - return points; - } - - GuiFont - gui_mch_get_font( - char_u *name, - int giveErrorIfMissing) - { - LOGFONT lf; - GuiFont font = NOFONT; - - if (get_logfont(&lf, name, NULL, giveErrorIfMissing) == OK) - font = get_font_handle(&lf); - if (font == NOFONT && giveErrorIfMissing) - EMSG2(_(e_font), name); - return font; - } - - #if defined(FEAT_EVAL) || defined(PROTO) - /* - * Return the name of font "font" in allocated memory. - * Don't know how to get the actual name, thus use the provided name. - */ - /*ARGSUSED*/ - char_u * - gui_mch_get_fontname(GuiFont font, char_u *name) - { - if (name == NULL) - return NULL; - return vim_strsave(name); - } - #endif - - void - gui_mch_free_font(GuiFont font) - { - if (font) - DeleteObject((HFONT)font); - } - - static int - hex_digit(int c) - { - if (VIM_ISDIGIT(c)) - return c - '0'; - c = TOLOWER_ASC(c); - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - return -1000; - } - /* - * Return the Pixel value (color) for the given color name. - * Return INVALCOLOR for error. - */ - guicolor_T - gui_mch_get_color(char_u *name) - { - typedef struct guicolor_tTable - { - char *name; - COLORREF color; - } guicolor_tTable; - - static guicolor_tTable table[] = - { - {"Black", RGB(0x00, 0x00, 0x00)}, - {"DarkGray", RGB(0xA9, 0xA9, 0xA9)}, - {"DarkGrey", RGB(0xA9, 0xA9, 0xA9)}, - {"Gray", RGB(0xC0, 0xC0, 0xC0)}, - {"Grey", RGB(0xC0, 0xC0, 0xC0)}, - {"LightGray", RGB(0xD3, 0xD3, 0xD3)}, - {"LightGrey", RGB(0xD3, 0xD3, 0xD3)}, - {"Gray10", RGB(0x1A, 0x1A, 0x1A)}, - {"Grey10", RGB(0x1A, 0x1A, 0x1A)}, - {"Gray20", RGB(0x33, 0x33, 0x33)}, - {"Grey20", RGB(0x33, 0x33, 0x33)}, - {"Gray30", RGB(0x4D, 0x4D, 0x4D)}, - {"Grey30", RGB(0x4D, 0x4D, 0x4D)}, - {"Gray40", RGB(0x66, 0x66, 0x66)}, - {"Grey40", RGB(0x66, 0x66, 0x66)}, - {"Gray50", RGB(0x7F, 0x7F, 0x7F)}, - {"Grey50", RGB(0x7F, 0x7F, 0x7F)}, - {"Gray60", RGB(0x99, 0x99, 0x99)}, - {"Grey60", RGB(0x99, 0x99, 0x99)}, - {"Gray70", RGB(0xB3, 0xB3, 0xB3)}, - {"Grey70", RGB(0xB3, 0xB3, 0xB3)}, - {"Gray80", RGB(0xCC, 0xCC, 0xCC)}, - {"Grey80", RGB(0xCC, 0xCC, 0xCC)}, - {"Gray90", RGB(0xE5, 0xE5, 0xE5)}, - {"Grey90", RGB(0xE5, 0xE5, 0xE5)}, - {"White", RGB(0xFF, 0xFF, 0xFF)}, - {"DarkRed", RGB(0x80, 0x00, 0x00)}, - {"Red", RGB(0xFF, 0x00, 0x00)}, - {"LightRed", RGB(0xFF, 0xA0, 0xA0)}, - {"DarkBlue", RGB(0x00, 0x00, 0x80)}, - {"Blue", RGB(0x00, 0x00, 0xFF)}, - {"LightBlue", RGB(0xAD, 0xD8, 0xE6)}, - {"DarkGreen", RGB(0x00, 0x80, 0x00)}, - {"Green", RGB(0x00, 0xFF, 0x00)}, - {"LightGreen", RGB(0x90, 0xEE, 0x90)}, - {"DarkCyan", RGB(0x00, 0x80, 0x80)}, - {"Cyan", RGB(0x00, 0xFF, 0xFF)}, - {"LightCyan", RGB(0xE0, 0xFF, 0xFF)}, - {"DarkMagenta", RGB(0x80, 0x00, 0x80)}, - {"Magenta", RGB(0xFF, 0x00, 0xFF)}, - {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)}, - {"Brown", RGB(0x80, 0x40, 0x40)}, - {"Yellow", RGB(0xFF, 0xFF, 0x00)}, - {"LightYellow", RGB(0xFF, 0xFF, 0xE0)}, - {"DarkYellow", RGB(0xBB, 0xBB, 0x00)}, - {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, - {"Orange", RGB(0xFF, 0xA5, 0x00)}, - {"Purple", RGB(0xA0, 0x20, 0xF0)}, - {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, - {"Violet", RGB(0xEE, 0x82, 0xEE)}, - }; - - typedef struct SysColorTable - { - char *name; - int color; - } SysColorTable; - - static SysColorTable sys_table[] = - { - #ifdef WIN3264 - {"SYS_3DDKSHADOW", COLOR_3DDKSHADOW}, - {"SYS_3DHILIGHT", COLOR_3DHILIGHT}, - #ifndef __MINGW32__ - {"SYS_3DHIGHLIGHT", COLOR_3DHIGHLIGHT}, - #endif - {"SYS_BTNHILIGHT", COLOR_BTNHILIGHT}, - {"SYS_BTNHIGHLIGHT", COLOR_BTNHIGHLIGHT}, - {"SYS_3DLIGHT", COLOR_3DLIGHT}, - {"SYS_3DSHADOW", COLOR_3DSHADOW}, - {"SYS_DESKTOP", COLOR_DESKTOP}, - {"SYS_INFOBK", COLOR_INFOBK}, - {"SYS_INFOTEXT", COLOR_INFOTEXT}, - {"SYS_3DFACE", COLOR_3DFACE}, - #endif - {"SYS_BTNFACE", COLOR_BTNFACE}, - {"SYS_BTNSHADOW", COLOR_BTNSHADOW}, - {"SYS_ACTIVEBORDER", COLOR_ACTIVEBORDER}, - {"SYS_ACTIVECAPTION", COLOR_ACTIVECAPTION}, - {"SYS_APPWORKSPACE", COLOR_APPWORKSPACE}, - {"SYS_BACKGROUND", COLOR_BACKGROUND}, - {"SYS_BTNTEXT", COLOR_BTNTEXT}, - {"SYS_CAPTIONTEXT", COLOR_CAPTIONTEXT}, - {"SYS_GRAYTEXT", COLOR_GRAYTEXT}, - {"SYS_HIGHLIGHT", COLOR_HIGHLIGHT}, - {"SYS_HIGHLIGHTTEXT", COLOR_HIGHLIGHTTEXT}, - {"SYS_INACTIVEBORDER", COLOR_INACTIVEBORDER}, - {"SYS_INACTIVECAPTION", COLOR_INACTIVECAPTION}, - {"SYS_INACTIVECAPTIONTEXT", COLOR_INACTIVECAPTIONTEXT}, - {"SYS_MENU", COLOR_MENU}, - {"SYS_MENUTEXT", COLOR_MENUTEXT}, - {"SYS_SCROLLBAR", COLOR_SCROLLBAR}, - {"SYS_WINDOW", COLOR_WINDOW}, - {"SYS_WINDOWFRAME", COLOR_WINDOWFRAME}, - {"SYS_WINDOWTEXT", COLOR_WINDOWTEXT} - }; - - int r, g, b; - int i; - - if (name[0] == '#' && STRLEN(name) == 7) - { - /* Name is in "#rrggbb" format */ - r = hex_digit(name[1]) * 16 + hex_digit(name[2]); - g = hex_digit(name[3]) * 16 + hex_digit(name[4]); - b = hex_digit(name[5]) * 16 + hex_digit(name[6]); - if (r < 0 || g < 0 || b < 0) - return INVALCOLOR; - return RGB(r, g, b); - } - else - { - /* Check if the name is one of the colors we know */ - for (i = 0; i < sizeof(table) / sizeof(table[0]); i++) - if (STRICMP(name, table[i].name) == 0) - return table[i].color; - } - - /* - * Try to look up a system colour. - */ - for (i = 0; i < sizeof(sys_table) / sizeof(sys_table[0]); i++) - if (STRICMP(name, sys_table[i].name) == 0) - return GetSysColor(sys_table[i].color); - - /* - * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt". - */ - { - #define LINE_LEN 100 - FILE *fd; - char line[LINE_LEN]; - char_u *fname; - - fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt"); - if (fname == NULL) - return INVALCOLOR; - - fd = mch_fopen((char *)fname, "rt"); - vim_free(fname); - if (fd == NULL) - return INVALCOLOR; - - while (!feof(fd)) - { - int len; - int pos; - char *color; - - fgets(line, LINE_LEN, fd); - len = (int)STRLEN(line); - - if (len <= 1 || line[len-1] != '\n') - continue; - - line[len-1] = '\0'; - - i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos); - if (i != 3) - continue; - - color = line + pos; - - if (STRICMP(color, name) == 0) - { - fclose(fd); - return (guicolor_T) RGB(r, g, b); - } - } - - fclose(fd); - } - - return INVALCOLOR; - } - /* - * Return OK if the key with the termcap name "name" is supported. - */ - int - gui_mch_haskey(char_u *name) - { - int i; - - for (i = 0; special_keys[i].vim_code1 != NUL; i++) - if (name[0] == special_keys[i].vim_code0 && - name[1] == special_keys[i].vim_code1) - return OK; - return FAIL; - } - - void - gui_mch_beep(void) - { - MessageBeep(MB_OK); - } - /* - * Invert a rectangle from row r, column c, for nr rows and nc columns. - */ - void - gui_mch_invert_rectangle( - int r, - int c, - int nr, - int nc) - { - RECT rc; - - /* - * Note: InvertRect() excludes right and bottom of rectangle. - */ - rc.left = FILL_X(c); - rc.top = FILL_Y(r); - rc.right = rc.left + nc * gui.char_width; - rc.bottom = rc.top + nr * gui.char_height; - InvertRect(s_hdc, &rc); - } - - /* - * Iconify the GUI window. - */ - void - gui_mch_iconify(void) - { - ShowWindow(s_hwnd, SW_MINIMIZE); - } - - /* - * Draw a cursor without focus. - */ - void - gui_mch_draw_hollow_cursor(guicolor_T color) - { - HBRUSH hbr; - RECT rc; - - /* - * Note: FrameRect() excludes right and bottom of rectangle. - */ - rc.left = FILL_X(gui.col); - rc.top = FILL_Y(gui.row); - rc.right = rc.left + gui.char_width; - #ifdef FEAT_MBYTE - if (mb_lefthalve(gui.row, gui.col)) - rc.right += gui.char_width; - #endif - rc.bottom = rc.top + gui.char_height; - hbr = CreateSolidBrush(color); - FrameRect(s_hdc, &rc, hbr); - DeleteBrush(hbr); - } - /* - * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using - * color "color". - */ - void - gui_mch_draw_part_cursor( - int w, - int h, - guicolor_T color) - { - HBRUSH hbr; - RECT rc; - - /* - * Note: FillRect() excludes right and bottom of rectangle. - */ - rc.left = - #ifdef FEAT_RIGHTLEFT - /* vertical line should be on the right of current point */ - CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w : - #endif - FILL_X(gui.col); - rc.top = FILL_Y(gui.row) + gui.char_height - h; - rc.right = rc.left + w; - rc.bottom = rc.top + h; - hbr = CreateSolidBrush(color); - FillRect(s_hdc, &rc, hbr); - DeleteBrush(hbr); - } - - - /* - * Generates a VK_SPACE when the internal dead_key flag is set to output the - * dead key's nominal character and re-post the original message. - */ - static void - outputDeadKey_rePost(MSG originalMsg) - { - static MSG deadCharExpel; - - if (!dead_key) - return; - - dead_key = 0; - - /* Make Windows generate the dead key's character */ - deadCharExpel.message = originalMsg.message; - deadCharExpel.hwnd = originalMsg.hwnd; - deadCharExpel.wParam = VK_SPACE; - - MyTranslateMessage(&deadCharExpel); - - /* re-generate the current character free of the dead char influence */ - PostMessage(originalMsg.hwnd, originalMsg.message, originalMsg.wParam, - originalMsg.lParam); - } - - - /* - * Process a single Windows message. - * If one is not available we hang until one is. - */ - static void - process_message(void) - { - MSG msg; - UINT vk = 0; /* Virtual key */ - char_u string[40]; - int i; - int modifiers = 0; - int key; - #ifdef FEAT_MENU - static char_u k10[] = {K_SPECIAL, 'k', ';', 0}; - #endif - - pGetMessage(&msg, NULL, 0, 0); - - #ifdef FEAT_OLE - /* Look after OLE Automation commands */ - if (msg.message == WM_OLE) - { - char_u *str = (char_u *)msg.lParam; - if (str == NULL || *str == NUL) - { - /* Message can't be ours, forward it. Fixes problem with Ultramon - * 3.0.4 */ - pDispatchMessage(&msg); - } - else - { - add_to_input_buf(str, (int)STRLEN(str)); - vim_free(str); /* was allocated in CVim::SendKeys() */ - } - return; - } - #endif - - #ifdef FEAT_CHANNEL - if (msg.message == WM_NETBEANS) - { - int what; - channel_T *channel = channel_fd2channel((sock_T)msg.wParam, &what); - - if (channel != NULL) - { - /* Disable error messages, they can mess up the display and throw - * an exception. */ - ++emsg_off; - channel_read(channel, what, "process_message"); - --emsg_off; - } - return; - } - #endif - - #ifdef FEAT_SNIFF - if (sniff_request_waiting && want_sniff_request) - { - static char_u bytes[3] = {CSI, (char_u)KS_EXTRA, (char_u)KE_SNIFF}; - add_to_input_buf(bytes, 3); /* K_SNIFF */ - sniff_request_waiting = 0; - want_sniff_request = 0; - /* request is handled in normal.c */ - } - if (msg.message == WM_USER) - { - MyTranslateMessage(&msg); - pDispatchMessage(&msg); - return; - } - #endif - - #ifdef MSWIN_FIND_REPLACE - /* Don't process messages used by the dialog */ - if (s_findrep_hwnd != NULL && pIsDialogMessage(s_findrep_hwnd, &msg)) - { - HandleMouseHide(msg.message, msg.lParam); - return; - } - #endif - - /* - * Check if it's a special key that we recognise. If not, call - * TranslateMessage(). - */ - if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) - { - vk = (int) msg.wParam; - - /* - * Handle dead keys in special conditions in other cases we let Windows - * handle them and do not interfere. - * - * The dead_key flag must be reset on several occasions: - * - in _OnChar() (or _OnSysChar()) as any dead key was necessarily - * consumed at that point (This is when we let Windows combine the - * dead character on its own) - * - * - Before doing something special such as regenerating keypresses to - * expel the dead character as this could trigger an infinite loop if - * for some reason MyTranslateMessage() do not trigger a call - * immediately to _OnChar() (or _OnSysChar()). - */ - if (dead_key) - { - /* - * If a dead key was pressed and the user presses VK_SPACE, - * VK_BACK, or VK_ESCAPE it means that he actually wants to deal - * with the dead char now, so do nothing special and let Windows - * handle it. - * - * Note that VK_SPACE combines with the dead_key's character and - * only one WM_CHAR will be generated by TranslateMessage(), in - * the two other cases two WM_CHAR will be generated: the dead - * char and VK_BACK or VK_ESCAPE. That is most likely what the - * user expects. - */ - if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE)) - { - dead_key = 0; - MyTranslateMessage(&msg); - return; - } - /* In modes where we are not typing, dead keys should behave - * normally */ - else if (!(get_real_state() & (INSERT | CMDLINE | SELECTMODE))) - { - outputDeadKey_rePost(msg); - return; - } - } - - /* Check for CTRL-BREAK */ - if (vk == VK_CANCEL) - { - trash_input_buf(); - got_int = TRUE; - string[0] = Ctrl_C; - add_to_input_buf(string, 1); - } - - for (i = 0; special_keys[i].key_sym != 0; i++) - { - /* ignore VK_SPACE when ALT key pressed: system menu */ - if (special_keys[i].key_sym == vk - && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000))) - { - /* - * Behave as exected if we have a dead key and the special key - * is a key that would normally trigger the dead key nominal - * character output (such as a NUMPAD printable character or - * the TAB key, etc...). - */ - if (dead_key && (special_keys[i].vim_code0 == 'K' - || vk == VK_TAB || vk == CAR)) - { - outputDeadKey_rePost(msg); - return; - } - - #ifdef FEAT_MENU - /* Check for : Windows selects the menu. When is - * mapped we want to use the mapping instead. */ - if (vk == VK_F10 - && gui.menu_is_active - && check_map(k10, State, FALSE, TRUE, FALSE, - NULL, NULL) == NULL) - break; - #endif - if (GetKeyState(VK_SHIFT) & 0x8000) - modifiers |= MOD_MASK_SHIFT; - /* - * Don't use caps-lock as shift, because these are special keys - * being considered here, and we only want letters to get - * shifted -- webb - */ - /* - if (GetKeyState(VK_CAPITAL) & 0x0001) - modifiers ^= MOD_MASK_SHIFT; - */ - if (GetKeyState(VK_CONTROL) & 0x8000) - modifiers |= MOD_MASK_CTRL; - if (GetKeyState(VK_MENU) & 0x8000) - modifiers |= MOD_MASK_ALT; - - if (special_keys[i].vim_code1 == NUL) - key = special_keys[i].vim_code0; - else - key = TO_SPECIAL(special_keys[i].vim_code0, - special_keys[i].vim_code1); - key = simplify_key(key, &modifiers); - if (key == CSI) - key = K_CSI; - - if (modifiers) - { - string[0] = CSI; - string[1] = KS_MODIFIER; - string[2] = modifiers; - add_to_input_buf(string, 3); - } - - if (IS_SPECIAL(key)) - { - string[0] = CSI; - string[1] = K_SECOND(key); - string[2] = K_THIRD(key); - add_to_input_buf(string, 3); - } - else - { - int len; - - /* Handle "key" as a Unicode character. */ - len = char_to_string(key, string, 40, FALSE); - add_to_input_buf(string, len); - } - break; - } - } - if (special_keys[i].key_sym == 0) - { - /* Some keys need C-S- where they should only need C-. - * Ignore 0xff, Windows XP sends it when NUMLOCK has changed since - * system startup (Helmut Stiegler, 2003 Oct 3). */ - if (vk != 0xff - && (GetKeyState(VK_CONTROL) & 0x8000) - && !(GetKeyState(VK_SHIFT) & 0x8000) - && !(GetKeyState(VK_MENU) & 0x8000)) - { - /* CTRL-6 is '^'; Japanese keyboard maps '^' to vk == 0xDE */ - if (vk == '6' || MapVirtualKey(vk, 2) == (UINT)'^') - { - string[0] = Ctrl_HAT; - add_to_input_buf(string, 1); - } - /* vk == 0xBD AZERTY for CTRL-'-', but CTRL-[ for * QWERTY! */ - else if (vk == 0xBD) /* QWERTY for CTRL-'-' */ - { - string[0] = Ctrl__; - add_to_input_buf(string, 1); - } - /* CTRL-2 is '@'; Japanese keyboard maps '@' to vk == 0xC0 */ - else if (vk == '2' || MapVirtualKey(vk, 2) == (UINT)'@') - { - string[0] = Ctrl_AT; - add_to_input_buf(string, 1); - } - else - MyTranslateMessage(&msg); - } - else - MyTranslateMessage(&msg); - } - } - #ifdef FEAT_MBYTE_IME - else if (msg.message == WM_IME_NOTIFY) - _OnImeNotify(msg.hwnd, (DWORD)msg.wParam, (DWORD)msg.lParam); - else if (msg.message == WM_KEYUP && im_get_status()) - /* added for non-MS IME (Yasuhiro Matsumoto) */ - MyTranslateMessage(&msg); - #endif - #if !defined(FEAT_MBYTE_IME) && defined(GLOBAL_IME) - /* GIME_TEST */ - else if (msg.message == WM_IME_STARTCOMPOSITION) - { - POINT point; - - global_ime_set_font(&norm_logfont); - point.x = FILL_X(gui.col); - point.y = FILL_Y(gui.row); - MapWindowPoints(s_textArea, s_hwnd, &point, 1); - global_ime_set_position(&point); - } - #endif - - #ifdef FEAT_MENU - /* Check for : Default effect is to select the menu. When is - * mapped we need to stop it here to avoid strange effects (e.g., for the - * key-up event) */ - if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE, - NULL, NULL) == NULL) - #endif - pDispatchMessage(&msg); - } - - /* - * Catch up with any queued events. This may put keyboard input into the - * input buffer, call resize call-backs, trigger timers etc. If there is - * nothing in the event queue (& no timers pending), then we return - * immediately. - */ - void - gui_mch_update(void) - { - MSG msg; - - if (!s_busy_processing) - while (pPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) - && !vim_is_input_buf_full()) - process_message(); - } - - /* - * GUI input routine called by gui_wait_for_chars(). Waits for a character - * from the keyboard. - * wtime == -1 Wait forever. - * wtime == 0 This should never happen. - * wtime > 0 Wait wtime milliseconds for a character. - * Returns OK if a character was found to be available within the given time, - * or FAIL otherwise. - */ - int - gui_mch_wait_for_chars(int wtime) - { - MSG msg; - int focus; - - s_timed_out = FALSE; - - if (wtime > 0) - { - /* Don't do anything while processing a (scroll) message. */ - if (s_busy_processing) - return FAIL; - s_wait_timer = (UINT)SetTimer(NULL, 0, (UINT)wtime, - (TIMERPROC)_OnTimer); - } - - allow_scrollbar = TRUE; - - focus = gui.in_focus; - while (!s_timed_out) - { - /* Stop or start blinking when focus changes */ - if (gui.in_focus != focus) - { - if (gui.in_focus) - gui_mch_start_blink(); - else - gui_mch_stop_blink(); - focus = gui.in_focus; - } - - if (s_need_activate) - { - #ifdef WIN32 - (void)SetForegroundWindow(s_hwnd); - #else - (void)SetActiveWindow(s_hwnd); - #endif - s_need_activate = FALSE; - } - - #ifdef MESSAGE_QUEUE - parse_queued_messages(); - #endif - - #ifdef FEAT_CHANNEL - channel_handle_events(); - #endif - - /* - * Don't use gui_mch_update() because then we will spin-lock until a - * char arrives, instead we use GetMessage() to hang until an - * event arrives. No need to check for input_buf_full because we are - * returning as soon as it contains a single char -- webb - */ - process_message(); - - if (input_available()) - { - if (s_wait_timer != 0 && !s_timed_out) - { - KillTimer(NULL, s_wait_timer); - - /* Eat spurious WM_TIMER messages */ - while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) - ; - s_wait_timer = 0; - } - allow_scrollbar = FALSE; - - /* Clear pending mouse button, the release event may have been - * taken by the dialog window. But don't do this when getting - * focus, we need the mouse-up event then. */ - if (!s_getting_focus) - s_button_pending = -1; - - return OK; - } - } - allow_scrollbar = FALSE; - return FAIL; - } - - /* - * Clear a rectangular region of the screen from text pos (row1, col1) to - * (row2, col2) inclusive. - */ - void - gui_mch_clear_block( - int row1, - int col1, - int row2, - int col2) - { - RECT rc; - - /* - * Clear one extra pixel at the far right, for when bold characters have - * spilled over to the window border. - * Note: FillRect() excludes right and bottom of rectangle. - */ - rc.left = FILL_X(col1); - rc.top = FILL_Y(row1); - rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1); - rc.bottom = FILL_Y(row2 + 1); - clear_rect(&rc); - } - - /* - * Clear the whole text window. - */ - void - gui_mch_clear_all(void) - { - RECT rc; - - rc.left = 0; - rc.top = 0; - rc.right = Columns * gui.char_width + 2 * gui.border_width; - rc.bottom = Rows * gui.char_height + 2 * gui.border_width; - clear_rect(&rc); - } - /* - * Menu stuff. - */ - - void - gui_mch_enable_menu(int flag) - { - #ifdef FEAT_MENU - SetMenu(s_hwnd, flag ? s_menuBar : NULL); - #endif - } - - /*ARGSUSED*/ - void - gui_mch_set_menu_pos( - int x, - int y, - int w, - int h) - { - /* It will be in the right place anyway */ - } - - #if defined(FEAT_MENU) || defined(PROTO) - /* - * Make menu item hidden or not hidden - */ - void - gui_mch_menu_hidden( - vimmenu_T *menu, - int hidden) - { - /* - * This doesn't do what we want. Hmm, just grey the menu items for now. - */ - /* - if (hidden) - EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_DISABLED); - else - EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED); - */ - gui_mch_menu_grey(menu, hidden); - } - - /* - * This is called after setting all the menus to grey/hidden or not. - */ - void - gui_mch_draw_menubar(void) - { - DrawMenuBar(s_hwnd); - } - #endif /*FEAT_MENU*/ - - #ifndef PROTO - void - #ifdef VIMDLL - _export - #endif - _cdecl - SaveInst(HINSTANCE hInst) - { - s_hinst = hInst; - } - #endif - - /* - * Return the RGB value of a pixel as a long. - */ - long_u - gui_mch_get_rgb(guicolor_T pixel) - { - return (GetRValue(pixel) << 16) + (GetGValue(pixel) << 8) - + GetBValue(pixel); - } - - #if defined(FEAT_GUI_DIALOG) || defined(PROTO) - /* Convert pixels in X to dialog units */ - static WORD - PixelToDialogX(int numPixels) - { - return (WORD)((numPixels * 4) / s_dlgfntwidth); - } - - /* Convert pixels in Y to dialog units */ - static WORD - PixelToDialogY(int numPixels) - { - return (WORD)((numPixels * 8) / s_dlgfntheight); - } - - /* Return the width in pixels of the given text in the given DC. */ - static int - GetTextWidth(HDC hdc, char_u *str, int len) - { - SIZE size; - - GetTextExtentPoint(hdc, (LPCSTR)str, len, &size); - return size.cx; - } - - #ifdef FEAT_MBYTE - /* - * Return the width in pixels of the given text in the given DC, taking care - * of 'encoding' to active codepage conversion. - */ - static int - GetTextWidthEnc(HDC hdc, char_u *str, int len) - { - SIZE size; - WCHAR *wstr; - int n; - int wlen = len; - - if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) - { - /* 'encoding' differs from active codepage: convert text and use wide - * function */ - wstr = enc_to_utf16(str, &wlen); - if (wstr != NULL) - { - n = GetTextExtentPointW(hdc, wstr, wlen, &size); - vim_free(wstr); - if (n) - return size.cx; - } - } - - return GetTextWidth(hdc, str, len); - } - #else - # define GetTextWidthEnc(h, s, l) GetTextWidth((h), (s), (l)) - #endif - - /* - * A quick little routine that will center one window over another, handy for - * dialog boxes. Taken from the Win32SDK samples. - */ - static BOOL - CenterWindow( - HWND hwndChild, - HWND hwndParent) - { - RECT rChild, rParent; - int wChild, hChild, wParent, hParent; - int wScreen, hScreen, xNew, yNew; - HDC hdc; - - GetWindowRect(hwndChild, &rChild); - wChild = rChild.right - rChild.left; - hChild = rChild.bottom - rChild.top; - - /* If Vim is minimized put the window in the middle of the screen. */ - if (hwndParent == NULL || IsMinimized(hwndParent)) - { - #ifdef WIN16 - rParent.left = 0; - rParent.top = 0; - rParent.right = GetSystemMetrics(SM_CXSCREEN); - rParent.bottom = GetSystemMetrics(SM_CYFULLSCREEN); - #else - SystemParametersInfo(SPI_GETWORKAREA, 0, &rParent, 0); - #endif - } - else - GetWindowRect(hwndParent, &rParent); - wParent = rParent.right - rParent.left; - hParent = rParent.bottom - rParent.top; - - hdc = GetDC(hwndChild); - wScreen = GetDeviceCaps (hdc, HORZRES); - hScreen = GetDeviceCaps (hdc, VERTRES); - ReleaseDC(hwndChild, hdc); - - xNew = rParent.left + ((wParent - wChild) /2); - if (xNew < 0) - { - xNew = 0; - } - else if ((xNew+wChild) > wScreen) - { - xNew = wScreen - wChild; - } - - yNew = rParent.top + ((hParent - hChild) /2); - if (yNew < 0) - yNew = 0; - else if ((yNew+hChild) > hScreen) - yNew = hScreen - hChild; - - return SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0, - SWP_NOSIZE | SWP_NOZORDER); - } - #endif /* FEAT_GUI_DIALOG */ - - void - gui_mch_activate_window(void) - { - (void)SetActiveWindow(s_hwnd); - } - - #if defined(FEAT_TOOLBAR) || defined(PROTO) - void - gui_mch_show_toolbar(int showit) - { - if (s_toolbarhwnd == NULL) - return; - - if (showit) - { - # ifdef FEAT_MBYTE - # ifndef TB_SETUNICODEFORMAT - /* For older compilers. We assume this never changes. */ - # define TB_SETUNICODEFORMAT 0x2005 - # endif - /* Enable/disable unicode support */ - int uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage); - SendMessage(s_toolbarhwnd, TB_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0); - # endif - ShowWindow(s_toolbarhwnd, SW_SHOW); - } - else - ShowWindow(s_toolbarhwnd, SW_HIDE); - } - - /* Then number of bitmaps is fixed. Exit is missing! */ - #define TOOLBAR_BITMAP_COUNT 31 - - #endif - - #if defined(FEAT_GUI_TABLINE) || defined(PROTO) - static void - add_tabline_popup_menu_entry(HMENU pmenu, UINT item_id, char_u *item_text) - { - #ifdef FEAT_MBYTE - WCHAR *wn = NULL; - int n; - - if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) - { - /* 'encoding' differs from active codepage: convert menu name - * and use wide function */ - wn = enc_to_utf16(item_text, NULL); - if (wn != NULL) - { - MENUITEMINFOW infow; - - infow.cbSize = sizeof(infow); - infow.fMask = MIIM_TYPE | MIIM_ID; - infow.wID = item_id; - infow.fType = MFT_STRING; - infow.dwTypeData = wn; - infow.cch = (UINT)wcslen(wn); - n = InsertMenuItemW(pmenu, item_id, FALSE, &infow); - vim_free(wn); - if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) - /* Failed, try using non-wide function. */ - wn = NULL; - } - } - - if (wn == NULL) - #endif - { - MENUITEMINFO info; - - info.cbSize = sizeof(info); - info.fMask = MIIM_TYPE | MIIM_ID; - info.wID = item_id; - info.fType = MFT_STRING; - info.dwTypeData = (LPTSTR)item_text; - info.cch = (UINT)STRLEN(item_text); - InsertMenuItem(pmenu, item_id, FALSE, &info); - } - } - - static void - show_tabline_popup_menu(void) - { - HMENU tab_pmenu; - long rval; - POINT pt; - - /* When ignoring events don't show the menu. */ - if (hold_gui_events - # ifdef FEAT_CMDWIN - || cmdwin_type != 0 - # endif - ) - return; - - tab_pmenu = CreatePopupMenu(); - if (tab_pmenu == NULL) - return; - - if (first_tabpage->tp_next != NULL) - add_tabline_popup_menu_entry(tab_pmenu, - TABLINE_MENU_CLOSE, (char_u *)_("Close tab")); - add_tabline_popup_menu_entry(tab_pmenu, - TABLINE_MENU_NEW, (char_u *)_("New tab")); - add_tabline_popup_menu_entry(tab_pmenu, - TABLINE_MENU_OPEN, (char_u *)_("Open tab...")); - - GetCursorPos(&pt); - rval = TrackPopupMenuEx(tab_pmenu, TPM_RETURNCMD, pt.x, pt.y, s_tabhwnd, - NULL); - - DestroyMenu(tab_pmenu); - - /* Add the string cmd into input buffer */ - if (rval > 0) - { - TCHITTESTINFO htinfo; - int idx; - - if (ScreenToClient(s_tabhwnd, &pt) == 0) - return; - - htinfo.pt.x = pt.x; - htinfo.pt.y = pt.y; - idx = TabCtrl_HitTest(s_tabhwnd, &htinfo); - if (idx == -1) - idx = 0; - else - idx += 1; - - send_tabline_menu_event(idx, (int)rval); - } - } - - /* - * Show or hide the tabline. - */ - void - gui_mch_show_tabline(int showit) - { - if (s_tabhwnd == NULL) - return; - - if (!showit != !showing_tabline) - { - if (showit) - ShowWindow(s_tabhwnd, SW_SHOW); - else - ShowWindow(s_tabhwnd, SW_HIDE); - showing_tabline = showit; - } - } - - /* - * Return TRUE when tabline is displayed. - */ - int - gui_mch_showing_tabline(void) - { - return s_tabhwnd != NULL && showing_tabline; - } - - /* - * Update the labels of the tabline. - */ - void - gui_mch_update_tabline(void) - { - tabpage_T *tp; - TCITEM tie; - int nr = 0; - int curtabidx = 0; - int tabadded = 0; - #ifdef FEAT_MBYTE - static int use_unicode = FALSE; - int uu; - WCHAR *wstr = NULL; - #endif - - if (s_tabhwnd == NULL) - return; - - #if defined(FEAT_MBYTE) - # ifndef CCM_SETUNICODEFORMAT - /* For older compilers. We assume this never changes. */ - # define CCM_SETUNICODEFORMAT 0x2005 - # endif - uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage); - if (uu != use_unicode) - { - /* Enable/disable unicode support */ - SendMessage(s_tabhwnd, CCM_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0); - use_unicode = uu; - } - #endif - - tie.mask = TCIF_TEXT; - tie.iImage = -1; - - /* Disable redraw for tab updates to eliminate O(N^2) draws. */ - SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)FALSE, 0); - - /* Add a label for each tab page. They all contain the same text area. */ - for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) - { - if (tp == curtab) - curtabidx = nr; - - if (nr >= TabCtrl_GetItemCount(s_tabhwnd)) - { - /* Add the tab */ - tie.pszText = "-Empty-"; - TabCtrl_InsertItem(s_tabhwnd, nr, &tie); - tabadded = 1; - } - - get_tabline_label(tp, FALSE); - tie.pszText = (LPSTR)NameBuff; - #ifdef FEAT_MBYTE - wstr = NULL; - if (use_unicode) - { - /* Need to go through Unicode. */ - wstr = enc_to_utf16(NameBuff, NULL); - if (wstr != NULL) - { - TCITEMW tiw; - - tiw.mask = TCIF_TEXT; - tiw.iImage = -1; - tiw.pszText = wstr; - SendMessage(s_tabhwnd, TCM_SETITEMW, (WPARAM)nr, (LPARAM)&tiw); - vim_free(wstr); - } - } - if (wstr == NULL) - #endif - { - TabCtrl_SetItem(s_tabhwnd, nr, &tie); - } - } - - /* Remove any old labels. */ - while (nr < TabCtrl_GetItemCount(s_tabhwnd)) - TabCtrl_DeleteItem(s_tabhwnd, nr); - - if (!tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx) - TabCtrl_SetCurSel(s_tabhwnd, curtabidx); - - /* Re-enable redraw and redraw. */ - SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)TRUE, 0); - RedrawWindow(s_tabhwnd, NULL, NULL, - RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); - - if (tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx) - TabCtrl_SetCurSel(s_tabhwnd, curtabidx); - } - - /* - * Set the current tab to "nr". First tab is 1. - */ - void - gui_mch_set_curtab(int nr) - { - if (s_tabhwnd == NULL) - return; - - if (TabCtrl_GetCurSel(s_tabhwnd) != nr - 1) - TabCtrl_SetCurSel(s_tabhwnd, nr - 1); - } - - #endif - - /* - * ":simalt" command. - */ - void - ex_simalt(exarg_T *eap) - { - char_u *keys = eap->arg; - - PostMessage(s_hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)0); - while (*keys) - { - if (*keys == '~') - *keys = ' '; /* for showing system menu */ - PostMessage(s_hwnd, WM_CHAR, (WPARAM)*keys, (LPARAM)0); - keys++; - } - } - - /* - * Create the find & replace dialogs. - * You can't have both at once: ":find" when replace is showing, destroys - * the replace dialog first, and the other way around. - */ - #ifdef MSWIN_FIND_REPLACE - static void - initialise_findrep(char_u *initial_string) - { - int wword = FALSE; - int mcase = !p_ic; - char_u *entry_text; - - /* Get the search string to use. */ - entry_text = get_find_dialog_text(initial_string, &wword, &mcase); - - s_findrep_struct.hwndOwner = s_hwnd; - s_findrep_struct.Flags = FR_DOWN; - if (mcase) - s_findrep_struct.Flags |= FR_MATCHCASE; - if (wword) - s_findrep_struct.Flags |= FR_WHOLEWORD; - if (entry_text != NULL && *entry_text != NUL) - vim_strncpy((char_u *)s_findrep_struct.lpstrFindWhat, entry_text, - s_findrep_struct.wFindWhatLen - 1); - vim_free(entry_text); - } - #endif - - static void - set_window_title(HWND hwnd, char *title) - { - #ifdef FEAT_MBYTE - if (title != NULL && enc_codepage >= 0 && enc_codepage != (int)GetACP()) - { - WCHAR *wbuf; - int n; - - /* Convert the title from 'encoding' to UTF-16. */ - wbuf = (WCHAR *)enc_to_utf16((char_u *)title, NULL); - if (wbuf != NULL) - { - n = SetWindowTextW(hwnd, wbuf); - vim_free(wbuf); - if (n != 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - return; - /* Retry with non-wide function (for Windows 98). */ - } - } - #endif - (void)SetWindowText(hwnd, (LPCSTR)title); - } - - void - gui_mch_find_dialog(exarg_T *eap) - { - #ifdef MSWIN_FIND_REPLACE - if (s_findrep_msg != 0) - { - if (IsWindow(s_findrep_hwnd) && !s_findrep_is_find) - DestroyWindow(s_findrep_hwnd); - - if (!IsWindow(s_findrep_hwnd)) - { - initialise_findrep(eap->arg); - # if defined(FEAT_MBYTE) && defined(WIN3264) - /* If the OS is Windows NT, and 'encoding' differs from active - * codepage: convert text and use wide function. */ - if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT - && enc_codepage >= 0 && (int)GetACP() != enc_codepage) - { - findrep_atow(&s_findrep_struct_w, &s_findrep_struct); - s_findrep_hwnd = FindTextW( - (LPFINDREPLACEW) &s_findrep_struct_w); - } - else - # endif - s_findrep_hwnd = FindText((LPFINDREPLACE) &s_findrep_struct); - } - - set_window_title(s_findrep_hwnd, - _("Find string (use '\\\\' to find a '\\')")); - (void)SetFocus(s_findrep_hwnd); - - s_findrep_is_find = TRUE; - } - #endif - } - - - void - gui_mch_replace_dialog(exarg_T *eap) - { - #ifdef MSWIN_FIND_REPLACE - if (s_findrep_msg != 0) - { - if (IsWindow(s_findrep_hwnd) && s_findrep_is_find) - DestroyWindow(s_findrep_hwnd); - - if (!IsWindow(s_findrep_hwnd)) - { - initialise_findrep(eap->arg); - # if defined(FEAT_MBYTE) && defined(WIN3264) - if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT - && enc_codepage >= 0 && (int)GetACP() != enc_codepage) - { - findrep_atow(&s_findrep_struct_w, &s_findrep_struct); - s_findrep_hwnd = ReplaceTextW( - (LPFINDREPLACEW) &s_findrep_struct_w); - } - else - # endif - s_findrep_hwnd = ReplaceText( - (LPFINDREPLACE) &s_findrep_struct); - } - - set_window_title(s_findrep_hwnd, - _("Find & Replace (use '\\\\' to find a '\\')")); - (void)SetFocus(s_findrep_hwnd); - - s_findrep_is_find = FALSE; - } - #endif - } - - - /* - * Set visibility of the pointer. - */ - void - gui_mch_mousehide(int hide) - { - if (hide != gui.pointer_hidden) - { - ShowCursor(!hide); - gui.pointer_hidden = hide; - } - } - - #ifdef FEAT_MENU - static void - gui_mch_show_popupmenu_at(vimmenu_T *menu, int x, int y) - { - /* Unhide the mouse, we don't get move events here. */ - gui_mch_mousehide(FALSE); - - (void)TrackPopupMenu( - (HMENU)menu->submenu_id, - TPM_LEFTALIGN | TPM_LEFTBUTTON, - x, y, - (int)0, /*reserved param*/ - s_hwnd, - NULL); - /* - * NOTE: The pop-up menu can eat the mouse up event. - * We deal with this in normal.c. - */ - } - #endif - - /* - * Got a message when the system will go down. - */ - static void - _OnEndSession(void) - { - getout_preserve_modified(1); - } - - /* - * Get this message when the user clicks on the cross in the top right corner - * of a Windows95 window. - */ - /*ARGSUSED*/ - static void - _OnClose( - HWND hwnd) - { - gui_shell_closed(); - } - - /* - * Get a message when the window is being destroyed. - */ - static void - _OnDestroy( - HWND hwnd) - { - #ifdef WIN16_3DLOOK - Ctl3dUnregister(s_hinst); - #endif - if (!destroying) - _OnClose(hwnd); - } - - static void - _OnPaint( - HWND hwnd) - { - if (!IsMinimized(hwnd)) - { - PAINTSTRUCT ps; - - out_flush(); /* make sure all output has been processed */ - (void)BeginPaint(hwnd, &ps); - #if defined(FEAT_DIRECTX) - if (IS_ENABLE_DIRECTX()) - DWriteContext_BeginDraw(s_dwc); - #endif - - #ifdef FEAT_MBYTE - /* prevent multi-byte characters from misprinting on an invalid - * rectangle */ - if (has_mbyte) - { - RECT rect; - - GetClientRect(hwnd, &rect); - ps.rcPaint.left = rect.left; - ps.rcPaint.right = rect.right; - } - #endif - - if (!IsRectEmpty(&ps.rcPaint)) - { - #if defined(FEAT_DIRECTX) - if (IS_ENABLE_DIRECTX()) - DWriteContext_BindDC(s_dwc, s_hdc, &ps.rcPaint); - #endif - gui_redraw(ps.rcPaint.left, ps.rcPaint.top, - ps.rcPaint.right - ps.rcPaint.left + 1, - ps.rcPaint.bottom - ps.rcPaint.top + 1); - } - - #if defined(FEAT_DIRECTX) - if (IS_ENABLE_DIRECTX()) - DWriteContext_EndDraw(s_dwc); - #endif - EndPaint(hwnd, &ps); - } - } - - /*ARGSUSED*/ - static void - _OnSize( - HWND hwnd, - UINT state, - int cx, - int cy) - { - if (!IsMinimized(hwnd)) - { - gui_resize_shell(cx, cy); - - #ifdef FEAT_MENU - /* Menu bar may wrap differently now */ - gui_mswin_get_menu_height(TRUE); - #endif - } - } - - static void - _OnSetFocus( - HWND hwnd, - HWND hwndOldFocus) - { - gui_focus_change(TRUE); - s_getting_focus = TRUE; - (void)MyWindowProc(hwnd, WM_SETFOCUS, (WPARAM)hwndOldFocus, 0); - } - - static void - _OnKillFocus( - HWND hwnd, - HWND hwndNewFocus) - { - gui_focus_change(FALSE); - s_getting_focus = FALSE; - (void)MyWindowProc(hwnd, WM_KILLFOCUS, (WPARAM)hwndNewFocus, 0); - } - - /* - * Get a message when the user switches back to vim - */ - #ifdef WIN16 - static BOOL - #else - static LRESULT - #endif - _OnActivateApp( - HWND hwnd, - BOOL fActivate, - #ifdef WIN16 - HTASK dwThreadId - #else - DWORD dwThreadId - #endif - ) - { - /* we call gui_focus_change() in _OnSetFocus() */ - /* gui_focus_change((int)fActivate); */ - return MyWindowProc(hwnd, WM_ACTIVATEAPP, fActivate, (DWORD)dwThreadId); - } - - #if defined(FEAT_WINDOWS) || defined(PROTO) - void - gui_mch_destroy_scrollbar(scrollbar_T *sb) - { - DestroyWindow(sb->id); - } - #endif - - /* - * Get current mouse coordinates in text window. - */ - void - gui_mch_getmouse(int *x, int *y) - { - RECT rct; - POINT mp; - - (void)GetWindowRect(s_textArea, &rct); - (void)GetCursorPos((LPPOINT)&mp); - *x = (int)(mp.x - rct.left); - *y = (int)(mp.y - rct.top); - } - - /* - * Move mouse pointer to character at (x, y). - */ - void - gui_mch_setmouse(int x, int y) - { - RECT rct; - - (void)GetWindowRect(s_textArea, &rct); - (void)SetCursorPos(x + gui.border_offset + rct.left, - y + gui.border_offset + rct.top); - } - - static void - gui_mswin_get_valid_dimensions( - int w, - int h, - int *valid_w, - int *valid_h) - { - int base_width, base_height; - - base_width = gui_get_base_width() - + (GetSystemMetrics(SM_CXFRAME) + - GetSystemMetrics(SM_CXPADDEDBORDER)) * 2; - base_height = gui_get_base_height() - + (GetSystemMetrics(SM_CYFRAME) + - GetSystemMetrics(SM_CXPADDEDBORDER)) * 2 - + GetSystemMetrics(SM_CYCAPTION) - #ifdef FEAT_MENU - + gui_mswin_get_menu_height(FALSE) - #endif - ; - *valid_w = base_width + - ((w - base_width) / gui.char_width) * gui.char_width; - *valid_h = base_height + - ((h - base_height) / gui.char_height) * gui.char_height; - } - - void - gui_mch_flash(int msec) - { - RECT rc; - - /* - * Note: InvertRect() excludes right and bottom of rectangle. - */ - rc.left = 0; - rc.top = 0; - rc.right = gui.num_cols * gui.char_width; - rc.bottom = gui.num_rows * gui.char_height; - InvertRect(s_hdc, &rc); - gui_mch_flush(); /* make sure it's displayed */ - - ui_delay((long)msec, TRUE); /* wait for a few msec */ - - InvertRect(s_hdc, &rc); - } - - /* - * Return flags used for scrolling. - * The SW_INVALIDATE is required when part of the window is covered or - * off-screen. Refer to MS KB Q75236. - */ - static int - get_scroll_flags(void) - { - HWND hwnd; - RECT rcVim, rcOther, rcDest; - - GetWindowRect(s_hwnd, &rcVim); - - /* Check if the window is partly above or below the screen. We don't care - * about partly left or right of the screen, it is not relevant when - * scrolling up or down. */ - if (rcVim.top < 0 || rcVim.bottom > GetSystemMetrics(SM_CYFULLSCREEN)) - return SW_INVALIDATE; - - /* Check if there is an window (partly) on top of us. */ - for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; ) - if (IsWindowVisible(hwnd)) - { - GetWindowRect(hwnd, &rcOther); - if (IntersectRect(&rcDest, &rcVim, &rcOther)) - return SW_INVALIDATE; - } - return 0; - } - - /* - * On some Intel GPUs, the regions drawn just prior to ScrollWindowEx() - * may not be scrolled out properly. - * For gVim, when _OnScroll() is repeated, the character at the - * previous cursor position may be left drawn after scroll. - * The problem can be avoided by calling GetPixel() to get a pixel in - * the region before ScrollWindowEx(). - */ - static void - intel_gpu_workaround(void) - { - GetPixel(s_hdc, FILL_X(gui.col), FILL_Y(gui.row)); - } - - /* - * Delete the given number of lines from the given row, scrolling up any - * text further down within the scroll region. - */ - void - gui_mch_delete_lines( - int row, - int num_lines) - { - RECT rc; - - intel_gpu_workaround(); - - rc.left = FILL_X(gui.scroll_region_left); - rc.right = FILL_X(gui.scroll_region_right + 1); - rc.top = FILL_Y(row); - rc.bottom = FILL_Y(gui.scroll_region_bot + 1); - - ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height, - &rc, &rc, NULL, NULL, get_scroll_flags()); - - UpdateWindow(s_textArea); - /* This seems to be required to avoid the cursor disappearing when - * scrolling such that the cursor ends up in the top-left character on - * the screen... But why? (Webb) */ - /* It's probably fixed by disabling drawing the cursor while scrolling. */ - /* gui.cursor_is_valid = FALSE; */ - - gui_clear_block(gui.scroll_region_bot - num_lines + 1, - gui.scroll_region_left, - gui.scroll_region_bot, gui.scroll_region_right); - } - - /* - * Insert the given number of lines before the given row, scrolling down any - * following text within the scroll region. - */ - void - gui_mch_insert_lines( - int row, - int num_lines) - { - RECT rc; - - intel_gpu_workaround(); - - rc.left = FILL_X(gui.scroll_region_left); - rc.right = FILL_X(gui.scroll_region_right + 1); - rc.top = FILL_Y(row); - rc.bottom = FILL_Y(gui.scroll_region_bot + 1); - /* The SW_INVALIDATE is required when part of the window is covered or - * off-screen. How do we avoid it when it's not needed? */ - ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height, - &rc, &rc, NULL, NULL, get_scroll_flags()); - - UpdateWindow(s_textArea); - - gui_clear_block(row, gui.scroll_region_left, - row + num_lines - 1, gui.scroll_region_right); - } - - - /*ARGSUSED*/ - void - gui_mch_exit(int rc) - { - #if defined(FEAT_DIRECTX) - DWriteContext_Close(s_dwc); - DWrite_Final(); - s_dwc = NULL; - #endif - - ReleaseDC(s_textArea, s_hdc); - DeleteObject(s_brush); - - #ifdef FEAT_TEAROFF - /* Unload the tearoff bitmap */ - (void)DeleteObject((HGDIOBJ)s_htearbitmap); - #endif - - /* Destroy our window (if we have one). */ - if (s_hwnd != NULL) - { - destroying = TRUE; /* ignore WM_DESTROY message now */ - DestroyWindow(s_hwnd); - } - - #ifdef GLOBAL_IME - global_ime_end(); - #endif - } - - static char_u * - logfont2name(LOGFONT lf) - { - char *p; - char *res; - char *charset_name; - char *font_name = lf.lfFaceName; - - charset_name = charset_id2name((int)lf.lfCharSet); - #ifdef FEAT_MBYTE - /* Convert a font name from the current codepage to 'encoding'. - * TODO: Use Wide APIs (including LOGFONTW) instead of ANSI APIs. */ - if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) - { - int len; - acp_to_enc((char_u *)lf.lfFaceName, (int)strlen(lf.lfFaceName), - (char_u **)&font_name, &len); - } - #endif - res = (char *)alloc((unsigned)(strlen(font_name) + 20 - + (charset_name == NULL ? 0 : strlen(charset_name) + 2))); - if (res != NULL) - { - p = res; - /* make a normal font string out of the lf thing:*/ - sprintf((char *)p, "%s:h%d", font_name, pixels_to_points( - lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight, TRUE)); - while (*p) - { - if (*p == ' ') - *p = '_'; - ++p; - } - #ifndef MSWIN16_FASTTEXT - if (lf.lfItalic) - STRCAT(p, ":i"); - if (lf.lfWeight >= FW_BOLD) - STRCAT(p, ":b"); - #endif - if (lf.lfUnderline) - STRCAT(p, ":u"); - if (lf.lfStrikeOut) - STRCAT(p, ":s"); - if (charset_name != NULL) - { - STRCAT(p, ":c"); - STRCAT(p, charset_name); - } - } - - #ifdef FEAT_MBYTE - if (font_name != lf.lfFaceName) - vim_free(font_name); - #endif - return (char_u *)res; - } - - - #ifdef FEAT_MBYTE_IME - /* - * Set correct LOGFONT to IME. Use 'guifontwide' if available, otherwise use - * 'guifont' - */ - static void - update_im_font(void) - { - LOGFONT lf_wide; - - if (p_guifontwide != NULL && *p_guifontwide != NUL - && gui.wide_font != NOFONT - && GetObject((HFONT)gui.wide_font, sizeof(lf_wide), &lf_wide)) - norm_logfont = lf_wide; - else - norm_logfont = sub_logfont; - im_set_font(&norm_logfont); - } - #endif - - #ifdef FEAT_MBYTE - /* - * Handler of gui.wide_font (p_guifontwide) changed notification. - */ - void - gui_mch_wide_font_changed(void) - { - # ifndef MSWIN16_FASTTEXT - LOGFONT lf; - # endif - - # ifdef FEAT_MBYTE_IME - update_im_font(); - # endif - - # ifndef MSWIN16_FASTTEXT - gui_mch_free_font(gui.wide_ital_font); - gui.wide_ital_font = NOFONT; - gui_mch_free_font(gui.wide_bold_font); - gui.wide_bold_font = NOFONT; - gui_mch_free_font(gui.wide_boldital_font); - gui.wide_boldital_font = NOFONT; - - if (gui.wide_font - && GetObject((HFONT)gui.wide_font, sizeof(lf), &lf)) - { - if (!lf.lfItalic) - { - lf.lfItalic = TRUE; - gui.wide_ital_font = get_font_handle(&lf); - lf.lfItalic = FALSE; - } - if (lf.lfWeight < FW_BOLD) - { - lf.lfWeight = FW_BOLD; - gui.wide_bold_font = get_font_handle(&lf); - if (!lf.lfItalic) - { - lf.lfItalic = TRUE; - gui.wide_boldital_font = get_font_handle(&lf); - } - } - } - # endif - } - #endif - - /* - * Initialise vim to use the font with the given name. - * Return FAIL if the font could not be loaded, OK otherwise. - */ - /*ARGSUSED*/ - int - gui_mch_init_font(char_u *font_name, int fontset) - { - LOGFONT lf; - GuiFont font = NOFONT; - char_u *p; - - /* Load the font */ - if (get_logfont(&lf, font_name, NULL, TRUE) == OK) - font = get_font_handle(&lf); - if (font == NOFONT) - return FAIL; - - if (font_name == NULL) - font_name = (char_u *)lf.lfFaceName; - #if defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME) - norm_logfont = lf; - sub_logfont = lf; - #endif - #ifdef FEAT_MBYTE_IME - update_im_font(); - #endif - gui_mch_free_font(gui.norm_font); - gui.norm_font = font; - current_font_height = lf.lfHeight; - GetFontSize(font); - - p = logfont2name(lf); - if (p != NULL) - { - hl_set_font_name(p); - - /* When setting 'guifont' to "*" replace it with the actual font name. - * */ - if (STRCMP(font_name, "*") == 0 && STRCMP(p_guifont, "*") == 0) - { - vim_free(p_guifont); - p_guifont = p; - } - else - vim_free(p); - } - - #ifndef MSWIN16_FASTTEXT - gui_mch_free_font(gui.ital_font); - gui.ital_font = NOFONT; - gui_mch_free_font(gui.bold_font); - gui.bold_font = NOFONT; - gui_mch_free_font(gui.boldital_font); - gui.boldital_font = NOFONT; - - if (!lf.lfItalic) - { - lf.lfItalic = TRUE; - gui.ital_font = get_font_handle(&lf); - lf.lfItalic = FALSE; - } - if (lf.lfWeight < FW_BOLD) - { - lf.lfWeight = FW_BOLD; - gui.bold_font = get_font_handle(&lf); - if (!lf.lfItalic) - { - lf.lfItalic = TRUE; - gui.boldital_font = get_font_handle(&lf); - } - } - #endif - - return OK; - } - - #ifndef WPF_RESTORETOMAXIMIZED - # define WPF_RESTORETOMAXIMIZED 2 /* just in case someone doesn't have it */ - #endif - - /* - * Return TRUE if the GUI window is maximized, filling the whole screen. - */ - int - gui_mch_maximized(void) - { - WINDOWPLACEMENT wp; - - wp.length = sizeof(WINDOWPLACEMENT); - if (GetWindowPlacement(s_hwnd, &wp)) - return wp.showCmd == SW_SHOWMAXIMIZED - || (wp.showCmd == SW_SHOWMINIMIZED - && wp.flags == WPF_RESTORETOMAXIMIZED); - - return 0; - } - - /* - * Called when the font changed while the window is maximized. Compute the - * new Rows and Columns. This is like resizing the window. - */ - void - gui_mch_newfont(void) - { - RECT rect; - - GetWindowRect(s_hwnd, &rect); - if (win_socket_id == 0) - { - gui_resize_shell(rect.right - rect.left - - (GetSystemMetrics(SM_CXFRAME) + - GetSystemMetrics(SM_CXPADDEDBORDER)) * 2, - rect.bottom - rect.top - - (GetSystemMetrics(SM_CYFRAME) + - GetSystemMetrics(SM_CXPADDEDBORDER)) * 2 - - GetSystemMetrics(SM_CYCAPTION) - #ifdef FEAT_MENU - - gui_mswin_get_menu_height(FALSE) - #endif - ); - } - else - { - /* Inside another window, don't use the frame and border. */ - gui_resize_shell(rect.right - rect.left, - rect.bottom - rect.top - #ifdef FEAT_MENU - - gui_mswin_get_menu_height(FALSE) - #endif - ); - } - } - - /* - * Set the window title - */ - /*ARGSUSED*/ - void - gui_mch_settitle( - char_u *title, - char_u *icon) - { - set_window_title(s_hwnd, (title == NULL ? "VIM" : (char *)title)); - } - - #ifdef FEAT_MOUSESHAPE - /* Table for shape IDCs. Keep in sync with the mshape_names[] table in - * misc2.c! */ - static LPCSTR mshape_idcs[] = - { - IDC_ARROW, /* arrow */ - MAKEINTRESOURCE(0), /* blank */ - IDC_IBEAM, /* beam */ - IDC_SIZENS, /* updown */ - IDC_SIZENS, /* udsizing */ - IDC_SIZEWE, /* leftright */ - IDC_SIZEWE, /* lrsizing */ - IDC_WAIT, /* busy */ - #ifdef WIN3264 - IDC_NO, /* no */ - #else - IDC_ICON, /* no */ - #endif - IDC_ARROW, /* crosshair */ - IDC_ARROW, /* hand1 */ - IDC_ARROW, /* hand2 */ - IDC_ARROW, /* pencil */ - IDC_ARROW, /* question */ - IDC_ARROW, /* right-arrow */ - IDC_UPARROW, /* up-arrow */ - IDC_ARROW /* last one */ - }; - - void - mch_set_mouse_shape(int shape) - { - LPCSTR idc; - - if (shape == MSHAPE_HIDE) - ShowCursor(FALSE); - else - { - if (shape >= MSHAPE_NUMBERED) - idc = IDC_ARROW; - else - idc = mshape_idcs[shape]; - #ifdef SetClassLongPtr - SetClassLongPtr(s_textArea, GCLP_HCURSOR, (__int3264)(LONG_PTR)LoadCursor(NULL, idc)); - #else - # ifdef WIN32 - SetClassLong(s_textArea, GCL_HCURSOR, (long_u)LoadCursor(NULL, idc)); - # else /* Win16 */ - SetClassWord(s_textArea, GCW_HCURSOR, (WORD)LoadCursor(NULL, idc)); - # endif - #endif - if (!p_mh) - { - POINT mp; - - /* Set the position to make it redrawn with the new shape. */ - (void)GetCursorPos((LPPOINT)&mp); - (void)SetCursorPos(mp.x, mp.y); - ShowCursor(TRUE); - } - } - } - #endif - - #ifdef FEAT_BROWSE - /* - * The file browser exists in two versions: with "W" uses wide characters, - * without "W" the current codepage. When FEAT_MBYTE is defined and on - * Windows NT/2000/XP the "W" functions are used. - */ - - # if defined(FEAT_MBYTE) && defined(WIN3264) - /* - * Wide version of convert_filter(). - */ - static WCHAR * - convert_filterW(char_u *s) - { - char_u *tmp; - int len; - WCHAR *res; - - tmp = convert_filter(s); - if (tmp == NULL) - return NULL; - len = (int)STRLEN(s) + 3; - res = enc_to_utf16(tmp, &len); - vim_free(tmp); - return res; - } - - /* - * Wide version of gui_mch_browse(). Keep in sync! - */ - static char_u * - gui_mch_browseW( - int saving, - char_u *title, - char_u *dflt, - char_u *ext, - char_u *initdir, - char_u *filter) - { - /* We always use the wide function. This means enc_to_utf16() must work, - * otherwise it fails miserably! */ - OPENFILENAMEW fileStruct; - WCHAR fileBuf[MAXPATHL]; - WCHAR *wp; - int i; - WCHAR *titlep = NULL; - WCHAR *extp = NULL; - WCHAR *initdirp = NULL; - WCHAR *filterp; - char_u *p; - - if (dflt == NULL) - fileBuf[0] = NUL; - else - { - wp = enc_to_utf16(dflt, NULL); - if (wp == NULL) - fileBuf[0] = NUL; - else - { - for (i = 0; wp[i] != NUL && i < MAXPATHL - 1; ++i) - fileBuf[i] = wp[i]; - fileBuf[i] = NUL; - vim_free(wp); - } - } - - /* Convert the filter to Windows format. */ - filterp = convert_filterW(filter); - - vim_memset(&fileStruct, 0, sizeof(OPENFILENAMEW)); - #ifdef OPENFILENAME_SIZE_VERSION_400 - /* be compatible with Windows NT 4.0 */ - /* TODO: what to use for OPENFILENAMEW??? */ - fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400; - #else - fileStruct.lStructSize = sizeof(fileStruct); - #endif - - if (title != NULL) - titlep = enc_to_utf16(title, NULL); - fileStruct.lpstrTitle = titlep; - - if (ext != NULL) - extp = enc_to_utf16(ext, NULL); - fileStruct.lpstrDefExt = extp; - - fileStruct.lpstrFile = fileBuf; - fileStruct.nMaxFile = MAXPATHL; - fileStruct.lpstrFilter = filterp; - fileStruct.hwndOwner = s_hwnd; /* main Vim window is owner*/ - /* has an initial dir been specified? */ - if (initdir != NULL && *initdir != NUL) - { - /* Must have backslashes here, no matter what 'shellslash' says */ - initdirp = enc_to_utf16(initdir, NULL); - if (initdirp != NULL) - { - for (wp = initdirp; *wp != NUL; ++wp) - if (*wp == '/') - *wp = '\\'; - } - fileStruct.lpstrInitialDir = initdirp; - } - - /* - * TODO: Allow selection of multiple files. Needs another arg to this - * function to ask for it, and need to use OFN_ALLOWMULTISELECT below. - * Also, should we use OFN_FILEMUSTEXIST when opening? Vim can edit on - * files that don't exist yet, so I haven't put it in. What about - * OFN_PATHMUSTEXIST? - * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog. - */ - fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY); - #ifdef FEAT_SHORTCUT - if (curbuf->b_p_bin) - fileStruct.Flags |= OFN_NODEREFERENCELINKS; - #endif - if (saving) - { - if (!GetSaveFileNameW(&fileStruct)) - return NULL; - } - else - { - if (!GetOpenFileNameW(&fileStruct)) - return NULL; - } - - vim_free(filterp); - vim_free(initdirp); - vim_free(titlep); - vim_free(extp); - - /* Convert from UCS2 to 'encoding'. */ - p = utf16_to_enc(fileBuf, NULL); - if (p != NULL) - /* when out of memory we get garbage for non-ASCII chars */ - STRCPY(fileBuf, p); - vim_free(p); - - /* Give focus back to main window (when using MDI). */ - SetFocus(s_hwnd); - - /* Shorten the file name if possible */ - return vim_strsave(shorten_fname1((char_u *)fileBuf)); - } - # endif /* FEAT_MBYTE */ - - - /* - * Convert the string s to the proper format for a filter string by replacing - * the \t and \n delimiters with \0. - * Returns the converted string in allocated memory. - * - * Keep in sync with convert_filterW() above! - */ - static char_u * - convert_filter(char_u *s) - { - char_u *res; - unsigned s_len = (unsigned)STRLEN(s); - unsigned i; - - res = alloc(s_len + 3); - if (res != NULL) - { - for (i = 0; i < s_len; ++i) - if (s[i] == '\t' || s[i] == '\n') - res[i] = '\0'; - else - res[i] = s[i]; - res[s_len] = NUL; - /* Add two extra NULs to make sure it's properly terminated. */ - res[s_len + 1] = NUL; - res[s_len + 2] = NUL; - } - return res; - } - - /* - * Select a directory. - */ - char_u * - gui_mch_browsedir(char_u *title, char_u *initdir) - { - /* We fake this: Use a filter that doesn't select anything and a default - * file name that won't be used. */ - return gui_mch_browse(0, title, (char_u *)_("Not Used"), NULL, - initdir, (char_u *)_("Directory\t*.nothing\n")); - } - - /* - * Pop open a file browser and return the file selected, in allocated memory, - * or NULL if Cancel is hit. - * saving - TRUE if the file will be saved to, FALSE if it will be opened. - * title - Title message for the file browser dialog. - * dflt - Default name of file. - * ext - Default extension to be added to files without extensions. - * initdir - directory in which to open the browser (NULL = current dir) - * filter - Filter for matched files to choose from. - * - * Keep in sync with gui_mch_browseW() above! - */ - char_u * - gui_mch_browse( - int saving, - char_u *title, - char_u *dflt, - char_u *ext, - char_u *initdir, - char_u *filter) - { - OPENFILENAME fileStruct; - char_u fileBuf[MAXPATHL]; - char_u *initdirp = NULL; - char_u *filterp; - char_u *p; - - # if defined(FEAT_MBYTE) && defined(WIN3264) - if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT) - return gui_mch_browseW(saving, title, dflt, ext, initdir, filter); - # endif - - if (dflt == NULL) - fileBuf[0] = NUL; - else - vim_strncpy(fileBuf, dflt, MAXPATHL - 1); - - /* Convert the filter to Windows format. */ - filterp = convert_filter(filter); - - vim_memset(&fileStruct, 0, sizeof(OPENFILENAME)); - #ifdef OPENFILENAME_SIZE_VERSION_400 - /* be compatible with Windows NT 4.0 */ - fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400; - #else - fileStruct.lStructSize = sizeof(fileStruct); - #endif - - fileStruct.lpstrTitle = (LPSTR)title; - fileStruct.lpstrDefExt = (LPSTR)ext; - - fileStruct.lpstrFile = (LPSTR)fileBuf; - fileStruct.nMaxFile = MAXPATHL; - fileStruct.lpstrFilter = (LPSTR)filterp; - fileStruct.hwndOwner = s_hwnd; /* main Vim window is owner*/ - /* has an initial dir been specified? */ - if (initdir != NULL && *initdir != NUL) - { - /* Must have backslashes here, no matter what 'shellslash' says */ - initdirp = vim_strsave(initdir); - if (initdirp != NULL) - for (p = initdirp; *p != NUL; ++p) - if (*p == '/') - *p = '\\'; - fileStruct.lpstrInitialDir = (LPSTR)initdirp; - } - - /* - * TODO: Allow selection of multiple files. Needs another arg to this - * function to ask for it, and need to use OFN_ALLOWMULTISELECT below. - * Also, should we use OFN_FILEMUSTEXIST when opening? Vim can edit on - * files that don't exist yet, so I haven't put it in. What about - * OFN_PATHMUSTEXIST? - * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog. - */ - fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY); - #ifdef FEAT_SHORTCUT - if (curbuf->b_p_bin) - fileStruct.Flags |= OFN_NODEREFERENCELINKS; - #endif - if (saving) - { - if (!GetSaveFileName(&fileStruct)) - return NULL; - } - else - { - if (!GetOpenFileName(&fileStruct)) - return NULL; - } - - vim_free(filterp); - vim_free(initdirp); - - /* Give focus back to main window (when using MDI). */ - SetFocus(s_hwnd); - - /* Shorten the file name if possible */ - return vim_strsave(shorten_fname1((char_u *)fileBuf)); - } - #endif /* FEAT_BROWSE */ - - /*ARGSUSED*/ - static void - _OnDropFiles( - HWND hwnd, - HDROP hDrop) - { - #ifdef FEAT_WINDOWS - #ifdef WIN3264 - # define BUFPATHLEN _MAX_PATH - # define DRAGQVAL 0xFFFFFFFF - #else - # define BUFPATHLEN MAXPATHL - # define DRAGQVAL 0xFFFF - #endif - #ifdef FEAT_MBYTE - WCHAR wszFile[BUFPATHLEN]; - #endif - char szFile[BUFPATHLEN]; - UINT cFiles = DragQueryFile(hDrop, DRAGQVAL, NULL, 0); - UINT i; - char_u **fnames; - POINT pt; - int_u modifiers = 0; - - /* TRACE("_OnDropFiles: %d files dropped\n", cFiles); */ - - /* Obtain dropped position */ - DragQueryPoint(hDrop, &pt); - MapWindowPoints(s_hwnd, s_textArea, &pt, 1); - - reset_VIsual(); - - fnames = (char_u **)alloc(cFiles * sizeof(char_u *)); - - if (fnames != NULL) - for (i = 0; i < cFiles; ++i) - { - #ifdef FEAT_MBYTE - if (DragQueryFileW(hDrop, i, wszFile, BUFPATHLEN) > 0) - fnames[i] = utf16_to_enc(wszFile, NULL); - else - #endif - { - DragQueryFile(hDrop, i, szFile, BUFPATHLEN); - fnames[i] = vim_strsave((char_u *)szFile); - } - } - - DragFinish(hDrop); - - if (fnames != NULL) - { - if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) - modifiers |= MOUSE_SHIFT; - if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) - modifiers |= MOUSE_CTRL; - if ((GetKeyState(VK_MENU) & 0x8000) != 0) - modifiers |= MOUSE_ALT; - - gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles); - - s_need_activate = TRUE; - } - #endif - } - - /*ARGSUSED*/ - static int - _OnScroll( - HWND hwnd, - HWND hwndCtl, - UINT code, - int pos) - { - static UINT prev_code = 0; /* code of previous call */ - scrollbar_T *sb, *sb_info; - long val; - int dragging = FALSE; - int dont_scroll_save = dont_scroll; - #ifndef WIN3264 - int nPos; - #else - SCROLLINFO si; - - si.cbSize = sizeof(si); - si.fMask = SIF_POS; - #endif - - sb = gui_mswin_find_scrollbar(hwndCtl); - if (sb == NULL) - return 0; - - if (sb->wp != NULL) /* Left or right scrollbar */ - { - /* - * Careful: need to get scrollbar info out of first (left) scrollbar - * for window, but keep real scrollbar too because we must pass it to - * gui_drag_scrollbar(). - */ - sb_info = &sb->wp->w_scrollbars[0]; - } - else /* Bottom scrollbar */ - sb_info = sb; - val = sb_info->value; - - switch (code) - { - case SB_THUMBTRACK: - val = pos; - dragging = TRUE; - if (sb->scroll_shift > 0) - val <<= sb->scroll_shift; - break; - case SB_LINEDOWN: - val++; - break; - case SB_LINEUP: - val--; - break; - case SB_PAGEDOWN: - val += (sb_info->size > 2 ? sb_info->size - 2 : 1); - break; - case SB_PAGEUP: - val -= (sb_info->size > 2 ? sb_info->size - 2 : 1); - break; - case SB_TOP: - val = 0; - break; - case SB_BOTTOM: - val = sb_info->max; - break; - case SB_ENDSCROLL: - if (prev_code == SB_THUMBTRACK) - { - /* - * "pos" only gives us 16-bit data. In case of large file, - * use GetScrollPos() which returns 32-bit. Unfortunately it - * is not valid while the scrollbar is being dragged. - */ - val = GetScrollPos(hwndCtl, SB_CTL); - if (sb->scroll_shift > 0) - val <<= sb->scroll_shift; - } - break; - - default: - /* TRACE("Unknown scrollbar event %d\n", code); */ - return 0; - } - prev_code = code; - - #ifdef WIN3264 - si.nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val; - SetScrollInfo(hwndCtl, SB_CTL, &si, TRUE); - #else - nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val; - SetScrollPos(hwndCtl, SB_CTL, nPos, TRUE); - #endif - - /* - * When moving a vertical scrollbar, move the other vertical scrollbar too. - */ - if (sb->wp != NULL) - { - scrollbar_T *sba = sb->wp->w_scrollbars; - HWND id = sba[ (sb == sba + SBAR_LEFT) ? SBAR_RIGHT : SBAR_LEFT].id; - - #ifdef WIN3264 - SetScrollInfo(id, SB_CTL, &si, TRUE); - #else - SetScrollPos(id, SB_CTL, nPos, TRUE); - #endif - } - - /* Don't let us be interrupted here by another message. */ - s_busy_processing = TRUE; - - /* When "allow_scrollbar" is FALSE still need to remember the new - * position, but don't actually scroll by setting "dont_scroll". */ - dont_scroll = !allow_scrollbar; - - gui_drag_scrollbar(sb, val, dragging); - - s_busy_processing = FALSE; - dont_scroll = dont_scroll_save; - - return 0; - } - - - /* - * Get command line arguments. - * Use "prog" as the name of the program and "cmdline" as the arguments. - * Copy the arguments to allocated memory. - * Return the number of arguments (including program name). - * Return pointers to the arguments in "argvp". Memory is allocated with - * malloc(), use free() instead of vim_free(). - * Return pointer to buffer in "tofree". - * Returns zero when out of memory. - */ - /*ARGSUSED*/ - int - get_cmd_args(char *prog, char *cmdline, char ***argvp, char **tofree) - { - int i; - char *p; - char *progp; - char *pnew = NULL; - char *newcmdline; - int inquote; - int argc; - char **argv = NULL; - int round; - - *tofree = NULL; - - #ifdef FEAT_MBYTE - /* Try using the Unicode version first, it takes care of conversion when - * 'encoding' is changed. */ - argc = get_cmd_argsW(&argv); - if (argc != 0) - goto done; - #endif - - /* Handle the program name. Remove the ".exe" extension, and find the 1st - * non-space. */ - p = strrchr(prog, '.'); - if (p != NULL) - *p = NUL; - for (progp = prog; *progp == ' '; ++progp) - ; - - /* The command line is copied to allocated memory, so that we can change - * it. Add the size of the string, the separating NUL and a terminating - * NUL. */ - newcmdline = malloc(STRLEN(cmdline) + STRLEN(progp) + 2); - if (newcmdline == NULL) - return 0; - - /* - * First round: count the number of arguments ("pnew" == NULL). - * Second round: produce the arguments. - */ - for (round = 1; round <= 2; ++round) - { - /* First argument is the program name. */ - if (pnew != NULL) - { - argv[0] = pnew; - strcpy(pnew, progp); - pnew += strlen(pnew); - *pnew++ = NUL; - } - - /* - * Isolate each argument and put it in argv[]. - */ - p = cmdline; - argc = 1; - while (*p != NUL) - { - inquote = FALSE; - if (pnew != NULL) - argv[argc] = pnew; - ++argc; - while (*p != NUL && (inquote || (*p != ' ' && *p != '\t'))) - { - /* Backslashes are only special when followed by a double - * quote. */ - i = (int)strspn(p, "\\"); - if (p[i] == '"') - { - /* Halve the number of backslashes. */ - if (i > 1 && pnew != NULL) - { - vim_memset(pnew, '\\', i / 2); - pnew += i / 2; - } - - /* Even nr of backslashes toggles quoting, uneven copies - * the double quote. */ - if ((i & 1) == 0) - inquote = !inquote; - else if (pnew != NULL) - *pnew++ = '"'; - p += i + 1; - } - else if (i > 0) - { - /* Copy span of backslashes unmodified. */ - if (pnew != NULL) - { - vim_memset(pnew, '\\', i); - pnew += i; - } - p += i; - } - else - { - if (pnew != NULL) - *pnew++ = *p; - #ifdef FEAT_MBYTE - /* Can't use mb_* functions, because 'encoding' is not - * initialized yet here. */ - if (IsDBCSLeadByte(*p)) - { - ++p; - if (pnew != NULL) - *pnew++ = *p; - } - #endif - ++p; - } - } - - if (pnew != NULL) - *pnew++ = NUL; - while (*p == ' ' || *p == '\t') - ++p; /* advance until a non-space */ - } - - if (round == 1) - { - argv = (char **)malloc((argc + 1) * sizeof(char *)); - if (argv == NULL ) - { - free(newcmdline); - return 0; /* malloc error */ - } - pnew = newcmdline; - *tofree = newcmdline; - } - } - - #ifdef FEAT_MBYTE - done: - #endif - argv[argc] = NULL; /* NULL-terminated list */ - *argvp = argv; - return argc; - } --- 0 ---- *** ../vim-7.4.1363/src/Make_w16.mak 2016-01-01 17:56:13.405342815 +0100 --- src/Make_w16.mak 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,204 **** - # - # Borland C++ 5.0[12] makefile for vim, 16-bit windows gui version - # By Vince Negri - # - # NOTE: THIS IS OLD AND PROBABLY NO LONGER WORKS. - # - # ************************************************************* - # * WARNING! - # * This was originally produced by the IDE, but has since been - # * modified to make it work properly. Adjust with care! - # * In particular, leave LinkerLocalOptsAtW16_gvim16dexe alone - # * unless you are a guru. - # ************************************************************* - # - # Look for BOR below and either pass a different value or - # adjust the path as required. For example - # make -fMake_w16.mak -DBOR=C:\PF\Borland\BC5.01 -B BccW16.cfg - # make -fMake_w16.mak - # Note: $(BOR) is effectively ignored unless BccW16.cfg is rebuilt. - # - # Does not compile with Borland C++ 4.51 Walter Briscoe 2003-02-24 - # "out of memory" from compiler if gvim16 wildly wrong. WFB 2003-03-04 - # - # vim16.def must be a DOS-formatted file. (\r\n line endings.) - # It is a UNIX-formatted file (\n line endings) in vim-*-extra.tar.gz - - .AUTODEPEND - - # - # Borland C++ tools - # - IMPLIB = Implib - BCC = Bcc +BccW16.cfg - TLINK = TLink - TLIB = TLib - BRC = Brc - TASM = Tasm - # - # IDE macros - # - - # - # Options - # - !ifndef BOR - BOR = D:\BC5 - !endif - - # !ifndef INTDIR is lethal considering CLEAN below. WFB 2003-03-13 - INTDIR=w16 - - # /Twe Make the target a Windows .EXE with explicit functions exportable + - # /x Map file off - # /l Include source line numbers in object map files` - # /c case sensitive link - # /C Case-sensitive exports and imports (16-bit only) - # /k Produce "No Stack" warning. - # /Oa Minimise segment alignment - # /Oc Minimise Chain fixes - # /Oi Minimise Iterated data - # /Or Minimise resource alignment - # /P -P=x Code pack size - # /V Windows version for application - # /L Folder to search for library files - LinkerLocalOptsAtW16_gvim16dexe =/Twe/x/l/c/C/k/Or/Oc/Oa/Oi/P=65535/V3.10 - - CompInheritOptsAt_gvim16dexe = \ - -I$(BOR)\INCLUDE;PROTO;. \ - -DFEAT_GUI;FEAT_GUI_MSWIN;FEAT_GUI_W16;MSWIN;WIN16;MSWIN16_FASTTEXT \ - -DFEAT_TOOLBAR;WIN16_3DLOOK - - # - # Dependency List - # - Dep_Gvim16 = \ - gvim16.exe - - ObjFiles = \ - $(INTDIR)\buffer.obj\ - $(INTDIR)\charset.obj\ - $(INTDIR)\diff.obj\ - $(INTDIR)\digraph.obj\ - $(INTDIR)\edit.obj\ - $(INTDIR)\eval.obj\ - $(INTDIR)\ex_cmds.obj\ - $(INTDIR)\ex_cmds2.obj\ - $(INTDIR)\ex_docmd.obj\ - $(INTDIR)\ex_eval.obj\ - $(INTDIR)\ex_getln.obj\ - $(INTDIR)\fileio.obj\ - $(INTDIR)\fold.obj\ - $(INTDIR)\getchar.obj\ - $(INTDIR)\hardcopy.obj\ - $(INTDIR)\hashtab.obj\ - $(INTDIR)\gui.obj\ - $(INTDIR)\gui_w16.obj\ - $(INTDIR)\main.obj\ - $(INTDIR)\mark.obj\ - $(INTDIR)\mbyte.obj\ - $(INTDIR)\memfile.obj\ - $(INTDIR)\memline.obj\ - $(INTDIR)\menu.obj\ - $(INTDIR)\message.obj\ - $(INTDIR)\misc1.obj\ - $(INTDIR)\misc2.obj\ - $(INTDIR)\move.obj\ - $(INTDIR)\normal.obj\ - $(INTDIR)\ops.obj\ - $(INTDIR)\option.obj\ - $(INTDIR)\os_win16.obj\ - $(INTDIR)\os_msdos.obj\ - $(INTDIR)\os_mswin.obj\ - $(INTDIR)\winclip.obj\ - $(INTDIR)\popupmnu.obj\ - $(INTDIR)\quickfix.obj\ - $(INTDIR)\regexp.obj\ - $(INTDIR)\screen.obj\ - $(INTDIR)\search.obj\ - $(INTDIR)\spell.obj\ - $(INTDIR)\syntax.obj\ - $(INTDIR)\tag.obj\ - $(INTDIR)\term.obj\ - $(INTDIR)\ui.obj\ - $(INTDIR)\undo.obj\ - $(INTDIR)\version.obj\ - $(INTDIR)\window.obj - - Dep_gvim16dexe = \ - vimtbar.lib\ - vim16.def\ - $(INTDIR)\vim16.res\ - $(ObjFiles) - - # Without the following, the implicit rule in BUILTINS.MAK is picked up - # for a rule for .c.obj rather than the local implicit rule - .SUFFIXES - .SUFFIXES .c .obj - .path.c = . - - # -P- Force C++ compilation off - # -c Compilation only - # -n Place .OBJ files - {.}.c{$(INTDIR)}.obj: - $(BCC) -P- -c -n$(INTDIR)\ {$< } - - Gvim16 : BccW16.cfg $(Dep_Gvim16) - echo MakeNode - - gvim16.exe : $(Dep_gvim16dexe) - $(TLINK) $(LinkerLocalOptsAtW16_gvim16dexe) @&&| - c0wl.obj $(ObjFiles) - |,$*,,vimtbar ctl3dv2 import cwl, vim16.def,$(INTDIR)\vim16.res - - # Force objects to be built if $(BOR) changes - $(ObjFiles) : Make_w16.mak BccW16.cfg - - $(INTDIR)\vim16.res : vim16.rc - $(BRC) -R @&&| - $(CompInheritOptsAt_gvim16dexe) -fo$*.res $? - | - - - # Compiler configuration file - # There is no rule for $(INTDIR) as make always says it does not exist - BccW16.cfg : - -@if not exist $(INTDIR)\$(NULL) mkdir $(INTDIR) - Copy &&| - -3 ; Generate 80386 protected-mode compatible instructions - -a ; Byte alignment - -dc ; Move string literals from data segment to code segment - -ff ; Fast floating point - -H ; Generate and use precompiled headers - -H=$(INTDIR)\gvim16.csm ; gvim16.csm is the precompiled header filename - -k- ; No standard stack frame - -ml ; Large memory model - -OW ; Suppress the inc bp/dec bp on windows far functions - -O1 ; Generate smallest possible code - -O2 ; Generate fastest possible code (overrides prior -O1 control) - -pr ; Fastcall calling convention passing parameters in registers - -R- ; Exclude browser information in generated .OBJ files - -v- ; Turn off source debugging - -vi ; Turn inline function expansion on - -WE ; Only __far _export functions are exported - -w ; Display warnings - -w-par ; Suppress: Parameter 'parameter' is never used - -w-pch ; Cannot create pre-compiled header: initialized data in header - -w-sig ; identifier' declared but never used - -w-ucp ; Mixing pointers to different 'char' types - -wuse ; 'identifier' declared but never used - $(CompInheritOptsAt_gvim16dexe) - | $@ - - !IF "$(OS)" == "Windows_NT" - NULL= - DEL_TREE = rmdir /s /q - !ELSE - NULL=nul - DEL_TREE = deltree /y - !ENDIF - - CLEAN: - -@if exist $(INTDIR)\$(NULL) $(DEL_TREE) $(INTDIR) - -@if exist BccW16.cfg erase BccW16.cfg - -@if exist gvim16.exe erase gvim16.exe --- 0 ---- *** ../vim-7.4.1363/src/Makefile 2016-02-03 21:45:23.587069590 +0100 --- src/Makefile 2016-02-20 13:39:21.634679219 +0100 *************** *** 1336,1342 **** # All GUI files ALL_GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_motif.c gui_xmdlg.c gui_xmebw.c gui_athena.c gui_gtk_x11.c gui_x11.c gui_at_sb.c gui_at_fs.c pty.c ! ALL_GUI_PRO = gui.pro gui_gtk.pro gui_motif.pro gui_xmdlg.pro gui_athena.pro gui_gtk_x11.pro gui_x11.pro gui_w16.pro gui_w32.pro gui_photon.pro # }}} --- 1336,1342 ---- # All GUI files ALL_GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_motif.c gui_xmdlg.c gui_xmebw.c gui_athena.c gui_gtk_x11.c gui_x11.c gui_at_sb.c gui_at_fs.c pty.c ! ALL_GUI_PRO = gui.pro gui_gtk.pro gui_motif.pro gui_xmdlg.pro gui_athena.pro gui_gtk_x11.pro gui_x11.pro gui_w32.pro gui_photon.pro # }}} *************** *** 1715,1721 **** # Resources used for the Mac are in one directory. RSRC_DIR = os_mac_rsrc ! PRO_MANUAL = os_amiga.pro os_msdos.pro os_win16.pro os_win32.pro \ os_mswin.pro winclip.pro os_beos.pro os_vms.pro $(PERL_PRO) # Default target is making the executable and tools --- 1715,1721 ---- # Resources used for the Mac are in one directory. RSRC_DIR = os_mac_rsrc ! PRO_MANUAL = os_amiga.pro os_msdos.pro os_win32.pro \ os_mswin.pro winclip.pro os_beos.pro os_vms.pro $(PERL_PRO) # Default target is making the executable and tools *************** *** 1868,1887 **** $(CPROTO) -DMSDOS -UHAVE_CONFIG_H $< > proto/$@ echo "/* vim: set ft=c : */" >> proto/$@ - os_win16.pro: os_win16.c - $(CPROTO) -DWIN16 -UHAVE_CONFIG_H $< > proto/$@ - echo "/* vim: set ft=c : */" >> proto/$@ - os_win32.pro: os_win32.c $(CPROTO) -DWIN32 -UHAVE_CONFIG_H $< > proto/$@ echo "/* vim: set ft=c : */" >> proto/$@ os_mswin.pro: os_mswin.c ! $(CPROTO) -DWIN16 -DWIN32 -UHAVE_CONFIG_H $< > proto/$@ echo "/* vim: set ft=c : */" >> proto/$@ winclip.pro: winclip.c ! $(CPROTO) -DWIN16 -DWIN32 -UHAVE_CONFIG_H $< > proto/$@ echo "/* vim: set ft=c : */" >> proto/$@ os_beos.pro: os_beos.c --- 1868,1883 ---- $(CPROTO) -DMSDOS -UHAVE_CONFIG_H $< > proto/$@ echo "/* vim: set ft=c : */" >> proto/$@ os_win32.pro: os_win32.c $(CPROTO) -DWIN32 -UHAVE_CONFIG_H $< > proto/$@ echo "/* vim: set ft=c : */" >> proto/$@ os_mswin.pro: os_mswin.c ! $(CPROTO) -DWIN32 -UHAVE_CONFIG_H $< > proto/$@ echo "/* vim: set ft=c : */" >> proto/$@ winclip.pro: winclip.c ! $(CPROTO) -DWIN32 -UHAVE_CONFIG_H $< > proto/$@ echo "/* vim: set ft=c : */" >> proto/$@ os_beos.pro: os_beos.c *************** *** 2025,2030 **** --- 2021,2027 ---- test_menu \ test_perl \ test_quickfix \ + test_reltime \ test_searchpos \ test_set \ test_sort \ *** ../vim-7.4.1363/src/Make_cyg_ming.mak 2016-02-19 19:43:45.775649957 +0100 --- src/Make_cyg_ming.mak 2016-02-20 13:47:20.561700502 +0100 *************** *** 860,866 **** $(OUTDIR)/ex_eval.o: ex_eval.c $(INCL) ex_cmds.h $(CC) -c $(CFLAGS) ex_eval.c -o $(OUTDIR)/ex_eval.o ! $(OUTDIR)/gui_w32.o: gui_w32.c gui_w48.c $(INCL) $(CC) -c $(CFLAGS) gui_w32.c -o $(OUTDIR)/gui_w32.o $(OUTDIR)/gui_dwrite.o: gui_dwrite.cpp $(INCL) gui_dwrite.h --- 860,866 ---- $(OUTDIR)/ex_eval.o: ex_eval.c $(INCL) ex_cmds.h $(CC) -c $(CFLAGS) ex_eval.c -o $(OUTDIR)/ex_eval.o ! $(OUTDIR)/gui_w32.o: gui_w32.c $(INCL) $(CC) -c $(CFLAGS) gui_w32.c -o $(OUTDIR)/gui_w32.o $(OUTDIR)/gui_dwrite.o: gui_dwrite.cpp $(INCL) gui_dwrite.h *** ../vim-7.4.1363/src/Make_mvc.mak 2016-02-19 19:43:45.779649915 +0100 --- src/Make_mvc.mak 2016-02-20 13:47:41.545482662 +0100 *************** *** 1175,1181 **** $(OUTDIR)/gui_beval.obj: $(OUTDIR) gui_beval.c $(INCL) $(GUI_INCL) ! $(OUTDIR)/gui_w32.obj: $(OUTDIR) gui_w32.c gui_w48.c $(INCL) $(GUI_INCL) $(OUTDIR)/gui_dwrite.obj: $(OUTDIR) gui_dwrite.cpp $(INCL) $(GUI_INCL) --- 1175,1181 ---- $(OUTDIR)/gui_beval.obj: $(OUTDIR) gui_beval.c $(INCL) $(GUI_INCL) ! $(OUTDIR)/gui_w32.obj: $(OUTDIR) gui_w32.c $(INCL) $(GUI_INCL) $(OUTDIR)/gui_dwrite.obj: $(OUTDIR) gui_dwrite.cpp $(INCL) $(GUI_INCL) *** ../vim-7.4.1363/src/proto/gui_w16.pro 2016-01-19 13:21:55.837334377 +0100 --- src/proto/gui_w16.pro 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,80 **** - /* gui_w16.c */ - void gui_mch_set_blinking(long wait, long on, long off); - void gui_mch_stop_blink(void); - void gui_mch_start_blink(void); - LRESULT WINAPI vim_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); - void gui_mch_new_colors(void); - void gui_mch_def_colors(void); - int gui_mch_open(void); - int gui_mch_get_winpos(int *x, int *y); - void gui_mch_set_winpos(int x, int y); - void gui_mch_set_text_area_pos(int x, int y, int w, int h); - void gui_mch_enable_scrollbar(scrollbar_T *sb, int flag); - void gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h); - void gui_mch_create_scrollbar(scrollbar_T *sb, int orient); - int gui_mch_adjust_charheight(void); - GuiFont gui_mch_get_font(char_u *name, int giveErrorIfMissing); - char_u *gui_mch_get_fontname(GuiFont font, char_u *name); - void gui_mch_free_font(GuiFont font); - guicolor_T gui_mch_get_color(char_u *name); - int gui_mch_haskey(char_u *name); - void gui_mch_beep(void); - void gui_mch_invert_rectangle(int r, int c, int nr, int nc); - void gui_mch_iconify(void); - void gui_mch_draw_hollow_cursor(guicolor_T color); - void gui_mch_draw_part_cursor(int w, int h, guicolor_T color); - void gui_mch_update(void); - int gui_mch_wait_for_chars(int wtime); - void gui_mch_clear_block(int row1, int col1, int row2, int col2); - void gui_mch_clear_all(void); - void gui_mch_enable_menu(int flag); - void gui_mch_set_menu_pos(int x, int y, int w, int h); - void gui_mch_menu_hidden(vimmenu_T *menu, int hidden); - void gui_mch_draw_menubar(void); - long_u gui_mch_get_rgb(guicolor_T pixel); - void gui_mch_activate_window(void); - void gui_mch_show_toolbar(int showit); - void gui_mch_show_tabline(int showit); - int gui_mch_showing_tabline(void); - void gui_mch_update_tabline(void); - void gui_mch_set_curtab(int nr); - void ex_simalt(exarg_T *eap); - void gui_mch_find_dialog(exarg_T *eap); - void gui_mch_replace_dialog(exarg_T *eap); - void gui_mch_mousehide(int hide); - void gui_mch_destroy_scrollbar(scrollbar_T *sb); - void gui_mch_getmouse(int *x, int *y); - void gui_mch_setmouse(int x, int y); - void gui_mch_flash(int msec); - void gui_mch_delete_lines(int row, int num_lines); - void gui_mch_insert_lines(int row, int num_lines); - void gui_mch_exit(int rc); - void gui_mch_wide_font_changed(void); - int gui_mch_init_font(char_u *font_name, int fontset); - int gui_mch_maximized(void); - void gui_mch_newfont(void); - void gui_mch_settitle(char_u *title, char_u *icon); - void mch_set_mouse_shape(int shape); - char_u *gui_mch_browsedir(char_u *title, char_u *initdir); - char_u *gui_mch_browse(int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter); - int get_cmd_args(char *prog, char *cmdline, char ***argvp, char **tofree); - void gui_mch_prepare(int *argc, char **argv); - int gui_mch_init(void); - void gui_mch_set_shellsize(int width, int height, int min_width, int min_height, int base_width, int base_height, int direction); - void gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max); - void gui_mch_set_font(GuiFont font); - void gui_mch_set_fg_color(guicolor_T color); - void gui_mch_set_bg_color(guicolor_T color); - 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); - void gui_mch_flush(void); - void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h); - void gui_mch_add_menu(vimmenu_T *menu, int pos); - void gui_mch_show_popupmenu(vimmenu_T *menu); - void gui_make_popup(char_u *path_name, int mouse_pos); - void gui_mch_add_menu_item(vimmenu_T *menu, int idx); - void gui_mch_destroy_menu(vimmenu_T *menu); - void gui_mch_menu_grey(vimmenu_T *menu, int grey); - int gui_mch_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd); - void gui_mch_set_foreground(void); - /* vim: set ft=c : */ --- 0 ---- *** ../vim-7.4.1363/src/guiw16rc.h 2010-05-15 13:04:11.000000000 +0200 --- src/guiw16rc.h 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,17 **** - - #define IDR_VIM 150 - - #define IDR_VIM_ERROR 151 - #define IDR_VIM_ALERT 152 - #define IDR_VIM_INFO 153 - #define IDR_VIM_QUESTION 154 - - #define IDR_ICOBUDDYBASE 200 - - #define IDR_ICOBUDDY_DEF1 (IDR_ICOBUDDYBASE + 3) - #define IDR_ICOBUDDY_DEF2 (IDR_ICOBUDDYBASE + 0) - #define IDR_ICOBUDDY_DEF3 (IDR_ICOBUDDYBASE + 1) - #define IDR_ICOBUDDY_DEF4 (IDR_ICOBUDDYBASE + 2) - - #define IDR_ICOBUDDY_GRIN (IDR_ICOBUDDYBASE + 4) - #define IDR_ICOBUDDY_ALARM (IDR_ICOBUDDYBASE + 5) --- 0 ---- *** ../vim-7.4.1363/src/vim16.rc 2013-07-08 20:39:05.000000000 +0200 --- src/vim16.rc 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,81 **** - // vim:ts=8:sw=4:sts=4: - // - // VIM - Vi IMproved by Bram Moolenaar - // - // Do ":help uganda" in Vim to read copying and usage conditions. - // Do ":help credits" in Vim to see a list of people who contributed. - - // vim.rc - // Icon and version information for the Win32 version of Vim - // Must be in DOS format ! - - #include "version.h" - #include "gui_w3~1.h" - #include "guiw16rc.h" - - // - // Icons - // - IDR_VIM ICON "VIM.ICO" - - #ifndef FEAT_TINY - IDR_VIM_ERROR ICON "VIM_ER~1.ICO" - IDR_VIM_ALERT ICON "VIM_AL~1.ICO" - IDR_VIM_INFO ICON "VIM_INFO.ICO" - IDR_VIM_QUESTION ICON "VIM_QU~1.ICO" - #endif - - // - // Bitmaps - // - #ifdef FEAT_TOOLBAR - IDR_TOOLBAR1 BITMAP DISCARDABLE "tools16.bmp" - #endif - // - // Version - // - - VS_VERSION_INFO VERSIONINFO - FILEVERSION VIM_VERSION_MAJOR,VIM_VERSION_MINOR,VIM_VERSION_BUILD,VIM_VERSION_PATCHLEVEL - PRODUCTVERSION VIM_VERSION_MAJOR,VIM_VERSION_MINOR,VIM_VERSION_BUILD,VIM_VERSION_PATCHLEVEL - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - - #if VIM_VERSION_PATCHLEVEL > 0 - #ifdef _DEBUG - FILEFLAGS VS_FF_PRERELEASE | VS_FF_DEBUG | VS_FF_PATCHED - #else - FILEFLAGS VS_FF_PRERELEASE | VS_FF_PATCHED - #endif - #else - #ifdef _DEBUG - FILEFLAGS VS_FF_PRERELEASE | VS_FF_DEBUG - #else - FILEFLAGS VS_FF_PRERELEASE - #endif - #endif - - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L - BEGIN - BLOCK "StringFileInfo" - BEGIN - // 0x0409 == U.S. English; 0x04E4 => Windows Multilingual - BLOCK "040904E4" - BEGIN - VALUE "CompanyName", "Vim Developers\0" - VALUE "FileDescription", "Vi Improved - A Text Editor\0" - VALUE "FileVersion", VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR "\0" - VALUE "InternalName", "VIM\0" - VALUE "LegalCopyright", "Copyright \251 1996\0" - VALUE "LegalTrademarks", "Vim\0" - VALUE "OriginalFilename", "VIM.EXE\0" - VALUE "ProductName", "Vim\0" - VALUE "ProductVersion", VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 0x4E4 - END - END --- 0 ---- *** ../vim-7.4.1363/src/vim16.def 2013-08-10 13:25:08.000000000 +0200 --- src/vim16.def 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,5 **** - CODE PRELOAD EXECUTEONLY - DATA MULTIPLE SHARED - DESCRIPTION 'Vim 7.4' - STACKSIZE 16000 - HEAPSIZE 10000 --- 0 ---- *** ../vim-7.4.1363/src/eval.c 2016-02-19 23:31:36.347601232 +0100 --- src/eval.c 2016-02-20 13:23:50.152365095 +0100 *************** *** 13235,13243 **** #ifdef VMS "vms", #endif - #ifdef WIN16 - "win16", - #endif #ifdef WIN32 "win32", #endif --- 13235,13240 ---- *** ../vim-7.4.1363/src/gui.c 2016-01-30 16:39:20.434376524 +0100 --- src/gui.c 2016-02-20 13:24:53.755703791 +0100 *************** *** 2184,2190 **** guicolor_T fg_color; guicolor_T bg_color; guicolor_T sp_color; ! #if !defined(MSWIN16_FASTTEXT) && !defined(FEAT_GUI_GTK) GuiFont font = NOFONT; # ifdef FEAT_MBYTE GuiFont wide_font = NOFONT; --- 2184,2190 ---- guicolor_T fg_color; guicolor_T bg_color; guicolor_T sp_color; ! #if !defined(FEAT_GUI_GTK) GuiFont font = NOFONT; # ifdef FEAT_MBYTE GuiFont wide_font = NOFONT; *************** *** 2241,2247 **** highlight_mask = gui.highlight_mask; hl_mask_todo = highlight_mask; ! #if !defined(MSWIN16_FASTTEXT) && !defined(FEAT_GUI_GTK) /* Set the font */ if (aep != NULL && aep->ae_u.gui.font != NOFONT) font = aep->ae_u.gui.font; --- 2241,2247 ---- highlight_mask = gui.highlight_mask; hl_mask_todo = highlight_mask; ! #if !defined(FEAT_GUI_GTK) /* Set the font */ if (aep != NULL && aep->ae_u.gui.font != NOFONT) font = aep->ae_u.gui.font; *************** *** 2358,2368 **** clip_may_clear_selection(gui.row, gui.row); - #ifndef MSWIN16_FASTTEXT /* If there's no bold font, then fake it */ if (hl_mask_todo & (HL_BOLD | HL_STANDOUT)) draw_flags |= DRAW_BOLD; - #endif /* * When drawing bold or italic characters the spill-over from the left --- 2358,2366 ---- *************** *** 2383,2393 **** draw_flags |= DRAW_UNDERL; #else /* Do we underline the text? */ ! if ((hl_mask_todo & HL_UNDERLINE) ! # ifndef MSWIN16_FASTTEXT ! || (hl_mask_todo & HL_ITALIC) ! # endif ! ) draw_flags |= DRAW_UNDERL; #endif /* Do we undercurl the text? */ --- 2381,2387 ---- draw_flags |= DRAW_UNDERL; #else /* Do we underline the text? */ ! if ((hl_mask_todo & HL_UNDERLINE) || (hl_mask_todo & HL_ITALIC)) draw_flags |= DRAW_UNDERL; #endif /* Do we undercurl the text? */ *************** *** 3338,3344 **** static int prev_footer = -1; int using_footer = FALSE; #endif ! #if defined(FEAT_MENU) && !defined(WIN16) static int prev_tearoff = -1; int using_tearoff = FALSE; #endif --- 3332,3338 ---- static int prev_footer = -1; int using_footer = FALSE; #endif ! #if defined(FEAT_MENU) static int prev_tearoff = -1; int using_tearoff = FALSE; #endif *************** *** 3415,3421 **** break; #endif case GO_TEAROFF: ! #if defined(FEAT_MENU) && !defined(WIN16) using_tearoff = TRUE; #endif break; --- 3409,3415 ---- break; #endif case GO_TEAROFF: ! #if defined(FEAT_MENU) using_tearoff = TRUE; #endif break; *************** *** 3522,3528 **** fix_size = TRUE; } #endif ! #if defined(FEAT_MENU) && !defined(WIN16) && !(defined(WIN3264) && !defined(FEAT_TEAROFF)) if (using_tearoff != prev_tearoff) { gui_mch_toggle_tearoffs(using_tearoff); --- 3516,3522 ---- fix_size = TRUE; } #endif ! #if defined(FEAT_MENU) && !(defined(WIN3264) && !defined(FEAT_TEAROFF)) if (using_tearoff != prev_tearoff) { gui_mch_toggle_tearoffs(using_tearoff); *** ../vim-7.4.1363/src/misc2.c 2016-02-13 23:22:35.089363591 +0100 --- src/misc2.c 2016-02-20 13:25:40.243220440 +0100 *************** *** 1400,1406 **** length = (unsigned)STRLEN(string) + 3; /* two quotes and a trailing NUL */ for (p = string; *p != NUL; mb_ptr_adv(p)) { ! # if defined(WIN32) || defined(WIN16) || defined(DOS) if (!p_ssl) { if (*p == '"') --- 1400,1406 ---- length = (unsigned)STRLEN(string) + 3; /* two quotes and a trailing NUL */ for (p = string; *p != NUL; mb_ptr_adv(p)) { ! # if defined(WIN32) || defined(DOS) if (!p_ssl) { if (*p == '"') *************** *** 1431,1437 **** d = escaped_string; /* add opening quote */ ! # if defined(WIN32) || defined(WIN16) || defined(DOS) if (!p_ssl) *d++ = '"'; else --- 1431,1437 ---- d = escaped_string; /* add opening quote */ ! # if defined(WIN32) || defined(DOS) if (!p_ssl) *d++ = '"'; else *************** *** 1440,1446 **** for (p = string; *p != NUL; ) { ! # if defined(WIN32) || defined(WIN16) || defined(DOS) if (!p_ssl) { if (*p == '"') --- 1440,1446 ---- for (p = string; *p != NUL; ) { ! # if defined(WIN32) || defined(DOS) if (!p_ssl) { if (*p == '"') *************** *** 1483,1489 **** } /* add terminating quote and finish with a NUL */ ! # if defined(WIN32) || defined(WIN16) || defined(DOS) if (!p_ssl) *d++ = '"'; else --- 1483,1489 ---- } /* add terminating quote and finish with a NUL */ ! # if defined(WIN32) || defined(DOS) if (!p_ssl) *d++ = '"'; else *** ../vim-7.4.1363/src/option.c 2016-02-16 15:06:54.669635233 +0100 --- src/option.c 2016-02-20 13:26:07.446937589 +0100 *************** *** 2296,2309 **** # if defined(MSDOS) (char_u *)"command", # else ! # if defined(WIN16) ! (char_u *)"command.com", ! # else ! # if defined(WIN3264) (char_u *)"", /* set in set_init_1() */ ! # else (char_u *)"sh", - # endif # endif # endif #endif /* VMS */ --- 2296,2305 ---- # if defined(MSDOS) (char_u *)"command", # else ! # if defined(WIN3264) (char_u *)"", /* set in set_init_1() */ ! # else (char_u *)"sh", # endif # endif #endif /* VMS */ *************** *** 2367,2373 **** {"shellxescape", "sxe", P_STRING|P_VI_DEF|P_SECURE, (char_u *)&p_sxe, PV_NONE, { ! #if defined(MSDOS) || defined(WIN16) || defined(WIN3264) (char_u *)"\"&|<>()@^", #else (char_u *)"", --- 2363,2369 ---- {"shellxescape", "sxe", P_STRING|P_VI_DEF|P_SECURE, (char_u *)&p_sxe, PV_NONE, { ! #if defined(MSDOS) || defined(WIN3264) (char_u *)"\"&|<>()@^", #else (char_u *)"", *** ../vim-7.4.1363/src/os_msdos.c 2016-01-30 23:26:28.935356907 +0100 --- src/os_msdos.c 2016-02-20 13:26:47.210524142 +0100 *************** *** 28,39 **** # include #endif - /* - * MS-DOS only code, not used for Win16. - */ - #ifndef WIN16 - - #ifndef PROTO # include # ifdef DJGPP --- 28,33 ---- *************** *** 2850,2860 **** #endif /* FEAT_CLIPBOARD */ #endif /* DJGPP */ - /* - * End of MS-DOS only code - */ - #endif /* WIN16 */ - /* common MS-DOS and Win16 code follows */ static int --- 2844,2849 ---- *** ../vim-7.4.1363/src/os_mswin.c 2016-02-16 20:09:07.869342551 +0100 --- src/os_mswin.c 2016-02-20 13:30:50.239997128 +0100 *************** *** 10,37 **** /* * os_mswin.c * ! * Routines common to both Win16 and Win32. */ - #ifdef WIN16 - # ifdef __BORLANDC__ - # pragma warn -par - # pragma warn -ucp - # pragma warn -use - # pragma warn -aus - # endif - #endif - #include "vim.h" - #ifdef WIN16 - # define SHORT_FNAME /* always 8.3 file name */ - /* cproto fails on missing include files */ - # ifndef PROTO - # include - # endif - # include - #endif #include #include #include --- 10,20 ---- /* * os_mswin.c * ! * Routines for Win32. */ #include "vim.h" #include #include #include *************** *** 904,910 **** typedef int (*MYINTPROCINT)(int); # endif - # ifndef WIN16 /* * Check if a pointer points to a valid NUL terminated string. * Return the length of the string, including terminating NUL. --- 887,892 ---- *************** *** 944,950 **** return 0; } - # endif /* * Passed to do_in_runtimepath() to load a vim.ico file. --- 926,931 ---- *************** *** 991,1001 **** BOOL fRunTimeLinkSuccess = FALSE; // Get a handle to the DLL module. - # ifdef WIN16 - hinstLib = LoadLibrary(libname); - # else hinstLib = vimLoadLib((char *)libname); - # endif // If the handle is valid, try to get the function address. if (hinstLib != NULL) --- 972,978 ---- *************** *** 1034,1048 **** if (string_result == NULL) *number_result = retval_int; else if (retval_str != NULL ! # ifdef WIN16 ! && retval_str != (char_u *)1 ! && retval_str != (char_u *)-1 ! && !IsBadStringPtr(retval_str, INT_MAX) ! && (len = strlen(retval_str) + 1) > 0 ! # else ! && (len = check_str_len(retval_str)) > 0 ! # endif ! ) { *string_result = lalloc((long_u)len, TRUE); if (*string_result != NULL) --- 1011,1017 ---- if (string_result == NULL) *number_result = retval_int; else if (retval_str != NULL ! && (len = check_str_len(retval_str)) > 0) { *string_result = lalloc((long_u)len, TRUE); if (*string_result != NULL) *************** *** 1184,1192 **** #if (defined(FEAT_PRINTER) && !defined(FEAT_POSTSCRIPT)) || defined(PROTO) - # ifdef WIN16 - # define TEXT(a) a - # endif /*================================================================= * Win32 printer stuff */ --- 1153,1158 ---- *************** *** 1211,1217 **** #define IDC_PRINTTEXT2 402 #define IDC_PROGRESS 403 ! #if !defined(FEAT_MBYTE) || defined(WIN16) # define vimSetDlgItemText(h, i, s) SetDlgItemText(h, i, s) #else static BOOL --- 1177,1183 ---- #define IDC_PRINTTEXT2 402 #define IDC_PROGRESS 403 ! #if !defined(FEAT_MBYTE) # define vimSetDlgItemText(h, i, s) SetDlgItemText(h, i, s) #else static BOOL *************** *** 1456,1478 **** int dvoff; int rev_offset; int dpi; - #ifdef WIN16 - POINT pagesize; - #endif GetTextMetrics(prt_dlg.hDC, &prt_tm); prt_line_height = prt_tm.tmHeight + prt_tm.tmExternalLeading; hr = GetDeviceCaps(prt_dlg.hDC, HORZRES); - #ifdef WIN16 - Escape(prt_dlg.hDC, GETPHYSPAGESIZE, NULL, NULL, &pagesize); - phyw = pagesize.x; - Escape(prt_dlg.hDC, GETPRINTINGOFFSET, NULL, NULL, &pagesize); - dvoff = pagesize.x; - #else phyw = GetDeviceCaps(prt_dlg.hDC, PHYSICALWIDTH); dvoff = GetDeviceCaps(prt_dlg.hDC, PHYSICALOFFSETX); - #endif dpi = GetDeviceCaps(prt_dlg.hDC, LOGPIXELSX); rev_offset = phyw - (dvoff + hr); --- 1422,1434 ---- *************** *** 1501,1520 **** int rev_offset; int bottom_margin; int dpi; - #ifdef WIN16 - POINT pagesize; - #endif vr = GetDeviceCaps(prt_dlg.hDC, VERTRES); - #ifdef WIN16 - Escape(prt_dlg.hDC, GETPHYSPAGESIZE, NULL, NULL, &pagesize); - phyw = pagesize.y; - Escape(prt_dlg.hDC, GETPRINTINGOFFSET, NULL, NULL, &pagesize); - dvoff = pagesize.y; - #else phyw = GetDeviceCaps(prt_dlg.hDC, PHYSICALHEIGHT); dvoff = GetDeviceCaps(prt_dlg.hDC, PHYSICALOFFSETY); - #endif dpi = GetDeviceCaps(prt_dlg.hDC, LOGPIXELSY); rev_offset = phyw - (dvoff + vr); --- 1457,1466 ---- *************** *** 1741,1752 **** if (err) { - #ifdef WIN16 - char buf[20]; - - sprintf(buf, "%ld", err); - EMSG2(_("E238: Print error: %s"), buf); - #else char_u *buf; /* I suspect FormatMessage() doesn't work for values returned by --- 1687,1692 ---- *************** *** 1758,1764 **** EMSG2(_("E238: Print error: %s"), buf == NULL ? (char_u *)_("Unknown") : buf); LocalFree((LPVOID)(buf)); - #endif } else msg_clr_eos(); /* Maybe canceled */ --- 1698,1703 ---- *************** *** 1778,1788 **** hDlgPrint = CreateDialog(GetModuleHandle(NULL), TEXT("PrintDlgBox"), prt_dlg.hwndOwner, PrintDlgProc); - #ifdef WIN16 - Escape(prt_dlg.hDC, SETABORTPROC, 0, (LPSTR)AbortProc, NULL); - #else SetAbortProc(prt_dlg.hDC, AbortProc); - #endif wsprintf(szBuffer, _("Printing '%s'"), gettail(psettings->jobname)); vimSetDlgItemText(hDlgPrint, IDC_PRINTTEXT1, (char_u *)szBuffer); --- 1717,1723 ---- *************** *** 1845,1854 **** int mch_print_text_out(char_u *p, int len) { ! #if defined(FEAT_PROPORTIONAL_FONTS) || (defined(FEAT_MBYTE) && !defined(WIN16)) SIZE sz; #endif ! #if defined(FEAT_MBYTE) && !defined(WIN16) WCHAR *wp = NULL; int wlen = len; --- 1780,1789 ---- int mch_print_text_out(char_u *p, int len) { ! #if defined(FEAT_PROPORTIONAL_FONTS) || defined(FEAT_MBYTE) SIZE sz; #endif ! #if defined(FEAT_MBYTE) WCHAR *wp = NULL; int wlen = len; *************** *** 1888,1907 **** return (prt_pos_x + prt_left_margin + prt_tm.tmAveCharWidth + prt_tm.tmOverhang > prt_right_margin); #else - # ifdef WIN16 - GetTextExtentPoint(prt_dlg.hDC, (LPCSTR)p, len, &sz); - # else GetTextExtentPoint32(prt_dlg.hDC, (LPCSTR)p, len, &sz); - # endif prt_pos_x += (sz.cx - prt_tm.tmOverhang); /* This is wrong when printing spaces for a TAB. */ if (p[len] == NUL) return FALSE; - # ifdef WIN16 - GetTextExtentPoint(prt_dlg.hDC, p + len, 1, &sz); - # else GetTextExtentPoint32(prt_dlg.hDC, p + len, 1, &sz); - # endif return (prt_pos_x + prt_left_margin + sz.cx > prt_right_margin); #endif } --- 1823,1834 ---- *************** *** 3027,3040 **** lf->lfWidth = points_to_pixels(p, &p, FALSE, (long_i)printer_dc); break; case 'b': - #ifndef MSWIN16_FASTTEXT lf->lfWeight = FW_BOLD; - #endif break; case 'i': - #ifndef MSWIN16_FASTTEXT lf->lfItalic = TRUE; - #endif break; case 'u': lf->lfUnderline = TRUE; --- 2954,2963 ---- *** ../vim-7.4.1363/src/os_win16.c 2016-01-30 20:31:21.249607913 +0100 --- src/os_win16.c 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,427 **** - /* vi:set ts=8 sts=4 sw=4: - * - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - /* - * os_win16.c - * - * Win16 (Windows 3.1x) system-dependent routines. - * Carved brutally from os_win32.c by Vince Negri - */ - #ifdef __BORLANDC__ - # pragma warn -par - # pragma warn -ucp - # pragma warn -use - # pragma warn -aus - # pragma warn -obs - #endif - - #include "vim.h" - - /* cproto fails on missing include files */ - #ifndef PROTO - # include - #endif - - #include - #include - #include - #include - - #ifndef PROTO - # include - - # undef chdir - # include - # include /* required for FindExecutable() */ - #endif - - - /* Record all output and all keyboard & mouse input */ - /* #define MCH_WRITE_DUMP */ - - #ifdef MCH_WRITE_DUMP - FILE* fdDump = NULL; - #endif - - - /* - * When generating prototypes for Win32 on Unix, these lines make the syntax - * errors disappear. They do not need to be correct. - */ - #ifdef PROTO - typedef int HANDLE; - typedef int SMALL_RECT; - typedef int COORD; - typedef int SHORT; - typedef int WORD; - typedef int DWORD; - typedef int BOOL; - typedef int LPSTR; - typedef int LPTSTR; - typedef int KEY_EVENT_RECORD; - typedef int MOUSE_EVENT_RECORD; - # define WINAPI - typedef int CONSOLE_CURSOR_INFO; - typedef char * LPCSTR; - # define WINBASEAPI - typedef int INPUT_RECORD; - # define _cdecl - #endif - - #ifdef __BORLANDC__ - /* being a more ANSI compliant compiler, BorlandC doesn't define _stricoll: - * but it does in BC 5.02! */ - # if __BORLANDC__ < 0x502 - int _stricoll(char *a, char *b); - # endif - #endif - - /* cproto doesn't create a prototype for main() */ - int _cdecl - VimMain - (int argc, char **argv); - static int (_cdecl *pmain)(int, char **); - - #ifndef PROTO - void _cdecl SaveInst(HINSTANCE hInst); - static void (_cdecl *pSaveInst)(HINSTANCE); - - int WINAPI - WinMain( - HINSTANCE hInstance, - HINSTANCE hPrevInst, - LPSTR lpszCmdLine, - int nCmdShow) - { - int argc; - char **argv; - char *tofree; - char prog[256]; - - /* - * Ron: added full path name so that the $VIM variable will get set to our - * startup path (so the .vimrc file can be found w/o a VIM env. var.) - * Remove the ".exe" extension, and find the 1st non-space. - */ - GetModuleFileName(hInstance, prog, 255); - if (*prog != NUL) - exe_name = FullName_save((char_u *)prog, FALSE); - - /* Separate the command line into arguments. */ - argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree); - if (argc == 0) - { - /* Error message? */ - return 0; - } - - pSaveInst = SaveInst; - pmain = VimMain; - pSaveInst(hInstance); - pmain(argc, argv); - - free(argv); - if (tofree != NULL) - free(tofree); - - return 0; - } - #endif - - - - - - - #ifdef FEAT_MOUSE - - /* - * For the GUI the mouse handling is in gui_w32.c. - */ - void - mch_setmouse( - int on) - { - } - #endif /* FEAT_MOUSE */ - - - - /* - * GUI version of mch_init(). - */ - void - mch_init(void) - { - extern int _fmode; - - - /* Let critical errors result in a failure, not in a dialog box. Required - * for the timestamp test to work on removed floppies. */ - SetErrorMode(SEM_FAILCRITICALERRORS); - - _fmode = O_BINARY; /* we do our own CR-LF translation */ - - /* Specify window size. Is there a place to get the default from? */ - Rows = 25; - Columns = 80; - - - set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0); - - #ifdef FEAT_CLIPBOARD - clip_init(TRUE); - - /* - * Vim's own clipboard format recognises whether the text is char, line, - * or rectangular block. Only useful for copying between two Vims. - * "VimClipboard" was used for previous versions, using the first - * character to specify MCHAR, MLINE or MBLOCK. - */ - clip_star.format = RegisterClipboardFormat("VimClipboard2"); - clip_star.format_raw = RegisterClipboardFormat("VimRawBytes"); - #endif - } - - - - /* - * Do we have an interactive window? - */ - int - mch_check_win( - int argc, - char **argv) - { - return OK; /* GUI always has a tty */ - } - - - /* - * return process ID - */ - long - mch_get_pid(void) - { - return (long)GetCurrentTask(); - } - - - /* - * Specialised version of system(). - * This version proceeds as follows: - * 1. Start the program with WinExec - * 2. Wait for the module use count of the program to go to 0 - * (This is the best way of detecting the program has finished) - */ - - static int - mch_system(char *cmd, int options) - { - DWORD ret = 0; - UINT wShowWindow; - UINT h_module; - MSG msg; - BOOL again = TRUE; - - /* - * It's nicer to run a filter command in a minimized window, but in - */ - if (options & SHELL_DOOUT) - wShowWindow = SW_SHOWMINIMIZED; - else - wShowWindow = SW_SHOWNORMAL; - - /* Now, run the command */ - h_module = WinExec((LPCSTR)cmd, wShowWindow); - - if (h_module < 32) - { - /*error*/ - ret = -h_module; - } - else - { - /* Wait for the command to terminate before continuing */ - while (GetModuleUsage((HINSTANCE)h_module) > 0 && again ) - { - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && again) - { - if (msg.message == WM_QUIT) - - { - PostQuitMessage(msg.wParam); - again = FALSE; - } - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - } - - return ret; - } - - /* - * Either execute a command by calling the shell or start a new shell - */ - int - mch_call_shell( - char_u *cmd, - int options) /* SHELL_, see vim.h */ - { - int x; - int tmode = cur_tmode; - - out_flush(); - - - #ifdef MCH_WRITE_DUMP - if (fdDump) - { - fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options); - fflush(fdDump); - } - #endif - - /* - * Catch all deadly signals while running the external command, because a - * CTRL-C, Ctrl-Break or illegal instruction might otherwise kill us. - */ - signal(SIGINT, SIG_IGN); - signal(SIGILL, SIG_IGN); - signal(SIGFPE, SIG_IGN); - signal(SIGSEGV, SIG_IGN); - signal(SIGTERM, SIG_IGN); - signal(SIGABRT, SIG_IGN); - - if (options & SHELL_COOKED) - settmode(TMODE_COOK); /* set to normal mode */ - - if (cmd == NULL) - { - x = mch_system(p_sh, options); - } - else - { - /* we use "command" or "cmd" to start the shell; slow but easy */ - char_u *newcmd; - - newcmd = lalloc( - STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10, TRUE); - if (newcmd != NULL) - { - if (STRNICMP(cmd, "start ", 6) == 0) - { - sprintf((char *)newcmd, "%s\0", cmd+6); - if (WinExec((LPCSTR)newcmd, SW_SHOWNORMAL) > 31) - x = 0; - else - x = -1; - } - else - { - sprintf((char *)newcmd, "%s%s %s %s", - "", - p_sh, - p_shcf, - cmd); - x = mch_system((char *)newcmd, options); - } - vim_free(newcmd); - } - } - - if (tmode == TMODE_RAW) - settmode(TMODE_RAW); /* set to raw mode */ - - if (x && !(options & SHELL_SILENT) && !emsg_silent) - { - smsg(_("shell returned %d"), x); - msg_putchar('\n'); - } - #ifdef FEAT_TITLE - resettitle(); - #endif - - signal(SIGINT, SIG_DFL); - signal(SIGILL, SIG_DFL); - signal(SIGFPE, SIG_DFL); - signal(SIGSEGV, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGABRT, SIG_DFL); - - - return x; - } - - - /* - * Delay for half a second. - */ - void - mch_delay( - long msec, - int ignoreinput) - { - #ifdef MUST_FIX - Sleep((int)msec); /* never wait for input */ - #endif - } - - - /* - * check for an "interrupt signal": CTRL-break or CTRL-C - */ - void - mch_breakcheck(void) - { - /* never used */ - } - - - /* - * How much memory is available in Kbyte? - */ - long_u - mch_avail_mem( - int special) - { - return GetFreeSpace(0) >> 10; - } - - - /* - * Like rename(), returns 0 upon success, non-zero upon failure. - * Should probably set errno appropriately when errors occur. - */ - int - mch_rename( - const char *pszOldFile, - const char *pszNewFile) - { - - /* - * No need to play tricks, this isn't rubbish like Windows 95 - */ - return rename(pszOldFile, pszNewFile); - - } - - /* - * Get the default shell for the current hardware platform - */ - char* - default_shell(void) - { - char* psz = NULL; - - psz = "command.com"; - - return psz; - } --- 0 ---- *** ../vim-7.4.1363/src/os_win16.h 2014-02-23 22:52:33.372764715 +0100 --- src/os_win16.h 1970-01-01 01:00:00.000000000 +0100 *************** *** 1,143 **** - /* vi:set ts=8 sts=4 sw=4: - * - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - */ - - /* - * Win16 (Windows 3.1x) machine-dependent things. - */ - - #include "os_dos.h" /* common MS-DOS and Windows stuff */ - - #define BINARY_FILE_IO - #define USE_EXE_NAME /* use argv[0] for $VIM */ - #define SYNC_DUP_CLOSE /* sync() a file with dup() and close() */ - #define USE_TERM_CONSOLE - #define HAVE_STRING_H - #define HAVE_STRCSPN - #define HAVE_STRICMP - #define HAVE_STRNICMP - #define HAVE_STRFTIME /* guessed */ - #define HAVE_MEMSET - #define USE_TMPNAM /* use tmpnam() instead of mktemp() */ - #define HAVE_LOCALE_H - #define HAVE_FCNTL_H - #define HAVE_QSORT - #define HAVE_ST_MODE /* have stat.st_mode */ - #define HAVE_MATH_H - //#define USE_FNAME_CASE /* adjust case of file names */ - #ifndef FEAT_CLIPBOARD - # define FEAT_CLIPBOARD /* include clipboard support */ - #endif - #if defined(__DATE__) && defined(__TIME__) - # define HAVE_DATE_TIME - #endif - #define HAVE_AVAIL_MEM - - #define SHORT_FNAME /* always 8.3 file name */ - - #define SMALL_MALLOC /* 16 bit storage allocation */ - - #ifdef __BORLANDC__ - # define HAVE_PUTENV /* at least Bcc 5.2 has it */ - #endif - - #ifdef FEAT_GUI_W16 - # define NO_CONSOLE /* don't included console-only code */ - #endif - - /* toupper() is not really broken, but it's very slow. Probably because of - * using unicode characters on Windows NT */ - #define BROKEN_TOUPPER - - #define FNAME_ILLEGAL "\"*?><|" /* illegal characters in a file name */ - - #ifndef VIM_SIZEOF_INT - # define VIM_SIZEOF_INT 2 - #endif - - typedef long off_t; - - #include - #include - - /* cproto fails on missing include files */ - #ifndef PROTO - # include - # include - - # ifndef STRICT - # define STRICT - # endif - # ifndef COBJMACROS - # define COBJMACROS /* For OLE: Enable "friendlier" access to objects */ - # endif - # include - - #endif /* PROTO */ - - /* - * plenty of memory, use large buffers - */ - #define CMDBUFFSIZE 1024 /* size of the command processing buffer */ - - - #define BASENAMELEN (MAXPATHL-5) /* length of base of file name */ - - #ifndef DFLT_MAXMEM - # define DFLT_MAXMEM (256) /* use up to 256K for a buffer*/ - #endif - - #ifndef DFLT_MAXMEMTOT - # define DFLT_MAXMEMTOT (5*1024) /* use up to 5 Mbyte for Vim */ - #endif - - /* - * Some simple debugging macros that look and behave a lot like their - * namesakes in MFC. - */ - - #ifdef _DEBUG - - # if defined(_MSC_VER) && (_MSC_VER >= 1000) - /* Use the new debugging tools in Visual C++ 4.x */ - # include - # define ASSERT(f) _ASSERT(f) - # else - # include - # define ASSERT(f) assert(f) - # endif - - # define TRACE Trace - # define TRACE0(sz) Trace(_T("%s"), _T(sz)) - # define TRACE1(sz, p1) Trace(_T(sz), p1) - # define TRACE2(sz, p1, p2) Trace(_T(sz), p1, p2) - # define TRACE3(sz, p1, p2, p3) Trace(_T(sz), p1, p2, p3) - - /* In debug version, writes trace messages to debug stream */ - void __cdecl - Trace(char *pszFormat, ...); - - #else /* !_DEBUG */ - - /* These macros should all compile away to nothing */ - # define ASSERT(f) ((void)0) - # define TRACE 1 ? (void)0 : printf - # define TRACE0(sz) - # define TRACE1(sz, p1) - # define TRACE2(sz, p1, p2) - # define TRACE3(sz, p1, p2, p3) - - #endif /* !_DEBUG */ - - - #define ASSERT_POINTER(p, type) \ - ASSERT(((p) != NULL) && IsValidAddress((p), sizeof(type), FALSE)) - - #define ASSERT_NULL_OR_POINTER(p, type) \ - ASSERT(((p) == NULL) || IsValidAddress((p), sizeof(type), FALSE)) - - #define mch_setenv(name, val, x) setenv(name, val, x) --- 0 ---- *** ../vim-7.4.1363/src/version.c 2016-02-20 13:08:42.453801608 +0100 --- src/version.c 2016-02-20 13:51:52.990872173 +0100 *************** *** 3638,3646 **** # endif # endif #endif - #ifdef WIN16 - MSG_PUTS(_("\nMS-Windows 16-bit version")); - #endif #ifdef MSDOS # ifdef DJGPP MSG_PUTS(_("\n32-bit MS-DOS version")); --- 3640,3645 ---- *** ../vim-7.4.1363/src/winclip.c 2016-01-30 21:29:52.228928504 +0100 --- src/winclip.c 2016-02-20 13:31:31.079572466 +0100 *************** *** 14,28 **** * Also used by Cygwin, using os_unix.c. */ - #ifdef WIN16 - # ifdef __BORLANDC__ - # pragma warn -par - # pragma warn -ucp - # pragma warn -use - # pragma warn -aus - # endif - #endif - #include "vimio.h" #include "vim.h" --- 14,19 ---- *** ../vim-7.4.1363/src/feature.h 2016-02-14 19:13:37.314808670 +0100 --- src/feature.h 2016-02-20 13:32:04.411225870 +0100 *************** *** 320,326 **** * * Disabled for EBCDIC as it requires multibyte. */ ! #if defined(FEAT_BIG) && !defined(WIN16) && VIM_SIZEOF_INT >= 4 && !defined(EBCDIC) # define FEAT_ARABIC #endif #ifdef FEAT_ARABIC --- 320,326 ---- * * Disabled for EBCDIC as it requires multibyte. */ ! #if defined(FEAT_BIG) && VIM_SIZEOF_INT >= 4 && !defined(EBCDIC) # define FEAT_ARABIC #endif #ifdef FEAT_ARABIC *************** *** 624,631 **** * Multibyte support doesn't work on z/OS Unix currently. */ #if (defined(FEAT_NORMAL) || defined(FEAT_GUI_GTK) || defined(FEAT_ARABIC)) \ ! && !defined(FEAT_MBYTE) && !defined(WIN16) \ ! && VIM_SIZEOF_INT >= 4 && !defined(EBCDIC) # define FEAT_MBYTE #endif --- 624,630 ---- * Multibyte support doesn't work on z/OS Unix currently. */ #if (defined(FEAT_NORMAL) || defined(FEAT_GUI_GTK) || defined(FEAT_ARABIC)) \ ! && !defined(FEAT_MBYTE) && VIM_SIZEOF_INT >= 4 && !defined(EBCDIC) # define FEAT_MBYTE #endif *************** *** 763,769 **** && (defined(FEAT_GUI_GTK) \ || (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \ || defined(FEAT_GUI_MAC) \ ! || (defined(FEAT_GUI_MSWIN) && !defined(WIN16) \ && (!defined(_MSC_VER) || _MSC_VER > 1020))) # define FEAT_GUI_TABLINE #endif --- 762,768 ---- && (defined(FEAT_GUI_GTK) \ || (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \ || defined(FEAT_GUI_MAC) \ ! || (defined(FEAT_GUI_MSWIN) \ && (!defined(_MSC_VER) || _MSC_VER > 1020))) # define FEAT_GUI_TABLINE #endif *** ../vim-7.4.1363/src/proto.h 2016-01-30 21:48:44.325034448 +0100 --- src/proto.h 2016-02-20 13:32:25.699004509 +0100 *************** *** 38,54 **** # if defined(UNIX) || defined(__EMX__) || defined(VMS) # include "os_unix.pro" # endif ! # if defined(MSDOS) || defined(WIN16) # include "os_msdos.pro" # endif - # ifdef WIN16 - typedef LPSTR LPWSTR; - typedef LPCSTR LPCWSTR; - typedef int LPBOOL; - # include "os_win16.pro" - # include "os_mswin.pro" - # include "winclip.pro" - # endif # ifdef WIN3264 # include "os_win32.pro" # include "os_mswin.pro" --- 38,46 ---- # if defined(UNIX) || defined(__EMX__) || defined(VMS) # include "os_unix.pro" # endif ! # if defined(MSDOS) # include "os_msdos.pro" # endif # ifdef WIN3264 # include "os_win32.pro" # include "os_mswin.pro" *** ../vim-7.4.1363/src/vim.h 2016-02-15 21:56:42.725119689 +0100 --- src/vim.h 2016-02-20 13:32:54.754702375 +0100 *************** *** 27,33 **** # endif #endif ! #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) \ || defined(__EMX__) # include "vimio.h" #endif --- 27,33 ---- # endif #endif ! #if defined(MSDOS) || defined(WIN32) || defined(_WIN64) \ || defined(__EMX__) # include "vimio.h" #endif *************** *** 150,156 **** #if defined(FEAT_GUI_W32) || defined(FEAT_GUI_W16) # define FEAT_GUI_MSWIN #endif ! #if defined(WIN16) || defined(WIN32) || defined(_WIN64) # define MSWIN #endif /* Practically everything is common to both Win32 and Win64 */ --- 150,156 ---- #if defined(FEAT_GUI_W32) || defined(FEAT_GUI_W16) # define FEAT_GUI_MSWIN #endif ! #if defined(WIN32) || defined(_WIN64) # define MSWIN #endif /* Practically everything is common to both Win32 and Win64 */ *************** *** 308,317 **** # include "os_msdos.h" #endif - #ifdef WIN16 - # include "os_win16.h" - #endif - #ifdef WIN3264 # include "os_win32.h" #endif --- 308,313 ---- *************** *** 471,477 **** # include #endif ! #if defined(HAVE_ERRNO_H) || defined(DJGPP) || defined(WIN16) \ || defined(WIN32) || defined(_WIN64) || defined(__EMX__) # include #endif --- 467,473 ---- # include #endif ! #if defined(HAVE_ERRNO_H) || defined(DJGPP) \ || defined(WIN32) || defined(_WIN64) || defined(__EMX__) # include #endif *** ../vim-7.4.1363/Filelist 2016-02-03 21:56:38.376013009 +0100 --- Filelist 2016-02-20 13:38:18.219338696 +0100 *************** *** 300,306 **** src/Make_dvc.mak \ src/Make_ming.mak \ src/Make_mvc.mak \ - src/Make_w16.mak \ src/bigvim.bat \ src/bigvim64.bat \ src/msvcsetup.bat \ --- 300,305 ---- *************** *** 314,323 **** src/glbl_ime.h \ src/gui_dwrite.cpp \ src/gui_dwrite.h \ - src/gui_w16.c \ src/gui_w32.c \ - src/gui_w48.c \ - src/guiw16rc.h \ src/gui_w32_rc.h \ src/if_ole.cpp \ src/if_ole.h \ --- 313,319 ---- *************** *** 329,344 **** src/os_msdos.h \ src/os_w32dll.c \ src/os_w32exe.c \ - src/os_win16.c \ src/os_win32.c \ src/os_mswin.c \ - src/os_win16.h \ src/os_win32.h \ - src/proto/gui_w16.pro \ src/proto/gui_w32.pro \ src/proto/if_ole.pro \ src/proto/os_msdos.pro \ - src/proto/os_win16.pro \ src/proto/os_win32.pro \ src/proto/os_mswin.pro \ src/testdir/Make_dos.mak \ --- 325,336 ---- *************** *** 349,356 **** src/vim.rc \ src/vimio.h \ src/gvim.exe.mnf \ - src/vim16.def \ - src/vim16.rc \ src/vimrun.c \ src/vimtbar.h \ src/xpm_w32.c \ --- 341,346 ---- *************** *** 390,396 **** src/VisVim/Res/*.bmp \ src/tearoff.bmp \ src/tools.bmp \ - src/tools16.bmp \ src/vim*.ico \ src/vim.tlb \ src/vimtbar.lib \ --- 380,385 ---- *** ../vim-7.4.1363/src/version.c 2016-02-20 13:08:42.453801608 +0100 --- src/version.c 2016-02-20 13:51:52.990872173 +0100 *************** *** 749,750 **** --- 749,752 ---- { /* Add new patch number below this line */ + /**/ + 1364, /**/ -- LAUNCELOT leaps into SHOT with a mighty cry and runs the GUARD through and hacks him to the floor. Blood. Swashbuckling music (perhaps). LAUNCELOT races through into the castle screaming. SECOND SENTRY: Hey! "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///