ssbar.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 425 行

C
425
字号
/****************************************************************************
*
*                            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 "winvi.h"
#include <string.h>
#include <stdlib.h>
#include "ssbar.h"
#include "ssbardef.h"
#include "utils.h"
#include "subclass.h"
#include "wstatus.h"
#include "statwnd.h"

#define NARRAY( a )             ( sizeof( a ) / sizeof( a[ 0 ] ) )

#define DEFAULT_STATUSSTRING    "Line:$5L$[Col:$3C$[Mode: $M$[$|$T$[$H"
#define DEFAULT_STATUSSECTIONS  { 60, 105, 192, 244 }

enum buttonType {
    BUTTON_CONTENT,
    BUTTON_ALIGNMENT,
};

HWND            hSSbar = NULL;
static bool     haveCapture = FALSE;
static int      curItemID = -1;
static HWND     mod_hwnd;

char *findBlockString( int block )
{
    char    *mod;
    int     i;

    i = 0;
    mod = StatusString;
    while( i != block ) {
        while( *mod && *mod != '$' ) {
            mod++;
        }
        assert( *mod != '\0' );
        mod++;
        if( *mod == '[' ) {
            i++;
        }
        mod++;
    }
    return( mod );
}

void totalRedraw( void )
{
    StatusWndSetSeparatorsWithArray( StatusSections, NumStatusSections );
    UpdateStatusWindow();
    InvalidateRect( StatusWindow, NULL, TRUE );
    UpdateWindow( StatusWindow );
}

void destroyBlock( int i, char *start )
{
    char    new_ss[ MAX_STR ];

    if( NumStatusSections == 1 ) {
        // unfortunately wstatus.c can't handle this right now
        // (it would be nice)
        MyBeep();
        return;
    }

    if( i != NumStatusSections ) {
        memmove( StatusSections + i, StatusSections + i + 1,
                 ( NumStatusSections - 1 - i ) * sizeof( short ) );
    }
    NumStatusSections--;
    StatusSections = MemReAlloc( StatusSections,
                                 NumStatusSections * sizeof( short ) );

    strncpy( new_ss, StatusString, start - StatusString );
    new_ss[ start - StatusString ] = '\0';
    while( start[0] && !( start[0] == '$' && start[1] == '[' ) ) {
        start++;
    }
    if( start[0] == '$' ) {
        start += 2;
        strcat( new_ss, start );
    }
    AddString2( &StatusString, new_ss );

    totalRedraw();
}

void splitBlock( int i, char *start )
{
    char    new_ss[ MAX_STR ];
    int     diff;
    RECT    rect;

    if( NumStatusSections == MAX_SECTIONS ) {
        MyBeep();
        return;
    }

    if( i == NumStatusSections ) {
        GetWindowRect( StatusWindow, &rect );
        diff = rect.right - StatusSections[ i - 1 ];
    } else if( i == 0 ) {
        diff = StatusSections[ 1 ];
    } else {
        diff = StatusSections[ i ] - StatusSections[ i - 1 ];
    }

    if( diff < BOUNDARY_WIDTH * 4 ) {
        MyBeep();
        return;
    }
    NumStatusSections++;
    StatusSections = MemReAlloc( StatusSections,
                                 NumStatusSections * sizeof( short ) );
    memmove( StatusSections + i + 1, StatusSections + i,
             ( NumStatusSections - 1 - i ) * sizeof( short ) );
    if( i > 0 ) {
        StatusSections[ i ] = StatusSections[ i - 1 ] + ( diff / 2 );
    } else {
        StatusSections[ i ] /= 2;
    }

    while( start[0] && !( start[0] == '$' && start[1] == '[' ) ) {
        start++;
    }
    strncpy( new_ss, StatusString, start - StatusString );
    new_ss[ start - StatusString ] = '\0';
    strcat( new_ss, "$[ " );
    strcat( new_ss, start );
    AddString2( &StatusString, new_ss );

    totalRedraw();
}

void buildNewItem( char *start, int id )
{
    char    new_ss[ MAX_STR ];
    char    *sz_content[] = { "$T", "$D", "Mode: $M",
                              "Line:$5L", "Col:$3C", "$H" };
    char    *sz_alignment[] = { "$<", "$|", "$>" };
    char    *new_item;
    int     type;

    if( id >= SS_FIRST_CONTENT && id <= SS_LAST_CONTENT ) {
        new_item = sz_content[ id - SS_FIRST_CONTENT ];
        type = BUTTON_CONTENT;
    } else if( id >= SS_FIRST_ALIGNMENT && id <= SS_LAST_ALIGNMENT ) {
        new_item = sz_alignment[ id - SS_FIRST_ALIGNMENT ];
        type = BUTTON_ALIGNMENT;
    } else {
        assert( 0 );
    }

    strncpy( new_ss, StatusString, start - StatusString );
    new_ss[ start - StatusString ] = '\0';
    strcat( new_ss, new_item );
    if( type == BUTTON_CONTENT ) {
        // only copy alignments, if any
        while( start[0] && !( start[0] == '$' && start[1] == '[' ) ) {
            if( start[0] == '$' && ( start[1] == '<' || start[1] == '|'
                                                     || start[1] == '>' ) ) {
                strncat( new_ss, start, 2 );
                start++;
            }
            start++;
        }
    } else {
        // only copy contents, if any
        while( start[0] && !( start[0] == '$' && start[1] == '[' ) ) {
            if( start[0] == '$' && ( start[1] == '<' || start[1] == '|'
                                                     || start[1] == '>' ) ) {
                start += 2;
                continue;
            }
            // by no means the most efficient way, but hardly matters
            strncat( new_ss, start, 1 );
            start++;
        }
    }
    strcat( new_ss, start );
    AddString2( &StatusString, new_ss );

    totalRedraw();
}

void buildDefaults( void )
{
    short   def_sections[] = DEFAULT_STATUSSECTIONS;

    AddString2( &StatusString, DEFAULT_STATUSSTRING );

    NumStatusSections = NARRAY( def_sections );
    StatusSections = MemReAlloc( StatusSections, sizeof( def_sections ) );
    memcpy( StatusSections, def_sections, sizeof( def_sections ) );

    totalRedraw();
}

void buildNewStatusString( int block, int id )

{
    char    *mod;

    mod = findBlockString( block );

    switch( id ) {
        case SS_SPLIT:
            splitBlock( block, mod );
            break;
        case SS_DESTROY:
            destroyBlock( block, mod );
            break;
        case SS_DEFAULTS:
            buildDefaults();
            break;
        default:
            buildNewItem( mod, id );
    }
}

static void sendNewItem( int x, int id )
{
    int     i;

    if( mod_hwnd == NULL ) {
        return;
    }
    assert( mod_hwnd == StatusWindow );

    i = 0;
    while( i < NumStatusSections && StatusSections[ i ] < x ) {
        i++;
    }

    assert( curItemID != -1 );
    buildNewStatusString( i, id );
}

static long processLButtonUp( HWND hwnd, LONG lparam )
{
    POINT   m_pt;
    if( haveCapture ) {
        MAKE_POINT( m_pt, lparam );
        ClientToScreen( hwnd, &m_pt );
        ScreenToClient( StatusWindow, &m_pt );
        sendNewItem( m_pt.x, curItemID );
        CursorOp( COP_ARROW );
        DrawRectangleUpDown( hwnd, DRAW_UP );
        ReleaseCapture();
        haveCapture = FALSE;
        curItemID = -1;
    }
    return( 0L );
}

static long processLButtonDown( HWND hwnd )
{
    DrawRectangleUpDown( hwnd, DRAW_DOWN );
    CursorOp( COP_DROPSS );
    SetCapture( hwnd );
    haveCapture = TRUE;
    curItemID = GetDlgCtrlID( hwnd );
    mod_hwnd = NULL;
    return( 0L );
}

static long processMouseMove( HWND hwnd, UINT msg, UINT wparam, LONG lparam )
{
    RECT    rect;
    POINT   m_pt;

    msg = msg;
    wparam = wparam;

    if( haveCapture == FALSE ) {
        return( 0L );
    }

    // check we aren't on ourselves first
    MAKE_POINT( m_pt, lparam );
    ClientToScreen( hwnd, &m_pt );
    GetWindowRect( GetParent( hwnd ), &rect );
    if( PtInRect( &rect, m_pt ) ) {
        CursorOp( COP_DROPSS );
        mod_hwnd = NULL;
        return( 0L );
    }

    // otherwise, figure out what we're over & set cursor based on that
    mod_hwnd = GetOwnedWindow( m_pt );
    if( mod_hwnd == StatusWindow ) {
        CursorOp( COP_DROPSS );
    } else {
        mod_hwnd = NULL;
        CursorOp( COP_NODROP );
    }
    return( 0L );
}

long WINEXP StaticSubclassProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
    switch( msg ) {
    case WM_NCHITTEST:
        return( HTCLIENT );
    case WM_MOUSEMOVE:
        return( processMouseMove( hwnd, msg, wparam, lparam ) );
    case WM_LBUTTONDOWN:
        return( processLButtonDown( hwnd ) );
    case WM_LBUTTONUP:
        return( processLButtonUp( hwnd, lparam ) );
    }
    return( CallWindowProc( SubclassGenericFindOldProc( hwnd ),
                            hwnd, msg, wparam, lparam ) );
}

void addSubclasses( HWND hwnd )
{
    int     i;
    for( i = SS_FIRST_CONTENT; i <= SS_LAST_CONTENT; i++ ) {
        SubclassGenericAdd( GetDlgItem( hwnd, i ), (WNDPROC)StaticSubclassProc );
    }
    for( i = SS_FIRST_ALIGNMENT; i <= SS_LAST_ALIGNMENT; i++ ) {
        SubclassGenericAdd( GetDlgItem( hwnd, i ), (WNDPROC)StaticSubclassProc );
    }
    for( i = SS_FIRST_COMMAND; i <= SS_LAST_COMMAND; i++ ) {
        SubclassGenericAdd( GetDlgItem( hwnd, i ), (WNDPROC)StaticSubclassProc );
    }
}

void removeSubclasses( HWND hwnd )
{
    int     i;
    for( i = SS_FIRST_CONTENT; i <= SS_LAST_CONTENT; i++ ) {
        SubclassGenericRemove( GetDlgItem( hwnd, i ) );
    }
    for( i = SS_FIRST_ALIGNMENT; i <= SS_LAST_ALIGNMENT; i++ ) {
        SubclassGenericRemove( GetDlgItem( hwnd, i ) );
    }
    for( i = SS_FIRST_COMMAND; i <= SS_LAST_COMMAND; i++ ) {
        SubclassGenericRemove( GetDlgItem( hwnd, i ) );
    }
}

/*
 * SSDlgProc - callback routine for status bar settings drag & drop dialog
 */
