📄 mark.c
字号:
: curwin->w_jumplistidx - i,
curwin->w_jumplist[i].mark.lnum,
name);
msg_outtrans(IObuff);
vim_free(name);
}
out_flush();
}
if (curwin->w_jumplistidx == curwin->w_jumplistlen)
MSG_PUTS("\n>");
}
/*
* adjust marks between line1 and line2 (inclusive) to move 'amount' lines
* If 'amount' is MAXLNUM the mark is made invalid.
* If 'amount_after' is non-zero adjust marks after line 2.
*/
#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; \
}
void
mark_adjust(line1, line2, amount, amount_after)
linenr_t line1;
linenr_t line2;
long amount;
long amount_after;
{
int i;
int fnum = curbuf->b_fnum;
linenr_t *lp;
WIN *win;
if (line2 < line1 && amount_after == 0L) /* nothing to do */
return;
/* named marks, lower case and upper case */
for (i = 0; i < NMARKS; i++)
{
one_adjust(&(curbuf->b_namedm[i].lnum));
if (namedfm[i].fnum == fnum)
one_adjust(&(namedfm[i].mark.lnum));
}
for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
{
if (namedfm[i].fnum == fnum)
one_adjust(&(namedfm[i].mark.lnum));
}
/* previous context mark */
one_adjust(&(curwin->w_pcmark.lnum));
/* previous pcmark */
one_adjust(&(curwin->w_prev_pcmark.lnum));
/* Visual area */
one_adjust_nodel(&(curbuf->b_visual_start.lnum));
one_adjust_nodel(&(curbuf->b_visual_end.lnum));
/* marks in the tag stack */
for (win = firstwin; win != NULL; win = win->w_next)
if (win->w_buffer == curbuf)
for (i = 0; i < win->w_tagstacklen; i++)
if (win->w_tagstack[i].fmark.fnum == fnum)
one_adjust_nodel(&(win->w_tagstack[i].fmark.mark.lnum));
#ifdef QUICKFIX
/* quickfix marks */
qf_mark_adjust(line1, line2, amount, amount_after);
#endif
/* jumplist marks */
for (win = firstwin; win != NULL; win = win->w_next)
{
/*
* When deleting lines, this may create duplicate marks in the
* jumplist. They will be removed later.
*/
for (i = 0; i < win->w_jumplistlen; ++i)
if (win->w_jumplist[i].fnum == fnum)
one_adjust_nodel(&(win->w_jumplist[i].mark.lnum));
/*
* also adjust the line at the top of the window and the cursor
* position for windows with the same buffer.
*/
if (win != curwin && win->w_buffer == curbuf)
{
if (win->w_topline >= line1 && win->w_topline <= line2)
{
if (amount == MAXLNUM) /* topline is deleted */
{
if (line1 <= 1)
win->w_topline = 1;
else
win->w_topline = line1 - 1;
}
else /* keep topline on the same line */
win->w_topline += amount;
}
else if (amount_after && win->w_topline > line2)
win->w_topline += amount_after;
if (win->w_cursor.lnum >= line1 && win->w_cursor.lnum <= line2)
{
if (amount == MAXLNUM) /* line with cursor is deleted */
{
if (line1 <= 1)
win->w_cursor.lnum = 1;
else
win->w_cursor.lnum = line1 - 1;
win->w_cursor.col = 0;
}
else /* keep cursor on the same line */
win->w_cursor.lnum += amount;
}
else if (amount_after && win->w_cursor.lnum > line2)
win->w_cursor.lnum += amount_after;
}
}
}
/*
* When deleting lines, this may create duplicate marks in the
* jumplist. They will be removed here for the current window.
*/
static void
cleanup_jumplist()
{
int i;
int from, to;
to = 0;
for (from = 0; from < curwin->w_jumplistlen; ++from)
{
if (curwin->w_jumplistidx == from)
curwin->w_jumplistidx = to;
for (i = from + 1; i < curwin->w_jumplistlen; ++i)
if (curwin->w_jumplist[i].fnum == curwin->w_jumplist[from].fnum &&
curwin->w_jumplist[i].mark.lnum ==
curwin->w_jumplist[from].mark.lnum)
break;
if (i >= curwin->w_jumplistlen) /* no duplicate */
curwin->w_jumplist[to++] = curwin->w_jumplist[from];
}
if (curwin->w_jumplistidx == curwin->w_jumplistlen)
curwin->w_jumplistidx = to;
curwin->w_jumplistlen = to;
}
void
set_last_cursor(win)
WIN *win;
{
win->w_buffer->b_last_cursor = win->w_cursor;
}
#ifdef VIMINFO
int
read_viminfo_filemark(line, fp, force)
char_u *line;
FILE *fp;
int force;
{
int idx;
char_u *str;
/* We only get here (hopefully) if line[0] == '\'' */
str = line + 1;
if (*str > 127 || (!isdigit(*str) && !isupper(*str)))
{
if (viminfo_error("Illegal file mark name", line))
return TRUE; /* Too many errors, pretend end-of-file */
}
else
{
if (isdigit(*str))
idx = *str - '0' + NMARKS;
else
idx = *str - 'A';
if (namedfm[idx].mark.lnum == 0 || force)
{
str = skipwhite(str + 1);
namedfm[idx].mark.lnum = getdigits(&str);
str = skipwhite(str);
namedfm[idx].mark.col = getdigits(&str);
str = skipwhite(str);
viminfo_readstring(line);
namedfm_names[idx] = vim_strsave(str);
}
}
return vim_fgets(line, LSIZE, fp);
}
void
write_viminfo_filemarks(fp)
FILE *fp;
{
int i;
char_u *name;
if (get_viminfo_parameter('\'') == 0)
return;
fprintf(fp, "\n# File marks:\n");
/*
* Find a mark that is the same file and position as the cursor.
* That one, or else the last one is deleted.
* Move '0 to '1, '1 to '2, etc. until the matching one or '9
* Set '0 mark to current cursor position.
*/
if (curbuf->b_ffname != NULL && !removable(curbuf->b_ffname))
{
name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE);
for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i)
if (namedfm[i].mark.lnum == curwin->w_cursor.lnum
&& (namedfm_names[i] == NULL
? namedfm[i].fnum == curbuf->b_fnum
: (name != NULL
&& STRCMP(name, namedfm_names[i]) == 0)))
break;
vim_free(name);
vim_free(namedfm_names[i]);
for ( ; i > NMARKS; --i)
{
namedfm[i] = namedfm[i - 1];
namedfm_names[i] = namedfm_names[i - 1];
}
namedfm[NMARKS].mark = curwin->w_cursor;
namedfm[NMARKS].fnum = curbuf->b_fnum;
namedfm_names[NMARKS] = NULL;
}
for (i = 0; i < NMARKS + EXTRA_MARKS; i++)
{
if (namedfm[i].mark.lnum == 0) /* not set */
continue;
if (namedfm[i].fnum) /* there is a buffer */
name = buflist_nr2name(namedfm[i].fnum, TRUE, FALSE);
else
name = namedfm_names[i]; /* use name from .viminfo */
if (name == NULL)
continue;
fprintf(fp, "'%c %ld %ld %s\n",
i < NMARKS ? i + 'A' : i - NMARKS + '0',
(long)namedfm[i].mark.lnum,
(long)namedfm[i].mark.col,
name);
if (namedfm[i].fnum)
vim_free(name);
}
}
/*
* Return TRUE if "name" is on removable media (depending on 'viminfo').
*/
int
removable(name)
char_u *name;
{
char_u *p;
char_u part[51];
int retval = FALSE;
name = home_replace_save(NULL, name);
if (name != NULL)
{
for (p = p_viminfo; *p; )
{
copy_option_part(&p, part, 51, ", ");
if (part[0] == 'r'
&& STRNICMP(part + 1, name, STRLEN(part + 1)) == 0)
{
retval = TRUE;
break;
}
}
vim_free(name);
}
return retval;
}
/*
* Write all the named marks for all buffers.
* Return the number of buffers for which marks have been written.
*/
int
write_viminfo_marks(fp_out)
FILE *fp_out;
{
int count;
BUF *buf;
WIN *win;
int is_mark_set;
int i;
/*
* Set b_last_cursor for the all buffers that have a window.
*/
for (win = firstwin; win != NULL; win = win->w_next)
set_last_cursor(win);
fprintf(fp_out, "\n# History of marks within files (newest to oldest):\n");
count = 0;
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
{
/*
* Only write something if buffer has been loaded and at least one
* mark is set.
*/
if (buf->b_marks_read)
{
if (buf->b_last_cursor.lnum != 0)
is_mark_set = TRUE;
else
{
is_mark_set = FALSE;
for (i = 0; i < NMARKS; i++)
if (buf->b_namedm[i].lnum != 0)
{
is_mark_set = TRUE;
break;
}
}
if (is_mark_set && buf->b_ffname != NULL &&
buf->b_ffname[0] != NUL && !removable(buf->b_ffname))
{
home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE);
fprintf(fp_out, "\n> %s\n", (char *)IObuff);
if (buf->b_last_cursor.lnum != 0)
fprintf(fp_out, "\t\"\t%ld\t%d\n",
buf->b_last_cursor.lnum, buf->b_last_cursor.col);
for (i = 0; i < NMARKS; i++)
if (buf->b_namedm[i].lnum != 0)
fprintf(fp_out, "\t%c\t%ld\t%d\n", 'a' + i,
buf->b_namedm[i].lnum, buf->b_namedm[i].col);
count++;
}
}
}
return count;
}
/*
* Handle marks in the viminfo file:
* fp_out == NULL read marks for current buffer only
* fp_out != NULL copy marks for buffers not in buffer list
*/
void
copy_viminfo_marks(line, fp_in, fp_out, count, eof)
char_u *line;
FILE *fp_in;
FILE *fp_out;
int count;
int eof;
{
BUF *buf;
int num_marked_files;
char_u save_char;
int load_marks;
int copy_marks_out;
char_u *str;
int i;
char_u *p;
char_u *name_buf;
long lnum;
int col;
if ((name_buf = alloc(LSIZE)) == NULL)
return;
num_marked_files = get_viminfo_parameter('\'');
while (!eof && (count < num_marked_files || fp_out == NULL))
{
if (line[0] != '>')
{
if (line[0] != '\n' && line[0] != '\r' && line[0] != '#')
{
if (viminfo_error("Missing '>'", line))
break; /* too many errors, return now */
}
eof = vim_fgets(line, LSIZE, fp_in);
continue; /* Skip this dud line */
}
/*
* Find file name, set str to start.
* Ignore leading and trailing white space.
*/
str = skipwhite(line + 1);
p = str + STRLEN(str);
while (p != str && (*p == NUL || vim_isspace(*p)))
p--;
if (*p)
p++;
save_char = *p;
*p = NUL;
/*
* If fp_out == NULL, load marks for current buffer.
* If fp_out != NULL, copy marks for buffers not in buflist.
*/
load_marks = copy_marks_out = FALSE;
if (fp_out == NULL)
{
if (curbuf->b_ffname != NULL)
{
home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
if (fnamecmp(str, name_buf) == 0)
load_marks = TRUE;
}
}
else /* fp_out != NULL */
{
/* This is slow if there are many buffers!! */
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
if (buf->b_ffname != NULL)
{
home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE);
if (fnamecmp(str, name_buf) == 0)
break;
}
/*
* copy marks if the buffer has not been loaded
*/
if (buf == NULL || !buf->b_marks_read)
{
copy_marks_out = TRUE;
*p = save_char;
fputs("\n", fp_out);
fputs((char *)line, fp_out);
count++;
}
}
while (!(eof = vim_fgets(line, LSIZE, fp_in)) && line[0] == TAB)
{
if (load_marks)
{
if (line[1] != NUL)
sscanf((char *)line + 2, "%ld %d", &lnum, &col);
if (line[1] == '"')
{
curbuf->b_last_cursor.lnum = lnum;
curbuf->b_last_cursor.col = col;
}
else if ((i = line[1] - 'a') >= 0 && i < NMARKS)
{
curbuf->b_namedm[i].lnum = lnum;
curbuf->b_namedm[i].col = col;
}
}
else if (copy_marks_out)
fputs((char *)line, fp_out);
}
if (load_marks)
break;
}
vim_free(name_buf);
}
#endif /* VIMINFO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -