gecko-dev/cmd/winfe/medit.cpp

827 строки
22 KiB
C++
Executable File

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
// medit.cpp : implementation file
//
#include "stdafx.h"
#include "medit.h"
#include "fmabstra.h"
#include "libevent.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define EDIT_ID 25000
BEGIN_MESSAGE_MAP(CNetscapeEdit, CGenericEdit)
//{{AFX_MSG_MAP(CNetscapeEdit)
ON_WM_CHAR()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_WM_GETDLGCODE()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
IMPLEMENT_DYNAMIC(CNetscapeEdit, CGenericEdit)
#ifndef _AFXDLL
#define new DEBUG_NEW // MSVC Debugging new...goes to regular new in release mode
#endif
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
CNetscapeEdit::CNetscapeEdit()
{
m_Context = NULL;
m_Form = NULL;
m_Submit = FALSE;
m_callBase = FALSE;
#ifdef DEBUG
m_bOnCreateCalled = FALSE;
#endif
}
int CNetscapeEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
#ifdef DEBUG
m_bOnCreateCalled = TRUE;
#endif
if (CGenericEdit::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
//
// Make sure we have a valid context
// We might nto be in a form so don't barf if we don't have a form
//
BOOL CNetscapeEdit::SetContext(MWContext * context, LO_FormElementStruct * form)
{
if(!context)
return(FALSE);
m_Context = context;
m_Form = form;
return(TRUE);
}
LO_FormElementStruct *CNetscapeEdit::GetFormElement()
{
return(m_Form);
}
UINT CNetscapeEdit::OnGetDlgCode()
{
return CEdit::OnGetDlgCode() | DLGC_WANTARROWS | DLGC_WANTALLKEYS;
}
#ifdef XP_WIN16
//
// The creator of this form element should have created a segment for
// us to live in before we got here. Tell Windows to use that
// segment rather than the application's so that we don't run out of
// DGROUP space
//
BOOL CNetscapeEdit::PreCreateWindow( CREATESTRUCT& cs )
{
ASSERT(m_hInstance);
if(!m_hInstance)
return(TRUE);
cs.hInstance = m_hInstance;
return(TRUE);
}
#endif
//
// Called when the 'submit' event has been processed
//
static void
edit_submit_closure(MWContext * pContext, LO_Element * pEle, int32 event,
void * pObj, ETEventStatus status)
{
if(status != EVENT_OK || !pEle || !pContext)
return;
FE_SubmitInputElement(pContext, pEle);
}
//
// If the user has hit return load the url
// Otherwise pass the key on to the base library
//
void CNetscapeEdit::OnChar(UINT nChar, UINT nCnt, UINT nFlags)
{
BOOL bJsWantsEvent = m_Form->event_handler_present ||
LM_EventCaptureCheck(m_Context, EVENT_KEYDOWN | EVENT_KEYUP | EVENT_KEYPRESS);
// Check if we generated this event. If so, the base. If not, call JS
if (m_callBase || !bJsWantsEvent) {
if(nChar == '\r') { // the user hit return
#ifdef DEBUG
if(!m_bOnCreateCalled) {
TRACE("Bug 88020 still present\n");
#if defined (DEBUG_blythe) || defined(DEBUG_ftang) || defined(DEBUG_bstell) || defined(DEBUG_nhotta) || defined(DEBUG_jliu)
ASSERT(0);
#endif
}
#endif
if(m_Submit) { // if we are the only element, return == submit
// if the text is different throw out the old text and add the
// new text into the layout structure
UpdateAndCheckForChange();
// we are about to submit so tell libmocha about it first
// do the submit in our closure if libmocha says its OK
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_SUBMIT;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *)m_Form, event,
edit_submit_closure, this);
return;
}
else {
// we aren't auto-submitting, but the user still hit return
// they prolly mean that we should check to see if we should
// send a change event
if(!(GetStyle() & ES_MULTILINE))
UpdateAndCheckForChange();
}
} // wasn't the return key
//#ifdef NO_TAB_NAVIGATION
/*
// let the CGenericView to handle the Tab, to step through Form elements
// and links, even links inside a form.
if(nChar == VK_TAB) {
// if the high order bit is set (i.e. its negative) the shift
// key is being held down
BOOL bShift = GetKeyState(VK_SHIFT) < 0 ? TRUE : FALSE;
// Determine our form element.
if(m_Context) {
CFormElement *pMe = CFormElement::GetFormElement(ABSTRACTCX(m_Context), m_Form);
if(pMe) {
// We're handling tabbing between form elements.
pMe->Tab(bShift);
return;
}
}
}
CEdit::OnChar(nChar, nCnt, nFlags);
*/
//#endif /* NO_TAB_NAVIGATION */
CEdit::OnChar(nChar, nCnt, nFlags);
//If m_callBase is set, this event is a callback from a JS event and
//we have to update the value of the edit field to reflect new values.
if (bJsWantsEvent) {
UpdateEditField();
}
return;
}
// Give the event to JS. They'll call the base when they get back.
//
// Grab key events for this layer's parent.
CL_GrabKeyEvents(m_Context->compositor, CL_GetLayerParent(m_Form->layer));
/*
* If there's a compositor and someone has keyboard focus.
* Note that if noone has event focus, we don't really need
* to dispatch the event.
*/
if (m_Context->compositor &&
!CL_IsKeyEventGrabber(m_Context->compositor, NULL)) {
CL_Event event;
fe_EventStruct fe_event;
fe_event.fe_modifiers = nCnt;
fe_event.nChar = nChar;
fe_event.uFlags = nFlags;
fe_event.x = 1;
event.type = CL_EVENT_KEY_DOWN;
event.which = nChar;
event.fe_event = (void *)&fe_event;
event.fe_event_size = sizeof(fe_EventStruct);
event.modifiers = (GetKeyState(VK_SHIFT) < 0 ? EVENT_SHIFT_MASK : 0)
| (GetKeyState(VK_CONTROL) < 0 ? EVENT_CONTROL_MASK : 0)
| (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0);
event.x = CL_GetLayerXOrigin(m_Form->layer);
event.y = CL_GetLayerYOrigin(m_Form->layer);
event.data = nFlags>>14 & 1;//Bit represeting key repetition
CL_DispatchEvent(m_Context->compositor, &event);
}
}
//
// We just got focus --- maybe libmocha cares
//
void CNetscapeEdit::OnSetFocus(CWnd * pWnd)
{
CEdit::OnSetFocus(pWnd);
if(m_Context && m_Form) {
// set tab_focus to this element
CWinCX *pWinCX = WINCX(m_Context);
// if ((LO_Element *)m_Form == pWinCX->getLastTabFocusElement())
// return;
pWinCX->setFormElementTabFocus( (LO_Element *)m_Form );
CL_GrabKeyEvents(m_Context->compositor, CL_GetLayerParent(m_Form->layer));
// send the event to libmocha --- do any further processing
// in our closure routine
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_FOCUS;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *)m_Form, event,
NULL, this);
}
}
lo_FormElementTextData *CNetscapeEdit::GetTextData() {
lo_FormElementTextData *pRetval = NULL;
if(m_Form && m_Form->element_data) {
switch(m_Form->element_data->type) {
case FORM_TYPE_READONLY:
break;
default:
pRetval = &(m_Form->element_data->ele_text);
break;
}
}
return(pRetval);
}
//
// We just lost focus --- maybe libmocha cares
//
// If the current value is different from the value that we have previously
// stored call SendOnChange() for this element before calling BlurElement();
//
void CNetscapeEdit::OnKillFocus(CWnd * pWnd)
{
// Call base class and be done with the message processing first
CEdit::OnKillFocus(pWnd);
// if the text is different throw out the old text and add the
// new text into the layout structure
UpdateAndCheckForChange();
// Send the blur message.
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_BLUR;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *) m_Form, event,
NULL, this);
}
void CNetscapeEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(m_Form->event_handler_present ||
LM_EventCaptureCheck(m_Context, EVENT_KEYDOWN | EVENT_KEYUP | EVENT_KEYPRESS)) {
UpdateEditField();
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CNetscapeEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
BOOL bJsWantsEvent = m_Form->event_handler_present ||
LM_EventCaptureCheck(m_Context, EVENT_KEYDOWN | EVENT_KEYUP | EVENT_KEYPRESS);
// Check if we generated this event. If so, the base. If not, call JS
if (m_callBase || !bJsWantsEvent) {
CEdit::OnKeyUp(nChar, nRepCnt, nFlags);
return;
}
// Don't continue if this context is destroyed.
if(!m_Context || ABSTRACTCX(m_Context)->IsDestroyed()) {
return;
}
// Grab key events for this layer's parent.
CL_GrabKeyEvents(m_Context->compositor, CL_GetLayerParent(m_Form->layer));
/*
* If there's a compositor and someone has keyboard focus.
* Note that if noone has event focus, we don't really need
* to dispatch the event.
*/
if (m_Context->compositor &&
!CL_IsKeyEventGrabber(m_Context->compositor, NULL)) {
CL_Event event;
fe_EventStruct fe_event;
BYTE kbstate[256];
WORD asciiChar = 0;
GetKeyboardState(kbstate);
#ifdef WIN32
ToAscii(nChar, nFlags & 0xff, kbstate, &asciiChar, 0);
#else
ToAscii(nChar, nFlags & 0xff, kbstate, (DWORD*)&asciiChar, 0);
#endif
fe_event.fe_modifiers = nRepCnt;
fe_event.nChar = nChar;
fe_event.uFlags = nFlags;
fe_event.x = 1;
event.type = CL_EVENT_KEY_UP;
event.fe_event = (void *)&fe_event;
event.fe_event_size = sizeof(fe_EventStruct);
event.which = asciiChar;
event.modifiers = (GetKeyState(VK_SHIFT) < 0 ? EVENT_SHIFT_MASK : 0)
| (GetKeyState(VK_CONTROL) < 0 ? EVENT_CONTROL_MASK : 0)
| (GetKeyState(VK_MENU) < 0 ? EVENT_ALT_MASK : 0);
event.x = CL_GetLayerXOrigin(m_Form->layer);
event.y = CL_GetLayerYOrigin(m_Form->layer);
CL_DispatchEvent(m_Context->compositor, &event);
}
}
// This function returns true if it has to update the value of the field
// and false if it does not.
XP_Bool CNetscapeEdit::UpdateEditField()
{
// find out what the current text is
CString csText;
GetWindowText(csText);
// if the text is different throw out the old text and add the
// new text into the layout structure
lo_FormElementTextData * textData = GetTextData();
if(!textData)
return FALSE;
//
// This if() statement has two parts. If there used to not be
// any text and there is some now we will send a change message
// Or, if there already was text but it was different we also
// want to send a change event
if((!textData->current_text && !csText.IsEmpty()) ||
(textData->current_text && csText != (char *) textData->current_text))
{
LO_UpdateTextData(textData, (const char *)csText);
return TRUE;
}
return FALSE;
}
//
// See if our value has changed since the last time we checked.
// If it has, send a change event to Mocha
//
void CNetscapeEdit::UpdateAndCheckForChange()
{
if(UpdateEditField())
{
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_CHANGE;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *) m_Form, event,
NULL, this);
}
}
void CNetscapeEdit::OnEditKeyEvent(CL_EventType type, UINT nChar, UINT nRepCnt, UINT nFlags) {
m_callBase = TRUE;
if (type == CL_EVENT_KEY_DOWN)
SendMessage(WM_CHAR, nChar, MAKELONG(nRepCnt, nFlags));
else if (type == CL_EVENT_KEY_UP)
SendMessage(WM_KEYUP, nChar, MAKELONG(nRepCnt, nFlags));
m_callBase = FALSE;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CMochaListBox, CListBox)
//{{AFX_MSG_MAP(CMochaListBox)
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_CHAR()
#if defined(MSVC4)
ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelChange)
#endif // MSVC4
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CMochaListBox::SetContext(MWContext * context, LO_FormElementStruct * form)
{
m_Context = context;
m_Form = form;
}
void CMochaListBox::OnSetFocus(CWnd * pWnd)
{
CListBox::OnSetFocus(pWnd);
// set tab_focus to this element
CWinCX *pWinCX = WINCX(m_Context);
// if ((LO_Element *)m_Form == pWinCX->getLastTabFocusElement())
// return;
pWinCX->setFormElementTabFocus( (LO_Element *)m_Form );
CL_GrabKeyEvents(m_Context->compositor, CL_GetLayerParent(m_Form->layer));
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_FOCUS;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *) m_Form, event,
NULL, this);
}
//
// If the current value is different from the value that we have previously
// stored call SendOnChange() for this element before calling BlurElement();
//
void CMochaListBox::CheckForChange()
{
// get the base form element
lo_FormElementSelectData * pSelectData = NULL;
pSelectData = (lo_FormElementSelectData *) m_Form->element_data;
if(!pSelectData)
return;
// get the option state
lo_FormElementOptionData * pOptionData = NULL;
pOptionData = (lo_FormElementOptionData *) pSelectData->options;
if(!pOptionData)
return;
BOOL bChanged = FALSE;
for(int i = 0; i < pSelectData->option_cnt; i++) {
int iIsSelected = GetSel(i);
// see if we have found a selection which is not the current
// selection
if(pOptionData[i].selected && (iIsSelected < 1)) {
pOptionData[i].selected = FALSE;
bChanged = TRUE;
}
// see if item #i has gone from being unselected to being selected
if(!pOptionData[i].selected && (iIsSelected > 0)) {
pOptionData[i].selected = TRUE;
bChanged = TRUE;
}
}
// only send change message if things have changed
if(bChanged) {
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_CHANGE;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *) m_Form, event,
NULL, this);
}
}
//
// We just lost focus --- maybe libmocha cares
//
void CMochaListBox::OnKillFocus(CWnd * pWnd)
{
// let MFC do its thing
CListBox::OnKillFocus(pWnd);
// see if we have changed and fire a change event if necessary
CheckForChange();
// we have lost focus so whether the value changed or not we
// should tell the mocha library
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_BLUR;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *) m_Form, event, NULL, this);
}
#if defined(MSVC4)
void CMochaListBox::OnSelChange()
{
// The OnKillFocus() handler takes care of leaving a control, but Mocha
// also wants to know about a selection change in a combobox or listbox.
CheckForChange();
}
#else
// In Win16 and MFC prior to 4.0, only the parent of a control could get
// notification messages.
BOOL CMochaListBox::OnChildNotify(UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if (nMsg == WM_COMMAND) {
if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) {
CheckForChange();
return TRUE;
}
}
return CListBox::OnChildNotify(nMsg, wParam, lParam, pResult);
}
#endif
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CMochaComboBox, CComboBox)
//{{AFX_MSG_MAP(CMochaComboBox)
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_CHAR()
#if defined(MSVC4)
ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelChange)
#endif // MSVC4
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CMochaComboBox::SetContext(MWContext * context, LO_FormElementStruct * form)
{
m_Context = context;
m_Form = form;
}
void CMochaComboBox::OnSetFocus(CWnd * pWnd)
{
CComboBox::OnSetFocus(pWnd);
// set tab_focus to this element
CWinCX *pWinCX = WINCX(m_Context);
// if ((LO_Element *)m_Form == pWinCX->getLastTabFocusElement())
// return;
pWinCX->setFormElementTabFocus( (LO_Element *)m_Form );
CL_GrabKeyEvents(m_Context->compositor, CL_GetLayerParent(m_Form->layer));
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_FOCUS;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *) m_Form, event, NULL, this);
}
//
// If the current value is different from the value that we have previously
// stored call SendOnChange() for this element before calling BlurElement();
//
void CMochaComboBox::CheckForChange()
{
// get the base form element
lo_FormElementSelectData * pSelectData = NULL;
pSelectData = (lo_FormElementSelectData *) m_Form->element_data;
if(!pSelectData)
return;
// get the option state
lo_FormElementOptionData * pOptionData = NULL;
pOptionData = (lo_FormElementOptionData *) pSelectData->options;
if(!pOptionData)
return;
// index of single selection
int iCurSelection = GetCurSel();
if(iCurSelection == LB_ERR)
return;
BOOL bChanged = FALSE;
for(int i = 0; i < pSelectData->option_cnt; i++) {
// see if we have found a selection which is not the current
// selection
if(pOptionData[i].selected && i != iCurSelection) {
pOptionData[i].selected = FALSE;
bChanged = TRUE;
}
// see if item #i has gone from being unselected to being selected
if(!pOptionData[i].selected && i == iCurSelection) {
pOptionData[i].selected = TRUE;
bChanged = TRUE;
}
}
// only send change message if things have changed
if(bChanged) {
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_CHANGE;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *) m_Form, event,
NULL, this);
}
}
//
// We just lost focus --- maybe libmocha cares
//
void CMochaComboBox::OnKillFocus(CWnd * pWnd)
{
CComboBox::OnKillFocus(pWnd);
CheckForChange();
// we have lost focus so whether the value changed or not we should tell the
// mocha library
JSEvent *event;
event = XP_NEW_ZAP(JSEvent);
event->type = EVENT_BLUR;
event->layer_id = m_Form->layer_id;
ET_SendEvent(m_Context, (LO_Element *) m_Form, event, NULL, this);
}
#if defined(MSVC4)
void CMochaComboBox::OnSelChange()
{
// The OnKillFocus() handler takes care of leaving a control, but Mocha
// also wants to know about a selection change in a combobox or listbox.
CheckForChange();
}
#else
// In Win16 and MFC prior to 4.0, only the parent of a control could get
// notification messages.
BOOL CMochaComboBox::OnChildNotify(UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if (nMsg == WM_COMMAND) {
if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) {
CheckForChange();
return TRUE;
}
}
return CComboBox::OnChildNotify(nMsg, wParam, lParam, pResult);
}
#endif // MSVC4
BOOL FirstCharMatch( char * searchFor, lo_FormElementSelectData *pSelectData, int oldSel, int *newSel )
{
char *pCurrent = NULL;
int ii;
if( searchFor == NULL )
return( FALSE);
// get the option state
lo_FormElementOptionData * pOptionData = NULL;
pOptionData = (lo_FormElementOptionData *) pSelectData->options;
if(!pOptionData)
return(FALSE);
// index of single selection
BOOL bChanged = FALSE;
ii = oldSel + 1; // start with current selection.
if( ii == pSelectData->option_cnt )
ii = 0; // fold back to the begining of the list.
while( ! bChanged && ii != oldSel ) {
pCurrent = (char *)pOptionData[ii].text_value;
if( pCurrent && (toupper(*pCurrent) == toupper(* searchFor)) ) { // todo multi byte
bChanged = TRUE;
*newSel = ii;
break; // ii is the index to select.
}
ii++;
if( ii == pSelectData->option_cnt )
ii = 0; // fold back to the begining of the list.
}
return( bChanged );
}
void CMochaComboBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CComboBox::OnChar(nChar, nRepCnt, nFlags); // call base class
// refer to void CFormSelectOne::CreateWidget() in fmdelone.cpp
// combo boxes are created with CBS_OWNERDRAWFIXED, for i18n support.
// First-char-searching in list doesn't work any more.
// Need to do it here.
int newSel;
char searchFor[2];
searchFor[0] = nChar;
searchFor[1] = '\0';
// get the base form element
lo_FormElementSelectData * pSelectData = NULL;
pSelectData = (lo_FormElementSelectData *) m_Form->element_data;
if(!pSelectData)
return;
int iCurSelection = GetCurSel();
if(iCurSelection == LB_ERR)
return;
BOOL changed = FirstCharMatch( searchFor, pSelectData, iCurSelection, &newSel );
if( changed )
CComboBox::SetCurSel( newSel );
}
void CMochaListBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CListBox::OnChar(nChar, nRepCnt, nFlags);
int newSel;
char searchFor[2];
searchFor[0] = nChar;
searchFor[1] = '\0';
// get the base form element
lo_FormElementSelectData * pSelectData = NULL;
pSelectData = (lo_FormElementSelectData *) m_Form->element_data;
if(!pSelectData)
return;
int iCurSelection = GetCurSel();
if(iCurSelection == LB_ERR)
return;
BOOL changed = FirstCharMatch( searchFor, pSelectData, iCurSelection, &newSel );
if( changed ) {
CListBox::SetSel( -1, FALSE ); // clear all selections.
CListBox::SetSel( newSel );
}
}