717 lines
15 KiB
C
717 lines
15 KiB
C
/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
|
||
* This software is quasi-public; it may be used freely with
|
||
* like software, but may NOT be sold or made part of licensed
|
||
* products without permission of the author.
|
||
*/
|
||
/* EEEDIT - E-type routines */
|
||
|
||
#include "elle.h"
|
||
|
||
/* E_ - Operate on cur_buf. Do not change value of cur_dot unless
|
||
* unavoidable side effect (also e_setcur).
|
||
* EX_ - Like E_ but take SB ptr value. Never touch cur_dot.
|
||
* ED_ - Like E_, operate on cur_buf, update cur_dot and display stuff.
|
||
* D_ - Perform necessary display update for given operations.
|
||
*
|
||
* Note that "dot" refers to the current read/write pointer for a sbbuffer.
|
||
* The name comes from EMACS/TECO where "." represents this value.
|
||
*/
|
||
|
||
#define CURSBB (SBBUF *)cur_buf /* Shorthand for current SB buffer */
|
||
|
||
e_reset() /* Reset current buffer */
|
||
{ ex_reset(CURSBB);
|
||
cur_dot = 0;
|
||
}
|
||
|
||
/* Basic functions - apply SB routines to current buffer.
|
||
* There is some optimization here which knows that certain SB functions
|
||
* are macros.
|
||
*/
|
||
e_rgetc() /* Read/move 1 char backward */
|
||
{ return(sb_rgetc((CURSBB)));
|
||
}
|
||
e_rdelc() /* Delete 1 char backward */
|
||
{ return(sb_rdelc((CURSBB)));
|
||
}
|
||
e_delc() /* Delete 1 char forward */
|
||
{ return(sb_deln(CURSBB,(chroff)1));
|
||
}
|
||
e_getc() /* Read/move 1 char forward */
|
||
{ register SBBUF *sb;
|
||
sb = CURSBB; /* Macro: use reg */
|
||
return(sb_getc(sb));
|
||
}
|
||
e_backc() /* Move 1 char backward */
|
||
{ register SBBUF *sb;
|
||
sb = CURSBB; /* Macro: use reg */
|
||
sb_backc(sb); /* No value returned */
|
||
}
|
||
e_putc(c) /* Insert/write 1 char forward */
|
||
char c;
|
||
{ register SBBUF *sb;
|
||
sb = CURSBB; /* Macro: use reg */
|
||
return(sb_putc(sb, c));
|
||
}
|
||
e_peekc() /* Read 1 char forward (no move) */
|
||
{ register SBBUF *sb;
|
||
sb = CURSBB; /* Macro: use reg */
|
||
return(sb_peekc(sb));
|
||
}
|
||
e_ovwc(ch) /* Overwrite 1 char forward */
|
||
char ch;
|
||
{
|
||
sb_setovw(CURSBB); /* Turn on overwrite mode */
|
||
e_putc(ch);
|
||
sb_clrovw(CURSBB); /* Turn off overwrite mode */
|
||
}
|
||
|
||
SBSTR *
|
||
e_copyn(off) /* Copy N chars forward/backward, return SD to sbstring */
|
||
chroff off;
|
||
{ return(sb_cpyn(CURSBB,off));
|
||
}
|
||
e_deln(off) /* Delete N chars forward/backward */
|
||
chroff off;
|
||
{ return(sb_deln(CURSBB, off));
|
||
}
|
||
|
||
/* E_SETCUR() - set cur_dot to current position (dot). This is the only
|
||
* E_ routine that mungs cur_dot except for e_reset.
|
||
*/
|
||
e_setcur()
|
||
{ cur_dot = e_dot();
|
||
}
|
||
e_gosetcur(dot) /* Go to specified dot and set cur_dot as well */
|
||
chroff dot;
|
||
{ sb_seek(CURSBB,dot,0);
|
||
e_setcur(); /* Not cur_dot = dot since want canonicalization */
|
||
}
|
||
|
||
/* E_GO(dot) - Move to specified location. */
|
||
/* These "GO" routines all move to the location specified, returning
|
||
* 0 if successful and -1 on error. "cur_dot" is never changed,
|
||
* with the exception of e_gosetcur.
|
||
* Note that other "GO" routines (eg E_GONL) will return 1 if successful
|
||
* and 0 if stopped by EOF.
|
||
*/
|
||
|
||
e_gocur() { return(e_go(cur_dot)); } /* Move to cur_dot */
|
||
e_gobob() { return(e_go((chroff) 0)); } /* Move to Beg Of Buffer */
|
||
e_goeob() { return(sb_seek(CURSBB,(chroff)0,2)); } /* Move to End Of Buffer */
|
||
e_go(dot) /* Move to specified location. */
|
||
chroff dot;
|
||
{ return(sb_seek(CURSBB,dot,0));
|
||
}
|
||
e_igoff(ioff) /* Move (int) N chars forward/backward */
|
||
int ioff;
|
||
{ return(sb_seek(CURSBB,(chroff)ioff,1));
|
||
}
|
||
|
||
e_goff(off) /* Move (full) N chars forward/backward */
|
||
chroff off;
|
||
{ return(sb_seek(CURSBB,off,1));
|
||
}
|
||
|
||
int ex_gonl(), ex_gopl(), ex_gobol(), ex_goeol();
|
||
|
||
e_gobol() { return(ex_gobol(CURSBB)); } /* Move to beg of this line */
|
||
e_goeol() { return(ex_goeol(CURSBB)); } /* Move to end of this line */
|
||
e_gonl() { return(ex_gonl(CURSBB)); } /* Move to beg of next line */
|
||
e_gopl() { return(ex_gopl(CURSBB)); } /* Move to beg of prev line */
|
||
|
||
|
||
/* E_DOT() - Return current value of dot. */
|
||
chroff e_dot() { return(sb_tell(CURSBB)); } /* Current pos */
|
||
chroff e_nldot() { return(e_alldot(CURSBB,ex_gonl)); } /* Beg of next line */
|
||
chroff e_pldot() { return(e_alldot(CURSBB,ex_gopl)); } /* Beg of prev line */
|
||
chroff e_boldot(){ return(e_alldot(CURSBB,ex_gobol));} /* Beg of this line */
|
||
chroff e_eoldot(){ return(e_alldot(CURSBB,ex_goeol));} /* End of this line */
|
||
|
||
chroff
|
||
e_alldot(sbp,rtn) /* Auxiliary for above stuff */
|
||
SBBUF *sbp;
|
||
int (*rtn)();
|
||
{ return(ex_alldot(sbp,rtn,e_dot()));
|
||
}
|
||
|
||
/* E_BLEN - Return length of current buffer */
|
||
chroff
|
||
e_blen() { return(ex_blen(CURSBB)); }
|
||
|
||
/* EX_ routines - similar to E_ but take a buffer/sbbuf argument
|
||
* instead of assuming current buffer.
|
||
*/
|
||
|
||
/* EX_RESET - Reset a given buffer */
|
||
ex_reset(b)
|
||
struct buffer *b;
|
||
{ sbs_del(sb_close((SBBUF *)b));
|
||
sb_open((SBBUF *)b,(SBSTR *)0);
|
||
}
|
||
|
||
ex_go(sbp,loc) /* Move to given dot in specified sbbuf */
|
||
chroff loc;
|
||
SBBUF *sbp;
|
||
{ return(sb_seek(sbp,loc,0));
|
||
}
|
||
|
||
chroff
|
||
ex_dot(sbp) /* Return current position in specified sbbuf */
|
||
SBBUF *sbp;
|
||
{
|
||
return(sb_tell(sbp));
|
||
}
|
||
|
||
|
||
chroff
|
||
ex_boldot(sbp,dot) /* Return dot for BOL of specified sbbuf */
|
||
SBBUF *sbp;
|
||
chroff dot;
|
||
{ return(ex_alldot(sbp,ex_gobol,dot));
|
||
}
|
||
|
||
chroff
|
||
ex_alldot(sbp,rtn,dot) /* Auxiliary for some e_ stuff */
|
||
SBBUF *sbp;
|
||
int (*rtn)();
|
||
chroff dot;
|
||
{ register SBBUF *sb;
|
||
chroff savloc, retloc;
|
||
|
||
savloc = sb_tell(sb = sbp);
|
||
sb_seek(sb,dot,0);
|
||
(*rtn)(sb);
|
||
retloc = sb_tell(sb);
|
||
sb_seek(sb,savloc,0);
|
||
return(retloc);
|
||
}
|
||
|
||
/* GO (forward) to Next Line of specified sbbuf - returns 0 if stopped at EOF
|
||
* before an EOL is seen. */
|
||
ex_gonl(sbp)
|
||
SBBUF *sbp;
|
||
{ register SBBUF *sb;
|
||
register int c;
|
||
sb = sbp;
|
||
#if FX_EOLMODE
|
||
if(eolcrlf(sb))
|
||
while((c = sb_getc(sb)) != EOF)
|
||
{ if(c == LF) /* Possible EOL? */
|
||
{ sb_backc(sb); /* See if prev char was CR */
|
||
if((c = sb_rgetc(sb)) != EOF)
|
||
sb_getc(sb);
|
||
sb_getc(sb); /* Must restore position */
|
||
if(c == CR) /* Now test for CR */
|
||
return(1); /* Won, CR-LF! */
|
||
}
|
||
}
|
||
else
|
||
#endif
|
||
while((c = sb_getc(sb)) != EOF)
|
||
if(c == LF)
|
||
return(1);
|
||
return(0);
|
||
}
|
||
|
||
/* GO (forward) to End Of Line of specified sbbuf - returns 0 if stopped at
|
||
* EOF before an EOL is seen. */
|
||
ex_goeol(sbp)
|
||
SBBUF *sbp;
|
||
{ register SBBUF *sb;
|
||
register int c;
|
||
sb = sbp;
|
||
#if FX_EOLMODE
|
||
if(eolcrlf(sb))
|
||
while((c = sb_getc(sb)) != EOF)
|
||
{ if(c == LF) /* Possible EOL? */
|
||
{ sb_backc(sb); /* See if prev char was CR */
|
||
if((c = sb_rgetc(sb)) == CR)
|
||
return(1); /* Won, CR-LF! */
|
||
if(c != EOF) /* No, must restore position */
|
||
sb_getc(sb); /* Skip over */
|
||
sb_getc(sb); /* Skip over LF */
|
||
}
|
||
}
|
||
else
|
||
#endif
|
||
while((c = sb_getc(sb)) != EOF)
|
||
if(c == LF)
|
||
{ sb_backc(sb);
|
||
return(1);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
/* GO (backward) to Beg Of Line of specified sbbuf - returns 0 if stopped
|
||
* at EOF
|
||
*/
|
||
ex_gobol(sbp)
|
||
SBBUF *sbp;
|
||
{ register SBBUF *sb;
|
||
register int c;
|
||
sb = sbp;
|
||
#if FX_EOLMODE
|
||
if(eolcrlf(sb))
|
||
while((c = sb_rgetc(sb)) != EOF)
|
||
{ if(c == LF) /* Possible EOL? */
|
||
{ if((c = sb_rgetc(sb)) == CR)
|
||
{ sb_getc(sb); /* Won, CR-LF! */
|
||
sb_getc(sb); /* Move back */
|
||
return(1);
|
||
}
|
||
if(c != EOF) /* No, must restore position */
|
||
sb_getc(sb); /* Undo the rgetc */
|
||
}
|
||
}
|
||
else
|
||
#endif
|
||
while((c = sb_rgetc(sb)) != EOF)
|
||
if(c == LF)
|
||
{ sb_getc(sb);
|
||
return(1);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
/* GO (backward) to Previous Line of specified sbbuf - returns 0 if stopped
|
||
* at EOF before an EOL is seen (i.e. if already on 1st line of buffer)
|
||
*/
|
||
ex_gopl(sbp)
|
||
SBBUF *sbp;
|
||
{ register SBBUF *sb;
|
||
register int c;
|
||
sb = sbp;
|
||
#if FX_EOLMODE
|
||
if(eolcrlf(sb))
|
||
while((c = sb_rgetc(sb)) != EOF)
|
||
{ if(c == LF) /* Possible EOL? */
|
||
{ if((c = sb_rgetc(sb)) == CR)
|
||
{ ex_gobol(sb);
|
||
return(1); /* Won! */
|
||
}
|
||
if(c != EOF) /* No, must restore position */
|
||
sb_getc(sb); /* Undo the rgetc */
|
||
}
|
||
}
|
||
else
|
||
#endif
|
||
while((c = sb_rgetc(sb)) != EOF)
|
||
if(c == LF)
|
||
{ ex_gobol(sb);
|
||
return(1); /* Won! */
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
|
||
chroff
|
||
ex_blen(sbp) /* Return length of specified sbbuf */
|
||
SBBUF *sbp;
|
||
{
|
||
return(sb_tell(sbp)+sb_ztell(sbp));
|
||
}
|
||
|
||
/* Miscellaneous stuff */
|
||
|
||
/* E_GOFWSP() - Forward over whitespace */
|
||
e_gofwsp()
|
||
{ register int c;
|
||
while((c = e_getc()) == SP || c == TAB);
|
||
if(c != EOF) e_backc();
|
||
}
|
||
|
||
/* E_GOBWSP() - Backward over whitespace */
|
||
e_gobwsp()
|
||
{ register int c;
|
||
while((c = e_rgetc()) == SP || c == TAB);
|
||
if(c != EOF) e_getc();
|
||
}
|
||
|
||
|
||
/* E_GOLINE(n) - Goes N lines forward (or backward).
|
||
** If N == 0, goes to beginning of current line.
|
||
** Returns 0 if hit EOF.
|
||
*/
|
||
e_goline(i)
|
||
register int i;
|
||
{
|
||
if(i > 0)
|
||
{ do { if(!e_gonl()) return(0); }
|
||
while(--i);
|
||
}
|
||
else if(i < 0)
|
||
{ i = -i;
|
||
do { if(!e_gopl()) return(0); }
|
||
while(--i);
|
||
}
|
||
else e_gobol(); /* arg of 0 */
|
||
return 1;
|
||
}
|
||
|
||
/* E_LBLANKP() - Returns true if all characters in rest of line are blank.
|
||
* Moves to beginning of next line as side effect, unless fails.
|
||
*/
|
||
e_lblankp()
|
||
{ register int c;
|
||
for(;;) switch(e_getc())
|
||
{
|
||
case SP:
|
||
case TAB:
|
||
continue;
|
||
case LF: /* Normally drop thru to return 1 as for EOF */
|
||
#if FX_EOLMODE
|
||
if(eolcrlf(cur_buf))
|
||
{ e_rgetc();
|
||
if((c = e_rgetc()) != EOF) /* Get prev char */
|
||
e_getc();
|
||
e_getc();
|
||
if(c != CR) /* Now examine */
|
||
continue; /* Not CR-LF, go on */
|
||
} /* Else drop thru to return win */
|
||
#endif
|
||
case EOF:
|
||
return(1);
|
||
default:
|
||
return(0);
|
||
}
|
||
/* Never drops out */
|
||
}
|
||
|
||
|
||
e_insn(ch, cnt)
|
||
int ch;
|
||
int cnt;
|
||
{ register int i;
|
||
if((i = cnt) > 0)
|
||
do { e_putc(ch);
|
||
} while(--i);
|
||
}
|
||
|
||
e_sputz(acp)
|
||
char *acp;
|
||
{ register SBBUF *sb;
|
||
register char *cp;
|
||
register int c;
|
||
if(cp = acp)
|
||
{ sb = CURSBB;
|
||
while(c = *cp++)
|
||
sb_putc(sb,c);
|
||
}
|
||
}
|
||
|
||
/* BOLEQ - Returns TRUE if 2 dots are on the same line
|
||
* (i.e. have the same Beg-Of-Line)
|
||
*/
|
||
boleq(dot1,dot2)
|
||
chroff dot1,dot2;
|
||
{ return( (ex_boldot(CURSBB,dot1) == ex_boldot(CURSBB,dot2)));
|
||
}
|
||
|
||
|
||
char *
|
||
dottoa(str,val)
|
||
char *str;
|
||
chroff val;
|
||
{ register char *s;
|
||
|
||
s = str;
|
||
if(val < 0)
|
||
{ *s++ = '-';
|
||
val = -val;
|
||
}
|
||
if(val >= 10)
|
||
s = dottoa(s, val/10);
|
||
*s++ = '0' + (int)(val%10);
|
||
*s = 0;
|
||
return(s);
|
||
}
|
||
|
||
|
||
/* Paragraph utilities */
|
||
|
||
#if FX_FPARA || FX_BPARA || FX_MRKPARA || FX_FILLPARA
|
||
|
||
#if FX_SFPREF
|
||
extern char *fill_prefix; /* Defined in eefill.c for now */
|
||
extern int fill_plen; /* Ditto */
|
||
#endif /*FX_SFPREF*/
|
||
|
||
#if ICONOGRAPHICS
|
||
int para_mode = PARABLOCK; /* eexcmd.c only other file that refs this */
|
||
#endif /*ICONOGRAPHICS*/
|
||
|
||
|
||
/* Go to beginning of paragraph */
|
||
e_gobpa()
|
||
{ register int c;
|
||
chroff savdot;
|
||
|
||
savdot = e_dot();
|
||
e_bwsp();
|
||
while((c = e_rgetc()) != EOF)
|
||
if(c == LF) /* Went past line? */
|
||
{ e_getc(); /* Back up and check */
|
||
#if FX_SFPREF
|
||
if(fill_plen)
|
||
if(tstfillp(fill_plen))
|
||
{ e_igoff(-(fill_plen+1));
|
||
continue;
|
||
}
|
||
else break;
|
||
#endif /*FX_SFPREF*/
|
||
#if ICONOGRAPHICS
|
||
c = e_peekc ();
|
||
|
||
if (para_mode == PARABLOCK)
|
||
if (c == LF)
|
||
break;
|
||
|
||
if (para_mode == PARALINE)
|
||
if (c_wsp (c))
|
||
break;
|
||
#else
|
||
if(c_pwsp(e_peekc())) /* Check 1st chr for wsp */
|
||
break; /* If wsp, done */
|
||
#endif /*ICONOGRAPHICS*/
|
||
e_rgetc(); /* Nope, continue */
|
||
}
|
||
if((c = e_peekc()) == '.' || c == '-')
|
||
{ e_gonl();
|
||
if(e_dot() >= savdot)
|
||
e_gopl();
|
||
}
|
||
}
|
||
|
||
/* Go to end of paragraph */
|
||
e_goepa()
|
||
{ register int c;
|
||
|
||
e_gobol(); /* First go to beg of cur line */
|
||
e_fwsp();
|
||
while((c = e_getc()) != EOF)
|
||
if (c == LF)
|
||
{
|
||
#if FX_SFPREF
|
||
if(fill_plen) /* If Fill Prefix is defined */
|
||
if(tstfillp(fill_plen)) /* then must start with it */
|
||
continue;
|
||
else break; /* or else we're done */
|
||
#endif /*FX_SFPREF*/
|
||
#if ICONOGRAPHICS
|
||
if (para_mode == PARABLOCK)
|
||
if (e_peekc () == LF)
|
||
break;
|
||
|
||
if (para_mode == PARALINE)
|
||
if (c_wsp (e_peekc ()))
|
||
break;
|
||
#else
|
||
if(c_pwsp(e_peekc()))
|
||
break;
|
||
#endif /*-ICONOGRAPHICS*/
|
||
}
|
||
}
|
||
|
||
exp_do(rpos, rneg)
|
||
int (*rpos)(), (*rneg)();
|
||
{ register int e;
|
||
register int (*rtn)();
|
||
|
||
if((e = exp) == 0)
|
||
return;
|
||
rtn = rpos;
|
||
if(e < 0)
|
||
{ rtn = rneg;
|
||
e = -e;
|
||
}
|
||
do { (*rtn)();
|
||
} while(--e);
|
||
}
|
||
|
||
|
||
e_fwsp()
|
||
{ register int c;
|
||
while(c_wsp(c = e_getc()));
|
||
if(c != EOF) e_backc();
|
||
}
|
||
e_bwsp()
|
||
{ register int c;
|
||
while(c_wsp(c = e_rgetc()));
|
||
if(c != EOF) e_getc();
|
||
}
|
||
|
||
|
||
c_wsp(ch)
|
||
int ch;
|
||
{ register int c;
|
||
c = ch;
|
||
if(c == SP || c == TAB || c == LF || c == FF)
|
||
return(1);
|
||
return(0);
|
||
}
|
||
c_pwsp(ch)
|
||
int ch;
|
||
{ register int c;
|
||
c = ch;
|
||
if(c == '.' || c == '-')
|
||
return(1);
|
||
return(c_wsp(c));
|
||
}
|
||
|
||
#endif /* FX_FPARA || FX_BPARA || FX_MRKPARA || FX_FILLPARA */
|
||
|
||
/* Word function auxiliaries */
|
||
|
||
/* Returns true if this character is a delimiter. */
|
||
delimp(c)
|
||
int c;
|
||
{ static int delim_tab[] =
|
||
{
|
||
0177777, 0177777, /* All controls */
|
||
0177777, 0176000, /* All punct but 0-9 */
|
||
0000001, 0074000, /* All punct but A-Z and _ */
|
||
0000001, 0174000 /* All punct but a-z */
|
||
};
|
||
return (delim_tab[c >> 4] & (1 << (c & 017)));
|
||
}
|
||
|
||
e_wding(adot,n)
|
||
register chroff *adot;
|
||
int n;
|
||
{ chroff savdot;
|
||
savdot = e_dot();
|
||
e_gowd(n);
|
||
*adot = e_dot();
|
||
e_go(savdot);
|
||
if(*adot == savdot)
|
||
{ ring_bell();
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
chroff
|
||
e_wdot(dot,n)
|
||
chroff dot;
|
||
int n;
|
||
{ chroff savdot, retdot;
|
||
savdot = e_dot();
|
||
e_go(dot);
|
||
e_gowd(n);
|
||
retdot = e_dot();
|
||
e_go(savdot);
|
||
return(retdot);
|
||
}
|
||
e_gowd(n)
|
||
int n;
|
||
{ register int (*gch)(), c, cnt;
|
||
int e_getc(), e_rgetc();
|
||
chroff ret_dot;
|
||
|
||
if((cnt = n) == 0)
|
||
return;
|
||
if(cnt > 0)
|
||
gch = e_getc; /* Forward routine */
|
||
else
|
||
{ gch = e_rgetc; /* Backward routine */
|
||
cnt = -cnt;
|
||
}
|
||
do
|
||
{ ret_dot = e_dot(); /* Remember dot for last word found */
|
||
while((c = (*gch)()) != EOF && delimp(c));
|
||
if(c == EOF)
|
||
{ e_go(ret_dot); /* Use last word found */
|
||
break;
|
||
}
|
||
while((c = (*gch)()) != EOF && !delimp(c));
|
||
if(c == EOF)
|
||
break;
|
||
if(n < 0) e_getc(); else e_backc();
|
||
} while(--cnt);
|
||
}
|
||
|
||
/* Searching */
|
||
|
||
e_search(mstr,mlen,backwards)
|
||
char *mstr;
|
||
int mlen;
|
||
int backwards;
|
||
{ register SBBUF *sb;
|
||
register char *cp;
|
||
register int c;
|
||
char *savcp;
|
||
int cnt, scnt;
|
||
#if IMAGEN
|
||
register int c1;
|
||
register int caseless = (cur_buf->b_flags & B_TEXTMODE);
|
||
#endif /*IMAGEN*/
|
||
|
||
sb = (SBBUF *) cur_buf;
|
||
if (!backwards)
|
||
{ /* Search forwards */
|
||
sfwd: cp = mstr;
|
||
while((c = sb_getc(sb)) != EOF)
|
||
{
|
||
#if IMAGEN
|
||
if((!caseless && c != *cp) ||
|
||
(caseless && upcase(c) != upcase(*cp))) continue;
|
||
#else
|
||
if(c != *cp) continue;
|
||
#endif /*-IMAGEN*/
|
||
cp++;
|
||
cnt = mlen;
|
||
while(--cnt > 0)
|
||
{
|
||
#if IMAGEN
|
||
c1 = *cp++;
|
||
c = e_getc();
|
||
if ((!caseless && c1 != c) ||
|
||
(caseless && upcase(c1) != upcase(c)))
|
||
#else
|
||
if(*cp++ != (c = e_getc()))
|
||
#endif /*-IMAGEN*/
|
||
{ if(c == EOF) return(0);
|
||
sb_seek(sb,(chroff)(cnt-mlen),1);
|
||
goto sfwd;
|
||
}
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
else
|
||
{ /* Search backwards */
|
||
scnt = mlen - 1;
|
||
savcp = mstr + scnt; /* Point to end of string */
|
||
|
||
sbck: cp = savcp;
|
||
while((c = sb_rgetc(sb)) != EOF)
|
||
{
|
||
#if IMAGEN
|
||
if((!caseless && c != *cp) ||
|
||
(caseless && upcase(c) != upcase(*cp))) continue;
|
||
#else
|
||
if(c != *cp) continue;
|
||
#endif /*-IMAGEN*/
|
||
cp--;
|
||
if((cnt = scnt) == 0) return(1);
|
||
do
|
||
{
|
||
#if IMAGEN
|
||
c1 = *cp--;
|
||
c = e_rgetc();
|
||
if ((!caseless && c1 != c) ||
|
||
(caseless && upcase(c1) != upcase(c)))
|
||
#else
|
||
if(*cp-- != (c = e_rgetc()))
|
||
#endif /*-IMAGEN*/
|
||
{ if(c == EOF) return(0);
|
||
sb_seek(sb,(chroff)(mlen-cnt),1);
|
||
goto sbck;
|
||
}
|
||
}
|
||
while(--cnt);
|
||
return(1);
|
||
}
|
||
}
|
||
return(0); /* Failed */
|
||
}
|