00001
00032 #include "linden_common.h"
00033
00034 #include "llboost.h"
00035
00036 #include "llalertdialog.h"
00037 #include "llfontgl.h"
00038 #include "llresmgr.h"
00039 #include "lltextbox.h"
00040 #include "llbutton.h"
00041 #include "llcheckboxctrl.h"
00042 #include "llkeyboard.h"
00043 #include "llfocusmgr.h"
00044 #include "llui.h"
00045 #include "llxmlnode.h"
00046 #include "lllineeditor.h"
00047 #include "lluictrlfactory.h"
00048
00049
00050 const S32 MAX_ALLOWED_MSG_WIDTH = 400;
00051 const F32 DEFAULT_BUTTON_DELAY = 0.5f;
00052 const S32 MSG_PAD = 8;
00053
00054 LLAlertDialog::template_map_t LLAlertDialog::sAlertTemplates;
00055 LLAlertDialog::template_map_t LLAlertDialog::sIgnorableTemplates;
00056 LLControlGroup* LLAlertDialog::sSettings = NULL;
00057 std::map<LLString,LLAlertDialog*> LLAlertDialog::sUniqueActiveMap;
00058 LLAlertDialog::display_callback_t LLAlertDialog::sDisplayCallback;
00059 LLString LLAlertDialog::sStringSkipNextTime("Skip this dialog next time");
00060 LLString LLAlertDialog::sStringAlwaysChoose("Always choose this option");
00061
00062
00063 LLAlertDialog* LLAlertDialog::createXml( const LLString& xml_desc,
00064 alert_callback_t callback, void *user_data)
00065 {
00066 LLString::format_map_t args;
00067 return createXml(xml_desc, args, callback, user_data);
00068 }
00069
00070
00071 LLAlertDialog* LLAlertDialog::createXml( const LLString& xml_desc, const LLString::format_map_t& args,
00072 alert_callback_t callback, void *user_data)
00073 {
00074 template_map_t::iterator iter = sAlertTemplates.find(xml_desc);
00075 if (iter != sAlertTemplates.end())
00076 {
00077 LLAlertDialogTemplate* xml_template = iter->second;
00078
00079 llwarns << "Alert: [" << xml_desc << "] " << llendl;
00080 LLAlertDialog* dialog = new LLAlertDialog( xml_template, args, callback, user_data);
00081 return dialog;
00082 }
00083 else
00084 {
00085 LLString::format_map_t args;
00086 args["[ALERT_NAME]"] = xml_desc;
00087 llwarns << "Missing Alert: [" << xml_desc << "]" << llendl;
00088 LLAlertDialog* dialogp = LLAlertDialog::showXml("MissingAlert", args);
00089 if (dialogp == NULL)
00090 {
00091 llerrs << "Bad or missing alerts.xml!" << llendl;
00092 }
00093 return NULL;
00094 }
00095 }
00096
00097
00098 LLAlertDialog* LLAlertDialog::showXml( const LLString& xml_desc,
00099 alert_callback_t callback, void *user_data)
00100 {
00101 LLString::format_map_t args;
00102 return showXml(xml_desc, args, callback, user_data);
00103 }
00104
00105
00106 LLAlertDialog* LLAlertDialog::showXml( const LLString& xml_desc, const LLString::format_map_t& args,
00107 alert_callback_t callback, void *user_data)
00108 {
00109 LLAlertDialog* dialog = createXml(xml_desc, args, callback, user_data);
00110 return dialog && dialog->show() ? dialog : NULL;
00111 }
00112
00113
00114 LLAlertDialog* LLAlertDialog::showCritical( const LLString& desc, alert_callback_t callback, void *user_data)
00115 {
00116 LLAlertDialogTemplate xml_template;
00117 LLString::format_map_t args;
00118 xml_template.mTitle = "Critical Error";
00119 xml_template.mMessage = desc;
00120 xml_template.mModal = TRUE;
00121 xml_template.mOptions.push_back("Quit");
00122 LLAlertDialog* dialog = new LLAlertDialog( &xml_template, args, callback, user_data);
00123 return dialog && dialog->show() ? dialog : NULL;
00124 }
00125
00126
00127
00128
00129 static const S32 VPAD = 16;
00130 static const S32 HPAD = 25;
00131 static const S32 BTN_HPAD = 8;
00132 static const LLFONT_ID font_name = LLFONT_SANSSERIF;
00133
00134 LLAlertDialog::LLAlertDialog( const LLAlertDialogTemplate* xml_template,
00135 const LLString::format_map_t& args,
00136 alert_callback_t callback, void *user_data)
00137 : LLModalDialog( xml_template->mTitle, 100, 100, xml_template->mModal ),
00138 mCallback( callback ),
00139 mUserData( user_data ),
00140 mNumOptions( 0 ),
00141 mDefaultOption( 0 ),
00142 mOptionChosen( -1 ),
00143 mCheck(NULL),
00144 mUnique(xml_template->mUnique),
00145 mIgnorable(xml_template->mIgnorable),
00146 mLabel(xml_template->mLabel),
00147 mIgnoreLabel(xml_template->mIgnoreLabel),
00148 mButtonData(NULL),
00149 mLineEditor(NULL),
00150 mTextCallback(NULL)
00151 {
00152 createDialog(&(xml_template->mOptions), xml_template->mDefaultOption,
00153 xml_template->mMessage, args,
00154 xml_template->mEditLineText);
00155 setTitle(xml_template->mTitle);
00156 if (xml_template->mIgnorable)
00157 {
00158 if (xml_template->mIgnorable == IGNORE_USE_DEFAULT)
00159 {
00160 setCheckBox(sStringSkipNextTime, xml_template->mIgnoreLabel);
00161 }
00162 else
00163 {
00164 setCheckBox(sStringAlwaysChoose, xml_template->mIgnoreLabel);
00165 }
00166 }
00167 }
00168
00169
00170
00171 bool LLAlertDialog::show()
00172 {
00173
00174
00175 if (sDisplayCallback)
00176 {
00177 bool show = sDisplayCallback(mModal);
00178 if (show == false)
00179 {
00180 mOptionChosen = mDefaultOption;
00181 llinfos << "Alert: " << mLabel << llendl;
00182 delete this;
00183 return false;
00184 }
00185 }
00186
00187
00188 if (mIgnorable > 0)
00189 {
00190 BOOL warn = sSettings->getWarning(mIgnoreLabel);
00191 if (!warn)
00192 {
00193 switch(mIgnorable)
00194 {
00195 case IGNORE_USE_DEFAULT:
00196 mOptionChosen = mDefaultOption;
00197 break;
00198 case IGNORE_USE_SAVED:
00199 mOptionChosen = sSettings->getS32("Default" + mIgnoreLabel);
00200 break;
00201 case IGNORE_SHOW_AGAIN:
00202 break;
00203 }
00204 delete this;
00205 return false;
00206 }
00207 }
00208
00209
00210 if (mUnique)
00211 {
00212 std::map<LLString,LLAlertDialog*>::iterator iter = sUniqueActiveMap.find(mLabel);
00213 if (iter != sUniqueActiveMap.end())
00214 {
00215 gFloaterView->bringToFront(iter->second);
00216 mUnique = FALSE;
00217 delete this;
00218 return false;
00219 }
00220 sUniqueActiveMap[mLabel] = this;
00221 }
00222 startModal();
00223 gFloaterView->adjustToFitScreen(this, FALSE);
00224 open();
00225 setFocus(TRUE);
00226 if (mLineEditor)
00227 {
00228 mLineEditor->setFocus(TRUE);
00229 mLineEditor->selectAll();
00230 }
00231 if(mDefaultOption >= 0)
00232 {
00233
00234 mDefaultBtnTimer.start();
00235 mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY);
00236 }
00237 return true;
00238 }
00239
00240
00241 void LLAlertDialog::format(LLString& msg, const LLString::format_map_t& args)
00242 {
00243
00244 LLString::format_map_t targs = args;
00245 targs["[SECOND_LIFE]"] = "Second Life";
00246 LLString::format(msg, targs);
00247 }
00248
00249 void LLAlertDialog::createDialog(const std::vector<LLString>* optionsp, S32 default_option,
00250 const LLString& msg_in, const LLString::format_map_t& args,
00251 const LLString& edit_text)
00252 {
00253 setBackgroundVisible(TRUE);
00254 setBackgroundOpaque(TRUE);
00255
00256 const LLFontGL* font = gResMgr->getRes( font_name );
00257 const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
00258 const S32 EDITOR_HEIGHT = 20;
00259
00260
00261 std::vector<LLString> default_option_list;
00262 mNumOptions = optionsp->size();
00263 if( 0 == mNumOptions )
00264 {
00265 default_option_list.push_back("Close");
00266 optionsp = &default_option_list;
00267 default_option = 0;
00268 mNumOptions = 1;
00269 }
00270
00271 const std::vector<LLString>& options = *optionsp;
00272 mButtonData = new ButtonData[mNumOptions];
00273
00274
00275 S32 button_width = 0;
00276 S32 sp = font->getWidth("OO");
00277 for( S32 i = 0; i < mNumOptions; i++ )
00278 {
00279 S32 w = S32(font->getWidth( options[i] ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD;
00280 button_width = llmax( w, button_width );
00281 }
00282 S32 btn_total_width = button_width;
00283 if( mNumOptions > 1 )
00284 {
00285 btn_total_width = (mNumOptions * button_width) + ((mNumOptions - 1) * BTN_HPAD);
00286 }
00287
00288
00289
00290 LLString msg = msg_in;
00291 LLAlertDialog::format( msg, args );
00292 llwarns << "Alert: " << msg << llendl;
00293 LLTextBox* msg_box = new LLTextBox( "Alert message", msg, (F32)MAX_ALLOWED_MSG_WIDTH, font );
00294
00295 const LLRect& text_rect = msg_box->getRect();
00296 S32 dialog_width = llmax( btn_total_width, text_rect.getWidth() ) + 2 * HPAD;
00297 S32 dialog_height = text_rect.getHeight() + 3 * VPAD + BTN_HEIGHT;
00298
00299 if (hasTitleBar())
00300 {
00301 dialog_height += LINE_HEIGHT;
00302 }
00303
00304 if (edit_text.size() > 0)
00305 {
00306 dialog_width = llmax(dialog_width, S32(font->getWidth( edit_text ) + 0.99f));
00307 dialog_height += EDITOR_HEIGHT;
00308 }
00309
00310 reshape( dialog_width, dialog_height, FALSE );
00311
00312 S32 msg_y = mRect.getHeight() - VPAD;
00313 if (hasTitleBar())
00314 {
00315 msg_y -= LINE_HEIGHT;
00316 }
00317
00318 LLRect rect;
00319 rect.setLeftTopAndSize( HPAD, msg_y, text_rect.getWidth(), text_rect.getHeight() );
00320 msg_box->setRect( rect );
00321 msg_box->setColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) );
00322 addChild(msg_box);
00323
00324
00325 S32 button_left = (mRect.getWidth() - btn_total_width) / 2;
00326
00327 for( S32 i = 0; i < mNumOptions; i++ )
00328 {
00329 LLRect button_rect;
00330 button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT );
00331
00332 LLButton* btn = new LLButton(
00333 "btn", button_rect,
00334 "","", "",
00335 &LLAlertDialog::onButtonPressed, (void*)(&mButtonData[i]),
00336 font,
00337 options[i],
00338 options[i]);
00339
00340 mButtonData[i].mSelf = this;
00341 mButtonData[i].mButton = btn;
00342 mButtonData[i].mOption = i;
00343
00344 addChild(btn);
00345
00346 if( i == default_option )
00347 {
00348 btn->setFocus(TRUE);
00349 }
00350
00351 button_left += button_width + BTN_HPAD;
00352 }
00353
00354
00355 if (edit_text.size() > 0)
00356 {
00357 S32 y = VPAD + BTN_HEIGHT + VPAD/2;
00358 mLineEditor = new LLLineEditor("lineeditor",
00359 LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y),
00360 edit_text,
00361 LLFontGL::sSansSerif,
00362 STD_STRING_STR_LEN);
00363 addChild(mLineEditor);
00364 }
00365 }
00366
00367 bool LLAlertDialog::setCheckBox( const LLString& check_title, const LLString& check_control )
00368 {
00369 const LLFontGL* font = gResMgr->getRes( font_name );
00370 const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
00371
00372
00373 S32 max_msg_width = mRect.getWidth() - 2 * HPAD;
00374 S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16;
00375 max_msg_width = llmax(max_msg_width, check_width);
00376 S32 dialog_width = max_msg_width + 2 * HPAD;
00377
00378 S32 dialog_height = mRect.getHeight();
00379 dialog_height += LINE_HEIGHT;
00380 dialog_height += LINE_HEIGHT / 2;
00381
00382 reshape( dialog_width, dialog_height, FALSE );
00383
00384 S32 msg_x = (mRect.getWidth() - max_msg_width) / 2;
00385
00386 LLRect check_rect;
00387 check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2,
00388 max_msg_width, LINE_HEIGHT);
00389
00390 mCheck = new LLCheckboxCtrl("check", check_rect, check_title, font);
00391 addChild(mCheck);
00392
00393
00394
00395 if (mIgnorable == IGNORE_SHOW_AGAIN)
00396 {
00397 mCheck->setValue(TRUE);
00398 }
00399
00400 return true;
00401 }
00402
00403 void LLAlertDialog::setVisible( BOOL visible )
00404 {
00405 LLModalDialog::setVisible( visible );
00406
00407 if( visible )
00408 {
00409 centerOnScreen();
00410 make_ui_sound("UISndAlert");
00411 }
00412 }
00413
00414 LLAlertDialog::~LLAlertDialog()
00415 {
00416 if (mOptionChosen >= 0)
00417 {
00418 if (mTextCallback && mLineEditor)
00419 {
00420 mTextCallback(mOptionChosen, mLineEditor->getText(), mUserData);
00421 }
00422 else if (mCallback)
00423 {
00424 mCallback(mOptionChosen, mUserData);
00425 }
00426
00427
00428 if (mCheck
00429 && sSettings->getWarning(mIgnoreLabel))
00430 {
00431
00432
00433 BOOL check = mCheck->getValue();
00434 switch(mIgnorable)
00435 {
00436 case IGNORE_USE_DEFAULT:
00437 sSettings->setWarning(mIgnoreLabel, !check);
00438 break;
00439 case IGNORE_USE_SAVED:
00440 sSettings->setWarning(mIgnoreLabel, !check);
00441 sSettings->setS32("Default" + mIgnoreLabel, mOptionChosen);
00442 break;
00443 case IGNORE_SHOW_AGAIN:
00444 sSettings->setWarning(mIgnoreLabel, check);
00445 break;
00446 default:
00447 break;
00448 }
00449 }
00450 }
00451 delete[] mButtonData;
00452 if (mUnique)
00453 {
00454 sUniqueActiveMap.erase(mLabel);
00455 }
00456 }
00457
00458 BOOL LLAlertDialog::hasTitleBar() const
00459 {
00460 return (getTitle() != "" && getTitle() != " ")
00461 || isMinimizeable()
00462 || isCloseable();
00463 }
00464
00465 BOOL LLAlertDialog::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
00466 {
00467 if( KEY_RETURN == key && mask == MASK_NONE )
00468 {
00469
00470
00471
00472
00473
00474 LLModalDialog::handleKeyHere( key, mask , called_from_parent );
00475 return TRUE;
00476 }
00477 else if (KEY_RIGHT == key)
00478 {
00479 focusNextItem(FALSE);
00480 return TRUE;
00481 }
00482 else if (KEY_LEFT == key)
00483 {
00484 focusPrevItem(FALSE);
00485 return TRUE;
00486 }
00487 else if (KEY_TAB == key && mask == MASK_NONE)
00488 {
00489 focusNextItem(FALSE);
00490 return TRUE;
00491 }
00492 else if (KEY_TAB == key && mask == MASK_SHIFT)
00493 {
00494 focusPrevItem(FALSE);
00495 return TRUE;
00496 }
00497 else
00498 {
00499 return LLModalDialog::handleKeyHere( key, mask , called_from_parent );
00500 }
00501 }
00502
00503
00504 void LLAlertDialog::draw()
00505 {
00506
00507 if(mDefaultBtnTimer.hasExpired() && mDefaultBtnTimer.getStarted())
00508 {
00509 mDefaultBtnTimer.stop();
00510 setDefaultBtn(mButtonData[mDefaultOption].mButton);
00511 }
00512 if (getVisible())
00513 {
00514 LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow");
00515 S32 shadow_lines = LLUI::sConfigGroup->getS32("DropShadowFloater");
00516
00517 gl_drop_shadow( 0, mRect.getHeight(), mRect.getWidth(), 0,
00518 shadow_color, shadow_lines);
00519
00520 LLModalDialog::draw();
00521 }
00522 }
00523
00524 void LLAlertDialog::setOptionEnabled( S32 option, BOOL enable )
00525 {
00526 if( (option >= 0) && (option < mNumOptions) )
00527 {
00528 mButtonData[option].mButton->setEnabled( enable );
00529 }
00530 }
00531
00532 void LLAlertDialog::setEditTextCallback(alert_text_callback_t callback, void *user_data)
00533 {
00534 if (mLineEditor)
00535 {
00536 mTextCallback = callback;
00537 mUserData = user_data;
00538 }
00539 else
00540 {
00541 llwarns << "LLAlertDialog::setEditTextCallback called on dialog with no line editor" << llendl;
00542 }
00543 }
00544
00545 void LLAlertDialog::setEditTextArgs(const LLString::format_map_t& edit_args)
00546 {
00547 if (mLineEditor)
00548 {
00549 LLString msg = mLineEditor->getText();
00550 LLAlertDialog::format(msg, edit_args);
00551 mLineEditor->setText(msg);
00552 }
00553 else
00554 {
00555 llwarns << "LLAlertDialog::setEditTextArgs called on dialog with no line editor" << llendl;
00556 }
00557 }
00558
00559 void LLAlertDialog::setDrawAsterixes(BOOL enable)
00560 {
00561 if (mLineEditor)
00562 {
00563 if (enable)
00564 {
00565 mLineEditor->clear();
00566 }
00567 mLineEditor->setDrawAsterixes(enable);
00568 }
00569 }
00570
00571
00572 void LLAlertDialog::onButtonPressed( void* userdata )
00573 {
00574 ButtonData* button_data = (ButtonData*)userdata;
00575 LLAlertDialog* self = button_data->mSelf;
00576
00577 self->mOptionChosen = button_data->mOption;
00578 self->close();
00579 }
00580
00581
00582
00583
00584 const LLString& LLAlertDialog::getTemplateMessage(const LLString& xml_desc)
00585 {
00586 template_map_t::iterator iter = sAlertTemplates.find(xml_desc);
00587 if (iter != sAlertTemplates.end())
00588 {
00589 return iter->second->mMessage;
00590 }
00591 else
00592 {
00593 return xml_desc;
00594 }
00595 }
00596
00597
00598 bool LLAlertDialog::parseAlerts(const LLString& xml_filename, LLControlGroup* settings, BOOL settings_only)
00599 {
00600 LLXMLNodePtr root;
00601 BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
00602
00603 if (!success || root.isNull() || !root->hasName( "alerts" ))
00604 {
00605 llerrs << "Problem reading UI Alerts file: " << xml_filename << llendl;
00606 return false;
00607 }
00608
00609 BOOL add_settings = FALSE;
00610 if (settings)
00611 {
00612 sSettings = settings;
00613 add_settings = TRUE;
00614 }
00615 llassert(sSettings);
00616
00617 for (LLXMLNode* alert = root->getFirstChild();
00618 alert != NULL; alert = alert->getNextSibling())
00619 {
00620 if (alert->hasName("global"))
00621 {
00622 LLString global_name;
00623 if (alert->getAttributeString("name", global_name))
00624 {
00625 if (global_name == "skipnexttime")
00626 {
00627 sStringSkipNextTime = alert->getTextContents();
00628 }
00629 else if (global_name == "alwayschoose")
00630 {
00631 sStringAlwaysChoose = alert->getTextContents();
00632 }
00633 }
00634 continue;
00635 }
00636
00637 if (!alert->hasName("alert"))
00638 {
00639 continue;
00640 }
00641
00642 LLAlertDialogTemplate* xml_template = settings_only ? NULL : new LLAlertDialogTemplate;
00643
00644
00645 LLString alert_name;
00646 if (alert->getAttributeString("name", alert_name))
00647 {
00648 if (xml_template)
00649 {
00650 xml_template->mLabel = alert_name;
00651 }
00652 }
00653 else
00654 {
00655 llwarns << "Unable to parse alert with no name" << llendl;
00656 delete xml_template;
00657 continue;
00658 }
00659
00660 LLString title;
00661 if (alert->getAttributeString("title", title))
00662 {
00663 if (xml_template)
00664 {
00665 xml_template->mTitle = title;
00666 }
00667 }
00668
00669 BOOL modal;
00670 if (alert->getAttributeBOOL("modal", modal))
00671 {
00672 if (xml_template)
00673 {
00674 xml_template->mModal = modal;
00675 }
00676 }
00677
00678 BOOL unique;
00679 if (alert->getAttributeBOOL("unique", unique))
00680 {
00681 if (xml_template)
00682 {
00683 xml_template->mUnique = unique;
00684 }
00685 }
00686
00687 S32 default_option = 0;
00688 BOOL nodefault;
00689 if (alert->getAttributeBOOL("nodefault", nodefault))
00690 {
00691 if (nodefault)
00692 {
00693 if (xml_template)
00694 {
00695 xml_template->mDefaultOption = -1;
00696 }
00697 default_option = -1;
00698 }
00699 }
00700
00701 S32 btn_idx = 0;
00702 for (LLXMLNode* child = alert->getFirstChild();
00703 child != NULL; child = child->getNextSibling())
00704 {
00705
00706 if (child->hasName("message"))
00707 {
00708 if (xml_template)
00709 {
00710 xml_template->mMessage = child->getTextContents();
00711 }
00712 }
00713
00714
00715 if (child->hasName("option"))
00716 {
00717 LLString label = child->getTextContents();
00718 BOOL is_default = FALSE;
00719 child->getAttributeBOOL("default", is_default);
00720 LLString ignore_text;
00721 if (!child->getAttributeString("ignore", ignore_text))
00722 {
00723 ignore_text = label;
00724 }
00725 if (xml_template)
00726 {
00727 xml_template->addOption(label, ignore_text, is_default);
00728 }
00729 if (is_default)
00730 {
00731 default_option = btn_idx;
00732 }
00733 btn_idx++;
00734 }
00735
00736
00737 if (child->hasName("editline"))
00738 {
00739 if (xml_template)
00740 {
00741 xml_template->mEditLineText = child->getTextContents();
00742 if (xml_template->mEditLineText.empty())
00743 {
00744 xml_template->mEditLineText = " ";
00745 }
00746 }
00747 }
00748
00749
00750 if (child->hasName("ignore"))
00751 {
00752 LLString ignore_text = child->getTextContents();
00753
00754 LLString name;
00755 child->getAttributeString("name", name);
00756
00757
00758
00759 name = alert_name;
00760
00761 if (xml_template)
00762 {
00763 xml_template->mIgnorable = LLAlertDialog::IGNORE_USE_DEFAULT;
00764 xml_template->mIgnoreListText = ignore_text;
00765 xml_template->mIgnoreLabel = name;
00766 }
00767 if (!ignore_text.empty())
00768 {
00769 if (add_settings)
00770 {
00771 settings->addWarning(name);
00772 }
00773 if (xml_template)
00774 {
00775 sIgnorableTemplates[name] = xml_template;
00776 }
00777 }
00778
00779 BOOL save_option = FALSE;
00780 child->getAttributeBOOL("save_option", save_option);
00781 if (save_option)
00782 {
00783 if (xml_template)
00784 {
00785 xml_template->mIgnorable = LLAlertDialog::IGNORE_USE_SAVED;
00786 }
00787 if (add_settings)
00788 {
00789 settings->declareS32("Default" + name, default_option, "Default option number for this alert dialog");
00790 }
00791 }
00792 }
00793 }
00794 if (xml_template)
00795 {
00796 xml_template->mDefaultOption = default_option;
00797 sAlertTemplates[xml_template->mLabel] = xml_template;
00798 }
00799 }
00800 return true;
00801 }