File:  [WindowsNT SDKs] / mstools / ole20 / samples / outline / outllist.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:24:38 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993

/*************************************************************************
** 
**    OLE 2 Sample Code
**    
**    outldata.c
**    
**    This file contains LineList and NameTable functions
**    and related support functions.
**    
**    (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
**
*************************************************************************/


#include "outline.h"

OLEDBGDATA

extern LPOUTLINEAPP g_lpApp;

char ErrMsgListBox[] = "Can't create ListBox!";

static int g_iMapMode;

/* LineList_Init
 * -------------
 *
 *      Create and Initialize the LineList (owner-drawn listbox)
 */
BOOL LineList_Init(LPLINELIST lpLL, LPOUTLINEDOC lpOutlineDoc)
{
    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;

#if defined( INPLACE_CNTR )
    lpLL->m_hWndListBox = CreateWindow(
                    "listbox",              /* Window class name           */
                    NULL,                   /* Window's title              */
                    WS_CHILDWINDOW |

                    /* OLE2NOTE: an in-place contanier MUST use
                    **    WS_CLIPCHILDREN window style for the window
                    **    that it uses as the parent for the server's
                    **    in-place active window so that its
                    **    painting does NOT interfere with the painting
                    **    of the server's in-place active child window.
                    */

                    WS_CLIPCHILDREN |
                    WS_VISIBLE |
                    WS_VSCROLL |
                    WS_HSCROLL |
                    LBS_EXTENDEDSEL |
                    LBS_NOTIFY |
                    LBS_OWNERDRAWVARIABLE |
                    LBS_NOINTEGRALHEIGHT |
                    LBS_USETABSTOPS,
                    0, 0,                   /* Use default X, Y            */
                    0, 0,                   /* Use default X, Y            */
                    lpOutlineDoc->m_hWndDoc,/* Parent window's handle      */
                    (HMENU)IDC_LINELIST,    /* Child Window ID             */
                    lpOutlineApp->m_hInst,  /* Instance of window          */
                    NULL);                  /* Create struct for WM_CREATE */
#else
    lpLL->m_hWndListBox = CreateWindow(
                    "listbox",              /* Window class name           */
                    NULL,                   /* Window's title              */
                    WS_CHILDWINDOW |
                    WS_VISIBLE |
                    WS_VSCROLL |
                    WS_HSCROLL |
                    LBS_EXTENDEDSEL |
                    LBS_NOTIFY |
                    LBS_OWNERDRAWVARIABLE |
                    LBS_NOINTEGRALHEIGHT |
                    LBS_USETABSTOPS,
                    0, 0,                   /* Use default X, Y            */
                    0, 0,                   /* Use default X, Y            */
                    lpOutlineDoc->m_hWndDoc,/* Parent window's handle      */
                    (HMENU)IDC_LINELIST,    /* Child Window ID             */
                    lpOutlineApp->m_hInst,  /* Instance of window          */
                    NULL);                  /* Create struct for WM_CREATE */

#endif                      


    if(! lpLL->m_hWndListBox) {
        OutlineApp_ErrorMessage(g_lpApp, ErrMsgListBox);
        return FALSE;
    }

    lpOutlineApp->m_ListBoxWndProc = 
            (FARPROC) GetWindowLong ( lpLL->m_hWndListBox, GWL_WNDPROC );
    SetWindowLong (lpLL->m_hWndListBox, GWL_WNDPROC, (LONG) LineListWndProc);

#if defined ( USE_DRAGDROP )
    /* m_iDragOverLine saves index of line that has drag/drop target 
    **    feedback. we currently use our focus rectangle feedback for
	**    this. it would be better to have a different visual feedback
	**    for potential target of the pending drop.
    */
    lpLL->m_iDragOverLine = -1;
#endif

    lpLL->m_nNumLines = 0;
    lpLL->m_nMaxLineWidthInHimetric = 0;
    lpLL->m_lpDoc = lpOutlineDoc;
    _fmemset(&lpLL->m_lrSaveSel, 0, sizeof(LINERANGE));
	
    return TRUE;
}


/* LineList_Destroy
 * ----------------
 *
 *      Clear (delete) all Line objects from the list and free supporting
 *      memory (ListBox Window) used by the LineList object itself.
 */
void LineList_Destroy(LPLINELIST lpLL)
{
    int i;
    int linesTotal = lpLL->m_nNumLines;

    // Delete all Line objects
    for (i = 0; i < linesTotal; i++) 
        LineList_DeleteLine(lpLL, 0);   // NOTE: always delete line 0

    // Remove all Lines from the ListBox
    SendMessage(lpLL->m_hWndListBox,LB_RESETCONTENT,0,0L);

    lpLL->m_nNumLines=0;
    DestroyWindow(lpLL->m_hWndListBox);
    lpLL->m_hWndListBox = NULL;
}


