1/* ----------------------------------------------------------------------- 2 * Copyright (c) 2003-2004 Waldemar Kornewald, Waldemar.Kornewald@web.de 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 * ----------------------------------------------------------------------- */ 22 23//----------------------------------------------------------------------- 24// GeneralAddon saves the loaded settings. 25// GeneralView saves the current settings. 26//----------------------------------------------------------------------- 27 28#include "GeneralAddon.h" 29 30#include "InterfaceUtils.h" 31#include "MessageDriverSettingsUtils.h" 32#include <stl_algobase.h> 33 // for max() 34 35#include <Box.h> 36#include <Button.h> 37#include <MenuField.h> 38#include <MenuItem.h> 39#include <PopUpMenu.h> 40#include <StringView.h> 41 42#include <PPPDefs.h> 43 44 45// message constants 46static const uint32 kMsgSelectDevice = 'SELD'; 47static const uint32 kMsgSelectAuthenticator = 'SELA'; 48 49// labels 50#ifdef LANG_GERMAN 51static const char *kLabelGeneral = "Allgemein"; 52static const char *kLabelDevice = "Ger��t: "; 53static const char *kLabelNoDevicesFound = "Keine Ger��te Gefunden!"; 54static const char *kLabelAuthenticator = "Login: "; 55static const char *kLabelNoAuthenticatorsFound = "Keine Login-Methoden gefunden!"; 56static const char *kLabelName = "Benutzername: "; 57static const char *kLabelPassword = "Password: "; 58static const char *kLabelSavePassword = "Passwort Speichern"; 59static const char *kLabelNone = "Ohne"; 60#else 61static const char *kLabelGeneral = "General"; 62static const char *kLabelDevice = "Device: "; 63static const char *kLabelNoDevicesFound = "No Devices Found!"; 64static const char *kLabelAuthenticator = "Login: "; 65static const char *kLabelNoAuthenticatorsFound = "No Authenticators Found!"; 66static const char *kLabelName = "Username: "; 67static const char *kLabelPassword = "Password: "; 68static const char *kLabelSavePassword = "Save Password"; 69static const char *kLabelNone = "None"; 70#endif 71 72// string constants for information saved in the settings message 73static const char *kGeneralTabAuthentication = "Authentication"; 74static const char *kGeneralTabAuthenticators = "Authenticators"; 75 76 77#define DEFAULT_AUTHENTICATOR "PAP" 78 // this authenticator is selected by default when creating a new interface 79 80 81GeneralAddon::GeneralAddon(BMessage *addons) 82 : DialUpAddon(addons), 83 fHasPassword(false), 84 fAuthenticatorsCount(0), 85 fSettings(NULL), 86 fProfile(NULL), 87 fGeneralView(NULL) 88{ 89} 90 91 92GeneralAddon::~GeneralAddon() 93{ 94} 95 96 97bool 98GeneralAddon::NeedsAuthenticationRequest() const 99{ 100 return fGeneralView->AuthenticatorName(); 101} 102 103 104DialUpAddon* 105GeneralAddon::FindDevice(const BString& moduleName) const 106{ 107 DialUpAddon *addon; 108 for(int32 index = 0; Addons()->FindPointer(DUN_DEVICE_ADDON_TYPE, index, 109 reinterpret_cast<void**>(&addon)) == B_OK; index++) 110 if(addon && moduleName == addon->KernelModuleName()) 111 return addon; 112 113 return NULL; 114} 115 116 117bool 118GeneralAddon::LoadSettings(BMessage *settings, BMessage *profile, bool isNew) 119{ 120 fIsNew = isNew; 121 fHasPassword = false; 122 fDeviceName = fUsername = fPassword = ""; 123 fDeviceAddon = NULL; 124 fAuthenticatorsCount = 0; 125 fSettings = settings; 126 fProfile = profile; 127 128 if(fGeneralView) 129 fGeneralView->Reload(); 130 // reset all views (empty settings) 131 132 if(!settings || !profile || isNew) 133 return true; 134 135 if(!LoadDeviceSettings()) 136 return false; 137 138 if(!LoadAuthenticationSettings()) 139 return false; 140 141 if(fGeneralView) 142 fGeneralView->Reload(); 143 // reload new settings 144 145 return true; 146} 147 148 149bool 150GeneralAddon::LoadDeviceSettings() 151{ 152 int32 index = 0; 153 BMessage device; 154 if(!FindMessageParameter(PPP_DEVICE_KEY, *fSettings, &device, &index)) 155 return false; 156 // TODO: tell user that device specification is missing 157 158 if(device.FindString(MDSU_VALUES, &fDeviceName) != B_OK) 159 return false; 160 // TODO: tell user that device specification is missing 161 162 device.AddBool(MDSU_VALID, true); 163 fSettings->ReplaceMessage(MDSU_PARAMETERS, index, &device); 164 165 fDeviceAddon = FindDevice(fDeviceName); 166 if(!fDeviceAddon) 167 return false; 168 169 return fDeviceAddon->LoadSettings(fSettings, fProfile, false); 170} 171 172 173bool 174GeneralAddon::LoadAuthenticationSettings() 175{ 176 // we only handle the profile (although settings could contain different data) 177 int32 itemIndex = 0; 178 BMessage authentication, item; 179 180 if(!FindMessageParameter(PPP_AUTHENTICATOR_KEY, *fProfile, &item, &itemIndex)) 181 return true; 182 183 // find authenticators (though we load all authenticators, we only use one) 184 BString name; 185 for(int32 index = 0; item.FindString(MDSU_VALUES, index, &name) == B_OK; index++) { 186 BMessage authenticator; 187 if(!GetAuthenticator(name, &authenticator)) 188 return false; 189 // fatal error: we do not know how to handle this authenticator 190 191 MarkAuthenticatorAsValid(name); 192 authentication.AddString(kGeneralTabAuthenticators, name); 193 ++fAuthenticatorsCount; 194 } 195 196 fSettings->AddMessage(kGeneralTabAuthentication, &authentication); 197 198 bool hasUsername = false; 199 // a username must be present 200 201 // load username and password 202 BMessage parameter; 203 int32 parameterIndex = 0; 204 if(FindMessageParameter("User", item, ¶meter, ¶meterIndex) 205 && parameter.FindString(MDSU_VALUES, &fUsername) == B_OK) { 206 hasUsername = true; 207 parameter.AddBool(MDSU_VALID, true); 208 item.ReplaceMessage(MDSU_PARAMETERS, parameterIndex, ¶meter); 209 } 210 211 parameterIndex = 0; 212 if(FindMessageParameter("Password", item, ¶meter, ¶meterIndex) 213 && parameter.FindString(MDSU_VALUES, &fPassword) == B_OK) { 214 fHasPassword = true; 215 parameter.AddBool(MDSU_VALID, true); 216 item.ReplaceMessage(MDSU_PARAMETERS, parameterIndex, ¶meter); 217 } 218 219 // tell DUN whether everything is valid 220 if(hasUsername) 221 item.AddBool(MDSU_VALID, true); 222 223 fProfile->ReplaceMessage(MDSU_PARAMETERS, itemIndex, &item); 224 225 return true; 226} 227 228 229bool 230GeneralAddon::HasTemporaryProfile() const 231{ 232 return fGeneralView->HasTemporaryProfile(); 233} 234 235 236void 237GeneralAddon::IsModified(bool *settings, bool *profile) const 238{ 239 if(!fSettings) { 240 *settings = *profile = false; 241 return; 242 } 243 244 bool deviceSettings, authenticationSettings, deviceProfile, authenticationProfile; 245 246 IsDeviceModified(&deviceSettings, &deviceProfile); 247 IsAuthenticationModified(&authenticationSettings, &authenticationProfile); 248 249 *settings = (deviceSettings || authenticationSettings); 250 *profile = (deviceProfile || authenticationProfile); 251} 252 253 254void 255GeneralAddon::IsDeviceModified(bool *settings, bool *profile) const 256{ 257 fGeneralView->IsDeviceModified(settings, profile); 258} 259 260 261void 262GeneralAddon::IsAuthenticationModified(bool *settings, bool *profile) const 263{ 264 // currently we only support selecting one authenticator 265 if(fAuthenticatorsCount == 0) 266 *settings = fGeneralView->AuthenticatorName(); 267 else { 268 BMessage authentication; 269 if(fSettings->FindMessage(kGeneralTabAuthentication, &authentication) != B_OK) { 270 *settings = *profile = false; 271 return; 272 // error! 273 } 274 275 BString authenticator; 276 if(authentication.FindString(kGeneralTabAuthenticators, 277 &authenticator) != B_OK) { 278 *settings = *profile = false; 279 return; 280 // error! 281 } 282 283 *settings = (!fGeneralView->AuthenticatorName() 284 || authenticator != fGeneralView->AuthenticatorName()); 285 } 286 287 *profile = (*settings || fUsername != fGeneralView->Username() 288 || (fPassword != fGeneralView->Password() && fHasPassword) 289 || fHasPassword != fGeneralView->DoesSavePassword()); 290} 291 292 293bool 294GeneralAddon::SaveSettings(BMessage *settings, BMessage *profile, bool saveTemporary) 295{ 296 if(!fSettings || !settings || !fGeneralView->DeviceName()) 297 return false; 298 // TODO: tell user that a device is needed (if we fail because of this) 299 300 if(!fGeneralView->DeviceAddon() || !fGeneralView->DeviceAddon()->SaveSettings( 301 settings, profile, saveTemporary)) 302 return false; 303 304 if(fGeneralView->AuthenticatorName()) { 305 BMessage authenticator; 306 authenticator.AddString(MDSU_NAME, PPP_AUTHENTICATOR_KEY); 307 authenticator.AddString(MDSU_VALUES, fGeneralView->AuthenticatorName()); 308 settings->AddMessage(MDSU_PARAMETERS, &authenticator); 309 310 BMessage username; 311 username.AddString(MDSU_NAME, "User"); 312 username.AddString(MDSU_VALUES, fGeneralView->Username()); 313 authenticator.AddMessage(MDSU_PARAMETERS, &username); 314 315 if(saveTemporary || fGeneralView->DoesSavePassword()) { 316 // save password, too 317 BMessage password; 318 password.AddString(MDSU_NAME, "Password"); 319 password.AddString(MDSU_VALUES, fGeneralView->Password()); 320 authenticator.AddMessage(MDSU_PARAMETERS, &password); 321 } 322 323 profile->AddMessage(MDSU_PARAMETERS, &authenticator); 324 } 325 326 return true; 327} 328 329 330bool 331GeneralAddon::GetPreferredSize(float *width, float *height) const 332{ 333 BRect rect; 334 if(Addons()->FindRect(DUN_TAB_VIEW_RECT, &rect) != B_OK) 335 rect.Set(0, 0, 200, 300); 336 // set default values 337 338 if(width) 339 *width = rect.Width(); 340 if(height) 341 *height = rect.Height(); 342 343 return true; 344} 345 346 347BView* 348GeneralAddon::CreateView(BPoint leftTop) 349{ 350 if(!fGeneralView) { 351 BRect rect; 352 Addons()->FindRect(DUN_TAB_VIEW_RECT, &rect); 353 fGeneralView = new GeneralView(this, rect); 354 fGeneralView->Reload(); 355 } 356 357 fGeneralView->MoveTo(leftTop); 358 return fGeneralView; 359} 360 361 362BView* 363GeneralAddon::AuthenticationView() const 364{ 365 return fGeneralView ? fGeneralView->AuthenticationView() : NULL; 366} 367 368 369bool 370GeneralAddon::GetAuthenticator(const BString& moduleName, BMessage *entry) const 371{ 372 if(!entry) 373 return false; 374 375 BString name; 376 for(int32 index = 0; Addons()->FindMessage(DUN_AUTHENTICATOR_ADDON_TYPE, index, 377 entry) == B_OK; index++) { 378 entry->FindString("KernelModuleName", &name); 379 if(name == moduleName) 380 return true; 381 } 382 383 return false; 384} 385 386 387bool 388GeneralAddon::MarkAuthenticatorAsValid(const BString& moduleName) 389{ 390 BMessage authenticator; 391 int32 index = 0; 392 BString name; 393 394 for(; FindMessageParameter(PPP_AUTHENTICATOR_KEY, *fSettings, &authenticator, 395 &index); index++) { 396 authenticator.FindString("KernelModuleName", &name); 397 if(name == moduleName) { 398 authenticator.AddBool(MDSU_VALID, true); 399 fSettings->ReplaceMessage(MDSU_PARAMETERS, index, &authenticator); 400 return true; 401 } 402 } 403 404 return false; 405} 406 407 408GeneralView::GeneralView(GeneralAddon *addon, BRect frame) 409 : BView(frame, kLabelGeneral, B_FOLLOW_NONE, 0), 410 fAddon(addon) 411{ 412 BRect rect = Bounds(); 413 rect.InsetBy(5, 5); 414 rect.bottom = 100; 415 fDeviceBox = new BBox(rect, "Device"); 416 Addon()->Addons()->AddFloat(DUN_DEVICE_VIEW_WIDTH, 417 fDeviceBox->Bounds().Width() - 10); 418 rect.top = rect.bottom + 10; 419 rect.bottom = rect.top 420 + 25 // space for topmost control 421 + 3 * 20 // size of controls 422 + 3 * 5; // space beween controls and bottom of box 423 fAuthenticationBox = new BBox(rect, "Authentication"); 424 425 fDeviceField = new BMenuField(BRect(5, 0, 250, 20), "Device", 426 kLabelDevice, new BPopUpMenu(kLabelNoDevicesFound)); 427 fDeviceField->SetDivider(StringWidth(fDeviceField->Label()) + 5); 428 fDeviceField->Menu()->SetRadioMode(true); 429 AddDevices(); 430 fDeviceBox->SetLabel(fDeviceField); 431 432 fAuthenticatorField = new BMenuField(BRect(5, 0, 250, 20), "Authenticator", 433 kLabelAuthenticator, new BPopUpMenu(kLabelNoAuthenticatorsFound)); 434 fAuthenticatorField->SetDivider(StringWidth(fAuthenticatorField->Label()) + 5); 435 fAuthenticatorField->Menu()->SetRadioMode(true); 436 AddAuthenticators(); 437 fAuthenticationBox->SetLabel(fAuthenticatorField); 438 439 rect = fAuthenticationBox->Bounds(); 440 rect.InsetBy(10, 5); 441 rect.top = 25; 442// fAuthenticationView = new BControl(rect, "authenticationView", NULL, NULL, 443// B_FOLLOW_NONE, 0); 444 // BControl automatically sets the view color when attached (we want that) 445 fAuthenticationView = new BView(rect, "authenticationView", B_FOLLOW_NONE, 0); 446 fAuthenticationView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 447 rect = fAuthenticationView->Bounds(); 448 rect.bottom = rect.top + 20; 449 fUsername = new BTextControl(rect, "username", kLabelName, NULL, NULL); 450 rect.top = rect.bottom + 5; 451 rect.bottom = rect.top + 20; 452 fPassword = new BTextControl(rect, "password", kLabelPassword, NULL, NULL); 453 fPassword->TextView()->HideTyping(true); 454 455 // set dividers 456 float width = max(StringWidth(fUsername->Label()), 457 StringWidth(fPassword->Label())); 458 fUsername->SetDivider(width + 5); 459 fPassword->SetDivider(width + 5); 460 461 rect.top = rect.bottom + 5; 462 rect.bottom = rect.top + 20; 463 fSavePassword = new BCheckBox(rect, "SavePassword", kLabelSavePassword, NULL); 464 465 fAuthenticationView->AddChild(fUsername); 466 fAuthenticationView->AddChild(fPassword); 467 fAuthenticationView->AddChild(fSavePassword); 468 fAuthenticationBox->AddChild(fAuthenticationView); 469 470 AddChild(fDeviceBox); 471 AddChild(fAuthenticationBox); 472} 473 474 475GeneralView::~GeneralView() 476{ 477} 478 479 480void 481GeneralView::Reload() 482{ 483 fDeviceAddon = NULL; 484 485 BMenuItem *item = NULL; 486 for(int32 index = 0; index < fDeviceField->Menu()->CountItems(); index++) { 487 item = fDeviceField->Menu()->ItemAt(index); 488 if(item && item->Message() && item->Message()->FindPointer("Addon", 489 reinterpret_cast<void**>(&fDeviceAddon)) == B_OK 490 && fDeviceAddon == Addon()->DeviceAddon()) 491 break; 492 } 493 494 if(fDeviceAddon && fDeviceAddon == Addon()->DeviceAddon()) 495 item->SetMarked(true); 496 else if(Addon()->IsNew() && fDeviceField->Menu()->CountItems() > 0) { 497 item = fDeviceField->Menu()->ItemAt(0); 498 item->SetMarked(true); 499 item->Message()->FindPointer("Addon", reinterpret_cast<void**>(&fDeviceAddon)); 500 fDeviceAddon->LoadSettings(Addon()->Settings(), Addon()->Profile(), true); 501 } else { 502 fDeviceAddon = NULL; 503 item = fDeviceField->Menu()->FindMarked(); 504 if(item) 505 item->SetMarked(false); 506 } 507 508 if(Addon()->CountAuthenticators() > 0) { 509 BString kernelModule, authenticator; 510 BMessage authentication; 511 if(Addon()->Settings()->FindMessage(kGeneralTabAuthentication, 512 &authentication) == B_OK) 513 authentication.FindString(kGeneralTabAuthenticators, &authenticator); 514 BMenu *menu = fAuthenticatorField->Menu(); 515 for(int32 index = 0; index < menu->CountItems(); index++) { 516 item = menu->ItemAt(index); 517 if(item && item->Message() 518 && item->Message()->FindString("KernelModuleName", 519 &kernelModule) == B_OK && kernelModule == authenticator) { 520 item->SetMarked(true); 521 break; 522 } 523 } 524 } else if(Addon()->IsNew() && fAuthenticatorDefault) 525 fAuthenticatorDefault->SetMarked(true); 526 else 527 fAuthenticatorNone->SetMarked(true); 528 529 fUsername->SetText(Addon()->Username()); 530 fPassword->SetText(Addon()->Password()); 531 fSavePassword->SetValue(Addon()->HasPassword()); 532 533 ReloadDeviceView(); 534 UpdateControls(); 535} 536 537 538const char* 539GeneralView::DeviceName() const 540{ 541 if(fDeviceAddon) 542 return fDeviceAddon->KernelModuleName(); 543 544 return NULL; 545} 546 547 548const char* 549GeneralView::AuthenticatorName() const 550{ 551 BMenuItem *marked = fAuthenticatorField->Menu()->FindMarked(); 552 if(marked && marked != fAuthenticatorNone) 553 return marked->Message()->FindString("KernelModuleName"); 554 555 return NULL; 556} 557 558 559void 560GeneralView::IsDeviceModified(bool *settings, bool *profile) const 561{ 562 if(fDeviceAddon != Addon()->DeviceAddon()) 563 *settings = *profile = true; 564 else if(fDeviceAddon) 565 fDeviceAddon->IsModified(settings, profile); 566 else 567 *settings = *profile = false; 568} 569 570 571void 572GeneralView::AttachedToWindow() 573{ 574 SetViewColor(Parent()->ViewColor()); 575 fDeviceField->Menu()->SetTargetForItems(this); 576 fAuthenticatorField->Menu()->SetTargetForItems(this); 577 fUsername->SetTarget(this); 578 fPassword->SetTarget(this); 579} 580 581 582void 583GeneralView::MessageReceived(BMessage *message) 584{ 585 switch(message->what) { 586 case kMsgSelectDevice: 587 if(message->FindPointer("Addon", reinterpret_cast<void**>(&fDeviceAddon)) 588 != B_OK) 589 fDeviceAddon = NULL; 590 else { 591 if(fDeviceAddon != Addon()->DeviceAddon()) 592 fDeviceAddon->LoadSettings(Addon()->Settings(), Addon()->Profile(), 593 Addon()->IsNew()); 594 595 ReloadDeviceView(); 596 } 597 break; 598 599 case kMsgSelectAuthenticator: 600 UpdateControls(); 601 break; 602 603 default: 604 BView::MessageReceived(message); 605 } 606} 607 608 609void 610GeneralView::ReloadDeviceView() 611{ 612 // first remove existing device view(s) 613 while(fDeviceBox->CountChildren() > 1) 614 fDeviceBox->RemoveChild(fDeviceBox->ChildAt(1)); 615 616 if(!fDeviceAddon) 617 return; 618 619 BRect rect(fDeviceBox->Bounds()); 620 float width, height; 621 if(!fDeviceAddon->GetPreferredSize(&width, &height)) { 622 width = rect.Width(); 623 height = 50; 624 } 625 626 if(width > rect.Width()) 627 width = rect.Width(); 628 if(height < 10) 629 height = 10; 630 // set minimum height 631 else if(height > 200) 632 height = 200; 633 // set maximum height 634 635 rect.InsetBy((rect.Width() - width) / 2, 0); 636 // center horizontally 637 rect.top = 25; 638 rect.bottom = rect.top + height; 639 float deltaY = height + 30 - fDeviceBox->Bounds().Height(); 640 fDeviceBox->ResizeBy(0, deltaY); 641 fAuthenticationBox->MoveBy(0, deltaY); 642 643 BView *deviceView = fDeviceAddon->CreateView(rect.LeftTop()); 644 if(deviceView) 645 fDeviceBox->AddChild(deviceView); 646} 647 648 649void 650GeneralView::UpdateControls() 651{ 652 BMenu *menu = fAuthenticatorField->Menu(); 653 int32 index = menu->IndexOf(menu->FindMarked()); 654 if(index < 0) 655 fAuthenticatorNone->SetMarked(true); 656 657 if(index == 0) { 658 fUsername->SetEnabled(false); 659 fPassword->SetEnabled(false); 660 fSavePassword->SetEnabled(false); 661 } else { 662 fUsername->SetEnabled(true); 663 fPassword->SetEnabled(true); 664 fSavePassword->SetEnabled(true); 665 } 666} 667 668 669void 670GeneralView::AddDevices() 671{ 672 AddAddonsToMenu(Addon()->Addons(), fDeviceField->Menu(), DUN_DEVICE_ADDON_TYPE, 673 kMsgSelectDevice); 674} 675 676 677void 678GeneralView::AddAuthenticators() 679{ 680 fAuthenticatorDefault = NULL; 681 fAuthenticatorNone = new BMenuItem(kLabelNone, 682 new BMessage(kMsgSelectAuthenticator)); 683 fAuthenticatorField->Menu()->AddItem(fAuthenticatorNone); 684 fAuthenticatorNone->SetMarked(true); 685 fAuthenticatorField->Menu()->AddSeparatorItem(); 686 687 BMenuItem *item; 688 BMessage addon; 689 for(int32 index = 0; 690 Addon()->Addons()->FindMessage(DUN_AUTHENTICATOR_ADDON_TYPE, index, 691 &addon) == B_OK; index++) { 692 BMessage *message = new BMessage(kMsgSelectAuthenticator); 693 message->AddString("KernelModuleName", addon.FindString("KernelModuleName")); 694 695 BString name, technicalName, friendlyName; 696 bool hasTechnicalName 697 = (addon.FindString("TechnicalName", &technicalName) == B_OK); 698 bool hasFriendlyName 699 = (addon.FindString("FriendlyName", &friendlyName) == B_OK); 700 if(hasTechnicalName) { 701 name << technicalName; 702 if(hasFriendlyName) 703 name << " ("; 704 } 705 if(hasFriendlyName) { 706 name << friendlyName; 707 if(hasTechnicalName) 708 name << ")"; 709 } 710 711 int32 insertAt = FindNextMenuInsertionIndex(fAuthenticatorField->Menu(), 712 name.String(), 2); 713 item = new BMenuItem(name.String(), message); 714 if(hasTechnicalName && technicalName == DEFAULT_AUTHENTICATOR) 715 fAuthenticatorDefault = item; 716 fAuthenticatorField->Menu()->AddItem(item, insertAt); 717 } 718} 719