/** * Runs a MIDlet from an installed MIDlet suite. This is an example of * how to use the public MIDP API. * * @param argc The total number of arguments * @param argv An array of 'C' strings containing the arguments * * @return <tt>0</tt> for success, otherwise <tt>-1</tt> * * IMPL_NOTE:determine if it is desirable for user targeted output * messages to be sent via the log/trace service, or if * they should remain as printf calls */ int runMidlet(int argc, char** commandlineArgs) { int status = -1; SuiteIdType suiteId = UNUSED_SUITE_ID; pcsl_string classname = PCSL_STRING_NULL; pcsl_string arg0 = PCSL_STRING_NULL; pcsl_string arg1 = PCSL_STRING_NULL; pcsl_string arg2 = PCSL_STRING_NULL; int repeatMidlet = 0; char* argv[RUNMIDLET_MAX_ARGS]; int i, used; int debugOption = MIDP_NO_DEBUG; char *progName = commandlineArgs[0]; char* appDir = NULL; char* confDir = NULL; char* additionalPath; SuiteIdType* pSuites = NULL; int numberOfSuites = 0; int ordinalSuiteNumber = -1; char* chSuiteNum = NULL; MIDPError errCode; char** ppParamsFromPlatform; char** ppSavedParams = NULL; int savedNumberOfParams = 0, numberOfParams = 0; JVM_Initialize(); /* It's OK to call this more than once */ /* get midp application directory, set it */ appDir = getApplicationDir(argv[0]); if (appDir == NULL) { REPORT_ERROR(LC_AMS, "Failed to recieve midp application directory"); return -1; } midpSetAppDir(appDir); /* get midp configuration directory, set it */ confDir = getConfigurationDir(argv[0]); if (confDir == NULL) { REPORT_ERROR(LC_AMS, "Failed to recieve midp configuration directory"); return -1; } midpSetConfigDir(confDir); if (midpInitialize() != 0) { REPORT_ERROR(LC_AMS, "Not enough memory"); return -1; } /* Set Java heap parameters now so they can been overridden from command line */ setHeapParameters(); /* * Check if there are some parameters passed to us from the platform * (i.e., in the current implementation, they are read from a file). */ errCode = ams_get_startup_params(&ppParamsFromPlatform, &numberOfParams); if (errCode == ALL_OK && numberOfParams > 0) { savedNumberOfParams = numberOfParams; ppSavedParams = ppParamsFromPlatform; while ((used = JVM_ParseOneArg(numberOfParams, ppParamsFromPlatform)) > 0) { numberOfParams -= used; ppParamsFromPlatform += used; } if (numberOfParams + 1 > RUNMIDLET_MAX_ARGS) { REPORT_ERROR(LC_AMS, "(1) Number of arguments exceeds supported limit"); ams_free_startup_params(ppSavedParams, savedNumberOfParams); return -1; } argv[0] = progName; for (i = 0; i < numberOfParams; i++) { /* argv[0] is the program name */ argv[i + 1] = ppParamsFromPlatform[i]; } } /* if savedNumberOfParams > 0, ignore the command-line parameters */ if (savedNumberOfParams <= 0) { /* * Debugger port: command-line argument overrides * configuration settings. */ { char* debuggerPortString = midpRemoveCommandOption("-port", commandlineArgs, &argc); if (debuggerPortString != NULL) { int debuggerPort; if (sscanf(debuggerPortString, "%d", &debuggerPort) != 1) { REPORT_ERROR(LC_AMS, "Invalid debugger port format"); return -1; } setInternalProperty("VmDebuggerPort", debuggerPortString); } } /* * Parse options for the VM. This is desirable on a 'development' platform * such as linux_qte. For actual device ports, copy this block of code only * if your device can handle command-line arguments. */ /* * JVM_ParseOneArg expects commandlineArgs[0] to contain the first actual * parameter */ argc --; commandlineArgs ++; while ((used = JVM_ParseOneArg(argc, commandlineArgs)) > 0) { argc -= used; commandlineArgs += used; } /* Restore commandlineArgs[0] to contain the program name. */ argc ++; commandlineArgs --; commandlineArgs[0] = progName; } /* * Not all platforms allow rewriting the command line arg array, * make a copy */ if ((numberOfParams <= 0 && argc > RUNMIDLET_MAX_ARGS) || (numberOfParams > RUNMIDLET_MAX_ARGS)) { REPORT_ERROR(LC_AMS, "Number of arguments exceeds supported limit"); ams_free_startup_params(ppSavedParams, savedNumberOfParams); return -1; } if (savedNumberOfParams <= 0) { for (i = 0; i < argc; i++) { argv[i] = commandlineArgs[i]; } } else { /* * if savedNumberOfParams is greater than zero, command-line parameters * are ignored */ argc = numberOfParams + 1; /* +1 because argv[0] is the program name */ } /* * IMPL_NOTE: corresponding VM option is called "-debugger" */ if (midpRemoveOptionFlag("-debug", argv, &argc) != NULL) { debugOption = MIDP_DEBUG_SUSPEND; } if (midpRemoveOptionFlag("-loop", argv, &argc) != NULL) { repeatMidlet = 1; } /* run the midlet suite by its ordinal number */ if ((chSuiteNum = midpRemoveCommandOption("-ordinal", argv, &argc)) != NULL) { /* the format of the string is "number:" */ if (sscanf(chSuiteNum, "%d", &ordinalSuiteNumber) != 1) { REPORT_ERROR(LC_AMS, "Invalid suite number format"); ams_free_startup_params(ppSavedParams, savedNumberOfParams); return -1; } } /* additionalPath gets appended to the classpath */ additionalPath = midpRemoveCommandOption("-classpathext", argv, &argc); if (argc == 1 && ordinalSuiteNumber == -1) { REPORT_ERROR(LC_AMS, "Too few arguments given."); ams_free_startup_params(ppSavedParams, savedNumberOfParams); return -1; } if (argc > 6) { REPORT_ERROR(LC_AMS, "Too many arguments given\n"); ams_free_startup_params(ppSavedParams, savedNumberOfParams); return -1; } do { int onlyDigits; int len; int i; if (argc > 5) { if (PCSL_STRING_OK != pcsl_string_from_chars(argv[5], &arg2)) { REPORT_ERROR(LC_AMS, "Out of Memory"); break; } } if (argc > 4) { if (PCSL_STRING_OK != pcsl_string_from_chars(argv[4], &arg1)) { REPORT_ERROR(LC_AMS, "Out of Memory"); break; } } if (argc > 3) { if (PCSL_STRING_OK != pcsl_string_from_chars(argv[3], &arg0)) { REPORT_ERROR(LC_AMS, "Out of Memory"); break; } } if (argc > 2) { if (PCSL_STRING_OK != pcsl_string_from_chars(argv[2], &classname)) { REPORT_ERROR(LC_AMS, "Out of Memory"); break; } } /* if the storage name only digits, convert it */ onlyDigits = 1; len = strlen(argv[1]); for (i = 0; i < len; i++) { if (!isdigit((argv[1])[i])) { onlyDigits = 0; break; } } if (ordinalSuiteNumber != -1 || onlyDigits) { /* load IDs of the installed suites */ MIDPError err = midp_get_suite_ids(&pSuites, &numberOfSuites); if (err != ALL_OK) { REPORT_ERROR1(LC_AMS, "Error in midp_get_suite_ids(), code %d", err); break; } } if (ordinalSuiteNumber != -1) { /* run the midlet suite by its ordinal number */ if (ordinalSuiteNumber > numberOfSuites || ordinalSuiteNumber < 1) { REPORT_ERROR(LC_AMS, "Suite number out of range"); midp_free_suite_ids(pSuites, numberOfSuites); break; } suiteId = pSuites[ordinalSuiteNumber - 1]; } else if (onlyDigits) { /* run the midlet suite by its ID */ int i; /* the format of the string is "number:" */ if (sscanf(argv[1], "%d", &suiteId) != 1) { REPORT_ERROR(LC_AMS, "Invalid suite ID format"); break; } for (i = 0; i < numberOfSuites; i++) { if (suiteId == pSuites[i]) { break; } } if (i == numberOfSuites) { REPORT_ERROR(LC_AMS, "Suite with the given ID was not found"); break; } } else { /* Run by ID */ suiteId = INTERNAL_SUITE_ID; if (strcmp(argv[1], "internal") && strcmp(argv[1], "-1") && additionalPath == NULL) { /* * If the argument is not a suite ID, it might be a full * path to the midlet suite's jar file. * In this case this path is added to the classpath and * the suite is run without installation (it is useful * for internal test and development purposes). */ additionalPath = argv[1]; } } if (pcsl_string_is_null(&classname)) { int res = find_midlet_class(suiteId, 1, &classname); if (OUT_OF_MEM_LEN == res) { REPORT_ERROR(LC_AMS, "Out of Memory"); break; } if (NULL_LEN == res) { REPORT_ERROR(LC_AMS, "Could not find the first MIDlet"); break; } } do { status = midp_run_midlet_with_args_cp(suiteId, &classname, &arg0, &arg1, &arg2, debugOption, additionalPath); } while (repeatMidlet && status != MIDP_SHUTDOWN_STATUS); if (pSuites != NULL) { midp_free_suite_ids(pSuites, numberOfSuites); suiteId = UNUSED_SUITE_ID; } } while (0); pcsl_string_free(&arg0); pcsl_string_free(&arg1); pcsl_string_free(&arg2); pcsl_string_free(&classname); switch (status) { case MIDP_SHUTDOWN_STATUS: break; case MIDP_ERROR_STATUS: REPORT_ERROR(LC_AMS, "The MIDlet suite could not be run."); break; case SUITE_NOT_FOUND_STATUS: REPORT_ERROR(LC_AMS, "The MIDlet suite was not found."); break; default: break; } if (JVM_GetConfig(JVM_CONFIG_SLAVE_MODE) == KNI_FALSE) { midpFinalize(); } ams_free_startup_params(ppSavedParams, savedNumberOfParams); return status; }
/** Sets new value of MAX_ISOLATES property */ static void setMaxIsolates(int value) { char valueStr[5]; sprintf(valueStr, "%d", value); setInternalProperty("MAX_ISOLATES", valueStr); }
StdWidgetFactory::StdWidgetFactory(QObject *parent, const char *, const QStringList &) : KFormDesigner::WidgetFactory(parent, "stdwidgets") { KFormDesigner::WidgetInfo *wFormWidget = new KFormDesigner::WidgetInfo(this); wFormWidget->setPixmap("form"); wFormWidget->setClassName("FormWidgetBase"); wFormWidget->setName(i18n("Form")); wFormWidget->setNamePrefix(i18n("This string will be used to name widgets of this class. It must _not_ contain white " "spaces and non latin1 characters.", "form")); wFormWidget->setDescription(i18n("A simple form widget")); addClass(wFormWidget); KFormDesigner::WidgetInfo *wCustomWidget = new KFormDesigner::WidgetInfo(this); wCustomWidget->setPixmap("unknown_widget"); wCustomWidget->setClassName("CustomWidget"); wCustomWidget->setName(i18n("Custom Widget")); wCustomWidget->setNamePrefix(i18n("This string will be used to name widgets of this class. It must _not_ contain white " "spaces and non latin1 characters.", "customWidget")); wCustomWidget->setDescription(i18n("A custom or non-supported widget")); addClass(wCustomWidget); KFormDesigner::WidgetInfo *wLabel = new KFormDesigner::WidgetInfo(this); wLabel->setPixmap("label"); wLabel->setClassName("QLabel"); wLabel->setName(i18n("Text Label")); wLabel->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "label")); wLabel->setDescription(i18n("A widget to display text")); addClass(wLabel); KFormDesigner::WidgetInfo *wPixLabel = new KFormDesigner::WidgetInfo(this); wPixLabel->setPixmap("pixmaplabel"); wPixLabel->setClassName("KexiPictureLabel"); wPixLabel->setName(i18n("Picture Label")); //! @todo Qt designer compatibility: maybe use this class when QLabel has a pixmap set...? //wPixLabel->addAlternateClassName("QLabel"); wPixLabel->setSavingName("KexiPictureLabel"); wPixLabel->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "picture")); wPixLabel->setDescription(i18n("A widget to display pictures")); addClass(wPixLabel); KFormDesigner::WidgetInfo *wLineEdit = new KFormDesigner::WidgetInfo(this); wLineEdit->setPixmap("lineedit"); wLineEdit->setClassName("KLineEdit"); wLineEdit->addAlternateClassName("QLineEdit"); wLineEdit->setIncludeFileName("klineedit.h"); wLineEdit->setName(i18n("Line Edit")); wLineEdit->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "lineEdit")); wLineEdit->setDescription(i18n("A widget to input text")); addClass(wLineEdit); KFormDesigner::WidgetInfo *wSpring = new KFormDesigner::WidgetInfo(this); wSpring->setPixmap("spring"); wSpring->setClassName("Spring"); wSpring->setName(i18n("Spring")); wSpring->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "spring")); wSpring->setDescription(i18n("A spring to place between widgets")); addClass(wSpring); KFormDesigner::WidgetInfo *wPushButton = new KFormDesigner::WidgetInfo(this); wPushButton->setPixmap("button"); wPushButton->setClassName("KPushButton"); wPushButton->addAlternateClassName("QPushButton"); wPushButton->setIncludeFileName("kpushbutton.h"); wPushButton->setName(i18n("Push Button")); wPushButton->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "button")); wPushButton->setDescription(i18n("A simple push button to execute actions")); addClass(wPushButton); KFormDesigner::WidgetInfo *wRadioButton = new KFormDesigner::WidgetInfo(this); wRadioButton->setPixmap("radio"); wRadioButton->setClassName("QRadioButton"); wRadioButton->setName(i18n("Option Button")); wRadioButton->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "optionButton")); wRadioButton->setDescription(i18n("An option button with text or pixmap label")); addClass(wRadioButton); KFormDesigner::WidgetInfo *wCheckBox = new KFormDesigner::WidgetInfo(this); wCheckBox->setPixmap("check"); wCheckBox->setClassName("QCheckBox"); wCheckBox->setName(i18n("Check Box")); wCheckBox->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "checkBox")); wCheckBox->setDescription(i18n("A check box with text or pixmap label")); addClass(wCheckBox); KFormDesigner::WidgetInfo *wSpinBox = new KFormDesigner::WidgetInfo(this); wSpinBox->setPixmap("spin"); wSpinBox->setClassName("KIntSpinBox"); wSpinBox->addAlternateClassName("QSpinBox"); wSpinBox->setIncludeFileName("knuminput.h"); wSpinBox->setName(i18n("Spin Box")); wSpinBox->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "spinBox")); wSpinBox->setDescription(i18n("A spin box widget")); addClass(wSpinBox); KFormDesigner::WidgetInfo *wComboBox = new KFormDesigner::WidgetInfo(this); wComboBox->setPixmap("combo"); wComboBox->setClassName("KComboBox"); wComboBox->addAlternateClassName("QComboBox"); wComboBox->setIncludeFileName("kcombobox.h"); wComboBox->setName(i18n("Combo Box")); wComboBox->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "comboBox")); wComboBox->setDescription(i18n("A combo box widget")); addClass(wComboBox); KFormDesigner::WidgetInfo *wListBox = new KFormDesigner::WidgetInfo(this); wListBox->setPixmap("listbox"); wListBox->setClassName("KListBox"); wListBox->addAlternateClassName("QListBox"); wListBox->setIncludeFileName("klistbox.h"); wListBox->setName(i18n("List Box")); wListBox->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "listBox")); wListBox->setDescription(i18n("A simple list widget")); addClass(wListBox); KFormDesigner::WidgetInfo *wTextEdit = new KFormDesigner::WidgetInfo(this); wTextEdit->setPixmap("textedit"); wTextEdit->setClassName("KTextEdit"); wTextEdit->addAlternateClassName("QTextEdit"); wTextEdit->setIncludeFileName("ktextedit.h"); wTextEdit->setName(i18n("Text Editor")); wTextEdit->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "textEditor")); wTextEdit->setDescription(i18n("A simple single-page rich text editor")); addClass(wTextEdit); KFormDesigner::WidgetInfo *wListView = new KFormDesigner::WidgetInfo(this); wListView->setPixmap("listview"); wListView->setClassName("KListView"); wListView->addAlternateClassName("QListView"); wListView->setIncludeFileName("klistview.h"); wListView->setName(i18n("List View")); wListView->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "listView")); wListView->setDescription(i18n("A list (or tree) widget")); addClass(wListView); KFormDesigner::WidgetInfo *wSlider = new KFormDesigner::WidgetInfo(this); wSlider->setPixmap("slider"); wSlider->setClassName("QSlider"); wSlider->setName(i18n("Slider")); wSlider->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "slider")); wSlider->setDescription(i18n("An horizontal slider")); addClass(wSlider); KFormDesigner::WidgetInfo *wProgressBar = new KFormDesigner::WidgetInfo(this); wProgressBar->setPixmap("progress"); wProgressBar->setClassName("KProgress"); wProgressBar->addAlternateClassName("QProgressBar"); wProgressBar->setIncludeFileName("kprogress.h"); wProgressBar->setName(i18n("Progress Bar")); wProgressBar->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "progressBar")); wProgressBar->setDescription(i18n("A progress indicator widget")); addClass(wProgressBar); KFormDesigner::WidgetInfo *wLine = new KFormDesigner::WidgetInfo(this); wLine->setPixmap("line"); wLine->setClassName("Line"); wLine->setName(i18n("Line")); wLine->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "line")); wLine->setDescription(i18n("A line to be used as a separator")); addClass(wLine); KFormDesigner::WidgetInfo *wDate = new KFormDesigner::WidgetInfo(this); wDate->setPixmap("dateedit"); wDate->setClassName("KDateWidget"); #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9) wDate->addAlternateClassName("QDateEdit"); wDate->setIncludeFileName("kdatewidget.h"); #endif wDate->setName(i18n("Date Widget")); wDate->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "dateWidget")); wDate->setDescription(i18n("A widget to input and display a date")); addClass(wDate); KFormDesigner::WidgetInfo *wTime = new KFormDesigner::WidgetInfo(this); wTime->setPixmap("timeedit"); wTime->setClassName("KTimeWidget"); #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9) wTime->addAlternateClassName("QTimeEdit"); wTime->setIncludeFileName("ktimewidget.h"); #endif wTime->setName(i18n("Time Widget")); wTime->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "timeWidget")); wTime->setDescription(i18n("A widget to input and display a time")); addClass(wTime); KFormDesigner::WidgetInfo *wDateTime = new KFormDesigner::WidgetInfo(this); wDateTime->setPixmap("datetimeedit"); wDateTime->setClassName("KDateTimeWidget"); #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9) wDateTime->addAlternateClassName("QDateTimeEdit"); wDateTime->setIncludeFileName("kdatetimewidget.h"); #endif wDateTime->setName(i18n("Date/Time Widget")); wDateTime->setNamePrefix( i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters.", "dateTimeWidget")); wDateTime->setDescription(i18n("A widget to input and display a time and a date")); addClass(wDateTime); m_propDesc["toggleButton"] = i18n("Toggle"); m_propDesc["autoRepeat"] = i18n("Auto Repeat"); m_propDesc["autoDefault"] = i18n("Auto Default"); m_propDesc["default"] = i18n("Default"); m_propDesc["flat"] = i18n("Flat"); m_propDesc["echoMode"] = i18n("Echo mode for Line Edit widget eg. Normal, NoEcho, Password","Echo Mode"); m_propDesc["indent"] = i18n("Indent"); //line m_propDesc["orientation"] = i18n("Orientation"); //checkbox m_propDesc["checked"] = i18n("Checked checkbox", "Checked"); m_propDesc["tristate"] = i18n("Tristate checkbox", "Tristate"); //for EchoMode m_propValDesc["Normal"] = i18n("For Echo Mode", "Normal"); m_propValDesc["NoEcho"] = i18n("For Echo Mode", "No Echo"); m_propValDesc["Password"] = i18n("For Echo Mode", "Password"); //for spring m_propDesc["sizeType"] = i18n("Size Type"); //for labels m_propDesc["textFormat"] = i18n("Text Format"); m_propValDesc["PlainText"] = i18n("For Text Format", "Plain"); m_propValDesc["RichText"] = i18n("For Text Format", "Hypertext"); m_propValDesc["AutoText"] = i18n("For Text Format", "Auto"); m_propValDesc["LogText"] = i18n("For Text Format", "Log"); //KTextEdit m_propDesc["tabStopWidth"] = i18n("Tab Stop Width"); m_propDesc["tabChangesFocus"] = i18n("Tab Changes Focus"); m_propDesc["wrapPolicy"] = i18n("Word Wrap Policy"); m_propValDesc["AtWordBoundary"] = i18n("For Word Wrap Policy", "At Word Boundary"); m_propValDesc["Anywhere"] = i18n("For Word Wrap Policy", "Anywhere"); m_propValDesc["AtWordOrDocumentBoundary"] = i18n("For Word Wrap Policy", "At Word Boundary If Possible"); m_propDesc["wordWrap"] = i18n("Word Wrapping"); m_propDesc["wrapColumnOrWidth"] = i18n("Word Wrap Position"); m_propValDesc["NoWrap"] = i18n("For Word Wrap Position", "None"); m_propValDesc["WidgetWidth"] = i18n("For Word Wrap Position", "Widget's Width"); m_propValDesc["FixedPixelWidth"] = i18n("For Word Wrap Position", "In Pixels"); m_propValDesc["FixedColumnWidth"] = i18n("For Word Wrap Position", "In Columns"); m_propDesc["linkUnderline"] = i18n("Links Underlined"); //internal props setInternalProperty("Line","orientationSelectionPopup","1"); setInternalProperty("Line","orientationSelectionPopup:horizontalIcon","line_horizontal"); setInternalProperty("Line","orientationSelectionPopup:verticalIcon","line_vertical"); setInternalProperty("Line","orientationSelectionPopup:horizontalText",i18n("Insert &Horizontal Line")); setInternalProperty("Line","orientationSelectionPopup:verticalText",i18n("Insert &Vertical Line")); setInternalProperty("Spring","orientationSelectionPopup","1"); setInternalProperty("Spring","orientationSelectionPopup:horizontalIcon","spring"); setInternalProperty("Spring","orientationSelectionPopup:verticalIcon","spring_vertical"); setInternalProperty("Spring","orientationSelectionPopup:horizontalText",i18n("Insert &Horizontal Spring")); setInternalProperty("Spring","orientationSelectionPopup:verticalText",i18n("Insert &Vertical Spring")); }