create procedure lib_string_sub_pre15 (
                     strg_in varchar( 32765),
                     strg_beg smallint,
                     strg_len smallint)
                   returns (
                     strg_out varchar( 32765))
  as
    declare variable strg_cmp varchar( 32765);
    declare variable pos smallint;
    declare variable chr char(1);

    begin
      /*
        contributed by Lucas Franzen
        no need for dbms support of
        substring sql command functions
        on older interbase / firebird versions (pre 1.5)

        caution:
        the characters in the comparison part of the code
        are not converted to their corresponding html sequences,
        so check them before compilation
      */

      if (   (strg_in is null)
          or (strg_beg is null)
          or (strg_beg <= 0)
          or (strg_len is null)
          or (strg_len <= 0))
        then
          strg_out = null;
        else
          begin
            strg_out = '';
            strg_cmp = '';
            pos = 1;

            while (pos < strg_beg) do
              begin
                strg_cmp = strg_cmp || '_';
                pos = pos + 1;
              end

            while (pos < strg_beg + strg_len) do
              begin
                     if (strg_in like strg_cmp || ' %') then chr = ' ';
                else if (strg_in like strg_cmp || '!%') then chr = '!';
                else if (strg_in like strg_cmp || '"%') then chr = '"';
                else if (strg_in like strg_cmp || '#%') then chr = '#';
                else if (strg_in like strg_cmp || '$%') then chr = '$';
                else if (strg_in like strg_cmp || '&%') then chr = '&';
                else if (strg_in like strg_cmp || '''%') then chr = '''';
                else if (strg_in like strg_cmp || '(%') then chr = '(';
                else if (strg_in like strg_cmp || ')%') then chr = ')';
                else if (strg_in like strg_cmp || '*%') then chr = '*';
                else if (strg_in like strg_cmp || '+%') then chr = '+';
                else if (strg_in like strg_cmp || ',%') then chr = ',';
                else if (strg_in like strg_cmp || '-%') then chr = '-';
                else if (strg_in like strg_cmp || '.%') then chr = '.';
                else if (strg_in like strg_cmp || '/%') then chr = '/';

                else if (strg_in like strg_cmp || '0%') then chr = '0';
                else if (strg_in like strg_cmp || '1%') then chr = '1';
                else if (strg_in like strg_cmp || '2%') then chr = '2';
                else if (strg_in like strg_cmp || '3%') then chr = '3';
                else if (strg_in like strg_cmp || '4%') then chr = '4';
                else if (strg_in like strg_cmp || '5%') then chr = '5';
                else if (strg_in like strg_cmp || '6%') then chr = '6';
                else if (strg_in like strg_cmp || '7%') then chr = '7';
                else if (strg_in like strg_cmp || '8%') then chr = '8';
                else if (strg_in like strg_cmp || '9%') then chr = '9';

                else if (strg_in like strg_cmp || ':%') then chr = ':';
                else if (strg_in like strg_cmp || ';%') then chr = ';';
                else if (strg_in like strg_cmp || '<%') then chr = '<';
                else if (strg_in like strg_cmp || '=%') then chr = '=';
                else if (strg_in like strg_cmp || '>%') then chr = '>';
                else if (strg_in like strg_cmp || '?%') then chr = '?';
                else if (strg_in like strg_cmp || '@%') then chr = '@';

                else if (strg_in like strg_cmp || 'A%') then chr = 'A';
                else if (strg_in like strg_cmp || 'B%') then chr = 'B';
                else if (strg_in like strg_cmp || 'C%') then chr = 'C';
                else if (strg_in like strg_cmp || 'D%') then chr = 'D';
                else if (strg_in like strg_cmp || 'E%') then chr = 'E';
                else if (strg_in like strg_cmp || 'F%') then chr = 'F';
                else if (strg_in like strg_cmp || 'G%') then chr = 'G';
                else if (strg_in like strg_cmp || 'H%') then chr = 'H';
                else if (strg_in like strg_cmp || 'I%') then chr = 'I';
                else if (strg_in like strg_cmp || 'J%') then chr = 'J';
                else if (strg_in like strg_cmp || 'K%') then chr = 'K';
                else if (strg_in like strg_cmp || 'L%') then chr = 'L';
                else if (strg_in like strg_cmp || 'M%') then chr = 'M';
                else if (strg_in like strg_cmp || 'N%') then chr = 'N';
                else if (strg_in like strg_cmp || 'O%') then chr = 'O';
                else if (strg_in like strg_cmp || 'P%') then chr = 'P';
                else if (strg_in like strg_cmp || 'Q%') then chr = 'Q';
                else if (strg_in like strg_cmp || 'R%') then chr = 'R';
                else if (strg_in like strg_cmp || 'S%') then chr = 'S';
                else if (strg_in like strg_cmp || 'T%') then chr = 'T';
                else if (strg_in like strg_cmp || 'U%') then chr = 'U';
                else if (strg_in like strg_cmp || 'V%') then chr = 'V';
                else if (strg_in like strg_cmp || 'W%') then chr = 'W';
                else if (strg_in like strg_cmp || 'X%') then chr = 'X';
                else if (strg_in like strg_cmp || 'Y%') then chr = 'Y';
                else if (strg_in like strg_cmp || 'Z%') then chr = 'Z';

                else if (strg_in like strg_cmp || '[%') then chr = '[';
                else if (strg_in like strg_cmp || '\%') then chr = '\';
                else if (strg_in like strg_cmp || ']%') then chr = ']';
                else if (strg_in like strg_cmp || '^%') then chr = '^';
                else if (strg_in like strg_cmp || '`%') then chr = '`';

                else if (strg_in like strg_cmp || 'a%') then chr = 'a';
                else if (strg_in like strg_cmp || 'b%') then chr = 'b';
                else if (strg_in like strg_cmp || 'c%') then chr = 'c';
                else if (strg_in like strg_cmp || 'd%') then chr = 'd';
                else if (strg_in like strg_cmp || 'e%') then chr = 'e';
                else if (strg_in like strg_cmp || 'f%') then chr = 'f';
                else if (strg_in like strg_cmp || 'g%') then chr = 'g';
                else if (strg_in like strg_cmp || 'h%') then chr = 'h';
                else if (strg_in like strg_cmp || 'i%') then chr = 'i';
                else if (strg_in like strg_cmp || 'j%') then chr = 'j';
                else if (strg_in like strg_cmp || 'k%') then chr = 'k';
                else if (strg_in like strg_cmp || 'l%') then chr = 'l';
                else if (strg_in like strg_cmp || 'm%') then chr = 'm';
                else if (strg_in like strg_cmp || 'n%') then chr = 'n';
                else if (strg_in like strg_cmp || 'o%') then chr = 'o';
                else if (strg_in like strg_cmp || 'p%') then chr = 'p';
                else if (strg_in like strg_cmp || 'q%') then chr = 'q';
                else if (strg_in like strg_cmp || 'r%') then chr = 'r';
                else if (strg_in like strg_cmp || 's%') then chr = 's';
                else if (strg_in like strg_cmp || 't%') then chr = 't';
                else if (strg_in like strg_cmp || 'u%') then chr = 'u';
                else if (strg_in like strg_cmp || 'v%') then chr = 'v';
                else if (strg_in like strg_cmp || 'w%') then chr = 'w';
                else if (strg_in like strg_cmp || 'x%') then chr = 'x';
                else if (strg_in like strg_cmp || 'y%') then chr = 'y';
                else if (strg_in like strg_cmp || 'z%') then chr = 'z';

                else if (strg_in like strg_cmp || '{%') then chr = '{';
                else if (strg_in like strg_cmp || '|%') then chr = '|';
                else if (strg_in like strg_cmp || '}%') then chr = '}';
                else if (strg_in like strg_cmp || '~%') then chr = '~';

                else if (strg_in like strg_cmp || '£%') then chr = '£';
                else if (strg_in like strg_cmp || '²%') then chr = '²';
                else if (strg_in like strg_cmp || '³%') then chr = '³';
                else if (strg_in like strg_cmp || '¹%') then chr = '¹';
                else if (strg_in like strg_cmp || '´%') then chr = '´';
                else if (strg_in like strg_cmp || 'µ%') then chr = 'µ';
                else if (strg_in like strg_cmp || '¶%') then chr = '¶';
                else if (strg_in like strg_cmp || '§%') then chr = '§';

                else if (strg_in like strg_cmp || 'ä%') then chr = 'ä';
                else if (strg_in like strg_cmp || 'ö%') then chr = 'ö';
                else if (strg_in like strg_cmp || 'ü%') then chr = 'ü';
                else if (strg_in like strg_cmp || 'Ä%') then chr = 'Ä';
                else if (strg_in like strg_cmp || 'Ö%') then chr = 'Ö';
                else if (strg_in like strg_cmp || 'Ü%') then chr = 'Ü';
                else if (strg_in like strg_cmp || 'ß%') then chr = 'ß';

                else if (strg_in like strg_cmp || 'Á%') then chr = 'Á';
                else if (strg_in like strg_cmp || 'É%') then chr = 'É';
                else if (strg_in like strg_cmp || 'Í%') then chr = 'Í';
                else if (strg_in like strg_cmp || 'Ó%') then chr = 'Ó';
                else if (strg_in like strg_cmp || 'Ú%') then chr = 'Ú';
                else if (strg_in like strg_cmp || 'á%') then chr = 'á';
                else if (strg_in like strg_cmp || 'é%') then chr = 'é';
                else if (strg_in like strg_cmp || 'í%') then chr = 'í';
                else if (strg_in like strg_cmp || 'ó%') then chr = 'ó';
                else if (strg_in like strg_cmp || 'ú%') then chr = 'ú';

                else if (strg_in like strg_cmp || 'À%') then chr = 'À';
                else if (strg_in like strg_cmp || 'È%') then chr = 'È';
                else if (strg_in like strg_cmp || 'Ì%') then chr = 'Ì';
                else if (strg_in like strg_cmp || 'Ò%') then chr = 'Ò';
                else if (strg_in like strg_cmp || 'Ù%') then chr = 'Ù';
                else if (strg_in like strg_cmp || 'à%') then chr = 'à';
                else if (strg_in like strg_cmp || 'è%') then chr = 'è';
                else if (strg_in like strg_cmp || 'ì%') then chr = 'ì';
                else if (strg_in like strg_cmp || 'ò%') then chr = 'ò';
                else if (strg_in like strg_cmp || 'ù%') then chr = 'ù';

                else if (strg_in like strg_cmp || 'Â%') then chr = 'Â';
                else if (strg_in like strg_cmp || 'Ê%') then chr = 'Ê';
                else if (strg_in like strg_cmp || 'Î%') then chr = 'Î';
                else if (strg_in like strg_cmp || 'Ô%') then chr = 'Ô';
                else if (strg_in like strg_cmp || 'Û%') then chr = 'Û';
                else if (strg_in like strg_cmp || 'â%') then chr = 'â';
                else if (strg_in like strg_cmp || 'ê%') then chr = 'ê';
                else if (strg_in like strg_cmp || 'î%') then chr = 'î';
                else if (strg_in like strg_cmp || 'ô%') then chr = 'ô';
                else if (strg_in like strg_cmp || 'û%') then chr = 'û';

                /* ... all characters in use */

                else                                         chr = '·';

                strg_out = strg_out || chr;
                strg_cmp = strg_cmp || '_';

                pos = pos + 1;
              end
          end

      suspend;
    end