uidialog.c

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

C
1,347
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>

#include "uidef.h"
#include "uimenu.h"
#include "uidialog.h"
#include "uigchar.h"

#define CTRL_BUF_LEN    80

typedef EVENT           an_event;

static bool exit_field( a_dialog *info, VFIELD *field )
{
    bool                flag;
    an_edit_control     *edit;
    a_list              *list;
    a_combo_box         *combo;

    flag = FALSE;
    if( field != NULL ) {
        switch( field->typ ) {
        case FLD_EDIT :
        case FLD_INVISIBLE_EDIT:
            if( info->edit_data != NULL ) {
                edit = field->ptr;
                if( uieditisdirty() ) {
                    flag = TRUE;
                }
                uiedittrim( info->edit_data->edit_buffer );
                edit->buffer = info->edit_data->edit_buffer;
                edit->length = info->edit_data->edit_eline.length;
                uiendedit();
                info->edit_data = NULL;
            }
            uinocursor( info->vs );
            break;
        case FLD_COMBOBOX :
            combo = field->ptr;
            list = &combo->list;
            edit = &combo->edit;

            if( !combo->perm ) {
                uiendlistbox( list );           // Shut down listbox
            }
            if( info->edit_data != NULL ) {
                if( uieditisdirty() ) {
                    flag = TRUE;
                }
                uiedittrim( info->edit_data->edit_buffer );
                edit->buffer = info->edit_data->edit_buffer;
                edit->length = info->edit_data->edit_eline.length;
                uiendedit();
                info->edit_data = NULL;
            }
            uinocursor( info->vs );
            break;
        case FLD_PULLDOWN :
            list = field->ptr;
            uiendlistbox( list );
            break;
        case FLD_LISTBOX :
            list = field->ptr;
            list->box->attr = ATTR_EDIT;
            uipaintlistbox( list );
            break;
        case FLD_EDIT_MLE :
            list = field->ptr;
            list->box->attr = ATTR_NORMAL;
            uipaintlistbox( list );
            break;
        }
    }
    return( flag );
}

static bool notintab( VFIELD *fld )
{
    return( fld->typ < FLD_HOT );
}

static bool radiooff( VFIELD *fld )
{
    a_radio             *r;

    if( fld->typ == FLD_RADIO ) {
        r = fld->ptr;
        if( r->value != r->group->value ) {
            return( TRUE );
        }
    }
    return( FALSE );
}

static VFIELD *nextfield( VFIELD *fld )
{
    while( notintab( ++fld ) ) {                // unselectable field types!
        if( fld->typ == FLD_VOID ) {
            fld = NULL;
            break;
        }
    }
    return( fld );
}