/* LineList_AddLine
 * ----------------
 *
 *      Add one line to the list box. The line is added following the 
 * line with index "nIndex". If nIndex is larger than the number of lines
 * in the ListBox, then the line is appended to the end. The selection
 * is set to the newly added line.
 */
void LineList_AddLine(LPLINELIST lpLL, LPLINE lpLine, int nIndex)
{
    int nAddIndex = (lpLL->m_nNumLines == 0 ? 
            0 : 
            (nIndex >= lpLL->m_nNumLines ? lpLL->m_nNumLines : nIndex+1));
    LINERANGE lrSel;
	
#if defined( USE_HEADING )
	int nHeight = Line_GetHeightInHimetric(lpLine);
	
	nHeight = XformHeightInHimetricToPixels(NULL, nHeight);
	
	// Add a dummy string to the row heading
	Heading_RH_SendMessage(OutlineDoc_GetHeading(lpLL->m_lpDoc), 
			LB_INSERTSTRING, (WPARAM)nAddIndex, MAKELPARAM(nHeight, 0));
#endif


    lrSel.m_nStartLine = nAddIndex;
    lrSel.m_nEndLine =   nAddIndex;

    if (!lpLine) {
        OutlineApp_ErrorMessage(g_lpApp, "Could not create line.");
        return;
    }
	
    SendMessage(lpLL->m_hWndListBox, LB_INSERTSTRING, (WPARAM)nAddIndex,
			(DWORD)lpLine);
					
    LineList_SetMaxLineWidthInHimetric(
            lpLL, 
            Line_GetTotalWidthInHimetric(lpLine)
    );
    
    lpLL->m_nNumLines++;
    
    LineList_SetSel(lpLL, &lrSel);
}


/* LineList_DeleteLine
 * -------------------
 *
 *      Delete one line from listbox and memory
 */
void LineList_DeleteLine(LPLINELIST lpLL, int nIndex)
{
    LPLINE lpLine = LineList_GetLine(lpLL, nIndex);
    BOOL fResetSel;
    
    fResetSel = (BOOL)SendMessage(lpLL->m_hWndListBox, LB_GETSEL, (WPARAM)nIndex, 0L);

    if (lpLine)
        Line_Delete(lpLine);    // free memory of Line

    // Remove the Line from the ListBox
    SendMessage(lpLL->m_hWndListBox, LB_DELETESTRING, (WPARAM)nIndex, 0L);
    lpLL->m_nNumLines--;

    if (fResetSel) {
        if (nIndex > 0) {
#if defined( WIN32 )
            SendMessage(
                    lpLL->m_hWndListBox, 
                    LB_SETSEL,
                    (WPARAM)TRUE,
                    (LPARAM)nIndex-1
            );
#else 
            SendMessage(
                    lpLL->m_hWndListBox, 
                    LB_SETSEL,
                    (WPARAM)TRUE,
                    MAKELPARAM(nIndex-1,0)
            );
#endif
        } else {
            if (lpLL->m_nNumLines > 0) {
#if defined( WIN32 )
                SendMessage(
                        lpLL->m_hWndListBox, 
                        LB_SETSEL,
                        (WPARAM)TRUE,
                        (LPARAM)0
                );
#else 
                SendMessage(
                        lpLL->m_hWndListBox, 
                        LB_SETSEL,
                        (WPARAM)TRUE,
                        MAKELPARAM(0,0)
                );
#endif
            }
        }
    }
	
#if defined( USE_HEADING )
	// Remove the dummy string from the row heading
	Heading_RH_SendMessage(OutlineDoc_GetHeading(lpLL->m_lpDoc), 
			LB_DELETESTRING, (WPARAM)nIndex, 0L);
#endif

}


/* LineList_ReplaceLine
 * --------------------
 *
 *      Replace the line at a given index in the list box with a new 
 * line.
 */
void LineList_ReplaceLine(LPLINELIST lpLL, LPLINE lpLine, int nIndex)
{
    LPLINE lpOldLine = LineList_GetLine(lpLL, nIndex);

    if (lpOldLine)
        Line_Delete(lpOldLine);    // free memory of Line
    else 
        return;     // if no previous line then invalid index

    SendMessage(
            lpLL->m_hWndListBox, 
            LB_SETITEMDATA, 
            (WPARAM)nIndex, 
            (LPARAM)lpLine
    );
}


/* LineList_GetLineIndex
 * ---------------------
 *
 *      Return the index of the Line given a pointer to the line.
 *      Return -1 if the line is not found.
 */
