I wrote this very simple function (modification from nl2br actually) to convert newlines to well formatted HTML paragraphs instead of line breaks, allowing better formatting of a dynamic output. It's not the most perfect piece of code ever written, but it works and it can be quite useful.

The <br /> tag does not have as much possibilities as the <p> tag when it comes to CSS, which gave me the idea to write this function.

--
Louis-Philippe Huberdeau


--- BEGIN ---


/* {{{ proto string nl2p(string str)
   Converts newlines to HTML paragraphs for standard compliance */
PHP_FUNCTION(nl2p)
{
        /* in brief this inserts </p>\n<p> before matched regexp \n\r?|\r\n? ,
           <p> before the string and </p> after the string */
        zval    **zstr;
        char    *tmp, *str;
        int     new_length;
        char    *end, *target;
        int     repl_cnt = 0;
        int seen_other_char = 0;

        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zstr) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        
        convert_to_string_ex(zstr);

str = Z_STRVAL_PP(zstr);
end = str + Z_STRLEN_PP(zstr);

/* it is really faster to scan twice and allocate mem once insted scanning once
and constantly reallocing */
while (str < end) {
if( seen_other_char ) {
if (*str == '\r') {
if (*(str+1) == '\n') {
str++;
}
repl_cnt++;


                                seen_other_char = 0;
                        } else if (*str == '\n') {
                                if (*(str+1) == '\r') {
                                        str++;
                                }
                                repl_cnt++;

                                seen_other_char = 0;
                        }
                } else if( *str != '\n' && *str != '\r' ) {
                        seen_other_char = 1;
                }
                
                str++;
        }
        
        if (repl_cnt == 0) {
                RETURN_STRINGL(Z_STRVAL_PP(zstr), Z_STRLEN_PP(zstr), 1);
        }

new_length = Z_STRLEN_PP(zstr) + repl_cnt * (sizeof("\n</p>\n<p>") - 1) + sizeof("\n<p>\n") + sizeof("\n</p>");
tmp = target = emalloc(new_length + 1);


str = Z_STRVAL_PP(zstr);

        *target++ = '\n';
        *target++ = '<';
        *target++ = 'p';
        *target++ = '>';
        *target++ = '\n';

seen_other_char = 0;

while (str < end) {
switch (*str) {
case '\r':
case '\n':
if( seen_other_char ) {
*target++ = '\n';
*target++ = '<';
*target++ = '/';
*target++ = 'p';
*target++ = '>';
*target++ = '\n';
*target++ = '<';
*target++ = 'p';
*target++ = '>';

if ((*str == '\r' && *(str+1) == '\n') || (*str == '\n' && *(str+1) == '\r')) {
*target++ = *str++;
}


                                        seen_other_char = 0;
                                }

                                *target++ = *str;
                                break;
                        default:
                                seen_other_char = 1;
                                *target++ = *str;
                }
        
                str++;
        }

        *target++ = '\n';
        *target++ = '<';
        *target++ = '/';
        *target++ = 'p';
        *target++ = '>';
        *target++ = '\n';
        
        *target = '\0';

        RETURN_STRINGL(tmp, new_length, 0);
}
/* }}} */


--- END ---


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Reply via email to