Re: XForms: Wraping in multiline input

From: Steve Lamont (spl@ncmir.ucsd.edu)
Date: Fri Sep 15 2000 - 11:39:34 EDT

  • Next message: Ronald Joe Record: "XForms: XForms distribution for UnixWare"

    # To subscribers of the xforms list from Steve Lamont <spl@ncmir.ucsd.edu> :

    > I have read the XForms documentation over and over again but I couldn't find
    > any reference on making a multiline input wrap at the end of the line.
    > If someone knows how to do it, please tell me ...

    There isn't a provision for it currently.

    You can add line wrap using an input filter. Here's a quick hack that
    I did as a "proof-of-concept:"

                                    - - -
    #define MAX_CHARS_PER_LINE 30

    static int filter( FL_OBJECT *obj, const char *old, const char *cur, int c )

    {

        if ( c == ' ' ) {

            int lines = fl_get_input_numberoflines( obj );
            int l;
            char *buffer = strdup( cur );
            char *b = buffer;
            char **text = ( char **) malloc( ( lines + 1 ) * sizeof( char *) );
            int x;
            int y;
            int line_length;
            
            for ( l = 0; l < lines; l++ ) {

                text[l] = strdup( strtok( b, "\n" ) );
                b = NULL;
                
            }

            fl_get_input_cursorpos( obj, &x, &y );
            
            if ( ( line_length = strlen( text[y - 1] ) ) > MAX_CHARS_PER_LINE ) {
                
                int pos;
                char *line = text[y - 1];
                char *new_line = NULL;

                /*
                 * Find the last non-whitespace character in the line.
                 */

                for ( pos = strlen( line ) - 1; pos > 0; pos-- )
                    if ( !isspace( line[pos] ) )
                        break;

                /*
                 * Now that we're in non-whitespace, look for the beginning
                 * of this token.
                 */

                for ( ; pos > 0; pos-- )
                    if ( isspace( line[pos] ) )
                        break;
                
                /*
                 * If this doesn't start at the beginning of the line, then
                 * we can insert a line break.
                 */

                if ( pos > 0 ) {

                    int buffer_length = 0;
                    
                    /*
                     * This will be the new line.
                     */

                    new_line = strdup( line + pos + 1 );

                    /*
                     * Now eat any whitespace trailing the original line
                     * from where we truncated it for the line break and
                     * trim it.
                     */

                    for ( ; pos >= 0; pos-- )
                        if ( !isspace( line[pos] ) )
                            break;
                    text[y - 1][pos + 1] = '\0';
                    
                    /*
                     * Make space for the newly created line.
                     */

                    memmove( &text[y + 1], &text[y],
                             sizeof( char *) * ( lines - y ) );
                    text[y] = new_line;

                    /*
                     * Compute the length of the new buffer and create it
                     */

                    for ( l = 0; l < lines; l++ )
                        buffer_length += strlen( text[l] ) + 1;

                    buffer = ( char *) realloc( buffer, buffer_length );
                    buffer[0] = '\0';

                    /*
                     * Copy the text into the new buffer.
                     */

                    for ( l = 0; l < lines; l++ ) {

                        strcat( buffer, text[l] );
                        strcat( buffer, "\n" );

                    }
                    strcat( buffer, text[lines] );

                    /*
                     * Feed it back to XForms.
                     */

                    fl_freeze_form( obj->form );
                    fl_set_input( obj, buffer );
                    fl_unfreeze_form( obj->form );

                    free( new_line );
                    free( buffer );

                }

            }

        }
        return FL_VALID;

    }
                                    - - -

    You will want to change the `MAX_CHARS_PER_LINE' definition to
    something longer than 30 characters of course -- you may want to
    dynamically calculate this given the font and the width of the input
    area.

    There are at least two bugs.

    If you move the cursor to the middle of the text somewhere and start
    adding text, when you get to a linewrap condition, the cursor moves to
    the end of the file. I don't think that's hard to fix -- it just
    involves a little extra bookkeeping and setting of the cursor position
    rather than allowing it to go to default.

    It also doesn't handle pasted text correctly -- pasted text is not
    passed through the input filter, it seems. I'm not exactly sure of a
    workaround for that at the moment, but I expect that there is.

    In any case, this should get you started.

                                                            spl
    _________________________________________________
    To unsubscribe, send the message "unsubscribe" to
    xforms-request@bob.usuhs.mil or see
    http://bob.usuhs.mil/mailserv/xforms.html
    XForms Home Page: http://world.std.com/~xforms
    List Archive: http://bob.usuhs.mil/mailserv/list-archives/



    This archive was generated by hypermail 2b29 : Fri Sep 15 2000 - 11:46:31 EDT