diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llui/llfloater.cpp | 265 |
1 files changed, 157 insertions, 108 deletions
diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp index bc5f197..02a410e 100644 --- a/linden/indra/llui/llfloater.cpp +++ b/linden/indra/llui/llfloater.cpp | |||
@@ -506,26 +506,25 @@ void LLFloater::setVisible( BOOL visible ) | |||
506 | } | 506 | } |
507 | } | 507 | } |
508 | 508 | ||
509 | LLView* LLFloater::getRootMostFastFrameView() | 509 | void LLFloater::open() /* Flawfinder: ignore */ |
510 | { | 510 | { |
511 | // trying to render a background floater in a fast frame, abort!!! | 511 | if (mSoundFlags != SILENT |
512 | //if (!isFrontmost()) | 512 | // don't play open sound for hosted (tabbed) windows |
513 | //{ | 513 | && !getHost() |
514 | // gViewerWindow->finishFastFrame(); | 514 | && !sHostp |
515 | //} | 515 | && (!getVisible() || isMinimized())) |
516 | 516 | { | |
517 | return LLView::getRootMostFastFrameView(); | 517 | make_ui_sound("UISndWindowOpen"); |
518 | } | 518 | } |
519 | 519 | ||
520 | void LLFloater::open() | ||
521 | { | ||
522 | //RN: for now, we don't allow rehosting from one multifloater to another | 520 | //RN: for now, we don't allow rehosting from one multifloater to another |
523 | // just need to fix the bugs | 521 | // just need to fix the bugs |
524 | LLMultiFloater* hostp = getHost(); | 522 | LLMultiFloater* hostp = getHost(); |
525 | if (sHostp != NULL && hostp == NULL) | 523 | if (sHostp != NULL && hostp == NULL) |
526 | { | 524 | { |
527 | // needs a host | 525 | // needs a host |
528 | sHostp->addFloater(this, TRUE); | 526 | // only select tabs if window they are hosted in is visible |
527 | sHostp->addFloater(this, sHostp->getVisible()); | ||
529 | } | 528 | } |
530 | else if (hostp != NULL) | 529 | else if (hostp != NULL) |
531 | { | 530 | { |
@@ -538,13 +537,7 @@ void LLFloater::open() | |||
538 | setVisibleAndFrontmost(mAutoFocus); | 537 | setVisibleAndFrontmost(mAutoFocus); |
539 | } | 538 | } |
540 | 539 | ||
541 | if (mSoundFlags != SILENT) | 540 | onOpen(); |
542 | { | ||
543 | if (!getVisible() || isMinimized()) | ||
544 | { | ||
545 | make_ui_sound("UISndWindowOpen"); | ||
546 | } | ||
547 | } | ||
548 | } | 541 | } |
549 | 542 | ||
550 | void LLFloater::close(bool app_quitting) | 543 | void LLFloater::close(bool app_quitting) |
@@ -562,6 +555,7 @@ void LLFloater::close(bool app_quitting) | |||
562 | 555 | ||
563 | if (mSoundFlags != SILENT | 556 | if (mSoundFlags != SILENT |
564 | && getVisible() | 557 | && getVisible() |
558 | && !getHost() | ||
565 | && !app_quitting) | 559 | && !app_quitting) |
566 | { | 560 | { |
567 | make_ui_sound("UISndWindowClose"); | 561 | make_ui_sound("UISndWindowClose"); |
@@ -689,7 +683,7 @@ const LLString& LLFloater::getTitle() const | |||
689 | 683 | ||
690 | void LLFloater::translate(S32 x, S32 y) | 684 | void LLFloater::translate(S32 x, S32 y) |
691 | { | 685 | { |
692 | LLView::translate(x, y); | 686 | LLPanel::translate(x, y); |
693 | 687 | ||
694 | if (x != 0 || y != 0) | 688 | if (x != 0 || y != 0) |
695 | { | 689 | { |
@@ -719,7 +713,7 @@ BOOL LLFloater::canSnapTo(LLView* other_view) | |||
719 | } | 713 | } |
720 | } | 714 | } |
721 | 715 | ||
722 | return LLView::canSnapTo(other_view); | 716 | return LLPanel::canSnapTo(other_view); |
723 | } | 717 | } |
724 | 718 | ||
725 | void LLFloater::snappedTo(LLView* snap_view) | 719 | void LLFloater::snappedTo(LLView* snap_view) |
@@ -783,8 +777,6 @@ void LLFloater::setMinimized(BOOL minimize) | |||
783 | 777 | ||
784 | if (minimize) | 778 | if (minimize) |
785 | { | 779 | { |
786 | mMinimized = TRUE; | ||
787 | |||
788 | mPreviousRect = mRect; | 780 | mPreviousRect = mRect; |
789 | 781 | ||
790 | reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE); | 782 | reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE); |
@@ -830,6 +822,8 @@ void LLFloater::setMinimized(BOOL minimize) | |||
830 | ++dependent_it; | 822 | ++dependent_it; |
831 | } | 823 | } |
832 | 824 | ||
825 | mMinimized = TRUE; | ||
826 | |||
833 | // Lose keyboard focus when minimized | 827 | // Lose keyboard focus when minimized |
834 | releaseFocus(); | 828 | releaseFocus(); |
835 | } | 829 | } |
@@ -1207,12 +1201,12 @@ void LLFloater::onClickTearOff(void *userdata) | |||
1207 | 1201 | ||
1208 | new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->mRect.getWidth(), self->mRect.getHeight()); | 1202 | new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->mRect.getWidth(), self->mRect.getHeight()); |
1209 | 1203 | ||
1210 | self->open(); | 1204 | self->open(); /* Flawfinder: ignore */ |
1211 | self->setRect(new_rect); | 1205 | self->setRect(new_rect); |
1212 | gFloaterView->adjustToFitScreen(self, FALSE); | 1206 | gFloaterView->adjustToFitScreen(self, FALSE); |
1213 | self->setCanDrag(TRUE); | 1207 | self->setCanDrag(TRUE); |
1214 | self->setCanResize(TRUE); | 1208 | // give focus to new window to keep continuity for the user |
1215 | self->setCanMinimize(TRUE); | 1209 | self->setFocus(TRUE); |
1216 | } | 1210 | } |
1217 | else //Attach to parent. | 1211 | else //Attach to parent. |
1218 | { | 1212 | { |
@@ -1234,24 +1228,36 @@ void LLFloater::onClickEdit(void *userdata) | |||
1234 | } | 1228 | } |
1235 | 1229 | ||
1236 | // static | 1230 | // static |
1237 | void LLFloater::closeByMenu( void* userdata ) | 1231 | void LLFloater::closeFocusedFloater() |
1238 | { | 1232 | { |
1239 | LLFloater* self = (LLFloater*) userdata; | 1233 | LLFloater* focused_floater = NULL; |
1240 | if (!self || self->getHost()) return; | ||
1241 | 1234 | ||
1242 | LLFloaterView* parent = (LLFloaterView*) self->getParent(); | 1235 | std::map<LLViewHandle, LLFloater*>::iterator iter; |
1236 | for(iter = sFloaterMap.begin(); iter != sFloaterMap.end(); ++iter) | ||
1237 | { | ||
1238 | focused_floater = iter->second; | ||
1239 | if (focused_floater->hasFocus()) | ||
1240 | { | ||
1241 | break; | ||
1242 | } | ||
1243 | } | ||
1243 | 1244 | ||
1244 | // grab focus status before close just in case floater is deleted | 1245 | if (iter == sFloaterMap.end()) |
1245 | BOOL has_focus = gFocusMgr.childHasKeyboardFocus(self); | 1246 | { |
1246 | self->close(); | 1247 | // nothing found, return |
1248 | return; | ||
1249 | } | ||
1250 | |||
1251 | focused_floater->close(); | ||
1247 | 1252 | ||
1248 | // if this floater used to have focus and now nothing took focus | 1253 | // if nothing took focus after closing focused floater |
1249 | // give it to next floater (to allow closing multiple windows via keyboard in rapid succession) | 1254 | // give it to next floater (to allow closing multiple windows via keyboard in rapid succession) |
1250 | if (has_focus && gFocusMgr.getKeyboardFocus() == NULL) | 1255 | if (gFocusMgr.getKeyboardFocus() == NULL) |
1251 | { | 1256 | { |
1252 | parent->focusFrontFloater(); | 1257 | // HACK: use gFloaterView directly in case we are using Ctrl-W to close snapshot window |
1258 | // which sits in gSnapshotFloaterView, and needs to pass focus on to normal floater view | ||
1259 | gFloaterView->focusFrontFloater(); | ||
1253 | } | 1260 | } |
1254 | |||
1255 | } | 1261 | } |
1256 | 1262 | ||
1257 | 1263 | ||
@@ -1351,10 +1357,26 @@ void LLFloater::draw() | |||
1351 | focused_child->setVisible(TRUE); | 1357 | focused_child->setVisible(TRUE); |
1352 | } | 1358 | } |
1353 | drawChild(focused_child); | 1359 | drawChild(focused_child); |
1360 | |||
1361 | // update tearoff button for torn off floaters | ||
1362 | // when last host goes away | ||
1363 | if (mCanTearOff && !getHost()) | ||
1364 | { | ||
1365 | LLFloater* old_host = gFloaterView->getFloaterByHandle(mLastHostHandle); | ||
1366 | if (!old_host) | ||
1367 | { | ||
1368 | setCanTearOff(FALSE); | ||
1369 | } | ||
1370 | } | ||
1354 | } | 1371 | } |
1355 | } | 1372 | } |
1356 | 1373 | ||
1357 | // virtual | 1374 | // virtual |
1375 | void LLFloater::onOpen() | ||
1376 | { | ||
1377 | } | ||
1378 | |||
1379 | // virtual | ||
1358 | void LLFloater::onClose(bool app_quitting) | 1380 | void LLFloater::onClose(bool app_quitting) |
1359 | { | 1381 | { |
1360 | destroy(); | 1382 | destroy(); |
@@ -2018,23 +2040,52 @@ void LLFloaterView::focusFrontFloater() | |||
2018 | 2040 | ||
2019 | void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) | 2041 | void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) |
2020 | { | 2042 | { |
2021 | // count the number of minimized children | 2043 | S32 col = 0; |
2022 | S32 count = 0; | 2044 | LLRect snap_rect_local = getSnapRect(); |
2023 | for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) | 2045 | snap_rect_local.translate(-mRect.mLeft, -mRect.mBottom); |
2024 | { | 2046 | for(S32 row = snap_rect_local.mBottom; |
2025 | LLView* viewp = *child_it; | 2047 | row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE; |
2026 | LLFloater *floater = (LLFloater *)viewp; | 2048 | row += LLFLOATER_HEADER_SIZE ) //loop rows |
2027 | if (floater->isMinimized()) | 2049 | { |
2028 | { | 2050 | for(col = snap_rect_local.mLeft; |
2029 | count++; | 2051 | col < snap_rect_local.getWidth() - MINIMIZED_WIDTH; |
2030 | } | 2052 | col += MINIMIZED_WIDTH) |
2053 | { | ||
2054 | bool foundGap = TRUE; | ||
2055 | for(child_list_const_iter_t child_it = getChildList()->begin(); | ||
2056 | child_it != getChildList()->end(); | ||
2057 | ++child_it) //loop floaters | ||
2058 | { | ||
2059 | // Examine minimized children. | ||
2060 | LLFloater* floater = (LLFloater*)((LLView*)*child_it); | ||
2061 | if(floater->isMinimized()) | ||
2062 | { | ||
2063 | LLRect r = floater->getRect(); | ||
2064 | if((r.mBottom < (row + LLFLOATER_HEADER_SIZE)) | ||
2065 | && (r.mBottom > (row - LLFLOATER_HEADER_SIZE)) | ||
2066 | && (r.mLeft < (col + MINIMIZED_WIDTH)) | ||
2067 | && (r.mLeft > (col - MINIMIZED_WIDTH))) | ||
2068 | { | ||
2069 | // needs the check for off grid. can't drag, | ||
2070 | // but window resize makes them off | ||
2071 | foundGap = FALSE; | ||
2072 | break; | ||
2073 | } | ||
2074 | } | ||
2075 | } //done floaters | ||
2076 | if(foundGap) | ||
2077 | { | ||
2078 | *left = col; | ||
2079 | *bottom = row; | ||
2080 | return; //done | ||
2081 | } | ||
2082 | } //done this col | ||
2031 | } | 2083 | } |
2032 | 2084 | ||
2033 | // space over for that many and up if necessary | 2085 | // crude - stack'em all at 0,0 when screen is full of minimized |
2034 | S32 tiles_per_row = mRect.getWidth() / MINIMIZED_WIDTH; | 2086 | // floaters. |
2035 | 2087 | *left = snap_rect_local.mLeft; | |
2036 | *left = (count % tiles_per_row) * MINIMIZED_WIDTH; | 2088 | *bottom = snap_rect_local.mBottom; |
2037 | *bottom = (count / tiles_per_row) * LLFLOATER_HEADER_SIZE; | ||
2038 | } | 2089 | } |
2039 | 2090 | ||
2040 | 2091 | ||
@@ -2211,7 +2262,7 @@ LLFloater *LLFloaterView::getFrontmost() | |||
2211 | for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) | 2262 | for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) |
2212 | { | 2263 | { |
2213 | LLView* viewp = *child_it; | 2264 | LLView* viewp = *child_it; |
2214 | if ( viewp->getVisible() ) | 2265 | if ( viewp->getVisible() && !viewp->isDead()) |
2215 | { | 2266 | { |
2216 | return (LLFloater *)viewp; | 2267 | return (LLFloater *)viewp; |
2217 | } | 2268 | } |
@@ -2423,31 +2474,11 @@ LLString LLMultiFloater::getWidgetTag() const | |||
2423 | return LL_MULTI_FLOATER_TAG; | 2474 | return LL_MULTI_FLOATER_TAG; |
2424 | } | 2475 | } |
2425 | 2476 | ||
2426 | void LLMultiFloater::init(const LLString& title, BOOL resizable, | 2477 | void LLMultiFloater::open() /* Flawfinder: ignore */ |
2427 | S32 min_width, S32 min_height, BOOL drag_on_left, | ||
2428 | BOOL minimizable, BOOL close_btn) | ||
2429 | { | ||
2430 | LLFloater::init(title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn); | ||
2431 | |||
2432 | /*mTabContainer = new LLTabContainer("Preview Tabs", | ||
2433 | LLRect(LLPANEL_BORDER_WIDTH, mRect.getHeight() - LLFLOATER_HEADER_SIZE, mRect.getWidth() - LLPANEL_BORDER_WIDTH, 0), | ||
2434 | mTabPos, | ||
2435 | NULL, | ||
2436 | NULL); | ||
2437 | mTabContainer->setFollowsAll(); | ||
2438 | if (mResizable && mTabPos == LLTabContainerCommon::BOTTOM) | ||
2439 | { | ||
2440 | mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); | ||
2441 | } | ||
2442 | |||
2443 | addChild(mTabContainer);*/ | ||
2444 | } | ||
2445 | |||
2446 | void LLMultiFloater::open() | ||
2447 | { | 2478 | { |
2448 | if (mTabContainer->getTabCount() > 0) | 2479 | if (mTabContainer->getTabCount() > 0) |
2449 | { | 2480 | { |
2450 | LLFloater::open(); | 2481 | LLFloater::open(); /* Flawfinder: ignore */ |
2451 | } | 2482 | } |
2452 | else | 2483 | else |
2453 | { | 2484 | { |
@@ -2519,16 +2550,9 @@ void LLMultiFloater::growToFit(LLFloater* floaterp, S32 width, S32 height) | |||
2519 | // store new width and height with this floater so that it will keep its size when detached | 2550 | // store new width and height with this floater so that it will keep its size when detached |
2520 | found_data_it->second.mWidth = width; | 2551 | found_data_it->second.mWidth = width; |
2521 | found_data_it->second.mHeight = height; | 2552 | found_data_it->second.mHeight = height; |
2522 | |||
2523 | S32 cur_height = mRect.getHeight(); | ||
2524 | reshape(llmax(mRect.getWidth(), width + LLPANEL_BORDER_WIDTH * 2), llmax(mRect.getHeight(), height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT + (LLPANEL_BORDER_WIDTH * 2))); | ||
2525 | |||
2526 | // make sure upper left corner doesn't move | ||
2527 | translate(0, mRect.getHeight() - cur_height); | ||
2528 | |||
2529 | // Try to keep whole view onscreen, don't allow partial offscreen. | ||
2530 | gFloaterView->adjustToFitScreen(this, FALSE); | ||
2531 | } | 2553 | } |
2554 | |||
2555 | resizeToContents(); | ||
2532 | } | 2556 | } |
2533 | 2557 | ||
2534 | /** | 2558 | /** |
@@ -2597,8 +2621,6 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, | |||
2597 | if ( select_added_floater ) | 2621 | if ( select_added_floater ) |
2598 | { | 2622 | { |
2599 | mTabContainer->selectLastTab(); | 2623 | mTabContainer->selectLastTab(); |
2600 | // explicitly call tabopen to load preview assets, etc. | ||
2601 | tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), true); | ||
2602 | } | 2624 | } |
2603 | 2625 | ||
2604 | floaterp->setHost(this); | 2626 | floaterp->setHost(this); |
@@ -2671,24 +2693,7 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp) | |||
2671 | 2693 | ||
2672 | if (mAutoResize) | 2694 | if (mAutoResize) |
2673 | { | 2695 | { |
2674 | floater_data_map_t::iterator floater_it; | 2696 | resizeToContents(); |
2675 | S32 new_width = 0; | ||
2676 | S32 new_height = 0; | ||
2677 | for (floater_it = mFloaterDataMap.begin(); floater_it != mFloaterDataMap.end(); ++floater_it) | ||
2678 | { | ||
2679 | new_width = llmax(new_width, floater_it->second.mWidth + LLPANEL_BORDER_WIDTH * 2); | ||
2680 | new_height = llmax(new_height, floater_it->second.mHeight + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT); | ||
2681 | } | ||
2682 | |||
2683 | S32 cur_height = mRect.getHeight(); | ||
2684 | |||
2685 | reshape(new_width, new_height); | ||
2686 | |||
2687 | // make sure upper left corner doesn't move | ||
2688 | translate(0, cur_height - new_height); | ||
2689 | |||
2690 | // Try to keep whole view onscreen, don't allow partial offscreen. | ||
2691 | gFloaterView->adjustToFitScreen(this, FALSE); | ||
2692 | } | 2697 | } |
2693 | 2698 | ||
2694 | tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); | 2699 | tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); |
@@ -2721,6 +2726,13 @@ void LLMultiFloater::setVisible(BOOL visible) | |||
2721 | { | 2726 | { |
2722 | cur_floaterp->setVisible(visible); | 2727 | cur_floaterp->setVisible(visible); |
2723 | } | 2728 | } |
2729 | |||
2730 | // if no tab selected, and we're being shown, | ||
2731 | // select last tab to be added | ||
2732 | if (visible && !cur_floaterp) | ||
2733 | { | ||
2734 | mTabContainer->selectLastTab(); | ||
2735 | } | ||
2724 | } | 2736 | } |
2725 | } | 2737 | } |
2726 | 2738 | ||
@@ -2823,6 +2835,43 @@ BOOL LLMultiFloater::postBuild() | |||
2823 | return FALSE; | 2835 | return FALSE; |
2824 | } | 2836 | } |
2825 | 2837 | ||
2838 | void LLMultiFloater::resizeToContents() | ||
2839 | { | ||
2840 | // we're already in the middle of a reshape, don't interrupt it | ||
2841 | floater_data_map_t::iterator floater_it; | ||
2842 | S32 new_width = 0; | ||
2843 | S32 new_height = 0; | ||
2844 | for (floater_it = mFloaterDataMap.begin(); floater_it != mFloaterDataMap.end(); ++floater_it) | ||
2845 | { | ||
2846 | new_width = llmax(new_width, floater_it->second.mWidth + LLPANEL_BORDER_WIDTH * 2); | ||
2847 | new_height = llmax(new_height, floater_it->second.mHeight + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT); | ||
2848 | } | ||
2849 | |||
2850 | S32 new_min_width = 0; | ||
2851 | S32 new_min_height = 0; | ||
2852 | S32 tab_idx; | ||
2853 | for (tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) | ||
2854 | { | ||
2855 | LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); | ||
2856 | if (floaterp) | ||
2857 | { | ||
2858 | new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); | ||
2859 | new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT); | ||
2860 | } | ||
2861 | } | ||
2862 | setResizeLimits(new_min_width, new_min_height); | ||
2863 | |||
2864 | S32 cur_height = mRect.getHeight(); | ||
2865 | |||
2866 | reshape(new_width, new_height); | ||
2867 | |||
2868 | // make sure upper left corner doesn't move | ||
2869 | translate(0, cur_height - new_height); | ||
2870 | |||
2871 | // Try to keep whole view onscreen, don't allow partial offscreen. | ||
2872 | gFloaterView->adjustToFitScreen(this, FALSE); | ||
2873 | } | ||
2874 | |||
2826 | // virtual | 2875 | // virtual |
2827 | LLXMLNodePtr LLFloater::getXML(bool save_children) const | 2876 | LLXMLNodePtr LLFloater::getXML(bool save_children) const |
2828 | { | 2877 | { |
@@ -2872,7 +2921,7 @@ LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f | |||
2872 | return floaterp; | 2921 | return floaterp; |
2873 | } | 2922 | } |
2874 | 2923 | ||
2875 | void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open) | 2924 | void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open) /* Flawfinder: ignore */ |
2876 | { | 2925 | { |
2877 | LLString name(getName()); | 2926 | LLString name(getName()); |
2878 | LLString title(getTitle()); | 2927 | LLString title(getTitle()); |
@@ -2946,8 +2995,8 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor | |||
2946 | } | 2995 | } |
2947 | 2996 | ||
2948 | applyRectControl(); | 2997 | applyRectControl(); |
2949 | if (open) | 2998 | if (open) /* Flawfinder: ignore */ |
2950 | { | 2999 | { |
2951 | this->open(); | 3000 | this->open(); /* Flawfinder: ignore */ |
2952 | } | 3001 | } |
2953 | } | 3002 | } |