unit funciones;

interface

function RtfToText(Cadena: PChar): PChar; cdecl; export;

implementation

uses
  Forms, Classes, SysUtils, StdCtrls, ComCtrls;


// Esta función falla cuando hay caracteres especiales en el texto (ñ, por ejemplo).
// Mejor la de abajo.

function RtfToText2(Cadena: PChar): PChar;
var
  i: integer;
  CadenaAux1: String;

begin
  //Si no tiene ninguna llave no esta guardado como rtf
  if (Pos('{', Cadena) = 0) then
     Result := Cadena
  else
  //Esta guardado con rtf
  begin
    //Quitamos todo lo que está antes de \fs1x
    i := Pos('\fs', Cadena);
    CadenaAux1 := Copy(Cadena, i, StrLen(Cadena)-1);

    //Quitamos la parte de delante \fs1x
    i:= Pos(' ', CadenaAux1);
    CadenaAux1 := Copy(PChar(CadenaAux1), i+1, StrLen(PChar(CadenaAux1))-1);

    //Quitamos todo lo de la parte de atras a partir de la primera barra \ que tengamos
    i:= Pos('\', CadenaAux1);
    CadenaAux1 := Copy(PChar(CadenaAux1), 0, i-1);

    Result := PChar(CadenaAux1);
  end;
end;


{
  Convert RTF enabled text to plain.
  http://www.delphipraxis.net/topic45179.html
}

// HAY QUE LIMPIAR LA CADENA DE ENTRADA DE SALTOS DE LÍNEA (#$D#$A) POR QUE
// SI NO, NO ES UNA CADENA CON TEXTO RTF VÁLIDO

function RtfToText(Cadena: PChar): PChar;
const
  SaltoLinea = #13#10; //--> #$D#$A
var
  aSource: string; // <- Para almacenar la cadena de entrada sin saltos de línea
  Source: string;
  NChar: Integer;

  function ProcessGroupRecursevly: string;

  function HexToInt(HexStr: String): Integer;
  begin
    result := StrToInt('$' + HexStr);
  end;

  procedure SkipStar;
  var
     BracesOpened: Integer;
     Escaped: Boolean;
  begin
       BracesOpened:=1;
       Escaped:=false;
       while BracesOpened>0
             do begin
                Inc (NChar);
                case Source [NChar] of
                     '{': if Escaped
                             then Escaped:=false
                             else Inc (BracesOpened);
                     '}': if Escaped
                             then Escaped:=false
                             else Dec (BracesOpened);
                     '\': Escaped:=not Escaped;
                     else Escaped:=false;
                end;
             end;
  end;

  function UnicodeCharCode2ANSIChar (aCode: LongInt): Char;
  type
      TUnicode2ANSITable=array [$0410..$044f] of Char;
  const
       Unicode2ANSITable: TUnicode2AnsiTable=('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß',
                                               'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
  begin
       if (Low (Unicode2ANSITable)<=aCode) and (aCode<=High (Unicode2ANSITable)) then
        UnicodeCharCode2ANSIChar:=Unicode2ANSITable [aCode]
       else UnicodeCharCode2ANSIChar:='?';
  end;

  var
     Control, NumericValue, TextValue: string;
  begin
       Result:='';
       Inc (NChar);
       while NChar<=Length (Source)
             do case Source [NChar] of
                     '{': Result:=Result+ProcessGroupRecursevly;
                     '}': begin
                               Inc (NChar);
                               Break;
                          end;
                     '\': begin
                               Inc (NChar);
                               case Source [NChar] of
                                    '''': begin
                                               Result:=Result+Chr (HexToInt (Copy (Source, NChar+1, 2)));
                                               Inc (NChar, 3);
                                          end;
                                    '~': Result:=Result+#$20;
                                    '*': SkipStar;
                                    'a'..'z': begin
                                                   Control:='';
                                                   while Source [NChar] in ['a'..'z']
                                                         do begin
                                                            Control:=Control+Source [NChar];
                                                            Inc (NChar);
                                                         end;
                                                   if Source [NChar]='-'
                                                      then begin
                                                           NumericValue:=Source [NChar];
                                                           Inc (NChar);
                                                      end
                                                      else NumericValue:='';
                                                    while Source [NChar] in ['0'..'9']
                                                          do begin
                                                             NumericValue:=NumericValue+Source [NChar];
                                                             Inc (NChar);
                                                          end;
                                                    if Source [NChar]='{'
                                                       then ProcessGroupRecursevly;
                                                    TextValue:='';
                                                    if not (Source [NChar] in ['a'..'z', '{', '}', '\'])
                                                       then begin
                                                            Inc (NChar);
                                                            while not (Source [NChar] in ['{', '}', '\'])
                                                                  do begin
                                                                     TextValue:=TextValue+Source [NChar];
                                                                     Inc (NChar);
                                                                  end;
                                                       end;
                                                    if (Control='line') or (Control='par')
                                                       then Result:=Result+#$0D#$0A
                                                       else if Control='tab'
                                                               then Result:=Result+#$09
                                                               else if Control='u'
                                                                       then Result:=Result+UnicodeCharCode2ANSIChar (StrToInt (NumericValue))
                                                                       else if Control='colortbl'
                                                                               then TextValue:='';
                                                   if Length (TextValue)>0
                                                      then if (not ((TextValue [Length (TextValue)]=';') and (Source [NChar]='}')))
                                                              then begin
                                                                   Result:=Result+TextValue;
                                                                   TextValue:='';
                                                              end;
                                              end;
                                    else begin
                                         Result:=Result+Source [NChar];
                                         Inc (NChar);
                                    end;
                               end;
                     end;
                     else begin
                          Result:=Result+Source [NChar];
                          Inc (NChar);
                     end;
             end;
  end;

  function InitSource: Boolean;
  var
     BracesCount: Integer;
     Escaped: Boolean;
  begin
       if Copy (aSource, 1, 5) <> '{\rtf' then
        InitSource:=false
       else begin
               Source:='';
               BracesCount:=0;
               Escaped:=false;
               NChar:=1;
               while (NChar<=Length (aSource)) and (BracesCount>=0)
                     do begin
                        if not (aSource [NChar] in [#$0D, #$0A])
                           then begin
                                Source:=Source+aSource [NChar];
                                case aSource [NChar] of
                                     '{': if not Escaped
                                             then Inc (BracesCount)
                                             else Escaped:=false;
                                     '}': if not Escaped
                                             then Dec (BracesCount)
                                             else Escaped:=false;
                                     '\': Escaped:=true;
                                     else Escaped:=false;
                                end;
                           end;
                        Inc (NChar);
                     end;
               InitSource:=BracesCount=0;
          end;
  end;

begin
  // Hay que quitar el salto de línea al final de la aSource RTF
  aSource := Copy(Cadena, 1, length(Cadena)-2);

  // Cambiar los saltos de línea que no son de RTF por un caracter para
  // que se limpien.
  aSource := StringReplace(aSource, SaltoLinea, '^', [rfreplaceall]);
  
  if InitSource then
  begin
    NChar:=1;
    Result:= PChar(ProcessGroupRecursevly);
  end
  else
    Result := PChar(aSource);
end;

end.