int LineList_GetLineIndex(LPLINELIST lpLL, LPLINE lpLine)
{
    LRESULT lReturn;

    if (! lpLine) return -1;

    lReturn = SendMessage(
            lpLL->m_hWndListBox,
            LB_FINDSTRING, 
            (WPARAM)-1, 
            (LPARAM)(LPCSTR)lpLine
        );
    
    return ((lReturn == LB_ERR) ? -1 : (int)lReturn);
}


/* LineList_GetLine
 * ----------------
 *
 *      Retrieve the pointer to the Line given its index in the LineList
 */
LPLINE LineList_GetLine(LPLINELIST lpLL, int nIndex)
{
    DWORD dWord = 0;
    LPLINE lpLine;

    if (lpLL->m_nNumLines == 0 || nIndex > lpLL->m_nNumLines || nIndex < 0) 
        return NULL;

    SendMessage(lpLL->m_hWndListBox,LB_GETTEXT,nIndex,(LPARAM)(LPCSTR)&dWord);
    lpLine=(LPLINE)dWord;
    return lpLine;
}


/* LineList_SetFocusLine
 * ---------------------
 *
 */
 
void LineList_SetFocusLine ( LPLINELIST lpLL, WORD wIndex )
{
    
    SendMessage(lpLL->m_hWndListBox, LB_SETCARETINDEX, (WPARAM)wIndex, 0L );

}


/* LineList_GetLineRect
 * --------------------
 *
 * Retrieve the rectangle of a Line given its index in the LineList
 */
BOOL LineList_GetLineRect(LPLINELIST lpLL, int nIndex, LPRECT lpRect)
{
    DWORD iReturn = (DWORD)LB_ERR; 

    if ( !(lpLL->m_nNumLines == 0 || nIndex > lpLL->m_nNumLines || nIndex < 0) ) 
        iReturn = SendMessage(lpLL->m_hWndListBox,LB_GETITEMRECT,nIndex,(LPARAM)lpRect);

    return (iReturn == LB_ERR ? FALSE : TRUE );
}


/* LineList_GetFocusLineIndex
 * --------------------------
 *
 * Get the index of the line that currently has focus (the active line).
 */
int LineList_GetFocusLineIndex(LPLINELIST lpLL)
{
    return (int)SendMessage(lpLL->m_hWndListBox,LB_GETCARETINDEX,0,0L);
}


/* LineList_GetCount
 * -----------------
 *
 *      Return number of line objects 
 */
int LineList_GetCount(LPLINELIST lpLL)
{
	if (lpLL) 
		return lpLL->m_nNumLines;
	else {
		OleDbgAssert(lpLL!=NULL);
		return 0;
	}
}


/* LineList_SetMaxLineWidthInHimetric
 * ----------------------------------
 *
 *	Adjust the maximum line width for the listbox. The max line width is 
 *	used to determine if a horizontal scroll bar is needed.
 *
 *	Parameters:
 *		nWidthInHimetric - if +ve, width of an additional line
 *						 - if -ve, reset Max to be the value 
 *
 *	Returns:
 *      TRUE is max line width of LineList changed
 *      FALSE if no change
 */
BOOL LineList_SetMaxLineWidthInHimetric(LPLINELIST lpLL, int nWidthInHimetric)
{
    int nWidthInPix;
    BOOL fSizeChanged = FALSE;
	LPSCALEFACTOR lpscale;
	
	if (!lpLL)
		return FALSE;

	lpscale = OutlineDoc_GetScaleFactor(lpLL->m_lpDoc);

	if (nWidthInHimetric < 0) {
		lpLL->m_nMaxLineWidthInHimetric = -1;
		nWidthInHimetric *= -1;
	}
	
    if (nWidthInHimetric > lpLL->m_nMaxLineWidthInHimetric) {
        lpLL->m_nMaxLineWidthInHimetric = nWidthInHimetric;
        nWidthInPix = XformWidthInHimetricToPixels(NULL, nWidthInHimetric +
				LOWORD(OutlineDoc_GetMargin(lpLL->m_lpDoc)) +
				HIWORD(OutlineDoc_GetMargin(lpLL->m_lpDoc)));

		nWidthInPix = (int)(nWidthInPix * lpscale->dwSxN / lpscale->dwSxD);
        SendMessage(
                lpLL->m_hWndListBox, 
                LB_SETHORIZONTALEXTENT, 
                nWidthInPix,
                0L
        );
        fSizeChanged = TRUE;

#if defined( USE_HEADING )
		Heading_CH_SetHorizontalExtent(
				OutlineDoc_GetHeading(lpLL->m_lpDoc), lpLL->m_hWndListBox);
#endif

    }
    return fSizeChanged;
}


