diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index af0a802445..d8cfc29f93 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.1. Last change: 2007 Aug 10 +*options.txt* For Vim version 7.1. Last change: 2008 Feb 24 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4951,7 +4951,7 @@ A jump table for the options with a short description can be found at |Q_op|. |autocmd-osfiletypes| *'paragraphs'* *'para'* -'paragraphs' 'para' string (default "IPLPPPQPP LIpplpipbp") +'paragraphs' 'para' string (default "IPLPPPQPP TPHPLIPpLpItpplpipbp") global Specifies the nroff macros that separate paragraphs. These are pairs of two letters (see |object-motions|). diff --git a/runtime/plugin/matchparen.vim b/runtime/plugin/matchparen.vim index 28bab71348..f38e4819d6 100644 --- a/runtime/plugin/matchparen.vim +++ b/runtime/plugin/matchparen.vim @@ -1,6 +1,6 @@ " Vim plugin for showing matching parens " Maintainer: Bram Moolenaar -" Last Change: 2008 Jan 06 +" Last Change: 2008 Feb 27 " Exit quickly when: " - this plugin was already loaded (or disabled) @@ -34,7 +34,8 @@ function! s:Highlight_Matching_Pair() endif " Avoid that we remove the popup menu. - if pumvisible() + " Return when there are no colors (looks like the cursor jumps). + if pumvisible() || (&t_Co < 8 && !has("gui_running")) return endif @@ -60,39 +61,13 @@ function! s:Highlight_Matching_Pair() endif " Figure out the arguments for searchpairpos(). - " Restrict the search to visible lines with "stopline". - " And avoid searching very far (e.g., for closed folds and long lines) - " The "viewable" variables give a range in which we can scroll while keeping - " the cursor at the same position - " adjustedScrolloff accounts for very large numbers of scrolloff - let adjustedScrolloff = min([&scrolloff, (line('w$') - line('w0')) / 2]) - let bottom_viewable = min([line('$'), c_lnum + &lines - adjustedScrolloff - 2]) - let top_viewable = max([1, c_lnum-&lines+adjustedScrolloff + 2]) - " one of these stoplines will be adjusted below, but the current values are - " minimal boundaries within the current window - let stoplinebottom = line('w$') - let stoplinetop = line('w0') if i % 2 == 0 let s_flags = 'nW' let c2 = plist[i + 1] - if has("byte_offset") && has("syntax_items") && &smc > 0 - let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2]) - let stopline = min([bottom_viewable, byte2line(stopbyte)]) - else - let stopline = min([bottom_viewable, c_lnum + 100]) - endif - let stoplinebottom = stopline else let s_flags = 'nbW' let c2 = c let c = plist[i - 1] - if has("byte_offset") && has("syntax_items") && &smc > 0 - let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2]) - let stopline = max([top_viewable, byte2line(stopbyte)]) - else - let stopline = max([top_viewable, c_lnum - 100]) - endif - let stoplinetop = stopline endif if c == '[' let c = '\[' @@ -111,10 +86,47 @@ function! s:Highlight_Matching_Pair() \ '=~? "string\\|character\\|singlequote\\|comment"' execute 'if' s_skip '| let s_skip = 0 | endif' + " Limit the search to lines visible in the window. + let stoplinebottom = line('w$') + let stoplinetop = line('w0') + if i % 2 == 0 + let stopline = stoplinebottom + else + let stopline = stoplinetop + endif + try - " Limit the search time to 500 msec to avoid a hang on very long lines. - let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 500) + " Limit the search time to 300 msec to avoid a hang on very long lines. + " This fails when a timeout is not supported. + let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 300) catch /E118/ + " Can't use the timeout, restrict the stopline a bit more to avoid taking + " a long time on closed folds and long lines. + " The "viewable" variables give a range in which we can scroll while + " keeping the cursor at the same position. + " adjustedScrolloff accounts for very large numbers of scrolloff. + let adjustedScrolloff = min([&scrolloff, (line('w$') - line('w0')) / 2]) + let bottom_viewable = min([line('$'), c_lnum + &lines - adjustedScrolloff - 2]) + let top_viewable = max([1, c_lnum-&lines+adjustedScrolloff + 2]) + " one of these stoplines will be adjusted below, but the current values are + " minimal boundaries within the current window + if i % 2 == 0 + if has("byte_offset") && has("syntax_items") && &smc > 0 + let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2]) + let stopline = min([bottom_viewable, byte2line(stopbyte)]) + else + let stopline = min([bottom_viewable, c_lnum + 100]) + endif + let stoplinebottom = stopline + else + if has("byte_offset") && has("syntax_items") && &smc > 0 + let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2]) + let stopline = max([top_viewable, byte2line(stopbyte)]) + else + let stopline = max([top_viewable, c_lnum - 100]) + endif + let stoplinetop = stopline + endif let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline) endtry diff --git a/src/GvimExt/Makefile b/src/GvimExt/Makefile index 69e4270c9f..24880253d6 100644 --- a/src/GvimExt/Makefile +++ b/src/GvimExt/Makefile @@ -24,7 +24,7 @@ gvimext.dll: gvimext.obj \ gvimext.obj: gvimext.h .cpp.obj: - $(cc) $(cflags) -DFEAT_GETTEXT $(cvarsdll) $*.cpp + $(cc) $(cflags) -DFEAT_GETTEXT $(cvarsmt) $*.cpp gvimext.res: gvimext.rc $(rc) $(rcflags) $(rcvars) gvimext.rc diff --git a/src/INSTALLpc.txt b/src/INSTALLpc.txt index a13dce0596..f256ac13de 100644 --- a/src/INSTALLpc.txt +++ b/src/INSTALLpc.txt @@ -82,9 +82,8 @@ To compile and debug Vim with the VC2003 Toolkit, you will also need |ms-platform-sdk|, |dotnet-1.1-redist|, |dotnet-1.1-sdk|, and |windbg-download|. -It's easier to download Visual C++ 2005 Express Edition, |msvc-2005-express|. -The advantage of the VC 2003 Toolkit is that it will be freely available -long after VC 2005 Express Edition stops being free in November 2006. +It's easier to download Visual C++ 2008 Express Edition, |msvc-2008-express|, +which is freely available in perpetuity. The free Code::Blocks IDE works with the VC2003 Toolkit, as described at http://wiki.codeblocks.org/index.php?title=Integrating_Microsoft_Visual_Toolkit_2003_with_Code::Blocks_IDE @@ -152,6 +151,14 @@ Instructions for integrating the Platform SDK into VC Express: http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/default.aspx +Visual C++ 2008 Express Edition *msvc-2008-express* +------------------------------- + +Visual C++ 2008 Express Edition can be downloaded for free from: + http://msdn2.microsoft.com/en-us/express/default.aspx +This includes the IDE and the debugger. You can build Vim with Make_mvc.mak. + + 2. MinGW ======== diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index b407fbe06f..34c87a5982 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -1,6 +1,7 @@ # Makefile for Vim on Win32 (Windows NT/2000/XP/2003 and Windows 95/98/Me) # and Win64, using the Microsoft Visual C++ compilers. Known to work with -# VC5, VC6 (VS98), VC7.0 (VS2002), VC7.1 (VS2003), and VC8 (VS2005). +# VC5, VC6 (VS98), VC7.0 (VS2002), VC7.1 (VS2003), VC8 (VS2005), +# and VC9 (VS2008). # # To build using other Windows compilers, see INSTALLpc.txt # @@ -285,7 +286,8 @@ XPM_INC = -I $(XPM)\include # need shell32.lib for ExtractIcon() # gdi32.lib and comdlg32.lib for printing support # ole32.lib and uuid.lib are needed for FEAT_SHORTCUT -CON_LIB = advapi32.lib shell32.lib gdi32.lib comdlg32.lib ole32.lib uuid.lib +CON_LIB = oldnames.lib kernel32.lib advapi32.lib shell32.lib gdi32.lib \ + comdlg32.lib ole32.lib uuid.lib /machine:$(CPU) /nodefaultlib !if "$(DELAYLOAD)" == "yes" CON_LIB = $(CON_LIB) /DELAYLOAD:comdlg32.dll /DELAYLOAD:ole32.dll DelayImp.lib !endif @@ -331,6 +333,7 @@ MSVCVER = 5.0 !endif !if "$(_NMAKE_VER)" == "6.00.8168.0" MSVCVER = 6.0 +CPU = ix86 !endif !if "$(_NMAKE_VER)" == "7.00.9466" MSVCVER = 7.0 @@ -344,6 +347,9 @@ MSVCVER = 8.0 !if "$(_NMAKE_VER)" == "8.00.50727.762" MSVCVER = 8.0 !endif +!if "$(_NMAKE_VER)" == "9.00.20706.01" +MSVCVER = 9.0 +!endif !endif # Abort bulding VIM if version of VC is unrecognised. @@ -352,13 +358,13 @@ MSVCVER = 8.0 !message Cannot determine Visual C version being used. If you are using the !message Windows SDK then you must have the environment variable MSVCVER set to !message your version of the VC compiler. If you are not using the Express -!message version of Visual C you van either set MSVCVER or update this makefile -!message to handle the new value for _NMAKE_VER. +!message version of Visual C, you can either set MSVCVER or update this makefile +!message to handle the new value for _NMAKE_VER, "$(_NMAKE_VER)". !error Make aborted. !endif # Convert processor ID to MVC-compatible number -!if "$(MSVCVER)" != "8.0" +!if ("$(MSVCVER)" != "8.0") && ("$(MSVCVER)" != "9.0") !if "$(CPUNR)" == "i386" CPUARG = /G3 !elseif "$(CPUNR)" == "i486" @@ -373,7 +379,7 @@ CPUARG = /G7 /arch:SSE2 CPUARG = !endif !else -# VC8 only allows specifying SSE architecture +# VC8/9 only allows specifying SSE architecture !if "$(CPUNR)" == "pentium4" CPUARG = /arch:SSE2 !endif @@ -391,7 +397,7 @@ OPTFLAG = /O2 !else # MAXSPEED OPTFLAG = /Ox !endif -!if "$(MSVCVER)" == "8.0" +!if ("$(MSVCVER)" == "8.0") || ("$(MSVCVER)" == "9.0") # Use link time code generation if not worried about size !if "$(OPTIMIZE)" != "SPACE" OPTFLAG = $(OPTFLAG) /GL @@ -404,11 +410,11 @@ CFLAGS = $(CFLAGS) /MD LIBC = msvcrt.lib ! else LIBC = libcmt.lib -CFLAGS = $(CFLAGS) /MT +CFLAGS = $(CFLAGS) /Zl /MT ! endif !else # DEBUG VIM = vimd -! if "$(CPU)" == "i386" +! if ("$(CPU)" == "i386") || ("$(CPU)" == "ix86") DEBUGINFO = /ZI ! endif CFLAGS = $(CFLAGS) -D_DEBUG -DDEBUG /Od @@ -424,7 +430,7 @@ CFLAGS = $(CFLAGS) /MDd LIBC = $(LIBC) msvcrtd.lib ! else LIBC = $(LIBC) libcmtd.lib -CFLAGS = $(CFLAGS) /MTd +CFLAGS = $(CFLAGS) /Zl /MTd ! endif !endif # DEBUG @@ -534,7 +540,7 @@ GUI_OBJ = \ $(OUTDIR)\gui_w32.obj \ $(OUTDIR)\os_w32exe.obj GUI_LIB = \ - oldnames.lib kernel32.lib gdi32.lib version.lib $(IME_LIB) \ + gdi32.lib version.lib $(IME_LIB) \ winspool.lib comctl32.lib advapi32.lib shell32.lib \ /machine:$(CPU) /nodefaultlib !else @@ -757,7 +763,7 @@ LINKARGS2 = $(CON_LIB) $(GUI_LIB) $(LIBC) $(OLE_LIB) user32.lib $(SNIFF_LIB) \ # Report link time code generation progress if used. !ifdef NODEBUG -!if "$(MSVCVER)" == "8.0" +!if ("$(MSVCVER)" == "8.0") || ("$(MSVCVER)" == "9.0") !if "$(OPTIMIZE)" != "SPACE" LINKARGS1 = $(LINKARGS1) /LTCG:STATUS !endif diff --git a/src/Makefile b/src/Makefile index 95d846b136..75c90ffe79 100644 --- a/src/Makefile +++ b/src/Makefile @@ -545,7 +545,7 @@ LINT_OPTIONS = -beprxzF # For unknown reasons adding "-lc" fixes a linking problem with GCC. That's # probably a bug in the "-pg" implementation. # Need to recompile everything after changing this: "make clean" "make". -#PROFILE_CFLAGS = -pg -g +#PROFILE_CFLAGS = -pg -g -DWE_ARE_PROFILING #PROFILE_LIBS = -pg #PROFILE_LIBS = -pg -lc diff --git a/src/buffer.c b/src/buffer.c index 7cddc11f93..9e7068810d 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -4922,7 +4922,7 @@ chk_modeline(lnum, flags) return retval; } -#ifdef FEAT_VIMINFO +#if defined(FEAT_VIMINFO) || defined(PROTO) int read_viminfo_bufferlist(virp, writing) vir_T *virp; @@ -5043,13 +5043,14 @@ buf_spname(buf) #if defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS) if (bt_quickfix(buf)) { - win_T *win; + win_T *win = NULL; + tabpage_T *tp; /* * For location list window, w_llist_ref points to the location list. * For quickfix window, w_llist_ref is NULL. */ - FOR_ALL_WINDOWS(win) + FOR_ALL_TAB_WINDOWS(tp, win) if (win->w_buffer == buf) break; if (win != NULL && win->w_llist_ref != NULL) diff --git a/src/dosinst.c b/src/dosinst.c index 9226b6302b..c4ed7f6a11 100644 --- a/src/dosinst.c +++ b/src/dosinst.c @@ -1365,7 +1365,7 @@ install_registry(void) printf("Creating \"Edit with Vim\" popup menu entry\n"); - fprintf(fd, "HKEY_CLASSES_ROOT\\CLSID\\%s\n", vim_ext_clsid); + fprintf(fd, "[HKEY_CLASSES_ROOT\\CLSID\\%s]\n", vim_ext_clsid); fprintf(fd, "@=\"%s\"\n", vim_ext_name); fprintf(fd, "[HKEY_CLASSES_ROOT\\CLSID\\%s\\InProcServer32]\n", vim_ext_clsid); diff --git a/src/edit.c b/src/edit.c index 6a2f9518db..fb17eecc9e 100644 --- a/src/edit.c +++ b/src/edit.c @@ -5491,7 +5491,7 @@ insertchar(c, flags, second_indent) #if defined(FEAT_EVAL) int do_internal = TRUE; - if (*curbuf->b_p_fex != NUL) + if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0) { do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0); /* It may be required to save for undo again, e.g. when setline() @@ -6057,7 +6057,7 @@ auto_format(trailblank, prev_line) * be adjusted for the text formatting. */ saved_cursor = pos; - format_lines((linenr_T)-1); + format_lines((linenr_T)-1, FALSE); curwin->w_cursor = saved_cursor; saved_cursor.lnum = 0; diff --git a/src/eval.c b/src/eval.c index e6a706b364..9e2999bfa1 100644 --- a/src/eval.c +++ b/src/eval.c @@ -13974,6 +13974,7 @@ f_reverse(argvars, rettv) rettv->vval.v_list = l; rettv->v_type = VAR_LIST; ++l->lv_refcount; + l->lv_idx = l->lv_len - l->lv_idx - 1; } } @@ -14682,6 +14683,8 @@ f_setline(argvars, rettv) appended_lines_mark(lcount, added); } +static void set_qf_ll_list __ARGS((win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv)); + /* * Used by "setqflist()" and "setloclist()" functions */ @@ -15220,7 +15223,7 @@ f_sort(argvars, rettv) if (!item_compare_func_err) { /* Clear the List and append the items in the sorted order. */ - l->lv_first = l->lv_last = NULL; + l->lv_first = l->lv_last = l->lv_idx_item = NULL; l->lv_len = 0; for (i = 0; i < len; ++i) list_append(l, ptrs[i]); diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 63a82d824d..f1aa113ace 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3015,7 +3015,7 @@ modifier_len(cmd) break; if (!isalpha(p[j]) && j >= cmdmods[i].minlen && (p == cmd || cmdmods[i].has_count)) - return j + (p - cmd); + return j + (int)(p - cmd); } return 0; } @@ -3949,8 +3949,7 @@ get_address(ptr, skip, to_other_file) curwin->w_cursor.col = 0; searchcmdlen = 0; if (!do_search(NULL, c, cmd, 1L, - SEARCH_HIS + SEARCH_MSG + SEARCH_START, - NULL)) + SEARCH_HIS | SEARCH_MSG, NULL)) { curwin->w_cursor = pos; cmd = NULL; @@ -3997,8 +3996,7 @@ get_address(ptr, skip, to_other_file) pos.col = 0; if (searchit(curwin, curbuf, &pos, *cmd == '?' ? BACKWARD : FORWARD, - (char_u *)"", 1L, - SEARCH_MSG + SEARCH_START, + (char_u *)"", 1L, SEARCH_MSG, i, (linenr_T)0, NULL) != FAIL) lnum = pos.lnum; else diff --git a/src/fileio.c b/src/fileio.c index d69cb768b2..25a63f81d0 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -9244,7 +9244,7 @@ aucmd_prepbuf(aco, buf) aco_save_T *aco; /* structure to save values in */ buf_T *buf; /* new curbuf */ { - aco->save_buf = buf; + aco->save_buf = curbuf; curbuf = buf; curwin->w_buffer = buf; } diff --git a/src/globals.h b/src/globals.h index 2310dcaa26..4c266016ec 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1263,7 +1263,7 @@ EXTERN int echo_wid_arg INIT(= FALSE); /* --echo-wid argument */ * The value of the --windowid argument. * For embedding gvim inside another application. */ -EXTERN int win_socket_id INIT(= 0); +EXTERN long_u win_socket_id INIT(= 0); #endif #if defined(FEAT_CLIENTSERVER) || defined(FEAT_EVAL) diff --git a/src/gui_mac.c b/src/gui_mac.c index adc8ddc1f1..b3c6f1f540 100644 --- a/src/gui_mac.c +++ b/src/gui_mac.c @@ -59,7 +59,33 @@ SInt32 gMacSystemVersion; #ifdef MACOS_CONVERT # define USE_CARBONKEYHANDLER + +static int im_is_active = FALSE; +#if 0 +static int im_start_row = 0; +static int im_start_col = 0; +#endif + +#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0])) + +static TSMDocumentID gTSMDocument; + +static void im_on_window_switch(int active); static EventHandlerUPP keyEventHandlerUPP = NULL; +static EventHandlerUPP winEventHandlerUPP = NULL; + +static pascal OSStatus gui_mac_handle_window_activate( + EventHandlerCallRef nextHandler, EventRef theEvent, void *data); + +static pascal OSStatus gui_mac_handle_text_input( + EventHandlerCallRef nextHandler, EventRef theEvent, void *data); + +static pascal OSStatus gui_mac_update_input_area( + EventHandlerCallRef nextHandler, EventRef theEvent); + +static pascal OSStatus gui_mac_unicode_key_event( + EventHandlerCallRef nextHandler, EventRef theEvent); + #endif @@ -127,6 +153,9 @@ ControlActionUPP gScrollDrag; /* Keeping track of which scrollbar is being dragged */ static ControlHandle dragged_sb = NULL; +/* Vector of char_u --> control index for hotkeys in dialogs */ +static short *gDialogHotKeys; + static struct { FMFontFamily family; @@ -137,7 +166,11 @@ static struct #ifdef MACOS_CONVERT # define USE_ATSUI_DRAWING +int p_macatsui_last; ATSUStyle gFontStyle; +# ifdef FEAT_MBYTE +ATSUStyle gWideFontStyle; +# endif Boolean gIsFontFallbackSet; #endif @@ -265,6 +298,11 @@ static void initialise_tabline(void); static WindowRef drawer = NULL; // TODO: put into gui.h #endif +#ifdef USE_ATSUI_DRAWING +static void gui_mac_set_font_attributes(GuiFont font); +static void gui_mac_dispose_atsui_style(void); +#endif + /* * ------------------------------------------------------------ * Conversion Utility @@ -1935,12 +1973,12 @@ gui_mac_doActivateEvent(EventRecord *event) /* Dim scrollbars */ if (whichWindow == gui.VimWindow) { - ControlRef rootControl; - GetRootControl(gui.VimWindow, &rootControl); - if ((event->modifiers) & activeFlag) - ActivateControl(rootControl); - else - DeactivateControl(rootControl); + ControlRef rootControl; + GetRootControl(gui.VimWindow, &rootControl); + if ((event->modifiers) & activeFlag) + ActivateControl(rootControl); + else + DeactivateControl(rootControl); } /* Activate */ @@ -1976,15 +2014,87 @@ gui_mac_doSuspendEvent(EventRecord *event) * Handle the key */ #ifdef USE_CARBONKEYHANDLER + static pascal OSStatus +gui_mac_handle_window_activate( + EventHandlerCallRef nextHandler, + EventRef theEvent, + void *data) +{ + UInt32 eventClass = GetEventClass(theEvent); + UInt32 eventKind = GetEventKind(theEvent); -static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the keys */ + if (eventClass == kEventClassWindow) + { + switch (eventKind) + { + case kEventWindowActivated: +#if defined(USE_IM_CONTROL) + im_on_window_switch(TRUE); +#endif + return noErr; + + case kEventWindowDeactivated: +#if defined(USE_IM_CONTROL) + im_on_window_switch(FALSE); +#endif + return noErr; + } + } + + return eventNotHandledErr; +} + + static pascal OSStatus +gui_mac_handle_text_input( + EventHandlerCallRef nextHandler, + EventRef theEvent, + void *data) +{ + UInt32 eventClass = GetEventClass(theEvent); + UInt32 eventKind = GetEventKind(theEvent); + + if (eventClass != kEventClassTextInput) + return eventNotHandledErr; + + if ((kEventTextInputUpdateActiveInputArea != eventKind) && + (kEventTextInputUnicodeForKeyEvent != eventKind) && + (kEventTextInputOffsetToPos != eventKind) && + (kEventTextInputPosToOffset != eventKind) && + (kEventTextInputGetSelectedText != eventKind)) + return eventNotHandledErr; + + switch (eventKind) + { + case kEventTextInputUpdateActiveInputArea: + return gui_mac_update_input_area(nextHandler, theEvent); + case kEventTextInputUnicodeForKeyEvent: + return gui_mac_unicode_key_event(nextHandler, theEvent); + + case kEventTextInputOffsetToPos: + case kEventTextInputPosToOffset: + case kEventTextInputGetSelectedText: + break; + } + + return eventNotHandledErr; +} + + static pascal +OSStatus gui_mac_update_input_area( + EventHandlerCallRef nextHandler, + EventRef theEvent) +{ + return eventNotHandledErr; +} + +static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the + keys */ # define INLINE_KEY_BUFFER_SIZE 80 static pascal OSStatus -gui_mac_doKeyEventCarbon( +gui_mac_unicode_key_event( EventHandlerCallRef nextHandler, - EventRef theEvent, - void *data) + EventRef theEvent) { /* Multibyte-friendly key event handler */ OSStatus err = -1; @@ -2000,7 +2110,7 @@ gui_mac_doKeyEventCarbon( char_u *to = NULL; Boolean isSpecial = FALSE; int i; - EventRef keyEvent; + EventRef keyEvent; /* Mask the mouse (as per user setting) */ if (p_mh) @@ -2008,39 +2118,39 @@ gui_mac_doKeyEventCarbon( /* Don't use the keys when the dialog wants them. */ if (dialog_busy) - return eventNotHandledErr; + return eventNotHandledErr; if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText, - typeUnicodeText, NULL, 0, &actualSize, NULL)) - return eventNotHandledErr; + typeUnicodeText, NULL, 0, &actualSize, NULL)) + return eventNotHandledErr; text = (UniChar *)alloc(actualSize); if (!text) - return eventNotHandledErr; + return eventNotHandledErr; err = GetEventParameter(theEvent, kEventParamTextInputSendText, - typeUnicodeText, NULL, actualSize, NULL, text); + typeUnicodeText, NULL, actualSize, NULL, text); require_noerr(err, done); err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent, - typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent); + typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent); require_noerr(err, done); err = GetEventParameter(keyEvent, kEventParamKeyModifiers, - typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); + typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); require_noerr(err, done); err = GetEventParameter(keyEvent, kEventParamKeyCode, - typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym); + typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym); require_noerr(err, done); err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes, - typeChar, NULL, sizeof(char), NULL, &charcode); + typeChar, NULL, sizeof(char), NULL, &charcode); require_noerr(err, done); #ifndef USE_CMD_KEY if (modifiers & cmdKey) - goto done; /* Let system handle Cmd+... */ + goto done; /* Let system handle Cmd+... */ #endif key_char = charcode; @@ -2048,84 +2158,84 @@ gui_mac_doKeyEventCarbon( /* Find the special key (eg., for cursor keys) */ if (actualSize <= sizeof(UniChar) && - ((text[0] < 0x20) || (text[0] == 0x7f))) + ((text[0] < 0x20) || (text[0] == 0x7f))) { - for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i) - if (special_keys[i].key_sym == key_sym) - { - key_char = TO_SPECIAL(special_keys[i].vim_code0, - special_keys[i].vim_code1); - key_char = simplify_key(key_char, - (int *)&vimModifiers); - isSpecial = TRUE; - break; - } + for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i) + if (special_keys[i].key_sym == key_sym) + { + key_char = TO_SPECIAL(special_keys[i].vim_code0, + special_keys[i].vim_code1); + key_char = simplify_key(key_char, + (int *)&vimModifiers); + isSpecial = TRUE; + break; + } } /* Intercept CMD-. and CTRL-c */ if (((modifiers & controlKey) && key_char == 'c') || - ((modifiers & cmdKey) && key_char == '.')) - got_int = TRUE; + ((modifiers & cmdKey) && key_char == '.')) + got_int = TRUE; if (!isSpecial) { - /* remove SHIFT for keys that are already shifted, e.g., - * '(' and '*' */ - if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char)) - vimModifiers &= ~MOD_MASK_SHIFT; + /* remove SHIFT for keys that are already shifted, e.g., + * '(' and '*' */ + if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char)) + vimModifiers &= ~MOD_MASK_SHIFT; - /* remove CTRL from keys that already have it */ - if (key_char < 0x20) - vimModifiers &= ~MOD_MASK_CTRL; + /* remove CTRL from keys that already have it */ + if (key_char < 0x20) + vimModifiers &= ~MOD_MASK_CTRL; - /* don't process unicode characters here */ - if (!IS_SPECIAL(key_char)) - { - /* Following code to simplify and consolidate vimModifiers - * taken liberally from gui_w48.c */ - key_char = simplify_key(key_char, (int *)&vimModifiers); + /* don't process unicode characters here */ + if (!IS_SPECIAL(key_char)) + { + /* Following code to simplify and consolidate vimModifiers + * taken liberally from gui_w48.c */ + key_char = simplify_key(key_char, (int *)&vimModifiers); - /* Interpret META, include SHIFT, etc. */ - key_char = extract_modifiers(key_char, (int *)&vimModifiers); - if (key_char == CSI) - key_char = K_CSI; + /* Interpret META, include SHIFT, etc. */ + key_char = extract_modifiers(key_char, (int *)&vimModifiers); + if (key_char == CSI) + key_char = K_CSI; - if (IS_SPECIAL(key_char)) - isSpecial = TRUE; - } + if (IS_SPECIAL(key_char)) + isSpecial = TRUE; + } } if (vimModifiers) { - result[len++] = CSI; - result[len++] = KS_MODIFIER; - result[len++] = vimModifiers; + result[len++] = CSI; + result[len++] = KS_MODIFIER; + result[len++] = vimModifiers; } if (isSpecial && IS_SPECIAL(key_char)) { - result[len++] = CSI; - result[len++] = K_SECOND(key_char); - result[len++] = K_THIRD(key_char); + result[len++] = CSI; + result[len++] = K_SECOND(key_char); + result[len++] = K_THIRD(key_char); } else { - encLen = actualSize; - to = mac_utf16_to_enc(text, actualSize, &encLen); - if (to) - { - /* This is basically add_to_input_buf_csi() */ - for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i) - { - result[len++] = to[i]; - if (to[i] == CSI) - { - result[len++] = KS_EXTRA; - result[len++] = (int)KE_CSI; - } - } - vim_free(to); - } + encLen = actualSize; + to = mac_utf16_to_enc(text, actualSize, &encLen); + if (to) + { + /* This is basically add_to_input_buf_csi() */ + for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i) + { + result[len++] = to[i]; + if (to[i] == CSI) + { + result[len++] = KS_EXTRA; + result[len++] = (int)KE_CSI; + } + } + vim_free(to); + } } add_to_input_buf(result, len); @@ -2135,10 +2245,10 @@ done: vim_free(text); if (err == noErr) { - /* Fake event to wake up WNE (required to get - * key repeat working */ - PostEvent(keyUp, 0); - return noErr; + /* Fake event to wake up WNE (required to get + * key repeat working */ + PostEvent(keyUp, 0); + return noErr; } return eventNotHandledErr; @@ -2334,7 +2444,7 @@ gui_mac_doMouseDownEvent(EventRecord *theEvent) /* prevent that the vim window size changes if it's activated by a click into the tab pane */ if (whichWindow == drawer) - return; + return; #endif switch (thePart) @@ -2569,11 +2679,11 @@ gui_mac_handle_event(EventRecord *event) if (IsShowContextualMenuClick(event)) { # if 0 - gui_mac_handle_contextual_menu(event); + gui_mac_handle_contextual_menu(event); # else - gui_mac_doMouseDownEvent(event); + gui_mac_doMouseDownEvent(event); # endif - return; + return; } /* Handle normal event */ @@ -2832,7 +2942,6 @@ gui_mch_prepare(int *argc, char **argv) # else /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr) * of TN2015 - * This technic remove the ../Contents/MacOS/etc part */ (void)GetCurrentProcess(&psn); /* if (err != noErr) return err; */ @@ -2931,14 +3040,11 @@ receiveHandler(WindowRef theWindow, void *handlerRefCon, DragRef theDrag) gui_mch_init(void) { /* TODO: Move most of this stuff toward gui_mch_init */ - Rect windRect; - MenuHandle pomme; - EventTypeSpec eventTypeSpec; + Rect windRect; + MenuHandle pomme; EventHandlerRef mouseWheelHandlerRef; -#ifdef USE_CARBONKEYHANDLER - EventHandlerRef keyEventHandlerRef; -#endif - ControlRef rootControl; + EventTypeSpec eventTypeSpec; + ControlRef rootControl; if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr) gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */ @@ -3042,16 +3148,47 @@ gui_mch_init(void) } #ifdef USE_CARBONKEYHANDLER - eventTypeSpec.eventClass = kEventClassTextInput; - eventTypeSpec.eventKind = kEventUnicodeForKeyEvent; - keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon); - if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1, - &eventTypeSpec, NULL, &keyEventHandlerRef)) + InterfaceTypeList supportedServices = { kUnicodeDocument }; + NewTSMDocument(1, supportedServices, &gTSMDocument, 0); + + /* We don't support inline input yet, use input window by default */ + UseInputWindow(gTSMDocument, TRUE); + + /* Should we activate the document by default? */ + // ActivateTSMDocument(gTSMDocument); + + EventTypeSpec textEventTypes[] = { + { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, + { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, + { kEventClassTextInput, kEventTextInputPosToOffset }, + { kEventClassTextInput, kEventTextInputOffsetToPos }, + }; + + keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_text_input); + if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, + NR_ELEMS(textEventTypes), + textEventTypes, NULL, NULL)) { - keyEventHandlerRef = NULL; DisposeEventHandlerUPP(keyEventHandlerUPP); keyEventHandlerUPP = NULL; } + + EventTypeSpec windowEventTypes[] = { + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowDeactivated }, + }; + + /* Install window event handler to support TSMDocument activate and + * deactivate */ + winEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_window_activate); + if (noErr != InstallWindowEventHandler(gui.VimWindow, + winEventHandlerUPP, + NR_ELEMS(windowEventTypes), + windowEventTypes, NULL, NULL)) + { + DisposeEventHandlerUPP(winEventHandlerUPP); + winEventHandlerUPP = NULL; + } #endif /* @@ -3107,6 +3244,19 @@ gui_mch_open(void) return OK; } +#ifdef USE_ATSUI_DRAWING + static void +gui_mac_dispose_atsui_style(void) +{ + if (p_macatsui && gFontStyle) + ATSUDisposeStyle(gFontStyle); +#ifdef FEAT_MBYTE + if (p_macatsui && gWideFontStyle) + ATSUDisposeStyle(gWideFontStyle); +#endif +} +#endif + void gui_mch_exit(int rc) { @@ -3122,8 +3272,13 @@ gui_mch_exit(int rc) DisposeEventHandlerUPP(mouseWheelHandlerUPP); #ifdef USE_ATSUI_DRAWING - if (p_macatsui && gFontStyle) - ATSUDisposeStyle(gFontStyle); + gui_mac_dispose_atsui_style(); +#endif + +#ifdef USE_CARBONKEYHANDLER + FixTSMDocument(gTSMDocument); + DeactivateTSMDocument(gTSMDocument); + DeleteTSMDocument(gTSMDocument); #endif /* Exit to shell? */ @@ -3263,6 +3418,26 @@ gui_mac_select_font(char_u *font_name) return selected_font; } +#ifdef USE_ATSUI_DRAWING + static void +gui_mac_create_atsui_style(void) +{ + if (p_macatsui && gFontStyle == NULL) + { + if (ATSUCreateStyle(&gFontStyle) != noErr) + gFontStyle = NULL; + } +#ifdef FEAT_MBYTE + if (p_macatsui && gWideFontStyle == NULL) + { + if (ATSUCreateStyle(&gWideFontStyle) != noErr) + gWideFontStyle = NULL; + } +#endif + + p_macatsui_last = p_macatsui; +} +#endif /* * Initialise vim to use the font with the given name. Return FAIL if the font @@ -3280,11 +3455,7 @@ gui_mch_init_font(char_u *font_name, int fontset) char_u used_font_name[512]; #ifdef USE_ATSUI_DRAWING - if (p_macatsui && gFontStyle == NULL) - { - if (ATSUCreateStyle(&gFontStyle) != noErr) - gFontStyle = NULL; - } + gui_mac_create_atsui_style(); #endif if (font_name == NULL) @@ -3348,49 +3519,8 @@ gui_mch_init_font(char_u *font_name, int fontset) gui.char_height = font_info.ascent + font_info.descent + p_linespace; #ifdef USE_ATSUI_DRAWING - ATSUFontID fontID; - Fixed fontSize; - ATSStyleRenderingOptions fontOptions; - if (p_macatsui && gFontStyle) - { - fontID = font & 0xFFFF; - fontSize = Long2Fix(font >> 16); - - /* No antialiasing by default (do not attempt to touch antialising - * options on pre-Jaguar) */ - fontOptions = - (gMacSystemVersion >= 0x1020) ? - kATSStyleNoAntiAliasing : - kATSStyleNoOptions; - - ATSUAttributeTag attribTags[] = - { - kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag, - kATSUMaxATSUITagValue+1 - }; - ByteCount attribSizes[] = - { - sizeof(ATSUFontID), sizeof(Fixed), - sizeof(ATSStyleRenderingOptions), sizeof font - }; - ATSUAttributeValuePtr attribValues[] = - { - &fontID, &fontSize, &fontOptions, &font - }; - - /* Convert font id to ATSUFontID */ - if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr) - { - if (ATSUSetAttributes(gFontStyle, - (sizeof attribTags)/sizeof(ATSUAttributeTag), - attribTags, attribSizes, attribValues) != noErr) - { - ATSUDisposeStyle(gFontStyle); - gFontStyle = NULL; - } - } - } + gui_mac_set_font_attributes(font); #endif return OK; @@ -3447,6 +3577,68 @@ gui_mch_get_fontname(GuiFont font, char_u *name) } #endif +#ifdef USE_ATSUI_DRAWING + static void +gui_mac_set_font_attributes(GuiFont font) +{ + ATSUFontID fontID; + Fixed fontSize; + Fixed fontWidth; + + fontID = font & 0xFFFF; + fontSize = Long2Fix(font >> 16); + fontWidth = Long2Fix(gui.char_width); + + ATSUAttributeTag attribTags[] = + { + kATSUFontTag, kATSUSizeTag, kATSUImposeWidthTag, + kATSUMaxATSUITagValue + 1 + }; + + ByteCount attribSizes[] = + { + sizeof(ATSUFontID), sizeof(Fixed), sizeof(fontWidth), + sizeof(font) + }; + + ATSUAttributeValuePtr attribValues[] = + { + &fontID, &fontSize, &fontWidth, &font + }; + + if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr) + { + if (ATSUSetAttributes(gFontStyle, + (sizeof attribTags) / sizeof(ATSUAttributeTag), + attribTags, attribSizes, attribValues) != noErr) + { +# ifndef NDEBUG + fprintf(stderr, "couldn't set font style\n"); +# endif + ATSUDisposeStyle(gFontStyle); + gFontStyle = NULL; + } + +#ifdef FEAT_MBYTE + if (has_mbyte) + { + /* FIXME: we should use a more mbyte sensitive way to support + * wide font drawing */ + fontWidth = Long2Fix(gui.char_width * 2); + + if (ATSUSetAttributes(gWideFontStyle, + (sizeof attribTags) / sizeof(ATSUAttributeTag), + attribTags, attribSizes, attribValues) != noErr) + { + ATSUDisposeStyle(gWideFontStyle); + gWideFontStyle = NULL; + } + } +#endif + } +} +#endif + /* * Set the current text font. */ @@ -3456,63 +3648,19 @@ gui_mch_set_font(GuiFont font) #ifdef USE_ATSUI_DRAWING GuiFont currFont; ByteCount actualFontByteCount; - ATSUFontID fontID; - Fixed fontSize; - ATSStyleRenderingOptions fontOptions; if (p_macatsui && gFontStyle) { /* Avoid setting same font again */ - if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font, - &currFont, &actualFontByteCount) == noErr && - actualFontByteCount == (sizeof font)) + if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue + 1, + sizeof(font), &currFont, &actualFontByteCount) == noErr + && actualFontByteCount == (sizeof font)) { if (currFont == font) return; } - fontID = font & 0xFFFF; - fontSize = Long2Fix(font >> 16); - /* Respect p_antialias setting only for wide font. - * The reason for doing this at the moment is a bit complicated, - * but it's mainly because a) latin (non-wide) aliased fonts - * look bad in OS X 10.3.x and below (due to a bug in ATS), and - * b) wide multibyte input does not suffer from that problem. */ - /*fontOptions = - (p_antialias && (font == gui.wide_font)) ? - kATSStyleNoOptions : kATSStyleNoAntiAliasing; - */ - /*fontOptions = kATSStyleAntiAliasing;*/ - - ATSUAttributeTag attribTags[] = - { - kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag, - kATSUMaxATSUITagValue+1 - }; - ByteCount attribSizes[] = - { - sizeof(ATSUFontID), sizeof(Fixed), - sizeof(ATSStyleRenderingOptions), sizeof font - }; - ATSUAttributeValuePtr attribValues[] = - { - &fontID, &fontSize, &fontOptions, &font - }; - - if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr) - { - if (ATSUSetAttributes(gFontStyle, - (sizeof attribTags)/sizeof(ATSUAttributeTag), - attribTags, attribSizes, attribValues) != noErr) - { -# ifndef NDEBUG - fprintf(stderr, "couldn't set font style\n"); -# endif - ATSUDisposeStyle(gFontStyle); - gFontStyle = NULL; - } - } - + gui_mac_set_font_attributes(font); } if (p_macatsui && !gIsFontFallbackSet) @@ -3536,7 +3684,9 @@ gui_mch_set_font(GuiFont font) &fallbackFonts, NULL) == noErr) { - ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred); + ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), + &fallbackFonts, + kATSUSequentialFallbacksPreferred); } /* ATSUAttributeValuePtr fallbackValues[] = { }; @@ -3921,7 +4071,10 @@ draw_string_ATSUI(int row, int col, char_u *s, int len, int flags) /* - ATSUI automatically antialiases text (Someone) * - for some reason it does not work... (Jussi) */ - +#ifdef MAC_ATSUI_DEBUG + fprintf(stderr, "row = %d, col = %d, len = %d: '%c'\n", + row, col, len, len == 1 ? s[0] : ' '); +#endif /* * When antialiasing we're using srcOr mode, we have to clear the block * before drawing the text. @@ -3956,35 +4109,122 @@ draw_string_ATSUI(int row, int col, char_u *s, int len, int flags) } { - /* Use old-style, non-antialiased QuickDraw text rendering. */ TextMode(srcCopy); TextFace(normal); - /* SelectFont(hdc, gui.currFont); */ - + /* SelectFont(hdc, gui.currFont); */ if (flags & DRAW_TRANSP) { TextMode(srcOr); } MoveTo(TEXT_X(col), TEXT_Y(row)); - ATSUTextLayout textLayout; - if (ATSUCreateTextLayoutWithTextPtr(tofree, - kATSUFromTextBeginning, kATSUToTextEnd, - utf16_len, - (gFontStyle ? 1 : 0), &utf16_len, - (gFontStyle ? &gFontStyle : NULL), - &textLayout) == noErr) + if (gFontStyle && flags & DRAW_BOLD) { + Boolean attValue = true; + ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag }; + ByteCount attribSizes[] = { sizeof(Boolean) }; + ATSUAttributeValuePtr attribValues[] = { &attValue }; + + ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, attribValues); + } + +#ifdef FEAT_MBYTE + if (has_mbyte) + { + int n, width_in_cell, last_width_in_cell; + UniCharArrayOffset offset = 0; + UniCharCount yet_to_draw = 0; + ATSUTextLayout textLayout; + ATSUStyle textStyle; + + last_width_in_cell = 1; + ATSUCreateTextLayout(&textLayout); + ATSUSetTextPointerLocation(textLayout, tofree, + kATSUFromTextBeginning, + kATSUToTextEnd, utf16_len); + /* + ATSUSetRunStyle(textLayout, gFontStyle, + kATSUFromTextBeginning, kATSUToTextEnd); */ + + /* Compute the length in display cells. */ + for (n = 0; n < len; n += MB_BYTE2LEN(s[n])) + { + width_in_cell = (*mb_ptr2cells)(s + n); + + /* probably we are switching from single byte character + * to multibyte characters (which requires more than one + * cell to draw) */ + if (width_in_cell != last_width_in_cell) + { +#ifdef MAC_ATSUI_DEBUG + fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n", + n, last_width_in_cell, width_in_cell, offset, yet_to_draw); +#endif + textStyle = last_width_in_cell > 1 ? gWideFontStyle + : gFontStyle; + + ATSUSetRunStyle(textLayout, textStyle, offset, yet_to_draw); + offset += yet_to_draw; + yet_to_draw = 0; + last_width_in_cell = width_in_cell; + } + + yet_to_draw++; + } + + if (yet_to_draw) + { +#ifdef MAC_ATSUI_DEBUG + fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n", + n, last_width_in_cell, width_in_cell, offset, yet_to_draw); +#endif + /* finish the rest style */ + textStyle = width_in_cell > 1 ? gWideFontStyle : gFontStyle; + ATSUSetRunStyle(textLayout, textStyle, offset, kATSUToTextEnd); + } + ATSUSetTransientFontMatching(textLayout, TRUE); - ATSUDrawText(textLayout, - kATSUFromTextBeginning, kATSUToTextEnd, - kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); - + kATSUFromTextBeginning, kATSUToTextEnd, + kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); ATSUDisposeTextLayout(textLayout); } + else +#endif + { + ATSUTextLayout textLayout; + + if (ATSUCreateTextLayoutWithTextPtr(tofree, + kATSUFromTextBeginning, kATSUToTextEnd, + utf16_len, + (gFontStyle ? 1 : 0), &utf16_len, + (gFontStyle ? &gFontStyle : NULL), + &textLayout) == noErr) + { + ATSUSetTransientFontMatching(textLayout, TRUE); + + ATSUDrawText(textLayout, + kATSUFromTextBeginning, kATSUToTextEnd, + kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); + + ATSUDisposeTextLayout(textLayout); + } + } + + /* drawing is done, now reset bold to normal */ + if (gFontStyle && flags & DRAW_BOLD) + { + Boolean attValue = false; + + ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag }; + ByteCount attribSizes[] = { sizeof(Boolean) }; + ATSUAttributeValuePtr attribValues[] = { &attValue }; + + ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, + attribValues); + } } if (flags & DRAW_UNDERC) @@ -3998,6 +4238,13 @@ draw_string_ATSUI(int row, int col, char_u *s, int len, int flags) gui_mch_draw_string(int row, int col, char_u *s, int len, int flags) { #if defined(USE_ATSUI_DRAWING) + if (p_macatsui == 0 && p_macatsui_last != 0) + /* switch from macatsui to nomacatsui */ + gui_mac_dispose_atsui_style(); + else if (p_macatsui != 0 && p_macatsui_last == 0) + /* switch from nomacatsui to macatsui */ + gui_mac_create_atsui_style(); + if (p_macatsui) draw_string_ATSUI(row, col, s, len, flags); else @@ -4228,12 +4475,13 @@ gui_mch_wait_for_chars(int wtime) */ /* TODO: reduce wtime accordinly??? */ if (wtime > -1) - sleeppyTick = 60*wtime/1000; + sleeppyTick = 60 * wtime / 1000; else sleeppyTick = 32767; + if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn)) { - gui_mac_handle_event(&event); + gui_mac_handle_event(&event); if (input_available()) { allow_scrollbar = FALSE; @@ -5274,6 +5522,49 @@ macSetDialogItemText( SetDialogItemText(itemHandle, itemName); } + +/* ModalDialog() handler for message dialogs that have hotkey accelerators. + * Expects a mapping of hotkey char to control index in gDialogHotKeys; + * setting gDialogHotKeys to NULL disables any hotkey handling. + */ + static pascal Boolean +DialogHotkeyFilterProc ( + DialogRef theDialog, + EventRecord *event, + DialogItemIndex *itemHit) +{ + char_u keyHit; + + if (event->what == keyDown || event->what == autoKey) + { + keyHit = (event->message & charCodeMask); + + if (gDialogHotKeys && gDialogHotKeys[keyHit]) + { +#ifdef DEBUG_MAC_DIALOG_HOTKEYS + printf("user pressed hotkey '%c' --> item %d\n", keyHit, gDialogHotKeys[keyHit]); +#endif + *itemHit = gDialogHotKeys[keyHit]; + + /* When handing off to StdFilterProc, pretend that the user + * clicked the control manually. Note that this is also supposed + * to cause the button to hilite briefly (to give some user + * feedback), but this seems not to actually work (or it's too + * fast to be seen). + */ + event->what = kEventControlSimulateHit; + + return true; /* we took care of it */ + } + + /* Defer to the OS's standard behavior for this event. + * This ensures that Enter will still activate the default button. */ + return StdFilterProc(theDialog, event, itemHit); + } + return false; /* Let ModalDialog deal with it */ +} + + /* TODO: There have been some crashes with dialogs, check your inbox * (Jussi) */ @@ -5299,6 +5590,8 @@ gui_mch_dialog( GrafPtr oldPort; short itemHit; char_u *buttonChar; + short hotKeys[256]; /* map of hotkey -> control ID */ + char_u aHotKey; Rect box; short button; short lastButton; @@ -5326,6 +5619,8 @@ gui_mch_dialog( WindowRef theWindow; + ModalFilterUPP dialogUPP; + /* Check 'v' flag in 'guioptions': vertical button placement. */ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL); @@ -5365,6 +5660,9 @@ gui_mch_dialog( buttonChar = buttons; button = 0; + /* initialize the hotkey mapping */ + memset(hotKeys, 0, sizeof(hotKeys)); + for (;*buttonChar != 0;) { /* Get the name of the button */ @@ -5374,7 +5672,18 @@ gui_mch_dialog( { if (*buttonChar != DLG_HOTKEY_CHAR) name[++len] = *buttonChar; + else + { + aHotKey = (char_u)*(buttonChar+1); + if (aHotKey >= 'A' && aHotKey <= 'Z') + aHotKey = (char_u)((int)aHotKey + (int)'a' - (int)'A'); + hotKeys[aHotKey] = button; +#ifdef DEBUG_MAC_DIALOG_HOTKEYS + printf("### hotKey for button %d is '%c'\n", button, aHotKey); +#endif + } } + if (*buttonChar != 0) buttonChar++; name[0] = len; @@ -5443,7 +5752,13 @@ gui_mch_dialog( (void) C2PascalString(textfield, &name); SetDialogItemText(itemHandle, name); inputItm.width = StringWidth(name); + + /* Hotkeys don't make sense if there's a text field */ + gDialogHotKeys = NULL; } + else + /* Install hotkey table */ + gDialogHotKeys = (short *)&hotKeys; /* Set the and button. */ SetDialogDefaultItem(theDialog, dfltbutton); @@ -5532,10 +5847,13 @@ gui_mch_dialog( dialog_busy = TRUE; #endif + /* Prepare the shortcut-handling filterProc for handing to the dialog */ + dialogUPP = NewModalFilterUPP(DialogHotkeyFilterProc); + /* Hang until one of the button is hit */ do { - ModalDialog(nil, &itemHit); + ModalDialog(dialogUPP, &itemHit); } while ((itemHit < 1) || (itemHit > lastButton)); #ifdef USE_CARBONKEYHANDLER @@ -5558,6 +5876,9 @@ gui_mch_dialog( /* Restore the original graphical port */ SetPort(oldPort); + /* Free the modal filterProc */ + DisposeRoutineDescriptor(dialogUPP); + /* Get ride of th edialog (free memory) */ DisposeDialog(theDialog); @@ -6031,7 +6352,7 @@ char_u *FullPathFromFSSpec_save(FSSpec file) #endif } -#if defined(USE_IM_CONTROL) || defined(PROTO) +#if (defined(USE_IM_CONTROL) || defined(PROTO)) && defined(USE_CARBONKEYHANDLER) /* * Input Method Control functions. */ @@ -6042,7 +6363,71 @@ char_u *FullPathFromFSSpec_save(FSSpec file) void im_set_position(int row, int col) { +#if 0 /* TODO: Implement me! */ + im_start_row = row; + im_start_col = col; +#endif +} + +static ScriptLanguageRecord gTSLWindow; +static ScriptLanguageRecord gTSLInsert; +static ScriptLanguageRecord gTSLDefault = { 0, 0 }; + +static Component gTSCWindow; +static Component gTSCInsert; +static Component gTSCDefault; + +static int im_initialized = 0; + + static void +im_on_window_switch(int active) +{ + ScriptLanguageRecord *slptr = NULL; + OSStatus err; + + if (! gui.in_use) + return; + + if (im_initialized == 0) + { + im_initialized = 1; + + /* save default TSM component (should be U.S.) to default */ + GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault, + kKeyboardInputMethodClass); + } + + if (active == TRUE) + { + im_is_active = TRUE; + ActivateTSMDocument(gTSMDocument); + slptr = &gTSLWindow; + + if (slptr) + { + err = SetDefaultInputMethodOfClass(gTSCWindow, slptr, + kKeyboardInputMethodClass); + if (err == noErr) + err = SetTextServiceLanguage(slptr); + + if (err == noErr) + KeyScript(slptr->fScript | smKeyForceKeyScriptMask); + } + } + else + { + err = GetTextServiceLanguage(&gTSLWindow); + if (err == noErr) + slptr = &gTSLWindow; + + if (slptr) + GetDefaultInputMethodOfClass(&gTSCWindow, slptr, + kKeyboardInputMethodClass); + + im_is_active = FALSE; + DeactivateTSMDocument(gTSMDocument); + } } /* @@ -6051,7 +6436,57 @@ im_set_position(int row, int col) void im_set_active(int active) { - KeyScript(active ? smKeySysScript : smKeyRoman); + ScriptLanguageRecord *slptr = NULL; + OSStatus err; + + if (! gui.in_use) + return; + + if (im_initialized == 0) + { + im_initialized = 1; + + /* save default TSM component (should be U.S.) to default */ + GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault, + kKeyboardInputMethodClass); + } + + if (active == TRUE) + { + im_is_active = TRUE; + ActivateTSMDocument(gTSMDocument); + slptr = &gTSLInsert; + + if (slptr) + { + err = SetDefaultInputMethodOfClass(gTSCInsert, slptr, + kKeyboardInputMethodClass); + if (err == noErr) + err = SetTextServiceLanguage(slptr); + + if (err == noErr) + KeyScript(slptr->fScript | smKeyForceKeyScriptMask); + } + } + else + { + err = GetTextServiceLanguage(&gTSLInsert); + if (err == noErr) + slptr = &gTSLInsert; + + if (slptr) + GetDefaultInputMethodOfClass(&gTSCInsert, slptr, + kKeyboardInputMethodClass); + + /* restore to default when switch to normal mode, so than we could + * enter commands easier */ + SetDefaultInputMethodOfClass(gTSCDefault, &gTSLDefault, + kKeyboardInputMethodClass); + SetTextServiceLanguage(&gTSLDefault); + + im_is_active = FALSE; + DeactivateTSMDocument(gTSMDocument); + } } /* @@ -6060,9 +6495,10 @@ im_set_active(int active) int im_get_status(void) { - SInt32 script = GetScriptManagerVariable(smKeyScript); - return (script != smRoman - && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0; + if (! gui.in_use) + return 0; + + return im_is_active; } #endif /* defined(USE_IM_CONTROL) || defined(PROTO) */ @@ -6118,7 +6554,7 @@ getTabCount(void) int numTabs = 0; for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) - ++numTabs; + ++numTabs; return numTabs; } @@ -6126,8 +6562,8 @@ getTabCount(void) static OSStatus dbItemDataCallback(ControlRef browser, DataBrowserItemID itemID, - DataBrowserPropertyID property /* column id */, - DataBrowserItemDataRef itemData, + DataBrowserPropertyID property /* column id */, + DataBrowserItemDataRef itemData, Boolean changeValue) { OSStatus status = noErr; @@ -6170,9 +6606,9 @@ dbItemNotificationCallback(ControlRef browser, static void dbGetContextualMenuCallback(ControlRef browser, MenuRef *menu, - UInt32 *helpType, + UInt32 *helpType, CFStringRef *helpItemString, - AEDesc *selection) + AEDesc *selection) { // on mac os 9: kCMHelpItemNoHelp, but it's not the same *helpType = kCMHelpItemRemoveHelp; // OS X only ;-) @@ -6395,9 +6831,9 @@ initialise_tabline(void) gui_mch_show_tabline(int showit) { if (showit == 0) - CloseDrawer(drawer, true); + CloseDrawer(drawer, true); else - OpenDrawer(drawer, kWindowEdgeRight, true); + OpenDrawer(drawer, kWindowEdgeRight, true); } /* @@ -6425,11 +6861,11 @@ gui_mch_update_tabline(void) // adjust data browser if (tabLabels != NULL) { - int i; + int i; - for (i = 0; i < tabLabelsSize; ++i) - CFRelease(tabLabels[i]); - free(tabLabels); + for (i = 0; i < tabLabelsSize; ++i) + CFRelease(tabLabels[i]); + free(tabLabels); } tabLabels = (CFStringRef *)malloc(numTabs * sizeof(CFStringRef)); tabLabelsSize = numTabs; @@ -6438,7 +6874,7 @@ gui_mch_update_tabline(void) { if (tp == curtab) curtabidx = nr; - tabLabels[nr-1] = getTabLabel(tp); + tabLabels[nr-1] = getTabLabel(tp); } RemoveDataBrowserItems(dataBrowser, kDataBrowserNoItem, 0, NULL, diff --git a/src/if_cscope.c b/src/if_cscope.c index 52aa534014..0019559512 100644 --- a/src/if_cscope.c +++ b/src/if_cscope.c @@ -1400,7 +1400,7 @@ cs_lookup_cmd(eap) return NULL; /* Store length of eap->arg before it gets modified by strtok(). */ - eap_arg_len = STRLEN(eap->arg); + eap_arg_len = (int)STRLEN(eap->arg); if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL) return NULL; @@ -2096,6 +2096,18 @@ cs_read_prompt(i) return CSCOPE_SUCCESS; } +#if defined(UNIX) && defined(SIGALRM) +/* + * Used to catch and ignore SIGALRM below. + */ +/* ARGSUSED */ + static RETSIGTYPE +sig_handler SIGDEFARG(sigarg) +{ + /* do nothing */ + SIGRETURN; +} +#endif /* * PRIVATE: cs_release_csp @@ -2108,9 +2120,6 @@ cs_release_csp(i, freefnpp) int i; int freefnpp; { -#if defined(UNIX) - int pstat; -#else /* * Trying to exit normally (not sure whether it is fit to UNIX cscope */ @@ -2119,6 +2128,88 @@ cs_release_csp(i, freefnpp) (void)fputs("q\n", csinfo[i].to_fp); (void)fflush(csinfo[i].to_fp); } +#if defined(UNIX) + { + int waitpid_errno; + int pstat; + pid_t pid; + +# if defined(HAVE_SIGACTION) + struct sigaction sa, old; + + /* Use sigaction() to limit the waiting time to two seconds. */ + sigemptyset(&sa.sa_mask); + sa.sa_handler = sig_handler; + sa.sa_flags = SA_NODEFER; + sigaction(SIGALRM, &sa, &old); + alarm(2); /* 2 sec timeout */ + + /* Block until cscope exits or until timer expires */ + pid = waitpid(csinfo[i].pid, &pstat, 0); + waitpid_errno = errno; + + /* cancel pending alarm if still there and restore signal */ + alarm(0); + sigaction(SIGALRM, &old, NULL); +# else + int waited; + + /* Can't use sigaction(), loop for two seconds. First yield the CPU + * to give cscope a chance to exit quickly. */ + sleep(0); + for (waited = 0; waited < 40; ++waited) + { + pid = waitpid(csinfo[i].pid, &pstat, WNOHANG); + waitpid_errno = errno; + if (pid != 0) + break; /* break unless the process is still running */ + mch_delay(50L, FALSE); /* sleep 50 ms */ + } +# endif + /* + * If the cscope process is still running: kill it. + * Safety check: If the PID would be zero here, the entire X session + * would be killed. -1 and 1 are dangerous as well. + */ + if (pid < 0 && csinfo[i].pid > 1) + { +# ifdef ECHILD + int alive = TRUE; + + if (waitpid_errno == ECHILD) + { + /* + * When using 'vim -g', vim is forked and cscope process is + * no longer a child process but a sibling. So waitpid() + * fails with errno being ECHILD (No child processes). + * Don't send SIGKILL to cscope immediately but wait + * (polling) for it to exit normally as result of sending + * the "q" command, hence giving it a chance to clean up + * its temporary files. + */ + int waited; + + sleep(0); + for (waited = 0; waited < 40; ++waited) + { + /* Check whether cscope process is still alive */ + if (kill(csinfo[i].pid, 0) != 0) + { + alive = FALSE; /* cscope process no longer exists */ + break; + } + mch_delay(50L, FALSE); /* sleep 50ms */ + } + } + if (alive) +# endif + { + kill(csinfo[i].pid, SIGKILL); + (void)waitpid(csinfo[i].pid, &pstat, 0); + } + } + } +#else /* !UNIX */ if (csinfo[i].hProc != NULL) { /* Give cscope a chance to exit normally */ @@ -2133,18 +2224,6 @@ cs_release_csp(i, freefnpp) if (csinfo[i].to_fp != NULL) (void)fclose(csinfo[i].to_fp); - /* - * Safety check: If the PID would be zero here, the entire X session would - * be killed. -1 and 1 are dangerous as well. - */ -#if defined(UNIX) - if (csinfo[i].pid > 1) - { - kill(csinfo[i].pid, SIGTERM); - (void)waitpid(csinfo[i].pid, &pstat, 0); - } -#endif - if (freefnpp) { vim_free(csinfo[i].fname); diff --git a/src/if_ole.cpp b/src/if_ole.cpp index fad2097e12..b2057f973c 100644 --- a/src/if_ole.cpp +++ b/src/if_ole.cpp @@ -34,6 +34,12 @@ extern HWND s_hwnd; extern HWND vim_parent_hwnd; } +#if _MSC_VER < 1300 +/* Work around old versions of basetsd.h which wrongly declares + * UINT_PTR as unsigned long */ +# define UINT_PTR UINT +#endif + #include "if_ole.h" // Interface definitions #include "iid_ole.c" // UUID definitions (compile here) @@ -107,7 +113,7 @@ public: STDMETHOD(SendKeys)(BSTR keys); STDMETHOD(Eval)(BSTR expr, BSTR *result); STDMETHOD(SetForeground)(void); - STDMETHOD(GetHwnd)(UINT *result); + STDMETHOD(GetHwnd)(UINT_PTR *result); private: // Constructor is private - create using CVim::Create() @@ -288,9 +294,9 @@ CVim::Invoke( } STDMETHODIMP -CVim::GetHwnd(UINT *result) +CVim::GetHwnd(UINT_PTR *result) { - *result = (UINT) s_hwnd; + *result = (UINT_PTR)s_hwnd; return S_OK; } diff --git a/src/if_ole.h b/src/if_ole.h index 30191b843c..0b48b92ff1 100644 --- a/src/if_ole.h +++ b/src/if_ole.h @@ -79,7 +79,7 @@ EXTERN_C const IID IID_IVim; virtual HRESULT STDMETHODCALLTYPE SetForeground( void) = 0; virtual HRESULT STDMETHODCALLTYPE GetHwnd( - /* [retval][out] */ UINT __RPC_FAR *result) = 0; + /* [retval][out] */ UINT_PTR __RPC_FAR *result) = 0; }; @@ -143,7 +143,7 @@ EXTERN_C const IID IID_IVim; HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetHwnd )( IVim __RPC_FAR * This, - /* [retval][out] */ UINT __RPC_FAR *result); + /* [retval][out] */ UINT_PTR __RPC_FAR *result); END_INTERFACE } IVimVtbl; @@ -236,7 +236,7 @@ void __RPC_STUB IVim_SetForeground_Stub( HRESULT STDMETHODCALLTYPE IVim_GetHwnd_Proxy( IVim __RPC_FAR * This, - /* [retval][out] */ UINT __RPC_FAR *result); + /* [retval][out] */ UINT_PTR __RPC_FAR *result); void __RPC_STUB IVim_GetHwnd_Stub( diff --git a/src/if_ole.idl b/src/if_ole.idl index 83cde3acd9..3629fafcdb 100644 --- a/src/if_ole.idl +++ b/src/if_ole.idl @@ -20,7 +20,7 @@ interface IVim : IDispatch HRESULT SendKeys([in]BSTR keys); HRESULT Eval([in]BSTR expr, [out, retval]BSTR* result); HRESULT SetForeground(void); - HRESULT GetHwnd([out, retval]UINT* result); + HRESULT GetHwnd([out, retval]UINT_PTR* result); }; // Component and type library definitions diff --git a/src/main.c b/src/main.c index e415ab9bb7..856fa5f262 100644 --- a/src/main.c +++ b/src/main.c @@ -1605,15 +1605,15 @@ early_arg_scan(parmp) else if (STRICMP(argv[i], "--socketid") == 0) # endif { - unsigned int id; - int count; + long_u id; + int count; if (i == argc - 1) mainerr_arg_missing((char_u *)argv[i]); if (STRNICMP(argv[i+1], "0x", 2) == 0) - count = sscanf(&(argv[i + 1][2]), "%x", &id); + count = sscanf(&(argv[i + 1][2]), SCANF_HEX_LONG_U, &id); else - count = sscanf(argv[i+1], "%u", &id); + count = sscanf(argv[i + 1], SCANF_DECIMAL_LONG_U, &id); if (count != 1) mainerr(ME_INVALID_ARG, (char_u *)argv[i]); else diff --git a/src/mark.c b/src/mark.c index 2accbba1fb..7428969860 100644 --- a/src/mark.c +++ b/src/mark.c @@ -522,7 +522,7 @@ fname2fnum(fm) int len; expand_env((char_u *)"~/", NameBuff, MAXPATHL); - len = STRLEN(NameBuff); + len = (int)STRLEN(NameBuff); vim_strncpy(NameBuff + len, fm->fname + 2, MAXPATHL - len - 1); } else diff --git a/src/misc2.c b/src/misc2.c index fd0405fd9a..6a562d8893 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -751,7 +751,7 @@ vim_mem_profile_dump() #endif /* - * Note: if unsinged is 16 bits we can only allocate up to 64K with alloc(). + * Note: if unsigned is 16 bits we can only allocate up to 64K with alloc(). * Use lalloc for larger blocks. */ char_u * @@ -1082,7 +1082,11 @@ free_all_mem() win_free_all(); #endif - /* Free all buffers. */ + /* Free all buffers. Reset 'autochdir' to avoid accessing things that + * were freed already. */ +#ifdef FEAT_AUTOCHDIR + p_acd = FALSE; +#endif for (buf = firstbuf; buf != NULL; ) { nextbuf = buf->b_next; diff --git a/src/netbeans.c b/src/netbeans.c index e3e32008e9..ed415a5ccb 100644 --- a/src/netbeans.c +++ b/src/netbeans.c @@ -1216,7 +1216,7 @@ nb_partialremove(linenr_T lnum, colnr_T first, colnr_T last) int lastbyte = last; oldtext = ml_get(lnum); - oldlen = STRLEN(oldtext); + oldlen = (int)STRLEN(oldtext); if (first >= (colnr_T)oldlen || oldlen == 0) /* just in case */ return; if (lastbyte >= oldlen) @@ -1241,8 +1241,8 @@ nb_joinlines(linenr_T first, linenr_T other) int len_first, len_other; char_u *p; - len_first = STRLEN(ml_get(first)); - len_other = STRLEN(ml_get(other)); + len_first = (int)STRLEN(ml_get(first)); + len_other = (int)STRLEN(ml_get(other)); p = alloc((unsigned)(len_first + len_other + 1)); if (p != NULL) { diff --git a/src/normal.c b/src/normal.c index c509d774a2..00679ae26b 100644 --- a/src/normal.c +++ b/src/normal.c @@ -8364,6 +8364,7 @@ nv_wordcmd(cap) int n; int word_end; int flag = FALSE; + pos_T startpos = curwin->w_cursor; /* * Set inclusive for the "E" and "e" command. @@ -8424,8 +8425,9 @@ nv_wordcmd(cap) else n = fwd_word(cap->count1, cap->arg, cap->oap->op_type != OP_NOP); - /* Don't leave the cursor on the NUL past the end of line. */ - if (n != FAIL) + /* Don't leave the cursor on the NUL past the end of line. Unless we + * didn't move it forward. */ + if (lt(startpos, curwin->w_cursor)) adjust_cursor(cap->oap); if (n == FAIL && cap->oap->op_type == OP_NOP) diff --git a/src/ops.c b/src/ops.c index 5433f38526..ba774b8772 100644 --- a/src/ops.c +++ b/src/ops.c @@ -4380,7 +4380,7 @@ op_format(oap, keep_cursor) if (keep_cursor) saved_cursor = oap->cursor_start; - format_lines(oap->line_count); + format_lines(oap->line_count, keep_cursor); /* * Leave the cursor at the first non-blank of the last formatted line. @@ -4495,8 +4495,9 @@ fex_format(lnum, count, c) * first line. */ void -format_lines(line_count) +format_lines(line_count, avoid_fex) linenr_T line_count; + int avoid_fex; /* don't use 'formatexpr' */ { int max_len; int is_not_par; /* current line not part of parag. */ @@ -4666,7 +4667,7 @@ format_lines(line_count) #ifdef FEAT_COMMENTS + (do_comments ? INSCHAR_DO_COM : 0) #endif - , second_indent); + + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent); State = old_State; p_smd = smd_save; second_indent = -1; diff --git a/src/option.c b/src/option.c index d60b37fa12..7e01dc5fb8 100644 --- a/src/option.c +++ b/src/option.c @@ -1856,7 +1856,8 @@ static struct vimoption }, {"paragraphs", "para", P_STRING|P_VI_DEF, (char_u *)&p_para, PV_NONE, - {(char_u *)"IPLPPPQPP LIpplpipbp", (char_u *)0L}}, + {(char_u *)"IPLPPPQPP TPHPLIPpLpItpplpipbp", + (char_u *)0L}}, {"paste", NULL, P_BOOL|P_VI_DEF|P_PRI_MKRC, (char_u *)&p_paste, PV_NONE, {(char_u *)FALSE, (char_u *)0L}}, diff --git a/src/os_unix.c b/src/os_unix.c index 9a21782ebd..f66e4ef460 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -269,8 +269,9 @@ static struct signalinfo #ifdef SIGVTALRM {SIGVTALRM, "VTALRM", TRUE}, #endif -#if defined(SIGPROF) && !defined(FEAT_MZSCHEME) - /* MzScheme uses SIGPROF for its own needs */ +#if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING) + /* MzScheme uses SIGPROF for its own needs; On Linux with profiling + * this makes Vim exit. WE_ARE_PROFILING is defined in Makefile. */ {SIGPROF, "PROF", TRUE}, #endif #ifdef SIGXCPU diff --git a/src/os_win32.c b/src/os_win32.c index b0502b26b5..54837ecb2e 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -2856,7 +2856,7 @@ handler_routine( windgoto((int)Rows - 1, 0); g_fForceExit = TRUE; - sprintf((char *)IObuff, _("Vim: Caught %s event\n"), + vim_snprintf((char *)IObuff, IOSIZE, _("Vim: Caught %s event\n"), (dwCtrlType == CTRL_CLOSE_EVENT ? _("close") : dwCtrlType == CTRL_LOGOFF_EVENT @@ -3282,12 +3282,13 @@ mch_call_shell( { /* we use "command" or "cmd" to start the shell; slow but easy */ char_u *newcmd; - - newcmd = lalloc((long_u) ( + long_u cmdlen = ( #ifdef FEAT_GUI_W32 STRLEN(vimrun_path) + #endif - STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10), TRUE); + STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10); + + newcmd = lalloc(cmdlen, TRUE); if (newcmd != NULL) { char_u *cmdbase = (*cmd == '"' ? cmd + 1 : cmd); @@ -3373,14 +3374,15 @@ mch_call_shell( if (!s_dont_use_vimrun) /* Use vimrun to execute the command. It opens a console * window, which can be closed without killing Vim. */ - sprintf((char *)newcmd, "%s%s%s %s %s", + vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s", vimrun_path, (msg_silent != 0 || (options & SHELL_DOOUT)) ? "-s " : "", p_sh, p_shcf, cmd); else #endif - sprintf((char *)newcmd, "%s %s %s", p_sh, p_shcf, cmd); + vim_snprintf((char *)newcmd, cmdlen, "%s %s %s", + p_sh, p_shcf, cmd); x = mch_system((char *)newcmd, options); } vim_free(newcmd); @@ -4664,12 +4666,29 @@ mch_fopen(char *name, char *mode) # endif ) { +# if defined(DEBUG) && _MSC_VER > 1200 + /* Work around an annoying assertion in the Microsoft debug CRT + * when mode's text/binary setting doesn't match _get_fmode(). */ + char newMode = mode[strlen(mode) - 1]; + int oldMode = 0; + + _get_fmode(&oldMode); + if (newMode == 't') + _set_fmode(_O_TEXT); + else if (newMode == 'b') + _set_fmode(_O_BINARY); +# endif wn = enc_to_ucs2(name, NULL); wm = enc_to_ucs2(mode, NULL); if (wn != NULL && wm != NULL) f = _wfopen(wn, wm); vim_free(wn); vim_free(wm); + +# if defined(DEBUG) && _MSC_VER > 1200 + _set_fmode(oldMode); +# endif + if (f != NULL) return f; /* Retry with non-wide function (for Windows 98). Can't use diff --git a/src/popupmnu.c b/src/popupmnu.c index 4dd3a94882..1d747a6bf3 100644 --- a/src/popupmnu.c +++ b/src/popupmnu.c @@ -337,7 +337,7 @@ pum_redraw() if (rt != NULL) { - len = STRLEN(rt); + len = (int)STRLEN(rt); if (len > pum_width) { for (j = pum_width; j < len; ++j) diff --git a/src/proto/ops.pro b/src/proto/ops.pro index 9ce80b3a9c..37c319414f 100644 --- a/src/proto/ops.pro +++ b/src/proto/ops.pro @@ -41,7 +41,7 @@ int do_join __ARGS((int insert_space)); void op_format __ARGS((oparg_T *oap, int keep_cursor)); void op_formatexpr __ARGS((oparg_T *oap)); int fex_format __ARGS((linenr_T lnum, long count, int c)); -void format_lines __ARGS((linenr_T line_count)); +void format_lines __ARGS((linenr_T line_count, int avoid_fex)); int paragraph_start __ARGS((linenr_T lnum)); int do_addsub __ARGS((int command, linenr_T Prenum1)); int read_viminfo_register __ARGS((vir_T *virp, int force)); diff --git a/src/quickfix.c b/src/quickfix.c index d2b24bb10b..9259c4318b 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -106,7 +106,9 @@ struct efm_S static int qf_init_ext __ARGS((qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast)); static void qf_new_list __ARGS((qf_info_T *qi)); +static void ll_free_all __ARGS((qf_info_T **pqi)); static int qf_add_entry __ARGS((qf_info_T *qi, qfline_T **prevp, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid)); +static qf_info_T *ll_new_list __ARGS((void)); static void qf_msg __ARGS((qf_info_T *qi)); static void qf_free __ARGS((qf_info_T *qi, int idx)); static char_u *qf_types __ARGS((int, int)); diff --git a/src/screen.c b/src/screen.c index a739927254..7be34fa99b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -4527,7 +4527,7 @@ win_line(wp, lnum, startrow, endrow, nochange) #endif col == W_WIDTH(wp) - 1) && (*ptr != NUL - || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) + || (wp->w_p_list && lcs_eol_one > 0) || (n_extra && (c_extra != NUL || *p_extra != NUL)))) { c = lcs_ext; diff --git a/src/search.c b/src/search.c index 59fa322340..a25816fda8 100644 --- a/src/search.c +++ b/src/search.c @@ -547,7 +547,10 @@ searchit(win, buf, pos, dir, pat, count, options, pat_use, stop_lnum, tm) return FAIL; } - if (options & SEARCH_START) + /* When not accepting a match at the start position set "extra_col" to a + * non-zero value. Don't do that when starting at MAXCOL, since MAXCOL + + * 1 is zero. */ + if ((options & SEARCH_START) || pos->col == MAXCOL) extra_col = 0; #ifdef FEAT_MBYTE /* Watch out for the "col" being MAXCOL - 2, used in a closed fold. */ diff --git a/src/spell.c b/src/spell.c index f45be18c2d..567c6cd363 100644 --- a/src/spell.c +++ b/src/spell.c @@ -2268,6 +2268,8 @@ spell_move_to(wp, dir, allwords, curline, attrp) /* * For spell checking: concatenate the start of the following line "line" into * "buf", blanking-out special characters. Copy less then "maxlen" bytes. + * Keep the blanks at the start of the next line, this is used in win_line() + * to skip those bytes if the word was OK. */ void spell_cat_line(buf, line, maxlen) @@ -2284,12 +2286,14 @@ spell_cat_line(buf, line, maxlen) if (*p != NUL) { - *buf = ' '; - vim_strncpy(buf + 1, line, maxlen - 2); - n = (int)(p - line); - if (n >= maxlen) - n = maxlen - 1; - vim_memset(buf + 1, ' ', n); + /* Only worth concatenating if there is something else than spaces to + * concatenate. */ + n = (int)(p - line) + 1; + if (n < maxlen - 1) + { + vim_memset(buf, ' ', n); + vim_strncpy(buf + n, p, maxlen - 1 - n); + } } } diff --git a/src/version.c b/src/version.c index 07c85b5963..8345d3bec4 100644 --- a/src/version.c +++ b/src/version.c @@ -681,6 +681,54 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 291, +/**/ + 290, +/**/ + 289, +/**/ + 288, +/**/ + 287, +/**/ + 286, +/**/ + 285, +/**/ + 284, +/**/ + 283, +/**/ + 282, +/**/ + 281, +/**/ + 280, +/**/ + 279, +/**/ + 278, +/**/ + 277, +/**/ + 276, +/**/ + 275, +/**/ + 274, +/**/ + 273, +/**/ + 272, +/**/ + 271, +/**/ + 270, +/**/ + 269, +/**/ + 268, /**/ 267, /**/ diff --git a/src/vim.h b/src/vim.h index 2cd49d7ce8..fc575bd3e4 100644 --- a/src/vim.h +++ b/src/vim.h @@ -356,16 +356,19 @@ typedef unsigned int int_u; * On Win64 longs are 32 bit and pointers 64 bit. * For printf() and scanf() we need to take care of long_u specifically. */ #ifdef _WIN64 -typedef unsigned __int64 long_u; -typedef __int64 long_i; -# define SCANF_HEX_LONG_U "%Ix" -# define PRINTF_HEX_LONG_U "0x%Ix" +typedef unsigned __int64 long_u; +typedef __int64 long_i; +# define SCANF_HEX_LONG_U "%Ix" +# define SCANF_DECIMAL_LONG_U "%Iu" +# define PRINTF_HEX_LONG_U "0x%Ix" #else -typedef unsigned long long_u; -typedef long long_i; -# define SCANF_HEX_LONG_U "%lx" -# define PRINTF_HEX_LONG_U "0x%lx" +typedef unsigned long long_u; +typedef long long_i; +# define SCANF_HEX_LONG_U "%lx" +# define SCANF_DECIMAL_LONG_U "%lu" +# define PRINTF_HEX_LONG_U "0x%lx" #endif +#define PRINTF_DECIMAL_LONG_U SCANF_DECIMAL_LONG_U /* * The characters and attributes cached for the screen. @@ -462,9 +465,10 @@ typedef unsigned long u8char_T; /* long should be 32 bits or more */ /* * Check input method control. */ -#if defined(FEAT_XIM) || \ - (defined(FEAT_GUI) && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) \ - || defined(FEAT_GUI_MACVIM) +#if defined(FEAT_XIM) \ + || (defined(FEAT_GUI) && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) \ + || (defined(FEAT_GUI_MAC) && defined(FEAT_MBYTE)) \ + || defined(FEAT_GUI_MACVIM) # define USE_IM_CONTROL #endif @@ -951,6 +955,7 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname); #define INSCHAR_FORMAT 1 /* force formatting */ #define INSCHAR_DO_COM 2 /* format comments */ #define INSCHAR_CTRLV 4 /* char typed just after CTRL-V */ +#define INSCHAR_NO_FEX 8 /* don't use 'formatexpr' */ /* flags for open_line() */ #define OPENLINE_DELSPACES 1 /* delete spaces after cursor */ diff --git a/src/window.c b/src/window.c index 74e3646872..584b9a4856 100644 --- a/src/window.c +++ b/src/window.c @@ -6303,7 +6303,7 @@ match_add(wp, grp, pat, prio, id) cur = cur->next; } } - if ((hlg_id = syn_namen2id(grp, STRLEN(grp))) == 0) + if ((hlg_id = syn_namen2id(grp, (int)STRLEN(grp))) == 0) { EMSG2(_(e_nogroup), grp); return -1;