/************************************************************************* ** ** 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 */ /* 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_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 */ #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) GetWindowLongPtr ( lpLL->m_hWndListBox, GWLP_WNDPROC ); SetWindowLongPtr (lpLL->m_hWndListBox, GWLP_WNDPROC, (LONG_PTR) 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 lRet; if (! lpLine) return -1; lRet = SendMessage( lpLL->m_hWndListBox, LB_FINDSTRING, (WPARAM)-1, (LPARAM)(LPCSTR)lpLine ); return ((lRet == LB_ERR) ? -1 : (int)lRet); } /* LineList_GetLine * ---------------- * * Retrieve the pointer to the Line given its index in the LineList */ LPLINE LineList_GetLine(LPLINELIST lpLL, int nIndex) { DWORD dWord; LRESULT lRet; if (lpLL->m_nNumLines == 0 || nIndex > lpLL->m_nNumLines || nIndex < 0) return NULL; lRet = SendMessage( lpLL->m_hWndListBox,LB_GETTEXT,nIndex,(LPARAM)(LPCSTR)&dWord); return ((lRet == LB_ERR || lRet == 0) ? NULL : (LPLINE)dWord); } /* 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); if (lpLine) { 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); if (lpLine) { 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_ONDISK 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(&llhRecord,0,sizeof(llhRecord)); /* 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(llhRecord), &nWritten ); if (hrErr != NOERROR) { OleDbgOutHResult("Write LineList header returned", hrErr); goto error; } for(i = nStartLine; i <= nEndLine; i++) { lpLine = LineList_GetLine(lpLL, i); if(lpLine && 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(llhRecord), &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: #if defined( _DEBUG ) OleDbgAssertSz( hrErr == NOERROR, "Could not write LineList header to LineList stream" ); #endif 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_ONDISK llineRecord; /* write LineList header record */ hrErr = lpLLStm->lpVtbl->Read( lpLLStm, (LPVOID)&llineRecord, sizeof(llineRecord), &nRead ); if (hrErr != NOERROR) { OleDbgOutHResult("Read LineList header returned", hrErr); goto error; } nNumLines = (int) 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 /*fErase*/); 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 /*fErase*/); } 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 /*fErase*/); // Force repaint immediately UpdateWindow(lpLL->m_hWndListBox); } lpLL->m_iDragOverLine = -1; } #endif