setupinf.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,908 行 · 第 1/5 页

C
1,908
字号

typedef struct dialog_info {    // structure used when parsing a dialog
    array_info          array;
    int                 num_push_buttons;
    int                 num_variables;
    int                 num_radio_buttons;
    int                 max_width;
    int                 wrap_width;
    a_dialog_header     *curr_dialog;
    int                 row_num;
    int                 col_num;
} DIALOG_INFO;

// Characters prohibited from beginning lines

#define NUM_INVALID_FIRST       56

static unsigned short InvalidFirst[ NUM_INVALID_FIRST ] =
{
    0x8141, 0x8142, 0x8143, 0x8144, 0x8146, 0x8147, 0x8148, 0x8149,
    0x814a, 0x814b, 0x8152, 0x8153, 0x8154, 0x8155, 0x8158, 0x815b,
    0x815c, 0x815d, 0x8166, 0x8168, 0x816a, 0x816c, 0x816e, 0x8170,
    0x8172, 0x8174, 0x8176, 0x8178, 0x817a, 0x818b, 0x818c, 0x818d,
    0x818e, 0x8193, 0x829f, 0x82a1, 0x82a3, 0x82a5, 0x82a7, 0x82c1,
    0x82e1, 0x82e3, 0x82e5, 0x82ec, 0x8340, 0x8342, 0x8344, 0x8346,
    0x8348, 0x8362, 0x8383, 0x8385, 0x8387, 0x838e, 0x8395, 0x8396
};

// Characters prohibited from terminating lines

#define NUM_INVALID_LAST        19

static unsigned short InvalidLast[ NUM_INVALID_LAST ] =
{
    0x8165, 0x8167, 0x8169, 0x816b, 0x816d, 0x816f, 0x8171, 0x8173,
    0x8175, 0x8177, 0x8179, 0x818f, 0x8190, 0x8191, 0x8192, 0x8197,
    0x8198, 0x81a7, 0x81f2
};

static bool valid_first_char( char *p )
/*************************************/

{
    int                 i;
    unsigned short      kanji_char;

    if( GUICharLen( *p ) == 2 ) {
        // Kanji
        kanji_char = ( *p << 8 ) + *( p + 1 );
        if( kanji_char < InvalidFirst[ 0 ]
        ||  kanji_char > InvalidFirst[ NUM_INVALID_FIRST - 1 ] ) {
            // list is sorted
            return( TRUE );
        }
        for( i = 0; i < NUM_INVALID_FIRST; ++i ) {
            if( kanji_char == InvalidFirst[ i ] ) {
                return( FALSE );        // invalid
            } else if( kanji_char < InvalidFirst[ i ] ) {
                return( TRUE );
            }
        }
        return( TRUE );
    } else {
        return( FALSE );
    }
}

static bool valid_last_char( char *p )
/************************************/

{
    int                 i;
    unsigned short      kanji_char;

    if( GUICharLen( *p ) == 2 ) {
        // Kanji
        kanji_char = ( *p << 8 ) + *( p + 1 );
        if( kanji_char < InvalidLast[ 0 ]
        ||  kanji_char > InvalidLast[ NUM_INVALID_LAST - 1 ] ) {
            // list is sorted
            return( TRUE );
        }
        for( i = 0; i < NUM_INVALID_LAST; ++i ) {
            if( kanji_char == InvalidLast[ i ] ) {
                return( FALSE );        // invalid
            } else if( kanji_char < InvalidLast[ i ] ) {
                return( TRUE );
            }
        }
        return( TRUE );
    } else {
        return( FALSE );
    }
}

static char *find_break( char *text, DIALOG_INFO *dlg, int *chwidth )
/*******************************************************************/
{
    char            *e;
    char            *n;
    char            *br;
    char            *s;
    int             len;
    gui_ord         width;
    int             winwidth;

    // Line endings are word breaks already
    s = text;
    while( *s && (*s != '\r') && (*s != '\n') ) s++;
    len = s - text;

    winwidth = dlg->wrap_width * CharWidth;
    // Use string length as cutoff to avoid overflow on width
    if( len < 2 * dlg->wrap_width ) {
        width = GUIGetExtentX( MainWnd, text, len );
        if( width < winwidth ) {
            *chwidth = (width / CharWidth) + 1;
            dlg->max_width = max( dlg->max_width, *chwidth );
            return( text + len );
        }
    }
    dlg->max_width = max( dlg->max_width, dlg->wrap_width );
    *chwidth = dlg->max_width;
    br = text;
    for( e=text;; ) {
        if( *e == '\0' )
            return( text );
        if( *e == '\\' && *( e + 1 ) == 'n' )
            return( e );
        n = e + GUICharLen( *e );
        width = GUIGetExtentX( MainWnd, text, n - text );
        if( width >= winwidth )
            break;
        // is this a good place to break?
        if( *e == ' ' || *e == '\t' ) { // English
            br = n;
        } else if( valid_last_char( e ) && valid_first_char( n ) ) {
            br = n;
        }
        e = n;
    }
    if( br == text )
        return( e );
    return( br );
}

