hackdctl.c

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

C
797
字号
/****************************************************************************
*
*                            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:  The implementation of the data control library and the
*               dynamic template library for VIW.
*
****************************************************************************/

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "ctltype.h"
#include "dyntpl.h"

///////////////////////////////////////////////////////////////////////////
// Missing information is marked by MISSING!!!
//
// Original files came from watcom11\samples\win\datactl\*.C
// (heavily modified and tweaked to fit for VIW)
// Modifications made by Felix Fontein (felix@amuq.net).

///////////////////////////////////////////////////////////////////////////
// The forward declarations of the control element handlers

// The *_start functions will be called on dialog initialization
// and reset, and they should initialize the state of the control
// elements based on the data in the dialog data struct.
//   first parameter: pointer to the control element data
//   second parameter: the program's instance handle
//   third parameter: the dialog's window handle
//   fourth parameter: pointer to dialog data struct
//   fifth parameter: boolean (no idea what it is for) (MISSING!!!)
static BOOL ctl_check_start( ctl_elt *, HANDLE, HWND, void *, BOOL );
static BOOL ctl_radio_start( ctl_elt *, HANDLE, HWND, void *, BOOL );
static BOOL ctl_text_start( ctl_elt *, HANDLE, HWND, void *, BOOL );
static BOOL ctl_combo_start( ctl_elt *, HANDLE, HWND, void *, BOOL );
static BOOL ctl_dcombo_start( ctl_elt *, HANDLE, HWND, void *, BOOL );
static BOOL ctl_int_start( ctl_elt *, HANDLE, HWND, void *, BOOL );
static BOOL ctl_float_start( ctl_elt *, HANDLE, HWND, void *, BOOL );
static BOOL ctl_rint_start( ctl_elt *, HANDLE, HWND, void *, BOOL );
static BOOL ctl_rfloat_start( ctl_elt *, HANDLE, HWND, void *, BOOL );

// The *_finish functions will be called to retain the control element
// data into the dialog data struct.
//   first parameter: pointer to the control element data
//   second parameter: the program's instance handle
//   third parameter: the dialog's window handle
//   fourth parameter: pointer to dialog data struct
//   fifth parameter: finish_type (no idea what it is for) (MISSING!!!)
static BOOL ctl_check_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );
static BOOL ctl_radio_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );
static BOOL ctl_text_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );
static BOOL ctl_combo_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );
static BOOL ctl_dcombo_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );
static BOOL ctl_int_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );
static BOOL ctl_float_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );
static BOOL ctl_rint_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );
static BOOL ctl_rfloat_finish( ctl_elt *, HANDLE, HWND, void *, finish_type );

// The *_modified functions will be called to query if the control element
// was modified.
//   first parameter: pointer to the control element data
//   second parameter: the wParam of the message
//   third parameter: the lParam of the message
static BOOL ctl_check_modified( ctl_elt *, UINT, LONG );
static BOOL ctl_text_modified( ctl_elt *, UINT, LONG );
static BOOL ctl_combo_modified( ctl_elt *, UINT, LONG );
static BOOL ctl_radio_modified( ctl_elt *, UINT, LONG );

// The control table: Contains the
ctl_action Ctl_int_actions[] =
{
    { NULL, NULL, NULL }, // empty dummy, since we are starting to count from one
    { ctl_check_start, ctl_check_finish, ctl_check_modified },
    { ctl_radio_start, ctl_radio_finish, ctl_radio_modified },
    { ctl_text_start, ctl_text_finish, ctl_text_modified },
    { ctl_combo_start, ctl_combo_finish, ctl_combo_modified },
    { ctl_dcombo_start, ctl_dcombo_finish, ctl_combo_modified },
    { ctl_int_start, ctl_int_finish, ctl_text_modified },
    { ctl_float_start, ctl_float_finish, ctl_text_modified },
    { ctl_int_start, ctl_rint_finish, ctl_text_modified },
    { ctl_float_start, ctl_rfloat_finish, ctl_text_modified },
    // missing: CTL_ESCOMBO,        // editable string combo box (drop down) (MISSING!!!)
    // missing: CTL_DHCOMBO,        // dynamic combo box, with HWND parm (MISSING!!!)
};