/* LineList_GetMaxLineWidthInHimetric
 * ----------------------------------
 *
 *      Return the width of the widest line
 */
int LineList_GetMaxLineWidthInHimetric(LPLINELIST lpLL)
{
    return lpLL->m_nMaxLineWidthInHimetric;
}


/* LineList_RecalcMaxLineWidthInHimetric
 * -------------------------------------
 *
 *	Recalculate the maximum line width in the entire list. 
 *
 *	Parameters:
 *		nWidthInHimetric should be set to the width of line being removed.
 *		nWidthInHimetric == 0 forces list to recalculate in all cases.
 *		nWidthInHimetric == current max width => forces recalc.
 *
 *	Returns:
 *      TRUE is max line width of LineList changed
 *      FALSE if no change
 */
BOOL LineList_RecalcMaxLineWidthInHimetric(
        LPLINELIST          lpLL, 
	int                 nWidthInHimetric
)
{
    int i;
    LPLINE lpLine;
    BOOL fSizeChanged = FALSE;
    int nOrgMaxLineWidthInHimetric = lpLL->m_nMaxLineWidthInHimetric;

    if (nWidthInHimetric == 0 || 
        nWidthInHimetric == lpLL->m_nMaxLineWidthInHimetric) {
		
        lpLL->m_nMaxLineWidthInHimetric = -1;		
		
        LineList_SetMaxLineWidthInHimetric(lpLL, 0);

        for(i = 0; i < lpLL->m_nNumLines; i++) {
            lpLine=LineList_GetLine(lpLL, i);
            LineList_SetMaxLineWidthInHimetric(
                    lpLL, 
                    Line_GetTotalWidthInHimetric(lpLine)
            );
        }
    }
    
    if (nOrgMaxLineWidthInHimetric != lpLL->m_nMaxLineWidthInHimetric) 
        fSizeChanged = TRUE;

    return fSizeChanged;
}


/* LineList_CalcSelExtentInHimetric
 * --------------------------------
 *
 *      Calculate the extents (widht and height) of a selection of lines.
 *
 * if lplrSel == NULL, calculate extent of all lines.
 */
void LineList_CalcSelExtentInHimetric(
        LPLINELIST          lpLL, 
        LPLINERANGE         lplrSel, 
        LPSIZEL             lpsizel
)
{
    int i;
    int nEndLine;
    int nStartLine;
    LPLINE lpLine;
    long lWidth;

    if (lplrSel) {
        nEndLine = lplrSel->m_nEndLine;
        nStartLine = lplrSel->m_nStartLine;
    } else {
        nEndLine = LineList_GetCount(lpLL) - 1;
        nStartLine = 0;
    }

    lpsizel->cx = 0;
    lpsizel->cy = 0;

    for(i = nStartLine; i <= nEndLine; i++) {
        lpLine=LineList_GetLine(lpLL,i);
        lWidth = (long)Line_GetTotalWidthInHimetric(lpLine);
        lpsizel->cx = max(lpsizel->cx, lWidth);
        lpsizel->cy += lpLine->m_nHeightInHimetric;
    }
}


/* LineList_GetWindow
 * ------------------
 *
 * Return handle of list box
 */
HWND LineList_GetWindow(LPLINELIST lpLL)
{
    return lpLL->m_hWndListBox;
}


/* LineList_GetDC
 * --------------
 *
 * Return DC handle of list box
 */
HDC LineList_GetDC(LPLINELIST lpLL)
{
    HFONT hfontOld;
    HDC hDC = GetDC(lpLL->m_hWndListBox);
    int     iXppli;     //* pixels per logical inch along width
    int     iYppli;     //* pixels per logical inch along height 
    SIZE    size;

    // Setup a mapping mode for the DC which maps physical pixel
    // coordinates to HIMETRIC units. The standard MM_HIMETRIC mapping
    // mode does not work correctly because it does not take into
    // account that a logical inch on the display screen is drawn
    // physically larger than 1 inch. We will setup an anisotropic
    // mapping mode which will perform the transformation properly.

    g_iMapMode = SetMapMode(hDC, MM_ANISOTROPIC);
    iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
    iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
    SetViewportExtEx(hDC, iXppli, iYppli, &size);
    SetWindowExtEx(hDC, HIMETRIC_PER_INCH, HIMETRIC_PER_INCH, &size);

    // Set the default font size, and font face name
    hfontOld = SelectObject(hDC, OutlineApp_GetActiveFont(g_lpApp));

    return hDC;
}   


/* LineList_ReleaseDC
 * ------------------
 *
 *      Release DC of list box returned from previous LineList_GetDC call.
 */