static bool dialog_static( char *next, DIALOG_INFO *dlg )
/*******************************************************/
{
    char                *line;
    int                 len;
    char                *text;
    bool                rc = TRUE;
    char                dummy_var[ DUMMY_VAR_SIZE ];
    vhandle             var_handle;

    line = next; next = NextToken( line, '"' );
    line = next; next = NextToken( line, '"' );
    GUIStrDup( line, &text );
    line = next; next = NextToken( line, ',' );
    line = next; next = NextToken( line, ',' );
    if( line == NULL || *line == '\0' || EvalCondition( line ) ) {
        line = next; next = NextToken( line, ',' );
        if( line != NULL ) {
            // condition for visibility (dynamic)
            GUIStrDup( line,
                       &dlg->curr_dialog->pVisibilityConds[ dlg->curr_dialog->num_controls ] );
        }
        MakeDummyVar( dummy_var );
        // dummy_var allows control to have an id - used by dynamic visibility feature
        var_handle = AddVariable( dummy_var );
        if( text != NULL ) {
            text = AddInstallName( text, TRUE );
            len = strlen( text );
            set_dlg_dynamstring( dlg->curr_dialog->controls, dlg->array.num-1,
                                 text, var_handle, dlg->col_num, dlg->row_num, dlg->col_num + len );
            dlg->max_width = max( dlg->max_width, dlg->col_num + len );
        } else {
            set_dlg_dynamstring( dlg->curr_dialog->controls, dlg->array.num-1,
                                 "", var_handle, dlg->col_num, dlg->row_num, dlg->col_num + 0 );
        }
    } else {
        rc = FALSE;
    }
    GUIMemFree( text );
    return( rc );
}

static char * textwindow_wrap( char *text, DIALOG_INFO *dlg, bool convert_newline )
/*********************************************************************************/
// Makes newline chars into a string into \r\n combination.
// Frees passed in string and allocates new one.
{
    char        *big_buffer = NULL;
    char        *orig_index = NULL;
    char        *new_index = NULL;
    char        *break_candidate = NULL;
    int         chwidth;
    bool        new_line = TRUE;

    if( text == NULL ) {
        return( NULL );
    }

    big_buffer = GUIMemAlloc( strlen( text ) * 2 + 1 );
    if( big_buffer == NULL ) {
        return( NULL );
    }
    orig_index = text;
    break_candidate = find_break( orig_index, dlg, &chwidth );
    for( new_index = big_buffer; *orig_index != '\0'; orig_index++, new_index++ ) {
        if( new_line ) {
            while( *orig_index == '\t' || *orig_index == ' ' ) {
                orig_index++;
            }
        }

        if( ( convert_newline
              && *orig_index == '\\' && *(orig_index + 1) == 'n' )
            || ( !convert_newline && *orig_index == '\r' && *(orig_index + 1) == '\n' ) ) {
            *new_index = '\r';
            new_index++;
            orig_index++;
            *new_index = '\n';
            break_candidate = find_break( orig_index + 1, dlg, &chwidth );
        } else if( break_candidate != NULL
                   && orig_index == break_candidate ) {
            *new_index = '\r';
            new_index++;
            *new_index = '\n';
            new_index++;
            *new_index = *break_candidate;
            break_candidate = find_break( orig_index + 1, dlg, &chwidth );
            new_line = TRUE;
            continue;
        } else if( *orig_index == '\t' ) {
            *new_index = ' ';
        } else {
            *new_index = *orig_index;
        }
        new_line = FALSE;
    }
    *new_index = '\0';

    GUIMemFree( text );
    GUIStrDup( big_buffer, &text );
    GUIMemFree( big_buffer );
    return( text );
}

