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 + -
显示快捷键?