void LineList_ReleaseDC(LPLINELIST lpLL, HDC hDC)
{
    SetMapMode(hDC, g_iMapMode);    
    ReleaseDC(lpLL->m_hWndListBox, hDC);
}


/* LineList_SetLineHeight
 * ----------------------
 *
 *      Set the height of a line in the LineList list box
 */
void LineList_SetLineHeight(LPLINELIST lpLL,int nIndex,int nHeightInHimetric)
{
    LPARAM			lParam;
	LPOUTLINEDOC	lpDoc;
	LPSCALEFACTOR	lpscale;
    UINT			uHeightInPix;
	LPHEADING		lphead;
	
	if (!lpLL) 
		return;

	lpDoc = lpLL->m_lpDoc;
	lphead = OutlineDoc_GetHeading(lpDoc);
	lpscale = OutlineDoc_GetScaleFactor(lpDoc);
	
	uHeightInPix = XformHeightInHimetricToPixels(NULL, nHeightInHimetric);
	
	Heading_RH_SendMessage(lphead, LB_SETITEMDATA, (WPARAM)nIndex, 
			MAKELPARAM(uHeightInPix, 0));
			
	uHeightInPix = (UINT)(uHeightInPix * lpscale->dwSyN / lpscale->dwSyD);
			
	if (uHeightInPix > LISTBOX_HEIGHT_LIMIT)
		uHeightInPix = LISTBOX_HEIGHT_LIMIT;


    lParam = MAKELPARAM(uHeightInPix, 0);
    SendMessage(lpLL->m_hWndListBox,LB_SETITEMHEIGHT,(WPARAM)nIndex, lParam);
	Heading_RH_SendMessage(lphead, LB_SETITEMHEIGHT, (WPARAM)nIndex, lParam);
	Heading_RH_ForceRedraw(lphead, TRUE);
}


/* LineList_ReScale
 * ----------------
 *
 *      Re-scale the LineList list box
 */
void LineList_ReScale(LPLINELIST lpLL, LPSCALEFACTOR lpscale)
{
	int nIndex;
	LPLINE lpLine;
	UINT uWidthInHim;
	
	if (!lpLL)
		return;

	for (nIndex = 0; nIndex < lpLL->m_nNumLines; nIndex++) {
		lpLine = LineList_GetLine(lpLL, nIndex);
		LineList_SetLineHeight(
				lpLL, 
				nIndex, 
				Line_GetHeightInHimetric(lpLine)
		);
	}

	uWidthInHim = LineList_GetMaxLineWidthInHimetric(lpLL);
	LineList_SetMaxLineWidthInHimetric(lpLL, -(int)uWidthInHim);
}

/* LineList_SetSel
 * ---------------
 *
 *      Set the selection in list box
 */
void LineList_SetSel(LPLINELIST lpLL, LPLINERANGE lplrSel)
{
    DWORD dwSel;
    
    if (lpLL->m_nNumLines <= 0 || lplrSel->m_nStartLine < 0) 
        return;     // no lines in list; can't set a selection
    
    dwSel = MAKELPARAM(lplrSel->m_nStartLine, lplrSel->m_nEndLine);

    lpLL->m_lrSaveSel = *lplrSel;

    /* remove previous selection */
#if defined( WIN32 )
    SendMessage(
            lpLL->m_hWndListBox, 
            LB_SETSEL,
            (WPARAM)FALSE,
            (LPARAM)-1
    );
#else 
    SendMessage(
            lpLL->m_hWndListBox, 
            LB_SETSEL,
            (WPARAM)FALSE,
            MAKELPARAM(-1,0)
    );
#endif

    /* mark selection */
    SendMessage(lpLL->m_hWndListBox,LB_SELITEMRANGE, (WPARAM)TRUE, (LPARAM)dwSel);
    /* set focus line (caret) */
    LineList_SetFocusLine ( lpLL, (WORD)lplrSel->m_nStartLine );
    
}


/* LineList_GetSel
 * ---------------
 *
 * Get the selection in list box.
 *
 * Returns the count of items selected
 */
int LineList_GetSel(LPLINELIST lpLL, LPLINERANGE lplrSel)
{
    int nNumSel=(int)SendMessage(lpLL->m_hWndListBox,LB_GETSELCOUNT,0,0L);
    
    if (nNumSel) {
        SendMessage(lpLL->m_hWndListBox,LB_GETSELITEMS,
            (WPARAM)1,(LPARAM)(int FAR*)&(lplrSel->m_nStartLine));
        lplrSel->m_nEndLine = lplrSel->m_nStartLine + nNumSel - 1;
    } else {
        _fmemset(lplrSel, 0, sizeof(LINERANGE));
    }
    return nNumSel;
}


