docs: private static void encodeURIQuery(Writer writer, final String string, int offset, final String characterEncoding)
              throws IOException
      {
          //StringBuilder sb = null;    //create later on demand
          int start = offset;
          int length = string.length();
          int realLength = length-offset;
          String app;
          char c;
          //boolean endLoop = false;
          for (int i = offset; i < length; ++i)
          {
              app = null;
              c = string.charAt(i);
              
              // - From %00 to %20 (' ' %20 could encode as +, but %20 also works, so we keep %20)
              // - <"> %22 (If there is encode of "%", there is a risk of duplicate encoding, so 
              //            we make easier and omit this one)
              // - "<" %3C, ">" %3E,
              // - "\" %5C, "^" %5E, "`" %60 
              // - "{" %7B, "|" %7C, "}" %7D
              // - From %7F ad infinitum (each character as many bytes as necessary but take into account
              //   that a single char should contain 2,3 or more bytes!. This data should be encoded 
              //   translating from the document character encoding to percent encoding)
              //
              // "&" should be encoded as "&amp;" because this link is inside an html page, and 
              // put & is invalid in this context   
              
              if (   (c <= (char)0x20) || (c >= (char)0x7F) || 
                      c == '"' || c == '<' ||
                      c == '>' || c == '\\' || c == '^' || c == '`' ||
                      c == '{' || c == '|' || c == '}')
              {
                  // The percent encoding on this part should be done using UTF-8 charset
                  // as RFC 3986 Section 3.2.2 says
                  //app = percentEncode(c, characterEncoding);
                  if (start < i)
                  {
                      writer.write(string, start, i-start);
                  }
                  start = i+1;
                  percentEncode(writer, c, characterEncoding);
              }
              else if (c == '%')
              {
                  if (i + 2 < length)
                  {
                      char c1 = string.charAt(i+1);
                      char c2 = string.charAt(i+2);
                      if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z') || (c1 >='a' && c1 <='z')) &&
                          (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z') || (c2 >='a' && c2 <='z')))
                      {
                          // do not percent encode, because it could be already encoded
                      }
                      else
                      {
                          //app = percentEncode(c, characterEncoding);
                          if (start < i)
                          {
                              writer.write(string, start, i-start);
                          }
                          start = i+1;
                          percentEncode(writer, c, characterEncoding);
                      }
                  }
                  else
                  {
                      //app = percentEncode(c, characterEncoding);
                      if (start < i)
                      {
                          writer.write(string, start, i-start);
                      }
                      start = i+1;
                      percentEncode(writer, c, characterEncoding);
                  }
              }
              else if (c == '&')
              {
                  if (i+4 < length )
                  {
                      if ('a' == string.charAt(i+1) &&
                          'm' == string.charAt(i+2) &&
                          'p' == string.charAt(i+3) &&
                          ';' == string.charAt(i+4))
                      {
                          //Skip
                      }
                      else
                      {
                          app = "&amp;";
                      }
                  }
                  else
                  {
                      app = "&amp;";
                  }
              }
              else
              {
                  //No encoding, just do nothing, char will be added later.
              }
                          
              if (app != null)
              {
                  //if (sb == null)
                  //{
                  //    sb = new StringBuilder(string.substring(0, i));
                  //}
                  //sb.append(app);
                  if (start < i)
                  {
                      writer.write(string, start, i-start);
                  }
                  start = i+1;
                  writer.write(app);
              }
              //else
              //{
              //    if (sb != null)
              //    {
              //        sb.append(c);
              //    }
              //}
              //if (endLoop)
              //{
              //    break;
              //}
          }
          
          //if (sb == null)
          //{
          //    return string;
          //}
          //else
          //{
          //    return sb.toString();
          //}
          if (start == offset)
          {
              writer.write(string, offset, realLength);
          }
          else if (start < length)
          {
              writer.write(string,start,length-start);
          }
      }