diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-04-29 21:04:15 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-04-29 21:04:15 +0200 |
commit | ed8ce057b7a2fcd89b5f55680ae8f85d62a992a5 (patch) | |
tree | fea5d30140297aa6888bf6d68a4c00b62f425622 /src | |
parent | 939b5db4808770d3a2ec35e3902a9d5165adc0cf (diff) |
patch 8.2.0660: the search.c file is a bit bigv8.2.0660
Problem: The search.c file is a bit big.
Solution: Split off the text object code to a separate file. (Yegappan
Lakshmanan, closes #6007)
Diffstat (limited to 'src')
-rw-r--r-- | src/Make_cyg_ming.mak | 1 | ||||
-rw-r--r-- | src/Make_morph.mak | 1 | ||||
-rw-r--r-- | src/Make_mvc.mak | 4 | ||||
-rw-r--r-- | src/Make_vms.mms | 5 | ||||
-rw-r--r-- | src/Makefile | 34 | ||||
-rw-r--r-- | src/README.md | 1 | ||||
-rw-r--r-- | src/proto.h | 1 | ||||
-rw-r--r-- | src/proto/search.pro | 13 | ||||
-rw-r--r-- | src/proto/textobject.pro | 16 | ||||
-rw-r--r-- | src/search.c | 1951 | ||||
-rw-r--r-- | src/textobject.c | 1965 | ||||
-rw-r--r-- | src/version.c | 2 |
12 files changed, 2018 insertions, 1976 deletions
diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 750e940e06..7964b0a1f2 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -787,6 +787,7 @@ OBJ = \ $(OUTDIR)/tag.o \ $(OUTDIR)/term.o \ $(OUTDIR)/testing.o \ + $(OUTDIR)/textobject.o \ $(OUTDIR)/textprop.o \ $(OUTDIR)/time.o \ $(OUTDIR)/ui.o \ diff --git a/src/Make_morph.mak b/src/Make_morph.mak index 1830d85b50..d326174cd2 100644 --- a/src/Make_morph.mak +++ b/src/Make_morph.mak @@ -103,6 +103,7 @@ SRC = arabic.c \ tag.c \ term.c \ testing.c \ + textobject.c \ textprop.c \ time.c \ ui.c \ diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index ebc059f862..c873ca0840 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -806,6 +806,7 @@ OBJ = \ $(OUTDIR)\tag.obj \ $(OUTDIR)\term.obj \ $(OUTDIR)\testing.obj \ + $(OUTDIR)\textobject.obj \ $(OUTDIR)\textprop.obj \ $(OUTDIR)\time.obj \ $(OUTDIR)\ui.obj \ @@ -1744,6 +1745,8 @@ $(OUTDIR)/term.obj: $(OUTDIR) term.c $(INCL) $(OUTDIR)/term.obj: $(OUTDIR) testing.c $(INCL) +$(OUTDIR)/textobject.obj: $(OUTDIR) textobject.c $(INCL) + $(OUTDIR)/textprop.obj: $(OUTDIR) textprop.c $(INCL) $(OUTDIR)/time.obj: $(OUTDIR) time.c $(INCL) @@ -1942,6 +1945,7 @@ proto.h: \ proto/tag.pro \ proto/term.pro \ proto/testing.pro \ + proto/textobject.pro \ proto/textprop.pro \ proto/time.pro \ proto/ui.pro \ diff --git a/src/Make_vms.mms b/src/Make_vms.mms index fdd7ba7c1e..e04020172a 100644 --- a/src/Make_vms.mms +++ b/src/Make_vms.mms @@ -382,6 +382,7 @@ SRC = \ term.c \ termlib.c \ testing.c \ + textobject.c \ textprop.c \ time.c \ ui.c \ @@ -491,6 +492,7 @@ OBJ = \ term.obj \ termlib.obj \ testing.obj \ + textobject.obj \ textprop.obj \ time.obj \ ui.obj \ @@ -989,6 +991,9 @@ termlib.obj : termlib.c vim.h [.auto]config.h feature.h os_unix.h \ testing.obj : testing.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h +textobject.obj : textobject.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ + [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h textprop.obj : textprop.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h diff --git a/src/Makefile b/src/Makefile index 19453c7421..c8e0f087fe 100644 --- a/src/Makefile +++ b/src/Makefile @@ -404,7 +404,7 @@ CClink = $(CC) # Use --with-luajit if you want to use LuaJIT instead of Lua. # Set PATH environment variable to find lua or luajit executable. # This requires at least "normal" features, "tiny" and "small" don't work. -#CONF_OPT_LUA = --enable-luainterp +CONF_OPT_LUA = --enable-luainterp #CONF_OPT_LUA = --enable-luainterp=dynamic #CONF_OPT_LUA = --enable-luainterp --with-luajit #CONF_OPT_LUA = --enable-luainterp=dynamic --with-luajit @@ -433,7 +433,7 @@ CClink = $(CC) # When you get an error for a missing "perl.exp" file, try creating an empty # one: "touch perl.exp". # This requires at least "normal" features, "tiny" and "small" don't work. -#CONF_OPT_PERL = --enable-perlinterp +CONF_OPT_PERL = --enable-perlinterp #CONF_OPT_PERL = --enable-perlinterp=dynamic # PYTHON @@ -447,10 +447,10 @@ CClink = $(CC) # dlopen(), dlsym(), dlclose(), i.e. pythonX.Y.so must be available # However, this may still cause problems, such as "import termios" failing. # Build two separate versions of Vim in that case. -#CONF_OPT_PYTHON = --enable-pythoninterp +CONF_OPT_PYTHON = --enable-pythoninterp #CONF_OPT_PYTHON = --enable-pythoninterp --with-python-command=python2.7 #CONF_OPT_PYTHON = --enable-pythoninterp=dynamic -#CONF_OPT_PYTHON3 = --enable-python3interp +CONF_OPT_PYTHON3 = --enable-python3interp #CONF_OPT_PYTHON3 = --enable-python3interp --with-python3-command=python3.6 #CONF_OPT_PYTHON3 = --enable-python3interp=dynamic @@ -460,19 +460,19 @@ CClink = $(CC) # Note: you need the development package (e.g., ruby1.9.1-dev on Ubuntu). # This requires at least "normal" features, "tiny" and "small" don't work. #CONF_OPT_RUBY = --enable-rubyinterp -#CONF_OPT_RUBY = --enable-rubyinterp=dynamic +CONF_OPT_RUBY = --enable-rubyinterp=dynamic #CONF_OPT_RUBY = --enable-rubyinterp --with-ruby-command=ruby1.9.1 # TCL # Uncomment this when you want to include the Tcl interface. # First one is for static linking, second one for dynamic loading. #CONF_OPT_TCL = --enable-tclinterp -#CONF_OPT_TCL = --enable-tclinterp=dynamic +CONF_OPT_TCL = --enable-tclinterp=dynamic #CONF_OPT_TCL = --enable-tclinterp --with-tclsh=tclsh8.4 # CSCOPE # Uncomment this when you want to include the Cscope interface. -#CONF_OPT_CSCOPE = --enable-cscope +CONF_OPT_CSCOPE = --enable-cscope # NETBEANS - NetBeans interface. Only works with Motif, GTK, and gnome. # Motif version must have XPM libraries (see |netbeans-xpm|). @@ -540,7 +540,7 @@ CClink = $(CC) #CONF_OPT_FEAT = --with-features=small #CONF_OPT_FEAT = --with-features=normal #CONF_OPT_FEAT = --with-features=big -#CONF_OPT_FEAT = --with-features=huge +CONF_OPT_FEAT = --with-features=huge # COMPILED BY - For including a specific e-mail address for ":version". #CONF_OPT_COMPBY = "--with-compiledby=John Doe <JohnDoe@yahoo.com>" @@ -614,11 +614,11 @@ CClink = $(CC) # Use this with GCC to check for mistakes, unused arguments, etc. # Note: If you use -Wextra and get warnings in GTK code about function # parameters, you can add -Wno-cast-function-type -#CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-cast-function-type -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 +CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-cast-function-type -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 # Add -Wpedantic to find // comments and other C99 constructs. # Better disable Perl and Python to avoid a lot of warnings. #CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wpedantic -Wunreachable-code -Wunused-result -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -#CFLAGS = -g -O2 -Wall -Wextra -Wshadow -Wmissing-prototypes -Wpedantic -Wunreachable-code -Wunused-result -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 +#CFLAGS = -g -O2 -Wall -Wextra -Wshadow -Wmissing-prototypes -Wpedantic -Wunreachable-code -Wno-cast-function-type -Wunused-result -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 #PYTHON_CFLAGS_EXTRA = -Wno-missing-field-initializers #MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code -Wno-unused-parameter @@ -707,12 +707,12 @@ SANITIZER_LIBS = $(SANITIZER_CFLAGS) # Configuration is in the .ccmalloc or ~/.ccmalloc file. # Doesn't work very well, since memory linked to from global variables # (in libraries) is also marked as leaked memory. -#LEAK_CFLAGS = -DEXITFREE +LEAK_CFLAGS = -DEXITFREE #LEAK_LIBS = -lccmalloc # Uncomment this line to have Vim call abort() when an internal error is # detected. Useful when using a tool to find errors. -#ABORT_CFLAGS = -DABORT_ON_INTERNAL_ERROR +ABORT_CFLAGS = -DABORT_ON_INTERNAL_ERROR ##################################################### ### Specific systems, check if yours is listed! ### {{{ @@ -1680,6 +1680,7 @@ BASIC_SRC = \ term.c \ terminal.c \ testing.c \ + textobject.c \ textprop.c \ time.c \ ui.c \ @@ -1822,6 +1823,7 @@ OBJ_COMMON = \ objects/term.o \ objects/terminal.o \ objects/testing.o \ + objects/textobject.o \ objects/textprop.o \ objects/time.o \ objects/ui.o \ @@ -1996,6 +1998,7 @@ PRO_AUTO = \ terminal.pro \ termlib.pro \ testing.pro \ + textobject.pro \ textprop.pro \ time.pro \ ui.pro \ @@ -3469,6 +3472,9 @@ objects/terminal.o: terminal.c $(TERM_DEPS) objects/testing.o: testing.c $(CCC) -o $@ testing.c +objects/textobject.o: textobject.c + $(CCC) -o $@ textobject.c + objects/textprop.o: textprop.c $(CCC) -o $@ textprop.c @@ -4060,6 +4066,10 @@ objects/testing.o: testing.c vim.h protodef.h auto/config.h feature.h os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ proto.h globals.h +objects/textobject.o: textobject.c vim.h protodef.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ + proto.h globals.h objects/textprop.o: textprop.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ diff --git a/src/README.md b/src/README.md index 54be08284f..765313da7e 100644 --- a/src/README.md +++ b/src/README.md @@ -80,6 +80,7 @@ syntax.c | syntax and other highlighting tag.c | tags term.c | terminal handling, termcap codes testing.c | testing: assert and test functions +textobject.c | text objects textprop.c | text properties time.c | time and timer functions undo.c | undo and redo diff --git a/src/proto.h b/src/proto.h index 0115c68d19..d54936c751 100644 --- a/src/proto.h +++ b/src/proto.h @@ -223,6 +223,7 @@ void mbyte_im_set_active(int active_arg); # include "textprop.pro" # endif # include "testing.pro" +# include "textobject.pro" # include "time.pro" # include "ui.pro" # include "undo.pro" diff --git a/src/proto/search.pro b/src/proto/search.pro index 018c33a4f2..1e15a8828e 100644 --- a/src/proto/search.pro +++ b/src/proto/search.pro @@ -30,19 +30,6 @@ int searchc(cmdarg_T *cap, int t_cmd); pos_T *findmatch(oparg_T *oap, int initc); pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int maxtravel); void showmatch(int c); -int findsent(int dir, long count); -int findpar(int *pincl, int dir, long count, int what, int both); -int startPS(linenr_T lnum, int para, int both); -int fwd_word(long count, int bigword, int eol); -int bck_word(long count, int bigword, int stop); -int end_word(long count, int bigword, int stop, int empty); -int bckend_word(long count, int bigword, int eol); -int current_word(oparg_T *oap, long count, int include, int bigword); -int current_sent(oparg_T *oap, long count, int include); -int current_block(oparg_T *oap, long count, int include, int what, int other); -int current_tagblock(oparg_T *oap, long count_arg, int include); -int current_par(oparg_T *oap, long count, int include, int type); -int current_quote(oparg_T *oap, long count, int include, int quotechar); int current_search(long count, int forward); int linewhite(linenr_T lnum); void find_pattern_in_path(char_u *ptr, int dir, int len, int whole, int skip_comments, int type, long count, int action, linenr_T start_lnum, linenr_T end_lnum); diff --git a/src/proto/textobject.pro b/src/proto/textobject.pro new file mode 100644 index 0000000000..7931979140 --- /dev/null +++ b/src/proto/textobject.pro @@ -0,0 +1,16 @@ +/* textobject.c */ +int findsent(int dir, long count); +int findpar(int *pincl, int dir, long count, int what, int both); +int startPS(linenr_T lnum, int para, int both); +int fwd_word(long count, int bigword, int eol); +int bck_word(long count, int bigword, int stop); +int end_word(long count, int bigword, int stop, int empty); +int bckend_word(long count, int bigword, int eol); +int current_word(oparg_T *oap, long count, int include, int bigword); +int current_sent(oparg_T *oap, long count, int include); +int current_block(oparg_T *oap, long count, int include, int what, int other); +int current_tagblock(oparg_T *oap, long count_arg, int include); +int current_par(oparg_T *oap, long count, int include, int type); +int current_quote(oparg_T *oap, long count, int include, int quotechar); +/* vim: set ft=c : */ + diff --git a/src/search.c b/src/search.c index 8c335ffd3a..0bf49629eb 100644 --- a/src/search.c +++ b/src/search.c @@ -17,8 +17,6 @@ static void set_vv_searchforward(void); static int first_submatch(regmmatch_T *rp); #endif static int check_linecomment(char_u *line); -static int cls(void); -static int skip_chars(int, int); #ifdef FEAT_FIND_ID static void show_pat_in_path(char_u *, int, int, int, FILE *, linenr_T *, long); @@ -2838,1955 +2836,6 @@ showmatch( } /* - * Find the start of the next sentence, searching in the direction specified - * by the "dir" argument. The cursor is positioned on the start of the next - * sentence when found. If the next sentence is found, return OK. Return FAIL - * otherwise. See ":h sentence" for the precise definition of a "sentence" - * text object. - */ - int -findsent(int dir, long count) -{ - pos_T pos, tpos; - int c; - int (*func)(pos_T *); - int startlnum; - int noskip = FALSE; // do not skip blanks - int cpo_J; - int found_dot; - - pos = curwin->w_cursor; - if (dir == FORWARD) - func = incl; - else - func = decl; - - while (count--) - { - /* - * if on an empty line, skip up to a non-empty line - */ - if (gchar_pos(&pos) == NUL) - { - do - if ((*func)(&pos) == -1) - break; - while (gchar_pos(&pos) == NUL); - if (dir == FORWARD) - goto found; - } - /* - * if on the start of a paragraph or a section and searching forward, - * go to the next line - */ - else if (dir == FORWARD && pos.col == 0 && - startPS(pos.lnum, NUL, FALSE)) - { - if (pos.lnum == curbuf->b_ml.ml_line_count) - return FAIL; - ++pos.lnum; - goto found; - } - else if (dir == BACKWARD) - decl(&pos); - - // go back to the previous non-white non-punctuation character - found_dot = FALSE; - while (c = gchar_pos(&pos), VIM_ISWHITE(c) - || vim_strchr((char_u *)".!?)]\"'", c) != NULL) - { - tpos = pos; - if (decl(&tpos) == -1 || (LINEEMPTY(tpos.lnum) && dir == FORWARD)) - break; - - if (found_dot) - break; - if (vim_strchr((char_u *) ".!?", c) != NULL) - found_dot = TRUE; - - if (vim_strchr((char_u *) ")]\"'", c) != NULL - && vim_strchr((char_u *) ".!?)]\"'", gchar_pos(&tpos)) == NULL) - break; - - decl(&pos); - } - - // remember the line where the search started - startlnum = pos.lnum; - cpo_J = vim_strchr(p_cpo, CPO_ENDOFSENT) != NULL; - - for (;;) // find end of sentence - { - c = gchar_pos(&pos); - if (c == NUL || (pos.col == 0 && startPS(pos.lnum, NUL, FALSE))) - { - if (dir == BACKWARD && pos.lnum != startlnum) - ++pos.lnum; - break; - } - if (c == '.' || c == '!' || c == '?') - { - tpos = pos; - do - if ((c = inc(&tpos)) == -1) - break; - while (vim_strchr((char_u *)")]\"'", c = gchar_pos(&tpos)) - != NULL); - if (c == -1 || (!cpo_J && (c == ' ' || c == '\t')) || c == NUL - || (cpo_J && (c == ' ' && inc(&tpos) >= 0 - && gchar_pos(&tpos) == ' '))) - { - pos = tpos; - if (gchar_pos(&pos) == NUL) // skip NUL at EOL - inc(&pos); - break; - } - } - if ((*func)(&pos) == -1) - { - if (count) - return FAIL; - noskip = TRUE; - break; - } - } -found: - // skip white space - while (!noskip && ((c = gchar_pos(&pos)) == ' ' || c == '\t')) - if (incl(&pos) == -1) - break; - } - - setpcmark(); - curwin->w_cursor = pos; - return OK; -} - -/* - * Find the next paragraph or section in direction 'dir'. - * Paragraphs are currently supposed to be separated by empty lines. - * If 'what' is NUL we go to the next paragraph. - * If 'what' is '{' or '}' we go to the next section. - * If 'both' is TRUE also stop at '}'. - * Return TRUE if the next paragraph or section was found. - */ - int -findpar( - int *pincl, // Return: TRUE if last char is to be included - int dir, - long count, - int what, - int both) -{ - linenr_T curr; - int did_skip; // TRUE after separating lines have been skipped - int first; // TRUE on first line - int posix = (vim_strchr(p_cpo, CPO_PARA) != NULL); -#ifdef FEAT_FOLDING - linenr_T fold_first; // first line of a closed fold - linenr_T fold_last; // last line of a closed fold - int fold_skipped; // TRUE if a closed fold was skipped this - // iteration -#endif - - curr = curwin->w_cursor.lnum; - - while (count--) - { - did_skip = FALSE; - for (first = TRUE; ; first = FALSE) - { - if (*ml_get(curr) != NUL) - did_skip = TRUE; - -#ifdef FEAT_FOLDING - // skip folded lines - fold_skipped = FALSE; - if (first && hasFolding(curr, &fold_first, &fold_last)) - { - curr = ((dir > 0) ? fold_last : fold_first) + dir; - fold_skipped = TRUE; - } -#endif - - // POSIX has its own ideas of what a paragraph boundary is and it - // doesn't match historical Vi: It also stops at a "{" in the - // first column and at an empty line. - if (!first && did_skip && (startPS(curr, what, both) - || (posix && what == NUL && *ml_get(curr) == '{'))) - break; - -#ifdef FEAT_FOLDING - if (fold_skipped) - curr -= dir; -#endif - if ((curr += dir) < 1 || curr > curbuf->b_ml.ml_line_count) - { - if (count) - return FALSE; - curr -= dir; - break; - } - } - } - setpcmark(); - if (both && *ml_get(curr) == '}') // include line with '}' - ++curr; - curwin->w_cursor.lnum = curr; - if (curr == curbuf->b_ml.ml_line_count && what != '}') - { - char_u *line = ml_get(curr); - - // Put the cursor on the last character in the last line and make the - // motion inclusive. - if ((curwin->w_cursor.col = (colnr_T)STRLEN(line)) != 0) - { - --curwin->w_cursor.col; - curwin->w_cursor.col -= - (*mb_head_off)(line, line + curwin->w_cursor.col); - *pincl = TRUE; - } - } - else - curwin->w_cursor.col = 0; - return TRUE; -} - -/* - * check if the string 's' is a nroff macro that is in option 'opt' - */ - static int -inmacro(char_u *opt, char_u *s) -{ - char_u *macro; - - for (macro = opt; macro[0]; ++macro) - { - // Accept two characters in the option being equal to two characters - // in the line. A space in the option matches with a space in the - // line or the line having ended. - if ( (macro[0] == s[0] - || (macro[0] == ' ' - && (s[0] == NUL || s[0] == ' '))) - && (macro[1] == s[1] - || ((macro[1] == NUL || macro[1] == ' ') - && (s[0] == NUL || s[1] == NUL || s[1] == ' ')))) - break; - ++macro; - if (macro[0] == NUL) - break; - } - return (macro[0] != NUL); -} - -/* - * startPS: return TRUE if line 'lnum' is the start of a section or paragraph. - * If 'para' is '{' or '}' only check for sections. - * If 'both' is TRUE also stop at '}' - */ - int -startPS(linenr_T lnum, int para, int both) -{ - char_u *s; - - s = ml_get(lnum); - if (*s == para || *s == '\f' || (both && *s == '}')) - return TRUE; - if (*s == '.' && (inmacro(p_sections, s + 1) || - (!para && inmacro(p_para, s + 1)))) - return TRUE; - return FALSE; -} - -/* - * The following routines do the word searches performed by the 'w', 'W', - * 'b', 'B', 'e', and 'E' commands. - */ - -/* - * To perform these searches, characters are placed into one of three - * classes, and transitions between classes determine word boundaries. - * - * The classes are: - * - * 0 - white space - * 1 - punctuation - * 2 or higher - keyword characters (letters, digits and underscore) - */ - -static int cls_bigword; // TRUE for "W", "B" or "E" - -/* - * cls() - returns the class of character at curwin->w_cursor - * - * If a 'W', 'B', or 'E' motion is being done (cls_bigword == TRUE), chars - * from class 2 and higher are reported as class 1 since only white space - * boundaries are of interest. - */ - static int -cls(void) -{ - int c; - - c = gchar_cursor(); - if (c == ' ' || c == '\t' || c == NUL) - return 0; - if (enc_dbcs != 0 && c > 0xFF) - { - // If cls_bigword, report multi-byte chars as class 1. - if (enc_dbcs == DBCS_KOR && cls_bigword) - return 1; - - // process code leading/trailing bytes - return dbcs_class(((unsigned)c >> 8), (c & 0xFF)); - } - if (enc_utf8) - { - c = utf_class(c); - if (c != 0 && cls_bigword) - return 1; - return c; - } - - // If cls_bigword is TRUE, report all non-blanks as class 1. - if (cls_bigword) - return 1; - - if (vim_iswordc(c)) - return 2; - return 1; -} - - -/* - * fwd_word(count, type, eol) - move forward one word - * - * Returns FAIL if the cursor was already at the end of the file. - * If eol is TRUE, last word stops at end of line (for operators). - */ - int -fwd_word( - long count, - int bigword, // "W", "E" or "B" - int eol) -{ - int sclass; // starting class - int i; - int last_line; - - curwin->w_cursor.coladd = 0; - cls_bigword = bigword; - while (--count >= 0) - { -#ifdef FEAT_FOLDING - // When inside a range of folded lines, move to the last char of the - // last line. - if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) - coladvance((colnr_T)MAXCOL); -#endif - sclass = cls(); - - /* - * We always move at least one character, unless on the last - * character in the buffer. - */ - last_line = (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count); - i = inc_cursor(); - if (i == -1 || (i >= 1 && last_line)) // started at last char in file - return FAIL; - if (i >= 1 && eol && count == 0) // started at last char in line - return OK; - - /* - * Go one char past end of current word (if any) - */ - if (sclass != 0) - while (cls() == sclass) - { - i = inc_cursor(); - if (i == -1 || (i >= 1 && eol && count == 0)) - return OK; - } - - /* - * go to next non-white - */ - while (cls() == 0) - { - /* - * We'll stop if we land on a blank line - */ - if (curwin->w_cursor.col == 0 && *ml_get_curline() == NUL) - break; - - i = inc_cursor(); - if (i == -1 || (i >= 1 && eol && count == 0)) - return OK; - } - } - return OK; -} - -/* - * bck_word() - move backward 'count' words - * - * If stop is TRUE and we are already on the start of a word, move one less. - * - * Returns FAIL if top of the file was reached. - */ - int -bck_word(long count, int bigword, int stop) -{ - int sclass; // starting class - - curwin->w_cursor.coladd = 0; - cls_bigword = bigword; - while (--count >= 0) - { -#ifdef FEAT_FOLDING - // When inside a range of folded lines, move to the first char of the - // first line. - if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL)) - curwin->w_cursor.col = 0; -#endif - sclass = cls(); - if (dec_cursor() == -1) // started at start of file - return FAIL; - - if (!stop || sclass == cls() || sclass == 0) - { - /* - * Skip white space before the word. - * Stop on an empty line. - */ - while (cls() == 0) - { - if (curwin->w_cursor.col == 0 - && LINEEMPTY(curwin->w_cursor.lnum)) - goto finished; - if (dec_cursor() == -1) // hit start of file, stop here - return OK; - } - - /* - * Move backward to start of this word. - */ - if (skip_chars(cls(), BACKWARD)) - return OK; - } - - inc_cursor(); // overshot - forward one -finished: - stop = FALSE; - } - return OK; -} - -/* - * end_word() - move to the end of the word - * - * There is an apparent bug in the 'e' motion of the real vi. At least on the - * System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e' - * motion crosses blank lines. When the real vi crosses a blank line in an - * 'e' motion, the cursor is placed on the FIRST character of the next - * non-blank line. The 'E' command, however, works correctly. Since this - * appears to be a bug, I have not duplicated it here. - * - * Returns FAIL if end of the file was reached. - * - * If stop is TRUE and we are already on the end of a word, move one less. - * If empty is TRUE stop on an empty line. - */ - int -end_word( - long count, - int bigword, - int stop, - int empty) -{ - int sclass; // starting class - - curwin->w_cursor.coladd = 0; - cls_bigword = bigword; - while (--count >= 0) - { -#ifdef FEAT_FOLDING - // When inside a range of folded lines, move to the last char of the - // last line. - if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) - coladvance((colnr_T)MAXCOL); -#endif - sclass = cls(); - if (inc_cursor() == -1) - return FAIL; - - /* - * If we're in the middle of a word, we just have to move to the end - * of it. - */ - if (cls() == sclass && sclass != 0) - { - /* - * Move forward to end of the current word - */ - if (skip_chars(sclass, FORWARD)) - return FAIL; - } - else if (!stop || sclass == 0) - { - /* - * We were at the end of a word. Go to the end of the next word. - * First skip white space, if 'empty' is TRUE, stop at empty line. - */ - while (cls() == 0) - { - if (empty && curwin->w_cursor.col == 0 - && LINEEMPTY(curwin->w_cursor.lnum)) - goto finished; - if (inc_cursor() == -1) // hit end of file, stop here - return FAIL; - } - - /* - * Move forward to the end of this word. - */ - if (skip_chars(cls(), FORWARD)) - return FAIL; - } - dec_cursor(); // overshot - one char backward -finished: - stop = FALSE; // we move only one word less - } - return OK; -} - -/* - * Move back to the end of the word. - * - * Returns FAIL if start of the file was reached. - */ - int -bckend_word( - long count, - int bigword, // TRUE for "B" - int eol) // TRUE: stop at end of line. -{ - int sclass; // starting class - int i; - - curwin->w_cursor.coladd = 0; - cls_bigword = bigword; - while (--count >= 0) - { - sclass = cls(); - if ((i = dec_cursor()) == -1) - return FAIL; - if (eol && i == 1) - return OK; - - /* - * Move backward to before the start of this word. - */ - if (sclass != 0) - { - while (cls() == sclass) - if ((i = dec_cursor()) == -1 || (eol && i == 1)) - return OK; - } - - /* - * Move backward to end of the previous word - */ - while (cls() == 0) - { - if (curwin->w_cursor.col == 0 && LINEEMPTY(curwin->w_cursor.lnum)) - break; - if ((i = dec_cursor()) == -1 || (eol && i == 1)) - return OK; - } - } - return OK; -} - -/* - * Skip a row of characters of the same class. - * Return TRUE when end-of-file reached, FALSE otherwise. - */ - static int -skip_chars(int cclass, int dir) -{ - while (cls() == cclass) - if ((dir == FORWARD ? inc_cursor() : dec_cursor()) == -1) - return TRUE; - return FALSE; -} - -#ifdef FEAT_TEXTOBJ -/* - * Go back to the start of the word or the start of white space - */ - static void -back_in_line(void) -{ - int sclass; // starting class - - sclass = cls(); - for (;;) - { - if (curwin->w_cursor.col == 0) // stop at start of line - break; - dec_cursor(); - if (cls() != sclass) // stop at start of word - { - inc_cursor(); - break; - } - } -} - - static void -find_first_blank(pos_T *posp) -{ - int c; - - while (decl(posp) != -1) - { - c = gchar_pos(posp); - if (!VIM_ISWHITE(c)) - { - incl(posp); - break; - } - } -} - -/* - * Skip count/2 sentences and count/2 separating white spaces. - */ - static void -findsent_forward( - long count, - int at_start_sent) // cursor is at start of sentence -{ - while (count--) - { - findsent(FORWARD, 1L); - if (at_start_sent) - find_first_blank(&curwin->w_cursor); - if (count == 0 || at_start_sent) - decl(&curwin->w_cursor); - at_start_sent = !at_start_sent; - } -} - -/* - * Find word under cursor, cursor at end. - * Used while an operator is pending, and in Visual mode. - */ - int -current_word( - oparg_T *oap, - long count, - int include, // TRUE: include word and white space - int bigword) // FALSE == word, TRUE == WORD -{ - pos_T start_pos; - pos_T pos; - int inclusive = TRUE; - int include_white = FALSE; - - cls_bigword = bigword; - CLEAR_POS(&start_pos); - - // Correct cursor when 'selection' is exclusive - if (VIsual_active && *p_sel == 'e' && LT_POS(VIsual, curwin->w_cursor)) - dec_cursor(); - - /* - * When Visual mode is not active, or when the VIsual area is only one - * character, select the word and/or white space under the cursor. - */ - if (!VIsual_active || EQUAL_POS(curwin->w_cursor, VIsual)) - { - /* - * Go to start of current word or white space. - */ - back_in_line(); - start_pos = curwin->w_cursor; - - /* - * If the start is on white space, and white space should be included - * (" word"), or start is not on white space, and white space should - * not be included ("word"), find end of word. - */ - if ((cls() == 0) == include) - { - if (end_word(1L, bigword, TRUE, TRUE) == FAIL) - return FAIL; - } - else - { - /* - * If the start is not on white space, and white space should be - * included ("word "), or start is on white space and white - * space should not be included (" "), find start of word. - * If we end up in the first column of the next line (single char - * word) back up to end of the line. - */ - fwd_word(1L, bigword, TRUE); - if (curwin->w_cursor.col == 0) - decl(&curwin->w_cursor); - else - oneleft(); - - if (include) - include_white = TRUE; - } - - if (VIsual_active) - { - // should do something when inclusive == FALSE ! - VIsual = start_pos; - redraw_curbuf_later(INVERTED); // update the inversion - } - else - { - oap->start = start_pos; - oap->motion_type = MCHAR; - } - --count; |