/* LineList_RemoveSel
 * ------------------
 *
 * Remove the selection in list box but save the selection state so that
 * it can be restored by calling LineList_RestoreSel
 * LineList_RemoveSel is called when the LineList window looses focus.
 */
void LineList_RemoveSel(LPLINELIST lpLL)
{
    LINERANGE lrSel;
    if (LineList_GetSel(lpLL, &lrSel) > 0) {
        lpLL->m_lrSaveSel = lrSel;
#if defined( WIN32 )
        SendMessage(
                lpLL->m_hWndListBox, 
                LB_SETSEL,
                (WPARAM)FALSE,
                (LPARAM)-1
        );
#else 
        SendMessage(
                lpLL->m_hWndListBox, 
                LB_SETSEL,
                (WPARAM)FALSE,
                MAKELPARAM(-1,0)
        );
#endif
    }
}


/* LineList_RestoreSel
 * ------------------
 *
 * Restore the selection in list box that was previously saved by a call to 
 * LineList_RemoveSel.
 * LineList_RestoreSel is called when the LineList window gains focus.
 */
void LineList_RestoreSel(LPLINELIST lpLL)
{
    LineList_SetSel(lpLL, &lpLL->m_lrSaveSel);
}


/* LineList_SetRedraw
 * ------------------
 *
 *      Enable/Disable the redraw of the linelist (listbox) on screen
 *
 *  fEnbaleDraw = TRUE      - enable redraw
 *                FALSE     - disable redraw
 */
void LineList_SetRedraw(LPLINELIST lpLL, BOOL fEnableDraw)
{
    SendMessage(lpLL->m_hWndListBox,WM_SETREDRAW,(WPARAM)fEnableDraw,0L);
}


/* LineList_ForceRedraw
 * --------------------
 *
 *      Force redraw of the linelist (listbox) on screen
 */
void LineList_ForceRedraw(LPLINELIST lpLL, BOOL fErase)
{
    InvalidateRect(lpLL->m_hWndListBox, NULL, fErase);
}


/* LineList_ForceLineRedraw
 * ------------------------
 *
 *      Force a particular line of the linelist (listbox) to redraw.
 */
void LineList_ForceLineRedraw(LPLINELIST lpLL, int nIndex, BOOL fErase)
{
    RECT   rect;

    LineList_GetLineRect( lpLL, nIndex, (LPRECT)&rect );
    InvalidateRect( lpLL->m_hWndListBox, (LPRECT)&rect, fErase );
}


/* LineList_ScrollLineIntoView
 * ---------------------------
 *  Make sure that the specified line is in view; if necessary scroll 
 *      the listbox. if any portion of the line is visible, then no 
 *      scrolling will occur.
 */
void LineList_ScrollLineIntoView(LPLINELIST lpLL, int nIndex)
{
    RECT rcWindow;
    RECT rcLine;
    RECT rcInt;

    if ( lpLL->m_nNumLines == 0 )
        return;

    if (! LineList_GetLineRect( lpLL, nIndex, (LPRECT)&rcLine ) )
        return;

    GetClientRect( lpLL->m_hWndListBox, (LPRECT) &rcWindow ); 

    if (! IntersectRect((LPRECT)&rcInt, (LPRECT)&rcWindow, (LPRECT)&rcLine)) 
        SendMessage( 
                lpLL->m_hWndListBox, 
                LB_SETTOPINDEX, 
                (WPARAM)nIndex, 
                (LPARAM)NULL
        );
}


/* LineList_CopySelToDoc
 * ---------------------
 *
 *      Copy the selection of the linelist to another document
 *
 *  RETURNS: number of lines copied.
 */
int LineList_CopySelToDoc(
        LPLINELIST              lpSrcLL, 
        LPLINERANGE             lplrSel, 
        LPOUTLINEDOC            lpDestDoc
)
{
    int             nEndLine;
    int             nStartLine;
    LPLINELIST      lpDestLL = &lpDestDoc->m_LineList;
    signed short    nDestIndex = LineList_GetFocusLineIndex(lpDestLL);
    LPLINE          lpSrcLine;
    int             nCopied = 0;
    int             i;

    if (lplrSel) {
        nEndLine = lplrSel->m_nEndLine;
        nStartLine = lplrSel->m_nStartLine;
    } else {
        nEndLine = LineList_GetCount(lpSrcLL) - 1;
        nStartLine = 0;
    }

    for(i = nStartLine; i <= nEndLine; i++) {
        lpSrcLine = LineList_GetLine(lpSrcLL, i);
        if (lpSrcLine && Line_CopyToDoc(lpSrcLine, lpDestDoc, nDestIndex)) {
            nDestIndex++;
            nCopied++;
        }
    }

    return nCopied;
}


