uidialog.c

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

C
1,347
字号
        if( field->typ == FLD_COMBOBOX ) {
            combo = field->ptr;
            edit  = &combo->edit;
        } else {
            edit = field->ptr;
        }
        if( info->edit_data == NULL ) {
            info->edit_data = uibegedit( info->vs, area.row, area.col, area.width,
                                  UIData->attrs[ ATTR_CURR_EDIT ],
                                  edit->buffer, edit->length, 0, 0, TRUE, 0,
                                  field->typ == FLD_INVISIBLE_EDIT );
        }
        break;
    case FLD_LISTBOX :
        list = field->ptr;
        list->box->attr = ATTR_CURR_EDIT;
        uipaintlistbox( list );
        break;
    case FLD_EDIT_MLE :
        list = field->ptr;
        list->box->attr = ATTR_NORMAL;
        uipaintlistbox( list );
        break;
    }
}

void uireinitdialog( a_dialog *info, VFIELD *fields )
{
    unsigned            i;

    uiposnhotspots( info->vs, fields );
    info->dirty = FALSE;
    info->first = NULL;
    info->other = NULL;
    info->fields = fields;

    info->first = &fields[0];
    /* set first to be first field in tab sequence */
    while( notintab( info->first ) ) {
        if( info->first->typ == FLD_VOID ) {
            info->first = NULL;
            break;
        }
        ++(info->first);
    }
    info->curr = info->first;
    if( info->first != NULL ) {
        /* set curr to first field in tab sequence not an unset radio button */
        while( radiooff( info->curr ) ) {
            info->curr = nextfield( info->curr );
        }
    }

    for( i = 0 ; fields[i].typ != FLD_VOID ; ++i ) {
        print_field( info->vs, &fields[i], &fields[i] == info->curr );
    }
    enter_field( info, info->curr );
}

bool uigetdialogarea( a_dialog *dialog, SAREA *area )
{
    VSCREEN     *vs;

    if( dialog != NULL && area != NULL ) {
        vs = (VSCREEN *)dialog->vs;
        *area = vs->area;
        return( TRUE );
    }
    return( FALSE );
}

void *uibegdialog( char *title, VFIELD *fields, ORD rows, ORD cols, int rpos, int cpos )
{
    char                *lines[1];
    a_dialog            *info;

    lines[ 0 ] = NULL;
    info = uicalloc( 1, sizeof( a_dialog ) );
    if( info == NULL ) {
        return( NULL );
    }
    info->vs = uiinitdialog( title, UIData->attrs[ ATTR_NORMAL ],
                           lines, rows, cols, rpos, cpos );
    uireinitdialog( info, fields );
    return( info );
}

static void do_radio( a_dialog *info, VFIELD *field )
{
    a_radio *cur_radio;
    VFIELD  *fields;
    a_radio *radio;
    int i;

    fields = info->fields;
    // might want to use info->first, kind of unsure
    cur_radio = field->ptr;
    if( cur_radio->value == cur_radio->group->value ) return;

    info->dirty = TRUE;

    for( i = 0 ; fields[i].typ != FLD_VOID ; ++i ) {
        if( fields[i].typ == FLD_RADIO ) {
            radio = fields[i].ptr;
            if( radio->group == cur_radio->group  &&
                radio->value == radio->group->value ) {
                radio->group->value = cur_radio->value;
                print_field( info->vs, &fields[i], FALSE );
                break;
            }
        }
    }
    cur_radio->group->value = cur_radio->value;
    print_field( info->vs, field, TRUE );
}

void uiupdatecombobox( a_combo_box *combo )
{
    char                *str;
    a_list              *list;
    an_edit_control     *edit;

    edit  = &combo->edit;
    list  = &combo->list;
    str = (char *)uimalloc( CTRL_BUF_LEN );
    if( str != NULL ) {
        if( (*list->get)( list->data, list->choice, str, CTRL_BUF_LEN ) ) {
            uifree( edit->buffer );
            edit->buffer = str;
            edit->length = strlen( str );
        } else {
            uifree( str );
        }
    }
}

void uiupdateedit( a_dialog *info, VFIELD *field )
{
    an_edit_control     *edit;
    a_combo_box         *combo;

    if( ( field == NULL ) || ( info == NULL ) || ( field != info->curr ) ) {
        return;
    }
    edit = NULL;
    switch( field->typ ) {
    case FLD_COMBOBOX :
        combo = field->ptr;
        edit = &combo->edit;
        break;
    case FLD_EDIT :
    case FLD_INVISIBLE_EDIT:
        edit = field->ptr;
        break;
    }
    if( edit != NULL ) {
        if( info->edit_data != NULL ) {
            uiendedit();
            info->edit_data = NULL;
        }
        enter_field( info, info->curr );
    }
}

