You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1183 lines
28 KiB
1183 lines
28 KiB
/*************************************************************************
|
|
**
|
|
** 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
|