/* LineList_SaveSelToStg
 * ---------------------
 *
 *      Save lines in selection into lpDestStg.
 *
 *      Return TRUE if ok, FALSE if error
 */
BOOL LineList_SaveSelToStg(
        LPLINELIST              lpLL, 
        LPLINERANGE             lplrSel, 
        UINT                    uFormat, 
        LPSTORAGE               lpSrcStg, 
        LPSTORAGE               lpDestStg, 
        LPSTREAM                lpLLStm, 
        BOOL                    fRemember
)
{
    int nEndLine;
    int nStartLine;
    int nNumLinesWritten = 0;
    HRESULT hrErr = NOERROR;
    ULONG nWritten;
    LPLINE lpLine;
    LINELISTHEADER llhRecord;
    int i;
    LARGE_INTEGER dlibSaveHeaderPos;
    LARGE_INTEGER dlibZeroOffset;
    LISet32( dlibZeroOffset, 0 );

    if (lplrSel) {
        nEndLine = lplrSel->m_nEndLine;
        nStartLine = lplrSel->m_nStartLine;
    } else {
        nEndLine = LineList_GetCount(lpLL) - 1;
        nStartLine = 0;
    }

    _fmemset((LPLINELISTHEADER)&llhRecord,0,sizeof(LINELISTHEADER));

    /* save seek position for LineList header record */
    hrErr = lpLLStm->lpVtbl->Seek(
            lpLLStm,
            dlibZeroOffset,
            STREAM_SEEK_CUR,
            (ULARGE_INTEGER FAR*)&dlibSaveHeaderPos
    );
    if (hrErr != NOERROR) goto error;

    /* write LineList header record */
    hrErr = lpLLStm->lpVtbl->Write(
            lpLLStm,
            (LPVOID)&llhRecord,
            sizeof(LINELISTHEADER),
            &nWritten
        );
    if (hrErr != NOERROR) goto error;

    for(i = nStartLine; i <= nEndLine; i++) {
        lpLine = LineList_GetLine(lpLL, i);
        if(Line_SaveToStg(lpLine, uFormat, lpSrcStg, lpDestStg, lpLLStm,
                                                                fRemember))
            llhRecord.m_nNumLines++;
    }

    /* retore seek position for LineList header record */
    hrErr = lpLLStm->lpVtbl->Seek(
            lpLLStm,
            dlibSaveHeaderPos,
            STREAM_SEEK_SET,
            NULL
    );
    if (hrErr != NOERROR) goto error;

    /* write LineList header record */
    hrErr = lpLLStm->lpVtbl->Write(
            lpLLStm,
            (LPVOID)&llhRecord,
            sizeof(LINELISTHEADER),
            &nWritten
    );
    if (hrErr != NOERROR) goto error;

    /* reset seek position to end of stream */
    hrErr = lpLLStm->lpVtbl->Seek(
            lpLLStm,
            dlibZeroOffset,
            STREAM_SEEK_END,
            NULL
    );
    if (hrErr != NOERROR) goto error;

    return TRUE;
    
error:
    OleDbgAssertSz(
            hrErr == NOERROR, 
            "Could not write LineList header to LineList stream"
    );
    return FALSE;
}


/* LineList_LoadFromStg
 * --------------------
 *
 *      Load lines into linelist from storage.
 *
 *      Return TRUE if ok, FALSE if error
 */
BOOL LineList_LoadFromStg(
        LPLINELIST              lpLL, 
        LPSTORAGE               lpSrcStg, 
        LPSTREAM                lpLLStm
)
{
    HRESULT hrErr;
    ULONG nRead;
    LPLINE lpLine;
    int i;
    int nNumLines;
    LINELISTHEADER llineRecord;

    /* write LineList header record */
    hrErr = lpLLStm->lpVtbl->Read(
            lpLLStm,
            (LPVOID)&llineRecord,
            sizeof(LINELISTHEADER),
            &nRead
    );

    if (! OleDbgVerifySz(hrErr == NOERROR, 
                    "Could not read LineList header from LineList stream")) 
        goto error;

    nNumLines = llineRecord.m_nNumLines;
    
    for(i = 0; i < nNumLines; i++) {
        lpLine = Line_LoadFromStg(lpSrcStg, lpLLStm, lpLL->m_lpDoc);
        if (! lpLine)
            goto error;

        // Directly add lines to LineList without trying to update a NameTbl
        LineList_AddLine(lpLL, lpLine, i-1);
    }

    return TRUE;
    
error:
    // Delete any Line objects that were created
    if (lpLL->m_nNumLines > 0) {
        int nNumLines = lpLL->m_nNumLines;
        for (i = 0; i < nNumLines; i++) 
            LineList_DeleteLine(lpLL, i);
    }

    return FALSE;
}