static  void setcombobuffer( a_dialog *info, VFIELD *fld )
{
    a_combo_box         *combo;
    an_edit_control     *edit;

    combo = fld->ptr;
    edit  = &combo->edit;
    uiupdatecombobox( combo );
    if( info->edit_data != NULL ) {
        info->edit_data->edit_buffer = edit->buffer;
        info->edit_data->edit_eline.buffer = edit->buffer;
        info->edit_data->edit_eline.length = edit->length;
        info->edit_data->edit_eline.update = TRUE;
        info->edit_data->edit_eline.index = 0;
        info->edit_data->edit_eline.scroll = 0;
    }
}

EVENT   pulldownfilter( EVENT ev, a_dialog *info )
{
    a_list          *list = NULL;
    a_combo_box     *combo;

    VSCREEN     *vs;
    SAREA       area;
    VFIELD      *fld;

    fld = info->curr;

    if( fld->typ == FLD_PULLDOWN ) {
        list = fld->ptr;
    } else if( fld->typ == FLD_COMBOBOX ) {
        combo = fld->ptr;
        list = &combo->list;
    }
    if( list->get == NULL ) {
        list->get = ( bool (*) ( void *, unsigned, char *, unsigned ) )
                        uigetlistelement;       // set get_element function
    }
    switch( ev ) {
    case EV_MOUSE_DCLICK:
    case EV_MOUSE_PRESS:
    {
        ORD             row, col;

        uivmousepos( info->vs, &row, &col );
        area = fld->area;
        area.width += 1;    /* extra column for button */
        if( fld->typ == FLD_COMBOBOX ) {
            /* mouse press must be on little button at right */
            area.col += area.width;
            area.width = 1;
        }
        if( fld->typ == FLD_COMBOBOX || fld->typ == FLD_PULLDOWN ) {
            /* mouse press must be on top line */
            area.height = 1;
        }
        if( row < area.row  || row >= area.row + area.height ) break;
        if( col < area.col  || col >= area.col + area.width ) break;
        /* FALLS into next case */
    }
    case EV_CURSOR_DOWN:
    case EV_ALT_CURSOR_DOWN:
        /* list->box must be null */
        area = fld->area;
        vs   = info->vs;
        area.row += ( vs->area.row + 2 );
        area.col += vs->area.col;
        if( fld->typ == FLD_COMBOBOX ) {
            area.col++;
        }
        if( area.row + area.height >= UIData->height ) {
            area.row -= area.height + 3;
        }
        vs = uiopen( &area, NULL, V_DIALOGUE | V_LISTBOX );
        area.row = 0;
        area.col = 0;
        list->box = uibeglistbox( vs, &area, list );
        if( ev != EV_MOUSE_PRESS && ev != EV_MOUSE_DCLICK
                        && fld->typ == FLD_COMBOBOX ) {
            info->dirty = TRUE;
            setcombobuffer( info, fld );
            print_field( info->vs, fld, TRUE );
        }
        break;
    }
    return( ev );
}

static void *forwardtab( a_dialog *info )
{
    VFIELD             *fld;

    if( info->curr == NULL ){
        fld = info->first;
    } else {
        fld = nextfield( info->curr );
        if( fld == NULL ) {
            fld = info->first;
        }
    }
    while( radiooff( fld ) ) {
        fld = nextfield( fld );
    }
    return( fld );
}

static void *backwardtab( a_dialog *info )
{
    VFIELD      *fld, *hold;

    hold = NULL;
    fld = info->first;
    while( fld != info->curr ) {
        if( !radiooff( fld ) ) {
            hold = fld;
        }
        fld = nextfield( fld );
    }
    if( hold == NULL ) {        /* wrap */
        while( fld != NULL ) {
            if( !radiooff( fld ) ) {
                hold = fld;
            }
            fld = nextfield( fld );
        }
    }
    return( hold );
}

extern void uidialogexitcurr( a_dialog *info )
{
    /* you must call this function to set info->dirty or to do  */
    /* blank trimming on an edit control                        */
    if( exit_field( info, info->curr ) ) {
        info->dirty = TRUE;
    }
}

