⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 undo.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*
*                            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 "imgedit.h"
#include "undo.h"
#include "iemem.h"

static an_undo_stack    *firstStack;
static an_undo_stack    *lastStack;

/*
 * setBaseImage - Sets the base image (for when no undos are left)
 */
static void setBaseImage( img_node *node, an_undo_stack *stack )
{
    stack->firstxor = DuplicateBitmap( node->hxorbitmap );
    stack->firstand = DuplicateBitmap( node->handbitmap );
} /* setBaseImage */

/*
 * moveToUndo - moves the top of the redo stack to the top of the undo stack.
 */
void moveToUndo( an_undo_stack *stack )
{
    an_undo_node        *new_redo_top;

    if ( !(stack->top_redo) ) {
        return;
    }

    new_redo_top = stack->top_redo->next;
    if (new_redo_top) {
        new_redo_top->previous = NULL;
    }
    stack->top_redo->next = stack->top_undo;

    if (stack->top_undo) {
        stack->top_undo->previous = stack->top_redo;
    } else {
        stack->bottom_undo = stack->top_redo;
    }
    stack->top_undo = stack->top_redo;
    stack->top_redo = new_redo_top;
} /* moveToUndo */

/*
 * copyBitmaps - copy the xor and the and bitmaps
 */
void copyBitmaps( img_node *node, HBITMAP xorbitmap, HBITMAP andbitmap )
{
    WPI_PRES            pres;
    HDC                 destdc;
    WPI_PRES            destpres;
    HDC                 srcdc;
    WPI_PRES            srcpres;
    HBITMAP             oldsrc;
    HBITMAP             olddest;

    pres = _wpi_getpres( node->viewhwnd );
    destpres = _wpi_createcompatiblepres( pres, Instance, &destdc );
    srcpres = _wpi_createcompatiblepres( pres, Instance, &srcdc );
    _wpi_releasepres( node->viewhwnd, pres );

    oldsrc = _wpi_selectbitmap( srcpres, xorbitmap );
    olddest = _wpi_selectbitmap( destpres, node->hxorbitmap );
    _wpi_bitblt( destpres, 0, 0, node->width, node->height, srcpres, 0, 0,
                                                                SRCCOPY );
    _wpi_getoldbitmap( srcpres, oldsrc );
    _wpi_getoldbitmap( destpres, olddest );

    oldsrc = _wpi_selectbitmap( srcpres, andbitmap );
    olddest = _wpi_selectbitmap( destpres, node->handbitmap );
    _wpi_bitblt( destpres, 0, 0, node->width, node->height, srcpres, 0, 0,
                                                                SRCCOPY );
    _wpi_getoldbitmap( srcpres, oldsrc );
    _wpi_getoldbitmap( destpres, olddest );
    _wpi_deletecompatiblepres( srcpres, oldsrc );
    _wpi_deletecompatiblepres( destpres, olddest );
} /* copyBitmaps */

/*
 * deleteRedoStack - deletes the redo stack.
 */
static void deleteRedoStack( an_undo_stack *stack )
{
    an_undo_node        *new_top;

    while( stack->top_redo ) {
        new_top = stack->top_redo->next;
        stack->top_redo->next = NULL;
        _wpi_deletebitmap( stack->top_redo->xorbitmap );
        _wpi_deletebitmap( stack->top_redo->andbitmap );
        MemFree( stack->top_redo );
        stack->top_redo = new_top;
        stack->redocount = 0;
    }
} /* deleteRedoStack */

/*
 * addToRedo - adds a node to the redo stack
 */
void addToRedo( an_undo_stack *stack )
{
    if (!stack) return;
    if (stack->top_redo) {
        stack->top_undo->next = stack->top_redo;
        stack->top_redo->previous = stack->top_undo;
        stack->top_redo = stack->top_undo;
    } else {
        stack->top_redo = stack->top_undo;
        stack->top_redo->next = NULL;
    }
} /* addToRedo */

/*
 * getTopStack - retrieves the top stack (of potentially many icons) from
 *               the icon list.
 */