BOOL WINEXP SSDlgProc( HWND hwnd, UINT msg, UINT wparam, LONG lparam )
{
    lparam = lparam;
    wparam = wparam;
    hwnd = hwnd;

    switch( msg ) {
    case WM_INITDIALOG:
        hSSbar = hwnd;
        MoveWindowTopRight( hwnd );
        addSubclasses( hwnd );
        return( TRUE );
    case WM_CLOSE:
        removeSubclasses( hwnd );
        hSSbar = NULL;
        // update editflags (may have closed from system menu)
        EditFlags.SSbar = FALSE;
        DestroyWindow( hwnd );
        break;
    }
    return( FALSE );
}

/*
 * RefreshSSbar - turn status settings bar on/off
 */
void RefreshSSbar( void )
{
    static DLGPROC      proc;

    if( EditFlags.SSbar ) {
        if( hSSbar != NULL ) {
            return;
        }
        proc = (DLGPROC) MakeProcInstance( (FARPROC) SSDlgProc, InstanceHandle );
        hSSbar = CreateDialog( InstanceHandle, "SSBAR", Root, proc );
    } else {
        if( hSSbar == NULL ) {
            return;
        }
        SendMessage( hSSbar, WM_CLOSE, 0, 0L );
        FreeProcInstance( (FARPROC) proc );
    }
    UpdateStatusWindow();
}

⌨️ 快捷键说明

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