///////////////////////////////////////////////////////////////////////////////
// The ctl_dlg_ functions

BOOL ctl_dlg_init( WPI_INST inst, HWND dlg, void *ptr, void *ctl_ptr)
/*******************************************************************/
/* initialize a data control. Returns TRUE if it gets up OK. Could return
   FALSE if a data error occurs */
{
    int                 num;
    ctl_elt             *elt;
    clt_def             *ctl = ctl_ptr;      // so app doesn't have to do type cast;

    // enumerate all control elements.
    for( num = ctl->num_ctls, elt = ctl->elts; num > 0; --num, ++elt ) {
        // Initialize control element.
        if( !(Ctl_int_actions[elt->type].setup)( elt, inst, dlg, ptr, TRUE ) ) {
            return( FALSE );
        }
        // Set modified marker to FALSE (i.e. not modified).
        elt->modified = FALSE;
    }

    return( TRUE );
}

BOOL ctl_dlg_done( WPI_INST inst, HWND dlg, void *ptr, void *ctl_ptr)
/*******************************************************************/
/* finalize a data control. Returns TRUE if all field verification is ok,
   FALSE otherwise */
{
    int                 num;
    ctl_elt             *elt;
    clt_def             *ctl = ctl_ptr;      // so app doesn't have to do type cast;

    // enumerate all control elements.
    for( num = ctl->num_ctls, elt = ctl->elts; num > 0; --num, ++elt ) {
        // was the element modified?
        if( elt->modified ) {
            // yes: query new state
            if( !(Ctl_int_actions[elt->type].finish)( elt, inst, dlg, ptr, FINISH_DONE ) ) {
                // some error occured: terminate with error
                return( FALSE );
            }
        }
    }

    return( TRUE );
}

void  ctl_dlg_process( void *ctl_ptr, WPI_PARAM1 wparam, WPI_PARAM2 lparam )
/**************************************************************************/
/* this routine must be called for all WM_COMMAND events sent to the
   dialog. */
{
    clt_def             *ctl = ctl_ptr;      // so app doesn't have to do type cast;
    ctl_elt             *elt;
    int                 num;
    BOOL                mod;

    // enumerate all control elements.
    for( num = ctl->num_ctls, elt = ctl->elts; num > 0; --num, ++elt ) {
        // query if message modified the element
        mod = (Ctl_int_actions[elt->type].modified)( elt, wparam, lparam );
        // mark the modify state
        elt->modified |= mod;
        if( mod ) {
            // the element was modified:
            // no need to check the other elements then.
            break;
        }
    }
}

BOOL ctl_dlg_reset( WPI_INST ___a, HWND dlg, void *ptr, void *ctl_ptr, BOOL ___b)
/*******************************************************************************/
/* this routine must be called to reset the dialog to the given state */
{
    // simply call the ctl_dlg_init routine
    return ctl_dlg_init( ___a, dlg, ptr, ctl_ptr);
}

//////////////////////////////////////////////////////////////////////////////////
// The dyn_tpl_ functions

