OUTLNTBL.C

/************************************************************************* 
**
** OLE 2 Sample Code
**
** outlntbl.c
**
** This file contains OutlineNameTable functions.
**
** (c) Copyright Microsoft Corp. 1992 - 1997 All Rights Reserved
**
*************************************************************************/


#include "outline.h"

OLEDBGDATA

extern LPOUTLINEAPP g_lpApp;

OLECHAR ErrMsgNameTable[] = OLESTR("Can't create NameTable!");


/* OutlineNameTable_Init
* ---------------------
*
* initialize a name table.
*/
BOOL OutlineNameTable_Init(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINEDOC lpOutlineDoc)
{
HWND lpParent = OutlineDoc_GetWindow(lpOutlineDoc);

lpOutlineNameTable->m_nCount = 0;

/* We will use an OwnerDraw listbox as our data structure to
** maintain the table of Names. this listbox will never be made
** visible. the listbox is just a convenient data structure to
** manage a collection.
*/
lpOutlineNameTable->m_hWndListBox = CreateWindow(
"listbox", /* Window class name */
NULL, /* Window's title */
WS_CHILDWINDOW |
LBS_OWNERDRAWFIXED,
0, 0, /* Use default X, Y */
0, 0, /* Use default X, Y */
lpParent, /* Parent window's handle */
(HMENU)IDC_NAMETABLE, /* Child Window ID */
g_lpApp->m_hInst, /* Instance of window */
NULL); /* Create struct for WM_CREATE */

if (! lpOutlineNameTable->m_hWndListBox) {
OutlineApp_ErrorMessage(g_lpApp, ErrMsgNameTable);
return FALSE;
}

return TRUE;
}


/* OutlineNameTable_Destroy
* ------------------------
*
* Free memory used by the name table.
*/
void OutlineNameTable_Destroy(LPOUTLINENAMETABLE lpOutlineNameTable)
{
// Delete all names
OutlineNameTable_ClearAll(lpOutlineNameTable);

DestroyWindow(lpOutlineNameTable->m_hWndListBox);
Delete(lpOutlineNameTable);
}


/* OutlineNameTable_AddName
* ------------------------
*
* Add a name to the table
*/
void OutlineNameTable_AddName(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINENAME lpOutlineName)
{
SendMessage(
lpOutlineNameTable->m_hWndListBox,
LB_ADDSTRING,
0,
(DWORD)lpOutlineName
);
lpOutlineNameTable->m_nCount++;
}


/* OutlineNameTable_DeleteName
* ---------------------------
*
* Delete a name from table
*/
void OutlineNameTable_DeleteName(LPOUTLINENAMETABLE lpOutlineNameTable,int nIndex)
{
LPOUTLINENAME lpOutlineName = OutlineNameTable_GetName(lpOutlineNameTable, nIndex);

#if defined( OLE_SERVER )
/* NOTE: if there is a pseudo object attached to this name, it
** must first be closed before deleting the Name. this will
** cause OnClose notification to be sent to all linking clients.
*/
ServerName_ClosePseudoObj((LPSERVERNAME)lpOutlineName);
#endif

if (lpOutlineName)
Delete(lpOutlineName); // free memory for name

SendMessage(
lpOutlineNameTable->m_hWndListBox,
LB_DELETESTRING,
(WPARAM)nIndex,
0L
);
lpOutlineNameTable->m_nCount--;
}


/* OutlineNameTable_GetNameIndex
* -----------------------------
*
* Return the index of the Name given a pointer to the Name.
* Return -1 if the Name is not found.
*/
int OutlineNameTable_GetNameIndex(LPOUTLINENAMETABLE lpOutlineNameTable, LPOUTLINENAME lpOutlineName)
{
LRESULT lReturn;

if (! lpOutlineName) return -1;

lReturn = SendMessage(
lpOutlineNameTable->m_hWndListBox,
LB_FINDSTRING,
(WPARAM)-1,
(LPARAM)(LPCSTR)lpOutlineName
);

return ((lReturn == LB_ERR) ? -1 : (int)lReturn);
}