static bool dialog_textwindow( char *next, DIALOG_INFO *dlg )
/***********************************************************/
{
    char                *line;
    char                *text;
    char                *file_name;
    unsigned int        rows;
    bool                rc = TRUE;
    void                *io;
    struct stat         buf;
    char                dummy_var[ DUMMY_VAR_SIZE ];
    vhandle             var_handle;

    text = NULL;
    line = next; next = NextToken( line, ',' );
    rows = atoi( line );
    if( rows > 0 ) {
        rows -= 1;
    }
    line = next; next = NextToken( line, '"' );
    line = next; next = NextToken( line, '"' );
    if( line == NULL ) {
        rc = FALSE;
    } else {
        if( *line == '@' ) {
            GUIStrDup( line + 1, &file_name );
            io = FileOpen( file_name, O_RDONLY + O_BINARY );
            if( io != NULL ) {
                FileStat( file_name, &buf );
                text = GUIMemAlloc( buf.st_size + 1 );  // 1 for terminating null
                if( text != NULL ) {
                    FileRead( io, text, buf.st_size );
                    text[ buf.st_size ] = '\0';
                    FileClose( io );
                }
            }
            GUIMemFree( file_name );
            text = textwindow_wrap( text, dlg, FALSE ); //VERY VERY SLOW!!!!  Don't use large files!!!
                                                        // bottleneck is the find_break function
        } else {
            GUIStrDup( line, &text );
            text = textwindow_wrap( text, dlg, TRUE );
        }

        line = next; next = NextToken( line, ',' );
        line = next; next = NextToken( line, ',' );
        if( ( line == NULL || *line == '\0' || EvalCondition( line ) ) && text != NULL ) {
            line = next; next = NextToken( line, ',' );
            if( line != NULL ) {
                // condition for visibility (dynamic)
                GUIStrDup( line,
                           &dlg->curr_dialog->pVisibilityConds[ dlg->curr_dialog->num_controls ] );
            }
            MakeDummyVar( dummy_var );
            // dummy_var allows control to have an id - used by dynamic visibility feature
            var_handle = AddVariable( dummy_var );
            set_dlg_textwindow( dlg->curr_dialog->controls, dlg->array.num-1,
                      text, var_handle, C0, dlg->row_num, dlg->max_width + 2, rows,
                      GUI_VSCROLL );
            dlg->curr_dialog->rows += rows;
            dlg->row_num += rows;
#if defined( __DOS__ )
            dlg->curr_dialog->rows += 2;
            dlg->row_num += 2;
#endif
        } else {
            rc = FALSE;
        }
        GUIMemFree( text );
    }
    return( rc );
}

static bool dialog_dynamic( char *next, DIALOG_INFO *dlg )
/********************************************************/
{
    int                 len;
    char                *line;
    vhandle             var_handle;
    char                *vbl_name;
    char                *text;
    bool                rc = TRUE;

    line = next; next = NextToken( line, ',' );
    GUIStrDup( line, &vbl_name );
    line = next; next = NextToken( line, '"' );
    line = next; next = NextToken( line, '"' );
    var_handle = AddVariable( vbl_name );
    GUIStrDup( line, &text );
    line = next; next = NextToken( line, ',' );
    line = next; next = NextToken( line, ',' );
    if( line == NULL || *line == '\0' || EvalCondition( line ) ) {
        if( text != NULL ) {
            SetVariableByHandle( var_handle, text );
        }
        dlg->curr_dialog->pVariables[dlg->num_variables] = var_handle;
        dlg->num_variables += 1;
        len = strlen( text );
        line = next; next = NextToken( line, ',' );
        if( line != NULL ) {
            // condition for visibility (dynamic)
            GUIStrDup( line,
                       &dlg->curr_dialog->pVisibilityConds[ dlg->curr_dialog->num_controls ] );
        }
        dlg->max_width = max( dlg->max_width, max( len, 60 ) );
        set_dlg_dynamstring( dlg->curr_dialog->controls, dlg->array.num-1,
                             text, VarGetId( var_handle ), C0, dlg->row_num, C0 + dlg->max_width );
    } else {
        rc = FALSE;
    }
    GUIMemFree( vbl_name );
    GUIMemFree( text );
    return( rc );
}


static bool dialog_pushbutton( char *next, DIALOG_INFO *dlg )
/***********************************************************/
{
    char                *line;
    char                *line_start;
    int                 id;
    bool                def_ret;
    bool                rc = TRUE;

    line_start = next; next = NextToken( line_start, ',' );
    line = next; next = NextToken( line, ',' );
    if( line == NULL || *line == '\0' || EvalCondition( line ) ) {
        dlg->num_push_buttons += 1;
        def_ret = FALSE;
        if( *line_start == '.' ) {
            ++line_start;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?