void dyn_tpl_init( void *dyn_def, HWND dlg_hld )
// Initialize the given dialog by the dynamic template.
{
    int                 num;
    dyn_tpl_dim         *dim; // pointer to the current dyn_tpl_dim object
    dyn_tpl_dlg         *dyn = dyn_def; // so app doesn't have to do type cast
    char                *dimptr = (char*)&dyn->tpls; // points to the start of the next
                                                     // dyn_tpl_dim object
    int                 *int_ctr; // used to count the ints
    int                 i;

    // TODO: add support for static templates

    for( num = dyn->num_tpls; num > 0; --num)
    {
        // set dim to the current dyn_tpl_dim object
        dim = (dyn_tpl_dim*)dimptr;
        // find the size of the current dyn_tpl_dim object
        dimptr += sizeof(dyn_tpl_dim);
        int_ctr = (int*)dimptr;
        while (*int_ctr++ != -1) ; // the list of ints is at it seems terminated by -1 (MISSING!!!)
        dimptr = (char*)int_ctr;
        // Is the current object in use?
        if (dim->info.use)
        {
            // Yes: query the new state
            dyn_dim_type state = dim->info.tpl_state(dlg_hld, TRUE);
            dim->info.state = state;
            // first, there comes a list in form "begin,end" which is zero terminated
            for (i = 0; dim->dyn_tpl[i] != 0; i += 2)
            {
                // extract two elements b and e from the list
                int b = dim->dyn_tpl[i], e = dim->dyn_tpl[i + 1];
                // mark all control elements in range [b; e] as state indicates.
                for (; b <= e; ++b)
                {
                    HWND h = GetDlgItem(dlg_hld, b);
                    ShowWindow(h, (dim->info.state == DYN_INVISIBLE) ? SW_HIDE : SW_SHOW);
                    EnableWindow(h, (dim->info.state == DYN_VISIBLE) ? TRUE : FALSE);
                }
            }
            // then there comes a list in form "item" which is zero terminated
            for (++i; dim->dyn_tpl[i] != 0; ++i)
            {
                // mark control element as state indicates.
                HWND h = GetDlgItem(dlg_hld, dim->dyn_tpl[i]);
                ShowWindow(h, (dim->info.state == DYN_INVISIBLE) ? SW_HIDE : SW_SHOW);
                EnableWindow(h, (dim->info.state == DYN_VISIBLE) ? TRUE : FALSE);
            }
            // I don't know what comes now, just take it as another list (MISSING!!!)
            for (++i; dim->dyn_tpl[i] != -1; ++i)
            {
                // mark control element as state indicates.
                HWND h = GetDlgItem(dlg_hld, dim->dyn_tpl[i]);
                ShowWindow(h, (dim->info.state == DYN_INVISIBLE) ? SW_HIDE : SW_SHOW);
                EnableWindow(h, (dim->info.state == DYN_VISIBLE) ? TRUE : FALSE);
            }
        }
    }
}

void dyn_tpl_process( void *dyn_def, HWND dlg_hld, WPI_PARAM1 parm1, WPI_PARAM2 parm2 )
// Process changes of the dynamic template for the given dialog.
{
    int                 num;
    dyn_tpl_dim         *dim; // pointer to the current dyn_tpl_dim object
    dyn_tpl_dlg         *dyn = dyn_def; // so app doesn't have to do type cast
    char                *dimptr = (char*)&dyn->tpls; // points to the start of the next
                                                     // dyn_tpl_dim object
    int                 *int_ctr; // used to count the ints
    int                 i;

    // TODO: add support for static templates

    for( num = dyn->num_tpls; num > 0; --num )
    {
        // set dim to the current dyn_tpl_dim object
        dim = (dyn_tpl_dim*)dimptr;
        // find the size of the current dyn_tpl_dim object
        dimptr += sizeof(dyn_tpl_dim);
        int_ctr = (int*)dimptr;
        while (*int_ctr++ != -1) ; // the list of ints is at it seems terminated by -1 (MISSING!!!)
        dimptr = (char*)int_ctr;
        // Is the current object in use?
        if (dim->info.use)
            // check if the state has changed
            if (dim->info.tpl_check(parm1, parm2, dlg_hld))
            {
                // query the new state
                dyn_dim_type state = dim->info.tpl_state(dlg_hld, TRUE);
                if (dim->info.state != state)
                {
                    // the state has really changed:
                    dim->info.state = state;
                    // first, there comes a list in form "begin,end" which is zero terminated
                    for (i = 0; dim->dyn_tpl[i] != 0; i += 2)
                    {
                        // extract two elements b and e from the list
                        int b = dim->dyn_tpl[i], e = dim->dyn_tpl[i + 1];
                        // mark all control elements in range [b; e] as state indicates.
                        for (; b <= e; ++b)
                        {
                            HWND h = GetDlgItem(dlg_hld, b);
                            ShowWindow(h, (dim->info.state == DYN_INVISIBLE) ? SW_HIDE : SW_SHOW);
                            EnableWindow(h, (dim->info.state == DYN_VISIBLE) ? TRUE : FALSE);
                        }
                    }
                    // then there comes a list in form "item" which is zero terminated
                    for (++i; dim->dyn_tpl[i] != 0; ++i)
                    {
                        // mark control element as state indicates.
                        HWND h = GetDlgItem(dlg_hld, dim->dyn_tpl[i]);
                        ShowWindow(h, (dim->info.state == DYN_INVISIBLE) ? SW_HIDE : SW_SHOW);
                        EnableWindow(h, (dim->info.state == DYN_VISIBLE) ? TRUE : FALSE);
                    }
                    // I don't know what comes now, just take it as another list (MISSING!!!)
                    for (++i; dim->dyn_tpl[i] != -1; ++i)
                    {
                        // mark control element as state indicates.
                        HWND h = GetDlgItem(dlg_hld, dim->dyn_tpl[i]);
                        ShowWindow(h, (dim->info.state == DYN_INVISIBLE) ? SW_HIDE : SW_SHOW);
                        EnableWindow(h, (dim->info.state == DYN_VISIBLE) ? TRUE : FALSE);
                    }
                }
            }
    }
}