static void print_field( VSCREEN *vs, VFIELD *field, unsigned current )
{
    SAREA               *area;
    char                *str;
    ATTR                attr;
    ATTR                hotattr;
    char                ctrlbuf[CTRL_BUF_LEN+1];
    unsigned            length = 0;
    a_check             *check = NULL;
    a_radio             *radio = NULL;
    a_list              *list;
    a_combo_box         *combo;
    a_hot_spot          *hotspot;
    an_edit_control     *edit;
    VSCREEN             *c_vs;
    SAREA               c_area;
    bool                use_hottext;
    char                hotkey;

    if( field == NULL ) return;
    area = &field->area;
    str = NULL;
    use_hottext = FALSE;
    memset( ctrlbuf, '\0', CTRL_BUF_LEN+1 );

    attr = UIData->attrs[ current ? ATTR_CURR_EDIT : ATTR_EDIT ];

    switch( field->typ ) {
    case FLD_HOT :
        hotspot = field->ptr;
        if( current ) {
            hotspot->flags |= HOT_CURRENT ;
        } else {
            hotspot->flags &= (~HOT_CURRENT);
        }
        hotspot->flags |= uihotspot( vs, hotspot->str,
                            &field->area, hotspot->flags );
        return;                     // don't want to print anything
    case FLD_TEXT :
        attr = UIData->attrs[ ATTR_NORMAL ];
        str  = field->ptr;
        break;
    case FLD_LABEL :
        attr = UIData->attrs[ ATTR_NORMAL ];
        strcpy( ctrlbuf, (char *)field->ptr );
        strcat( ctrlbuf, ":" );
        length = area->width;
        break;
    case FLD_FRAME :
        uidrawbox( vs, area, UIData->attrs[ ATTR_NORMAL ], field->ptr );
        return;
    case FLD_EDIT :
    case FLD_INVISIBLE_EDIT :
        edit = field->ptr;
        if( edit->buffer != NULL ) {
            length = min( edit->length, CTRL_BUF_LEN );
            if( length > area->width ) {
                length = area->width;
            }
            if( field->typ == FLD_INVISIBLE_EDIT ) {
                memset( ctrlbuf, '*', length );
            } else {
                strncpy( ctrlbuf, edit->buffer, length );
            }
        } else {
            length = 0;
        }
        break;
    case FLD_COMBOBOX :
        combo = field->ptr;
        edit  = &combo->edit;
        list  = &combo->list;

        if( combo->perm == FALSE ) {
            ctrlbuf[0] = UiGChar[ UI_ARROW_DOWN ];  /* JBS was 25 */
            uivtextput( vs, area->row, area->col + area->width + 1,
                        UIData->attrs[ ATTR_SCROLL_ICON ], ctrlbuf, 1 );
            ctrlbuf[0] = '\0';
        }
        if( edit->buffer != NULL ) {
            length = min( edit->length, CTRL_BUF_LEN );
            strncpy( ctrlbuf, edit->buffer, length );
        } else {
            length = 0;
        }
        if( list->get == NULL ) {
            list->get = ( bool (*) ( void *, unsigned, char *, unsigned ) )
                            uigetlistelement;
        }
        if( list->box == NULL  &&  combo->perm == TRUE ) {
            c_area = *area;
            c_area.row += vs->area.row + 2;
            c_area.col += vs->area.col + 1;
            c_vs = uiopen( &c_area, NULL, V_DIALOGUE | V_LISTBOX );
            if( c_vs == NULL ) {
                break;
            }
            c_area.row = 0;
            c_area.col = 0;
            list->box = uibeglistbox( c_vs, &c_area, list );
        }
        break;
    case FLD_PULLDOWN :
        list = field->ptr;
        ctrlbuf[0] = UiGChar[ UI_ARROW_DOWN ];  /* JBS was 25 */
        uivtextput( vs, area->row, area->col + area->width,
                    UIData->attrs[ ATTR_SCROLL_ICON ], ctrlbuf, 1 );
        ctrlbuf[0] = '\0';
        if( list->get == NULL ) {
            list->get = ( bool (*) ( void *, unsigned, char *, unsigned ) )
                                uigetlistelement;
        }
        (*list->get)( list->data, list->choice, ctrlbuf, area->width );
        length = area->width;
        break;
    case FLD_LISTBOX:
    case FLD_EDIT_MLE:
        list = field->ptr;
        if( list->box == NULL ) {
            c_area = *area;
            c_area.row += ((VSCREEN *)vs)->area.row;
            c_area.col += ((VSCREEN *)vs)->area.col;
            c_vs = uiopen( &c_area, NULL, V_DIALOGUE | V_LISTBOX );
            if( c_vs == NULL ) {
                break;
            }
            c_area.row = 0;
            c_area.col = 0;
            list->box = uibeglistbox( c_vs, &c_area, list );
        }
        return;
    case FLD_CHECK:
        attr = UIData->attrs[ current ? ATTR_CURR_EDIT : ATTR_NORMAL ];
        check = field->ptr;

        ctrlbuf[0] = UiGChar[ UI_CHECKBOX_LEFT ];
        if( _checked( check ) ) {
            ctrlbuf[1] = UiGChar[ UI_CHECKBOX_FULL ];
        } else {
            ctrlbuf[1] = UiGChar[ UI_CHECKBOX_EMPTY ];
        }
        ctrlbuf[2] = UiGChar[ UI_CHECKBOX_RIGHT ];
        ctrlbuf[3] = ' ';

        strncat( ctrlbuf, check->str, CTRL_BUF_LEN - 4 );
        length = strlen( ctrlbuf );
        use_hottext = TRUE;
        break;
    case FLD_RADIO:
        attr = UIData->attrs[ current ? ATTR_CURR_EDIT : ATTR_NORMAL ];
        radio = field->ptr;

        ctrlbuf[0] = UiGChar[ UI_RADIO_LEFT ];
        if( radio->value == radio->group->value ) {
            ctrlbuf[1] = UiGChar[ UI_RADIO_FULL ];
        } else {
            ctrlbuf[1] = UiGChar[ UI_RADIO_EMPTY ];
        }
        ctrlbuf[2] = UiGChar[ UI_RADIO_RIGHT ];
        ctrlbuf[3] = ' ';

        strncat( ctrlbuf, radio->str, CTRL_BUF_LEN - 4 );
        length = strlen( ctrlbuf );
        use_hottext = TRUE;
        break;
    }
    if( str != NULL ) {
        uivtextput( vs, area->row, area->col, attr, str, area->width );
    } else if( use_hottext ) {
        if( current ) {
            hotattr = attr;
        } else {
            hotattr = UIData->attrs[ ATTR_RADIO_HOTSPOT ];
        }
        hotkey = uidrawhottext( vs, ctrlbuf, area, attr, hotattr, FALSE, FALSE, FALSE );
        if( field->typ == FLD_CHECK ) {
            check->hotkey = hotkey;
        } else if( field->typ == FLD_RADIO ) {
            radio->hotkey = hotkey;
        }
    } else {
        uitextfield( vs, area->row, area->col, area->width, attr,
                     ctrlbuf, length );
    }
}

