| 1869 | |
| 1870 | |
| 1871 | void ParseClickOptions(LPTSTR aOptions, int &aX, int &aY, vk_type &aVK, KeyEventTypes &aEventType |
| 1872 | , int &aRepeatCount, bool &aMoveOffset) |
| 1873 | // Caller has trimmed leading whitespace from aOptions, but not necessarily the trailing whitespace. |
| 1874 | // aOptions must be a modifiable string because this function temporarily alters it. |
| 1875 | { |
| 1876 | // Set defaults for all output parameters for caller. |
| 1877 | aX = COORD_UNSPECIFIED; |
| 1878 | aY = COORD_UNSPECIFIED; |
| 1879 | aVK = VK_LBUTTON; |
| 1880 | aEventType = KEYDOWNANDUP; |
| 1881 | aRepeatCount = 1; |
| 1882 | aMoveOffset = false; |
| 1883 | |
| 1884 | TCHAR *next_option, *option_end, orig_char; |
| 1885 | vk_type temp_vk; |
| 1886 | |
| 1887 | for (next_option = aOptions; *next_option; next_option = omit_leading_whitespace(option_end)) |
| 1888 | { |
| 1889 | // Allow optional commas to make scripts more readable. Don't support g_delimiter because StrChrAny |
| 1890 | // below doesn't. |
| 1891 | while (*next_option == ',') // Ignore all commas. |
| 1892 | if (!*(next_option = omit_leading_whitespace(next_option + 1))) |
| 1893 | goto break_both; // Entire option string ends in a comma. |
| 1894 | // Find the end of this option item: |
| 1895 | if ( !(option_end = StrChrAny(next_option, _T(" \t,"))) ) // Space, tab, comma. |
| 1896 | option_end = next_option + _tcslen(next_option); // Set to position of zero terminator instead. |
| 1897 | |
| 1898 | // Temp termination for IsNumeric(), ConvertMouseButton(), and peace-of-mind. |
| 1899 | orig_char = *option_end; |
| 1900 | *option_end = '\0'; |
| 1901 | |
| 1902 | // Parameters can occur in almost any order to enhance usability (at the cost of |
| 1903 | // slightly diminishing the ability unambiguously add more parameters in the future). |
| 1904 | // Seems okay to support floats because ATOI() will just omit the decimal portion. |
| 1905 | if (IsNumeric(next_option, true, false, true)) |
| 1906 | { |
| 1907 | // Any numbers present must appear in the order: X, Y, RepeatCount |
| 1908 | // (optionally with other options between them). |
| 1909 | if (aX == COORD_UNSPECIFIED) // This will be converted into repeat-count if it is later discovered there's no Y coordinate. |
| 1910 | aX = ATOI(next_option); |
| 1911 | else if (aY == COORD_UNSPECIFIED) |
| 1912 | aY = ATOI(next_option); |
| 1913 | else // Third number is the repeat-count (but if there's only one number total, that's repeat count too, see further below). |
| 1914 | aRepeatCount = ATOI(next_option); // If negative or zero, caller knows to handle it as a MouseMove vs. Click. |
| 1915 | } |
| 1916 | else // Mouse button/name and/or Down/Up/Repeat-count is present. |
| 1917 | { |
| 1918 | if (temp_vk = Line::ConvertMouseButton(next_option, true)) |
| 1919 | aVK = temp_vk; |
| 1920 | else |
| 1921 | { |
| 1922 | switch (ctoupper(*next_option)) |
| 1923 | { |
| 1924 | case 'D': aEventType = KEYDOWN; break; |
| 1925 | case 'U': aEventType = KEYUP; break; |
| 1926 | case 'R': aMoveOffset = true; break; // Since it wasn't recognized as the right mouse button, it must have other letters after it, e.g. Rel/Relative. |
| 1927 | // default: Ignore anything else to reserve them for future use. |
| 1928 | } |
no test coverage detected