| 10104 | |
| 10105 | |
| 10106 | int GuiType::FindTabIndexByName(GuiControlType &aTabControl, LPTSTR aName, bool aExactMatch) |
| 10107 | // Find the first tab in this tab control whose leading-part-of-name matches aName. |
| 10108 | // Return int vs. TabIndexType so that failure can be indicated. |
| 10109 | { |
| 10110 | int tab_count = TabCtrl_GetItemCount(aTabControl.hwnd); |
| 10111 | // Although strictly performing a leading-part-of-name match should technically cause |
| 10112 | // an empty string to result in the first item (index 0), it seems unlikely that a user |
| 10113 | // would expect that. The caller should verify *aName != 0. |
| 10114 | if (!tab_count || !*aName) |
| 10115 | return -1; // No match. |
| 10116 | |
| 10117 | TCITEM tci; |
| 10118 | tci.mask = TCIF_TEXT; |
| 10119 | TCHAR buf[1024]; |
| 10120 | tci.pszText = buf; |
| 10121 | tci.cchTextMax = _countof(buf) - 1; // MSDN example uses -1. |
| 10122 | |
| 10123 | size_t aName_length = _tcslen(aName); |
| 10124 | if (aName_length >= _countof(buf)) // Checking this early avoids having to check it in the loop. |
| 10125 | return -1; // No match possible. |
| 10126 | |
| 10127 | for (int i = 0; i < tab_count; ++i) |
| 10128 | { |
| 10129 | if (TabCtrl_GetItem(aTabControl.hwnd, i, &tci)) |
| 10130 | { |
| 10131 | if (aExactMatch) |
| 10132 | { |
| 10133 | if (!_tcsicmp(tci.pszText, aName)) // Match found. |
| 10134 | return i; |
| 10135 | } |
| 10136 | else |
| 10137 | { |
| 10138 | tci.pszText[aName_length] = '\0'; // Facilitates checking of only the leading part like strncmp(). Buffer overflow is impossible due to a check higher above. |
| 10139 | if (!lstrcmpi(tci.pszText, aName)) // Match found. |
| 10140 | return i; |
| 10141 | } |
| 10142 | } |
| 10143 | } |
| 10144 | |
| 10145 | // Since above didn't return, no match found. |
| 10146 | return -1; |
| 10147 | } |
| 10148 | |
| 10149 | |
| 10150 | |