-/*
+/* -*- Mode: C; tab-width: 4 -*-
+ *
* Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
* limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
-
- Change History (most recent first):
-
-$Log: SecondPage.cpp,v $
-Revision 1.10 2005/01/20 19:54:38 shersche
-Fix parse error when text record is NULL
-
-Revision 1.9 2005/01/06 08:13:50 shersche
-Don't use moreComing flag to determine number of text record, disregard queue name if qtotal isn't defined, don't disregard queue name if "rp" is the only key specified
-
-Revision 1.8 2005/01/04 21:09:14 shersche
-Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
-
-Revision 1.7 2004/12/31 07:25:27 shersche
-Tidy up printer management, and fix memory leaks when hitting 'Cancel'
-
-Revision 1.6 2004/12/30 01:24:02 shersche
-<rdar://problem/3906182> Remove references to description key
-Bug #: 3906182
-
-Revision 1.5 2004/12/30 01:02:47 shersche
-<rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
-Bug #: 3734478
-
-Revision 1.4 2004/12/29 18:53:38 shersche
-<rdar://problem/3725106>
-<rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
-Bug #: 3725106, 3737413
-
-Revision 1.3 2004/09/13 21:26:15 shersche
-<rdar://problem/3796483> Use the moreComing flag to determine whether drawing should take place in OnAddPrinter and OnRemovePrinter callbacks
-Bug #: 3796483
-
-Revision 1.2 2004/06/26 03:19:57 shersche
-clean up warning messages
-
-Submitted by: herscher
-
-Revision 1.1 2004/06/18 04:36:57 rpantos
-First checked in
-
-
-*/
+ */
#include "stdafx.h"
#include "PrinterSetupWizardApp.h"
// local variable is initialize but not referenced
#pragma warning(disable:4189)
-#define WM_SERVICE_EVENT ( WM_USER + 0x101 )
-
// CSecondPage dialog
IMPLEMENT_DYNAMIC(CSecondPage, CPropertyPage)
CSecondPage::CSecondPage()
- : CPropertyPage(CSecondPage::IDD),
- m_pdlBrowser( NULL ),
- m_lprBrowser( NULL ),
- m_ippBrowser( NULL ),
- m_selected( NULL )
+ : CPropertyPage(CSecondPage::IDD)
{
m_psp.dwFlags &= ~(PSP_HASHELP);
m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_BROWSE_TITLE);
m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_BROWSE_SUBTITLE);
- m_resolver = NULL;
m_emptyListItem = NULL;
m_initialized = false;
m_waiting = false;
-
- LoadPrinterNames();
}
CSecondPage::~CSecondPage()
{
- StopBrowse();
-}
-
-
-OSStatus
-CSecondPage::LoadPrinterNames()
-{
- PBYTE buffer = NULL;
- OSStatus err = 0;
-
- //
- // rdar://problem/3701926 - Printer can't be installed twice
- //
- // First thing we want to do is make sure the printer isn't already installed.
- // If the printer name is found, we'll try and rename it until we
- // find a unique name
- //
- DWORD dwNeeded = 0, dwNumPrinters = 0;
-
- BOOL ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwNumPrinters);
- err = translate_errno( ok, errno_compat(), kUnknownErr );
-
- if ((err == ERROR_INSUFFICIENT_BUFFER) && (dwNeeded > 0))
- {
- try
- {
- buffer = new unsigned char[dwNeeded];
- }
- catch (...)
- {
- buffer = NULL;
- }
-
- require_action( buffer, exit, kNoMemoryErr );
- ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, buffer, dwNeeded, &dwNeeded, &dwNumPrinters);
- err = translate_errno( ok, errno_compat(), kUnknownErr );
- require_noerr( err, exit );
-
- for (DWORD index = 0; index < dwNumPrinters; index++)
- {
- PRINTER_INFO_4 * lppi4 = (PRINTER_INFO_4*) (buffer + index * sizeof(PRINTER_INFO_4));
-
- m_printerNames[lppi4->pPrinterName] = lppi4->pPrinterName;
- }
- }
-
-exit:
-
- if (buffer != NULL)
- {
- delete [] buffer;
- }
-
- return err;
}
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
+ // Initialize so that nothing is selected when we add to the list
+
+ psheet->SetSelectedPrinter( NULL );
+ m_gotChoice = false;
+ m_browseList.Select( NULL, TVGN_FIRSTVISIBLE );
+
//
- // load the no rendezvous printers message until something shows up in the browse list
+ // load the no printers message until something shows up in the browse list
//
- text.LoadString(IDS_NO_RENDEZVOUS_PRINTERS);
+ text.LoadString(IDS_NO_PRINTERS);
LoadTextAndDisableWindow( text );
// disable the printer information box
//
SetPrinterInformationState( FALSE );
+ m_descriptionField.SetWindowText( L"" );
+ m_locationField.SetWindowText( L"" );
exit:
}
-OSStatus
-CSecondPage::StartOperation( DNSServiceRef ref )
-{
- OSStatus err;
-
- err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(ref), m_hWnd, WM_SERVICE_EVENT, FD_READ|FD_CLOSE);
- require_noerr( err, exit );
-
- m_serviceRefList.push_back( ref );
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StopOperation( DNSServiceRef & ref )
-{
- OSStatus err = kNoErr;
-
- if ( ref )
- {
- m_serviceRefList.remove( ref );
-
- if ( IsWindow( m_hWnd ) )
- {
- err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD( ref ), m_hWnd, 0, 0 );
- require_noerr( err, exit );
- }
-
- DNSServiceRefDeallocate( ref );
- ref = NULL;
- }
-
-exit:
-
- return err;
-}
-
-
-Printer*
-CSecondPage::Lookup(const char * inName)
-{
- check( IsWindow( m_hWnd ) );
- check( inName );
-
- HTREEITEM item = m_browseList.GetChildItem( TVI_ROOT );\r
- while ( item )\r
- {\r
- Printer * printer;\r
- DWORD_PTR data;\r
-\r
- data = m_browseList.GetItemData( item );\r
- printer = reinterpret_cast<Printer*>(data);\r
-\r
- if ( printer && ( printer->name == inName ) )
- {
- return printer;
- }
-\r
- item = m_browseList.GetNextItem( item, TVGN_NEXT );
- }
-
- return NULL;
-}
-
-
-OSStatus
-CSecondPage::StartBrowse()
-{
- OSStatus err;
-
- //
- // setup the DNS-SD browsing
- //
- err = DNSServiceBrowse( &m_pdlBrowser, 0, 0, kPDLServiceType, NULL, OnBrowse, this );
- require_noerr( err, exit );
-
- err = StartOperation( m_pdlBrowser );
- require_noerr( err, exit );
-
- err = DNSServiceBrowse( &m_lprBrowser, 0, 0, kLPRServiceType, NULL, OnBrowse, this );
- require_noerr( err, exit );
-
- err = StartOperation( m_lprBrowser );
- require_noerr( err, exit );
-
- err = DNSServiceBrowse( &m_ippBrowser, 0, 0, kIPPServiceType, NULL, OnBrowse, this );
- require_noerr( err, exit );
-
- err = StartOperation( m_ippBrowser );
- require_noerr( err, exit );
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StopBrowse()
-{
- OSStatus err;
-
- err = StopOperation( m_pdlBrowser );
- require_noerr( err, exit );
-
- err = StopOperation( m_lprBrowser );
- require_noerr( err, exit );
-
- err = StopOperation( m_ippBrowser );
- require_noerr( err, exit );
-
- while ( m_printers.size() > 0 )
- {
- Printer * printer = m_printers.front();
-
- m_printers.pop_front();
-
- if ( printer->resolving )
- {
- StopResolve( printer );
- }
-
- delete printer;
- }
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StartResolve( Printer * printer )
-{
- CPrinterSetupWizardSheet * psheet;
- OSStatus err = kNoErr;
- Services::iterator it;
-
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
-
- check( printer );
-
- for ( it = printer->services.begin(); it != printer->services.end(); it++ )
- {
- if ( (*it)->serviceRef == NULL )
- {
- err = StartResolve( *it );
- require_noerr( err, exit );
- }
- }
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StartResolve( Service * service )
-{
- CPrinterSetupWizardSheet * psheet;
- OSStatus err = kNoErr;
-
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
-
- check( service->serviceRef == NULL );
-
- //
- // clean out any queues that were collected during a previous
- // resolve
- //
-
- service->EmptyQueues();
-
- //
- // now start the new resolve
- //
-
- err = DNSServiceResolve( &service->serviceRef, 0, 0, service->printer->name.c_str(), service->type.c_str(), service->domain.c_str(), (DNSServiceResolveReply) OnResolve, service );
- require_noerr( err, exit );
-
- err = StartOperation( service->serviceRef );
- require_noerr( err, exit );
-
- //
- // If we're not currently resolving, then disable the next button
- // and set the cursor to hourglass
- //
-
- if ( !service->printer->resolving )
- {
- psheet->SetWizardButtons( PSWIZB_BACK );
-
- psheet->m_active = psheet->m_wait;
- SetCursor(psheet->m_active);
- }
-
- service->printer->resolving++;
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StopResolve(Printer * printer)
-{
- OSStatus err = kNoErr;
-
- check( printer );
-
- Services::iterator it;
-
- for ( it = printer->services.begin(); it != printer->services.end(); it++ )
- {
- if ( (*it)->serviceRef )
- {
- err = StopResolve( *it );
- require_noerr( err, exit );
- }
- }
-
-exit:
-
- return err;
-}
-
-
-OSStatus
-CSecondPage::StopResolve( Service * service )
+void CSecondPage::DoDataExchange(CDataExchange* pDX)
{
- OSStatus err;
-
- check( service->serviceRef );
-
- err = StopOperation( service->serviceRef );
- require_noerr( err, exit );
+ CPropertyPage::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
+ DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);
- service->printer->resolving--;
+ DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);
-exit:
+ DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);
- return err;
-}
+ DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);
+ DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);
-void CSecondPage::DoDataExchange(CDataExchange* pDX)
-{
- CPropertyPage::DoDataExchange(pDX);
- DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
- DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);\r
- DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);\r
- DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);\r
- DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);\r
- DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);\r
}
{
CPrinterSetupWizardSheet * psheet;
Printer * printer;
+ CWnd * pWnd;
+ Printers::iterator it;
OSStatus err = kNoErr;
+ BOOL b;
+
+ b = CPropertyPage::OnSetActive();
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_action( psheet, exit, err = kUnknownErr );
- if ( ( printer = psheet->GetSelectedPrinter() ) != NULL )
- {
- psheet->SetSelectedPrinter( NULL );
- delete printer;
- }
+ // Stash the selected printer if any
+
+ printer = psheet->GetSelectedPrinter();
- //
// initialize the browse list...this will remove everything currently
- // in it, and add the no rendezvous printers item
- //
- InitBrowseList();
+ // in it, and add the no printers item
- //
- // start browing
- //
- err = StartBrowse();
- require_noerr( err, exit );
+ InitBrowseList();
-exit:
+ // Populate the list with any printers that we currently know about
- if ( err != kNoErr )
+ for ( it = psheet->m_printers.begin(); it != psheet->m_printers.end(); it++ )
{
- if ( err == kDNSServiceErr_Firewall )
- {
- CString text, caption;
-
- text.LoadString( IDS_FIREWALL );
- caption.LoadString( IDS_FIREWALL_CAPTION );
-
- MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
- }
- else
- {
- CPrinterSetupWizardSheet::WizardException exc;
-
- exc.text.LoadString( IDS_NO_MDNSRESPONDER_SERVICE_TEXT );
- exc.caption.LoadString( IDS_ERROR_CAPTION );
-
- throw(exc);
- }
+ OnAddPrinter( *it, false );
}
- return CPropertyPage::OnSetActive();
-}
-
-
-BOOL
-CSecondPage::OnKillActive()
-{
- OSStatus err = kNoErr;
-
- if ( m_selected )
+ if ( ( !printer && ( psheet->m_printers.size() > 0 ) ) || ( printer != psheet->GetSelectedPrinter() ) )
{
- CPrinterSetupWizardSheet * psheet;
-
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
-
- psheet->SetSelectedPrinter( m_selected );
- m_printers.remove( m_selected );
- m_selected = NULL;
- }
-
- err = StopBrowse();
- require_noerr( err, exit );
-
-exit:
-
- return CPropertyPage::OnKillActive();
-}
-
-
-void DNSSD_API
-CSecondPage::OnBrowse(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inName,
- const char * inType,
- const char * inDomain,
- void * inContext )
-{
- DEBUG_UNUSED(inRef);
-
- CSecondPage * self;
- bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
-
- require_noerr( inErrorCode, exit );
-
- self = reinterpret_cast <CSecondPage*>( inContext );
- require_quiet( self, exit );
+ if ( !printer )
+ {
+ printer = psheet->m_printers.front();
+ }
- if ( inFlags & kDNSServiceFlagsAdd )
- {
- self->OnAddPrinter( inInterfaceIndex, inName, inType, inDomain, moreComing );
- }
- else
- {
- self->OnRemovePrinter( inName, inType, inDomain, moreComing );
+ psheet->SetSelectedPrinter( printer );
}
-
-exit:
-
- return;
-}
-
-
-void DNSSD_API
-CSecondPage::OnResolve(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inFullName,
- const char * inHostName,
- uint16_t inPort,
- uint16_t inTXTSize,
- const char * inTXT,
- void * inContext )
-{
- DEBUG_UNUSED(inFullName);
- DEBUG_UNUSED(inInterfaceIndex);
- DEBUG_UNUSED(inFlags);
- DEBUG_UNUSED(inRef);
-
- CSecondPage * self;
- Service * service;
- Queue * q;
- bool qtotalDefined = false;
- uint32_t qpriority = kDefaultPriority;
- CString qname;
- int idx;
- OSStatus err;
-
- require_noerr( inErrorCode, exit );
-
- service = reinterpret_cast<Service*>( inContext );
- require_quiet( service, exit);
-
- check( service->refs != 0 );
-
- self = service->printer->window;
- require_quiet( self, exit );
-
- err = self->StopOperation( service->serviceRef );
- require_noerr( err, exit );
- //
- // hold on to the hostname...
- //
- err = UTF8StringToStringObject( inHostName, service->hostname );
- require_noerr( err, exit );
-
- //
- // <rdar://problem/3739200> remove the trailing dot on hostname
- //
- idx = service->hostname.ReverseFind('.');
-
- if ((idx > 1) && ((service->hostname.GetLength() - 1) == idx))
+ if ( printer )
{
- service->hostname.Delete(idx, 1);
+ m_browseList.SelectItem( printer->item );
+ ::SetFocus( m_browseList );
}
- //
- // hold on to the port
- //
- service->portNumber = ntohs(inPort);
-
- //
- // parse the text record.
- //
-
- err = self->ParseTextRecord( service, inTXTSize, inTXT, qtotalDefined, qname, qpriority );
- require_noerr( err, exit );
-
- if ( service->qtotal == 1 )
- {
- //
- // create a new queue
- //
- try
- {
- q = new Queue;
- }
- catch (...)
- {
- q = NULL;
- }
-
- require_action( q, exit, err = E_OUTOFMEMORY );
-
- if ( qtotalDefined )
- {
- q->name = qname;
- }
-
- q->priority = qpriority;
-
- service->queues.push_back( q );
-
- //
- // we've completely resolved this service
- //
-
- self->OnResolveService( service );
- }
- else
+ // Hide the back button
+ pWnd = ((CPropertySheet*)GetParent())->GetDlgItem(ID_WIZBACK);
+ if ( pWnd != NULL )
{
- //
- // if qtotal is more than 1, then we need to get additional
- // text records. if not, then this service is considered
- // resolved
- //
-
- err = DNSServiceQueryRecord(&service->serviceRef, 0, inInterfaceIndex, inFullName, kDNSServiceType_TXT, kDNSServiceClass_IN, OnQuery, (void*) service );
- require_noerr( err, exit );
-
- err = self->StartOperation( service->serviceRef );
- require_noerr( err, exit );
+ pWnd->ShowWindow(SW_HIDE);
}
exit:
- return;
+ return b;
}
-void DNSSD_API
-CSecondPage::OnQuery(
- DNSServiceRef inRef,
- DNSServiceFlags inFlags,
- uint32_t inInterfaceIndex,
- DNSServiceErrorType inErrorCode,
- const char * inFullName,
- uint16_t inRRType,
- uint16_t inRRClass,
- uint16_t inRDLen,
- const void * inRData,
- uint32_t inTTL,
- void * inContext)
+BOOL
+CSecondPage::OnKillActive()
{
- DEBUG_UNUSED( inTTL );
- DEBUG_UNUSED( inRRClass );
- DEBUG_UNUSED( inRRType );
- DEBUG_UNUSED( inFullName );
- DEBUG_UNUSED( inInterfaceIndex );
- DEBUG_UNUSED( inRef );
+ CPrinterSetupWizardSheet * psheet;
+ CWnd * pWnd;
- Service * service = NULL;
- Queue * q;
- CSecondPage * self;
- bool qtotalDefined = false;
- bool moreComing = (bool) (inFlags & kDNSServiceFlagsMoreComing);
- OSStatus err = kNoErr;
-
- require_noerr( inErrorCode, exit );
-
- service = reinterpret_cast<Service*>( inContext );
- require_quiet( service, exit);
-
- self = service->printer->window;
- require_quiet( self, exit );
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
+
+ psheet->SetLastPage(this);
- if ( ( inFlags & kDNSServiceFlagsAdd ) && ( inRDLen > 0 ) && ( inRData != NULL ) )
+ // Show the back button
+ pWnd = ((CPropertySheet*)GetParent())->GetDlgItem(ID_WIZBACK);
+ if ( pWnd != NULL )
{
- const char * inTXT = ( const char * ) inRData;
-
- //
- // create a new queue
- //
- try
- {
- q = new Queue;
- }
- catch (...)
- {
- q = NULL;
- }
-
- require_action( q, exit, err = E_OUTOFMEMORY );
-
- err = service->printer->window->ParseTextRecord( service, inRDLen, inTXT, qtotalDefined, q->name, q->priority );
- require_noerr( err, exit );
-
- if ( !qtotalDefined )
- {
- q->name = L"";
- }
-
- //
- // add this queue
- //
-
- service->queues.push_back( q );
-
- if ( service->queues.size() == service->qtotal )
- {
- //
- // else if moreComing is not set, then we're going
- // to assume that we're done
- //
-
- self->StopOperation( service->serviceRef );
-
- //
- // sort the queues
- //
-
- service->queues.sort( OrderQueueFunc );
-
- //
- // we've completely resolved this service
- //
-
- self->OnResolveService( service );
- }
+ pWnd->ShowWindow(SW_SHOW);
}
exit:
- if ( err && service && ( service->serviceRef != NULL ) )
- {
- service->printer->window->StopOperation( service->serviceRef );
- }
-
- return;
+ return CPropertyPage::OnKillActive();
}
BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
- ON_MESSAGE( WM_SERVICE_EVENT, OnServiceEvent )
ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
+ ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnNmClickBrowseList)
+ ON_NOTIFY(TVN_KEYDOWN, IDC_BROWSE_LIST, OnTvnKeyDownBrowseList)
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
// Printer::EventHandler implementation
OSStatus
CSecondPage::OnAddPrinter(
- uint32_t inInterfaceIndex,
- const char * inName,
- const char * inType,
- const char * inDomain,
- bool moreComing)
+ Printer * printer,
+ bool moreComing )
{
- Printer * printer;
- Service * service;
CPrinterSetupWizardSheet * psheet;
- DWORD printerNameCount;
- bool newPrinter = false;
+ Printer * selectedPrinter;
OSStatus err = kNoErr;
check( IsWindow( m_hWnd ) );
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
- printer = Lookup( inName );
-
- if (printer == NULL)
- {
- try
- {
- printer = new Printer;
- }
- catch (...)
- {
- printer = NULL;
- }
-
- require_action( printer, exit, err = E_OUTOFMEMORY );
-
- printer->window = this;
- printer->name = inName;
-
- err = UTF8StringToStringObject(inName, printer->displayName);
- check_noerr( err );
- printer->actualName = printer->displayName;
- printer->installed = false;
- printer->deflt = false;
- printer->resolving = 0;
-
- //
- // Compare this name against printers that are already installed
- // to avoid name clashes. Rename as necessary
- // to come up with a unique name.
- //
- printerNameCount = 2;
-
- for (;;)
- {
- PrinterNameMap::iterator it;
-
- it = m_printerNames.find(printer->actualName);
-
- if (it != m_printerNames.end())
- {
- printer->actualName.Format(L"%s (%d)", printer->displayName, printerNameCount);
- }
- else
- {
- break;
- }
-
- printerNameCount++;
- }
-
- newPrinter = true;
- }
-
- check( printer );
-
- service = printer->LookupService( inType );
-
- if ( service != NULL )
- {
- service->refs++;
- }
- else
+ if ( printer )
{
- try
- {
- service = new Service;
- }
- catch (...)
- {
- service = NULL;
- }
-
- require_action( service, exit, err = E_OUTOFMEMORY );
-
- service->printer = printer;
- service->ifi = inInterfaceIndex;
- service->type = inType;
- service->domain = inDomain;
- service->qtotal = 1;
- service->refs = 1;
- service->serviceRef = NULL;
-
- printer->services.push_back( service );
-
- //
- // if the printer is selected, then we'll want to start a
- // resolve on this guy
- //
+ selectedPrinter = psheet->GetSelectedPrinter();
- if ( m_selected == printer )
- {
- StartResolve( service );
- }
- }
-
- if ( newPrinter )
- {
printer->item = m_browseList.InsertItem(printer->displayName);
m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
- m_printers.push_back( printer );
-
m_browseList.SortChildren(TVI_ROOT);
-
- if ( printer->name == m_selectedName )
- {
- m_browseList.SelectItem( printer->item );
- }
//
// if the searching item is still in the list
m_emptyListItem = NULL;
m_browseList.EnableWindow(TRUE);
}
+
+ if ( !selectedPrinter )
+ {
+ psheet->SetSelectedPrinter( printer );
+ m_browseList.SelectItem( printer->item );
+ ::SetFocus( m_browseList );
+ }
}
exit:
OSStatus
CSecondPage::OnRemovePrinter(
- const char * inName,
- const char * inType,
- const char * inDomain,
- bool moreComing)
+ Printer * printer,
+ bool moreComing)
{
- DEBUG_UNUSED( inDomain );
- DEBUG_UNUSED( inType );
-
- Printer * printer;
- OSStatus err = kNoErr;
+ CPrinterSetupWizardSheet * psheet;
+ OSStatus err = kNoErr;
check( IsWindow( m_hWnd ) );
+ check( printer );
- m_browseList.SetRedraw(FALSE);
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_quiet( psheet, exit );
- printer = Lookup( inName );
+ m_browseList.SetRedraw(FALSE);
if ( printer )
{
- Service * service;
-
- service = printer->LookupService( inType );
-
- if ( service && ( --service->refs == 0 ) )
+ //
+ // check to make sure if we're the only item in the control...i.e.
+ // the list size is 1.
+ //
+ if (m_browseList.GetCount() > 1)
{
- if ( service->serviceRef != NULL )
- {
- err = StopResolve( service );
- require_noerr( err, exit );
- }
-
- printer->services.remove( service );
-
- delete service;
+ //
+ // if we're not the only thing in the list, then
+ // simply remove it from the list
+ //
+ m_browseList.DeleteItem( printer->item );
}
-
- if ( printer->services.size() == 0 )
+ else
{
//
- // check to make sure if we're the only item in the control...i.e.
- // the list size is 1.
+ // if we're the only thing in the list, then redisplay
+ // it with the no printers message
//
- if (m_browseList.GetCount() > 1)
- {
- //
- // if we're not the only thing in the list, then
- // simply remove it from the list
- //
- m_browseList.DeleteItem( printer->item );
- }
- else
- {
- //
- // if we're the only thing in the list, then redisplay
- // it with the no rendezvous printers message
- //
- InitBrowseList();
- }
-
- m_printers.remove( printer );
-
- if ( m_selected == printer )
- {
- m_selected = NULL;
- m_selectedName = "";
- }
-
- delete printer;
+ InitBrowseList();
}
}
exit:
- if (!moreComing)
+ if ( !moreComing )
{
m_browseList.SetRedraw(TRUE);
m_browseList.Invalidate();
{
CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
require_quiet( psheet, exit );
-
- check( service );
- if ( !--service->printer->resolving )
- {
- //
- // sort the services now. we want the service that
- // has the highest priority queue to be first in
- // the list.
- //
+ check( service );
- service->printer->services.sort( OrderServiceFunc );
+ Queue * q = service->SelectedQueue();
- //
- // and set it to selected
- //
+ check( q );
+
- m_selected = service->printer;
- m_selectedName = service->printer->name;
+ //
+ // and set it to selected
+ //
- //
- // and update the printer information box
- //
- SetPrinterInformationState( TRUE );
+ m_selectedName = service->printer->name;
- m_descriptionField.SetWindowText( service->description );
- m_locationField.SetWindowText( service->location );
+ //
+ // and update the printer information box
+ //
+ SetPrinterInformationState( TRUE );
- psheet->SetWizardButtons( PSWIZB_BACK|PSWIZB_NEXT );
+ m_descriptionField.SetWindowText( q->description );
+ m_locationField.SetWindowText( q->location );
- //
- // reset the cursor
- //
+ //
+ // reset the cursor
+ //
- psheet->m_active = psheet->m_arrow;
- SetCursor(psheet->m_active);
- }
+ SetCursor(psheet->m_active);
exit:
}
-LONG
-CSecondPage::OnServiceEvent(WPARAM inWParam, LPARAM inLParam)
+void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
{
- if (WSAGETSELECTERROR(inLParam) && !(HIWORD(inLParam)))
- {
- dlog( kDebugLevelError, "OnServiceEvent: window error\n" );
- }
- else
- {
- SOCKET sock = (SOCKET) inWParam;
-
- // iterate thru list
- ServiceRefList::iterator begin = m_serviceRefList.begin();
- ServiceRefList::iterator end = m_serviceRefList.end();
-
- while (begin != end)
- {
- DNSServiceRef ref = *begin++;
+ LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
+ CPrinterSetupWizardSheet * psheet;
+ Printer * printer;
+ int err = 0;
- check(ref != NULL);
+ psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
+ require_action( psheet, exit, err = kUnknownErr );
+
+ // The strange code here is to workaround a bug in the CTreeCtrl, whereupon the item
+ // we selected isn't passed through correctly to this callback routine.
+
+ if ( !m_gotChoice )
+ {
+ printer = psheet->GetSelectedPrinter();
+
+ // If we really haven't selected a printer, then re-select NULL and exit
+
+ if ( !printer )
+ {
+ m_browseList.SelectItem( NULL );
- if ((SOCKET) DNSServiceRefSockFD(ref) == sock)
- {
- DNSServiceProcessResult(ref);
- break;
- }
+ goto exit;
}
- }
- return ( 0 );
-}
+ // If we already have selected a printer, fake like we've clicked on it, but only
+ // if the CTreeCtrl hasn't already selected it
+
+ else if ( printer->item != m_browseList.GetSelectedItem() )
+ {
+ m_gotChoice = true;
+ m_browseList.SelectItem( printer->item );
-void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
-{
- LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
- CPrinterSetupWizardSheet * psheet;
- int err = 0;
+ goto exit;
+ }
+ }
HTREEITEM item = m_browseList.GetSelectedItem();
require_quiet( item, exit );
- psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_action( psheet, exit, err = kUnknownErr );
-
- Printer * printer;
-
printer = reinterpret_cast<Printer*>(m_browseList.GetItemData( item ) );
require_quiet( printer, exit );
// this call will trigger a resolve. When the resolve is complete,
// our OnResolve will be called.
//
- err = StartResolve( printer );
+ err = psheet->StartResolve( printer );
require_noerr( err, exit );
//
}
-bool
-CSecondPage::OrderServiceFunc( const Service * a, const Service * b )
+void CSecondPage::OnNmClickBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
{
- Queue * q1, * q2;
-
- q1 = (a->queues.size() > 0) ? a->queues.front() : NULL;
+ DEBUG_UNUSED( pNMHDR );
- q2 = (b->queues.size() > 0) ? b->queues.front() : NULL;
+ m_gotChoice = true;
- if ( !q1 && !q2 )
- {
- return true;
- }
- else if ( q1 && !q2 )
- {
- return true;
- }
- else if ( !q1 && q2 )
- {
- return false;
- }
- else if ( q1->priority < q2->priority )
- {
- return true;
- }
- else if ( q1->priority > q2->priority )
- {
- return false;
- }
- else if ( ( a->type == kPDLServiceType ) || ( ( a->type == kLPRServiceType ) && ( b->type == kIPPServiceType ) ) )
- {
- return true;
- }
- else
- {
- return false;
- }
+ *pResult = 0;
}
-bool
-CSecondPage::OrderQueueFunc( const Queue * q1, const Queue * q2 )
+void CSecondPage::OnTvnKeyDownBrowseList( NMHDR * pNMHDR, LRESULT * pResult)
{
- return ( q1->priority <= q2->priority ) ? true : false;
+ DEBUG_UNUSED( pNMHDR );
+
+ m_gotChoice = true;
+
+ *pResult = 0;
}
void
CSecondPage::SetPrinterInformationState( BOOL state )
{
- m_printerInformation.EnableWindow( state );\r
- m_descriptionLabel.EnableWindow( state );\r
- m_descriptionField.EnableWindow( state );\r
- m_locationLabel.EnableWindow( state );\r
- m_locationField.EnableWindow( state );\r
-}\r
-\r
-\r
-OSStatus
-CSecondPage::ParseTextRecord( Service * service, uint16_t inTXTSize, const char * inTXT, bool & qtotalDefined, CString & qname, uint32_t & qpriority )
-{
- bool rpOnly = true;
- OSStatus err = kNoErr;
-
- while (inTXTSize)
- {
- char buf[256];
+ m_printerInformation.EnableWindow( state );
- unsigned char num = *inTXT;
- check( (int) num < inTXTSize );
+ m_descriptionLabel.EnableWindow( state );
- if ( num )
- {
- memset(buf, 0, sizeof(buf));
- memcpy(buf, inTXT + 1, num);
-
- CString elem;
-
- err = UTF8StringToStringObject( buf, elem );
- require_noerr( err, exit );
-
- int curPos = 0;
-
- CString key = elem.Tokenize(L"=", curPos);
- CString val = elem.Tokenize(L"=", curPos);
-
- key.MakeLower();
-
- if ( key == L"rp" )
- {
- qname = val;
- }
- else
- {
- rpOnly = false;
-
- if ((key == L"usb_mfg") || (key == L"usb_manufacturer"))
- {
- service->usb_MFG = val;
- }
- else if ((key == L"usb_mdl") || (key == L"usb_model"))
- {
- service->usb_MDL = val;
- }
- else if (key == L"ty")
- {
- service->description = val;
- }
- else if (key == L"product")
- {
- service->product = val;
- }
- else if (key == L"note")
- {
- service->location = val;
- }
- else if (key == L"qtotal")
- {
- service->qtotal = (unsigned short) _ttoi((LPCTSTR) val);
- qtotalDefined = true;
- }
- else if (key == L"priority")
- {
- qpriority = _ttoi((LPCTSTR) val);
- }
- }
- }
+ m_descriptionField.EnableWindow( state );
- inTXTSize -= (num + 1);
- inTXT += (num + 1);
- }
+ m_locationLabel.EnableWindow( state );
-exit:
+ m_locationField.EnableWindow( state );
- if ( rpOnly )
- {
- qtotalDefined = true;
- }
-
- return err;
}
+