static an_undo_stack *getTopStack( HWND hwnd )
{
    an_undo_stack       *stack;

    stack = firstStack;
    while( stack ) {
        if (stack->hwnd == hwnd) {
            return( stack );
        }
        stack = stack->next;
    }
    return( NULL );
} /* getTopStack */

/*
 * getStack - returns the stack corresponding to the window handle.
 */
static an_undo_stack *getStack( HWND hwnd )
{
    an_undo_stack       *stack;
    int                 i;

    stack = getTopStack( hwnd );
    if (!stack) {
        return (NULL);
    }

    for (i=0; i < stack->current_icon; ++ i) {
        if (!stack) {
            break;
        }
        stack = stack->nexticon;
    }
    return( stack );
} /* getStack */

/*
 * checkIfSaved - checks if the image is saved or not (by the number of
 *                undo's on the undo stack.
 */
void checkIfSaved( img_node *node )
{
    BOOL                issaved_flag;
    an_undo_stack       *stack;

    stack = getTopStack( node->hwnd );
    if (!stack) return;

    /*
     * if it is currently saved, and we undo an operation, then it becomes
     * unsaved.  from then on, it can only become saved by explicitly saving
     * it.
     */
    if (node->issaved) {
        SetIsSaved( node->hwnd, FALSE );
        while( stack ) {
            stack->modified = TRUE;
            stack = stack->nexticon;
        }
        return;
    }

    issaved_flag = TRUE;
    while (stack) {
        if ( (stack->opcount == 0) && !(stack->modified) ) {
            issaved_flag = TRUE & issaved_flag;
        } else {
            issaved_flag = FALSE;
            if (node->issaved) {
                SetIsSaved( node->hwnd, FALSE );
            }
            break;
        }
        stack = stack->nexticon;
    }
    SetIsSaved( node->hwnd, issaved_flag );
} /* checkIfSaved */

/*
 * deleteFromBottom - delete an element from the bottom of the stack (since
 *                    the stack is a fixed size).
 */
static void deleteFromBottom( an_undo_stack *stack )
{
    an_undo_node        *temp;

    if (!stack) return;
    if (!(stack->bottom_undo)) {
        return;
    }

    temp = stack->bottom_undo->previous;
    _wpi_deletebitmap( stack->firstxor );
    _wpi_deletebitmap( stack->firstand );
    stack->firstxor = stack->bottom_undo->xorbitmap;
    stack->firstand = stack->bottom_undo->andbitmap;
    stack->bottom_undo->previous = NULL;
    MemFree( stack->bottom_undo );

    stack->bottom_undo = temp;
    if (temp) {
        stack->bottom_undo->next = NULL;
    }
} /* deleteFromBottom */

/*
 * moveFromTop - delete from the top of the stack (when undo is selected)
 *                 if this call is a result of an UndoOp, the xor and and
 *                 bitmaps are the new bitmaps for the active image so we
 *                 don't want to delete them.
 */
static void moveFromTop( an_undo_stack *stack, BOOL add_to_redo )
{
    an_undo_node        *new_undo;

    if (!(stack->top_undo)) {
        return;
    }

    new_undo = stack->top_undo->next;
    if (new_undo) {
        new_undo->previous = NULL;
    } else {
        stack->bottom_undo = NULL;
    }

    if (!add_to_redo) {
        _wpi_deletebitmap( stack->top_undo->xorbitmap );
        _wpi_deletebitmap( stack->top_undo->andbitmap );
        stack->top_undo->next = NULL;
        MemFree( stack->top_undo );
    } else {
        addToRedo( stack );
    }

    stack->top_undo = new_undo;
} /* moveFromTop */

/*
 * RecordImage - After something is drawn, the operation is recorded so
 *                   that it can be undone if desired.
 */
