diff options
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/src/buffer.c b/src/buffer.c index 90f965f42d..4486611540 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -91,6 +91,7 @@ static void clear_wininfo(buf_T *buf); # define dev_T unsigned #endif +static void insert_sign(buf_T *buf, signlist_T *prev, signlist_T *next, int id, linenr_T lnum, int typenr); static char *msg_loclist = N_("[Location List]"); static char *msg_qflist = N_("[Quickfix List]"); @@ -568,6 +569,7 @@ free_buffer_stuff ( vars_clear(&buf->b_vars->dv_hashtab); /* free all internal variables */ hash_init(&buf->b_vars->dv_hashtab); uc_clear(&buf->b_ucmds); /* clear local user commands */ + buf_delete_signs(buf); /* delete any signs */ map_clear_int(buf, MAP_ALL_MODES, TRUE, FALSE); /* clear local mappings */ map_clear_int(buf, MAP_ALL_MODES, TRUE, TRUE); /* clear local abbrevs */ vim_free(buf->b_start_fenc); @@ -4410,6 +4412,273 @@ win_found: } #endif +/* + * Insert the sign into the signlist. + */ +static void insert_sign( + buf_T *buf, /* buffer to store sign in */ + signlist_T *prev, /* previous sign entry */ + signlist_T *next, /* next sign entry */ + int id, /* sign ID */ + linenr_T lnum, /* line number which gets the mark */ + int typenr /* typenr of sign we are adding */ + ) +{ + signlist_T *newsign; + + newsign = (signlist_T *)lalloc((long_u)sizeof(signlist_T), FALSE); + if (newsign != NULL) { + newsign->id = id; + newsign->lnum = lnum; + newsign->typenr = typenr; + newsign->next = next; + + if (prev == NULL) { + /* When adding first sign need to redraw the windows to create the + * column for signs. */ + if (buf->b_signlist == NULL) { + redraw_buf_later(buf, NOT_VALID); + changed_cline_bef_curs(); + } + + /* first sign in signlist */ + buf->b_signlist = newsign; + } + else { + prev->next = newsign; + } + } +} + +/* + * Add the sign into the signlist. Find the right spot to do it though. + */ +void buf_addsign( + buf_T *buf, /* buffer to store sign in */ + int id, /* sign ID */ + linenr_T lnum, /* line number which gets the mark */ + int typenr /* typenr of sign we are adding */ + ) +{ + signlist_T *sign; /* a sign in the signlist */ + signlist_T *prev; /* the previous sign */ + + prev = NULL; + for (sign = buf->b_signlist; sign != NULL; sign = sign->next) { + if (lnum == sign->lnum && id == sign->id) { + sign->typenr = typenr; + return; + } + else if (id < 0 /* keep signs sorted by lnum */ + && lnum < sign->lnum) + { + insert_sign(buf, prev, sign, id, lnum, typenr); + return; + } + prev = sign; + } + insert_sign(buf, prev, sign, id, lnum, typenr); + + return; +} + +linenr_T buf_change_sign_type( + buf_T *buf, /* buffer to store sign in */ + int markId, /* sign ID */ + int typenr /* typenr of sign we are adding */ + ) +{ + signlist_T *sign; /* a sign in the signlist */ + + for (sign = buf->b_signlist; sign != NULL; sign = sign->next) { + if (sign->id == markId) { + sign->typenr = typenr; + return sign->lnum; + } + } + + return (linenr_T)0; +} + +int buf_getsigntype( + buf_T *buf, + linenr_T lnum, + int type /* SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL */ + ) +{ + signlist_T *sign; /* a sign in a b_signlist */ + + for (sign = buf->b_signlist; sign != NULL; sign = sign->next) { + if (sign->lnum == lnum + && (type == SIGN_ANY + || (type == SIGN_TEXT + && sign_get_text(sign->typenr) != NULL) + || (type == SIGN_LINEHL + && sign_get_attr(sign->typenr, TRUE) != 0))) { + return sign->typenr; + } + } + return 0; +} + + +linenr_T buf_delsign( + buf_T *buf, /* buffer sign is stored in */ + int id /* sign id */ + ) +{ + signlist_T **lastp; /* pointer to pointer to current sign */ + signlist_T *sign; /* a sign in a b_signlist */ + signlist_T *next; /* the next sign in a b_signlist */ + linenr_T lnum; /* line number whose sign was deleted */ + + lastp = &buf->b_signlist; + lnum = 0; + for (sign = buf->b_signlist; sign != NULL; sign = next) { + next = sign->next; + if (sign->id == id) { + *lastp = next; + lnum = sign->lnum; + vim_free(sign); + break; + } else { + lastp = &sign->next; + } + } + + /* When deleted the last sign needs to redraw the windows to remove the + * sign column. */ + if (buf->b_signlist == NULL) { + redraw_buf_later(buf, NOT_VALID); + changed_cline_bef_curs(); + } + + return lnum; +} + + +/* + * Find the line number of the sign with the requested id. If the sign does + * not exist, return 0 as the line number. This will still let the correct file + * get loaded. + */ +int buf_findsign( + buf_T *buf, /* buffer to store sign in */ + int id /* sign ID */ + ) +{ + signlist_T *sign; /* a sign in the signlist */ + + for (sign = buf->b_signlist; sign != NULL; sign = sign->next) { + if (sign->id == id) { + return sign->lnum; + } + } + + return 0; +} + +int buf_findsign_id( + buf_T *buf, /* buffer whose sign we are searching for */ + linenr_T lnum /* line number of sign */ + ) +{ + signlist_T *sign; /* a sign in the signlist */ + + for (sign = buf->b_signlist; sign != NULL; sign = sign->next) { + if (sign->lnum == lnum) { + return sign->id; + } + } + + return 0; +} + + +/* + * Delete signs in buffer "buf". + */ +void buf_delete_signs(buf_T *buf) +{ + signlist_T *next; + + while (buf->b_signlist != NULL) { + next = buf->b_signlist->next; + vim_free(buf->b_signlist); + buf->b_signlist = next; + } +} + +/* + * Delete all signs in all buffers. + */ +void buf_delete_all_signs() +{ + buf_T *buf; /* buffer we are checking for signs */ + + for (buf = firstbuf; buf != NULL; buf = buf->b_next) { + if (buf->b_signlist != NULL) { + /* Need to redraw the windows to remove the sign column. */ + redraw_buf_later(buf, NOT_VALID); + buf_delete_signs(buf); + } + } +} + +/* + * List placed signs for "rbuf". If "rbuf" is NULL do it for all buffers. + */ +void sign_list_placed(buf_T *rbuf) +{ + buf_T *buf; + signlist_T *p; + char lbuf[BUFSIZ]; + + MSG_PUTS_TITLE(_("\n--- Signs ---")); + msg_putchar('\n'); + if (rbuf == NULL) { + buf = firstbuf; + } else { + buf = rbuf; + } + while (buf != NULL && !got_int) { + if (buf->b_signlist != NULL) { + vim_snprintf(lbuf, BUFSIZ, _("Signs for %s:"), buf->b_fname); + MSG_PUTS_ATTR(lbuf, hl_attr(HLF_D)); + msg_putchar('\n'); + } + for (p = buf->b_signlist; p != NULL && !got_int; p = p->next) { + vim_snprintf(lbuf, BUFSIZ, _(" line=%ld id=%d name=%s"), + (long)p->lnum, p->id, sign_typenr2name(p->typenr)); + MSG_PUTS(lbuf); + msg_putchar('\n'); + } + if (rbuf != NULL) { + break; + } + buf = buf->b_next; + } +} + +/* + * Adjust a placed sign for inserted/deleted lines. + */ +void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) +{ + signlist_T *sign; /* a sign in a b_signlist */ + + for (sign = curbuf->b_signlist; sign != NULL; sign = sign->next) { + if (sign->lnum >= line1 && sign->lnum <= line2) { + if (amount == MAXLNUM) { + sign->lnum = line1; + } else { + sign->lnum += amount; + } + } + else if (sign->lnum > line2) + sign->lnum += amount_after; + } +} /* * Set 'buflisted' for curbuf to "on" and trigger autocommands if it changed. |