2017-04-19 18:11:50 +02:00
|
|
|
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
|
|
|
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
|
|
|
2014-01-31 14:39:15 +01:00
|
|
|
/*
|
|
|
|
* mark.c: functions for setting marks and jumping to them
|
|
|
|
*/
|
|
|
|
|
2014-06-23 07:40:35 +02:00
|
|
|
#include <assert.h>
|
2014-06-23 03:46:34 +02:00
|
|
|
#include <inttypes.h>
|
2014-03-26 06:51:44 +01:00
|
|
|
#include <string.h>
|
2015-02-23 21:45:11 +01:00
|
|
|
#include <limits.h>
|
2014-03-26 06:51:44 +01:00
|
|
|
|
2014-05-12 11:59:22 +02:00
|
|
|
#include "nvim/vim.h"
|
2014-06-17 17:22:05 +02:00
|
|
|
#include "nvim/ascii.h"
|
2014-05-12 11:59:22 +02:00
|
|
|
#include "nvim/mark.h"
|
|
|
|
#include "nvim/buffer.h"
|
|
|
|
#include "nvim/charset.h"
|
|
|
|
#include "nvim/diff.h"
|
|
|
|
#include "nvim/eval.h"
|
|
|
|
#include "nvim/ex_cmds.h"
|
|
|
|
#include "nvim/fileio.h"
|
|
|
|
#include "nvim/fold.h"
|
|
|
|
#include "nvim/mbyte.h"
|
|
|
|
#include "nvim/memline.h"
|
|
|
|
#include "nvim/memory.h"
|
|
|
|
#include "nvim/message.h"
|
|
|
|
#include "nvim/normal.h"
|
|
|
|
#include "nvim/option.h"
|
|
|
|
#include "nvim/path.h"
|
|
|
|
#include "nvim/quickfix.h"
|
|
|
|
#include "nvim/search.h"
|
2019-05-24 22:10:19 +02:00
|
|
|
#include "nvim/sign.h"
|
2014-05-12 12:12:27 +02:00
|
|
|
#include "nvim/strings.h"
|
2015-02-17 03:47:56 +01:00
|
|
|
#include "nvim/ui.h"
|
2014-05-12 11:59:22 +02:00
|
|
|
#include "nvim/os/os.h"
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
#include "nvim/os/time.h"
|
2014-11-27 18:10:42 +01:00
|
|
|
#include "nvim/os/input.h"
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This file contains routines to maintain and manipulate marks.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If a named file mark's lnum is non-zero, it is valid.
|
|
|
|
* If a named file mark's fnum is non-zero, it is for an existing buffer,
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
* otherwise it is from .shada and namedfm[n].fname is the file name.
|
2014-01-31 14:39:15 +01:00
|
|
|
* There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
* shada).
|
2014-01-31 14:39:15 +01:00
|
|
|
*/
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
|
|
|
|
/// Global marks (marks with file number or name)
|
|
|
|
static xfmark_T namedfm[NGLOBALMARKS];
|
|
|
|
|
2014-05-10 15:24:13 +02:00
|
|
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
|
|
|
# include "mark.c.generated.h"
|
|
|
|
#endif
|
2014-01-31 14:39:15 +01:00
|
|
|
/*
|
|
|
|
* Set named mark "c" at current cursor position.
|
|
|
|
* Returns OK on success, FAIL if bad name given.
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
int setmark(int c)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
return setmark_pos(c, &curwin->w_cursor, curbuf->b_fnum);
|
|
|
|
}
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// Free fmark_T item
|
|
|
|
void free_fmark(fmark_T fm)
|
|
|
|
{
|
2016-08-20 21:24:34 +02:00
|
|
|
tv_dict_unref(fm.additional_data);
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Free xfmark_T item
|
2015-06-28 07:06:16 +02:00
|
|
|
void free_xfmark(xfmark_T fm)
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
{
|
|
|
|
xfree(fm.fname);
|
|
|
|
free_fmark(fm.fmark);
|
|
|
|
}
|
|
|
|
|
2015-08-16 17:54:41 +02:00
|
|
|
/// Free and clear fmark_T item
|
|
|
|
void clear_fmark(fmark_T *fm)
|
|
|
|
FUNC_ATTR_NONNULL_ALL
|
|
|
|
{
|
|
|
|
free_fmark(*fm);
|
|
|
|
memset(fm, 0, sizeof(*fm));
|
|
|
|
}
|
|
|
|
|
2014-01-31 14:39:15 +01:00
|
|
|
/*
|
|
|
|
* Set named mark "c" to position "pos".
|
|
|
|
* When "c" is upper case use file "fnum".
|
|
|
|
* Returns OK on success, FAIL if bad name given.
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
int setmark_pos(int c, pos_T *pos, int fnum)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Check for a special key (may cause islower() to crash). */
|
|
|
|
if (c < 0)
|
|
|
|
return FAIL;
|
|
|
|
|
|
|
|
if (c == '\'' || c == '`') {
|
|
|
|
if (pos == &curwin->w_cursor) {
|
|
|
|
setpcmark();
|
|
|
|
/* keep it even when the cursor doesn't move */
|
|
|
|
curwin->w_prev_pcmark = curwin->w_pcmark;
|
|
|
|
} else
|
|
|
|
curwin->w_pcmark = *pos;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2018-06-06 23:39:38 +02:00
|
|
|
// Can't set a mark in a non-existant buffer.
|
|
|
|
buf_T *buf = buflist_findnr(fnum);
|
|
|
|
if (buf == NULL) {
|
|
|
|
return FAIL;
|
|
|
|
}
|
|
|
|
|
2014-01-31 14:39:15 +01:00
|
|
|
if (c == '"') {
|
2018-06-06 23:39:38 +02:00
|
|
|
RESET_FMARK(&buf->b_last_cursor, *pos, buf->b_fnum);
|
2014-01-31 14:39:15 +01:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allow setting '[ and '] for an autocommand that simulates reading a
|
|
|
|
* file. */
|
|
|
|
if (c == '[') {
|
2018-06-06 23:39:38 +02:00
|
|
|
buf->b_op_start = *pos;
|
2014-01-31 14:39:15 +01:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
if (c == ']') {
|
2018-06-06 23:39:38 +02:00
|
|
|
buf->b_op_end = *pos;
|
2014-01-31 14:39:15 +01:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c == '<' || c == '>') {
|
2018-06-06 23:39:38 +02:00
|
|
|
if (c == '<') {
|
|
|
|
buf->b_visual.vi_start = *pos;
|
|
|
|
} else {
|
|
|
|
buf->b_visual.vi_end = *pos;
|
|
|
|
}
|
|
|
|
if (buf->b_visual.vi_mode == NUL) {
|
|
|
|
// Visual_mode has not yet been set, use a sane default.
|
|
|
|
buf->b_visual.vi_mode = 'v';
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2017-01-02 20:09:48 +01:00
|
|
|
if (ASCII_ISLOWER(c)) {
|
2014-01-31 14:39:15 +01:00
|
|
|
i = c - 'a';
|
setpos(): Set lowercase mark in other buffers (#5753)
Also make setpos("'A", [999, 1, 1, 0]) fail, i.e. return -1 (assuming there is no buffer 999).
Fixes #5713
Background:
`:help setpos()` mentions an argument `"bufnum"` that determines the buffer a mark should be put in.
This argument is respected for uppercase marks, but not for lowercase marks.
This is reasonable (though I personally would like `setpos()` to be able to set marks in other buffers), but the help doesn't mention this anywhere.
It's also strange that attempting to change buffers with `setpos('.', [bufnr('#'), 1, 1, 0])` alerts the user that having a different buffer is an error, while attempting to set a mark with `setpos("'d", [bufnr('#'), 1, 1, 0])` doesn't tell the user that the `"bufnum"` argument is an error.
2017-01-15 21:36:29 +01:00
|
|
|
RESET_FMARK(buf->b_namedm + i, *pos, fnum);
|
2014-01-31 14:39:15 +01:00
|
|
|
return OK;
|
|
|
|
}
|
2017-01-02 20:09:48 +01:00
|
|
|
if (ASCII_ISUPPER(c) || ascii_isdigit(c)) {
|
|
|
|
if (ascii_isdigit(c)) {
|
|
|
|
i = c - '0' + NMARKS;
|
|
|
|
} else {
|
|
|
|
i = c - 'A';
|
|
|
|
}
|
2015-06-28 07:06:16 +02:00
|
|
|
RESET_XFMARK(namedfm + i, *pos, fnum, NULL);
|
2014-01-31 14:39:15 +01:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
return FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the previous context mark to the current position and add it to the
|
|
|
|
* jump list.
|
|
|
|
*/
|
2014-03-16 08:20:00 +01:00
|
|
|
void setpcmark(void)
|
|
|
|
{
|
2014-01-31 14:39:15 +01:00
|
|
|
xfmark_T *fm;
|
|
|
|
|
|
|
|
/* for :global the mark is set only once */
|
|
|
|
if (global_busy || listcmd_busy || cmdmod.keepjumps)
|
|
|
|
return;
|
|
|
|
|
|
|
|
curwin->w_prev_pcmark = curwin->w_pcmark;
|
|
|
|
curwin->w_pcmark = curwin->w_cursor;
|
|
|
|
|
2017-12-23 22:29:38 +01:00
|
|
|
if (curwin->w_pcmark.lnum == 0) {
|
|
|
|
curwin->w_pcmark.lnum = 1;
|
|
|
|
}
|
|
|
|
|
jumplist: browser-style (or 'tagstack') navigation #11530
Traditionally, when navigating to a specific location from the middle of
the jumplist results in shifting the current location to the bottom of
the list and adding the new location after it. This behavior is not
desireable to all users--see, for example
https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior.
Here, another jumplist behavior is introduced. When jumpoptions (a new
option set added here) includes stack, the jumplist behaves like the
tagstack or like history in a web browser. That is, when navigating to
a location from the middle of the jumplist
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
to a new location the locations after the current location in the jump
list are discarded
2 first
1 second
0 third
<-- current location
The result is that when moving forward from that location, the new
location will be appended to the jumplist:
3 first
2 second
1 third
0 new
If the new location is the same
new == second
as some previous (but not immediately prior) entry in the jumplist,
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
both occurrences preserved
3 first
2 second
1 third
0 second (new)
when moving forward from that location.
It would be desireable to go farther and, when the new location is the
same as the location that is currently next in the jumplist,
new == fourth
make the result of navigating to the new location by jumping (e.g. 50gg)
be the same as moving forward in the jumplist
2 first
1 second
0 third
1 new <-- current location
2 fifth
and simply increment the jumplist index. That change is NOT part of
this patch because it would require passing the new cursor location to
the function (setpcmark) from all of its callees. That in turn would
require those callees to know *before* calling what the new cursor
location is, which do they do not currently.
2019-12-10 09:56:56 +01:00
|
|
|
if (jop_flags & JOP_STACK) {
|
2019-12-10 10:24:20 +01:00
|
|
|
// jumpoptions=stack: if we're somewhere in the middle of the jumplist
|
|
|
|
// discard everything after the current index.
|
jumplist: browser-style (or 'tagstack') navigation #11530
Traditionally, when navigating to a specific location from the middle of
the jumplist results in shifting the current location to the bottom of
the list and adding the new location after it. This behavior is not
desireable to all users--see, for example
https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior.
Here, another jumplist behavior is introduced. When jumpoptions (a new
option set added here) includes stack, the jumplist behaves like the
tagstack or like history in a web browser. That is, when navigating to
a location from the middle of the jumplist
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
to a new location the locations after the current location in the jump
list are discarded
2 first
1 second
0 third
<-- current location
The result is that when moving forward from that location, the new
location will be appended to the jumplist:
3 first
2 second
1 third
0 new
If the new location is the same
new == second
as some previous (but not immediately prior) entry in the jumplist,
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
both occurrences preserved
3 first
2 second
1 third
0 second (new)
when moving forward from that location.
It would be desireable to go farther and, when the new location is the
same as the location that is currently next in the jumplist,
new == fourth
make the result of navigating to the new location by jumping (e.g. 50gg)
be the same as moving forward in the jumplist
2 first
1 second
0 third
1 new <-- current location
2 fifth
and simply increment the jumplist index. That change is NOT part of
this patch because it would require passing the new cursor location to
the function (setpcmark) from all of its callees. That in turn would
require those callees to know *before* calling what the new cursor
location is, which do they do not currently.
2019-12-10 09:56:56 +01:00
|
|
|
if (curwin->w_jumplistidx < curwin->w_jumplistlen - 1) {
|
|
|
|
// Discard the rest of the jumplist by cutting the length down to
|
|
|
|
// contain nothing beyond the current index.
|
|
|
|
curwin->w_jumplistlen = curwin->w_jumplistidx + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-31 14:39:15 +01:00
|
|
|
/* If jumplist is full: remove oldest entry */
|
|
|
|
if (++curwin->w_jumplistlen > JUMPLISTSIZE) {
|
|
|
|
curwin->w_jumplistlen = JUMPLISTSIZE;
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
free_xfmark(curwin->w_jumplist[0]);
|
2015-06-28 07:06:16 +02:00
|
|
|
memmove(&curwin->w_jumplist[0], &curwin->w_jumplist[1],
|
|
|
|
(JUMPLISTSIZE - 1) * sizeof(curwin->w_jumplist[0]));
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
curwin->w_jumplistidx = curwin->w_jumplistlen;
|
|
|
|
fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
SET_XFMARK(fm, curwin->w_pcmark, curbuf->b_fnum, NULL);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* To change context, call setpcmark(), then move the current position to
|
|
|
|
* where ever, then call checkpcmark(). This ensures that the previous
|
|
|
|
* context will only be changed if the cursor moved to a different line.
|
|
|
|
* If pcmark was deleted (with "dG") the previous mark is restored.
|
|
|
|
*/
|
2014-03-16 08:20:00 +01:00
|
|
|
void checkpcmark(void)
|
|
|
|
{
|
2014-01-31 14:39:15 +01:00
|
|
|
if (curwin->w_prev_pcmark.lnum != 0
|
|
|
|
&& (equalpos(curwin->w_pcmark, curwin->w_cursor)
|
|
|
|
|| curwin->w_pcmark.lnum == 0)) {
|
|
|
|
curwin->w_pcmark = curwin->w_prev_pcmark;
|
|
|
|
curwin->w_prev_pcmark.lnum = 0; /* Show it has been checked */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* move "count" positions in the jump list (count may be negative)
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
pos_T *movemark(int count)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
pos_T *pos;
|
|
|
|
xfmark_T *jmp;
|
|
|
|
|
2019-05-19 14:34:04 +02:00
|
|
|
cleanup_jumplist(curwin, true);
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
if (curwin->w_jumplistlen == 0) /* nothing to jump to */
|
|
|
|
return (pos_T *)NULL;
|
|
|
|
|
|
|
|
for (;; ) {
|
|
|
|
if (curwin->w_jumplistidx + count < 0
|
|
|
|
|| curwin->w_jumplistidx + count >= curwin->w_jumplistlen)
|
|
|
|
return (pos_T *)NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if first CTRL-O or CTRL-I command after a jump, add cursor position
|
|
|
|
* to list. Careful: If there are duplicates (CTRL-O immediately after
|
|
|
|
* starting Vim on a file), another entry may have been removed.
|
|
|
|
*/
|
|
|
|
if (curwin->w_jumplistidx == curwin->w_jumplistlen) {
|
|
|
|
setpcmark();
|
|
|
|
--curwin->w_jumplistidx; /* skip the new entry */
|
|
|
|
if (curwin->w_jumplistidx + count < 0)
|
|
|
|
return (pos_T *)NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
curwin->w_jumplistidx += count;
|
|
|
|
|
|
|
|
jmp = curwin->w_jumplist + curwin->w_jumplistidx;
|
|
|
|
if (jmp->fmark.fnum == 0)
|
|
|
|
fname2fnum(jmp);
|
|
|
|
if (jmp->fmark.fnum != curbuf->b_fnum) {
|
|
|
|
/* jump to other file */
|
|
|
|
if (buflist_findnr(jmp->fmark.fnum) == NULL) { /* Skip this one .. */
|
|
|
|
count += count < 0 ? -1 : 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (buflist_getfile(jmp->fmark.fnum, jmp->fmark.mark.lnum,
|
|
|
|
0, FALSE) == FAIL)
|
|
|
|
return (pos_T *)NULL;
|
|
|
|
/* Set lnum again, autocommands my have changed it */
|
|
|
|
curwin->w_cursor = jmp->fmark.mark;
|
|
|
|
pos = (pos_T *)-1;
|
|
|
|
} else
|
|
|
|
pos = &(jmp->fmark.mark);
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move "count" positions in the changelist (count may be negative).
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
pos_T *movechangelist(int count)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
if (curbuf->b_changelistlen == 0) /* nothing to jump to */
|
|
|
|
return (pos_T *)NULL;
|
|
|
|
|
|
|
|
n = curwin->w_changelistidx;
|
|
|
|
if (n + count < 0) {
|
|
|
|
if (n == 0)
|
|
|
|
return (pos_T *)NULL;
|
|
|
|
n = 0;
|
2014-03-16 08:20:00 +01:00
|
|
|
} else if (n + count >= curbuf->b_changelistlen) {
|
2014-01-31 14:39:15 +01:00
|
|
|
if (n == curbuf->b_changelistlen - 1)
|
|
|
|
return (pos_T *)NULL;
|
|
|
|
n = curbuf->b_changelistlen - 1;
|
|
|
|
} else
|
|
|
|
n += count;
|
|
|
|
curwin->w_changelistidx = n;
|
2015-06-28 07:06:16 +02:00
|
|
|
return &(curbuf->b_changelist[n].mark);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find mark "c" in buffer pointed to by "buf".
|
|
|
|
* If "changefile" is TRUE it's allowed to edit another file for '0, 'A, etc.
|
|
|
|
* If "fnum" is not NULL store the fnum there for '0, 'A etc., don't edit
|
|
|
|
* another file.
|
|
|
|
* Returns:
|
|
|
|
* - pointer to pos_T if found. lnum is 0 when mark not set, -1 when mark is
|
|
|
|
* in another file which can't be gotten. (caller needs to check lnum!)
|
|
|
|
* - NULL if there is no mark called 'c'.
|
|
|
|
* - -1 if mark is in other file and jumped there (only if changefile is TRUE)
|
|
|
|
*/
|
2019-10-31 01:36:53 +01:00
|
|
|
pos_T *getmark_buf(buf_T *buf, int c, bool changefile)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
return getmark_buf_fnum(buf, c, changefile, NULL);
|
|
|
|
}
|
|
|
|
|
2019-10-31 01:36:53 +01:00
|
|
|
pos_T *getmark(int c, bool changefile)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
return getmark_buf_fnum(curbuf, c, changefile, NULL);
|
|
|
|
}
|
|
|
|
|
2019-10-31 01:36:53 +01:00
|
|
|
pos_T *getmark_buf_fnum(buf_T *buf, int c, bool changefile, int *fnum)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
pos_T *posp;
|
|
|
|
pos_T *startp, *endp;
|
|
|
|
static pos_T pos_copy;
|
|
|
|
|
|
|
|
posp = NULL;
|
|
|
|
|
|
|
|
/* Check for special key, can't be a mark name and might cause islower()
|
|
|
|
* to crash. */
|
|
|
|
if (c < 0)
|
|
|
|
return posp;
|
2015-08-23 12:53:47 +02:00
|
|
|
if (c > '~') { // check for islower()/isupper()
|
|
|
|
} else if (c == '\'' || c == '`') { // previous context mark
|
|
|
|
pos_copy = curwin->w_pcmark; // need to make a copy because
|
|
|
|
posp = &pos_copy; // w_pcmark may be changed soon
|
|
|
|
} else if (c == '"') { // to pos when leaving buffer
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
posp = &(buf->b_last_cursor.mark);
|
2015-08-23 12:53:47 +02:00
|
|
|
} else if (c == '^') { // to where Insert mode stopped
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
posp = &(buf->b_last_insert.mark);
|
2015-08-23 12:53:47 +02:00
|
|
|
} else if (c == '.') { // to where last change was made
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
posp = &(buf->b_last_change.mark);
|
2015-08-23 12:53:47 +02:00
|
|
|
} else if (c == '[') { // to start of previous operator
|
2014-01-31 14:39:15 +01:00
|
|
|
posp = &(buf->b_op_start);
|
2015-08-23 12:53:47 +02:00
|
|
|
} else if (c == ']') { // to end of previous operator
|
2014-01-31 14:39:15 +01:00
|
|
|
posp = &(buf->b_op_end);
|
2015-08-23 12:53:47 +02:00
|
|
|
} else if (c == '{' || c == '}') { // to previous/next paragraph
|
2014-01-31 14:39:15 +01:00
|
|
|
pos_T pos;
|
|
|
|
oparg_T oa;
|
|
|
|
int slcb = listcmd_busy;
|
|
|
|
|
|
|
|
pos = curwin->w_cursor;
|
|
|
|
listcmd_busy = TRUE; /* avoid that '' is changed */
|
|
|
|
if (findpar(&oa.inclusive,
|
2014-05-01 20:00:13 +02:00
|
|
|
c == '}' ? FORWARD : BACKWARD, 1L, NUL, FALSE)) {
|
2014-01-31 14:39:15 +01:00
|
|
|
pos_copy = curwin->w_cursor;
|
|
|
|
posp = &pos_copy;
|
|
|
|
}
|
|
|
|
curwin->w_cursor = pos;
|
|
|
|
listcmd_busy = slcb;
|
2014-03-16 08:20:00 +01:00
|
|
|
} else if (c == '(' || c == ')') { /* to previous/next sentence */
|
2014-01-31 14:39:15 +01:00
|
|
|
pos_T pos;
|
|
|
|
int slcb = listcmd_busy;
|
|
|
|
|
|
|
|
pos = curwin->w_cursor;
|
|
|
|
listcmd_busy = TRUE; /* avoid that '' is changed */
|
|
|
|
if (findsent(c == ')' ? FORWARD : BACKWARD, 1L)) {
|
|
|
|
pos_copy = curwin->w_cursor;
|
|
|
|
posp = &pos_copy;
|
|
|
|
}
|
|
|
|
curwin->w_cursor = pos;
|
|
|
|
listcmd_busy = slcb;
|
2014-03-16 08:20:00 +01:00
|
|
|
} else if (c == '<' || c == '>') { /* start/end of visual area */
|
2014-01-31 14:39:15 +01:00
|
|
|
startp = &buf->b_visual.vi_start;
|
|
|
|
endp = &buf->b_visual.vi_end;
|
2018-06-06 23:39:38 +02:00
|
|
|
if (((c == '<') == lt(*startp, *endp) || endp->lnum == 0)
|
|
|
|
&& startp->lnum != 0) {
|
2014-01-31 14:39:15 +01:00
|
|
|
posp = startp;
|
2018-06-06 23:39:38 +02:00
|
|
|
} else {
|
2014-01-31 14:39:15 +01:00
|
|
|
posp = endp;
|
2018-06-06 23:39:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// For Visual line mode, set mark at begin or end of line
|
2014-01-31 14:39:15 +01:00
|
|
|
if (buf->b_visual.vi_mode == 'V') {
|
|
|
|
pos_copy = *posp;
|
|
|
|
posp = &pos_copy;
|
|
|
|
if (c == '<')
|
|
|
|
pos_copy.col = 0;
|
|
|
|
else
|
|
|
|
pos_copy.col = MAXCOL;
|
|
|
|
pos_copy.coladd = 0;
|
|
|
|
}
|
2014-03-16 08:20:00 +01:00
|
|
|
} else if (ASCII_ISLOWER(c)) { /* normal named mark */
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
posp = &(buf->b_namedm[c - 'a'].mark);
|
2015-04-23 00:47:53 +02:00
|
|
|
} else if (ASCII_ISUPPER(c) || ascii_isdigit(c)) { /* named file mark */
|
|
|
|
if (ascii_isdigit(c))
|
2014-01-31 14:39:15 +01:00
|
|
|
c = c - '0' + NMARKS;
|
|
|
|
else
|
|
|
|
c -= 'A';
|
|
|
|
posp = &(namedfm[c].fmark.mark);
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
if (namedfm[c].fmark.fnum == 0) {
|
2014-01-31 14:39:15 +01:00
|
|
|
fname2fnum(&namedfm[c]);
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
if (fnum != NULL)
|
|
|
|
*fnum = namedfm[c].fmark.fnum;
|
|
|
|
else if (namedfm[c].fmark.fnum != buf->b_fnum) {
|
|
|
|
/* mark is in another file */
|
|
|
|
posp = &pos_copy;
|
|
|
|
|
|
|
|
if (namedfm[c].fmark.mark.lnum != 0
|
|
|
|
&& changefile && namedfm[c].fmark.fnum) {
|
|
|
|
if (buflist_getfile(namedfm[c].fmark.fnum,
|
|
|
|
(linenr_T)1, GETF_SETMARK, FALSE) == OK) {
|
|
|
|
/* Set the lnum now, autocommands could have changed it */
|
|
|
|
curwin->w_cursor = namedfm[c].fmark.mark;
|
|
|
|
return (pos_T *)-1;
|
|
|
|
}
|
|
|
|
pos_copy.lnum = -1; /* can't get file */
|
|
|
|
} else
|
|
|
|
pos_copy.lnum = 0; /* mark exists, but is not valid in
|
|
|
|
current buffer */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return posp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Search for the next named mark in the current file.
|
|
|
|
*
|
|
|
|
* Returns pointer to pos_T of the next mark or NULL if no mark is found.
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
pos_T *
|
|
|
|
getnextmark (
|
|
|
|
pos_T *startpos, /* where to start */
|
|
|
|
int dir, /* direction for search */
|
|
|
|
int begin_line
|
|
|
|
)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
pos_T *result = NULL;
|
|
|
|
pos_T pos;
|
|
|
|
|
|
|
|
pos = *startpos;
|
|
|
|
|
|
|
|
/* When searching backward and leaving the cursor on the first non-blank,
|
|
|
|
* position must be in a previous line.
|
|
|
|
* When searching forward and leaving the cursor on the first non-blank,
|
|
|
|
* position must be in a next line. */
|
|
|
|
if (dir == BACKWARD && begin_line)
|
|
|
|
pos.col = 0;
|
|
|
|
else if (dir == FORWARD && begin_line)
|
|
|
|
pos.col = MAXCOL;
|
|
|
|
|
|
|
|
for (i = 0; i < NMARKS; i++) {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
if (curbuf->b_namedm[i].mark.lnum > 0) {
|
2014-01-31 14:39:15 +01:00
|
|
|
if (dir == FORWARD) {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
if ((result == NULL || lt(curbuf->b_namedm[i].mark, *result))
|
|
|
|
&& lt(pos, curbuf->b_namedm[i].mark))
|
|
|
|
result = &curbuf->b_namedm[i].mark;
|
2014-03-16 08:20:00 +01:00
|
|
|
} else {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
if ((result == NULL || lt(*result, curbuf->b_namedm[i].mark))
|
|
|
|
&& lt(curbuf->b_namedm[i].mark, pos))
|
|
|
|
result = &curbuf->b_namedm[i].mark;
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For an xtended filemark: set the fnum from the fname.
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
* This is used for marks obtained from the .shada file. It's postponed
|
2014-01-31 14:39:15 +01:00
|
|
|
* until the mark is used to avoid a long startup delay.
|
|
|
|
*/
|
2019-05-19 14:34:04 +02:00
|
|
|
static void fname2fnum(xfmark_T *fm)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
char_u *p;
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
if (fm->fname != NULL) {
|
|
|
|
/*
|
|
|
|
* First expand "~/" in the file name to the home directory.
|
|
|
|
* Don't expand the whole name, it may contain other '~' chars.
|
|
|
|
*/
|
|
|
|
if (fm->fname[0] == '~' && (fm->fname[1] == '/'
|
|
|
|
#ifdef BACKSLASH_IN_FILENAME
|
|
|
|
|| fm->fname[1] == '\\'
|
|
|
|
#endif
|
|
|
|
)) {
|
|
|
|
int len;
|
|
|
|
|
|
|
|
expand_env((char_u *)"~/", NameBuff, MAXPATHL);
|
|
|
|
len = (int)STRLEN(NameBuff);
|
2014-05-26 16:09:09 +02:00
|
|
|
STRLCPY(NameBuff + len, fm->fname + 2, MAXPATHL - len);
|
2014-01-31 14:39:15 +01:00
|
|
|
} else
|
2014-05-26 16:09:09 +02:00
|
|
|
STRLCPY(NameBuff, fm->fname, MAXPATHL);
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* Try to shorten the file name. */
|
2014-03-27 12:38:33 +01:00
|
|
|
os_dirname(IObuff, IOSIZE);
|
2014-04-13 20:30:53 +02:00
|
|
|
p = path_shorten_fname(NameBuff, IObuff);
|
2014-01-31 14:39:15 +01:00
|
|
|
|
2016-08-23 16:11:26 +02:00
|
|
|
// buflist_new() will call fmarks_check_names()
|
2016-10-31 03:50:19 +01:00
|
|
|
(void)buflist_new(NameBuff, p, (linenr_T)1, 0);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check all file marks for a name that matches the file name in buf.
|
|
|
|
* May replace the name with an fnum.
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
* Used for marks that come from the .shada file.
|
2014-01-31 14:39:15 +01:00
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
void fmarks_check_names(buf_T *buf)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
char_u *name = buf->b_ffname;
|
2014-01-31 14:39:15 +01:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (buf->b_ffname == NULL)
|
|
|
|
return;
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
for (i = 0; i < NGLOBALMARKS; ++i)
|
2014-01-31 14:39:15 +01:00
|
|
|
fmarks_check_one(&namedfm[i], name, buf);
|
|
|
|
|
2014-09-20 06:28:50 +02:00
|
|
|
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
2014-08-21 01:35:07 +02:00
|
|
|
for (i = 0; i < wp->w_jumplistlen; ++i) {
|
2014-01-31 14:39:15 +01:00
|
|
|
fmarks_check_one(&wp->w_jumplist[i], name, buf);
|
2014-08-21 01:35:07 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-23 21:34:45 +01:00
|
|
|
static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
if (fm->fmark.fnum == 0
|
|
|
|
&& fm->fname != NULL
|
|
|
|
&& fnamecmp(name, fm->fname) == 0) {
|
|
|
|
fm->fmark.fnum = buf->b_fnum;
|
2019-05-22 01:02:26 +02:00
|
|
|
XFREE_CLEAR(fm->fname);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check a if a position from a mark is valid.
|
|
|
|
* Give and error message and return FAIL if not.
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
int check_mark(pos_T *pos)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
if (pos == NULL) {
|
|
|
|
EMSG(_(e_umark));
|
|
|
|
return FAIL;
|
|
|
|
}
|
|
|
|
if (pos->lnum <= 0) {
|
|
|
|
/* lnum is negative if mark is in another file can can't get that
|
|
|
|
* file, error message already give then. */
|
|
|
|
if (pos->lnum == 0)
|
|
|
|
EMSG(_(e_marknotset));
|
|
|
|
return FAIL;
|
|
|
|
}
|
|
|
|
if (pos->lnum > curbuf->b_ml.ml_line_count) {
|
|
|
|
EMSG(_(e_markinval));
|
|
|
|
return FAIL;
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2015-10-23 13:42:35 +02:00
|
|
|
/// Clear all marks and change list in the given buffer
|
|
|
|
///
|
|
|
|
/// Used mainly when trashing the entire buffer during ":e" type commands.
|
|
|
|
///
|
|
|
|
/// @param[out] buf Buffer to clear marks in.
|
|
|
|
void clrallmarks(buf_T *const buf)
|
|
|
|
FUNC_ATTR_NONNULL_ALL
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
2015-10-23 13:42:35 +02:00
|
|
|
for (size_t i = 0; i < NMARKS; i++) {
|
|
|
|
clear_fmark(&buf->b_namedm[i]);
|
|
|
|
}
|
|
|
|
clear_fmark(&buf->b_last_cursor);
|
|
|
|
buf->b_last_cursor.mark.lnum = 1;
|
|
|
|
clear_fmark(&buf->b_last_insert);
|
|
|
|
clear_fmark(&buf->b_last_change);
|
|
|
|
buf->b_op_start.lnum = 0; // start/end op mark cleared
|
2014-01-31 14:39:15 +01:00
|
|
|
buf->b_op_end.lnum = 0;
|
2015-10-23 13:42:35 +02:00
|
|
|
for (int i = 0; i < buf->b_changelistlen; i++) {
|
|
|
|
clear_fmark(&buf->b_changelist[i]);
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
buf->b_changelistlen = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get name of file from a filemark.
|
|
|
|
* When it's in the current buffer, return the text at the mark.
|
|
|
|
* Returns an allocated string.
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
char_u *fm_getname(fmark_T *fmark, int lead_len)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
if (fmark->fnum == curbuf->b_fnum) /* current buffer */
|
|
|
|
return mark_line(&(fmark->mark), lead_len);
|
|
|
|
return buflist_nr2name(fmark->fnum, FALSE, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the line at mark "mp". Truncate to fit in window.
|
|
|
|
* The returned string has been allocated.
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
static char_u *mark_line(pos_T *mp, int lead_len)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
char_u *s, *p;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (mp->lnum == 0 || mp->lnum > curbuf->b_ml.ml_line_count)
|
|
|
|
return vim_strsave((char_u *)"-invalid-");
|
2015-02-12 13:49:02 +01:00
|
|
|
assert(Columns >= 0 && (size_t)Columns <= SIZE_MAX);
|
2018-09-14 02:07:19 +02:00
|
|
|
// Allow for up to 5 bytes per character.
|
|
|
|
s = vim_strnsave(skipwhite(ml_get(mp->lnum)), (size_t)Columns * 5);
|
2014-05-09 02:34:46 +02:00
|
|
|
|
2018-09-14 02:07:19 +02:00
|
|
|
// Truncate the line to fit it in the window
|
2014-01-31 14:39:15 +01:00
|
|
|
len = 0;
|
2018-06-12 05:43:14 +02:00
|
|
|
for (p = s; *p != NUL; MB_PTR_ADV(p)) {
|
2014-01-31 14:39:15 +01:00
|
|
|
len += ptr2cells(p);
|
|
|
|
if (len >= Columns - lead_len)
|
|
|
|
break;
|
|
|
|
}
|
2014-05-01 20:00:13 +02:00
|
|
|
*p = NUL;
|
2014-01-31 14:39:15 +01:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* print the marks
|
|
|
|
*/
|
2019-09-20 02:41:08 +02:00
|
|
|
void ex_marks(exarg_T *eap)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
char_u *arg = eap->arg;
|
|
|
|
int i;
|
|
|
|
char_u *name;
|
|
|
|
|
2014-05-01 20:00:13 +02:00
|
|
|
if (arg != NULL && *arg == NUL)
|
2014-01-31 14:39:15 +01:00
|
|
|
arg = NULL;
|
|
|
|
|
2015-08-23 12:53:47 +02:00
|
|
|
show_one_mark('\'', arg, &curwin->w_pcmark, NULL, true);
|
2014-01-31 14:39:15 +01:00
|
|
|
for (i = 0; i < NMARKS; ++i)
|
2015-08-23 12:53:47 +02:00
|
|
|
show_one_mark(i + 'a', arg, &curbuf->b_namedm[i].mark, NULL, true);
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
for (i = 0; i < NGLOBALMARKS; ++i) {
|
2014-01-31 14:39:15 +01:00
|
|
|
if (namedfm[i].fmark.fnum != 0)
|
|
|
|
name = fm_getname(&namedfm[i].fmark, 15);
|
|
|
|
else
|
|
|
|
name = namedfm[i].fname;
|
|
|
|
if (name != NULL) {
|
|
|
|
show_one_mark(i >= NMARKS ? i - NMARKS + '0' : i + 'A',
|
|
|
|
arg, &namedfm[i].fmark.mark, name,
|
|
|
|
namedfm[i].fmark.fnum == curbuf->b_fnum);
|
|
|
|
if (namedfm[i].fmark.fnum != 0)
|
2015-04-12 16:37:22 +02:00
|
|
|
xfree(name);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
2015-08-23 12:53:47 +02:00
|
|
|
show_one_mark('"', arg, &curbuf->b_last_cursor.mark, NULL, true);
|
|
|
|
show_one_mark('[', arg, &curbuf->b_op_start, NULL, true);
|
|
|
|
show_one_mark(']', arg, &curbuf->b_op_end, NULL, true);
|
|
|
|
show_one_mark('^', arg, &curbuf->b_last_insert.mark, NULL, true);
|
|
|
|
show_one_mark('.', arg, &curbuf->b_last_change.mark, NULL, true);
|
|
|
|
show_one_mark('<', arg, &curbuf->b_visual.vi_start, NULL, true);
|
|
|
|
show_one_mark('>', arg, &curbuf->b_visual.vi_end, NULL, true);
|
|
|
|
show_one_mark(-1, arg, NULL, NULL, false);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
2018-06-06 23:39:38 +02:00
|
|
|
static void
|
|
|
|
show_one_mark(
|
2014-02-23 21:34:45 +01:00
|
|
|
int c,
|
|
|
|
char_u *arg,
|
|
|
|
pos_T *p,
|
2019-07-01 20:28:37 +02:00
|
|
|
char_u *name_arg,
|
|
|
|
int current // in current file
|
2014-02-23 21:34:45 +01:00
|
|
|
)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
2019-07-01 20:28:37 +02:00
|
|
|
static bool did_title = false;
|
|
|
|
bool mustfree = false;
|
|
|
|
char_u *name = name_arg;
|
|
|
|
|
|
|
|
if (c == -1) { // finish up
|
|
|
|
if (did_title) {
|
|
|
|
did_title = false;
|
|
|
|
} else {
|
|
|
|
if (arg == NULL) {
|
2014-01-31 14:39:15 +01:00
|
|
|
MSG(_("No marks set"));
|
2019-07-01 20:28:37 +02:00
|
|
|
} else {
|
2014-01-31 14:39:15 +01:00
|
|
|
EMSG2(_("E283: No marks matching \"%s\""), arg);
|
2019-07-01 20:28:37 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
2019-07-01 20:28:37 +02:00
|
|
|
} else if (!got_int
|
|
|
|
&& (arg == NULL || vim_strchr(arg, c) != NULL)
|
|
|
|
&& p->lnum != 0) {
|
|
|
|
// don't output anything if 'q' typed at --more-- prompt
|
|
|
|
if (name == NULL && current) {
|
|
|
|
name = mark_line(p, 15);
|
|
|
|
mustfree = true;
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
2019-07-01 20:28:37 +02:00
|
|
|
if (!message_filtered(name)) {
|
|
|
|
if (!did_title) {
|
|
|
|
// Highlight title
|
|
|
|
msg_puts_title(_("\nmark line col file/text"));
|
|
|
|
did_title = true;
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
2019-07-01 20:28:37 +02:00
|
|
|
msg_putchar('\n');
|
|
|
|
if (!got_int) {
|
|
|
|
snprintf((char *)IObuff, IOSIZE, " %c %6ld %4d ", c, p->lnum, p->col);
|
|
|
|
msg_outtrans(IObuff);
|
|
|
|
if (name != NULL) {
|
|
|
|
msg_outtrans_attr(name, current ? HL_ATTR(HLF_D) : 0);
|
2018-06-10 12:24:00 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
2019-07-01 20:28:37 +02:00
|
|
|
ui_flush(); // show one line at a time
|
|
|
|
}
|
|
|
|
if (mustfree) {
|
|
|
|
xfree(name);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ":delmarks[!] [marks]"
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
void ex_delmarks(exarg_T *eap)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
char_u *p;
|
|
|
|
int from, to;
|
|
|
|
int i;
|
|
|
|
int lower;
|
|
|
|
int digit;
|
|
|
|
int n;
|
|
|
|
|
2014-05-01 20:00:13 +02:00
|
|
|
if (*eap->arg == NUL && eap->forceit)
|
2014-01-31 14:39:15 +01:00
|
|
|
/* clear all marks */
|
|
|
|
clrallmarks(curbuf);
|
|
|
|
else if (eap->forceit)
|
|
|
|
EMSG(_(e_invarg));
|
2014-05-01 20:00:13 +02:00
|
|
|
else if (*eap->arg == NUL)
|
2014-01-31 14:39:15 +01:00
|
|
|
EMSG(_(e_argreq));
|
|
|
|
else {
|
|
|
|
/* clear specified marks only */
|
2014-05-01 20:00:13 +02:00
|
|
|
for (p = eap->arg; *p != NUL; ++p) {
|
2014-01-31 14:39:15 +01:00
|
|
|
lower = ASCII_ISLOWER(*p);
|
2015-04-23 00:47:53 +02:00
|
|
|
digit = ascii_isdigit(*p);
|
2014-01-31 14:39:15 +01:00
|
|
|
if (lower || digit || ASCII_ISUPPER(*p)) {
|
|
|
|
if (p[1] == '-') {
|
|
|
|
/* clear range of marks */
|
|
|
|
from = *p;
|
|
|
|
to = p[2];
|
|
|
|
if (!(lower ? ASCII_ISLOWER(p[2])
|
2015-04-23 00:47:53 +02:00
|
|
|
: (digit ? ascii_isdigit(p[2])
|
2014-01-31 14:39:15 +01:00
|
|
|
: ASCII_ISUPPER(p[2])))
|
|
|
|
|| to < from) {
|
|
|
|
EMSG2(_(e_invarg2), p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p += 2;
|
|
|
|
} else
|
|
|
|
/* clear one lower case mark */
|
|
|
|
from = to = *p;
|
|
|
|
|
|
|
|
for (i = from; i <= to; ++i) {
|
2015-08-23 12:53:47 +02:00
|
|
|
if (lower) {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
curbuf->b_namedm[i - 'a'].mark.lnum = 0;
|
2015-08-23 12:53:47 +02:00
|
|
|
} else {
|
|
|
|
if (digit) {
|
2014-01-31 14:39:15 +01:00
|
|
|
n = i - '0' + NMARKS;
|
2015-08-23 12:53:47 +02:00
|
|
|
} else {
|
2014-01-31 14:39:15 +01:00
|
|
|
n = i - 'A';
|
2015-08-23 12:53:47 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
namedfm[n].fmark.mark.lnum = 0;
|
2019-05-22 01:02:26 +02:00
|
|
|
XFREE_CLEAR(namedfm[n].fname);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
switch (*p) {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
case '"': CLEAR_FMARK(&curbuf->b_last_cursor); break;
|
|
|
|
case '^': CLEAR_FMARK(&curbuf->b_last_insert); break;
|
|
|
|
case '.': CLEAR_FMARK(&curbuf->b_last_change); break;
|
2014-01-31 14:39:15 +01:00
|
|
|
case '[': curbuf->b_op_start.lnum = 0; break;
|
|
|
|
case ']': curbuf->b_op_end.lnum = 0; break;
|
|
|
|
case '<': curbuf->b_visual.vi_start.lnum = 0; break;
|
|
|
|
case '>': curbuf->b_visual.vi_end.lnum = 0; break;
|
|
|
|
case ' ': break;
|
|
|
|
default: EMSG2(_(e_invarg2), p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* print the jumplist
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
void ex_jumps(exarg_T *eap)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char_u *name;
|
|
|
|
|
2019-05-19 14:34:04 +02:00
|
|
|
cleanup_jumplist(curwin, true);
|
2019-05-19 14:57:10 +02:00
|
|
|
// Highlight title
|
2014-01-31 14:39:15 +01:00
|
|
|
MSG_PUTS_TITLE(_("\n jump line col file/text"));
|
|
|
|
for (i = 0; i < curwin->w_jumplistlen && !got_int; ++i) {
|
|
|
|
if (curwin->w_jumplist[i].fmark.mark.lnum != 0) {
|
|
|
|
name = fm_getname(&curwin->w_jumplist[i].fmark, 16);
|
2019-07-01 20:02:48 +02:00
|
|
|
|
|
|
|
// apply :filter /pat/ or file name not available
|
|
|
|
if (name == NULL || message_filtered(name)) {
|
2019-07-02 08:00:59 +02:00
|
|
|
xfree(name);
|
2014-01-31 14:39:15 +01:00
|
|
|
continue;
|
2019-07-01 20:02:48 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
msg_putchar('\n');
|
|
|
|
if (got_int) {
|
2015-04-12 16:37:22 +02:00
|
|
|
xfree(name);
|
2014-01-31 14:39:15 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
sprintf((char *)IObuff, "%c %2d %5ld %4d ",
|
|
|
|
i == curwin->w_jumplistidx ? '>' : ' ',
|
|
|
|
i > curwin->w_jumplistidx ? i - curwin->w_jumplistidx
|
|
|
|
: curwin->w_jumplistidx - i,
|
|
|
|
curwin->w_jumplist[i].fmark.mark.lnum,
|
|
|
|
curwin->w_jumplist[i].fmark.mark.col);
|
|
|
|
msg_outtrans(IObuff);
|
|
|
|
msg_outtrans_attr(name,
|
2018-06-10 12:24:00 +02:00
|
|
|
curwin->w_jumplist[i].fmark.fnum == curbuf->b_fnum
|
|
|
|
? HL_ATTR(HLF_D) : 0);
|
2015-04-12 16:37:22 +02:00
|
|
|
xfree(name);
|
2014-11-27 18:10:42 +01:00
|
|
|
os_breakcheck();
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
2015-02-17 03:47:56 +01:00
|
|
|
ui_flush();
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
if (curwin->w_jumplistidx == curwin->w_jumplistlen)
|
|
|
|
MSG_PUTS("\n>");
|
|
|
|
}
|
|
|
|
|
2017-01-02 20:09:48 +01:00
|
|
|
void ex_clearjumps(exarg_T *eap)
|
|
|
|
{
|
|
|
|
free_jumplist(curwin);
|
|
|
|
curwin->w_jumplistlen = 0;
|
|
|
|
curwin->w_jumplistidx = 0;
|
|
|
|
}
|
|
|
|
|
2014-01-31 14:39:15 +01:00
|
|
|
/*
|
|
|
|
* print the changelist
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
void ex_changes(exarg_T *eap)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char_u *name;
|
|
|
|
|
2018-06-10 12:24:00 +02:00
|
|
|
// Highlight title
|
2014-01-31 14:39:15 +01:00
|
|
|
MSG_PUTS_TITLE(_("\nchange line col text"));
|
|
|
|
|
|
|
|
for (i = 0; i < curbuf->b_changelistlen && !got_int; ++i) {
|
2015-06-28 07:06:16 +02:00
|
|
|
if (curbuf->b_changelist[i].mark.lnum != 0) {
|
2014-01-31 14:39:15 +01:00
|
|
|
msg_putchar('\n');
|
|
|
|
if (got_int)
|
|
|
|
break;
|
|
|
|
sprintf((char *)IObuff, "%c %3d %5ld %4d ",
|
|
|
|
i == curwin->w_changelistidx ? '>' : ' ',
|
|
|
|
i > curwin->w_changelistidx ? i - curwin->w_changelistidx
|
|
|
|
: curwin->w_changelistidx - i,
|
2015-06-28 07:06:16 +02:00
|
|
|
(long)curbuf->b_changelist[i].mark.lnum,
|
|
|
|
curbuf->b_changelist[i].mark.col);
|
2014-01-31 14:39:15 +01:00
|
|
|
msg_outtrans(IObuff);
|
2015-06-28 07:06:16 +02:00
|
|
|
name = mark_line(&curbuf->b_changelist[i].mark, 17);
|
2018-06-10 12:24:00 +02:00
|
|
|
msg_outtrans_attr(name, HL_ATTR(HLF_D));
|
2015-04-12 16:37:22 +02:00
|
|
|
xfree(name);
|
2014-11-27 18:10:42 +01:00
|
|
|
os_breakcheck();
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
2015-02-17 03:47:56 +01:00
|
|
|
ui_flush();
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
if (curwin->w_changelistidx == curbuf->b_changelistlen)
|
|
|
|
MSG_PUTS("\n>");
|
|
|
|
}
|
|
|
|
|
|
|
|
#define one_adjust(add) \
|
|
|
|
{ \
|
|
|
|
lp = add; \
|
|
|
|
if (*lp >= line1 && *lp <= line2) \
|
|
|
|
{ \
|
|
|
|
if (amount == MAXLNUM) \
|
|
|
|
*lp = 0; \
|
|
|
|
else \
|
|
|
|
*lp += amount; \
|
|
|
|
} \
|
|
|
|
else if (amount_after && *lp > line2) \
|
|
|
|
*lp += amount_after; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* don't delete the line, just put at first deleted line */
|
|
|
|
#define one_adjust_nodel(add) \
|
|
|
|
{ \
|
|
|
|
lp = add; \
|
|
|
|
if (*lp >= line1 && *lp <= line2) \
|
|
|
|
{ \
|
|
|
|
if (amount == MAXLNUM) \
|
|
|
|
*lp = line1; \
|
|
|
|
else \
|
|
|
|
*lp += amount; \
|
|
|
|
} \
|
|
|
|
else if (amount_after && *lp > line2) \
|
|
|
|
*lp += amount_after; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjust marks between line1 and line2 (inclusive) to move 'amount' lines.
|
|
|
|
* Must be called before changed_*(), appended_lines() or deleted_lines().
|
|
|
|
* May be called before or after changing the text.
|
|
|
|
* When deleting lines line1 to line2, use an 'amount' of MAXLNUM: The marks
|
|
|
|
* within this range are made invalid.
|
|
|
|
* If 'amount_after' is non-zero adjust marks after line2.
|
|
|
|
* Example: Delete lines 34 and 35: mark_adjust(34, 35, MAXLNUM, -2);
|
|
|
|
* Example: Insert two lines below 55: mark_adjust(56, MAXLNUM, 2, 0);
|
|
|
|
* or: mark_adjust(56, 55, MAXLNUM, 2);
|
|
|
|
*/
|
2016-08-28 15:36:18 +02:00
|
|
|
void mark_adjust(linenr_T line1,
|
|
|
|
linenr_T line2,
|
|
|
|
long amount,
|
|
|
|
long amount_after,
|
2017-01-18 13:20:07 +01:00
|
|
|
bool end_temp,
|
|
|
|
ExtmarkOp op)
|
2017-02-27 10:46:50 +01:00
|
|
|
{
|
2017-01-18 13:20:07 +01:00
|
|
|
mark_adjust_internal(line1, line2, amount, amount_after, true, end_temp, op);
|
2017-02-27 10:46:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// mark_adjust_nofold() does the same as mark_adjust() but without adjusting
|
|
|
|
// folds in any way. Folds must be adjusted manually by the caller.
|
|
|
|
// This is only useful when folds need to be moved in a way different to
|
|
|
|
// calling foldMarkAdjust() with arguments line1, line2, amount, amount_after,
|
|
|
|
// for an example of why this may be necessary, see do_move().
|
|
|
|
void mark_adjust_nofold(linenr_T line1, linenr_T line2, long amount,
|
2017-01-18 13:20:07 +01:00
|
|
|
long amount_after, bool end_temp,
|
|
|
|
ExtmarkOp op)
|
2017-02-27 10:46:50 +01:00
|
|
|
{
|
2017-01-18 13:20:07 +01:00
|
|
|
mark_adjust_internal(line1, line2, amount, amount_after, false, end_temp, op);
|
2017-02-27 10:46:50 +01:00
|
|
|
}
|
|
|
|
|
2016-08-28 15:36:18 +02:00
|
|
|
static void mark_adjust_internal(linenr_T line1, linenr_T line2,
|
|
|
|
long amount, long amount_after,
|
2017-01-18 13:20:07 +01:00
|
|
|
bool adjust_folds, bool end_temp,
|
|
|
|
ExtmarkOp op)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int fnum = curbuf->b_fnum;
|
|
|
|
linenr_T *lp;
|
2019-03-08 09:03:47 +01:00
|
|
|
static pos_T initpos = { 1, 0, 0 };
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
if (line2 < line1 && amount_after == 0L) /* nothing to do */
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!cmdmod.lockmarks) {
|
|
|
|
/* named marks, lower case and upper case */
|
|
|
|
for (i = 0; i < NMARKS; i++) {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
one_adjust(&(curbuf->b_namedm[i].mark.lnum));
|
2014-01-31 14:39:15 +01:00
|
|
|
if (namedfm[i].fmark.fnum == fnum)
|
|
|
|
one_adjust_nodel(&(namedfm[i].fmark.mark.lnum));
|
|
|
|
}
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
for (i = NMARKS; i < NGLOBALMARKS; i++) {
|
2014-01-31 14:39:15 +01:00
|
|
|
if (namedfm[i].fmark.fnum == fnum)
|
|
|
|
one_adjust_nodel(&(namedfm[i].fmark.mark.lnum));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* last Insert position */
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
one_adjust(&(curbuf->b_last_insert.mark.lnum));
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* last change position */
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
one_adjust(&(curbuf->b_last_change.mark.lnum));
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* last cursor position, if it was set */
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
if (!equalpos(curbuf->b_last_cursor.mark, initpos))
|
|
|
|
one_adjust(&(curbuf->b_last_cursor.mark.lnum));
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* list of change positions */
|
|
|
|
for (i = 0; i < curbuf->b_changelistlen; ++i)
|
2015-06-28 07:06:16 +02:00
|
|
|
one_adjust_nodel(&(curbuf->b_changelist[i].mark.lnum));
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* Visual area */
|
|
|
|
one_adjust_nodel(&(curbuf->b_visual.vi_start.lnum));
|
|
|
|
one_adjust_nodel(&(curbuf->b_visual.vi_end.lnum));
|
|
|
|
|
2017-10-01 15:37:27 +02:00
|
|
|
// quickfix marks
|
|
|
|
if (!qf_mark_adjust(NULL, line1, line2, amount, amount_after)) {
|
|
|
|
curbuf->b_has_qf_entry &= ~BUF_HAS_QF_ENTRY;
|
|
|
|
}
|
|
|
|
// location lists
|
|
|
|
bool found_one = false;
|
2014-08-23 19:03:14 +02:00
|
|
|
FOR_ALL_TAB_WINDOWS(tab, win) {
|
2017-10-01 15:37:27 +02:00
|
|
|
found_one |= qf_mark_adjust(win, line1, line2, amount, amount_after);
|
|
|
|
}
|
|
|
|
if (!found_one) {
|
|
|
|
curbuf->b_has_qf_entry &= ~BUF_HAS_LL_ENTRY;
|
2014-08-23 19:03:14 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
2014-03-28 07:09:08 +01:00
|
|
|
sign_mark_adjust(line1, line2, amount, amount_after);
|
2016-08-28 15:36:18 +02:00
|
|
|
bufhl_mark_adjust(curbuf, line1, line2, amount, amount_after, end_temp);
|
2017-01-18 13:20:07 +01:00
|
|
|
if (op != kExtmarkNOOP) {
|
|
|
|
extmark_adjust(curbuf, line1, line2, amount, amount_after, op, end_temp);
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* previous context mark */
|
|
|
|
one_adjust(&(curwin->w_pcmark.lnum));
|
|
|
|
|
|
|
|
/* previous pcmark */
|
|
|
|
one_adjust(&(curwin->w_prev_pcmark.lnum));
|
|
|
|
|
|
|
|
/* saved cursor for formatting */
|
|
|
|
if (saved_cursor.lnum != 0)
|
|
|
|
one_adjust_nodel(&(saved_cursor.lnum));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjust items in all windows related to the current buffer.
|
|
|
|
*/
|
2014-08-23 19:03:14 +02:00
|
|
|
FOR_ALL_TAB_WINDOWS(tab, win) {
|
|
|
|
if (!cmdmod.lockmarks) {
|
2014-01-31 14:39:15 +01:00
|
|
|
/* Marks in the jumplist. When deleting lines, this may create
|
|
|
|
* duplicate marks in the jumplist, they will be removed later. */
|
2014-08-23 19:03:14 +02:00
|
|
|
for (i = 0; i < win->w_jumplistlen; ++i) {
|
|
|
|
if (win->w_jumplist[i].fmark.fnum == fnum) {
|
2014-01-31 14:39:15 +01:00
|
|
|
one_adjust_nodel(&(win->w_jumplist[i].fmark.mark.lnum));
|
2014-08-23 19:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
if (win->w_buffer == curbuf) {
|
2014-08-23 19:03:14 +02:00
|
|
|
if (!cmdmod.lockmarks) {
|
2014-01-31 14:39:15 +01:00
|
|
|
/* marks in the tag stack */
|
2014-08-23 19:03:14 +02:00
|
|
|
for (i = 0; i < win->w_tagstacklen; i++) {
|
|
|
|
if (win->w_tagstack[i].fmark.fnum == fnum) {
|
2014-01-31 14:39:15 +01:00
|
|
|
one_adjust_nodel(&(win->w_tagstack[i].fmark.mark.lnum));
|
2014-08-23 19:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* the displayed Visual area */
|
|
|
|
if (win->w_old_cursor_lnum != 0) {
|
|
|
|
one_adjust_nodel(&(win->w_old_cursor_lnum));
|
|
|
|
one_adjust_nodel(&(win->w_old_visual_lnum));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* topline and cursor position for windows with the same buffer
|
|
|
|
* other than the current window */
|
|
|
|
if (win != curwin) {
|
|
|
|
if (win->w_topline >= line1 && win->w_topline <= line2) {
|
|
|
|
if (amount == MAXLNUM) { /* topline is deleted */
|
2014-08-23 19:03:14 +02:00
|
|
|
if (line1 <= 1) {
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_topline = 1;
|
2014-08-23 19:03:14 +02:00
|
|
|
} else {
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_topline = line1 - 1;
|
2014-08-23 19:03:14 +02:00
|
|
|
}
|
|
|
|
} else { /* keep topline on the same line */
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_topline += amount;
|
2014-08-23 19:03:14 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_topfill = 0;
|
2014-03-16 08:20:00 +01:00
|
|
|
} else if (amount_after && win->w_topline > line2) {
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_topline += amount_after;
|
|
|
|
win->w_topfill = 0;
|
|
|
|
}
|
|
|
|
if (win->w_cursor.lnum >= line1 && win->w_cursor.lnum <= line2) {
|
|
|
|
if (amount == MAXLNUM) { /* line with cursor is deleted */
|
2014-08-23 19:03:14 +02:00
|
|
|
if (line1 <= 1) {
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_cursor.lnum = 1;
|
2014-08-23 19:03:14 +02:00
|
|
|
} else {
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_cursor.lnum = line1 - 1;
|
2014-08-23 19:03:14 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_cursor.col = 0;
|
2014-08-23 19:03:14 +02:00
|
|
|
} else { /* keep cursor on the same line */
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_cursor.lnum += amount;
|
2014-08-23 19:03:14 +02:00
|
|
|
}
|
|
|
|
} else if (amount_after && win->w_cursor.lnum > line2) {
|
2014-01-31 14:39:15 +01:00
|
|
|
win->w_cursor.lnum += amount_after;
|
2014-08-23 19:03:14 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
2017-02-27 10:46:50 +01:00
|
|
|
if (adjust_folds) {
|
|
|
|
foldMarkAdjust(win, line1, line2, amount, amount_after);
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* adjust diffs */
|
|
|
|
diff_mark_adjust(line1, line2, amount, amount_after);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This code is used often, needs to be fast. */
|
|
|
|
#define col_adjust(pp) \
|
|
|
|
{ \
|
|
|
|
posp = pp; \
|
|
|
|
if (posp->lnum == lnum && posp->col >= mincol) \
|
|
|
|
{ \
|
|
|
|
posp->lnum += lnum_amount; \
|
2015-02-12 13:49:02 +01:00
|
|
|
assert(col_amount > INT_MIN && col_amount <= INT_MAX); \
|
2019-03-14 11:23:05 +01:00
|
|
|
if (col_amount < 0 && posp->col <= (colnr_T)-col_amount) { \
|
2014-01-31 14:39:15 +01:00
|
|
|
posp->col = 0; \
|
2019-03-14 11:23:05 +01:00
|
|
|
} else if (posp->col < spaces_removed) { \
|
|
|
|
posp->col = (int)col_amount + spaces_removed; \
|
|
|
|
} else { \
|
2015-02-12 13:49:02 +01:00
|
|
|
posp->col += (colnr_T)col_amount; \
|
2019-03-14 11:23:05 +01:00
|
|
|
} \
|
2014-01-31 14:39:15 +01:00
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2019-03-14 11:23:05 +01:00
|
|
|
// Adjust marks in line "lnum" at column "mincol" and further: add
|
|
|
|
// "lnum_amount" to the line number and add "col_amount" to the column
|
|
|
|
// position.
|
|
|
|
// "spaces_removed" is the number of spaces that were removed, matters when the
|
|
|
|
// cursor is inside them.
|
|
|
|
void mark_col_adjust(
|
|
|
|
linenr_T lnum, colnr_T mincol, long lnum_amount, long col_amount,
|
2017-01-18 13:20:07 +01:00
|
|
|
int spaces_removed, ExtmarkOp op)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int fnum = curbuf->b_fnum;
|
|
|
|
pos_T *posp;
|
|
|
|
|
|
|
|
if ((col_amount == 0L && lnum_amount == 0L) || cmdmod.lockmarks)
|
|
|
|
return; /* nothing to do */
|
|
|
|
|
|
|
|
/* named marks, lower case and upper case */
|
|
|
|
for (i = 0; i < NMARKS; i++) {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
col_adjust(&(curbuf->b_namedm[i].mark));
|
2014-01-31 14:39:15 +01:00
|
|
|
if (namedfm[i].fmark.fnum == fnum)
|
|
|
|
col_adjust(&(namedfm[i].fmark.mark));
|
|
|
|
}
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
for (i = NMARKS; i < NGLOBALMARKS; i++) {
|
2014-01-31 14:39:15 +01:00
|
|
|
if (namedfm[i].fmark.fnum == fnum)
|
|
|
|
col_adjust(&(namedfm[i].fmark.mark));
|
|
|
|
}
|
|
|
|
|
2017-01-18 13:20:07 +01:00
|
|
|
// Extmarks
|
|
|
|
if (op != kExtmarkNOOP) {
|
|
|
|
// TODO(timeyyy): consider spaces_removed? (behave like a delete)
|
|
|
|
extmark_col_adjust(curbuf, lnum, mincol, lnum_amount, col_amount,
|
|
|
|
kExtmarkUndo);
|
|
|
|
}
|
|
|
|
|
2014-01-31 14:39:15 +01:00
|
|
|
/* last Insert position */
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
col_adjust(&(curbuf->b_last_insert.mark));
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* last change position */
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
col_adjust(&(curbuf->b_last_change.mark));
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* list of change positions */
|
|
|
|
for (i = 0; i < curbuf->b_changelistlen; ++i)
|
2015-06-28 07:06:16 +02:00
|
|
|
col_adjust(&(curbuf->b_changelist[i].mark));
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* Visual area */
|
|
|
|
col_adjust(&(curbuf->b_visual.vi_start));
|
|
|
|
col_adjust(&(curbuf->b_visual.vi_end));
|
|
|
|
|
|
|
|
/* previous context mark */
|
|
|
|
col_adjust(&(curwin->w_pcmark));
|
|
|
|
|
|
|
|
/* previous pcmark */
|
|
|
|
col_adjust(&(curwin->w_prev_pcmark));
|
|
|
|
|
|
|
|
/* saved cursor for formatting */
|
|
|
|
col_adjust(&saved_cursor);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjust items in all windows related to the current buffer.
|
|
|
|
*/
|
2014-09-20 06:28:50 +02:00
|
|
|
FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
|
2014-01-31 14:39:15 +01:00
|
|
|
/* marks in the jumplist */
|
2014-08-21 01:35:07 +02:00
|
|
|
for (i = 0; i < win->w_jumplistlen; ++i) {
|
|
|
|
if (win->w_jumplist[i].fmark.fnum == fnum) {
|
2014-01-31 14:39:15 +01:00
|
|
|
col_adjust(&(win->w_jumplist[i].fmark.mark));
|
2014-08-21 01:35:07 +02:00
|
|
|
}
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
if (win->w_buffer == curbuf) {
|
|
|
|
/* marks in the tag stack */
|
2014-08-21 01:35:07 +02:00
|
|
|
for (i = 0; i < win->w_tagstacklen; i++) {
|
|
|
|
if (win->w_tagstack[i].fmark.fnum == fnum) {
|
2014-01-31 14:39:15 +01:00
|
|
|
col_adjust(&(win->w_tagstack[i].fmark.mark));
|
2014-08-21 01:35:07 +02:00
|
|
|
}
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
|
|
|
/* cursor position for other windows with the same buffer */
|
2014-08-21 01:35:07 +02:00
|
|
|
if (win != curwin) {
|
2014-01-31 14:39:15 +01:00
|
|
|
col_adjust(&win->w_cursor);
|
2014-08-21 01:35:07 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-19 14:22:05 +02:00
|
|
|
// When deleting lines, this may create duplicate marks in the
|
|
|
|
// jumplist. They will be removed here for the specified window.
|
2019-09-03 19:18:24 +02:00
|
|
|
// When "checktail" is true, removes tail jump if it matches current position.
|
|
|
|
void cleanup_jumplist(win_T *wp, bool checktail)
|
2014-03-16 08:20:00 +01:00
|
|
|
{
|
2014-01-31 14:39:15 +01:00
|
|
|
int i;
|
|
|
|
|
2019-09-03 19:18:24 +02:00
|
|
|
// Load all the files from the jump list. This is
|
|
|
|
// needed to properly clean up duplicate entries, but will take some
|
|
|
|
// time.
|
|
|
|
for (i = 0; i < wp->w_jumplistlen; i++) {
|
|
|
|
if ((wp->w_jumplist[i].fmark.fnum == 0)
|
|
|
|
&& (wp->w_jumplist[i].fmark.mark.lnum != 0)) {
|
|
|
|
fname2fnum(&wp->w_jumplist[i]);
|
2019-05-19 14:34:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-19 14:57:10 +02:00
|
|
|
int to = 0;
|
|
|
|
for (int from = 0; from < wp->w_jumplistlen; from++) {
|
|
|
|
if (wp->w_jumplistidx == from) {
|
2019-05-19 14:22:05 +02:00
|
|
|
wp->w_jumplistidx = to;
|
2019-05-19 14:57:10 +02:00
|
|
|
}
|
|
|
|
for (i = from + 1; i < wp->w_jumplistlen; i++) {
|
2019-05-19 14:22:05 +02:00
|
|
|
if (wp->w_jumplist[i].fmark.fnum
|
|
|
|
== wp->w_jumplist[from].fmark.fnum
|
|
|
|
&& wp->w_jumplist[from].fmark.fnum != 0
|
|
|
|
&& wp->w_jumplist[i].fmark.mark.lnum
|
2019-05-19 14:57:10 +02:00
|
|
|
== wp->w_jumplist[from].fmark.mark.lnum) {
|
2014-01-31 14:39:15 +01:00
|
|
|
break;
|
2019-05-19 14:57:10 +02:00
|
|
|
}
|
|
|
|
}
|
2019-12-10 10:24:20 +01:00
|
|
|
|
jumplist: browser-style (or 'tagstack') navigation #11530
Traditionally, when navigating to a specific location from the middle of
the jumplist results in shifting the current location to the bottom of
the list and adding the new location after it. This behavior is not
desireable to all users--see, for example
https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior.
Here, another jumplist behavior is introduced. When jumpoptions (a new
option set added here) includes stack, the jumplist behaves like the
tagstack or like history in a web browser. That is, when navigating to
a location from the middle of the jumplist
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
to a new location the locations after the current location in the jump
list are discarded
2 first
1 second
0 third
<-- current location
The result is that when moving forward from that location, the new
location will be appended to the jumplist:
3 first
2 second
1 third
0 new
If the new location is the same
new == second
as some previous (but not immediately prior) entry in the jumplist,
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
both occurrences preserved
3 first
2 second
1 third
0 second (new)
when moving forward from that location.
It would be desireable to go farther and, when the new location is the
same as the location that is currently next in the jumplist,
new == fourth
make the result of navigating to the new location by jumping (e.g. 50gg)
be the same as moving forward in the jumplist
2 first
1 second
0 third
1 new <-- current location
2 fifth
and simply increment the jumplist index. That change is NOT part of
this patch because it would require passing the new cursor location to
the function (setpcmark) from all of its callees. That in turn would
require those callees to know *before* calling what the new cursor
location is, which do they do not currently.
2019-12-10 09:56:56 +01:00
|
|
|
bool mustfree;
|
2019-12-10 10:24:20 +01:00
|
|
|
if (i >= wp->w_jumplistlen) { // not duplicate
|
jumplist: browser-style (or 'tagstack') navigation #11530
Traditionally, when navigating to a specific location from the middle of
the jumplist results in shifting the current location to the bottom of
the list and adding the new location after it. This behavior is not
desireable to all users--see, for example
https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior.
Here, another jumplist behavior is introduced. When jumpoptions (a new
option set added here) includes stack, the jumplist behaves like the
tagstack or like history in a web browser. That is, when navigating to
a location from the middle of the jumplist
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
to a new location the locations after the current location in the jump
list are discarded
2 first
1 second
0 third
<-- current location
The result is that when moving forward from that location, the new
location will be appended to the jumplist:
3 first
2 second
1 third
0 new
If the new location is the same
new == second
as some previous (but not immediately prior) entry in the jumplist,
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
both occurrences preserved
3 first
2 second
1 third
0 second (new)
when moving forward from that location.
It would be desireable to go farther and, when the new location is the
same as the location that is currently next in the jumplist,
new == fourth
make the result of navigating to the new location by jumping (e.g. 50gg)
be the same as moving forward in the jumplist
2 first
1 second
0 third
1 new <-- current location
2 fifth
and simply increment the jumplist index. That change is NOT part of
this patch because it would require passing the new cursor location to
the function (setpcmark) from all of its callees. That in turn would
require those callees to know *before* calling what the new cursor
location is, which do they do not currently.
2019-12-10 09:56:56 +01:00
|
|
|
mustfree = false;
|
2019-12-10 10:24:20 +01:00
|
|
|
} else if (i > from + 1) { // non-adjacent duplicate
|
|
|
|
// jumpoptions=stack: remove duplicates only when adjacent.
|
jumplist: browser-style (or 'tagstack') navigation #11530
Traditionally, when navigating to a specific location from the middle of
the jumplist results in shifting the current location to the bottom of
the list and adding the new location after it. This behavior is not
desireable to all users--see, for example
https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior.
Here, another jumplist behavior is introduced. When jumpoptions (a new
option set added here) includes stack, the jumplist behaves like the
tagstack or like history in a web browser. That is, when navigating to
a location from the middle of the jumplist
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
to a new location the locations after the current location in the jump
list are discarded
2 first
1 second
0 third
<-- current location
The result is that when moving forward from that location, the new
location will be appended to the jumplist:
3 first
2 second
1 third
0 new
If the new location is the same
new == second
as some previous (but not immediately prior) entry in the jumplist,
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
both occurrences preserved
3 first
2 second
1 third
0 second (new)
when moving forward from that location.
It would be desireable to go farther and, when the new location is the
same as the location that is currently next in the jumplist,
new == fourth
make the result of navigating to the new location by jumping (e.g. 50gg)
be the same as moving forward in the jumplist
2 first
1 second
0 third
1 new <-- current location
2 fifth
and simply increment the jumplist index. That change is NOT part of
this patch because it would require passing the new cursor location to
the function (setpcmark) from all of its callees. That in turn would
require those callees to know *before* calling what the new cursor
location is, which do they do not currently.
2019-12-10 09:56:56 +01:00
|
|
|
mustfree = !(jop_flags & JOP_STACK);
|
2019-12-10 10:24:20 +01:00
|
|
|
} else { // adjacent duplicate
|
jumplist: browser-style (or 'tagstack') navigation #11530
Traditionally, when navigating to a specific location from the middle of
the jumplist results in shifting the current location to the bottom of
the list and adding the new location after it. This behavior is not
desireable to all users--see, for example
https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior.
Here, another jumplist behavior is introduced. When jumpoptions (a new
option set added here) includes stack, the jumplist behaves like the
tagstack or like history in a web browser. That is, when navigating to
a location from the middle of the jumplist
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
to a new location the locations after the current location in the jump
list are discarded
2 first
1 second
0 third
<-- current location
The result is that when moving forward from that location, the new
location will be appended to the jumplist:
3 first
2 second
1 third
0 new
If the new location is the same
new == second
as some previous (but not immediately prior) entry in the jumplist,
2 first
1 second
0 third <-- current location
1 fourth
2 fifth
both occurrences preserved
3 first
2 second
1 third
0 second (new)
when moving forward from that location.
It would be desireable to go farther and, when the new location is the
same as the location that is currently next in the jumplist,
new == fourth
make the result of navigating to the new location by jumping (e.g. 50gg)
be the same as moving forward in the jumplist
2 first
1 second
0 third
1 new <-- current location
2 fifth
and simply increment the jumplist index. That change is NOT part of
this patch because it would require passing the new cursor location to
the function (setpcmark) from all of its callees. That in turn would
require those callees to know *before* calling what the new cursor
location is, which do they do not currently.
2019-12-10 09:56:56 +01:00
|
|
|
mustfree = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mustfree) {
|
|
|
|
xfree(wp->w_jumplist[from].fname);
|
|
|
|
} else {
|
2015-07-02 19:15:41 +02:00
|
|
|
if (to != from) {
|
2019-05-19 14:22:05 +02:00
|
|
|
// Not using wp->w_jumplist[to++] = wp->w_jumplist[from] because
|
2015-08-23 12:53:47 +02:00
|
|
|
// this way valgrind complains about overlapping source and destination
|
2015-07-02 19:15:41 +02:00
|
|
|
// in memcpy() call. (clang-3.6.0, debug build with -DEXITFREE).
|
2019-05-19 14:22:05 +02:00
|
|
|
wp->w_jumplist[to] = wp->w_jumplist[from];
|
2015-07-02 19:15:41 +02:00
|
|
|
}
|
|
|
|
to++;
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
2019-05-19 14:22:05 +02:00
|
|
|
if (wp->w_jumplistidx == wp->w_jumplistlen) {
|
|
|
|
wp->w_jumplistidx = to;
|
2019-04-02 00:50:28 +02:00
|
|
|
}
|
2019-05-19 14:22:05 +02:00
|
|
|
wp->w_jumplistlen = to;
|
2019-04-02 00:50:28 +02:00
|
|
|
|
|
|
|
// When pointer is below last jump, remove the jump if it matches the current
|
|
|
|
// line. This avoids useless/phantom jumps. #9805
|
2019-09-03 19:18:24 +02:00
|
|
|
if (checktail && wp->w_jumplistlen
|
|
|
|
&& wp->w_jumplistidx == wp->w_jumplistlen) {
|
2019-05-19 14:22:05 +02:00
|
|
|
const xfmark_T *fm_last = &wp->w_jumplist[wp->w_jumplistlen - 1];
|
2019-04-02 00:50:28 +02:00
|
|
|
if (fm_last->fmark.fnum == curbuf->b_fnum
|
2019-05-19 14:22:05 +02:00
|
|
|
&& fm_last->fmark.mark.lnum == wp->w_cursor.lnum) {
|
2019-04-02 00:50:28 +02:00
|
|
|
xfree(fm_last->fname);
|
2019-05-19 14:22:05 +02:00
|
|
|
wp->w_jumplistlen--;
|
|
|
|
wp->w_jumplistidx--;
|
2019-04-02 00:50:28 +02:00
|
|
|
}
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the jumplist from window "from" to window "to".
|
|
|
|
*/
|
2014-02-23 21:34:45 +01:00
|
|
|
void copy_jumplist(win_T *from, win_T *to)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < from->w_jumplistlen; ++i) {
|
|
|
|
to->w_jumplist[i] = from->w_jumplist[i];
|
|
|
|
if (from->w_jumplist[i].fname != NULL)
|
|
|
|
to->w_jumplist[i].fname = vim_strsave(from->w_jumplist[i].fname);
|
|
|
|
}
|
|
|
|
to->w_jumplistlen = from->w_jumplistlen;
|
|
|
|
to->w_jumplistidx = from->w_jumplistidx;
|
|
|
|
}
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// Iterate over jumplist items
|
|
|
|
///
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @warning No jumplist-editing functions must be run while iteration is in
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// progress.
|
|
|
|
///
|
|
|
|
/// @param[in] iter Iterator. Pass NULL to start iteration.
|
|
|
|
/// @param[in] win Window for which jump list is processed.
|
|
|
|
/// @param[out] fm Item definition.
|
|
|
|
///
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @return Pointer that needs to be passed to next `mark_jumplist_iter` call or
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// NULL if iteration is over.
|
|
|
|
const void *mark_jumplist_iter(const void *const iter, const win_T *const win,
|
|
|
|
xfmark_T *const fm)
|
2015-08-16 19:09:51 +02:00
|
|
|
FUNC_ATTR_NONNULL_ARG(2, 3) FUNC_ATTR_WARN_UNUSED_RESULT
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
if (iter == NULL && win->w_jumplistlen == 0) {
|
|
|
|
*fm = (xfmark_T) {{{0, 0, 0}, 0, 0, NULL}, NULL};
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
const xfmark_T *const iter_mark =
|
|
|
|
(iter == NULL
|
2015-08-08 14:00:52 +02:00
|
|
|
? &(win->w_jumplist[0])
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
: (const xfmark_T *const) iter);
|
|
|
|
*fm = *iter_mark;
|
2015-08-08 14:00:52 +02:00
|
|
|
if (iter_mark == &(win->w_jumplist[win->w_jumplistlen - 1])) {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
return NULL;
|
|
|
|
} else {
|
2015-08-08 14:00:52 +02:00
|
|
|
return iter_mark + 1;
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// Iterate over global marks
|
|
|
|
///
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @warning No mark-editing functions must be run while iteration is in
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// progress.
|
|
|
|
///
|
|
|
|
/// @param[in] iter Iterator. Pass NULL to start iteration.
|
|
|
|
/// @param[out] name Mark name.
|
|
|
|
/// @param[out] fm Mark definition.
|
|
|
|
///
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @return Pointer that needs to be passed to next `mark_global_iter` call or
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// NULL if iteration is over.
|
|
|
|
const void *mark_global_iter(const void *const iter, char *const name,
|
|
|
|
xfmark_T *const fm)
|
2015-08-16 19:09:51 +02:00
|
|
|
FUNC_ATTR_NONNULL_ARG(2, 3) FUNC_ATTR_WARN_UNUSED_RESULT
|
2014-03-16 08:20:00 +01:00
|
|
|
{
|
2015-08-16 19:09:51 +02:00
|
|
|
*name = NUL;
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
const xfmark_T *iter_mark = (iter == NULL
|
|
|
|
? &(namedfm[0])
|
|
|
|
: (const xfmark_T *const) iter);
|
2015-08-13 22:31:14 +02:00
|
|
|
while ((size_t) (iter_mark - &(namedfm[0])) < ARRAY_SIZE(namedfm)
|
|
|
|
&& !iter_mark->fmark.mark.lnum) {
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
iter_mark++;
|
|
|
|
}
|
2015-08-13 22:31:14 +02:00
|
|
|
if ((size_t) (iter_mark - &(namedfm[0])) == ARRAY_SIZE(namedfm)
|
|
|
|
|| !iter_mark->fmark.mark.lnum) {
|
|
|
|
return NULL;
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
}
|
|
|
|
size_t iter_off = (size_t) (iter_mark - &(namedfm[0]));
|
|
|
|
*name = (char) (iter_off < NMARKS
|
|
|
|
? 'A' + (char) iter_off
|
|
|
|
: '0' + (char) (iter_off - NMARKS));
|
|
|
|
*fm = *iter_mark;
|
|
|
|
while ((size_t) (++iter_mark - &(namedfm[0])) < ARRAY_SIZE(namedfm)) {
|
|
|
|
if (iter_mark->fmark.mark.lnum) {
|
|
|
|
return (const void *) iter_mark;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// Get next mark and its name
|
|
|
|
///
|
|
|
|
/// @param[in] buf Buffer for which next mark is taken.
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @param[in,out] mark_name Pointer to the current mark name. Next mark name
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// will be saved at this address as well.
|
|
|
|
///
|
2015-08-23 12:53:47 +02:00
|
|
|
/// Current mark name must either be NUL, '"', '^',
|
|
|
|
/// '.' or 'a' .. 'z'. If it is neither of these
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// behaviour is undefined.
|
|
|
|
///
|
|
|
|
/// @return Pointer to the next mark or NULL.
|
|
|
|
static inline const fmark_T *next_buffer_mark(const buf_T *const buf,
|
|
|
|
char *const mark_name)
|
2015-08-16 19:09:51 +02:00
|
|
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
switch (*mark_name) {
|
|
|
|
case NUL: {
|
|
|
|
*mark_name = '"';
|
|
|
|
return &(buf->b_last_cursor);
|
|
|
|
}
|
|
|
|
case '"': {
|
|
|
|
*mark_name = '^';
|
|
|
|
return &(buf->b_last_insert);
|
|
|
|
}
|
|
|
|
case '^': {
|
|
|
|
*mark_name = '.';
|
|
|
|
return &(buf->b_last_change);
|
2014-12-31 20:08:18 +01:00
|
|
|
}
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
case '.': {
|
|
|
|
*mark_name = 'a';
|
|
|
|
return &(buf->b_namedm[0]);
|
|
|
|
}
|
|
|
|
case 'z': {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
(*mark_name)++;
|
|
|
|
return &(buf->b_namedm[*mark_name - 'a']);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// Iterate over buffer marks
|
|
|
|
///
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @warning No mark-editing functions must be run while iteration is in
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// progress.
|
|
|
|
///
|
|
|
|
/// @param[in] iter Iterator. Pass NULL to start iteration.
|
|
|
|
/// @param[in] buf Buffer.
|
|
|
|
/// @param[out] name Mark name.
|
|
|
|
/// @param[out] fm Mark definition.
|
|
|
|
///
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @return Pointer that needs to be passed to next `mark_buffer_iter` call or
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// NULL if iteration is over.
|
|
|
|
const void *mark_buffer_iter(const void *const iter, const buf_T *const buf,
|
|
|
|
char *const name, fmark_T *const fm)
|
2015-08-16 19:09:51 +02:00
|
|
|
FUNC_ATTR_NONNULL_ARG(2, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
2015-08-16 19:09:51 +02:00
|
|
|
*name = NUL;
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
char mark_name = (char) (iter == NULL
|
|
|
|
? NUL
|
|
|
|
: (iter == &(buf->b_last_cursor)
|
|
|
|
? '"'
|
|
|
|
: (iter == &(buf->b_last_insert)
|
|
|
|
? '^'
|
|
|
|
: (iter == &(buf->b_last_change)
|
|
|
|
? '.'
|
|
|
|
: 'a' + (char) ((const fmark_T *)iter
|
|
|
|
- &(buf->b_namedm[0]))))));
|
|
|
|
const fmark_T *iter_mark = next_buffer_mark(buf, &mark_name);
|
|
|
|
while (iter_mark != NULL && iter_mark->mark.lnum == 0) {
|
|
|
|
iter_mark = next_buffer_mark(buf, &mark_name);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
if (iter_mark == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
size_t iter_off = (size_t) (iter_mark - &(buf->b_namedm[0]));
|
|
|
|
if (mark_name) {
|
|
|
|
*name = mark_name;
|
|
|
|
} else {
|
|
|
|
*name = (char) ('a' + (char) iter_off);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
*fm = *iter_mark;
|
|
|
|
return (const void *) iter_mark;
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// Set global mark
|
|
|
|
///
|
|
|
|
/// @param[in] name Mark name.
|
|
|
|
/// @param[in] fm Mark to be set.
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @param[in] update If true then only set global mark if it was created
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// later then existing one.
|
2015-08-04 07:14:08 +02:00
|
|
|
///
|
|
|
|
/// @return true on success, false on failure.
|
|
|
|
bool mark_set_global(const char name, const xfmark_T fm, const bool update)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
2015-08-13 23:02:27 +02:00
|
|
|
const int idx = mark_global_index(name);
|
|
|
|
if (idx == -1) {
|
2015-08-04 07:14:08 +02:00
|
|
|
return false;
|
2014-08-11 05:56:58 +02:00
|
|
|
}
|
2015-08-13 23:02:27 +02:00
|
|
|
xfmark_T *const fm_tgt = &(namedfm[idx]);
|
2015-07-26 19:46:40 +02:00
|
|
|
if (update && fm.fmark.timestamp <= fm_tgt->fmark.timestamp) {
|
2015-08-04 07:14:08 +02:00
|
|
|
return false;
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
if (fm_tgt->fmark.mark.lnum != 0) {
|
|
|
|
free_xfmark(*fm_tgt);
|
|
|
|
}
|
|
|
|
*fm_tgt = fm;
|
2015-08-04 07:14:08 +02:00
|
|
|
return true;
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// Set local mark
|
|
|
|
///
|
|
|
|
/// @param[in] name Mark name.
|
|
|
|
/// @param[in] buf Pointer to the buffer to set mark in.
|
|
|
|
/// @param[in] fm Mark to be set.
|
2015-08-23 12:53:47 +02:00
|
|
|
/// @param[in] update If true then only set global mark if it was created
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
/// later then existing one.
|
2015-08-04 07:14:08 +02:00
|
|
|
///
|
|
|
|
/// @return true on success, false on failure.
|
|
|
|
bool mark_set_local(const char name, buf_T *const buf,
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
const fmark_T fm, const bool update)
|
|
|
|
FUNC_ATTR_NONNULL_ALL
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
fmark_T *fm_tgt = NULL;
|
|
|
|
if (ASCII_ISLOWER(name)) {
|
|
|
|
fm_tgt = &(buf->b_namedm[name - 'a']);
|
|
|
|
} else if (name == '"') {
|
|
|
|
fm_tgt = &(buf->b_last_cursor);
|
|
|
|
} else if (name == '^') {
|
|
|
|
fm_tgt = &(buf->b_last_insert);
|
|
|
|
} else if (name == '.') {
|
|
|
|
fm_tgt = &(buf->b_last_change);
|
|
|
|
} else {
|
2015-08-04 07:14:08 +02:00
|
|
|
return false;
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
}
|
2015-07-26 19:46:40 +02:00
|
|
|
if (update && fm.timestamp <= fm_tgt->timestamp) {
|
2015-08-04 07:14:08 +02:00
|
|
|
return false;
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
}
|
|
|
|
if (fm_tgt->mark.lnum != 0) {
|
|
|
|
free_fmark(*fm_tgt);
|
|
|
|
}
|
|
|
|
*fm_tgt = fm;
|
2015-08-04 07:14:08 +02:00
|
|
|
return true;
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
* Free items in the jumplist of window "wp".
|
2014-01-31 14:39:15 +01:00
|
|
|
*/
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
void free_jumplist(win_T *wp)
|
2014-01-31 14:39:15 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
for (i = 0; i < wp->w_jumplistlen; ++i) {
|
|
|
|
free_xfmark(wp->w_jumplist[i]);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
2015-08-16 17:54:41 +02:00
|
|
|
wp->w_jumplistlen = 0;
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
void set_last_cursor(win_T *win)
|
|
|
|
{
|
|
|
|
if (win->w_buffer != NULL) {
|
|
|
|
RESET_FMARK(&win->w_buffer->b_last_cursor, win->w_cursor, 0);
|
|
|
|
}
|
|
|
|
}
|
2014-01-31 14:39:15 +01:00
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
#if defined(EXITFREE)
|
|
|
|
void free_all_marks(void)
|
|
|
|
{
|
|
|
|
int i;
|
2014-01-31 14:39:15 +01:00
|
|
|
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
for (i = 0; i < NGLOBALMARKS; i++) {
|
|
|
|
if (namedfm[i].fmark.mark.lnum != 0) {
|
|
|
|
free_xfmark(namedfm[i]);
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
|
|
|
}
|
2015-08-16 17:54:41 +02:00
|
|
|
memset(&namedfm[0], 0, sizeof(namedfm));
|
2014-01-31 14:39:15 +01:00
|
|
|
}
|
viminfo: First version of ShaDa file dumping
What works:
1. ShaDa file dumping: header, registers, jump list, history, search patterns,
substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.
Most was not tested.
TODO:
1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
reference).
2015-04-25 17:47:31 +02:00
|
|
|
#endif
|
2016-07-26 22:16:23 +02:00
|
|
|
|
|
|
|
/// Adjust position to point to the first byte of a multi-byte character
|
|
|
|
///
|
|
|
|
/// If it points to a tail byte it is move backwards to the head byte.
|
|
|
|
///
|
|
|
|
/// @param[in] buf Buffer to adjust position in.
|
|
|
|
/// @param[out] lp Position to adjust.
|
|
|
|
void mark_mb_adjustpos(buf_T *buf, pos_T *lp)
|
|
|
|
FUNC_ATTR_NONNULL_ALL
|
|
|
|
{
|
|
|
|
if (lp->col > 0 || lp->coladd > 1) {
|
|
|
|
const char_u *const p = ml_get_buf(buf, lp->lnum, false);
|
2018-08-09 21:14:09 +02:00
|
|
|
if (*p == NUL || (int)STRLEN(p) < lp->col) {
|
|
|
|
lp->col = 0;
|
|
|
|
} else {
|
2018-08-15 21:02:33 +02:00
|
|
|
lp->col -= utf_head_off(p, p + lp->col);
|
2018-08-09 21:14:09 +02:00
|
|
|
}
|
2016-07-26 22:16:23 +02:00
|
|
|
// Reset "coladd" when the cursor would be on the right half of a
|
|
|
|
// double-wide character.
|
|
|
|
if (lp->coladd == 1
|
|
|
|
&& p[lp->col] != TAB
|
2018-06-29 21:31:20 +02:00
|
|
|
&& vim_isprintc(utf_ptr2char(p + lp->col))
|
2016-07-26 22:16:23 +02:00
|
|
|
&& ptr2cells(p + lp->col) > 1) {
|
|
|
|
lp->coladd = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|