I don't know if this will help you with a hotfix, but here is the code I wrote to rotate and shift the bookmark stack to address problem #1. It's hot off the presses, and may have bugs, but in simple smoke tests it is working for me so far. It's not as elegant as I'd like, but it's a starting point, at least.
/**
* Ideally this would be a built in function that simply renames the bookmark.
* Until such a function is available, this attempts to achieve the effect of
* renaming a bookmark by getting its information, deleting it, and creating a
* new bookmark.
*
* @param old_name Name of existing pushed bookmark.
* @param new_name New name for the pushed bookmark.
*
* @return int 0 on success, or non-zero on failure.
*/
static int RenamePushedBookmark(_str old_name, _str new_name)
{
if (old_name :== new_name) {
return 0;
}
// bookmark attributes
bm_name := '';
bm_mark := 0;
bm_flags := 0;
bm_bufid := 0;
bm_line := 0;
bm_rline := 0;
bm_col := 0;
bm_rpos := 0;
bm_data := '';
bm_file := '';
bm_docname := '';
// get old bookmark
int k = _BookmarkFind(old_name, VSBMFLAG_PUSHED);
if (k < 0) {
return -1;
}
_BookmarkGetInfo(k, bm_name, bm_mark, bm_flags, bm_bufid,
bm_line, bm_rline, bm_col, bm_rpos, bm_data,
bm_file, bm_docname);
if (bm_bufid < 0) {
return -1;
}
// remove the existing bookmark, but pass 0 to avoid freeing bm_mark
_BookmarkRemove(k, 0);
// create a new bookmark
int temp_view_id;
int orig_view_id;
int status = _open_temp_view('', temp_view_id, orig_view_id, '+bi 'bm_bufid);
_BookmarkAdd(new_name, bm_mark, bm_flags, bm_rline, bm_col, bm_rpos, bm_data, bm_file, bm_docname);
_delete_temp_view(temp_view_id);
activate_window(orig_view_id);
return 0;
}
/**
* Gets called when a buffer is closed.
* This function is used to clean up pushed bookmarks from
* the bookmark stack when a file is closed by the user.
*
* @param buffid p_buf_id of the buffer that was closed
* @param name p_buf_name of the buffer that was closed
* @param docname p_DocumentName of the buffer that was closed
* @param flags assumed to be 0
*/
void _cbquit_bookmarks(int buffid, _str name, _str docname='', int flags=0)
{
// is this option turned off?
if (!def_cleanup_pushed_bookmarks_on_quit) {
return;
}
// bookmark attributes
bm_name := '';
bm_mark := 0;
bm_flags := 0;
bm_bufid := 0;
bm_line := 0;
bm_rline := 0;
bm_col := 0;
bm_rpos := 0;
bm_data := '';
bm_file := '';
bm_docname := '';
bm_msg := get_message(VSRC_PUSHED_BOOKMARK_NAME);
if (bm_msg=='') bm_msg="TAG";
int arrayBookmarkNums[];
int highestBookmarkNum = 0;
boolean isCondenseNeeded=false;
// check each bookmark if it matches the buffer being quit
n := _BookmarkQCount();
for (i:=n-1; i>=0; --i) {
_BookmarkGetInfo(i, bm_name, bm_mark, bm_flags, bm_bufid,
bm_line, bm_rline, bm_col, bm_rpos, bm_data,
bm_file, bm_docname);
if (!(bm_flags & VSBMFLAG_PUSHED)) {
continue;
}
boolean isPushedName = (pos(bm_msg, bm_name) == 1 && pos('^\:i$', substr(bm_name, length(bm_msg) + 1), 1, 'U'));
if (bm_bufid == buffid) {
_BookmarkRemove(i);
if (isPushedName) {
isCondenseNeeded = true;
}
} else if (isPushedName) {
// make an array out of the bookmark stack, so we can condense it
int bmNum = (int)substr(bm_name, length(bm_msg) + pos('S'));
arrayBookmarkNums[arrayBookmarkNums._length()]=bmNum;
if (highestBookmarkNum < bmNum) {
highestBookmarkNum = bmNum;
}
}
}
// Condense the bookmark stack if any bookmarks were removed from it. The
// circular stack will be rotated and shifted so that the first bookmark is
// named 1, and _bm_number-1 (before wrap around) is the highest bookmark.
if (isCondenseNeeded) {
// First move any bookmarks lower than _bm_number to be greater. This
// effectively rotates the circular stack, but does not yet shift it.
int ii;
arrayBookmarkNums._sort('N');
for (ii = 0; ii < arrayBookmarkNums._length(); ii++) {
if (arrayBookmarkNums[ii] < _bm_number) {
RenamePushedBookmark(bm_msg :+ arrayBookmarkNums[ii],
bm_msg :+ (arrayBookmarkNums[ii] + highestBookmarkNum + 1));
}
}
// Defer rotating arrayBookmarkNums until the stack has been rotated.
// Otherwise it is hard to keep track of what remains to be rotated.
for (ii = arrayBookmarkNums._length(); ii--;) {
if (arrayBookmarkNums[ii] < _bm_number) {
arrayBookmarkNums[arrayBookmarkNums._length()] = arrayBookmarkNums[ii] + highestBookmarkNum + 1;
arrayBookmarkNums._deleteel(ii);
}
}
// Then shift the bookmark stack to start at 1, and set _bm_number to
// the number after the highest bookmark (wrapping around to 1 if
// necessary).
arrayBookmarkNums._sort('N');
for (ii = 0; ii < arrayBookmarkNums._length(); ii++) {
RenamePushedBookmark(bm_msg :+ arrayBookmarkNums[ii],
bm_msg :+ (ii + 1));
}
_bm_number = arrayBookmarkNums._length() + 1;
if (_bm_number > def_max_bm_tags) {
_bm_number = 1;
}
}
}
EDIT: Oops, had neglected to wrap _bm_number if there were exactly def_max_bm_tags pushed bookmarks.