#if defined( USE_DRAGDROP )


/* LineList_SetFocusLineFromPointl
 * -------------------------------
 *
 */
 
void LineList_SetFocusLineFromPointl( LPLINELIST lpLL, POINTL pointl )
{
    int i = LineList_GetLineIndexFromPointl( lpLL, pointl );

    if ( i == (int)-1)
        return ;
    else 
        LineList_SetFocusLine( lpLL, (WORD)i );
}


/* LineList_SetDragOverLineFromPointl
 * ----------------------------------
 *
 */
 
void LineList_SetDragOverLineFromPointl ( LPLINELIST lpLL, POINTL pointl )
{
    int    nIndex = LineList_GetLineIndexFromPointl( lpLL, pointl );
    LPLINE lpline = LineList_GetLine( lpLL, nIndex );

    if (!lpline)
        return;
    
    if (! lpline->m_fDragOverLine) {
        /* user has dragged over a new line. force new drop target line
        **    to repaint so that drop feedback will be drawn.
        */
        lpline->m_fDragOverLine = TRUE;
        LineList_ForceLineRedraw( lpLL, nIndex, TRUE );

        if (lpLL->m_iDragOverLine!= -1 && lpLL->m_iDragOverLine!=nIndex) {

            /* force previous drop target line to repaint so that drop
            **    feedback will be undrawn
            */
            lpline = LineList_GetLine( lpLL, lpLL->m_iDragOverLine );
            if (lpline)
                lpline->m_fDragOverLine = FALSE;

            LineList_ForceLineRedraw( lpLL, lpLL->m_iDragOverLine, TRUE );
        }     
        
        lpLL->m_iDragOverLine = nIndex;
        
        // Force repaint immediately
        UpdateWindow(lpLL->m_hWndListBox);
    }
}


/* LineList_Scroll
 * ---------------
 *
 * Scroll the LineList list box in the desired direction by one line.
 *
 *      this function is called during a drag operation. 
 */
 
void LineList_Scroll(LPLINELIST lpLL, DWORD dwScrollDir)
{
	switch (dwScrollDir) {
		case SCROLLDIR_UP:
            SendMessage( lpLL->m_hWndListBox, WM_VSCROLL, SB_LINEUP, 0L );
			break;

		case SCROLLDIR_DOWN:
            SendMessage( lpLL->m_hWndListBox, WM_VSCROLL, SB_LINEDOWN, 0L );
			break;
	}
}


/* LineList_GetLineIndexFromPointl
 * -------------------------------
 *   do hit test to get index of line corresponding to pointl
 */
int LineList_GetLineIndexFromPointl(LPLINELIST lpLL, POINTL pointl)
{
    RECT  rect;
    POINT point;
    DWORD i;

    point.x = (int)pointl.x;
    point.y = (int)pointl.y;

    ScreenToClient( lpLL->m_hWndListBox, &point);	
    
    if ( lpLL->m_nNumLines == 0 )
        return -1;

    GetClientRect( lpLL->m_hWndListBox, (LPRECT) &rect ); 	

    i = SendMessage( lpLL->m_hWndListBox, LB_GETTOPINDEX, (WPARAM)NULL, (LPARAM)NULL );
    
    for ( ;; i++){
       
        RECT rectItem;

        if (!LineList_GetLineRect( lpLL, (int)i, (LPRECT)&rectItem ) )
            return -1;
         
        if ( rectItem.top > rect.bottom )
            return -1;

        if ( rectItem.top <= point.y && point.y <= rectItem.bottom)
            return (int)i;
       
    }
     
}


/* LineList_RestoreDragFeedback
 * ----------------------------
 *
 * Retore the index of the line that currently has focus (the active line).
 */
void LineList_RestoreDragFeedback(LPLINELIST lpLL)
{
    LPLINE lpLine;
    
    if (lpLL->m_iDragOverLine < 0 )
       return;
    
    lpLine = LineList_GetLine( lpLL, lpLL->m_iDragOverLine);
    
    if (lpLine) {
       
        lpLine->m_fDragOverLine = FALSE;
        LineList_ForceLineRedraw( lpLL, lpLL->m_iDragOverLine, TRUE );
        
        // Force repaint immediately
        UpdateWindow(lpLL->m_hWndListBox);
    }
 
    lpLL->m_iDragOverLine = -1;
    
}

#endif  

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.