/* OutlineNameTable_GetName
* ------------------------
*
* Retrieve the pointer to the Name given its index in the NameTable
*/
LPOUTLINENAME OutlineNameTable_GetName(LPOUTLINENAMETABLE lpOutlineNameTable, int nIndex)
{
LPOUTLINENAME lpOutlineName = NULL;
LRESULT lResult;

if (lpOutlineNameTable->m_nCount == 0 ||
nIndex > lpOutlineNameTable->m_nCount ||
nIndex < 0) {
return NULL;
}

lResult = SendMessage(
lpOutlineNameTable->m_hWndListBox,
LB_GETTEXT,
nIndex,
(LPARAM)(LPCSTR)&lpOutlineName
);
OleDbgAssert(lResult != LB_ERR);
return lpOutlineName;
}


/* OutlineNameTable_FindName
* -------------------------
*
* Find a name in the name table given a string.
*/
LPOUTLINENAME OutlineNameTable_FindName(LPOUTLINENAMETABLE lpOutlineNameTable, LPOLESTR lpszName)
{
LPOUTLINENAME lpOutlineName;
BOOL fFound = FALSE;
int i;

for (i = 0; i < lpOutlineNameTable->m_nCount; i++) {
lpOutlineName = OutlineNameTable_GetName(lpOutlineNameTable, i);
if (OLESTRCMP(lpOutlineName->m_szName, lpszName) == 0) {
fFound = TRUE;
break; // FOUND MATCH!
}
}

return (fFound ? lpOutlineName : NULL);
}


/* OutlineNameTable_FindNamedRange
* -------------------------------
*
* Find a name in the name table which matches a given line range.
*/
LPOUTLINENAME OutlineNameTable_FindNamedRange(LPOUTLINENAMETABLE lpOutlineNameTable, LPLINERANGE lplrSel)
{
LPOUTLINENAME lpOutlineName;
BOOL fFound = FALSE;
int i;

for (i = 0; i < lpOutlineNameTable->m_nCount; i++) {
lpOutlineName = OutlineNameTable_GetName(lpOutlineNameTable, i);
if ((lpOutlineName->m_nStartLine == lplrSel->m_nStartLine) &&
(lpOutlineName->m_nEndLine == lplrSel->m_nEndLine) ) {
fFound = TRUE;
break; // FOUND MATCH!
}
}

return (fFound ? lpOutlineName : NULL);
}


/* OutlineNameTable_GetCount
* -------------------------
*
* Return number of names in nametable
*/
int OutlineNameTable_GetCount(LPOUTLINENAMETABLE lpOutlineNameTable)
{
if (!lpOutlineNameTable)
return 0;

return lpOutlineNameTable->m_nCount;
}


/* OutlineNameTable_ClearAll
* -------------------------
*
* Remove all names from table
*/
void OutlineNameTable_ClearAll(LPOUTLINENAMETABLE lpOutlineNameTable)
{
LPOUTLINENAME lpOutlineName;
int i;
int nCount = lpOutlineNameTable->m_nCount;

for (i = 0; i < nCount; i++) {
lpOutlineName = OutlineNameTable_GetName(lpOutlineNameTable, i);
Delete(lpOutlineName); // free memory for name
}

lpOutlineNameTable->m_nCount = 0;
SendMessage(lpOutlineNameTable->m_hWndListBox,LB_RESETCONTENT,0,0L);
}


/* OutlineNameTable_AddLineUpdate
* ------------------------------
*
* Update table when a new line is added at nAddIndex
* The line used to be at nAddIndex is pushed down
*/
void OutlineNameTable_AddLineUpdate(LPOUTLINENAMETABLE lpOutlineNameTable, int nAddIndex)
{
LPOUTLINENAME lpOutlineName;
LINERANGE lrSel;
int i;
BOOL fRangeModified = FALSE;

for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
OutlineName_GetSel(lpOutlineName, &lrSel);

if((int)lrSel.m_nStartLine > nAddIndex) {
lrSel.m_nStartLine++;
fRangeModified = !fRangeModified;
}
if((int)lrSel.m_nEndLine > nAddIndex) {
lrSel.m_nEndLine++;
fRangeModified = !fRangeModified;
}

OutlineName_SetSel(lpOutlineName, &lrSel, fRangeModified);
}
}