void RecordImage( HWND hwnd )
{
    an_undo_node        *undo_node;
    an_undo_stack       *stack;
    img_node            *image_node;
    long                bytes;
    DWORD               free_space;
    DWORD               space_needed;

    stack = getStack( hwnd );
    if (!stack) return;

    deleteRedoStack( stack );

#ifndef __OS2_PM__
    free_space = GetFreeSpace( 0 );
#else
    free_space = 0;
#endif
    image_node = SelectImage( hwnd );
    if (!image_node) return;

    bytes = (image_node->width * image_node->bitcount + 31) / 32;
    bytes = bytes * 4 * image_node->height;
    /*
     * Here's a bit of a problem:  I'm not sure how much Windows is going
     * to need to keep running relatively happily!
     */
    space_needed =  max( SPACE_MIN, SPACE_LIMIT * bytes );

#ifndef __OS2_PM__
#ifndef __NT__
    if (free_space < space_needed) {
        if (!RelieveUndos()) {
            /*
             * No image is recorded if undo's could not be relieved.
             */
            return;
        }
    }
#endif
#endif

    undo_node = MemAlloc( sizeof(an_undo_node) );
    if (!undo_node) {
        RelieveUndos();
        undo_node = MemAlloc( sizeof(an_undo_node) );
        if (!undo_node) return;
    }
    undo_node->previous = NULL;
    undo_node->xorbitmap = DuplicateBitmap(image_node->hxorbitmap);
    undo_node->andbitmap = DuplicateBitmap(image_node->handbitmap);

    if (stack->opcount == 0) {
        undo_node->next = NULL;
        stack->top_undo = undo_node;
        stack->bottom_undo = undo_node;
    } else {
        undo_node->next = stack->top_undo;
        stack->top_undo->previous = undo_node;
        stack->top_undo = undo_node;
    }

    ++(stack->opcount);

    if (image_node->issaved) {
        SetIsSaved( image_node->hwnd, FALSE );
    }
} /* RecordImage */

/*
 * UndoOp - Undoes an operation.
 */
void UndoOp( void )
{
    img_node            *node;
    an_undo_stack       *stack;

    node = GetCurrentNode();

    if (!node) {
        return;
    }

    stack = getStack( node->hwnd );
    if (!stack) return;

    if (stack->opcount <= 0) {
        PrintHintTextByID( WIE_UNDOSTACKEMPTY, NULL );
        return;
    }

    moveFromTop(stack, TRUE);
    if ( !(stack->top_undo) ) {
        copyBitmaps( node, stack->firstxor, stack->firstand );
    } else {
        copyBitmaps( node, stack->top_undo->xorbitmap, stack->top_undo->andbitmap );
    }
    --(stack->opcount);
    ++(stack->redocount);

    IEPrintAmtText( WIE_UNDOITEMSLEFT, stack->opcount );

    InvalidateRect( node->viewhwnd, NULL, TRUE );
    BlowupImage(node->hwnd, NULL);

    checkIfSaved( node );
} /* UndoOp */

/*
 * CheckForUndo - check if the undo menu options should be enabled or not.
 */
void CheckForUndo( img_node *node )
{
    an_undo_stack       *stack;
    HMENU               hmenu;

    if (HMainWindow) {
        hmenu = _wpi_getmenu( _wpi_getframe(HMainWindow) );
    } else {
        return;
    }

    if (!node) {
        _wpi_enablemenuitem(hmenu, IMGED_UNDO, FALSE, FALSE);
        _wpi_enablemenuitem(hmenu, IMGED_REDO, FALSE, FALSE);
        return;
    }

    stack = getStack( node->hwnd );
    if (!stack) {
        _wpi_enablemenuitem(hmenu, IMGED_UNDO, FALSE, FALSE);
        _wpi_enablemenuitem(hmenu, IMGED_REDO, FALSE, FALSE);
        return;
    }

    if (stack->opcount <= 0) {
        _wpi_enablemenuitem(hmenu, IMGED_UNDO, FALSE, FALSE);
    } else {
        _wpi_enablemenuitem(hmenu, IMGED_UNDO, TRUE, FALSE);
    }

    if (stack->top_redo) {
        _wpi_enablemenuitem(hmenu, IMGED_REDO, TRUE, FALSE);
    } else {
        _wpi_enablemenuitem(hmenu, IMGED_REDO, FALSE, FALSE);
    }

    if (stack->original_xor) {
        _wpi_enablemenuitem(hmenu, IMGED_REST, TRUE, FALSE);
    } else {
        _wpi_enablemenuitem(hmenu, IMGED_REST, FALSE, FALSE);
    }
} /* CheckForUndo */

⌨️ 快捷键说明

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