]> git.saurik.com Git - apple/mdnsresponder.git/blob - Clients/PrinterSetupWizard/SecondPage.cpp
mDNSResponder-107.6.tar.gz
[apple/mdnsresponder.git] / Clients / PrinterSetupWizard / SecondPage.cpp
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16
17 Change History (most recent first):
18
19 $Log: SecondPage.cpp,v $
20 Revision 1.19 2006/08/14 23:24:09 cheshire
21 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
22
23 Revision 1.18 2005/07/20 17:44:54 shersche
24 <rdar://problem/4124524> UI fixes for CUPS workaround
25
26 Revision 1.17 2005/07/11 20:17:15 shersche
27 <rdar://problem/4124524> UI fixes associated with CUPS printer workaround fix.
28
29 Revision 1.16 2005/07/07 17:53:20 shersche
30 Fix problems associated with the CUPS printer workaround fix.
31
32 Revision 1.15 2005/04/13 17:46:22 shersche
33 <rdar://problem/4082122> Generic PCL not selected when printers advertise multiple text records
34
35 Revision 1.14 2005/03/20 20:08:37 shersche
36 <rdar://problem/4055670> Second screen should not select a printer by default
37
38 Revision 1.13 2005/02/15 07:50:10 shersche
39 <rdar://problem/4007151> Update name
40
41 Revision 1.12 2005/02/10 22:35:11 cheshire
42 <rdar://problem/3727944> Update name
43
44 Revision 1.11 2005/01/31 23:54:30 shersche
45 <rdar://problem/3947508> Start browsing when printer wizard starts. Move browsing logic from CSecondPage object to CPrinterSetupWizardSheet object.
46
47 Revision 1.10 2005/01/20 19:54:38 shersche
48 Fix parse error when text record is NULL
49
50 Revision 1.9 2005/01/06 08:13:50 shersche
51 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
52
53 Revision 1.8 2005/01/04 21:09:14 shersche
54 Fix problems in parsing text records. Fix problems in remove event handling. Ensure that the same service can't be resolved more than once.
55
56 Revision 1.7 2004/12/31 07:25:27 shersche
57 Tidy up printer management, and fix memory leaks when hitting 'Cancel'
58
59 Revision 1.6 2004/12/30 01:24:02 shersche
60 <rdar://problem/3906182> Remove references to description key
61 Bug #: 3906182
62
63 Revision 1.5 2004/12/30 01:02:47 shersche
64 <rdar://problem/3734478> Add Printer information box that displays description and location information when printer name is selected
65 Bug #: 3734478
66
67 Revision 1.4 2004/12/29 18:53:38 shersche
68 <rdar://problem/3725106>
69 <rdar://problem/3737413> Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase.
70 Bug #: 3725106, 3737413
71
72 Revision 1.3 2004/09/13 21:26:15 shersche
73 <rdar://problem/3796483> Use the moreComing flag to determine whether drawing should take place in OnAddPrinter and OnRemovePrinter callbacks
74 Bug #: 3796483
75
76 Revision 1.2 2004/06/26 03:19:57 shersche
77 clean up warning messages
78
79 Submitted by: herscher
80
81 Revision 1.1 2004/06/18 04:36:57 rpantos
82 First checked in
83
84
85 */
86
87 #include "stdafx.h"
88 #include "PrinterSetupWizardApp.h"
89 #include "PrinterSetupWizardSheet.h"
90 #include "SecondPage.h"
91 #include "DebugServices.h"
92 #include "WinServices.h"
93 #include <winspool.h>
94
95 // local variable is initialize but not referenced
96 #pragma warning(disable:4189)
97
98 // CSecondPage dialog
99
100 IMPLEMENT_DYNAMIC(CSecondPage, CPropertyPage)
101 CSecondPage::CSecondPage()
102 : CPropertyPage(CSecondPage::IDD)
103 {
104 m_psp.dwFlags &= ~(PSP_HASHELP);
105 m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
106
107 m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_BROWSE_TITLE);
108 m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_BROWSE_SUBTITLE);
109
110 m_emptyListItem = NULL;
111 m_initialized = false;
112 m_waiting = false;
113 }
114
115
116 CSecondPage::~CSecondPage()
117 {
118 }
119
120
121 void
122 CSecondPage::InitBrowseList()
123 {
124 CPrinterSetupWizardSheet * psheet;
125 CString text;
126
127 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
128 require_quiet( psheet, exit );
129
130 // Initialize so that nothing is selected when we add to the list
131
132 psheet->SetSelectedPrinter( NULL );
133 m_gotChoice = false;
134 m_browseList.Select( NULL, TVGN_FIRSTVISIBLE );
135
136 //
137 // load the no printers message until something shows up in the browse list
138 //
139 text.LoadString(IDS_NO_PRINTERS);
140
141 LoadTextAndDisableWindow( text );
142
143 //
144 // disable the next button until there's a printer to select
145 //
146 psheet->SetWizardButtons(PSWIZB_BACK);
147
148 //
149 // disable the printer information box
150 //
151 SetPrinterInformationState( FALSE );
152 m_descriptionField.SetWindowText( L"" );
153 m_locationField.SetWindowText( L"" );
154
155 exit:
156
157 return;
158 }
159
160
161 void CSecondPage::DoDataExchange(CDataExchange* pDX)
162 {
163 CPropertyPage::DoDataExchange(pDX);
164 DDX_Control(pDX, IDC_BROWSE_LIST, m_browseList);
165 DDX_Control(pDX, IDC_PRINTER_INFORMATION, m_printerInformation);
166
167 DDX_Control(pDX, IDC_DESCRIPTION_LABEL, m_descriptionLabel);
168
169 DDX_Control(pDX, IDC_DESCRIPTION_FIELD, m_descriptionField);
170
171 DDX_Control(pDX, IDC_LOCATION_LABEL, m_locationLabel);
172
173 DDX_Control(pDX, IDC_LOCATION_FIELD, m_locationField);
174
175 }
176
177
178 afx_msg BOOL
179 CSecondPage::OnSetCursor(CWnd * pWnd, UINT nHitTest, UINT message)
180 {
181 DEBUG_UNUSED(pWnd);
182 DEBUG_UNUSED(nHitTest);
183 DEBUG_UNUSED(message);
184
185 CPrinterSetupWizardSheet * psheet;
186
187 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
188 require_quiet( psheet, exit );
189
190 SetCursor(psheet->GetCursor());
191
192 exit:
193
194 return TRUE;
195 }
196
197
198 BOOL
199 CSecondPage::OnSetActive()
200 {
201 CPrinterSetupWizardSheet * psheet;
202 Printer * printer;
203 Printers::iterator it;
204 OSStatus err = kNoErr;
205 BOOL b;
206
207 b = CPropertyPage::OnSetActive();
208
209 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
210 require_action( psheet, exit, err = kUnknownErr );
211
212 // Stash the selected printer if any
213
214 printer = psheet->GetSelectedPrinter();
215
216 // initialize the browse list...this will remove everything currently
217 // in it, and add the no printers item
218
219 InitBrowseList();
220
221 // Populate the list with any printers that we currently know about
222
223 for ( it = psheet->m_printers.begin(); it != psheet->m_printers.end(); it++ )
224 {
225 OnAddPrinter( *it, false );
226 }
227
228 // And if we hit 'Back' from page 3, then re-select printer
229
230 if ( ( psheet->GetLastPage() == psheet->GetPage( 2 ) ) && printer )
231 {
232 psheet->SetSelectedPrinter( printer );
233 m_browseList.Select( printer->item, TVGN_FIRSTVISIBLE );
234 }
235
236 exit:
237
238 return b;
239 }
240
241
242 BOOL
243 CSecondPage::OnKillActive()
244 {
245 CPrinterSetupWizardSheet * psheet;
246
247 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
248 require_quiet( psheet, exit );
249
250 psheet->SetLastPage(this);
251
252 exit:
253
254 return CPropertyPage::OnKillActive();
255 }
256
257
258 BEGIN_MESSAGE_MAP(CSecondPage, CPropertyPage)
259 ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSE_LIST, OnTvnSelchangedBrowseList)
260 ON_NOTIFY(NM_CLICK, IDC_BROWSE_LIST, OnNmClickBrowseList)
261 ON_NOTIFY(TVN_KEYDOWN, IDC_BROWSE_LIST, OnTvnKeyDownBrowseList)
262 ON_WM_SETCURSOR()
263 END_MESSAGE_MAP()
264
265
266 // Printer::EventHandler implementation
267 OSStatus
268 CSecondPage::OnAddPrinter(
269 Printer * printer,
270 bool moreComing )
271 {
272 CPrinterSetupWizardSheet * psheet;
273 OSStatus err = kNoErr;
274
275 check( IsWindow( m_hWnd ) );
276
277 m_browseList.SetRedraw(FALSE);
278
279 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
280 require_quiet( psheet, exit );
281
282 printer->item = m_browseList.InsertItem(printer->displayName);
283
284 m_browseList.SetItemData( printer->item, (DWORD_PTR) printer );
285
286 m_browseList.SortChildren(TVI_ROOT);
287
288 //
289 // if the searching item is still in the list
290 // get rid of it
291 //
292 // note that order is important here. Insert the printer
293 // item before removing the placeholder so we always have
294 // an item in the list to avoid experiencing the bug
295 // in Microsoft's implementation of CTreeCtrl
296 //
297 if (m_emptyListItem != NULL)
298 {
299 m_browseList.DeleteItem(m_emptyListItem);
300 m_emptyListItem = NULL;
301 m_browseList.EnableWindow(TRUE);
302 }
303
304 exit:
305
306 if (!moreComing)
307 {
308 m_browseList.SetRedraw(TRUE);
309 m_browseList.Invalidate();
310 }
311
312 return err;
313 }
314
315
316 OSStatus
317 CSecondPage::OnRemovePrinter(
318 Printer * printer,
319 bool moreComing)
320 {
321 CPrinterSetupWizardSheet * psheet;
322 OSStatus err = kNoErr;
323
324 check( IsWindow( m_hWnd ) );
325 check( printer );
326
327 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
328 require_quiet( psheet, exit );
329
330 m_browseList.SetRedraw(FALSE);
331
332 //
333 // check to make sure if we're the only item in the control...i.e.
334 // the list size is 1.
335 //
336 if (m_browseList.GetCount() > 1)
337 {
338 //
339 // if we're not the only thing in the list, then
340 // simply remove it from the list
341 //
342 m_browseList.DeleteItem( printer->item );
343 }
344 else
345 {
346 //
347 // if we're the only thing in the list, then redisplay
348 // it with the no printers message
349 //
350 InitBrowseList();
351 }
352
353 exit:
354
355 if ( !moreComing )
356 {
357 m_browseList.SetRedraw(TRUE);
358 m_browseList.Invalidate();
359 }
360
361 return err;
362 }
363
364
365 void
366 CSecondPage::OnResolveService( Service * service )
367 {
368 CPrinterSetupWizardSheet * psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
369 require_quiet( psheet, exit );
370
371 check( service );
372
373 Queue * q = service->SelectedQueue();
374
375 check( q );
376
377
378 //
379 // and set it to selected
380 //
381
382 m_selectedName = service->printer->name;
383
384 //
385 // and update the printer information box
386 //
387 SetPrinterInformationState( TRUE );
388
389 m_descriptionField.SetWindowText( q->description );
390 m_locationField.SetWindowText( q->location );
391
392 //
393 // reset the cursor
394 //
395
396 SetCursor(psheet->m_active);
397
398 exit:
399
400 return;
401 }
402
403
404 void CSecondPage::OnTvnSelchangedBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
405 {
406 LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
407 CPrinterSetupWizardSheet * psheet;
408 Printer * printer;
409 int err = 0;
410
411 psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
412 require_action( psheet, exit, err = kUnknownErr );
413
414 // The strange code here is to workaround a bug in the CTreeCtrl, whereupon the item
415 // we selected isn't passed through correctly to this callback routine.
416
417 if ( !m_gotChoice )
418 {
419 printer = psheet->GetSelectedPrinter();
420
421 // If we really haven't selected a printer, then re-select NULL and exit
422
423 if ( !printer )
424 {
425 m_browseList.SelectItem( NULL );
426
427 goto exit;
428 }
429
430 // If we already have selected a printer, fake like we've clicked on it, but only
431 // if the CTreeCtrl hasn't already selected it
432
433 else if ( printer->item != m_browseList.GetSelectedItem() )
434 {
435 m_gotChoice = true;
436
437 m_browseList.SelectItem( printer->item );
438
439 goto exit;
440 }
441 }
442
443 HTREEITEM item = m_browseList.GetSelectedItem();
444 require_quiet( item, exit );
445
446 printer = reinterpret_cast<Printer*>(m_browseList.GetItemData( item ) );
447 require_quiet( printer, exit );
448
449 //
450 // this call will trigger a resolve. When the resolve is complete,
451 // our OnResolve will be called.
452 //
453 err = psheet->StartResolve( printer );
454 require_noerr( err, exit );
455
456 //
457 // And clear out the printer information box
458 //
459 SetPrinterInformationState( FALSE );
460 m_descriptionField.SetWindowText(L"");
461 m_locationField.SetWindowText(L"");
462
463 exit:
464
465 if (err != 0)
466 {
467 CString text;
468 CString caption;
469
470 text.LoadString(IDS_ERROR_SELECTING_PRINTER_TEXT);
471 caption.LoadString(IDS_ERROR_SELECTING_PRINTER_CAPTION);
472
473 MessageBox(text, caption, MB_OK|MB_ICONEXCLAMATION);
474 }
475
476 *pResult = 0;
477 }
478
479
480 void CSecondPage::OnNmClickBrowseList(NMHDR *pNMHDR, LRESULT *pResult)
481 {
482 DEBUG_UNUSED( pNMHDR );
483
484 m_gotChoice = true;
485
486 *pResult = 0;
487 }
488
489
490 void CSecondPage::OnTvnKeyDownBrowseList( NMHDR * pNMHDR, LRESULT * pResult)
491 {
492 DEBUG_UNUSED( pNMHDR );
493
494 m_gotChoice = true;
495
496 *pResult = 0;
497 }
498
499
500 void
501 CSecondPage::LoadTextAndDisableWindow( CString & text )
502 {
503 m_emptyListItem = m_browseList.InsertItem( text, 0, 0, NULL, TVI_FIRST );
504 m_browseList.SelectItem( NULL );
505
506 //
507 // this will remove everything else in the list...we might be navigating
508 // back to this window, and the browse list might have changed since
509 // we last displayed it.
510 //
511 if ( m_emptyListItem )
512 {
513 HTREEITEM item = m_browseList.GetNextVisibleItem( m_emptyListItem );
514
515 while ( item )
516 {
517 m_browseList.DeleteItem( item );
518 item = m_browseList.GetNextVisibleItem( m_emptyListItem );
519 }
520 }
521
522 m_browseList.EnableWindow( FALSE );
523 }
524
525
526 void
527 CSecondPage::SetPrinterInformationState( BOOL state )
528 {
529 m_printerInformation.EnableWindow( state );
530
531 m_descriptionLabel.EnableWindow( state );
532
533 m_descriptionField.EnableWindow( state );
534
535 m_locationLabel.EnableWindow( state );
536
537 m_locationField.EnableWindow( state );
538
539 }
540
541
542