////////////////////////////////////////////////////////////////////////////
// The following code is copyied almost 1:1 from the datactl library
// out of the samples directory.

////////////////////////////////////////////////////////////////////////////
// Check field implementation

static BOOL ctl_check_start( ctl_elt *elt, HANDLE inst, HWND dlg, void *ptr, BOOL ___b )
/**************************************************************************************/
/* start check field */
{
    inst = inst;

    CheckDlgButton( dlg, elt->control, _value_bool( ptr, elt ) );

    return( TRUE );
}

static BOOL ctl_check_finish( ctl_elt *elt, HANDLE inst, HWND dlg, void *ptr, finish_type ___f )
/**********************************************************************************************/
/* end check field */
{
    inst = inst;

    _value_bool( ptr, elt ) = IsDlgButtonChecked( dlg, elt->control );

    return( TRUE );
}

static BOOL ctl_check_modified( ctl_elt *elt, UINT wparam, LONG lparam )
/**********************************************************************/
{
    WORD        cmd;
    WORD        id;

    lparam = lparam;
    id = LOWORD( wparam );
    cmd = GET_WM_COMMAND_CMD( wparam, lparam );
    if( id == elt->control &&
        ( cmd == BN_CLICKED || cmd == BN_DOUBLECLICKED ) ) {
        return( TRUE );
    }

    return( FALSE );
}

////////////////////////////////////////////////////////////////////////////
// Combo list box implementation

static WORD ctl_combo_add_msg( HWND, int );
static WORD ctl_combo_sel_msg( HWND, int );
static WORD ctl_combo_get_msg( HWND, int );

static BOOL ctl_combo_start( ctl_elt *elt, HANDLE inst, HWND dlg, void *ptr, BOOL ___b )
/**************************************************************************************/
/* start a combo list box */
{
    char                value[50];
    WORD                id;
    int                 choose;
    int                 max;

    choose = _value_int( ptr, elt ) - elt->info.combo.origin;

    if( choose < 0 ) {
        choose = 0;
    } else {
        max = elt->info.combo.end_id - elt->info.combo.start_id;
        if( choose > max ) {
            choose = max;
        }
    }

    for( id = elt->info.combo.start_id; id <= elt->info.combo.end_id; ++id ) {

        LoadString( inst, id, value, 50 );
        value[49] = '\0';
        SendDlgItemMessage( dlg, elt->control,

⌨️ 快捷键说明

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