Yet another refinement... This function wraps a string at a given
width, but also respects embedded HTML, so HTML links are not broken.
Basically, this would be a fairly drop-in replacement for the exitsing
wordwrap function, with the addition of the HTMLmode parameter...
-Brad
---------------------- Start of code ----------------------
/* BF 5/24/01 ([EMAIL PROTECTED]) */
str = the string to wrap
width = the width to wrap lines at
newline = the string used to separate lines at the new break points
hard = whether words longer than width are wrapped
HTMLmode = whether to treat the text as containing HTML (entities,
tags, etc)
- doesn't wrap text in HTML tags
- doesn't count length of HTML tags in line widths
- treats HTML entities as a single character when
wrapping
*/
PHP_FUNCTION(il_str_wrap)
{
zval **_str, // The string to wrap
**_width = NULL, // The width to wrap lines at
**_newline = NULL, // The string used to separate new
lines
**_hard = NULL, // Whether words longer than <width>
are wrapped
**_htmlmode = NULL; // Whether to use HTML mode
char *newline = "\n"; // Default newline character
int width = 80; // Default width
int hard = 0; // Do not break words longer than width
int htmlmode = 0; // Don't use HTML mode
int slen;
int myargc = ZEND_NUM_ARGS();
if (myargc < 1 || myargc > 5 ||
zend_get_parameters_ex(myargc, &_str, &_width, &_newline,
&_hard, &_htmlmode) == FAILURE)
{
ZEND_WRONG_PARAM_COUNT();
} //if
// Convert the parameters to the appropriate types
convert_to_string_ex(_str);
if (myargc > 1) {
convert_to_long_ex(_width);
width = Z_LVAL_PP(_width);
if (myargc > 2) {
convert_to_string_ex(_newline);
newline = Z_STRVAL_PP(_newline);
if (myargc > 3) {
convert_to_boolean_ex(_hard);
hard = Z_LVAL_PP(_hard);
if (myargc > 4) {
convert_to_boolean_ex(_htmlmode);
htmlmode = Z_LVAL_PP(_htmlmode);
} // if
} // if
} // if
} // if
slen = Z_STRLEN_PP(_str);
{ // Begin code block (for localized vars)
int newlinelen = strlen(newline);
int buffactor = (slen + newlinelen);
int bufsize = buffactor * 2;
char* buf = emalloc(bufsize);
int buflen = 0;
int newbuflen;
int len;
int linelen = 0;
int inhtml = 0;
int lwplen;
char htmlend;
char* str = Z_STRVAL_PP(_str);
char *p, *sp, *lwp, *lastp;
p = str;
sp = p;
lastp = str + (slen * sizeof(char));
while (sp < lastp) {
if (inhtml) {
if (*sp == htmlend) inhtml = 0;
} else if (htmlmode && (*sp == '<')) {
inhtml = 1;
htmlend = '>';
} else if (htmlmode && (*sp == '&')) {
inhtml = 2;
htmlend = ';';
++linelen; // Count entities as one
character
// Perhaps this should check for entities using a "smarter" algorithm?
// This will break on some bad HTML code (ie. broken entities)
} else if (*sp == '\n') {
len = (sp - p) / sizeof(char);
newbuflen = buflen + len + newlinelen;
if (newbuflen >= bufsize) {
bufsize = newbuflen + buffactor;
buf = erealloc(buf, bufsize);
} //if
// Copy this portion in
strncpy(&buf[buflen], p, len);
// Copy the newline string in
strcpy(&buf[buflen + len], newline);
buflen = newbuflen;
p = sp + sizeof(char);
lwp = NULL;
linelen = 0;
} else {
++linelen;
++lwplen;
if (isspace(*sp)) {
lwp = sp;
lwplen = 1;
} //if
if ((linelen > width) && (lwp || hard))
{
char *ep;
if (lwp) {
ep = lwp;
lwp = NULL;
linelen = lwplen;
} else {
ep = sp;
linelen = 1;
} //if
len = (ep - p) / sizeof(char);
// Grow the buffer if needed
newbuflen = buflen + len +
newlinelen;
if (newbuflen >= bufsize) {
bufsize = newbuflen +
buffactor;
buf = erealloc(buf,
bufsize);
} //if
// Copy this portion in
strncpy(&buf[buflen], p, len);
// Copy the newline string in
strcpy(&buf[buflen + len],
newline);
buflen = newbuflen;
p = ep;
// while (isblank(*p))
// p += sizeof(char);
} //if
} //if
sp += sizeof(char);
} //while
// Copy the remaining string
/////////////////////////////////////
// Reallocate the buffer to the appropriate size
len = slen - ((p - str) / sizeof(char));
bufsize = buflen + len;
buf = erealloc(buf, bufsize + 1);
// Copy the string
strcpy(&buf[buflen], p);
buf[bufsize] = 0;
RETURN_STRINGL(buf, bufsize, 0);
} //Code block
} // PHP_FUNCTION(str_wrap)
/* }}} */
--
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php