summaryrefslogtreecommitdiff
path: root/Src/Zle/zle_utils.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2005-08-10 10:56:40 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2005-08-10 10:56:40 +0000
commit2a888b3d5ae1f485649b811ea433f286238fd308 (patch)
tree11f21c9ee2e716c8ab247c6d4ca834c6586ba101 /Src/Zle/zle_utils.c
parentef913283407fdc8166e5b937dcb08d1b4abde10d (diff)
downloadzsh-2a888b3d5ae1f485649b811ea433f286238fd308.tar.gz
zsh-2a888b3d5ae1f485649b811ea433f286238fd308.zip
c.f. 21590: metafy_line()/unmetafy_line() now support wide characters
Diffstat (limited to 'Src/Zle/zle_utils.c')
-rw-r--r--Src/Zle/zle_utils.c229
1 files changed, 176 insertions, 53 deletions
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index aa691bcdc..f8c4d2013 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -66,21 +66,36 @@ int linesz;
void
sizeline(int sz)
{
- while (sz > linesz)
+ int cursz = (zlemetaline != NULL) ? metalinesz : linesz;
+
+ while (sz > cursz)
{
- if (linesz < 256)
- linesz = 256;
+ if (cursz < 256)
+ cursz = 256;
else
- linesz *= 4;
+ cursz *= 4;
- zleline =
- (ZLE_STRING_T)realloc(zleline,
- (linesz + 2) * ZLE_CHAR_SIZE);
+ if (zlemetaline != NULL) {
+ /* One spare character for the NULL */
+ zlemetaline = (unsigned char *)realloc(zlemetaline, cursz + 1);
+ } else {
+ /* One spare character for the NULL, one for the newline */
+ zleline =
+ (ZLE_STRING_T)realloc(zleline,
+ (cursz + 2) * ZLE_CHAR_SIZE);
+ }
}
+
+ if (zlemetaline != NULL)
+ metalinesz = cursz;
+ else
+ linesz = cursz;
}
/*
* Insert a character, called from main shell.
+ * Note this always operates on the metafied multibyte version of the
+ * line.
*/
/**/
@@ -88,20 +103,7 @@ mod_export void
zleaddtoline(int chr)
{
spaceinline(1);
-#ifdef ZLE_UNICODE_SUPPORT
- /*
- * TODO: the main shell has as yet very little notion of multibyte
- * characters. Until this gets fixed we just have to assume
- * this is a complete character.
- *
- * Possibly we could get away with attempting to build up a
- * multibyte character here, storing partial characters between
- * calls.
- */
- zleline[zlecs++] = (ZLE_CHAR_T)chr;
-#else
- zleline[zlecs++] = chr;
-#endif
+ zlemetaline[zlemetacs++] = chr;
}
/*
@@ -125,9 +127,11 @@ zleaddtoline(int chr)
/**/
mod_export unsigned char *
-zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outll,
- int *outcs, int useheap)
+zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp,
+ int *outcsp, int useheap)
{
+ int outcs, outll;
+
#ifdef ZLE_UNICODE_SUPPORT
char *s;
int i, j;
@@ -135,9 +139,10 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outll,
s = zalloc(inll * MB_CUR_MAX + 1);
+ outcs = 0;
for(i=0; i < inll; i++, incs--) {
- if (outcs != NULL && incs == 0)
- *outcs = mb_len;
+ if (incs == 0)
+ outcs = mb_len;
j = wctomb(s + mb_len, instr[i]);
if (j == -1) {
/* invalid char; what to do? */
@@ -147,8 +152,41 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outll,
}
s[mb_len] = '\0';
- if (outll != NULL)
- *outll = mb_len;
+ outll = mb_len;
+#else
+ outll = inll;
+ outcs = incs;
+#endif
+
+ /*
+ * *outcsp and *outllp are to be indexes into the final string,
+ * not character offsets, so we need to take account of any
+ * metafiable characters.
+ */
+ if (outcsp != NULL || outllp != NULL) {
+#ifdef ZLE_UNICODE_SUPPORT
+ unsigned char *strp = (unsigned char *)s;
+#else
+ unsigned char *strp = instr;
+#endif
+ unsigned char *stopcs = strp + outcs;
+ unsigned char *stopll = strp + outll;
+
+ while (strp < stopll) {
+ if (imeta(*strp)) {
+ if (strp < stopcs)
+ outcs++;
+ outll++;
+ }
+ strp++;
+ }
+ if (outcsp != NULL)
+ *outcsp = outcs;
+ if (outllp != NULL)
+ *outllp = outll;
+ }
+
+#ifdef ZLE_UNICODE_SUPPORT
if (useheap)
{
unsigned char *ret =
@@ -163,11 +201,6 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outll,
return (unsigned char *) metafy((char *) s, mb_len, META_REALLOC);
}
#else
- if (outll != NULL)
- *outll = inll;
- if (outcs != NULL)
- *outcs = incs;
-
return (unsigned char *) metafy((char *) instr, inll,
useheap ? META_HEAPDUP : META_DUP);
#endif
@@ -186,6 +219,11 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outll,
* may take a newline and a null at a later stage.) These are not
* included in *outsz.
*
+ * If outcs is non-NULL, the character position in the original
+ * string incs (a standard string offset, i.e. incremented 2 for
+ * each metafied character) is converted into the corresponding
+ * character position in *outcs.
+ *
* Note that instr is modified in place, hence should be copied
* first if necessary;
*
@@ -196,7 +234,8 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outll,
/**/
mod_export ZLE_STRING_T
-stringaszleline(unsigned char *instr, int *outll, int *outsz)
+stringaszleline(unsigned char *instr, int incs,
+ int *outll, int *outsz, int *outcs)
{
ZLE_STRING_T outstr;
int ll, sz;
@@ -204,7 +243,23 @@ stringaszleline(unsigned char *instr, int *outll, int *outsz)
mbstate_t ps;
#endif
- unmetafy(instr, &ll);
+ if (outcs) {
+ /*
+ * Take account of Meta characters in the input string
+ * before we unmetafy it. This does not yet take account
+ * of multibyte characters. If there are none, this
+ * is all the processing required to calculate outcs.
+ */
+ unsigned char *inptr = instr, *cspos = instr + incs;
+ while (*inptr && inptr < cspos) {
+ if (*inptr == STOUC(Meta)) {
+ inptr++;
+ incs--;
+ }
+ inptr++;
+ }
+ }
+ unmetafy((char *)instr, &ll);
/*
* ll is the maximum number of characters there can be in
@@ -246,29 +301,53 @@ stringaszleline(unsigned char *instr, int *outll, int *outsz)
if (*outptr == L'\0' && ret == 0)
ret = 1;
+ if (outcs) {
+ int offs = inptr - (char *)instr;
+ if (offs <= incs && incs < offs + ret)
+ *outcs = outptr - outstr;
+ }
+
inptr += ret;
outptr++;
ll -= ret;
}
*outll = outptr - outstr;
- }
- else
+ } else {
*outll = 0;
+ if (outcs)
+ *outcs = 0;
+ }
#else
memcpy((char *)outstr, (char *)instr, ll);
*outll = ll;
+ if (outcs)
+ *outcs = incs;
#endif
return outstr;
}
-
+/*
+ * This function is called when we are playing very nasty tricks
+ * indeed: see bufferwords in hist.c. Consequently we can make
+ * absolutely no assumption about the state whatsoever, except
+ * that it has one.
+ */
/**/
mod_export unsigned char *
zlegetline(int *ll, int *cs)
{
- return zlelineasstring(zleline, zlell, zlecs, ll, cs, 0);
+ if (zlemetaline != NULL) {
+ *ll = zlemetall;
+ *cs = zlemetacs;
+ return (unsigned char *)ztrdup((char *)zlemetaline);
+ } else if (zleline) {
+ return zlelineasstring(zleline, zlell, zlecs, ll, cs, 0);
+ } else {
+ *ll = *cs = 0;
+ return (unsigned char *)ztrdup("");
+ }
}
@@ -280,14 +359,25 @@ spaceinline(int ct)
{
int i;
- sizeline(ct + zlell);
- for (i = zlell; --i >= zlecs;)
- zleline[i + ct] = zleline[i];
- zlell += ct;
- zleline[zlell] = ZWC('\0');
+ if (zlemetaline) {
+ sizeline(ct + zlemetall);
+ for (i = zlemetall; --i >= zlemetacs;)
+ zlemetaline[i + ct] = zlemetaline[i];
+ zlemetall += ct;
+ zlemetaline[zlemetall] = '\0';
- if (mark > zlecs)
- mark += ct;
+ if (mark > zlemetacs)
+ mark += ct;
+ } else {
+ sizeline(ct + zlell);
+ for (i = zlell; --i >= zlecs;)
+ zleline[i + ct] = zleline[i];
+ zlell += ct;
+ zleline[zlell] = ZWC('\0');
+
+ if (mark > zlecs)
+ mark += ct;
+ }
}
/**/
@@ -299,11 +389,19 @@ shiftchars(int to, int cnt)
else if (mark > to)
mark = to;
- while (to + cnt < zlell) {
- zleline[to] = zleline[to + cnt];
- to++;
+ if (zlemetaline) {
+ while (to + cnt < zlemetall) {
+ zlemetaline[to] = zlemetaline[to + cnt];
+ to++;
+ }
+ zlemetaline[zlemetall = to] = '\0';
+ } else {
+ while (to + cnt < zlell) {
+ zleline[to] = zleline[to + cnt];
+ to++;
+ }
+ zleline[zlell = to] = ZWC('\0');
}
- zleline[zlell = to] = ZWC('\0');
}
/**/
@@ -333,6 +431,7 @@ cut(int i, int ct, int dir)
if (!ct)
return;
+ UNMETACHECK();
if (zmod.flags & MOD_VIBUF) {
struct cutbuffer *b = &vibuf[zmod.vibuf];
@@ -411,14 +510,20 @@ cut(int i, int ct, int dir)
mod_export void
backdel(int ct)
{
- shiftchars(zlecs -= ct, ct);
+ if (zlemetaline != NULL)
+ shiftchars(zlemetacs -= ct, ct);
+ else
+ shiftchars(zlecs -= ct, ct);
}
/**/
mod_export void
foredel(int ct)
{
- shiftchars(zlecs, ct);
+ if (zlemetaline != NULL)
+ shiftchars(zlemetacs, ct);
+ else
+ shiftchars(zlecs, ct);
}
/**/
@@ -437,7 +542,7 @@ setline(char *s, int flags)
*/
free(zleline);
- zleline = stringaszleline(scp, &zlell, &linesz);
+ zleline = stringaszleline((unsigned char *)scp, 0, &zlell, &linesz, NULL);
if ((flags & ZSL_TOEND) && (zlecs = zlell) && invicmdmode())
zlecs--;
@@ -760,6 +865,19 @@ freechanges(struct change *p)
mod_export void
handleundo(void)
{
+ int remetafy;
+
+ /*
+ * Yuk: we call this from within the completion system,
+ * so we need to convert back to the form which can be
+ * copied into undo entries.
+ */
+ if (zlemetaline != NULL) {
+ unmetafy_line();
+ remetafy = 1;
+ } else
+ remetafy = 0;
+
mkundoent();
if(!nextchanges)
return;
@@ -780,6 +898,9 @@ handleundo(void)
curchange->prev = endnextchanges;
endnextchanges->next = curchange;
nextchanges = endnextchanges = NULL;
+
+ if (remetafy)
+ metafy_line();
}
/* add an entry to the undo system, if anything has changed */
@@ -792,7 +913,8 @@ mkundoent(void)
int sh = zlell < lastll ? zlell : lastll;
struct change *ch;
- if(lastll == zlell && !memcmp(lastline, zleline, zlell * ZLE_CHAR_SIZE))
+ UNMETACHECK();
+ if(lastll == zlell && !ZS_memcmp(lastline, zleline, zlell))
return;
for(pre = 0; pre < sh && zleline[pre] == lastline[pre]; )
pre++;
@@ -840,6 +962,7 @@ mkundoent(void)
void
setlastline(void)
{
+ UNMETACHECK();
if(lastlinesz != linesz)
lastline = realloc(lastline, (lastlinesz = linesz) * ZLE_CHAR_SIZE);
ZS_memcpy(lastline, zleline, (lastll = zlell));