+// Helper function for uadatpg_remapPatternWithOptionsLoc
+static int32_t
+_doReplaceAndReturnAdj( UDateTimePatternGenerator *dtpg, uint32_t options, UBool matchHourLen,
+ UnicodeString &patternString, const UnicodeString &skeleton, const UnicodeString &otherCycSkeleton,
+ int32_t timePatStart, int32_t timePatLimit, int32_t timeNonHourStart, int32_t timeNonHourLimit,
+ UErrorCode *pErrorCode) {
+ if (matchHourLen) {
+ options |= UDATPG_MATCH_HOUR_FIELD_LENGTH;
+ }
+ UnicodeString replacement=((DateTimePatternGenerator *)dtpg)->getBestPattern(otherCycSkeleton, (UDateTimePatternMatchOptions)options, *pErrorCode);
+ if (U_FAILURE(*pErrorCode)) {
+ return 0;
+ }
+ UnicodeString stringForOrigSkeleton=((DateTimePatternGenerator *)dtpg)->getBestPattern(skeleton, UDATPG_MATCH_ALL_FIELDS_LENGTH, *pErrorCode); // match orig field lengths
+ if (U_SUCCESS(*pErrorCode)) {
+ int32_t index = patternString.indexOf(stringForOrigSkeleton);
+ if (index >= 0) {
+ int32_t stringForOrigSkelLen = stringForOrigSkeleton.length();
+ patternString.replace(index, stringForOrigSkelLen, replacement);
+ return replacement.length() - stringForOrigSkelLen;
+ }
+ } else {
+ *pErrorCode = U_ZERO_ERROR;
+ }
+ if (timeNonHourStart >= 0 && timeNonHourLimit > timeNonHourStart) {
+ // find any minutes/seconds/milliseconds part of replacement, set that back to the
+ // minutes/seconds/milliseconds part of the original pattern.
+ // First get the minutes/seconds/milliseconds part of the original pattern.
+ UnicodeString nonHour;
+ patternString.extractBetween(timeNonHourStart, timeNonHourLimit, nonHour);
+ // Now scan to find position from just after hours to end of minutes/seconds/milliseconds.
+ timeNonHourStart = -1;
+ timeNonHourLimit = 0;
+ UBool inQuoted = FALSE;
+ int32_t repPos, repLen = replacement.length();
+ for (repPos = 0; repPos < repLen; repPos++) {
+ UChar repChr = replacement.charAt(repPos);
+ if (repChr == 0x27 /* ASCII-range single quote */) {
+ inQuoted = !inQuoted;
+ } else if (!inQuoted) {
+ if (repChr==LOW_H || repChr==CAP_H || repChr==CAP_K || repChr==LOW_K) { // hHKk, hour
+ timeNonHourStart = repPos + 1;
+ } else if (timeNonHourStart < 0 && (repChr==LOW_M || repChr==LOW_S)) { // 'm' or 's' and we did not have hour
+ timeNonHourStart = repPos;
+ }
+ if (!u_isWhitespace(repChr) && timeNonHourStart >= 0 && repChr!=LOW_A) { // NonHour portion should not include 'a'
+ timeNonHourLimit = repPos + 1;
+ }
+ }
+ }
+ // If we found minutes/seconds/milliseconds in replacement, restore that part to original.
+ if (timeNonHourStart >= 0 && timeNonHourLimit > timeNonHourStart) {
+ replacement.replaceBetween(timeNonHourStart, timeNonHourLimit, nonHour);
+ }
+ }
+ patternString.replaceBetween(timePatStart, timePatLimit, replacement);
+ return replacement.length() - (timePatLimit - timePatStart); // positive if replacement is longer
+}
+
+/*
+ * uadatpg_remapPatternWithOptionsLoc
+ *
+ * Thee general idea is:
+ * 1. Scan the pattern for one or more time subpatterns
+ * 2. For each time subpattern, if the hour pattern characters don't match the
+ * time cycle that we want to force to, then:
+ * a) Save the nonHour portion of the subpattern (from just after hours to end
+ * of minutes/seconds/ milliseconds)
+ * b) Turn the pattern characters in that subpattern into a skeleton, but with
+ * the hour pattern characters switched to the desired time cycle
+ * c) Use that skeleton to get the locale's corresponding replacement pattern
+ * for the desired time cycle (with all desired elements - min, sec, etc.)
+ * d) In that replacement pattern, find the new nonHour portion, and restore
+ * that to the original nonHour portion
+ * e) Finally, replace the original time subpattern with the adjusted
+ * replacement.
+ */