xref: /vim-8.2.3635/src/mark.c (revision e08aee60)
1edf3f97aSBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
2071d4279SBram Moolenaar  *
3071d4279SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
4071d4279SBram Moolenaar  *
5071d4279SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
6071d4279SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
7071d4279SBram Moolenaar  * See README.txt for an overview of the Vim source code.
8071d4279SBram Moolenaar  */
9071d4279SBram Moolenaar 
10071d4279SBram Moolenaar /*
11071d4279SBram Moolenaar  * mark.c: functions for setting marks and jumping to them
12071d4279SBram Moolenaar  */
13071d4279SBram Moolenaar 
14071d4279SBram Moolenaar #include "vim.h"
15071d4279SBram Moolenaar 
16071d4279SBram Moolenaar /*
17071d4279SBram Moolenaar  * This file contains routines to maintain and manipulate marks.
18071d4279SBram Moolenaar  */
19071d4279SBram Moolenaar 
20071d4279SBram Moolenaar /*
21071d4279SBram Moolenaar  * If a named file mark's lnum is non-zero, it is valid.
22071d4279SBram Moolenaar  * If a named file mark's fnum is non-zero, it is for an existing buffer,
23071d4279SBram Moolenaar  * otherwise it is from .viminfo and namedfm[n].fname is the file name.
24071d4279SBram Moolenaar  * There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing
25071d4279SBram Moolenaar  * viminfo).
26071d4279SBram Moolenaar  */
274ba37b58SBram Moolenaar static xfmark_T namedfm[NMARKS + EXTRA_MARKS];		// marks with file nr
28071d4279SBram Moolenaar 
295843f5f3SBram Moolenaar static void fname2fnum(xfmark_T *fm);
3092b8b2d3SBram Moolenaar static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf);
3192b8b2d3SBram Moolenaar static char_u *mark_line(pos_T *mp, int lead_len);
3292b8b2d3SBram Moolenaar static void show_one_mark(int, char_u *, pos_T *, char_u *, int current);
3388d298aeSBram Moolenaar static void mark_adjust_internal(linenr_T line1, linenr_T line2, long amount,
3488d298aeSBram Moolenaar     long amount_after, int adjust_folds);
35071d4279SBram Moolenaar 
36071d4279SBram Moolenaar /*
37bfb2d40bSBram Moolenaar  * Set named mark "c" at current cursor position.
38071d4279SBram Moolenaar  * Returns OK on success, FAIL if bad name given.
39071d4279SBram Moolenaar  */
40071d4279SBram Moolenaar     int
setmark(int c)4152ea13daSBram Moolenaar setmark(int c)
42071d4279SBram Moolenaar {
43bfb2d40bSBram Moolenaar     return setmark_pos(c, &curwin->w_cursor, curbuf->b_fnum);
44bfb2d40bSBram Moolenaar }
45bfb2d40bSBram Moolenaar 
46bfb2d40bSBram Moolenaar /*
47bfb2d40bSBram Moolenaar  * Set named mark "c" to position "pos".
48bfb2d40bSBram Moolenaar  * When "c" is upper case use file "fnum".
49bfb2d40bSBram Moolenaar  * Returns OK on success, FAIL if bad name given.
50bfb2d40bSBram Moolenaar  */
51bfb2d40bSBram Moolenaar     int
setmark_pos(int c,pos_T * pos,int fnum)5252ea13daSBram Moolenaar setmark_pos(int c, pos_T *pos, int fnum)
53bfb2d40bSBram Moolenaar {
54071d4279SBram Moolenaar     int		i;
55f13e00b2SBram Moolenaar     buf_T	*buf;
56071d4279SBram Moolenaar 
574ba37b58SBram Moolenaar     // Check for a special key (may cause islower() to crash).
58071d4279SBram Moolenaar     if (c < 0)
59071d4279SBram Moolenaar 	return FAIL;
60071d4279SBram Moolenaar 
61071d4279SBram Moolenaar     if (c == '\'' || c == '`')
62071d4279SBram Moolenaar     {
63bfb2d40bSBram Moolenaar 	if (pos == &curwin->w_cursor)
64bfb2d40bSBram Moolenaar 	{
65071d4279SBram Moolenaar 	    setpcmark();
664ba37b58SBram Moolenaar 	    // keep it even when the cursor doesn't move
67071d4279SBram Moolenaar 	    curwin->w_prev_pcmark = curwin->w_pcmark;
68bfb2d40bSBram Moolenaar 	}
69bfb2d40bSBram Moolenaar 	else
70bfb2d40bSBram Moolenaar 	    curwin->w_pcmark = *pos;
71071d4279SBram Moolenaar 	return OK;
72071d4279SBram Moolenaar     }
73071d4279SBram Moolenaar 
74f13e00b2SBram Moolenaar     buf = buflist_findnr(fnum);
75f13e00b2SBram Moolenaar     if (buf == NULL)
76f13e00b2SBram Moolenaar 	return FAIL;
77f13e00b2SBram Moolenaar 
7808250430SBram Moolenaar     if (c == '"')
7908250430SBram Moolenaar     {
80f13e00b2SBram Moolenaar 	buf->b_last_cursor = *pos;
8108250430SBram Moolenaar 	return OK;
8208250430SBram Moolenaar     }
8308250430SBram Moolenaar 
844ba37b58SBram Moolenaar     // Allow setting '[ and '] for an autocommand that simulates reading a
854ba37b58SBram Moolenaar     // file.
86071d4279SBram Moolenaar     if (c == '[')
87071d4279SBram Moolenaar     {
88f13e00b2SBram Moolenaar 	buf->b_op_start = *pos;
89071d4279SBram Moolenaar 	return OK;
90071d4279SBram Moolenaar     }
91071d4279SBram Moolenaar     if (c == ']')
92071d4279SBram Moolenaar     {
93f13e00b2SBram Moolenaar 	buf->b_op_end = *pos;
94071d4279SBram Moolenaar 	return OK;
95071d4279SBram Moolenaar     }
96071d4279SBram Moolenaar 
97bc88a275SBram Moolenaar     if (c == '<' || c == '>')
98bc88a275SBram Moolenaar     {
990306ac33SBram Moolenaar 	if (c == '<')
100f13e00b2SBram Moolenaar 	    buf->b_visual.vi_start = *pos;
101bc88a275SBram Moolenaar 	else
102f13e00b2SBram Moolenaar 	    buf->b_visual.vi_end = *pos;
103f13e00b2SBram Moolenaar 	if (buf->b_visual.vi_mode == NUL)
1044ba37b58SBram Moolenaar 	    // Visual_mode has not yet been set, use a sane default.
105f13e00b2SBram Moolenaar 	    buf->b_visual.vi_mode = 'v';
1060306ac33SBram Moolenaar 	return OK;
1070306ac33SBram Moolenaar     }
1080306ac33SBram Moolenaar 
1092d358997SBram Moolenaar     if (ASCII_ISLOWER(c))
110071d4279SBram Moolenaar     {
111071d4279SBram Moolenaar 	i = c - 'a';
112f13e00b2SBram Moolenaar 	buf->b_namedm[i] = *pos;
113071d4279SBram Moolenaar 	return OK;
114071d4279SBram Moolenaar     }
1152d358997SBram Moolenaar     if (ASCII_ISUPPER(c) || VIM_ISDIGIT(c))
116071d4279SBram Moolenaar     {
1172d358997SBram Moolenaar 	if (VIM_ISDIGIT(c))
1182d358997SBram Moolenaar 	    i = c - '0' + NMARKS;
1192d358997SBram Moolenaar 	else
120071d4279SBram Moolenaar 	    i = c - 'A';
121bfb2d40bSBram Moolenaar 	namedfm[i].fmark.mark = *pos;
122bfb2d40bSBram Moolenaar 	namedfm[i].fmark.fnum = fnum;
123d23a8236SBram Moolenaar 	VIM_CLEAR(namedfm[i].fname);
1242d358997SBram Moolenaar #ifdef FEAT_VIMINFO
1252d358997SBram Moolenaar 	namedfm[i].time_set = vim_time();
1262d358997SBram Moolenaar #endif
127071d4279SBram Moolenaar 	return OK;
128071d4279SBram Moolenaar     }
129071d4279SBram Moolenaar     return FAIL;
130071d4279SBram Moolenaar }
131071d4279SBram Moolenaar 
132071d4279SBram Moolenaar /*
133071d4279SBram Moolenaar  * Set the previous context mark to the current position and add it to the
134071d4279SBram Moolenaar  * jump list.
135071d4279SBram Moolenaar  */
136071d4279SBram Moolenaar     void
setpcmark(void)13752ea13daSBram Moolenaar setpcmark(void)
138071d4279SBram Moolenaar {
139071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
140071d4279SBram Moolenaar     int		i;
141071d4279SBram Moolenaar     xfmark_T	*fm;
142071d4279SBram Moolenaar #endif
143071d4279SBram Moolenaar 
1444ba37b58SBram Moolenaar     // for :global the mark is set only once
145e1004401SBram Moolenaar     if (global_busy || listcmd_busy || (cmdmod.cmod_flags & CMOD_KEEPJUMPS))
146071d4279SBram Moolenaar 	return;
147071d4279SBram Moolenaar 
148071d4279SBram Moolenaar     curwin->w_prev_pcmark = curwin->w_pcmark;
149071d4279SBram Moolenaar     curwin->w_pcmark = curwin->w_cursor;
150071d4279SBram Moolenaar 
151071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
1524ba37b58SBram Moolenaar     // If jumplist is full: remove oldest entry
153071d4279SBram Moolenaar     if (++curwin->w_jumplistlen > JUMPLISTSIZE)
154071d4279SBram Moolenaar     {
155071d4279SBram Moolenaar 	curwin->w_jumplistlen = JUMPLISTSIZE;
156071d4279SBram Moolenaar 	vim_free(curwin->w_jumplist[0].fname);
157071d4279SBram Moolenaar 	for (i = 1; i < JUMPLISTSIZE; ++i)
158071d4279SBram Moolenaar 	    curwin->w_jumplist[i - 1] = curwin->w_jumplist[i];
159071d4279SBram Moolenaar     }
160071d4279SBram Moolenaar     curwin->w_jumplistidx = curwin->w_jumplistlen;
161071d4279SBram Moolenaar     fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
162071d4279SBram Moolenaar 
163071d4279SBram Moolenaar     fm->fmark.mark = curwin->w_pcmark;
164071d4279SBram Moolenaar     fm->fmark.fnum = curbuf->b_fnum;
165071d4279SBram Moolenaar     fm->fname = NULL;
1662d358997SBram Moolenaar # ifdef FEAT_VIMINFO
1672d358997SBram Moolenaar     fm->time_set = vim_time();
1682d358997SBram Moolenaar # endif
169071d4279SBram Moolenaar #endif
170071d4279SBram Moolenaar }
171071d4279SBram Moolenaar 
172071d4279SBram Moolenaar /*
173071d4279SBram Moolenaar  * To change context, call setpcmark(), then move the current position to
174071d4279SBram Moolenaar  * where ever, then call checkpcmark().  This ensures that the previous
175071d4279SBram Moolenaar  * context will only be changed if the cursor moved to a different line.
176071d4279SBram Moolenaar  * If pcmark was deleted (with "dG") the previous mark is restored.
177071d4279SBram Moolenaar  */
178071d4279SBram Moolenaar     void
checkpcmark(void)17952ea13daSBram Moolenaar checkpcmark(void)
180071d4279SBram Moolenaar {
181071d4279SBram Moolenaar     if (curwin->w_prev_pcmark.lnum != 0
182b5aedf3eSBram Moolenaar 	    && (EQUAL_POS(curwin->w_pcmark, curwin->w_cursor)
183071d4279SBram Moolenaar 		|| curwin->w_pcmark.lnum == 0))
184071d4279SBram Moolenaar 	curwin->w_pcmark = curwin->w_prev_pcmark;
185*e08aee60SBram Moolenaar     curwin->w_prev_pcmark.lnum = 0;		// it has been checked
186071d4279SBram Moolenaar }
187071d4279SBram Moolenaar 
188071d4279SBram Moolenaar #if defined(FEAT_JUMPLIST) || defined(PROTO)
189071d4279SBram Moolenaar /*
190071d4279SBram Moolenaar  * move "count" positions in the jump list (count may be negative)
191071d4279SBram Moolenaar  */
192071d4279SBram Moolenaar     pos_T *
movemark(int count)19352ea13daSBram Moolenaar movemark(int count)
194071d4279SBram Moolenaar {
195071d4279SBram Moolenaar     pos_T	*pos;
196071d4279SBram Moolenaar     xfmark_T	*jmp;
197071d4279SBram Moolenaar 
19848679741SBram Moolenaar     cleanup_jumplist(curwin, TRUE);
199071d4279SBram Moolenaar 
2004ba37b58SBram Moolenaar     if (curwin->w_jumplistlen == 0)	    // nothing to jump to
201071d4279SBram Moolenaar 	return (pos_T *)NULL;
202071d4279SBram Moolenaar 
203071d4279SBram Moolenaar     for (;;)
204071d4279SBram Moolenaar     {
205071d4279SBram Moolenaar 	if (curwin->w_jumplistidx + count < 0
206071d4279SBram Moolenaar 		|| curwin->w_jumplistidx + count >= curwin->w_jumplistlen)
207071d4279SBram Moolenaar 	    return (pos_T *)NULL;
208071d4279SBram Moolenaar 
209071d4279SBram Moolenaar 	/*
210071d4279SBram Moolenaar 	 * if first CTRL-O or CTRL-I command after a jump, add cursor position
211f711faf0SBram Moolenaar 	 * to list.  Careful: If there are duplicates (CTRL-O immediately after
212071d4279SBram Moolenaar 	 * starting Vim on a file), another entry may have been removed.
213071d4279SBram Moolenaar 	 */
214071d4279SBram Moolenaar 	if (curwin->w_jumplistidx == curwin->w_jumplistlen)
215071d4279SBram Moolenaar 	{
216071d4279SBram Moolenaar 	    setpcmark();
2174ba37b58SBram Moolenaar 	    --curwin->w_jumplistidx;	// skip the new entry
218071d4279SBram Moolenaar 	    if (curwin->w_jumplistidx + count < 0)
219071d4279SBram Moolenaar 		return (pos_T *)NULL;
220071d4279SBram Moolenaar 	}
221071d4279SBram Moolenaar 
222071d4279SBram Moolenaar 	curwin->w_jumplistidx += count;
223071d4279SBram Moolenaar 
224071d4279SBram Moolenaar 	jmp = curwin->w_jumplist + curwin->w_jumplistidx;
225071d4279SBram Moolenaar 	if (jmp->fmark.fnum == 0)
226071d4279SBram Moolenaar 	    fname2fnum(jmp);
227071d4279SBram Moolenaar 	if (jmp->fmark.fnum != curbuf->b_fnum)
228071d4279SBram Moolenaar 	{
2294ba37b58SBram Moolenaar 	    // jump to other file
230071d4279SBram Moolenaar 	    if (buflist_findnr(jmp->fmark.fnum) == NULL)
2314ba37b58SBram Moolenaar 	    {					     // Skip this one ..
232071d4279SBram Moolenaar 		count += count < 0 ? -1 : 1;
233071d4279SBram Moolenaar 		continue;
234071d4279SBram Moolenaar 	    }
235071d4279SBram Moolenaar 	    if (buflist_getfile(jmp->fmark.fnum, jmp->fmark.mark.lnum,
236071d4279SBram Moolenaar 							    0, FALSE) == FAIL)
237071d4279SBram Moolenaar 		return (pos_T *)NULL;
2384ba37b58SBram Moolenaar 	    // Set lnum again, autocommands my have changed it
239071d4279SBram Moolenaar 	    curwin->w_cursor = jmp->fmark.mark;
240071d4279SBram Moolenaar 	    pos = (pos_T *)-1;
241071d4279SBram Moolenaar 	}
242071d4279SBram Moolenaar 	else
243071d4279SBram Moolenaar 	    pos = &(jmp->fmark.mark);
244071d4279SBram Moolenaar 	return pos;
245071d4279SBram Moolenaar     }
246071d4279SBram Moolenaar }
247071d4279SBram Moolenaar 
248071d4279SBram Moolenaar /*
249071d4279SBram Moolenaar  * Move "count" positions in the changelist (count may be negative).
250071d4279SBram Moolenaar  */
251071d4279SBram Moolenaar     pos_T *
movechangelist(int count)25252ea13daSBram Moolenaar movechangelist(int count)
253071d4279SBram Moolenaar {
254071d4279SBram Moolenaar     int		n;
255071d4279SBram Moolenaar 
2564ba37b58SBram Moolenaar     if (curbuf->b_changelistlen == 0)	    // nothing to jump to
257071d4279SBram Moolenaar 	return (pos_T *)NULL;
258071d4279SBram Moolenaar 
259071d4279SBram Moolenaar     n = curwin->w_changelistidx;
260071d4279SBram Moolenaar     if (n + count < 0)
261071d4279SBram Moolenaar     {
262071d4279SBram Moolenaar 	if (n == 0)
263071d4279SBram Moolenaar 	    return (pos_T *)NULL;
264071d4279SBram Moolenaar 	n = 0;
265071d4279SBram Moolenaar     }
266071d4279SBram Moolenaar     else if (n + count >= curbuf->b_changelistlen)
267071d4279SBram Moolenaar     {
268071d4279SBram Moolenaar 	if (n == curbuf->b_changelistlen - 1)
269071d4279SBram Moolenaar 	    return (pos_T *)NULL;
270071d4279SBram Moolenaar 	n = curbuf->b_changelistlen - 1;
271071d4279SBram Moolenaar     }
272071d4279SBram Moolenaar     else
273071d4279SBram Moolenaar 	n += count;
274071d4279SBram Moolenaar     curwin->w_changelistidx = n;
275071d4279SBram Moolenaar     return curbuf->b_changelist + n;
276071d4279SBram Moolenaar }
277071d4279SBram Moolenaar #endif
278071d4279SBram Moolenaar 
279071d4279SBram Moolenaar /*
2809d182dd0SBram Moolenaar  * Find mark "c" in buffer pointed to by "buf".
281bfb2d40bSBram Moolenaar  * If "changefile" is TRUE it's allowed to edit another file for '0, 'A, etc.
282bfb2d40bSBram Moolenaar  * If "fnum" is not NULL store the fnum there for '0, 'A etc., don't edit
283bfb2d40bSBram Moolenaar  * another file.
284071d4279SBram Moolenaar  * Returns:
285071d4279SBram Moolenaar  * - pointer to pos_T if found.  lnum is 0 when mark not set, -1 when mark is
286071d4279SBram Moolenaar  *   in another file which can't be gotten. (caller needs to check lnum!)
287071d4279SBram Moolenaar  * - NULL if there is no mark called 'c'.
288071d4279SBram Moolenaar  * - -1 if mark is in other file and jumped there (only if changefile is TRUE)
289071d4279SBram Moolenaar  */
290071d4279SBram Moolenaar     pos_T *
getmark_buf(buf_T * buf,int c,int changefile)29152ea13daSBram Moolenaar getmark_buf(buf_T *buf, int c, int changefile)
2929d182dd0SBram Moolenaar {
2939d182dd0SBram Moolenaar     return getmark_buf_fnum(buf, c, changefile, NULL);
2949d182dd0SBram Moolenaar }
2959d182dd0SBram Moolenaar 
2969d182dd0SBram Moolenaar     pos_T *
getmark(int c,int changefile)29752ea13daSBram Moolenaar getmark(int c, int changefile)
298bfb2d40bSBram Moolenaar {
2999d182dd0SBram Moolenaar     return getmark_buf_fnum(curbuf, c, changefile, NULL);
300bfb2d40bSBram Moolenaar }
301bfb2d40bSBram Moolenaar 
302bfb2d40bSBram Moolenaar     pos_T *
getmark_buf_fnum(buf_T * buf,int c,int changefile,int * fnum)30352ea13daSBram Moolenaar getmark_buf_fnum(
30452ea13daSBram Moolenaar     buf_T	*buf,
30552ea13daSBram Moolenaar     int		c,
30652ea13daSBram Moolenaar     int		changefile,
30752ea13daSBram Moolenaar     int		*fnum)
308071d4279SBram Moolenaar {
309071d4279SBram Moolenaar     pos_T		*posp;
310071d4279SBram Moolenaar     pos_T		*startp, *endp;
311071d4279SBram Moolenaar     static pos_T	pos_copy;
312071d4279SBram Moolenaar 
313071d4279SBram Moolenaar     posp = NULL;
314071d4279SBram Moolenaar 
3154ba37b58SBram Moolenaar     // Check for special key, can't be a mark name and might cause islower()
3164ba37b58SBram Moolenaar     // to crash.
317071d4279SBram Moolenaar     if (c < 0)
318071d4279SBram Moolenaar 	return posp;
319071d4279SBram Moolenaar #ifndef EBCDIC
3204ba37b58SBram Moolenaar     if (c > '~')			// check for islower()/isupper()
321071d4279SBram Moolenaar 	;
322071d4279SBram Moolenaar     else
323071d4279SBram Moolenaar #endif
3244ba37b58SBram Moolenaar 	if (c == '\'' || c == '`')	// previous context mark
325071d4279SBram Moolenaar     {
3264ba37b58SBram Moolenaar 	pos_copy = curwin->w_pcmark;	// need to make a copy because
3274ba37b58SBram Moolenaar 	posp = &pos_copy;		//   w_pcmark may be changed soon
328071d4279SBram Moolenaar     }
3294ba37b58SBram Moolenaar     else if (c == '"')			// to pos when leaving buffer
3309d182dd0SBram Moolenaar 	posp = &(buf->b_last_cursor);
3314ba37b58SBram Moolenaar     else if (c == '^')			// to where Insert mode stopped
3329d182dd0SBram Moolenaar 	posp = &(buf->b_last_insert);
3334ba37b58SBram Moolenaar     else if (c == '.')			// to where last change was made
3349d182dd0SBram Moolenaar 	posp = &(buf->b_last_change);
3354ba37b58SBram Moolenaar     else if (c == '[')			// to start of previous operator
3369d182dd0SBram Moolenaar 	posp = &(buf->b_op_start);
3374ba37b58SBram Moolenaar     else if (c == ']')			// to end of previous operator
3389d182dd0SBram Moolenaar 	posp = &(buf->b_op_end);
3394ba37b58SBram Moolenaar     else if (c == '{' || c == '}')	// to previous/next paragraph
340071d4279SBram Moolenaar     {
341071d4279SBram Moolenaar 	pos_T	pos;
342071d4279SBram Moolenaar 	oparg_T	oa;
343071d4279SBram Moolenaar 	int	slcb = listcmd_busy;
344071d4279SBram Moolenaar 
345071d4279SBram Moolenaar 	pos = curwin->w_cursor;
3464ba37b58SBram Moolenaar 	listcmd_busy = TRUE;	    // avoid that '' is changed
3478b96d64cSBram Moolenaar 	if (findpar(&oa.inclusive,
3488b96d64cSBram Moolenaar 			       c == '}' ? FORWARD : BACKWARD, 1L, NUL, FALSE))
349071d4279SBram Moolenaar 	{
350071d4279SBram Moolenaar 	    pos_copy = curwin->w_cursor;
351071d4279SBram Moolenaar 	    posp = &pos_copy;
352071d4279SBram Moolenaar 	}
353071d4279SBram Moolenaar 	curwin->w_cursor = pos;
354071d4279SBram Moolenaar 	listcmd_busy = slcb;
355071d4279SBram Moolenaar     }
3564ba37b58SBram Moolenaar     else if (c == '(' || c == ')')	// to previous/next sentence
357071d4279SBram Moolenaar     {
358071d4279SBram Moolenaar 	pos_T	pos;
359071d4279SBram Moolenaar 	int	slcb = listcmd_busy;
360071d4279SBram Moolenaar 
361071d4279SBram Moolenaar 	pos = curwin->w_cursor;
3624ba37b58SBram Moolenaar 	listcmd_busy = TRUE;	    // avoid that '' is changed
363071d4279SBram Moolenaar 	if (findsent(c == ')' ? FORWARD : BACKWARD, 1L))
364071d4279SBram Moolenaar 	{
365071d4279SBram Moolenaar 	    pos_copy = curwin->w_cursor;
366071d4279SBram Moolenaar 	    posp = &pos_copy;
367071d4279SBram Moolenaar 	}
368071d4279SBram Moolenaar 	curwin->w_cursor = pos;
369071d4279SBram Moolenaar 	listcmd_busy = slcb;
370071d4279SBram Moolenaar     }
3714ba37b58SBram Moolenaar     else if (c == '<' || c == '>')	// start/end of visual area
372071d4279SBram Moolenaar     {
3739d182dd0SBram Moolenaar 	startp = &buf->b_visual.vi_start;
3749d182dd0SBram Moolenaar 	endp = &buf->b_visual.vi_end;
375b5aedf3eSBram Moolenaar 	if (((c == '<') == LT_POS(*startp, *endp) || endp->lnum == 0)
376f13e00b2SBram Moolenaar 							  && startp->lnum != 0)
377071d4279SBram Moolenaar 	    posp = startp;
378071d4279SBram Moolenaar 	else
379071d4279SBram Moolenaar 	    posp = endp;
380071d4279SBram Moolenaar 	/*
381071d4279SBram Moolenaar 	 * For Visual line mode, set mark at begin or end of line
382071d4279SBram Moolenaar 	 */
3839d182dd0SBram Moolenaar 	if (buf->b_visual.vi_mode == 'V')
384071d4279SBram Moolenaar 	{
385071d4279SBram Moolenaar 	    pos_copy = *posp;
386071d4279SBram Moolenaar 	    posp = &pos_copy;
387071d4279SBram Moolenaar 	    if (c == '<')
388071d4279SBram Moolenaar 		pos_copy.col = 0;
389071d4279SBram Moolenaar 	    else
390071d4279SBram Moolenaar 		pos_copy.col = MAXCOL;
391071d4279SBram Moolenaar 	    pos_copy.coladd = 0;
392071d4279SBram Moolenaar 	}
393071d4279SBram Moolenaar     }
3944ba37b58SBram Moolenaar     else if (ASCII_ISLOWER(c))		// normal named mark
395071d4279SBram Moolenaar     {
3969d182dd0SBram Moolenaar 	posp = &(buf->b_namedm[c - 'a']);
397071d4279SBram Moolenaar     }
3984ba37b58SBram Moolenaar     else if (ASCII_ISUPPER(c) || VIM_ISDIGIT(c))	// named file mark
399071d4279SBram Moolenaar     {
400071d4279SBram Moolenaar 	if (VIM_ISDIGIT(c))
401071d4279SBram Moolenaar 	    c = c - '0' + NMARKS;
402071d4279SBram Moolenaar 	else
403071d4279SBram Moolenaar 	    c -= 'A';
404071d4279SBram Moolenaar 	posp = &(namedfm[c].fmark.mark);
405071d4279SBram Moolenaar 
406071d4279SBram Moolenaar 	if (namedfm[c].fmark.fnum == 0)
407071d4279SBram Moolenaar 	    fname2fnum(&namedfm[c]);
408bfb2d40bSBram Moolenaar 
409bfb2d40bSBram Moolenaar 	if (fnum != NULL)
410bfb2d40bSBram Moolenaar 	    *fnum = namedfm[c].fmark.fnum;
4119d182dd0SBram Moolenaar 	else if (namedfm[c].fmark.fnum != buf->b_fnum)
412071d4279SBram Moolenaar 	{
4134ba37b58SBram Moolenaar 	    // mark is in another file
414071d4279SBram Moolenaar 	    posp = &pos_copy;
415071d4279SBram Moolenaar 
416071d4279SBram Moolenaar 	    if (namedfm[c].fmark.mark.lnum != 0
417071d4279SBram Moolenaar 				       && changefile && namedfm[c].fmark.fnum)
418071d4279SBram Moolenaar 	    {
419071d4279SBram Moolenaar 		if (buflist_getfile(namedfm[c].fmark.fnum,
420071d4279SBram Moolenaar 				      (linenr_T)1, GETF_SETMARK, FALSE) == OK)
421071d4279SBram Moolenaar 		{
4224ba37b58SBram Moolenaar 		    // Set the lnum now, autocommands could have changed it
423071d4279SBram Moolenaar 		    curwin->w_cursor = namedfm[c].fmark.mark;
424071d4279SBram Moolenaar 		    return (pos_T *)-1;
425071d4279SBram Moolenaar 		}
4264ba37b58SBram Moolenaar 		pos_copy.lnum = -1;	// can't get file
427071d4279SBram Moolenaar 	    }
428071d4279SBram Moolenaar 	    else
4294ba37b58SBram Moolenaar 		pos_copy.lnum = 0;	// mark exists, but is not valid in
4304ba37b58SBram Moolenaar 					// current buffer
431071d4279SBram Moolenaar 	}
432071d4279SBram Moolenaar     }
433071d4279SBram Moolenaar 
434071d4279SBram Moolenaar     return posp;
435071d4279SBram Moolenaar }
436071d4279SBram Moolenaar 
437071d4279SBram Moolenaar /*
438071d4279SBram Moolenaar  * Search for the next named mark in the current file.
439071d4279SBram Moolenaar  *
440071d4279SBram Moolenaar  * Returns pointer to pos_T of the next mark or NULL if no mark is found.
441071d4279SBram Moolenaar  */
442071d4279SBram Moolenaar     pos_T *
getnextmark(pos_T * startpos,int dir,int begin_line)44352ea13daSBram Moolenaar getnextmark(
4444ba37b58SBram Moolenaar     pos_T	*startpos,	// where to start
4454ba37b58SBram Moolenaar     int		dir,	// direction for search
44652ea13daSBram Moolenaar     int		begin_line)
447071d4279SBram Moolenaar {
448071d4279SBram Moolenaar     int		i;
449071d4279SBram Moolenaar     pos_T	*result = NULL;
450071d4279SBram Moolenaar     pos_T	pos;
451071d4279SBram Moolenaar 
452071d4279SBram Moolenaar     pos = *startpos;
453071d4279SBram Moolenaar 
4544ba37b58SBram Moolenaar     // When searching backward and leaving the cursor on the first non-blank,
4554ba37b58SBram Moolenaar     // position must be in a previous line.
4564ba37b58SBram Moolenaar     // When searching forward and leaving the cursor on the first non-blank,
4574ba37b58SBram Moolenaar     // position must be in a next line.
458071d4279SBram Moolenaar     if (dir == BACKWARD && begin_line)
459071d4279SBram Moolenaar 	pos.col = 0;
460071d4279SBram Moolenaar     else if (dir == FORWARD && begin_line)
461071d4279SBram Moolenaar 	pos.col = MAXCOL;
462071d4279SBram Moolenaar 
463071d4279SBram Moolenaar     for (i = 0; i < NMARKS; i++)
464071d4279SBram Moolenaar     {
465071d4279SBram Moolenaar 	if (curbuf->b_namedm[i].lnum > 0)
466071d4279SBram Moolenaar 	{
467071d4279SBram Moolenaar 	    if (dir == FORWARD)
468071d4279SBram Moolenaar 	    {
469b5aedf3eSBram Moolenaar 		if ((result == NULL || LT_POS(curbuf->b_namedm[i], *result))
470b5aedf3eSBram Moolenaar 			&& LT_POS(pos, curbuf->b_namedm[i]))
471071d4279SBram Moolenaar 		    result = &curbuf->b_namedm[i];
472071d4279SBram Moolenaar 	    }
473071d4279SBram Moolenaar 	    else
474071d4279SBram Moolenaar 	    {
475b5aedf3eSBram Moolenaar 		if ((result == NULL || LT_POS(*result, curbuf->b_namedm[i]))
476b5aedf3eSBram Moolenaar 			&& LT_POS(curbuf->b_namedm[i], pos))
477071d4279SBram Moolenaar 		    result = &curbuf->b_namedm[i];
478071d4279SBram Moolenaar 	    }
479071d4279SBram Moolenaar 	}
480071d4279SBram Moolenaar     }
481071d4279SBram Moolenaar 
482071d4279SBram Moolenaar     return result;
483071d4279SBram Moolenaar }
484071d4279SBram Moolenaar 
485071d4279SBram Moolenaar /*
486071d4279SBram Moolenaar  * For an xtended filemark: set the fnum from the fname.
487071d4279SBram Moolenaar  * This is used for marks obtained from the .viminfo file.  It's postponed
488071d4279SBram Moolenaar  * until the mark is used to avoid a long startup delay.
489071d4279SBram Moolenaar  */
4905843f5f3SBram Moolenaar     static void
fname2fnum(xfmark_T * fm)49152ea13daSBram Moolenaar fname2fnum(xfmark_T *fm)
492071d4279SBram Moolenaar {
493071d4279SBram Moolenaar     char_u	*p;
494071d4279SBram Moolenaar 
495071d4279SBram Moolenaar     if (fm->fname != NULL)
496071d4279SBram Moolenaar     {
497071d4279SBram Moolenaar 	/*
498071d4279SBram Moolenaar 	 * First expand "~/" in the file name to the home directory.
499525ad4d0SBram Moolenaar 	 * Don't expand the whole name, it may contain other '~' chars.
500071d4279SBram Moolenaar 	 */
501525ad4d0SBram Moolenaar 	if (fm->fname[0] == '~' && (fm->fname[1] == '/'
502525ad4d0SBram Moolenaar #ifdef BACKSLASH_IN_FILENAME
503525ad4d0SBram Moolenaar 		    || fm->fname[1] == '\\'
504525ad4d0SBram Moolenaar #endif
505525ad4d0SBram Moolenaar 		    ))
506525ad4d0SBram Moolenaar 	{
507525ad4d0SBram Moolenaar 	    int len;
508525ad4d0SBram Moolenaar 
509525ad4d0SBram Moolenaar 	    expand_env((char_u *)"~/", NameBuff, MAXPATHL);
510cb4cef22SBram Moolenaar 	    len = (int)STRLEN(NameBuff);
511525ad4d0SBram Moolenaar 	    vim_strncpy(NameBuff + len, fm->fname + 2, MAXPATHL - len - 1);
512525ad4d0SBram Moolenaar 	}
513525ad4d0SBram Moolenaar 	else
514525ad4d0SBram Moolenaar 	    vim_strncpy(NameBuff, fm->fname, MAXPATHL - 1);
515525ad4d0SBram Moolenaar 
5164ba37b58SBram Moolenaar 	// Try to shorten the file name.
517071d4279SBram Moolenaar 	mch_dirname(IObuff, IOSIZE);
518071d4279SBram Moolenaar 	p = shorten_fname(NameBuff, IObuff);
519071d4279SBram Moolenaar 
5204ba37b58SBram Moolenaar 	// buflist_new() will call fmarks_check_names()
521071d4279SBram Moolenaar 	(void)buflist_new(NameBuff, p, (linenr_T)1, 0);
522071d4279SBram Moolenaar     }
523071d4279SBram Moolenaar }
524071d4279SBram Moolenaar 
525071d4279SBram Moolenaar /*
526071d4279SBram Moolenaar  * Check all file marks for a name that matches the file name in buf.
527071d4279SBram Moolenaar  * May replace the name with an fnum.
528071d4279SBram Moolenaar  * Used for marks that come from the .viminfo file.
529071d4279SBram Moolenaar  */
530071d4279SBram Moolenaar     void
fmarks_check_names(buf_T * buf)53152ea13daSBram Moolenaar fmarks_check_names(buf_T *buf)
532071d4279SBram Moolenaar {
533071d4279SBram Moolenaar     char_u	*name;
534071d4279SBram Moolenaar     int		i;
535071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
536071d4279SBram Moolenaar     win_T	*wp;
537071d4279SBram Moolenaar #endif
538071d4279SBram Moolenaar 
539071d4279SBram Moolenaar     if (buf->b_ffname == NULL)
540071d4279SBram Moolenaar 	return;
541071d4279SBram Moolenaar 
542071d4279SBram Moolenaar     name = home_replace_save(buf, buf->b_ffname);
543071d4279SBram Moolenaar     if (name == NULL)
544071d4279SBram Moolenaar 	return;
545071d4279SBram Moolenaar 
546071d4279SBram Moolenaar     for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
547071d4279SBram Moolenaar 	fmarks_check_one(&namedfm[i], name, buf);
548071d4279SBram Moolenaar 
549071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
550071d4279SBram Moolenaar     FOR_ALL_WINDOWS(wp)
551071d4279SBram Moolenaar     {
552071d4279SBram Moolenaar 	for (i = 0; i < wp->w_jumplistlen; ++i)
553071d4279SBram Moolenaar 	    fmarks_check_one(&wp->w_jumplist[i], name, buf);
554071d4279SBram Moolenaar     }
555071d4279SBram Moolenaar #endif
556071d4279SBram Moolenaar 
557071d4279SBram Moolenaar     vim_free(name);
558071d4279SBram Moolenaar }
559071d4279SBram Moolenaar 
560071d4279SBram Moolenaar     static void
fmarks_check_one(xfmark_T * fm,char_u * name,buf_T * buf)56152ea13daSBram Moolenaar fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf)
562071d4279SBram Moolenaar {
563071d4279SBram Moolenaar     if (fm->fmark.fnum == 0
564071d4279SBram Moolenaar 	    && fm->fname != NULL
565071d4279SBram Moolenaar 	    && fnamecmp(name, fm->fname) == 0)
566071d4279SBram Moolenaar     {
567071d4279SBram Moolenaar 	fm->fmark.fnum = buf->b_fnum;
568d23a8236SBram Moolenaar 	VIM_CLEAR(fm->fname);
569071d4279SBram Moolenaar     }
570071d4279SBram Moolenaar }
571071d4279SBram Moolenaar 
572071d4279SBram Moolenaar /*
573071d4279SBram Moolenaar  * Check a if a position from a mark is valid.
574071d4279SBram Moolenaar  * Give and error message and return FAIL if not.
575071d4279SBram Moolenaar  */
576071d4279SBram Moolenaar     int
check_mark(pos_T * pos)57752ea13daSBram Moolenaar check_mark(pos_T *pos)
578071d4279SBram Moolenaar {
579071d4279SBram Moolenaar     if (pos == NULL)
580071d4279SBram Moolenaar     {
581f9e3e09fSBram Moolenaar 	emsg(_(e_umark));
582071d4279SBram Moolenaar 	return FAIL;
583071d4279SBram Moolenaar     }
584071d4279SBram Moolenaar     if (pos->lnum <= 0)
585071d4279SBram Moolenaar     {
5864ba37b58SBram Moolenaar 	// lnum is negative if mark is in another file can can't get that
5874ba37b58SBram Moolenaar 	// file, error message already give then.
588071d4279SBram Moolenaar 	if (pos->lnum == 0)
589108010aaSBram Moolenaar 	    emsg(_(e_mark_not_set));
590071d4279SBram Moolenaar 	return FAIL;
591071d4279SBram Moolenaar     }
592071d4279SBram Moolenaar     if (pos->lnum > curbuf->b_ml.ml_line_count)
593071d4279SBram Moolenaar     {
594108010aaSBram Moolenaar 	emsg(_(e_mark_has_invalid_line_number));
595071d4279SBram Moolenaar 	return FAIL;
596071d4279SBram Moolenaar     }
597071d4279SBram Moolenaar     return OK;
598071d4279SBram Moolenaar }
599071d4279SBram Moolenaar 
600071d4279SBram Moolenaar /*
601071d4279SBram Moolenaar  * clrallmarks() - clear all marks in the buffer 'buf'
602071d4279SBram Moolenaar  *
603071d4279SBram Moolenaar  * Used mainly when trashing the entire buffer during ":e" type commands
604071d4279SBram Moolenaar  */
605071d4279SBram Moolenaar     void
clrallmarks(buf_T * buf)60652ea13daSBram Moolenaar clrallmarks(buf_T *buf)
607071d4279SBram Moolenaar {
608071d4279SBram Moolenaar     static int		i = -1;
609071d4279SBram Moolenaar 
6104ba37b58SBram Moolenaar     if (i == -1)	// first call ever: initialize
611071d4279SBram Moolenaar 	for (i = 0; i < NMARKS + 1; i++)
612071d4279SBram Moolenaar 	{
613071d4279SBram Moolenaar 	    namedfm[i].fmark.mark.lnum = 0;
614071d4279SBram Moolenaar 	    namedfm[i].fname = NULL;
6152d358997SBram Moolenaar #ifdef FEAT_VIMINFO
6162d358997SBram Moolenaar 	    namedfm[i].time_set = 0;
6172d358997SBram Moolenaar #endif
618071d4279SBram Moolenaar 	}
619071d4279SBram Moolenaar 
620071d4279SBram Moolenaar     for (i = 0; i < NMARKS; i++)
621071d4279SBram Moolenaar 	buf->b_namedm[i].lnum = 0;
6224ba37b58SBram Moolenaar     buf->b_op_start.lnum = 0;		// start/end op mark cleared
623071d4279SBram Moolenaar     buf->b_op_end.lnum = 0;
6244ba37b58SBram Moolenaar     buf->b_last_cursor.lnum = 1;	// '" mark cleared
625071d4279SBram Moolenaar     buf->b_last_cursor.col = 0;
626071d4279SBram Moolenaar     buf->b_last_cursor.coladd = 0;
6274ba37b58SBram Moolenaar     buf->b_last_insert.lnum = 0;	// '^ mark cleared
6284ba37b58SBram Moolenaar     buf->b_last_change.lnum = 0;	// '. mark cleared
629071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
630071d4279SBram Moolenaar     buf->b_changelistlen = 0;
631071d4279SBram Moolenaar #endif
632071d4279SBram Moolenaar }
633071d4279SBram Moolenaar 
634071d4279SBram Moolenaar /*
635071d4279SBram Moolenaar  * Get name of file from a filemark.
636071d4279SBram Moolenaar  * When it's in the current buffer, return the text at the mark.
637071d4279SBram Moolenaar  * Returns an allocated string.
638071d4279SBram Moolenaar  */
639071d4279SBram Moolenaar     char_u *
fm_getname(fmark_T * fmark,int lead_len)64052ea13daSBram Moolenaar fm_getname(fmark_T *fmark, int lead_len)
641071d4279SBram Moolenaar {
6424ba37b58SBram Moolenaar     if (fmark->fnum == curbuf->b_fnum)		    // current buffer
643071d4279SBram Moolenaar 	return mark_line(&(fmark->mark), lead_len);
644071d4279SBram Moolenaar     return buflist_nr2name(fmark->fnum, FALSE, TRUE);
645071d4279SBram Moolenaar }
646071d4279SBram Moolenaar 
647071d4279SBram Moolenaar /*
648071d4279SBram Moolenaar  * Return the line at mark "mp".  Truncate to fit in window.
649071d4279SBram Moolenaar  * The returned string has been allocated.
650071d4279SBram Moolenaar  */
651071d4279SBram Moolenaar     static char_u *
mark_line(pos_T * mp,int lead_len)65252ea13daSBram Moolenaar mark_line(pos_T *mp, int lead_len)
653071d4279SBram Moolenaar {
654071d4279SBram Moolenaar     char_u	*s, *p;
655071d4279SBram Moolenaar     int		len;
656071d4279SBram Moolenaar 
657071d4279SBram Moolenaar     if (mp->lnum == 0 || mp->lnum > curbuf->b_ml.ml_line_count)
658071d4279SBram Moolenaar 	return vim_strsave((char_u *)"-invalid-");
6599d5185bfSBram Moolenaar     // Allow for up to 5 bytes per character.
66071ccd03eSBram Moolenaar     s = vim_strnsave(skipwhite(ml_get(mp->lnum)), Columns * 5);
661071d4279SBram Moolenaar     if (s == NULL)
662071d4279SBram Moolenaar 	return NULL;
6639d5185bfSBram Moolenaar     // Truncate the line to fit it in the window.
664071d4279SBram Moolenaar     len = 0;
66591acfffcSBram Moolenaar     for (p = s; *p != NUL; MB_PTR_ADV(p))
666071d4279SBram Moolenaar     {
667071d4279SBram Moolenaar 	len += ptr2cells(p);
668071d4279SBram Moolenaar 	if (len >= Columns - lead_len)
669071d4279SBram Moolenaar 	    break;
670071d4279SBram Moolenaar     }
671071d4279SBram Moolenaar     *p = NUL;
672071d4279SBram Moolenaar     return s;
673071d4279SBram Moolenaar }
674071d4279SBram Moolenaar 
675071d4279SBram Moolenaar /*
676071d4279SBram Moolenaar  * print the marks
677071d4279SBram Moolenaar  */
678071d4279SBram Moolenaar     void
ex_marks(exarg_T * eap)6794bd78233SBram Moolenaar ex_marks(exarg_T *eap)
680071d4279SBram Moolenaar {
681071d4279SBram Moolenaar     char_u	*arg = eap->arg;
682071d4279SBram Moolenaar     int		i;
683071d4279SBram Moolenaar     char_u	*name;
68454c3fcd8SBram Moolenaar     pos_T	*posp, *startp, *endp;
685071d4279SBram Moolenaar 
686071d4279SBram Moolenaar     if (arg != NULL && *arg == NUL)
687071d4279SBram Moolenaar 	arg = NULL;
688071d4279SBram Moolenaar 
689071d4279SBram Moolenaar     show_one_mark('\'', arg, &curwin->w_pcmark, NULL, TRUE);
690071d4279SBram Moolenaar     for (i = 0; i < NMARKS; ++i)
691071d4279SBram Moolenaar 	show_one_mark(i + 'a', arg, &curbuf->b_namedm[i], NULL, TRUE);
692071d4279SBram Moolenaar     for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
693071d4279SBram Moolenaar     {
694071d4279SBram Moolenaar 	if (namedfm[i].fmark.fnum != 0)
695071d4279SBram Moolenaar 	    name = fm_getname(&namedfm[i].fmark, 15);
696071d4279SBram Moolenaar 	else
697071d4279SBram Moolenaar 	    name = namedfm[i].fname;
698071d4279SBram Moolenaar 	if (name != NULL)
699071d4279SBram Moolenaar 	{
700071d4279SBram Moolenaar 	    show_one_mark(i >= NMARKS ? i - NMARKS + '0' : i + 'A',
701071d4279SBram Moolenaar 		    arg, &namedfm[i].fmark.mark, name,
702071d4279SBram Moolenaar 		    namedfm[i].fmark.fnum == curbuf->b_fnum);
703071d4279SBram Moolenaar 	    if (namedfm[i].fmark.fnum != 0)
704071d4279SBram Moolenaar 		vim_free(name);
705071d4279SBram Moolenaar 	}
706071d4279SBram Moolenaar     }
707071d4279SBram Moolenaar     show_one_mark('"', arg, &curbuf->b_last_cursor, NULL, TRUE);
708071d4279SBram Moolenaar     show_one_mark('[', arg, &curbuf->b_op_start, NULL, TRUE);
709071d4279SBram Moolenaar     show_one_mark(']', arg, &curbuf->b_op_end, NULL, TRUE);
710071d4279SBram Moolenaar     show_one_mark('^', arg, &curbuf->b_last_insert, NULL, TRUE);
711071d4279SBram Moolenaar     show_one_mark('.', arg, &curbuf->b_last_change, NULL, TRUE);
71254c3fcd8SBram Moolenaar 
71354c3fcd8SBram Moolenaar     // Show the marks as where they will jump to.
71454c3fcd8SBram Moolenaar     startp = &curbuf->b_visual.vi_start;
71554c3fcd8SBram Moolenaar     endp = &curbuf->b_visual.vi_end;
71654c3fcd8SBram Moolenaar     if ((LT_POS(*startp, *endp) || endp->lnum == 0) && startp->lnum != 0)
71754c3fcd8SBram Moolenaar 	posp = startp;
71854c3fcd8SBram Moolenaar     else
71954c3fcd8SBram Moolenaar 	posp = endp;
72054c3fcd8SBram Moolenaar     show_one_mark('<', arg, posp, NULL, TRUE);
72154c3fcd8SBram Moolenaar     show_one_mark('>', arg, posp == startp ? endp : startp, NULL, TRUE);
72254c3fcd8SBram Moolenaar 
723071d4279SBram Moolenaar     show_one_mark(-1, arg, NULL, NULL, FALSE);
724071d4279SBram Moolenaar }
725071d4279SBram Moolenaar 
726071d4279SBram Moolenaar     static void
show_one_mark(int c,char_u * arg,pos_T * p,char_u * name_arg,int current)72752ea13daSBram Moolenaar show_one_mark(
72852ea13daSBram Moolenaar     int		c,
72952ea13daSBram Moolenaar     char_u	*arg,
73052ea13daSBram Moolenaar     pos_T	*p,
731ad6dc49aSBram Moolenaar     char_u	*name_arg,
7324ba37b58SBram Moolenaar     int		current)	// in current file
733071d4279SBram Moolenaar {
734071d4279SBram Moolenaar     static int	did_title = FALSE;
735071d4279SBram Moolenaar     int		mustfree = FALSE;
736ad6dc49aSBram Moolenaar     char_u	*name = name_arg;
737071d4279SBram Moolenaar 
7384ba37b58SBram Moolenaar     if (c == -1)			    // finish up
739071d4279SBram Moolenaar     {
740071d4279SBram Moolenaar 	if (did_title)
741071d4279SBram Moolenaar 	    did_title = FALSE;
742071d4279SBram Moolenaar 	else
743071d4279SBram Moolenaar 	{
744071d4279SBram Moolenaar 	    if (arg == NULL)
74532526b3cSBram Moolenaar 		msg(_("No marks set"));
746071d4279SBram Moolenaar 	    else
747f9e3e09fSBram Moolenaar 		semsg(_("E283: No marks matching \"%s\""), arg);
748071d4279SBram Moolenaar 	}
749071d4279SBram Moolenaar     }
750ad6dc49aSBram Moolenaar     // don't output anything if 'q' typed at --more-- prompt
751071d4279SBram Moolenaar     else if (!got_int
752071d4279SBram Moolenaar 	    && (arg == NULL || vim_strchr(arg, c) != NULL)
753071d4279SBram Moolenaar 	    && p->lnum != 0)
754071d4279SBram Moolenaar     {
755ad6dc49aSBram Moolenaar 	if (name == NULL && current)
756ad6dc49aSBram Moolenaar 	{
757ad6dc49aSBram Moolenaar 	    name = mark_line(p, 15);
758ad6dc49aSBram Moolenaar 	    mustfree = TRUE;
759ad6dc49aSBram Moolenaar 	}
760ad6dc49aSBram Moolenaar 	if (!message_filtered(name))
761ad6dc49aSBram Moolenaar 	{
762071d4279SBram Moolenaar 	    if (!did_title)
763071d4279SBram Moolenaar 	    {
764ad6dc49aSBram Moolenaar 		// Highlight title
76532526b3cSBram Moolenaar 		msg_puts_title(_("\nmark line  col file/text"));
766071d4279SBram Moolenaar 		did_title = TRUE;
767071d4279SBram Moolenaar 	    }
768071d4279SBram Moolenaar 	    msg_putchar('\n');
769071d4279SBram Moolenaar 	    if (!got_int)
770071d4279SBram Moolenaar 	    {
771071d4279SBram Moolenaar 		sprintf((char *)IObuff, " %c %6ld %4d ", c, p->lnum, p->col);
772071d4279SBram Moolenaar 		msg_outtrans(IObuff);
773071d4279SBram Moolenaar 		if (name != NULL)
774071d4279SBram Moolenaar 		{
7758820b486SBram Moolenaar 		    msg_outtrans_attr(name, current ? HL_ATTR(HLF_D) : 0);
776ad6dc49aSBram Moolenaar 		}
777ad6dc49aSBram Moolenaar 	    }
778ad6dc49aSBram Moolenaar 	    out_flush();		    // show one line at a time
779ad6dc49aSBram Moolenaar 	}
780071d4279SBram Moolenaar 	if (mustfree)
781071d4279SBram Moolenaar 	    vim_free(name);
782071d4279SBram Moolenaar     }
783071d4279SBram Moolenaar }
784071d4279SBram Moolenaar 
785c0197e28SBram Moolenaar /*
786c0197e28SBram Moolenaar  * ":delmarks[!] [marks]"
787c0197e28SBram Moolenaar  */
788c0197e28SBram Moolenaar     void
ex_delmarks(exarg_T * eap)78952ea13daSBram Moolenaar ex_delmarks(exarg_T *eap)
790c0197e28SBram Moolenaar {
791c0197e28SBram Moolenaar     char_u	*p;
792c0197e28SBram Moolenaar     int		from, to;
793c0197e28SBram Moolenaar     int		i;
794c0197e28SBram Moolenaar     int		lower;
795c0197e28SBram Moolenaar     int		digit;
796c0197e28SBram Moolenaar     int		n;
797c0197e28SBram Moolenaar 
798c0197e28SBram Moolenaar     if (*eap->arg == NUL && eap->forceit)
7994ba37b58SBram Moolenaar 	// clear all marks
800c0197e28SBram Moolenaar 	clrallmarks(curbuf);
801c0197e28SBram Moolenaar     else if (eap->forceit)
802f9e3e09fSBram Moolenaar 	emsg(_(e_invarg));
803c0197e28SBram Moolenaar     else if (*eap->arg == NUL)
804f9e3e09fSBram Moolenaar 	emsg(_(e_argreq));
805c0197e28SBram Moolenaar     else
806c0197e28SBram Moolenaar     {
8074ba37b58SBram Moolenaar 	// clear specified marks only
808c0197e28SBram Moolenaar 	for (p = eap->arg; *p != NUL; ++p)
809c0197e28SBram Moolenaar 	{
810c0197e28SBram Moolenaar 	    lower = ASCII_ISLOWER(*p);
811c0197e28SBram Moolenaar 	    digit = VIM_ISDIGIT(*p);
812c0197e28SBram Moolenaar 	    if (lower || digit || ASCII_ISUPPER(*p))
813c0197e28SBram Moolenaar 	    {
814c0197e28SBram Moolenaar 		if (p[1] == '-')
815c0197e28SBram Moolenaar 		{
8164ba37b58SBram Moolenaar 		    // clear range of marks
817c0197e28SBram Moolenaar 		    from = *p;
818c0197e28SBram Moolenaar 		    to = p[2];
819c0197e28SBram Moolenaar 		    if (!(lower ? ASCII_ISLOWER(p[2])
820c0197e28SBram Moolenaar 				: (digit ? VIM_ISDIGIT(p[2])
821c0197e28SBram Moolenaar 				    : ASCII_ISUPPER(p[2])))
822c0197e28SBram Moolenaar 			    || to < from)
823c0197e28SBram Moolenaar 		    {
824f9e3e09fSBram Moolenaar 			semsg(_(e_invarg2), p);
825c0197e28SBram Moolenaar 			return;
826c0197e28SBram Moolenaar 		    }
827c0197e28SBram Moolenaar 		    p += 2;
828c0197e28SBram Moolenaar 		}
829c0197e28SBram Moolenaar 		else
8304ba37b58SBram Moolenaar 		    // clear one lower case mark
831c0197e28SBram Moolenaar 		    from = to = *p;
832c0197e28SBram Moolenaar 
833c0197e28SBram Moolenaar 		for (i = from; i <= to; ++i)
834c0197e28SBram Moolenaar 		{
835c0197e28SBram Moolenaar 		    if (lower)
836c0197e28SBram Moolenaar 			curbuf->b_namedm[i - 'a'].lnum = 0;
837c0197e28SBram Moolenaar 		    else
838c0197e28SBram Moolenaar 		    {
839c0197e28SBram Moolenaar 			if (digit)
840c0197e28SBram Moolenaar 			    n = i - '0' + NMARKS;
841c0197e28SBram Moolenaar 			else
842c0197e28SBram Moolenaar 			    n = i - 'A';
843c0197e28SBram Moolenaar 			namedfm[n].fmark.mark.lnum = 0;
8448cd6cd80SBram Moolenaar 			namedfm[n].fmark.fnum = 0;
845d23a8236SBram Moolenaar 			VIM_CLEAR(namedfm[n].fname);
8462d358997SBram Moolenaar #ifdef FEAT_VIMINFO
8478cd6cd80SBram Moolenaar 			namedfm[n].time_set = digit ? 0 : vim_time();
8482d358997SBram Moolenaar #endif
849c0197e28SBram Moolenaar 		    }
850c0197e28SBram Moolenaar 		}
851c0197e28SBram Moolenaar 	    }
852c0197e28SBram Moolenaar 	    else
853c0197e28SBram Moolenaar 		switch (*p)
854c0197e28SBram Moolenaar 		{
855c0197e28SBram Moolenaar 		    case '"': curbuf->b_last_cursor.lnum = 0; break;
856c0197e28SBram Moolenaar 		    case '^': curbuf->b_last_insert.lnum = 0; break;
857c0197e28SBram Moolenaar 		    case '.': curbuf->b_last_change.lnum = 0; break;
858c0197e28SBram Moolenaar 		    case '[': curbuf->b_op_start.lnum    = 0; break;
859c0197e28SBram Moolenaar 		    case ']': curbuf->b_op_end.lnum      = 0; break;
860a226a6ddSBram Moolenaar 		    case '<': curbuf->b_visual.vi_start.lnum = 0; break;
861a226a6ddSBram Moolenaar 		    case '>': curbuf->b_visual.vi_end.lnum   = 0; break;
862c0197e28SBram Moolenaar 		    case ' ': break;
863f9e3e09fSBram Moolenaar 		    default:  semsg(_(e_invarg2), p);
864c0197e28SBram Moolenaar 			      return;
865c0197e28SBram Moolenaar 		}
866c0197e28SBram Moolenaar 	}
867c0197e28SBram Moolenaar     }
868c0197e28SBram Moolenaar }
869c0197e28SBram Moolenaar 
870071d4279SBram Moolenaar #if defined(FEAT_JUMPLIST) || defined(PROTO)
871071d4279SBram Moolenaar /*
872071d4279SBram Moolenaar  * print the jumplist
873071d4279SBram Moolenaar  */
874071d4279SBram Moolenaar     void
ex_jumps(exarg_T * eap UNUSED)87552ea13daSBram Moolenaar ex_jumps(exarg_T *eap UNUSED)
876071d4279SBram Moolenaar {
877071d4279SBram Moolenaar     int		i;
878071d4279SBram Moolenaar     char_u	*name;
879071d4279SBram Moolenaar 
88048679741SBram Moolenaar     cleanup_jumplist(curwin, TRUE);
881a7e18d23SBram Moolenaar 
8824ba37b58SBram Moolenaar     // Highlight title
88332526b3cSBram Moolenaar     msg_puts_title(_("\n jump line  col file/text"));
884071d4279SBram Moolenaar     for (i = 0; i < curwin->w_jumplistlen && !got_int; ++i)
885071d4279SBram Moolenaar     {
886071d4279SBram Moolenaar 	if (curwin->w_jumplist[i].fmark.mark.lnum != 0)
887071d4279SBram Moolenaar 	{
888071d4279SBram Moolenaar 	    name = fm_getname(&curwin->w_jumplist[i].fmark, 16);
889f86db78fSBram Moolenaar 
890f86db78fSBram Moolenaar 	    // apply :filter /pat/ or file name not available
891f86db78fSBram Moolenaar 	    if (name == NULL || message_filtered(name))
892d93090f4SBram Moolenaar 	    {
893d93090f4SBram Moolenaar 		vim_free(name);
894071d4279SBram Moolenaar 		continue;
895d93090f4SBram Moolenaar 	    }
896071d4279SBram Moolenaar 
897071d4279SBram Moolenaar 	    msg_putchar('\n');
898071d4279SBram Moolenaar 	    if (got_int)
899ed39e1d5SBram Moolenaar 	    {
900ed39e1d5SBram Moolenaar 		vim_free(name);
901071d4279SBram Moolenaar 		break;
902ed39e1d5SBram Moolenaar 	    }
903071d4279SBram Moolenaar 	    sprintf((char *)IObuff, "%c %2d %5ld %4d ",
904071d4279SBram Moolenaar 		i == curwin->w_jumplistidx ? '>' : ' ',
905071d4279SBram Moolenaar 		i > curwin->w_jumplistidx ? i - curwin->w_jumplistidx
906071d4279SBram Moolenaar 					  : curwin->w_jumplistidx - i,
907071d4279SBram Moolenaar 		curwin->w_jumplist[i].fmark.mark.lnum,
908071d4279SBram Moolenaar 		curwin->w_jumplist[i].fmark.mark.col);
909071d4279SBram Moolenaar 	    msg_outtrans(IObuff);
910071d4279SBram Moolenaar 	    msg_outtrans_attr(name,
911071d4279SBram Moolenaar 			    curwin->w_jumplist[i].fmark.fnum == curbuf->b_fnum
9128820b486SBram Moolenaar 							? HL_ATTR(HLF_D) : 0);
913071d4279SBram Moolenaar 	    vim_free(name);
914071d4279SBram Moolenaar 	    ui_breakcheck();
915071d4279SBram Moolenaar 	}
916071d4279SBram Moolenaar 	out_flush();
917071d4279SBram Moolenaar     }
918071d4279SBram Moolenaar     if (curwin->w_jumplistidx == curwin->w_jumplistlen)
91932526b3cSBram Moolenaar 	msg_puts("\n>");
920071d4279SBram Moolenaar }
921071d4279SBram Moolenaar 
9222d358997SBram Moolenaar     void
ex_clearjumps(exarg_T * eap UNUSED)9232d358997SBram Moolenaar ex_clearjumps(exarg_T *eap UNUSED)
9242d358997SBram Moolenaar {
9252d358997SBram Moolenaar     free_jumplist(curwin);
9262d358997SBram Moolenaar     curwin->w_jumplistlen = 0;
9272d358997SBram Moolenaar     curwin->w_jumplistidx = 0;
9282d358997SBram Moolenaar }
9292d358997SBram Moolenaar 
930071d4279SBram Moolenaar /*
931071d4279SBram Moolenaar  * print the changelist
932071d4279SBram Moolenaar  */
933071d4279SBram Moolenaar     void
ex_changes(exarg_T * eap UNUSED)93452ea13daSBram Moolenaar ex_changes(exarg_T *eap UNUSED)
935071d4279SBram Moolenaar {
936071d4279SBram Moolenaar     int		i;
937071d4279SBram Moolenaar     char_u	*name;
938071d4279SBram Moolenaar 
9394ba37b58SBram Moolenaar     // Highlight title
94032526b3cSBram Moolenaar     msg_puts_title(_("\nchange line  col text"));
941071d4279SBram Moolenaar 
942071d4279SBram Moolenaar     for (i = 0; i < curbuf->b_changelistlen && !got_int; ++i)
943071d4279SBram Moolenaar     {
944071d4279SBram Moolenaar 	if (curbuf->b_changelist[i].lnum != 0)
945071d4279SBram Moolenaar 	{
946071d4279SBram Moolenaar 	    msg_putchar('\n');
947071d4279SBram Moolenaar 	    if (got_int)
948071d4279SBram Moolenaar 		break;
949071d4279SBram Moolenaar 	    sprintf((char *)IObuff, "%c %3d %5ld %4d ",
950071d4279SBram Moolenaar 		    i == curwin->w_changelistidx ? '>' : ' ',
951071d4279SBram Moolenaar 		    i > curwin->w_changelistidx ? i - curwin->w_changelistidx
952071d4279SBram Moolenaar 						: curwin->w_changelistidx - i,
953071d4279SBram Moolenaar 		    (long)curbuf->b_changelist[i].lnum,
954071d4279SBram Moolenaar 		    curbuf->b_changelist[i].col);
955071d4279SBram Moolenaar 	    msg_outtrans(IObuff);
956071d4279SBram Moolenaar 	    name = mark_line(&curbuf->b_changelist[i], 17);
957071d4279SBram Moolenaar 	    if (name == NULL)
958071d4279SBram Moolenaar 		break;
9598820b486SBram Moolenaar 	    msg_outtrans_attr(name, HL_ATTR(HLF_D));
960071d4279SBram Moolenaar 	    vim_free(name);
961071d4279SBram Moolenaar 	    ui_breakcheck();
962071d4279SBram Moolenaar 	}
963071d4279SBram Moolenaar 	out_flush();
964071d4279SBram Moolenaar     }
965071d4279SBram Moolenaar     if (curwin->w_changelistidx == curbuf->b_changelistlen)
96632526b3cSBram Moolenaar 	msg_puts("\n>");
967071d4279SBram Moolenaar }
968071d4279SBram Moolenaar #endif
969071d4279SBram Moolenaar 
970071d4279SBram Moolenaar #define one_adjust(add) \
971071d4279SBram Moolenaar     { \
972071d4279SBram Moolenaar 	lp = add; \
973071d4279SBram Moolenaar 	if (*lp >= line1 && *lp <= line2) \
974071d4279SBram Moolenaar 	{ \
975071d4279SBram Moolenaar 	    if (amount == MAXLNUM) \
976071d4279SBram Moolenaar 		*lp = 0; \
977071d4279SBram Moolenaar 	    else \
978071d4279SBram Moolenaar 		*lp += amount; \
979071d4279SBram Moolenaar 	} \
980071d4279SBram Moolenaar 	else if (amount_after && *lp > line2) \
981071d4279SBram Moolenaar 	    *lp += amount_after; \
982071d4279SBram Moolenaar     }
983071d4279SBram Moolenaar 
9844ba37b58SBram Moolenaar // don't delete the line, just put at first deleted line
985071d4279SBram Moolenaar #define one_adjust_nodel(add) \
986071d4279SBram Moolenaar     { \
987071d4279SBram Moolenaar 	lp = add; \
988071d4279SBram Moolenaar 	if (*lp >= line1 && *lp <= line2) \
989071d4279SBram Moolenaar 	{ \
990071d4279SBram Moolenaar 	    if (amount == MAXLNUM) \
991071d4279SBram Moolenaar 		*lp = line1; \
992071d4279SBram Moolenaar 	    else \
993071d4279SBram Moolenaar 		*lp += amount; \
994071d4279SBram Moolenaar 	} \
995071d4279SBram Moolenaar 	else if (amount_after && *lp > line2) \
996071d4279SBram Moolenaar 	    *lp += amount_after; \
997071d4279SBram Moolenaar     }
998071d4279SBram Moolenaar 
999071d4279SBram Moolenaar /*
1000071d4279SBram Moolenaar  * Adjust marks between line1 and line2 (inclusive) to move 'amount' lines.
1001071d4279SBram Moolenaar  * Must be called before changed_*(), appended_lines() or deleted_lines().
1002071d4279SBram Moolenaar  * May be called before or after changing the text.
1003071d4279SBram Moolenaar  * When deleting lines line1 to line2, use an 'amount' of MAXLNUM: The marks
1004071d4279SBram Moolenaar  * within this range are made invalid.
1005071d4279SBram Moolenaar  * If 'amount_after' is non-zero adjust marks after line2.
1006071d4279SBram Moolenaar  * Example: Delete lines 34 and 35: mark_adjust(34, 35, MAXLNUM, -2);
1007071d4279SBram Moolenaar  * Example: Insert two lines below 55: mark_adjust(56, MAXLNUM, 2, 0);
1008071d4279SBram Moolenaar  *				   or: mark_adjust(56, 55, MAXLNUM, 2);
1009071d4279SBram Moolenaar  */
1010071d4279SBram Moolenaar     void
mark_adjust(linenr_T line1,linenr_T line2,long amount,long amount_after)101152ea13daSBram Moolenaar mark_adjust(
101252ea13daSBram Moolenaar     linenr_T	line1,
101352ea13daSBram Moolenaar     linenr_T	line2,
101452ea13daSBram Moolenaar     long	amount,
101552ea13daSBram Moolenaar     long	amount_after)
1016071d4279SBram Moolenaar {
101788d298aeSBram Moolenaar     mark_adjust_internal(line1, line2, amount, amount_after, TRUE);
101888d298aeSBram Moolenaar }
101988d298aeSBram Moolenaar 
102088d298aeSBram Moolenaar     void
mark_adjust_nofold(linenr_T line1,linenr_T line2,long amount,long amount_after)102188d298aeSBram Moolenaar mark_adjust_nofold(
102288d298aeSBram Moolenaar     linenr_T line1,
102388d298aeSBram Moolenaar     linenr_T line2,
102488d298aeSBram Moolenaar     long amount,
102588d298aeSBram Moolenaar     long amount_after)
102688d298aeSBram Moolenaar {
102788d298aeSBram Moolenaar     mark_adjust_internal(line1, line2, amount, amount_after, FALSE);
102888d298aeSBram Moolenaar }
102988d298aeSBram Moolenaar 
103088d298aeSBram Moolenaar     static void
mark_adjust_internal(linenr_T line1,linenr_T line2,long amount,long amount_after,int adjust_folds UNUSED)103188d298aeSBram Moolenaar mark_adjust_internal(
103288d298aeSBram Moolenaar     linenr_T line1,
103388d298aeSBram Moolenaar     linenr_T line2,
103488d298aeSBram Moolenaar     long amount,
103588d298aeSBram Moolenaar     long amount_after,
103688d298aeSBram Moolenaar     int adjust_folds UNUSED)
103788d298aeSBram Moolenaar {
1038071d4279SBram Moolenaar     int		i;
1039071d4279SBram Moolenaar     int		fnum = curbuf->b_fnum;
1040071d4279SBram Moolenaar     linenr_T	*lp;
1041071d4279SBram Moolenaar     win_T	*win;
1042bd1e5d2eSBram Moolenaar     tabpage_T	*tab;
104329ddebefSBram Moolenaar     static pos_T initpos = {1, 0, 0};
1044071d4279SBram Moolenaar 
10454ba37b58SBram Moolenaar     if (line2 < line1 && amount_after == 0L)	    // nothing to do
1046071d4279SBram Moolenaar 	return;
1047071d4279SBram Moolenaar 
1048e1004401SBram Moolenaar     if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
1049071d4279SBram Moolenaar     {
10504ba37b58SBram Moolenaar 	// named marks, lower case and upper case
1051071d4279SBram Moolenaar 	for (i = 0; i < NMARKS; i++)
1052071d4279SBram Moolenaar 	{
1053071d4279SBram Moolenaar 	    one_adjust(&(curbuf->b_namedm[i].lnum));
1054071d4279SBram Moolenaar 	    if (namedfm[i].fmark.fnum == fnum)
1055071d4279SBram Moolenaar 		one_adjust_nodel(&(namedfm[i].fmark.mark.lnum));
1056071d4279SBram Moolenaar 	}
1057071d4279SBram Moolenaar 	for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
1058071d4279SBram Moolenaar 	{
1059071d4279SBram Moolenaar 	    if (namedfm[i].fmark.fnum == fnum)
1060071d4279SBram Moolenaar 		one_adjust_nodel(&(namedfm[i].fmark.mark.lnum));
1061071d4279SBram Moolenaar 	}
1062071d4279SBram Moolenaar 
10634ba37b58SBram Moolenaar 	// last Insert position
1064071d4279SBram Moolenaar 	one_adjust(&(curbuf->b_last_insert.lnum));
1065071d4279SBram Moolenaar 
10664ba37b58SBram Moolenaar 	// last change position
1067071d4279SBram Moolenaar 	one_adjust(&(curbuf->b_last_change.lnum));
1068071d4279SBram Moolenaar 
10694ba37b58SBram Moolenaar 	// last cursor position, if it was set
1070b5aedf3eSBram Moolenaar 	if (!EQUAL_POS(curbuf->b_last_cursor, initpos))
1071b6a76ffcSBram Moolenaar 	    one_adjust(&(curbuf->b_last_cursor.lnum));
1072b6a76ffcSBram Moolenaar 
1073b6a76ffcSBram Moolenaar 
1074071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
10754ba37b58SBram Moolenaar 	// list of change positions
1076071d4279SBram Moolenaar 	for (i = 0; i < curbuf->b_changelistlen; ++i)
1077071d4279SBram Moolenaar 	    one_adjust_nodel(&(curbuf->b_changelist[i].lnum));
1078071d4279SBram Moolenaar #endif
1079071d4279SBram Moolenaar 
10804ba37b58SBram Moolenaar 	// Visual area
1081a226a6ddSBram Moolenaar 	one_adjust_nodel(&(curbuf->b_visual.vi_start.lnum));
1082a226a6ddSBram Moolenaar 	one_adjust_nodel(&(curbuf->b_visual.vi_end.lnum));
1083071d4279SBram Moolenaar 
1084071d4279SBram Moolenaar #ifdef FEAT_QUICKFIX
10854ba37b58SBram Moolenaar 	// quickfix marks
108628c258fdSBram Moolenaar 	qf_mark_adjust(NULL, line1, line2, amount, amount_after);
10874ba37b58SBram Moolenaar 	// location lists
1088bd1e5d2eSBram Moolenaar 	FOR_ALL_TAB_WINDOWS(tab, win)
108928c258fdSBram Moolenaar 	    qf_mark_adjust(win, line1, line2, amount, amount_after);
1090071d4279SBram Moolenaar #endif
1091071d4279SBram Moolenaar 
1092071d4279SBram Moolenaar #ifdef FEAT_SIGNS
1093071d4279SBram Moolenaar 	sign_mark_adjust(line1, line2, amount, amount_after);
1094071d4279SBram Moolenaar #endif
1095071d4279SBram Moolenaar     }
1096071d4279SBram Moolenaar 
10974ba37b58SBram Moolenaar     // previous context mark
1098071d4279SBram Moolenaar     one_adjust(&(curwin->w_pcmark.lnum));
1099071d4279SBram Moolenaar 
11004ba37b58SBram Moolenaar     // previous pcmark
1101071d4279SBram Moolenaar     one_adjust(&(curwin->w_prev_pcmark.lnum));
1102071d4279SBram Moolenaar 
11034ba37b58SBram Moolenaar     // saved cursor for formatting
1104071d4279SBram Moolenaar     if (saved_cursor.lnum != 0)
1105071d4279SBram Moolenaar 	one_adjust_nodel(&(saved_cursor.lnum));
1106071d4279SBram Moolenaar 
1107071d4279SBram Moolenaar     /*
1108071d4279SBram Moolenaar      * Adjust items in all windows related to the current buffer.
1109071d4279SBram Moolenaar      */
1110bd1e5d2eSBram Moolenaar     FOR_ALL_TAB_WINDOWS(tab, win)
1111071d4279SBram Moolenaar     {
1112071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
1113e1004401SBram Moolenaar 	if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
11144ba37b58SBram Moolenaar 	    // Marks in the jumplist.  When deleting lines, this may create
11154ba37b58SBram Moolenaar 	    // duplicate marks in the jumplist, they will be removed later.
1116071d4279SBram Moolenaar 	    for (i = 0; i < win->w_jumplistlen; ++i)
1117071d4279SBram Moolenaar 		if (win->w_jumplist[i].fmark.fnum == fnum)
1118071d4279SBram Moolenaar 		    one_adjust_nodel(&(win->w_jumplist[i].fmark.mark.lnum));
1119071d4279SBram Moolenaar #endif
1120071d4279SBram Moolenaar 
1121071d4279SBram Moolenaar 	if (win->w_buffer == curbuf)
1122071d4279SBram Moolenaar 	{
1123e1004401SBram Moolenaar 	    if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
11244ba37b58SBram Moolenaar 		// marks in the tag stack
1125071d4279SBram Moolenaar 		for (i = 0; i < win->w_tagstacklen; i++)
1126071d4279SBram Moolenaar 		    if (win->w_tagstack[i].fmark.fnum == fnum)
1127071d4279SBram Moolenaar 			one_adjust_nodel(&(win->w_tagstack[i].fmark.mark.lnum));
1128071d4279SBram Moolenaar 
11294ba37b58SBram Moolenaar 	    // the displayed Visual area
1130071d4279SBram Moolenaar 	    if (win->w_old_cursor_lnum != 0)
1131071d4279SBram Moolenaar 	    {
1132071d4279SBram Moolenaar 		one_adjust_nodel(&(win->w_old_cursor_lnum));
1133071d4279SBram Moolenaar 		one_adjust_nodel(&(win->w_old_visual_lnum));
1134071d4279SBram Moolenaar 	    }
1135071d4279SBram Moolenaar 
11364ba37b58SBram Moolenaar 	    // topline and cursor position for windows with the same buffer
11374ba37b58SBram Moolenaar 	    // other than the current window
1138071d4279SBram Moolenaar 	    if (win != curwin)
1139071d4279SBram Moolenaar 	    {
1140071d4279SBram Moolenaar 		if (win->w_topline >= line1 && win->w_topline <= line2)
1141071d4279SBram Moolenaar 		{
11424ba37b58SBram Moolenaar 		    if (amount == MAXLNUM)	    // topline is deleted
1143071d4279SBram Moolenaar 		    {
1144071d4279SBram Moolenaar 			if (line1 <= 1)
1145071d4279SBram Moolenaar 			    win->w_topline = 1;
1146071d4279SBram Moolenaar 			else
1147071d4279SBram Moolenaar 			    win->w_topline = line1 - 1;
1148071d4279SBram Moolenaar 		    }
11494ba37b58SBram Moolenaar 		    else		// keep topline on the same line
1150071d4279SBram Moolenaar 			win->w_topline += amount;
1151071d4279SBram Moolenaar #ifdef FEAT_DIFF
1152071d4279SBram Moolenaar 		    win->w_topfill = 0;
1153071d4279SBram Moolenaar #endif
1154071d4279SBram Moolenaar 		}
1155071d4279SBram Moolenaar 		else if (amount_after && win->w_topline > line2)
1156071d4279SBram Moolenaar 		{
1157071d4279SBram Moolenaar 		    win->w_topline += amount_after;
1158071d4279SBram Moolenaar #ifdef FEAT_DIFF
1159071d4279SBram Moolenaar 		    win->w_topfill = 0;
1160071d4279SBram Moolenaar #endif
1161071d4279SBram Moolenaar 		}
1162071d4279SBram Moolenaar 		if (win->w_cursor.lnum >= line1 && win->w_cursor.lnum <= line2)
1163071d4279SBram Moolenaar 		{
11644ba37b58SBram Moolenaar 		    if (amount == MAXLNUM) // line with cursor is deleted
1165071d4279SBram Moolenaar 		    {
1166071d4279SBram Moolenaar 			if (line1 <= 1)
1167071d4279SBram Moolenaar 			    win->w_cursor.lnum = 1;
1168071d4279SBram Moolenaar 			else
1169071d4279SBram Moolenaar 			    win->w_cursor.lnum = line1 - 1;
1170071d4279SBram Moolenaar 			win->w_cursor.col = 0;
1171071d4279SBram Moolenaar 		    }
11724ba37b58SBram Moolenaar 		    else		// keep cursor on the same line
1173071d4279SBram Moolenaar 			win->w_cursor.lnum += amount;
1174071d4279SBram Moolenaar 		}
1175071d4279SBram Moolenaar 		else if (amount_after && win->w_cursor.lnum > line2)
1176071d4279SBram Moolenaar 		    win->w_cursor.lnum += amount_after;
1177071d4279SBram Moolenaar 	    }
1178071d4279SBram Moolenaar 
1179071d4279SBram Moolenaar #ifdef FEAT_FOLDING
11804ba37b58SBram Moolenaar 	    // adjust folds
118188d298aeSBram Moolenaar 	    if (adjust_folds)
1182071d4279SBram Moolenaar 		foldMarkAdjust(win, line1, line2, amount, amount_after);
1183071d4279SBram Moolenaar #endif
1184071d4279SBram Moolenaar 	}
1185071d4279SBram Moolenaar     }
1186071d4279SBram Moolenaar 
1187071d4279SBram Moolenaar #ifdef FEAT_DIFF
11884ba37b58SBram Moolenaar     // adjust diffs
1189071d4279SBram Moolenaar     diff_mark_adjust(line1, line2, amount, amount_after);
1190071d4279SBram Moolenaar #endif
1191071d4279SBram Moolenaar }
1192071d4279SBram Moolenaar 
11934ba37b58SBram Moolenaar // This code is used often, needs to be fast.
1194071d4279SBram Moolenaar #define col_adjust(pp) \
1195071d4279SBram Moolenaar     { \
1196071d4279SBram Moolenaar 	posp = pp; \
1197071d4279SBram Moolenaar 	if (posp->lnum == lnum && posp->col >= mincol) \
1198071d4279SBram Moolenaar 	{ \
1199071d4279SBram Moolenaar 	    posp->lnum += lnum_amount; \
1200071d4279SBram Moolenaar 	    if (col_amount < 0 && posp->col <= (colnr_T)-col_amount) \
1201071d4279SBram Moolenaar 		posp->col = 0; \
1202e1e714efSBram Moolenaar 	    else if (posp->col < spaces_removed) \
1203e1e714efSBram Moolenaar 		posp->col = col_amount + spaces_removed; \
1204071d4279SBram Moolenaar 	    else \
1205071d4279SBram Moolenaar 		posp->col += col_amount; \
1206071d4279SBram Moolenaar 	} \
1207071d4279SBram Moolenaar     }
1208071d4279SBram Moolenaar 
1209071d4279SBram Moolenaar /*
1210071d4279SBram Moolenaar  * Adjust marks in line "lnum" at column "mincol" and further: add
1211071d4279SBram Moolenaar  * "lnum_amount" to the line number and add "col_amount" to the column
1212071d4279SBram Moolenaar  * position.
1213e1e714efSBram Moolenaar  * "spaces_removed" is the number of spaces that were removed, matters when the
1214e1e714efSBram Moolenaar  * cursor is inside them.
1215071d4279SBram Moolenaar  */
1216071d4279SBram Moolenaar     void
mark_col_adjust(linenr_T lnum,colnr_T mincol,long lnum_amount,long col_amount,int spaces_removed)121752ea13daSBram Moolenaar mark_col_adjust(
121852ea13daSBram Moolenaar     linenr_T	lnum,
121952ea13daSBram Moolenaar     colnr_T	mincol,
122052ea13daSBram Moolenaar     long	lnum_amount,
1221e1e714efSBram Moolenaar     long	col_amount,
1222e1e714efSBram Moolenaar     int		spaces_removed)
1223071d4279SBram Moolenaar {
1224071d4279SBram Moolenaar     int		i;
1225071d4279SBram Moolenaar     int		fnum = curbuf->b_fnum;
1226071d4279SBram Moolenaar     win_T	*win;
1227071d4279SBram Moolenaar     pos_T	*posp;
1228071d4279SBram Moolenaar 
1229e1004401SBram Moolenaar     if ((col_amount == 0L && lnum_amount == 0L)
1230e1004401SBram Moolenaar 				       || (cmdmod.cmod_flags & CMOD_LOCKMARKS))
12314ba37b58SBram Moolenaar 	return; // nothing to do
1232071d4279SBram Moolenaar 
12334ba37b58SBram Moolenaar     // named marks, lower case and upper case
1234071d4279SBram Moolenaar     for (i = 0; i < NMARKS; i++)
1235071d4279SBram Moolenaar     {
1236071d4279SBram Moolenaar 	col_adjust(&(curbuf->b_namedm[i]));
1237071d4279SBram Moolenaar 	if (namedfm[i].fmark.fnum == fnum)
1238071d4279SBram Moolenaar 	    col_adjust(&(namedfm[i].fmark.mark));
1239071d4279SBram Moolenaar     }
1240071d4279SBram Moolenaar     for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
1241071d4279SBram Moolenaar     {
1242071d4279SBram Moolenaar 	if (namedfm[i].fmark.fnum == fnum)
1243071d4279SBram Moolenaar 	    col_adjust(&(namedfm[i].fmark.mark));
1244071d4279SBram Moolenaar     }
1245071d4279SBram Moolenaar 
12464ba37b58SBram Moolenaar     // last Insert position
1247071d4279SBram Moolenaar     col_adjust(&(curbuf->b_last_insert));
1248071d4279SBram Moolenaar 
12494ba37b58SBram Moolenaar     // last change position
1250071d4279SBram Moolenaar     col_adjust(&(curbuf->b_last_change));
1251071d4279SBram Moolenaar 
1252071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
12534ba37b58SBram Moolenaar     // list of change positions
1254071d4279SBram Moolenaar     for (i = 0; i < curbuf->b_changelistlen; ++i)
1255071d4279SBram Moolenaar 	col_adjust(&(curbuf->b_changelist[i]));
1256071d4279SBram Moolenaar #endif
1257071d4279SBram Moolenaar 
12584ba37b58SBram Moolenaar     // Visual area
1259a226a6ddSBram Moolenaar     col_adjust(&(curbuf->b_visual.vi_start));
1260a226a6ddSBram Moolenaar     col_adjust(&(curbuf->b_visual.vi_end));
1261071d4279SBram Moolenaar 
12624ba37b58SBram Moolenaar     // previous context mark
1263071d4279SBram Moolenaar     col_adjust(&(curwin->w_pcmark));
1264071d4279SBram Moolenaar 
12654ba37b58SBram Moolenaar     // previous pcmark
1266071d4279SBram Moolenaar     col_adjust(&(curwin->w_prev_pcmark));
1267071d4279SBram Moolenaar 
12684ba37b58SBram Moolenaar     // saved cursor for formatting
1269071d4279SBram Moolenaar     col_adjust(&saved_cursor);
1270071d4279SBram Moolenaar 
1271071d4279SBram Moolenaar     /*
1272071d4279SBram Moolenaar      * Adjust items in all windows related to the current buffer.
1273071d4279SBram Moolenaar      */
1274071d4279SBram Moolenaar     FOR_ALL_WINDOWS(win)
1275071d4279SBram Moolenaar     {
1276071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
12774ba37b58SBram Moolenaar 	// marks in the jumplist
1278071d4279SBram Moolenaar 	for (i = 0; i < win->w_jumplistlen; ++i)
1279071d4279SBram Moolenaar 	    if (win->w_jumplist[i].fmark.fnum == fnum)
1280071d4279SBram Moolenaar 		col_adjust(&(win->w_jumplist[i].fmark.mark));
1281071d4279SBram Moolenaar #endif
1282071d4279SBram Moolenaar 
1283071d4279SBram Moolenaar 	if (win->w_buffer == curbuf)
1284071d4279SBram Moolenaar 	{
12854ba37b58SBram Moolenaar 	    // marks in the tag stack
1286071d4279SBram Moolenaar 	    for (i = 0; i < win->w_tagstacklen; i++)
1287071d4279SBram Moolenaar 		if (win->w_tagstack[i].fmark.fnum == fnum)
1288071d4279SBram Moolenaar 		    col_adjust(&(win->w_tagstack[i].fmark.mark));
1289071d4279SBram Moolenaar 
12904ba37b58SBram Moolenaar 	    // cursor position for other windows with the same buffer
1291071d4279SBram Moolenaar 	    if (win != curwin)
1292071d4279SBram Moolenaar 		col_adjust(&win->w_cursor);
1293071d4279SBram Moolenaar 	}
1294071d4279SBram Moolenaar     }
1295071d4279SBram Moolenaar }
1296071d4279SBram Moolenaar 
1297071d4279SBram Moolenaar #ifdef FEAT_JUMPLIST
1298071d4279SBram Moolenaar /*
1299071d4279SBram Moolenaar  * When deleting lines, this may create duplicate marks in the
1300a7e18d23SBram Moolenaar  * jumplist. They will be removed here for the specified window.
130148679741SBram Moolenaar  * When "loadfiles" is TRUE first ensure entries have the "fnum" field set
130248679741SBram Moolenaar  * (this may be a bit slow).
1303071d4279SBram Moolenaar  */
1304a7e18d23SBram Moolenaar     void
cleanup_jumplist(win_T * wp,int loadfiles)130548679741SBram Moolenaar cleanup_jumplist(win_T *wp, int loadfiles)
1306071d4279SBram Moolenaar {
1307071d4279SBram Moolenaar     int	    i;
1308071d4279SBram Moolenaar     int	    from, to;
1309071d4279SBram Moolenaar 
131048679741SBram Moolenaar     if (loadfiles)
131148679741SBram Moolenaar     {
13124ba37b58SBram Moolenaar 	// If specified, load all the files from the jump list. This is
13134ba37b58SBram Moolenaar 	// needed to properly clean up duplicate entries, but will take some
13144ba37b58SBram Moolenaar 	// time.
131548679741SBram Moolenaar 	for (i = 0; i < wp->w_jumplistlen; ++i)
131648679741SBram Moolenaar 	{
131748679741SBram Moolenaar 	    if ((wp->w_jumplist[i].fmark.fnum == 0) &&
131848679741SBram Moolenaar 		    (wp->w_jumplist[i].fmark.mark.lnum != 0))
131948679741SBram Moolenaar 		fname2fnum(&wp->w_jumplist[i]);
132048679741SBram Moolenaar 	}
132148679741SBram Moolenaar     }
132248679741SBram Moolenaar 
1323071d4279SBram Moolenaar     to = 0;
1324a7e18d23SBram Moolenaar     for (from = 0; from < wp->w_jumplistlen; ++from)
1325071d4279SBram Moolenaar     {
1326a7e18d23SBram Moolenaar 	if (wp->w_jumplistidx == from)
1327a7e18d23SBram Moolenaar 	    wp->w_jumplistidx = to;
1328a7e18d23SBram Moolenaar 	for (i = from + 1; i < wp->w_jumplistlen; ++i)
1329a7e18d23SBram Moolenaar 	    if (wp->w_jumplist[i].fmark.fnum
1330a7e18d23SBram Moolenaar 					== wp->w_jumplist[from].fmark.fnum
1331a7e18d23SBram Moolenaar 		    && wp->w_jumplist[from].fmark.fnum != 0
1332a7e18d23SBram Moolenaar 		    && wp->w_jumplist[i].fmark.mark.lnum
1333a7e18d23SBram Moolenaar 				  == wp->w_jumplist[from].fmark.mark.lnum)
1334071d4279SBram Moolenaar 		break;
13354ba37b58SBram Moolenaar 	if (i >= wp->w_jumplistlen)	    // no duplicate
1336a7e18d23SBram Moolenaar 	    wp->w_jumplist[to++] = wp->w_jumplist[from];
1337071d4279SBram Moolenaar 	else
1338a7e18d23SBram Moolenaar 	    vim_free(wp->w_jumplist[from].fname);
1339071d4279SBram Moolenaar     }
1340a7e18d23SBram Moolenaar     if (wp->w_jumplistidx == wp->w_jumplistlen)
1341a7e18d23SBram Moolenaar 	wp->w_jumplistidx = to;
1342a7e18d23SBram Moolenaar     wp->w_jumplistlen = to;
1343071d4279SBram Moolenaar }
1344071d4279SBram Moolenaar 
1345071d4279SBram Moolenaar /*
1346071d4279SBram Moolenaar  * Copy the jumplist from window "from" to window "to".
1347071d4279SBram Moolenaar  */
1348071d4279SBram Moolenaar     void
copy_jumplist(win_T * from,win_T * to)134952ea13daSBram Moolenaar copy_jumplist(win_T *from, win_T *to)
1350071d4279SBram Moolenaar {
1351071d4279SBram Moolenaar     int		i;
1352071d4279SBram Moolenaar 
1353071d4279SBram Moolenaar     for (i = 0; i < from->w_jumplistlen; ++i)
1354071d4279SBram Moolenaar     {
1355071d4279SBram Moolenaar 	to->w_jumplist[i] = from->w_jumplist[i];
1356071d4279SBram Moolenaar 	if (from->w_jumplist[i].fname != NULL)
1357071d4279SBram Moolenaar 	    to->w_jumplist[i].fname = vim_strsave(from->w_jumplist[i].fname);
1358071d4279SBram Moolenaar     }
1359071d4279SBram Moolenaar     to->w_jumplistlen = from->w_jumplistlen;
1360071d4279SBram Moolenaar     to->w_jumplistidx = from->w_jumplistidx;
1361071d4279SBram Moolenaar }
1362071d4279SBram Moolenaar 
1363071d4279SBram Moolenaar /*
1364071d4279SBram Moolenaar  * Free items in the jumplist of window "wp".
1365071d4279SBram Moolenaar  */
1366071d4279SBram Moolenaar     void
free_jumplist(win_T * wp)136752ea13daSBram Moolenaar free_jumplist(win_T *wp)
1368071d4279SBram Moolenaar {
1369071d4279SBram Moolenaar     int		i;
1370071d4279SBram Moolenaar 
1371071d4279SBram Moolenaar     for (i = 0; i < wp->w_jumplistlen; ++i)
1372071d4279SBram Moolenaar 	vim_free(wp->w_jumplist[i].fname);
1373071d4279SBram Moolenaar }
13744ba37b58SBram Moolenaar #endif // FEAT_JUMPLIST
1375071d4279SBram Moolenaar 
1376071d4279SBram Moolenaar     void
set_last_cursor(win_T * win)137752ea13daSBram Moolenaar set_last_cursor(win_T *win)
1378071d4279SBram Moolenaar {
13799db12933SBram Moolenaar     if (win->w_buffer != NULL)
1380071d4279SBram Moolenaar 	win->w_buffer->b_last_cursor = win->w_cursor;
1381071d4279SBram Moolenaar }
1382071d4279SBram Moolenaar 
1383ea408854SBram Moolenaar #if defined(EXITFREE) || defined(PROTO)
1384ea408854SBram Moolenaar     void
free_all_marks(void)138552ea13daSBram Moolenaar free_all_marks(void)
1386ea408854SBram Moolenaar {
1387ea408854SBram Moolenaar     int		i;
1388ea408854SBram Moolenaar 
1389ea408854SBram Moolenaar     for (i = 0; i < NMARKS + EXTRA_MARKS; i++)
1390ea408854SBram Moolenaar 	if (namedfm[i].fmark.mark.lnum != 0)
1391ea408854SBram Moolenaar 	    vim_free(namedfm[i].fname);
1392ea408854SBram Moolenaar }
1393ea408854SBram Moolenaar #endif
1394ea408854SBram Moolenaar 
13952d358997SBram Moolenaar /*
13961e78e696SBram Moolenaar  * Return a pointer to the named file marks.
13972d358997SBram Moolenaar  */
13981e78e696SBram Moolenaar     xfmark_T *
get_namedfm(void)13991e78e696SBram Moolenaar get_namedfm(void)
14002d358997SBram Moolenaar {
14011e78e696SBram Moolenaar     return namedfm;
1402071d4279SBram Moolenaar }
1403cfb4b47dSBram Moolenaar 
1404cfb4b47dSBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
1405cfb4b47dSBram Moolenaar /*
1406cfb4b47dSBram Moolenaar  * Add information about mark 'mname' to list 'l'
1407cfb4b47dSBram Moolenaar  */
1408cfb4b47dSBram Moolenaar     static int
add_mark(list_T * l,char_u * mname,pos_T * pos,int bufnr,char_u * fname)1409cfb4b47dSBram Moolenaar add_mark(list_T *l, char_u *mname, pos_T *pos, int bufnr, char_u *fname)
1410cfb4b47dSBram Moolenaar {
1411cfb4b47dSBram Moolenaar     dict_T	*d;
1412cfb4b47dSBram Moolenaar     list_T	*lpos;
1413cfb4b47dSBram Moolenaar 
1414cfb4b47dSBram Moolenaar     if (pos->lnum <= 0)
1415cfb4b47dSBram Moolenaar 	return OK;
1416cfb4b47dSBram Moolenaar 
1417cfb4b47dSBram Moolenaar     d = dict_alloc();
1418cfb4b47dSBram Moolenaar     if (d == NULL)
1419cfb4b47dSBram Moolenaar 	return FAIL;
1420cfb4b47dSBram Moolenaar 
1421cfb4b47dSBram Moolenaar     if (list_append_dict(l, d) == FAIL)
1422cfb4b47dSBram Moolenaar     {
1423cfb4b47dSBram Moolenaar 	dict_unref(d);
1424cfb4b47dSBram Moolenaar 	return FAIL;
1425cfb4b47dSBram Moolenaar     }
1426cfb4b47dSBram Moolenaar 
1427cfb4b47dSBram Moolenaar     lpos = list_alloc();
1428cfb4b47dSBram Moolenaar     if (lpos == NULL)
1429cfb4b47dSBram Moolenaar 	return FAIL;
1430cfb4b47dSBram Moolenaar 
1431cfb4b47dSBram Moolenaar     list_append_number(lpos, bufnr);
1432cfb4b47dSBram Moolenaar     list_append_number(lpos, pos->lnum);
1433f17e7ea6SBram Moolenaar     list_append_number(lpos, pos->col + 1);
1434cfb4b47dSBram Moolenaar     list_append_number(lpos, pos->coladd);
1435cfb4b47dSBram Moolenaar 
1436cfb4b47dSBram Moolenaar     if (dict_add_string(d, "mark", mname) == FAIL
1437cfb4b47dSBram Moolenaar 	    || dict_add_list(d, "pos", lpos) == FAIL
1438cfb4b47dSBram Moolenaar 	    || (fname != NULL && dict_add_string(d, "file", fname) == FAIL))
1439cfb4b47dSBram Moolenaar 	return FAIL;
1440cfb4b47dSBram Moolenaar 
1441cfb4b47dSBram Moolenaar     return OK;
1442cfb4b47dSBram Moolenaar }
1443cfb4b47dSBram Moolenaar 
1444cfb4b47dSBram Moolenaar /*
1445cfb4b47dSBram Moolenaar  * Get information about marks local to a buffer.
1446cfb4b47dSBram Moolenaar  */
1447cfb4b47dSBram Moolenaar     static void
get_buf_local_marks(buf_T * buf,list_T * l)1448cfb4b47dSBram Moolenaar get_buf_local_marks(buf_T *buf, list_T *l)
1449cfb4b47dSBram Moolenaar {
1450cfb4b47dSBram Moolenaar     char_u	mname[3] = "' ";
1451cfb4b47dSBram Moolenaar     int		i;
1452cfb4b47dSBram Moolenaar 
1453cfb4b47dSBram Moolenaar     // Marks 'a' to 'z'
1454cfb4b47dSBram Moolenaar     for (i = 0; i < NMARKS; ++i)
1455cfb4b47dSBram Moolenaar     {
1456cfb4b47dSBram Moolenaar 	mname[1] = 'a' + i;
1457cfb4b47dSBram Moolenaar 	add_mark(l, mname, &buf->b_namedm[i], buf->b_fnum, NULL);
1458cfb4b47dSBram Moolenaar     }
1459cfb4b47dSBram Moolenaar 
1460cfb4b47dSBram Moolenaar     // Mark '' is a window local mark and not a buffer local mark
1461cfb4b47dSBram Moolenaar     add_mark(l, (char_u *)"''", &curwin->w_pcmark, curbuf->b_fnum, NULL);
1462cfb4b47dSBram Moolenaar 
1463cfb4b47dSBram Moolenaar     add_mark(l, (char_u *)"'\"", &buf->b_last_cursor, buf->b_fnum, NULL);
1464cfb4b47dSBram Moolenaar     add_mark(l, (char_u *)"'[", &buf->b_op_start, buf->b_fnum, NULL);
1465cfb4b47dSBram Moolenaar     add_mark(l, (char_u *)"']", &buf->b_op_end, buf->b_fnum, NULL);
1466cfb4b47dSBram Moolenaar     add_mark(l, (char_u *)"'^", &buf->b_last_insert, buf->b_fnum, NULL);
1467cfb4b47dSBram Moolenaar     add_mark(l, (char_u *)"'.", &buf->b_last_change, buf->b_fnum, NULL);
1468cfb4b47dSBram Moolenaar     add_mark(l, (char_u *)"'<", &buf->b_visual.vi_start, buf->b_fnum, NULL);
1469cfb4b47dSBram Moolenaar     add_mark(l, (char_u *)"'>", &buf->b_visual.vi_end, buf->b_fnum, NULL);
1470cfb4b47dSBram Moolenaar }
1471cfb4b47dSBram Moolenaar 
1472cfb4b47dSBram Moolenaar /*
1473cfb4b47dSBram Moolenaar  * Get information about global marks ('A' to 'Z' and '0' to '9')
1474cfb4b47dSBram Moolenaar  */
1475cfb4b47dSBram Moolenaar     static void
get_global_marks(list_T * l)1476cfb4b47dSBram Moolenaar get_global_marks(list_T *l)
1477cfb4b47dSBram Moolenaar {
1478cfb4b47dSBram Moolenaar     char_u	mname[3] = "' ";
1479cfb4b47dSBram Moolenaar     int		i;
1480cfb4b47dSBram Moolenaar     char_u	*name;
1481cfb4b47dSBram Moolenaar 
1482cfb4b47dSBram Moolenaar     // Marks 'A' to 'Z' and '0' to '9'
1483cfb4b47dSBram Moolenaar     for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
1484cfb4b47dSBram Moolenaar     {
1485cfb4b47dSBram Moolenaar 	if (namedfm[i].fmark.fnum != 0)
1486cfb4b47dSBram Moolenaar 	    name = buflist_nr2name(namedfm[i].fmark.fnum, TRUE, TRUE);
1487cfb4b47dSBram Moolenaar 	else
1488cfb4b47dSBram Moolenaar 	    name = namedfm[i].fname;
1489cfb4b47dSBram Moolenaar 	if (name != NULL)
1490cfb4b47dSBram Moolenaar 	{
1491cfb4b47dSBram Moolenaar 	    mname[1] = i >= NMARKS ? i - NMARKS + '0' : i + 'A';
1492cfb4b47dSBram Moolenaar 	    add_mark(l, mname, &namedfm[i].fmark.mark,
1493cfb4b47dSBram Moolenaar 		    namedfm[i].fmark.fnum, name);
1494cfb4b47dSBram Moolenaar 	    if (namedfm[i].fmark.fnum != 0)
1495cfb4b47dSBram Moolenaar 		vim_free(name);
1496cfb4b47dSBram Moolenaar 	}
1497cfb4b47dSBram Moolenaar     }
1498cfb4b47dSBram Moolenaar }
1499cfb4b47dSBram Moolenaar 
1500cfb4b47dSBram Moolenaar /*
1501cfb4b47dSBram Moolenaar  * getmarklist() function
1502cfb4b47dSBram Moolenaar  */
1503cfb4b47dSBram Moolenaar     void
f_getmarklist(typval_T * argvars,typval_T * rettv)1504cfb4b47dSBram Moolenaar f_getmarklist(typval_T *argvars, typval_T *rettv)
1505cfb4b47dSBram Moolenaar {
1506cfb4b47dSBram Moolenaar     buf_T	*buf = NULL;
1507cfb4b47dSBram Moolenaar 
1508cfb4b47dSBram Moolenaar     if (rettv_list_alloc(rettv) != OK)
1509cfb4b47dSBram Moolenaar 	return;
1510cfb4b47dSBram Moolenaar 
15114490ec4eSYegappan Lakshmanan     if (in_vim9script() && check_for_opt_buffer_arg(argvars, 0) == FAIL)
15124490ec4eSYegappan Lakshmanan 	return;
15134490ec4eSYegappan Lakshmanan 
1514cfb4b47dSBram Moolenaar     if (argvars[0].v_type == VAR_UNKNOWN)
1515cfb4b47dSBram Moolenaar     {
1516cfb4b47dSBram Moolenaar 	get_global_marks(rettv->vval.v_list);
1517cfb4b47dSBram Moolenaar 	return;
1518cfb4b47dSBram Moolenaar     }
1519cfb4b47dSBram Moolenaar 
1520cfb4b47dSBram Moolenaar     buf = tv_get_buf(&argvars[0], FALSE);
1521cfb4b47dSBram Moolenaar     if (buf == NULL)
1522cfb4b47dSBram Moolenaar 	return;
1523cfb4b47dSBram Moolenaar 
1524cfb4b47dSBram Moolenaar     get_buf_local_marks(buf, rettv->vval.v_list);
1525cfb4b47dSBram Moolenaar }
1526cfb4b47dSBram Moolenaar #endif
1527