/* OutlineNameTable_DeleteLineUpdate
* ---------------------------------
*
* Update the table when a line at nDeleteIndex is removed
*/
void OutlineNameTable_DeleteLineUpdate(LPOUTLINENAMETABLE lpOutlineNameTable, int nDeleteIndex)
{
LPOUTLINENAME lpOutlineName;
LINERANGE lrSel;
int i;
BOOL fRangeModified = FALSE;

for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
OutlineName_GetSel(lpOutlineName, &lrSel);

if((int)lrSel.m_nStartLine > nDeleteIndex) {
lrSel.m_nStartLine--;
fRangeModified = !fRangeModified;
}
if((int)lrSel.m_nEndLine >= nDeleteIndex) {
lrSel.m_nEndLine--;
fRangeModified = !fRangeModified;
}

// delete the name if its entire range is deleted
if(lrSel.m_nStartLine > lrSel.m_nEndLine) {
OutlineNameTable_DeleteName(lpOutlineNameTable, i);
i--; // re-examine this name
} else {
OutlineName_SetSel(lpOutlineName, &lrSel, fRangeModified);
}
}
}


/* OutlineNameTable_SaveSelToStg
* -----------------------------
*
* Save only the names that refer to lines completely contained in the
* specified selection range.
*/
BOOL OutlineNameTable_SaveSelToStg(
LPOUTLINENAMETABLE lpOutlineNameTable,
LPLINERANGE lplrSel,
UINT uFormat,
LPSTREAM lpNTStm
)
{
HRESULT hrErr;
ULONG nWritten;
LPOUTLINENAME lpOutlineName;
short nNameCount = 0;
BOOL fNameSaved;
BOOL fStatus;
int i;
LARGE_INTEGER dlibZeroOffset;
LISet32( dlibZeroOffset, 0 );

/* initially write 0 for count of names. the correct count will be
** written at the end when we know how many names qualified to
** be written (within the selection).
*/
hrErr = lpNTStm->lpVtbl->Write(
lpNTStm,
(short FAR*)&nNameCount,
sizeof(nNameCount),
&nWritten
);
if (hrErr != NOERROR) {
OleDbgOutHResult("Write NameTable header returned", hrErr);
goto error;
}

for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
fStatus = OutlineName_SaveToStg(
lpOutlineName,
lplrSel,
uFormat,
lpNTStm,
(BOOL FAR*)&fNameSaved
);
if (! fStatus) goto error;
if (fNameSaved) nNameCount++;
}

/* write the final count of names written. */
hrErr = lpNTStm->lpVtbl->Seek(
lpNTStm,
dlibZeroOffset,
STREAM_SEEK_SET,
NULL
);
if (hrErr != NOERROR) {
OleDbgOutHResult("Seek to NameTable header returned", hrErr);
goto error;
}

hrErr = lpNTStm->lpVtbl->Write(
lpNTStm,
(short FAR*)&nNameCount,
sizeof(nNameCount),
&nWritten
);
if (hrErr != NOERROR) {
OleDbgOutHResult("Write NameTable count in header returned", hrErr);
goto error;
}

OleStdRelease((LPUNKNOWN)lpNTStm);
return TRUE;

error:
if (lpNTStm)
OleStdRelease((LPUNKNOWN)lpNTStm);

return FALSE;
}


/* OutlineNameTable_LoadFromStg
* ----------------------------
*
* Load Name Table from file
*
* Return TRUE if ok, FALSE if error
*/
BOOL OutlineNameTable_LoadFromStg(LPOUTLINENAMETABLE lpOutlineNameTable, LPSTORAGE lpSrcStg)
{
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
HRESULT hrErr;
IStream FAR* lpNTStm;
ULONG nRead;
short nCount;
LPOUTLINENAME lpOutlineName;
BOOL fStatus;
short i;

hrErr = lpSrcStg->lpVtbl->OpenStream(
lpSrcStg,
OLESTR("NameTable"),
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&lpNTStm
);
if (hrErr != NOERROR) {
OleDbgOutHResult("OpenStream NameTable returned", hrErr);
goto error;
}

hrErr = lpNTStm->lpVtbl->Read(lpNTStm,&nCount,sizeof(nCount),&nRead);
if (hrErr != NOERROR) {
OleDbgOutHResult("Read NameTable header returned", hrErr);
goto error;
}

for (i = 0; i < nCount; i++) {
lpOutlineName = OutlineApp_CreateName(lpOutlineApp);
if (! lpOutlineName) goto error;
fStatus = OutlineName_LoadFromStg(lpOutlineName, lpNTStm);
if (! fStatus) goto error;
OutlineNameTable_AddName(lpOutlineNameTable, lpOutlineName);
}

OleStdRelease((LPUNKNOWN)lpNTStm);
return TRUE;

error:
if (lpNTStm)
OleStdRelease((LPUNKNOWN)lpNTStm);

return FALSE;
}