summaryrefslogtreecommitdiff
path: root/Src/Zle/zle_utils.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2011-02-18 22:08:45 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2011-02-18 22:08:45 +0000
commit212ca9edf9c2be0499cdce39326abba57b088bcd (patch)
treeb14bcc7e91fb33213b349914c477d9c22cd8a25d /Src/Zle/zle_utils.c
parent6be3fe2fca7d904ce4c83303a1b23e36ed45a084 (diff)
downloadzsh-212ca9edf9c2be0499cdce39326abba57b088bcd.tar.gz
zsh-212ca9edf9c2be0499cdce39326abba57b088bcd.zip
28772: Update regions in region highlight dynamically
Diffstat (limited to 'Src/Zle/zle_utils.c')
-rw-r--r--Src/Zle/zle_utils.c337
1 files changed, 333 insertions, 4 deletions
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 5275bdbf6..3a2694bfd 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -179,6 +179,8 @@ zlecharasstring(ZLE_CHAR_T inchar, char *buf)
* string length, without the NULL byte.
*
* If outcsp is non-NULL, assign the new character position.
+ * If outcsp is &zlemetacs, update the positions in the region_highlight
+ * array, too. This is a bit of a hack.
*
* If useheap is 1, memory is returned from the heap, else is allocated
* for later freeing.
@@ -190,6 +192,7 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
int *outcsp, int useheap)
{
int outcs, outll;
+ struct region_highlight *rhp;
#ifdef MULTIBYTE_SUPPORT
char *s;
@@ -201,9 +204,22 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
outcs = 0;
memset(&mbs, 0, sizeof(mbs));
- for (i=0; i < inll; i++, incs--) {
+ for (i=0; i < inll; i++) {
if (incs == 0)
outcs = mb_len;
+ incs--;
+ if (region_highlights && outcsp == &zlemetacs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (rhp->start == 0)
+ rhp->start_meta = mb_len;
+ rhp->start--;
+ if (rhp->end == 0)
+ rhp->end_meta = mb_len;
+ rhp->end--;
+ }
+ }
#ifdef __STDC_ISO_10646__
if (ZSH_INVALID_WCHAR_TEST(instr[i])) {
s[mb_len++] = ZSH_INVALID_WCHAR_TO_CHAR(instr[i]);
@@ -222,12 +238,30 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
}
if (incs == 0)
outcs = mb_len;
+ if (region_highlights && outcsp == &zlemetacs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (rhp->start == 0)
+ rhp->start_meta = mb_len;
+ if (rhp->end == 0)
+ rhp->end_meta = mb_len;
+ }
+ }
s[mb_len] = '\0';
outll = mb_len;
#else
outll = inll;
outcs = incs;
+ if (region_highlights && outcsp == &zlemetacs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ rhp->start_meta = rhp->start;
+ rhp->end_meta = rhp->end;
+ }
+ }
#endif
/*
@@ -243,11 +277,33 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
#endif
char *stopcs = strp + outcs;
char *stopll = strp + outll;
-
+ char *startp = strp;
+
+ if (region_highlights && outcsp == &zlemetacs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ /* Used as temporary storage */
+ rhp->start = rhp->start_meta;
+ rhp->end = rhp->end_meta;
+ }
+ }
while (strp < stopll) {
if (imeta(*strp)) {
if (strp < stopcs)
outcs++;
+ if (region_highlights && outcsp == &zlemetacs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (strp < startp + rhp->start) {
+ rhp->start_meta++;
+ }
+ if (strp < startp + rhp->end) {
+ rhp->end_meta++;
+ }
+ }
+ }
outll++;
}
strp++;
@@ -290,6 +346,9 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
* each metafied character) is converted into the corresponding
* character position in *outcs.
*
+ * If, further, outcs is &zlecs, we update the positions in the
+ * region_highlight array, too. (This is a bit of a hack.)
+ *
* Note that instr is modified in place, hence should be copied
* first if necessary;
*
@@ -304,6 +363,7 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
{
ZLE_STRING_T outstr;
int ll, sz;
+ struct region_highlight *rhp;
#ifdef MULTIBYTE_SUPPORT
mbstate_t mbs;
#endif
@@ -316,10 +376,32 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
* is all the processing required to calculate outcs.
*/
char *inptr = instr, *cspos = instr + incs;
- while (*inptr && inptr < cspos) {
+ if (region_highlights && outcs == &zlecs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ rhp->start = rhp->start_meta;
+ rhp->end = rhp->end_meta;
+ }
+ }
+ while (*inptr) {
if (*inptr == Meta) {
+ if (inptr < cspos) {
+ incs--;
+ }
+ if (region_highlights && outcs == &zlecs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (inptr - instr < rhp->start) {
+ rhp->start_meta--;
+ }
+ if (inptr - instr < rhp->end) {
+ rhp->end_meta--;
+ }
+ }
+ }
inptr++;
- incs--;
}
inptr++;
}
@@ -385,6 +467,20 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
int offs = inptr - instr;
if (offs <= incs && incs < offs + (int)cnt)
*outcs = outptr - outstr;
+ if (region_highlights && outcs == &zlecs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (offs <= rhp->start_meta &&
+ rhp->start_meta < offs + (int)cnt) {
+ rhp->start = outptr - outstr;
+ }
+ if (offs <= rhp->end_meta &&
+ rhp->end_meta < offs + (int)cnt) {
+ rhp->end = outptr - outstr;
+ }
+ }
+ }
}
inptr += cnt;
@@ -404,6 +500,14 @@ stringaszleline(char *instr, int incs, int *outll, int *outsz, int *outcs)
*outll = ll;
if (outcs)
*outcs = incs;
+ if (region_highlights && outcs == &zlecs) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ rhp->start = rhp->start_meta;
+ rhp->end = rhp->end_meta;
+ }
+ }
#endif
return outstr;
@@ -432,6 +536,158 @@ zlegetline(int *ll, int *cs)
}
+/* Forward reference */
+struct zle_region;
+
+/* A non-special entry in region_highlight */
+struct zle_region {
+ struct zle_region *next;
+ /* Entries of region_highlight, as needed */
+ int atr;
+ int start;
+ int end;
+ int flags;
+};
+
+/* Forward reference */
+struct zle_position;
+
+/* A saved set of position information */
+struct zle_position {
+ /* Link pointer */
+ struct zle_position *next;
+ /* Cursor position */
+ int cs;
+ /* Mark */
+ int mk;
+ /* Line length */
+ int ll;
+ struct zle_region *regions;
+};
+
+/* LIFO stack of positions */
+struct zle_position *zle_positions;
+
+/*
+ * Save positions including cursor, end-of-line and
+ * (non-special) region highlighting.
+ *
+ * Must be matched by a subsequent zle_restore_positions().
+ */
+
+/**/
+void
+zle_save_positions(void)
+{
+ struct region_highlight *rhp;
+ struct zle_position *newpos;
+ struct zle_region **newrhpp, *newrhp;
+
+ newpos = (struct zle_position *)zalloc(sizeof(*newpos));
+
+ newpos->mk = mark;
+ if (zlemetaline) {
+ /* Use metafied information */
+ newpos->cs = zlemetacs;
+ newpos->ll = zlemetall;
+ } else {
+ /* Use unmetafied information */
+ newpos->cs = zlecs;
+ newpos->ll = zlell;
+
+ }
+
+ newrhpp = &newpos->regions;
+ *newrhpp = NULL;
+ if (region_highlights) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ /*
+ * This is a FIFO stack, so we preserve the order
+ * of entries when we restore region_highlights.
+ */
+ newrhp = *newrhpp = (struct zle_region *)zalloc(sizeof(**newrhpp));
+ newrhp->next = NULL;
+ newrhp->atr = rhp->atr;
+ newrhp->flags = rhp->flags;
+ if (zlemetaline) {
+ newrhp->start = rhp->start_meta;
+ newrhp->end = rhp->end_meta;
+ } else {
+ newrhp->start = rhp->start;
+ newrhp->end = rhp->end;
+ }
+ newrhpp = &newrhp->next;
+ }
+ }
+
+ newpos->next = zle_positions;
+ zle_positions = newpos;
+}
+
+/*
+ * Restore positions previously saved.
+ * Relies on zlemetaline being restored correctly beforehand,
+ * so that it can tell whether to use metafied positions or not.
+ */
+
+/**/
+void
+zle_restore_positions(void)
+{
+ struct zle_position *oldpos = zle_positions;
+ struct zle_region *oldrhp;
+ struct region_highlight *rhp;
+ int nreg;
+
+ zle_positions = oldpos->next;
+
+ mark = oldpos->mk;
+ if (zlemetaline) {
+ /* Use metafied information */
+ zlemetacs = oldpos->cs;
+ zlemetall = oldpos->ll;
+ } else {
+ /* Use unmetafied information */
+ zlecs = oldpos->cs;
+ zlell = oldpos->ll;
+ }
+
+ /* Count number of regions and see if the array needs resizing */
+ for (nreg = 0, oldrhp = oldpos->regions;
+ oldrhp;
+ nreg++, oldrhp = oldrhp->next)
+ ;
+ if (nreg + N_SPECIAL_HIGHLIGHTS != n_region_highlights) {
+ n_region_highlights = nreg + N_SPECIAL_HIGHLIGHTS;
+ region_highlights = (struct region_highlight *)
+ zrealloc(region_highlights,
+ sizeof(struct region_highlight) * n_region_highlights);
+ }
+ oldrhp = oldpos->regions;
+ rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ while (oldrhp) {
+ struct zle_region *nextrhp = oldrhp->next;
+
+ rhp->atr = oldrhp->atr;
+ rhp->flags = oldrhp->flags;
+ if (zlemetaline) {
+ rhp->start_meta = oldrhp->start;
+ rhp->end_meta = oldrhp->end;
+ } else {
+ rhp->start = oldrhp->start;
+ rhp->end = oldrhp->end;
+ }
+
+ zfree(oldrhp, sizeof(*oldrhp));
+ oldrhp = nextrhp;
+ rhp++;
+ }
+
+ zfree(oldpos, sizeof(*oldpos));
+}
+
/*
* Basic utility functions for adding to line or removing from line.
* At this level the counts supplied are raw character counts, so
@@ -450,6 +706,7 @@ mod_export void
spaceinline(int ct)
{
int i;
+ struct region_highlight *rhp;
if (zlemetaline) {
sizeline(ct + zlemetall);
@@ -460,6 +717,19 @@ spaceinline(int ct)
if (mark > zlemetacs)
mark += ct;
+
+ if (region_highlights) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (rhp->start_meta >= zlemetacs) {
+ rhp->start_meta += ct;
+ }
+ if (rhp->end_meta >= zlemetacs) {
+ rhp->end_meta += ct;
+ }
+ }
+ }
} else {
sizeline(ct + zlell);
for (i = zlell; --i >= zlecs;)
@@ -469,26 +739,85 @@ spaceinline(int ct)
if (mark > zlecs)
mark += ct;
+
+ if (region_highlights) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (rhp->start >= zlecs) {
+ rhp->start += ct;
+ }
+ if (rhp->end >= zlecs) {
+ rhp->end += ct;
+ }
+ }
+ }
}
region_active = 0;
}
+/*
+ * Within the ZLE line, cut the "cnt" characters from position "to".
+ */
+
/**/
void
shiftchars(int to, int cnt)
{
+ struct region_highlight *rhp;
+
if (mark >= to + cnt)
mark -= cnt;
else if (mark > to)
mark = to;
if (zlemetaline) {
+ /* before to is updated... */
+ if (region_highlights) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (rhp->start_meta > to) {
+ if (rhp->start_meta > to + cnt)
+ rhp->start_meta -= cnt;
+ else
+ rhp->start_meta = to;
+ }
+ if (rhp->end_meta > to) {
+ if (rhp->end_meta > to + cnt)
+ rhp->end_meta -= cnt;
+ else
+ rhp->end_meta = to;
+ }
+ }
+ }
+
while (to + cnt < zlemetall) {
zlemetaline[to] = zlemetaline[to + cnt];
to++;
}
zlemetaline[zlemetall = to] = '\0';
} else {
+ /* before to is updated... */
+ if (region_highlights) {
+ for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ rhp < region_highlights + n_region_highlights;
+ rhp++) {
+ if (rhp->start > to) {
+ if (rhp->start > to + cnt)
+ rhp->start -= cnt;
+ else
+ rhp->start = to;
+ }
+ if (rhp->end > to) {
+ if (rhp->end > to + cnt)
+ rhp->end -= cnt;
+ else
+ rhp->end = to;
+ }
+ }
+ }
+
while (to + cnt < zlell) {
zleline[to] = zleline[to + cnt];
to++;