docs: public static String resolveMacros(final String input, I_CmsMacroResolver resolver) {
  
          if ((input == null) || (input.length() < 3)) {
              // macro must have at last 3 chars "${}" or "%()"
              return input;
          }
  
          int pn = input.indexOf(I_CmsMacroResolver.MACRO_DELIMITER);
          int po = input.indexOf(I_CmsMacroResolver.MACRO_DELIMITER_OLD);
  
          if ((po == -1) && (pn == -1)) {
              // no macro delimiter found in input
              return input;
          }
  
          int len = input.length();
          StringBuffer result = new StringBuffer(len << 1);
          int np, pp1, pp2, e;
          String macro, value;
          boolean keep = resolver.isKeepEmptyMacros();
          boolean resolvedNone = true;
          char ds, de;
          int p;
  
          if ((po == -1) || ((pn > -1) && (pn < po))) {
              p = pn;
              ds = I_CmsMacroResolver.MACRO_START;
              de = I_CmsMacroResolver.MACRO_END;
          } else {
              p = po;
              ds = I_CmsMacroResolver.MACRO_START_OLD;
              de = I_CmsMacroResolver.MACRO_END_OLD;
          }
  
          // append chars before the first delimiter found
          result.append(input.substring(0, p));
          do {
              pp1 = p + 1;
              pp2 = pp1 + 1;
              if (pp2 >= len) {
                  // remaining chars can't be a macro (minimum size is 3)
                  result.append(input.substring(p, len));
                  break;
              }
              // get the next macro delimiter
              if ((pn > -1) && (pn < pp1)) {
                  pn = input.indexOf(I_CmsMacroResolver.MACRO_DELIMITER, pp1);
              }
              if ((po > -1) && (po < pp1)) {
                  po = input.indexOf(I_CmsMacroResolver.MACRO_DELIMITER_OLD, pp1);
              }
              if ((po == -1) && (pn == -1)) {
                  // none found, make sure remaining chars in this segment are appended
                  np = len;
              } else {
                  // check if the next delimiter is old or new style
                  if ((po == -1) || ((pn > -1) && (pn < po))) {
                      np = pn;
                  } else {
                      np = po;
                  }
              }
              // check if the next char is a "macro start"
              char st = input.charAt(pp1);
              if (st == ds) {
                  // we have a starting macro sequence "${" or "%(", now check if this segment contains a "}" or ")"
                  e = input.indexOf(de, p);
                  if ((e > 0) && (e < np)) {
                      // this segment contains a closing macro delimiter "}" or "]", so we may have found a macro
                      macro = input.substring(pp2, e);
                      // resolve macro
                      value = resolver.getMacroValue(macro);
                      e++;
                      if (value != null) {
                          // macro was successfully resolved
                          result.append(value);
                          resolvedNone = false;
                      } else if (keep) {
                          // macro was unknown, but should be kept
                          result.append(input.substring(p, e));
                      }
                  } else {
                      // no complete macro "${...}" or "%(...)" in this segment
                      e = p;
                  }
              } else {
                  // no macro start char after the "$" or "%"
                  e = p;
              }
              // set macro style for next delimiter found
              if (np == pn) {
                  ds = I_CmsMacroResolver.MACRO_START;
                  de = I_CmsMacroResolver.MACRO_END;
              } else {
                  ds = I_CmsMacroResolver.MACRO_START_OLD;
                  de = I_CmsMacroResolver.MACRO_END_OLD;
              }
              // append the remaining chars after the macro to the start of the next macro
              result.append(input.substring(e, np));
              // this is a nerdy joke ;-)
              p = np;
          } while (p < len);
  
          if (resolvedNone && keep) {
              // nothing was resolved and macros should be kept, return original input
              return input;
          }
  
          // input was changed during resolving of macros
          return result.toString();
      }