summaryrefslogtreecommitdiff
path: root/Src/Zle/zle_utils.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2008-04-13 16:58:42 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2008-04-13 16:58:42 +0000
commit97dcf155566083a4b6a43040184cb477d3ff2baf (patch)
treeab1eac3ca67fa36daf9c6fe9fda6be4b0522c4c6 /Src/Zle/zle_utils.c
parentc1db47d16b799820491994447514c7e3dbc7316a (diff)
downloadzsh-97dcf155566083a4b6a43040184cb477d3ff2baf.tar.gz
zsh-97dcf155566083a4b6a43040184cb477d3ff2baf.zip
24808: initial support for combining characters in zle
Diffstat (limited to 'Src/Zle/zle_utils.c')
-rw-r--r--Src/Zle/zle_utils.c129
1 files changed, 91 insertions, 38 deletions
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index cacf6b483..cd8e2b26c 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -357,6 +357,17 @@ zlegetline(int *ll, int *cs)
}
+/*
+ * Basic utility functions for adding to line or removing from line.
+ * At this level the counts supplied are raw character counts, so
+ * the calling code must be aware of combining characters where
+ * necessary, e.g. if we want to delete a + combing grave forward
+ * from the cursor, then shiftchars() gets the count 2 (not 1).
+ *
+ * This is necessary because these utility functions don't know about
+ * zlecs, and we need to count combined characters from there.
+ */
+
/* insert space for ct chars at cursor position */
/**/
@@ -412,27 +423,6 @@ shiftchars(int to, int cnt)
region_active = 0;
}
-/**/
-mod_export void
-backkill(int ct, int dir)
-{
- int i = (zlecs -= ct);
-
- cut(i, ct, dir);
- shiftchars(i, ct);
-}
-
-/**/
-mod_export void
-forekill(int ct, int dir)
-{
- int i = zlecs;
-
- cut(i, ct, dir);
- shiftchars(i, ct);
-}
-
-
/*
* Put the ct characters starting at zleline + i into the
* cutbuffer, circling the kill ring if necessary (it's
@@ -448,9 +438,9 @@ forekill(int ct, int dir)
/**/
void
-cut(int i, int ct, int dir)
+cut(int i, int ct, int flags)
{
- cuttext(zleline + i, ct, dir);
+ cuttext(zleline + i, ct, flags);
}
/*
@@ -459,7 +449,7 @@ cut(int i, int ct, int dir)
/**/
void
-cuttext(ZLE_STRING_T line, int ct, int dir)
+cuttext(ZLE_STRING_T line, int ct, int flags)
{
if (!ct)
return;
@@ -504,7 +494,7 @@ cuttext(ZLE_STRING_T line, int ct, int dir)
cutbuf.buf = (ZLE_STRING_T)zalloc(ZLE_CHAR_SIZE);
cutbuf.buf[0] = ZWC('\0');
cutbuf.len = cutbuf.flags = 0;
- } else if (!(lastcmd & ZLE_KILL) || dir < 0) {
+ } else if (!(lastcmd & ZLE_KILL) || (flags & CUT_RAW)) {
Cutbuffer kptr;
if (!kring) {
kringsize = KRINGCTDEF;
@@ -519,7 +509,7 @@ cuttext(ZLE_STRING_T line, int ct, int dir)
cutbuf.buf[0] = ZWC('\0');
cutbuf.len = cutbuf.flags = 0;
}
- if (dir) {
+ if (flags & (CUT_FRONT|CUT_REPLACE)) {
ZLE_STRING_T s = (ZLE_STRING_T)zalloc((cutbuf.len + ct)*ZLE_CHAR_SIZE);
ZS_memcpy(s, line, ct);
@@ -539,24 +529,87 @@ cuttext(ZLE_STRING_T line, int ct, int dir)
cutbuf.flags &= ~CUTBUFFER_LINE;
}
+/*
+ * Now we're back in the world of zlecs where we need to keep
+ * track of whether we're on a combining character.
+ */
+
/**/
mod_export void
-backdel(int ct)
+backkill(int ct, int flags)
{
- if (zlemetaline != NULL)
- shiftchars(zlemetacs -= ct, ct);
- else
- shiftchars(zlecs -= ct, ct);
+ int i;
+
+ if (flags & CUT_RAW) {
+ i = (zlecs -= ct);
+ } else {
+ int n = ct;
+ while (n--)
+ DECCS();
+ i = zlecs;
+ }
+
+ cut(i, ct, flags);
+ shiftchars(i, ct);
}
/**/
mod_export void
-foredel(int ct)
+forekill(int ct, int flags)
{
- if (zlemetaline != NULL)
- shiftchars(zlemetacs, ct);
- else
+ int i = zlecs;
+
+ if (!(flags & CUT_RAW)) {
+ int n = ct;
+ while (n--)
+ INCCS();
+ ct = zlecs - i;
+ zlecs = i;
+ }
+
+ cut(i, ct, flags);
+ shiftchars(i, ct);
+}
+
+/**/
+mod_export void
+backdel(int ct, int flags)
+{
+ if (flags & CUT_RAW) {
+ if (zlemetaline != NULL) {
+ shiftchars(zlemetacs -= ct, ct);
+ } else {
+ shiftchars(zlecs -= ct, ct);
+ }
+ } else {
+ int n = ct, origcs = zlecs;
+ DPUTS(zlemetaline != NULL, "backdel needs CUT_RAW when metafied");
+ while (n--)
+ DECCS();
+ shiftchars(zlecs, origcs - zlecs);
+ }
+}
+
+/**/
+mod_export void
+foredel(int ct, int flags)
+{
+ if (flags & CUT_RAW) {
+ if (zlemetaline != NULL) {
+ shiftchars(zlemetacs, ct);
+ } else if (flags & CUT_RAW) {
+ shiftchars(zlecs, ct);
+ }
+ } else {
+ int origcs = zlecs;
+ int n = ct;
+ DPUTS(zlemetaline != NULL, "backdel needs CUT_RAW when metafied");
+ while (n--)
+ INCCS();
+ ct = zlecs - origcs;
+ zlecs = origcs;
shiftchars(zlecs, ct);
+ }
}
/**/
@@ -578,7 +631,7 @@ setline(char *s, int flags)
zleline = stringaszleline(scp, 0, &zlell, &linesz, NULL);
if ((flags & ZSL_TOEND) && (zlecs = zlell) && invicmdmode())
- zlecs--;
+ DECCS();
else if (zlecs > zlell)
zlecs = zlell;
@@ -1035,7 +1088,7 @@ unapplychange(struct change *ch)
}
zlecs = ch->off;
if(ch->ins)
- foredel(ch->insl);
+ foredel(ch->insl, CUT_RAW);
if(ch->del) {
spaceinline(ch->dell);
ZS_memcpy(zleline + zlecs, ch->del, ch->dell);
@@ -1075,7 +1128,7 @@ applychange(struct change *ch)
}
zlecs = ch->off;
if(ch->del)
- foredel(ch->dell);
+ foredel(ch->dell, CUT_RAW);
if(ch->ins) {
spaceinline(ch->insl);
ZS_memcpy(zleline + zlecs, ch->ins, ch->insl);