void uiprintfield( a_dialog *dialog, VFIELD *field )
{
    print_field( dialog->vs, field, field == dialog->curr );
}

static void *makevs( char *heading, int cols, int rows, int cpos, int rpos )
{
    SAREA               area;

    uiposition( &area, rows, cols, rpos, cpos, TRUE );
    return( uiopen( &area, heading, V_DIALOGUE ) );
}

unsigned ui_split_line( char **sptr, char *t, unsigned max )
{
// Attempt to split the line at an appropriate place
//
//  \n forces the line to be split even when everything fits
//  \r will be a favoured place to split when things don't fit

    unsigned            delim, cr, i;
    char                *str;
    unsigned            len;
    unsigned            slen = 0;
    char                ch = '\0';

    str = *sptr;
    len = t - str;
    if( len < max ) max = len;
    for( delim = 0, cr = 0, i = 0 ; i < max ; ++i ) {
        ch = str[ i ];
        if( ch == '\n' ) {
            break;
        } else if( ch == '\r' ) {
            str[ i ] = ' ';
            cr = i;
        } else if( ch == ' ' || ch == ',' || ch == ')' ) {
            delim = i;
        }
    }
    if( ch == '\n' ) {            /* forced new line */
        max = i+1;
        slen = i;
    } else if( len == max ) {     /* everything fit */
        slen = max;
    } else if( cr > 0 ) {         /* split at the carriage return */
        str[ cr ] = '\r';
        max = cr+1;
        slen = cr;
    } else if( delim > 0 ) {      /* split at the space, comma, or paren */
        max = delim+1;
        slen = max;
    }
    str += max;
    *sptr = str;
    return( slen );
}

void *uiinitdialog( char *heading, ATTR attr, char *lines[],
            unsigned int extra_rows, int maxlen, int rpos, int cpos )
{
    VSCREEN             *vs;
    int                 len;
    unsigned            width;
    int                 i;
    unsigned            depth;
    unsigned            linelen;
    char                *s, *t, *line;
    SAREA               area;

    uisetscreenarea( &area, TRUE, FALSE );
    width = UIData->width - 2;
    for( depth = 0, i = 0 ; lines[ i ] != NULL ; ++i ) {
        s = lines[ i ];
        len = strlen( s );
        for( t = s + len ; s < t ; ) {
            ++ depth;
            linelen = ui_split_line( &s, t, width );
            maxlen = max( linelen+2, maxlen );
        }
    }
    if( depth > 0 ) {
        /* never put text on the first line of the dialog */
        ++depth;
    }
    maxlen = min( maxlen, width );
    vs = makevs( heading, maxlen, depth + extra_rows, cpos, rpos );
    uisetarea( &area, vs );
    width = area.width;
    area.row = 1;
    area.height = 1;
    for( i = 0 ; lines[ i ] != NULL ; ++i ) {
        s = lines[ i ];
        len = strlen( s );
        for( t = s + len ; s < t ; ) {
            line = s;
            linelen = ui_split_line( &s, t, width );
            uicntrtext( vs, &area, attr, linelen, line );
            area.row += 1;
        }
    }
    return( vs );
}

void uifinidialog( void *vs )
{
    uiclose( vs );
}

static void enter_field( a_dialog *info, VFIELD *field )
{
    an_edit_control     *edit;
    a_combo_box         *combo;
    a_list              *list;
    SAREA               area;

    if( field == NULL )  return;

    area = field->area;
    switch( field->typ ) {
    case FLD_EDIT :
    case FLD_INVISIBLE_EDIT :
    case FLD_COMBOBOX :

⌨️ 快捷键说明

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