Links/Find_Link [ Functions ]

NAME

Find_Link -- try to match word with a link

FUNCTION

Searches for the given word in the list of links and headers. There are three passes (or four, when the C option is selected). Each pass uses a different definition of "word":

SYNOPSIS

int
Find_Link( char *word_begin, 
           char **object_name, 
           char **label_name,
           char **file_name )

INPUTS

SIDE EFFECTS

label_name & file_name are modified

RESULT

NOTES

This is a rather sensitive algorithm. Don't mess with it too much.

SOURCE

{
    char               *cur_char = NULL, old_char;
    int                 low_index, high_index, cur_index, state, pass;
    unsigned int        length = 0;

    for ( pass = 0; pass < 3; pass++ )
    {
        switch ( pass )
        {
        case 0:
            {
                for ( cur_char = word_begin;
                      ( *cur_char == '_' ) || utf8_isalnum( *cur_char ) || utf8_ispunct( *cur_char );
                      cur_char++ );
                break;
            }
        case 1:
            {
                for ( cur_char = word_begin;
                      utf8_isalnum( *cur_char ) || ( *cur_char == '_' ) ||
                      ( *cur_char == '-' ) || ( *cur_char == '.' ) ||
                      ( *cur_char == ':' ); cur_char++ );
                break;
            }
        case 2:
            {
                for ( cur_char = word_begin;
                      utf8_isalnum( *cur_char ) || ( *cur_char == '_'); 
                      cur_char++ );
                break;
            }
        }

        if ( ( ( *( cur_char - 1 ) ) == ',' ) || ( ( *( cur_char - 1 ) ) == '.' ) )
        {
            cur_char--;
        }

        old_char = *cur_char;
        *cur_char = '\0';       /*
                                 * End the word with a '\0' 
                                 */
        if ( strlen( word_begin ) == length )
        {
            /* Do not test the same word over and over. If
             * the current string and the string of the previous
             * pass are the same length, they are the same. */

            /* RB_Say ("Skipping (pass %d) \"%s\"\n", SAY_INFO, pass, word_begin);  */
        }
        else
        {
            length = strlen( word_begin );
            /* RB_Say ("Testing (pass %d) \"%s\"\n", SAY_INFO, pass, word_begin); */
            /*
             * Search case sensitive for a link 
             */
            for ( cur_index = 0, low_index = 0, high_index =
                    link_index_size - 1; high_index >= low_index; )
            {
                cur_index = ( high_index - low_index ) / 2 + low_index;
                state = strcmp( word_begin, case_sensitive_link_index[cur_index]->object_name );
                if ( state < 0 )
                {
                    high_index = cur_index - 1;
                }
                else if ( state == 0 )
                {
                    *object_name = case_sensitive_link_index[cur_index]->object_name;
                    *label_name = case_sensitive_link_index[cur_index]->label_name;
                    *file_name = case_sensitive_link_index[cur_index]->file_name;
                    RB_Say( "linking \"%s\"->\"%s\" from \"%s\"\n", SAY_DEBUG,
                            word_begin, *object_name, *file_name );
                    *cur_char = old_char;
                    return ( TRUE );
                }
                else if ( state > 0 )
                {
                    low_index = cur_index + 1;
                }
            }

            /*
             * Search case insensitive for a link.
             * But only when the user asks for this.
             */
            if ( course_of_action.do_ignore_case_when_linking ) 
            {

                for ( cur_index = 0, low_index = 0, high_index =
                        link_index_size - 1; high_index >= low_index; )
                {
                    cur_index = ( high_index - low_index ) / 2 + low_index;
                    state = RB_Str_Case_Cmp( word_begin, link_index[cur_index]->object_name );
                    if ( state < 0 )
                    {
                        high_index = cur_index - 1;
                    }
                    else if ( state == 0 )
                    {
                        *object_name = link_index[cur_index]->object_name;
                        *label_name = link_index[cur_index]->label_name;
                        *file_name = link_index[cur_index]->file_name;
                        RB_Say( "linking \"%s\"->\"%s\" from \"%s\"\n", SAY_DEBUG,
                                word_begin, *object_name, *file_name );
                        *cur_char = old_char;
                        return ( TRUE );
                    }
                    else if ( state > 0 )
                    {
                        low_index = cur_index + 1;
                    }
                }
            }
        }
        *cur_char = old_char;
        *file_name = NULL;
        *object_name = NULL;
        *label_name = NULL;
    }
    return ( FALSE );
}