patch 9.0.1921: not possible to use the jumplist like a stack

Problem:  not possible to use the jumplist like a stack
Solution: Add the 'jumpoptions' setting to make the jumplist
          a stack.

Add an option for using jumplist like tag stack

related: #7738
closes: #13134

ported from NeoVim:

- https://neovim.io/doc/user/motion.html#jumplist-stack
- neovim/neovim@39094b3
- neovim/neovim#11530
- https://vi.stackexchange.com/questions/18344/how-to-change-jumplist-behavior

Based on the feedback in the previous PR, it looks like many people like
this option.

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Co-authored-by: butwerenotthereyet <58348703+butwerenotthereyet@users.noreply.github.com>
diff --git a/src/mark.c b/src/mark.c
index b3c644b..22e3c62 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -146,6 +146,16 @@
     curwin->w_prev_pcmark = curwin->w_pcmark;
     curwin->w_pcmark = curwin->w_cursor;
 
+    if (jop_flags & JOP_STACK)
+    {
+	// jumpoptions=stack: if we're somewhere in the middle of the jumplist
+	// discard everything after the current index.
+	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;
+    }
+
     // If jumplist is full: remove oldest entry
     if (++curwin->w_jumplistlen > JUMPLISTSIZE)
     {
@@ -1288,6 +1298,7 @@
 {
     int	    i;
     int	    from, to;
+    int	    mustfree;
 
     if (loadfiles)
     {
@@ -1314,10 +1325,18 @@
 		    && wp->w_jumplist[i].fmark.mark.lnum
 				  == wp->w_jumplist[from].fmark.mark.lnum)
 		break;
-	if (i >= wp->w_jumplistlen)	    // no duplicate
-	    wp->w_jumplist[to++] = wp->w_jumplist[from];
-	else
+	if (i >= wp->w_jumplistlen)	// not duplicate
+	    mustfree = FALSE;
+	else if (i > from + 1)		// non-adjacent duplicate
+	    // jumpoptions=stack: remove duplicates only when adjacent.
+	    mustfree = !(jop_flags & JOP_STACK);
+	else				// adjacent duplicate
+	    mustfree = TRUE;
+
+	if (mustfree)
 	    vim_free(wp->w_jumplist[from].fname);
+	else
+	    wp->w_jumplist[to++] = wp->w_jumplist[from];
     }
     if (wp->w_jumplistidx == wp->w_jumplistlen)
 	wp->w_jumplistidx = to;