Rework addition of Symbian splash screen to reduce the source impact (uses SVG from Bug 2414)
Notes: by using the OPTION SOURCEDIR parameter in the mifconv extension instructions, I can
arrange to use the same source file name in sfimage, without having to export over the original
Nokia file. This means that the name inside splashscreen.mbg is the same, which removes the need
for the conditional compilation in SplashScreen.cpp, and gets rid of sf_splashscreen.mmp.
/*
* This file is part of zsh, the Z shell.
*
* Copyright (c) 1992-1997 Paul Falstad
* All rights reserved.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and to distribute modified versions of this software for any
* purpose, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* In no event shall Paul Falstad or the Zsh Development Group be liable
* to any party for direct, indirect, special, incidental, or consequential
* damages arising out of the use of this software and its documentation,
* even if Paul Falstad and the Zsh Development Group have been advised of
* the possibility of such damage.
*
* Paul Falstad and the Zsh Development Group specifically disclaim any
* warranties, including, but not limited to, the implied warranties of
* merchantability and fitness for a particular purpose. The software
* provided hereunder is on an "as is" basis, and Paul Falstad and the
* Zsh Development Group have no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
*/
#include "zsh.mdh"
#include "prompt.pro"
#ifdef __SYMBIAN32__
#ifdef __WINSCW__
#pragma warn_possunwant off
#endif//__WINSCW__
#endif//__SYMBIAN32__
/* text attribute mask */
/**/
unsigned txtattrmask;
/* text change - attribute change made by prompts */
/**/
mod_export unsigned txtchange;
/* the command stack for use with %_ in prompts */
/**/
unsigned char *cmdstack;
/**/
int cmdsp;
/* parser states, for %_ */
static char *cmdnames[CS_COUNT] = {
"for", "while", "repeat", "select",
"until", "if", "then", "else",
"elif", "math", "cond", "cmdor",
"cmdand", "pipe", "errpipe", "foreach",
"case", "function", "subsh", "cursh",
"array", "quote", "dquote", "bquote",
"cmdsubst", "mathsubst", "elif-then", "heredoc",
"heredocd", "brace", "braceparam", "always",
};
/* The buffer into which an expanded and metafied prompt is being written, *
* and its size. */
static char *buf;
static int bufspc;
/* bp is the pointer to the current position in the buffer, where the next *
* character will be added. */
static char *bp;
/* Position of the start of the current line in the buffer */
static char *bufline;
/* bp1 is an auxiliary pointer into the buffer, which when non-NULL is *
* moved whenever the buffer is reallocated. It is used when data is *
* being temporarily held in the buffer. */
static char *bp1;
/* The format string, for %-expansion. */
static char *fm;
/* Non-zero if truncating the current segment of the buffer. */
static int trunclen;
/* Current level of nesting of %{ / %} sequences. */
static int dontcount;
/* Level of %{ / %} surrounding a truncation segment. */
static int trunccount;
/* Strings to use for %r and %R (for the spelling prompt). */
static char *rstring, *Rstring;
/*
* Expand path p; maximum is npath segments where 0 means the whole path.
* If tilde is 1, try and find a named directory to use.
*/
static void
promptpath(char *p, int npath, int tilde)
{
char *modp = p;
Nameddir nd;
if (tilde && ((nd = finddir(p))))
modp = tricat("~", nd->nam, p + strlen(nd->dir));
if (npath) {
char *sptr;
if (npath > 0) {
for (sptr = modp + strlen(modp); sptr > modp; sptr--) {
if (*sptr == '/' && !--npath) {
sptr++;
break;
}
}
if (*sptr == '/' && sptr[1] && sptr != modp)
sptr++;
stradd(sptr);
} else {
char cbu;
for (sptr = modp+1; *sptr; sptr++)
if (*sptr == '/' && !++npath)
break;
cbu = *sptr;
*sptr = 0;
stradd(modp);
*sptr = cbu;
}
} else
stradd(modp);
if (p != modp)
zsfree(modp);
}
/* Perform prompt expansion on a string, putting the result in a *
* permanently-allocated string. If ns is non-zero, this string *
* may have embedded Inpar and Outpar, which indicate a toggling *
* between spacing and non-spacing parts of the prompt, and *
* Nularg, which (in a non-spacing sequence) indicates a *
* `glitch' space. */
/**/
mod_export char *
promptexpand(char *s, int ns, char *rs, char *Rs)
{
if(!s)
return ztrdup("");
if ((termflags & TERM_UNKNOWN) && (unset(INTERACTIVE)))
init_term();
if (isset(PROMPTSUBST)) {
int olderr = errflag;
int oldval = lastval;
s = dupstring(s);
if (!parsestr(s))
singsub(&s);
/* Ignore errors and status change in prompt substitution */
errflag = olderr;
lastval = oldval;
}
rstring = rs;
Rstring = Rs;
fm = s;
bp = bufline = buf = zshcalloc(bufspc = 256);
bp1 = NULL;
trunclen = 0;
putpromptchar(1, '\0');
addbufspc(1);
if(dontcount)
*bp++ = Outpar;
*bp = 0;
if (!ns) {
/* If zero, Inpar, Outpar and Nularg should be removed. */
for (bp = buf; *bp; ) {
if (*bp == Meta)
bp += 2;
else if (*bp == Inpar || *bp == Outpar || *bp == Nularg)
chuck(bp);
else
bp++;
}
}
return buf;
}
/* Perform %- and !-expansion as required on a section of the prompt. The *
* section is ended by an instance of endchar. If doprint is 0, the valid *
* % sequences are merely skipped over, and nothing is stored. */
/**/
static int
putpromptchar(int doprint, int endchar)
{
char *ss, *tmbuf = NULL, *hostnam;
int t0, arg, test, sep, j, numjobs;
struct tm *tm;
time_t timet;
Nameddir nd;
for (; *fm && *fm != endchar; fm++) {
arg = 0;
if (*fm == '%' && isset(PROMPTPERCENT)) {
int minus = 0;
fm++;
if (*fm == '-') {
minus = 1;
fm++;
}
if (idigit(*fm)) {
arg = zstrtol(fm, &fm, 10);
if (minus)
arg *= -1;
} else if (minus)
arg = -1;
if (*fm == '(') {
int tc, otrunclen;
if (idigit(*++fm)) {
arg = zstrtol(fm, &fm, 10);
} else if (arg < 0) {
/* negative numbers don't make sense here */
arg *= -1;
}
test = 0;
ss = pwd;
switch (tc = *fm) {
case 'c':
case '.':
case '~':
if ((nd = finddir(ss))) {
arg--;
ss += strlen(nd->dir);
} /*FALLTHROUGH*/
case '/':
case 'C':
/* `/' gives 0, `/any' gives 1, etc. */
if (*ss++ == '/' && *ss)
arg--;
for (; *ss; ss++)
if (*ss == '/')
arg--;
if (arg <= 0)
test = 1;
break;
case 't':
case 'T':
case 'd':
case 'D':
case 'w':
timet = time(NULL);
tm = localtime(&timet);
switch (tc) {
case 't':
test = (arg == tm->tm_min);
break;
case 'T':
test = (arg == tm->tm_hour);
break;
case 'd':
test = (arg == tm->tm_mday);
break;
case 'D':
test = (arg == tm->tm_mon);
break;
case 'w':
test = (arg == tm->tm_wday);
break;
}
break;
case '?':
if (lastval == arg)
test = 1;
break;
case '#':
if (geteuid() == (uid_t)arg)
test = 1;
break;
case 'g':
if (getegid() == (gid_t)arg)
test = 1;
break;
case 'j':
for (numjobs = 0, j = 1; j <= maxjob; j++)
if (jobtab[j].stat && jobtab[j].procs &&
!(jobtab[j].stat & STAT_NOPRINT)) numjobs++;
if (numjobs >= arg)
test = 1;
break;
case 'l':
*bp = '\0';
countprompt(bufline, &t0, 0, 0);
if (t0 >= arg)
test = 1;
break;
case 'L':
if (shlvl >= arg)
test = 1;
break;
case 'S':
if (time(NULL) - shtimer.tv_sec >= arg)
test = 1;
break;
case 'v':
if (arrlen(psvar) >= arg)
test = 1;
break;
case '_':
test = (cmdsp >= arg);
break;
case '!':
test = privasserted();
break;
default:
test = -1;
break;
}
if (!*fm || !(sep = *++fm))
return 0;
fm++;
/* Don't do the current truncation until we get back */
otrunclen = trunclen;
trunclen = 0;
if (!putpromptchar(test == 1 && doprint, sep) || !*++fm ||
!putpromptchar(test == 0 && doprint, ')')) {
trunclen = otrunclen;
return 0;
}
trunclen = otrunclen;
continue;
}
if (!doprint)
switch(*fm) {
case '[':
while(idigit(*++fm));
while(*++fm != ']');
continue;
case '<':
while(*++fm != '<');
continue;
case '>':
while(*++fm != '>');
continue;
case 'D':
if(fm[1]=='{')
while(*++fm != '}');
continue;
default:
continue;
}
switch (*fm) {
case '~':
promptpath(pwd, arg, 1);
break;
case 'd':
case '/':
promptpath(pwd, arg, 0);
break;
case 'c':
case '.':
promptpath(pwd, arg ? arg : 1, 1);
break;
case 'C':
promptpath(pwd, arg ? arg : 1, 0);
break;
case 'N':
promptpath(scriptname ? scriptname : argzero, arg, 0);
break;
case 'h':
case '!':
addbufspc(DIGBUFSIZE);
convbase(bp, curhist, 10);
bp += strlen(bp);
break;
case 'j':
for (numjobs = 0, j = 1; j <= maxjob; j++)
if (jobtab[j].stat && jobtab[j].procs &&
!(jobtab[j].stat & STAT_NOPRINT)) numjobs++;
addbufspc(DIGBUFSIZE);
sprintf(bp, "%d", numjobs);
bp += strlen(bp);
break;
case 'M':
queue_signals();
if ((hostnam = getsparam("HOST")))
stradd(hostnam);
unqueue_signals();
break;
case 'm':
if (!arg)
arg++;
queue_signals();
if (!(hostnam = getsparam("HOST")))
break;
if (arg < 0) {
for (ss = hostnam + strlen(hostnam); ss > hostnam; ss--)
if (ss[-1] == '.' && !++arg)
break;
stradd(ss);
} else {
for (ss = hostnam; *ss; ss++)
if (*ss == '.' && !--arg)
break;
stradd(*ss ? dupstrpfx(hostnam, ss - hostnam) : hostnam);
}
unqueue_signals();
break;
case 'S':
txtchangeset(TXTSTANDOUT, TXTNOSTANDOUT);
txtset(TXTSTANDOUT);
tsetcap(TCSTANDOUTBEG, 1);
break;
case 's':
txtchangeset(TXTNOSTANDOUT, TXTSTANDOUT);
txtset(TXTDIRTY);
txtunset(TXTSTANDOUT);
tsetcap(TCSTANDOUTEND, 1);
break;
case 'B':
txtchangeset(TXTBOLDFACE, TXTNOBOLDFACE);
txtset(TXTDIRTY);
txtset(TXTBOLDFACE);
tsetcap(TCBOLDFACEBEG, 1);
break;
case 'b':
txtchangeset(TXTNOBOLDFACE, TXTBOLDFACE);
txtchangeset(TXTNOSTANDOUT, TXTSTANDOUT);
txtchangeset(TXTNOUNDERLINE, TXTUNDERLINE);
txtset(TXTDIRTY);
txtunset(TXTBOLDFACE);
tsetcap(TCALLATTRSOFF, 1);
break;
case 'U':
txtchangeset(TXTUNDERLINE, TXTNOUNDERLINE);
txtset(TXTUNDERLINE);
tsetcap(TCUNDERLINEBEG, 1);
break;
case 'u':
txtchangeset(TXTNOUNDERLINE, TXTUNDERLINE);
txtset(TXTDIRTY);
txtunset(TXTUNDERLINE);
tsetcap(TCUNDERLINEEND, 1);
break;
case '[':
if (idigit(*++fm))
arg = zstrtol(fm, &fm, 10);
if (!prompttrunc(arg, ']', doprint, endchar))
return *fm;
break;
case '<':
case '>':
if (!prompttrunc(arg, *fm, doprint, endchar))
return *fm;
break;
case '{': /*}*/
if (!dontcount++) {
addbufspc(1);
*bp++ = Inpar;
}
break;
case /*{*/ '}':
if (trunccount && trunccount >= dontcount)
return *fm;
if (dontcount && !--dontcount) {
addbufspc(1);
*bp++ = Outpar;
}
break;
case 't':
case '@':
case 'T':
case '*':
case 'w':
case 'W':
case 'D':
{
char *tmfmt, *dd;
switch (*fm) {
case 'T':
tmfmt = "%K:%M";
break;
case '*':
tmfmt = "%K:%M:%S";
break;
case 'w':
tmfmt = "%a %f";
break;
case 'W':
tmfmt = "%m/%d/%y";
break;
case 'D':
if (fm[1] == '{' /*}*/) {
for (ss = fm + 2; *ss && *ss != /*{*/ '}'; ss++)
if(*ss == '\\' && ss[1])
ss++;
dd = tmfmt = tmbuf = zalloc(ss - fm);
for (ss = fm + 2; *ss && *ss != /*{*/ '}';
ss++) {
if(*ss == '\\' && ss[1])
ss++;
*dd++ = *ss;
}
*dd = 0;
fm = ss - !*ss;
if (!*tmfmt) {
free(tmbuf);
continue;
}
} else
tmfmt = "%y-%m-%d";
break;
default:
tmfmt = "%l:%M%p";
break;
}
timet = time(NULL);
tm = localtime(&timet);
/*
* Hack because strftime won't say how
* much space it actually needs. Try to add it
* a few times until it works. Some formats don't
* actually have a length, so we could go on for
* ever.
*/
for(j = 0, t0 = strlen(tmfmt)*8; j < 3; j++, t0*=2) {
addbufspc(t0);
if (ztrftime(bp, t0, tmfmt, tm) >= 0)
break;
}
bp += strlen(bp);
free(tmbuf);
tmbuf = NULL;
break;
}
case 'n':
stradd(get_username());
break;
case 'l':
if (*ttystrname) {
ss = (strncmp(ttystrname, "/dev/tty", 8) ?
ttystrname + 5 : ttystrname + 8);
stradd(ss);
} else
stradd("()");
break;
case 'y':
if (*ttystrname) {
ss = (strncmp(ttystrname, "/dev/", 5) ?
ttystrname : ttystrname + 5);
stradd(ss);
} else
stradd("()");
break;
case 'L':
addbufspc(DIGBUFSIZE);
sprintf(bp, "%ld", (long)shlvl);
bp += strlen(bp);
break;
case '?':
addbufspc(DIGBUFSIZE);
sprintf(bp, "%ld", (long)lastval);
bp += strlen(bp);
break;
case '%':
case ')':
addbufspc(1);
*bp++ = *fm;
break;
case '#':
addbufspc(1);
*bp++ = privasserted() ? '#' : '%';
break;
case 'v':
if (!arg)
arg = 1;
else if (arg < 0)
arg += arrlen(psvar) + 1;
if (arg > 0 && arrlen(psvar) >= arg)
stradd(psvar[arg - 1]);
break;
case 'E':
tsetcap(TCCLEAREOL, 1);
break;
case '^':
if (cmdsp) {
if (arg >= 0) {
if (arg > cmdsp || arg == 0)
arg = cmdsp;
for (t0 = cmdsp - 1; arg--; t0--) {
stradd(cmdnames[cmdstack[t0]]);
if (arg) {
addbufspc(1);
*bp++=' ';
}
}
} else {
arg = -arg;
if (arg > cmdsp)
arg = cmdsp;
for (t0 = arg - 1; arg--; t0--) {
stradd(cmdnames[cmdstack[t0]]);
if (arg) {
addbufspc(1);
*bp++=' ';
}
}
}
}
break;
case '_':
if (cmdsp) {
if (arg >= 0) {
if (arg > cmdsp || arg == 0)
arg = cmdsp;
for (t0 = cmdsp - arg; arg--; t0++) {
stradd(cmdnames[cmdstack[t0]]);
if (arg) {
addbufspc(1);
*bp++=' ';
}
}
} else {
arg = -arg;
if (arg > cmdsp)
arg = cmdsp;
for (t0 = 0; arg--; t0++) {
stradd(cmdnames[cmdstack[t0]]);
if (arg) {
addbufspc(1);
*bp++=' ';
}
}
}
}
break;
case 'r':
if(rstring)
stradd(rstring);
break;
case 'R':
if(Rstring)
stradd(Rstring);
break;
case 'i':
addbufspc(DIGBUFSIZE);
sprintf(bp, "%ld", (long)lineno);
bp += strlen(bp);
break;
case '\0':
return 0;
case Meta:
fm++;
break;
}
} else if(*fm == '!' && isset(PROMPTBANG)) {
if(doprint) {
if(fm[1] == '!') {
fm++;
addbufspc(1);
pputc('!');
} else {
addbufspc(DIGBUFSIZE);
convbase(bp, curhist, 10);
bp += strlen(bp);
}
}
} else {
char c = *fm == Meta ? *++fm ^ 32 : *fm;
if (doprint) {
addbufspc(1);
pputc(c);
}
}
}
return *fm;
}
/* pputc adds a character to the buffer, metafying. There must *
* already be space. */
/**/
static void
pputc(char c)
{
if(imeta(STOUC(c))) {
*bp++ = Meta;
c ^= 32;
}
*bp++ = c;
if (c == '\n' && !dontcount)
bufline = bp;
}
/* Make sure there is room for `need' more characters in the buffer. */
/**/
static void
addbufspc(int need)
{
need *= 2; /* for metafication */
if((bp - buf) + need > bufspc) {
int bo = bp - buf;
int bo1 = bp1 ? bp1 - buf : -1;
if(need & 255)
need = (need | 255) + 1;
buf = realloc(buf, bufspc += need);
bp = buf + bo;
if(bo1 != -1)
bp1 = buf + bo1;
}
}
/* stradd() adds a metafied string to the prompt, *
* in a visible representation. */
/**/
void
stradd(char *d)
{
char *ps, *pc;
addbufspc(niceztrlen(d));
/* This loop puts the nice representation of the string into the prompt *
* buffer. */
for(ps=d; *ps; ps++)
for(pc=nicechar(*ps == Meta ? STOUC(*++ps)^32 : STOUC(*ps)); *pc; pc++)
*bp++ = *pc;
}
/* tsetcap(), among other things, can write a termcap string into the buffer. */
/**/
mod_export void
tsetcap(int cap, int flag)
{
if (tccan(cap) && !isset(SINGLELINEZLE) &&
!(termflags & (TERM_NOUP|TERM_BAD|TERM_UNKNOWN))) {
switch(flag) {
case -1:
tputs(tcstr[cap], 1, putraw);
break;
case 0:
tputs(tcstr[cap], 1, putshout);
break;
case 1:
if (!dontcount) {
addbufspc(1);
*bp++ = Inpar;
}
tputs(tcstr[cap], 1, putstr);
if (!dontcount) {
int glitch = 0;
if (cap == TCSTANDOUTBEG || cap == TCSTANDOUTEND)
glitch = tgetnum("sg");
else if (cap == TCUNDERLINEBEG || cap == TCUNDERLINEEND)
glitch = tgetnum("ug");
if(glitch < 0)
glitch = 0;
addbufspc(glitch + 1);
while(glitch--)
*bp++ = Nularg;
*bp++ = Outpar;
}
break;
}
if (txtisset(TXTDIRTY)) {
txtunset(TXTDIRTY);
if (txtisset(TXTBOLDFACE) && cap != TCBOLDFACEBEG)
tsetcap(TCBOLDFACEBEG, flag);
if (txtisset(TXTSTANDOUT))
tsetcap(TCSTANDOUTBEG, flag);
if (txtisset(TXTUNDERLINE))
tsetcap(TCUNDERLINEBEG, flag);
}
}
}
/**/
int
putstr(int d)
{
addbufspc(1);
pputc(d);
return 0;
}
/* Count height etc. of a prompt string returned by promptexpand(). *
* This depends on the current terminal width, and tabs and *
* newlines require nontrivial processing. *
* Passing `overf' as -1 means to ignore columns (absolute width). */
/**/
mod_export void
countprompt(char *str, int *wp, int *hp, int overf)
{
int w = 0, h = 1;
int s = 1;
for(; *str; str++) {
if(w >= columns && overf >= 0) {
w = 0;
h++;
}
if(*str == Meta)
str++;
if(*str == Inpar)
s = 0;
else if(*str == Outpar)
s = 1;
else if(*str == Nularg)
w++;
else if(s) {
if(*str == '\t')
w = (w | 7) + 1;
else if(*str == '\n') {
w = 0;
h++;
} else
w++;
}
}
if(w >= columns && overf >= 0) {
if (!overf || w > columns) {
w = 0;
h++;
}
}
if(wp)
*wp = w;
if(hp)
*hp = h;
}
/**/
static int
prompttrunc(int arg, int truncchar, int doprint, int endchar)
{
if (arg > 0) {
char ch = *fm, *ptr, *truncstr;
int truncatleft = ch == '<';
int w = bp - buf;
/*
* If there is already a truncation active, return so that
* can be finished, backing up so that the new truncation
* can be started afterwards.
*/
if (trunclen) {
while (*--fm != '%')
;
fm--;
return 0;
}
trunclen = arg;
if (*fm != ']')
fm++;
while (*fm && *fm != truncchar) {
if (*fm == '\\' && fm[1])
++fm;
addbufspc(1);
*bp++ = *fm++;
}
if (!*fm)
return 0;
if (bp - buf == w && truncchar == ']') {
addbufspc(1);
*bp++ = '<';
}
ptr = buf + w; /* addbufspc() may have realloc()'d buf */
truncstr = ztrduppfx(ptr, bp - ptr);
bp = ptr;
w = bp - buf;
fm++;
trunccount = dontcount;
putpromptchar(doprint, endchar);
trunccount = 0;
ptr = buf + w; /* putpromptchar() may have realloc()'d */
*bp = '\0';
countprompt(ptr, &w, 0, -1);
if (w > trunclen) {
/*
* We need to truncate. t points to the truncation string -- *
* which is inserted literally, without nice representation. *
* tlen is its length, and maxlen is the amount of the main *
* string that we want to keep. Note that if the truncation *
* string is longer than the truncation length (tlen > *
* trunclen), the truncation string is used in full. *
*/
char *t = truncstr;
int fullen = bp - ptr;
int tlen = ztrlen(t), maxlen;
maxlen = tlen < trunclen ? trunclen - tlen : 0;
if (w < fullen) {
/* Invisible substrings, lots of shuffling. */
int n = strlen(t);
char *p = ptr, *q = buf;
addbufspc(n);
ptr = buf + (p - q); /* addbufspc() may have realloc()'d */
if (truncatleft) {
p = ptr + n;
q = p;
n = fullen - w;
/* Shift the whole string right, then *
* selectively copy to the left. */
memmove(p, ptr, fullen);
while (w > 0 || n > 0) {
if (*p == Inpar)
do {
*q++ = *p;
--n;
} while (*p++ != Outpar && *p && n);
else if (w) {
if (--w < maxlen)
*q++ = *p;
++p;
}
}
bp = q;
} else {
/* Truncate on the right, selectively */
q = ptr + fullen;
/* First skip over as much as will "fit". */
while (w > 0 && maxlen > 0) {
if (*ptr == Inpar)
while (*ptr++ != Outpar && *ptr) {;}
else
++ptr, --w, --maxlen;
}
if (ptr < q) {
/* We didn't reach the end of the string. *
* In case there are more invisible bits, *
* insert the truncstr and keep looking. */
memmove(ptr + n, ptr, q - ptr);
q = ptr + n;
while (*t)
*ptr++ = *t++;
while (*q) {
if (*q == Inpar)
do {
*ptr++ = *q;
} while (*q++ != Outpar && *q);
else
++q;
}
bp = ptr;
*bp = 0;
} else
bp = ptr + n;
}
} else {
/* No invisible substrings. */
if (tlen > fullen) {
addbufspc(tlen - fullen);
ptr = bp; /* addbufspc() may have realloc()'d buf */
bp += tlen - fullen;
} else
bp -= fullen - trunclen;
if (truncatleft) {
if (maxlen)
memmove(ptr + strlen(t), ptr + fullen - maxlen,
maxlen);
} else
ptr += maxlen;
}
/* Finally, copy the truncstr into place. */
while (*t)
*ptr++ = *t++;
}
zsfree(truncstr);
trunclen = 0;
/*
* We may have returned early from the previous putpromptchar *
* because we found another truncation following this one. *
* In that case we need to do the rest now. *
*/
if (!*fm)
return 0;
if (*fm != endchar) {
fm++;
/*
* With trunclen set to zero, we always reach endchar *
* (or the terminating NULL) this time round. *
*/
if (!putpromptchar(doprint, endchar))
return 0;
}
/* Now we have to trick it into matching endchar again */
fm--;
} else {
if (*fm != ']')
fm++;
while(*fm && *fm != truncchar) {
if (*fm == '\\' && fm[1])
fm++;
fm++;
}
if (trunclen || !*fm)
return 0;
}
return 1;
}