extern void uidialogsetcurr( a_dialog *info, VFIELD *curr )
{
    VFIELD      *other;

    other = info->curr;
    if( other != curr ) {
        info->other = info->curr;
        info->curr  = curr;
        if( exit_field( info, other ) ) {
            info->dirty = TRUE;
        }
        print_field( info->vs, other, FALSE );
        enter_field( info, curr );
        print_field( info->vs, curr, TRUE );
        uidialogchangefield( info );
    }
}

void uimovefield( a_dialog *info, VFIELD *curr, int row_diff, int col_diff )
{
    a_combo_box *combo;
    a_list      *list;

    info = info;

    switch( curr->typ ) {
    case FLD_COMBOBOX :
        combo = curr->ptr;
        if( combo->perm ) {
            uimovelistbox( &combo->list, row_diff, col_diff );
        } else {
            uiendlistbox( &combo->list );
        }
        break;
    case FLD_LISTBOX :
    case FLD_EDIT_MLE :
        list = (a_list *)curr->ptr;
        uimovelistbox( list, row_diff, col_diff );
        if( list->box != NULL ) {
            uivsetactive( list->box->vs );
        }
        break;
    case FLD_PULLDOWN :
        uiendlistbox( (a_list *)curr->ptr );
        break;
    }
}

void uiredrawdialog( a_dialog *info )
{
    VSCREEN     *vs;
    int         i;

    vs = (VSCREEN *)info->vs;

    uivclose( vs );
    uivopen( vs );

    for( i = 0 ; info->fields[i].typ != FLD_VOID ; ++i ) {
        print_field( info->vs, &info->fields[i],
                     &info->fields[i] == info->curr );
    }
}

bool uiresizedialog( a_dialog *info, SAREA *new_area )
{
    int         row_diff;
    int         col_diff;
    VSCREEN     *vs;
    VFIELD      *curr;
    int         i;
    bool        resize;

    vs = (VSCREEN *)info->vs;

    if( new_area->row < 2 ) {
        new_area->row = 2;
    }
    if( new_area->col < 1 ) {
        new_area->col = 1;
    }
    if( new_area->row + vs->area.height >= UIData->height ) {
        new_area->row = UIData->height - vs->area.height - 1;
    }
    if( new_area->col + vs->area.width >= UIData->width ) {
        new_area->col = UIData->width - vs->area.width - 1;
    }
    row_diff = new_area->row - vs->area.row;
    col_diff = new_area->col - vs->area.col;
    resize = ( new_area->width != vs->area.width ) ||
             ( new_area->height != vs->area.height );
    if( resize ) {
        uivclose( vs );
        vs->area = *new_area;
        uivopen( vs );
    } else {
        uivmove( info->vs, new_area->row, new_area->col );
    }
    /* close all open pull down boxes */
    for( curr = info->fields; curr->typ != FLD_VOID; curr++ ) {
        uimovefield( info, curr, row_diff, col_diff );
    }
    if( resize ) {
        for( i = 0 ; info->fields[i].typ != FLD_VOID ; ++i ) {
            print_field( info->vs, &info->fields[i],
                         &info->fields[i] == info->curr );
        }
    }
    return( TRUE );
}

static  ORD     PrevRow = 0;
static  ORD     PrevCol = 0;

static EVENT uicheckmove( EVENT ev, a_dialog *info )
{
    EVENT       new_ev;
    ORD         row;
    ORD         col;
    SAREA       new_area;
    VSCREEN     *vs;
    int         prev_row;
    int         prev_col;

    new_ev = ev;
    switch( ev ) {
    case EV_MOUSE_PRESS :
        if( uivmousepos( NULL, &row, &col ) == info->vs ) {
            vs = (VSCREEN *)info->vs;
            if( ( row + 1 ) == vs->area.row ) { /* because it's framed */
                PrevRow = row;
                PrevCol = col;
                info->moving = TRUE;
                new_ev = EV_NO_EVENT;
            }
        }
        break;
    case EV_MOUSE_DRAG :
        if( info->moving ) {
            uivmousepos( NULL, &row, &col );
            if( ( row != PrevRow ) || ( col != PrevCol ) ) {
                vs = (VSCREEN *)info->vs;
                if( vs->area.row + row < PrevRow ) {
                    new_area.row = 0;
                } else {
                    new_area.row = vs->area.row + row - PrevRow;

⌨️ 快捷键说明

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