{Attached is an attempt at a Pascal RTF reader, which I abandoned in favor of C. The approach is to treat RTF as a language and write a recursive descent parser for it. The C version works quite well. The Pascal version may serve some simple purpose. It's yours to use freely.} program rtf; uses crt; const BUFSIZE = 1024; BEGIN_CWORD = #$DC; BEGIN_GROUP = #$FB; END_GROUP = #$FD; TOKENSET : set of char = [BEGIN_CWORD,BEGIN_GROUP,END_GROUP]; var current_ch : char; current_word : string[80]; current_parm : integer; rtf_version : integer; rtf_charset : string[8]; default_font : integer; margin : integer; index : integer; buffer : array [1..BUFSIZE] of char; f : file; tagfile : text; procedure item; forward; procedure group; forward; function o(ch: char) : char; begin case ch of BEGIN_GROUP: o := '{'; END_GROUP: o := '}'; BEGIN_CWORD: o := '\'; else o := ch; end; end; procedure getch; var ch : char; result : integer; function nextch : char; begin if index >= BUFSIZE then begin BlockRead(f, buffer, BUFSIZE, result); if result = 0 then begin writeln('Unexpected end of RTF file'); halt; end; index := 0; end; inc(index); nextch := buffer[index]; end; begin ch := nextch; case ch of '\': begin ch := nextch; if ch in ['{','}','\'] then current_ch := ch else begin current_ch := BEGIN_CWORD; dec(index); end; end; '{': current_ch := BEGIN_GROUP; '}': current_ch := END_GROUP; else current_ch := ch; end; end; procedure accept(expected: char; echo: boolean); begin if expected <> current_ch then begin writeln('SYNTAX: expected ',o(expected),' found ',o(current_ch)); end else begin if echo and (current_ch in [' '..'~']+TOKENSET) then write(o(current_ch)); getch; end; end; procedure accept_alpha(var alpha: string); begin alpha := ''; while current_ch in ['A'..'Z','a'..'z'] do begin alpha := alpha + current_ch; accept(current_ch, TRUE); end; end; procedure accept_num(var num: integer); var value : longint; signed : boolean; begin if current_ch = '-' then begin signed := TRUE; accept('-',TRUE); end else signed := FALSE; value := 0; while current_ch in ['0'..'9'] do begin value := value*10 + ord(current_ch)-ord('0'); accept(current_ch, TRUE); end; if value > 32767 then begin writeln('Integer overflow'); value := 32767; end; if signed then num := -value else num := value; end; procedure control_word(var spelling: string; var parm: integer); begin accept(BEGIN_CWORD,TRUE); accept_alpha(spelling); accept_num(parm); if current_ch = ' ' then accept(' ',TRUE); writeln(tagfile, spelling:10, parm:10); end; procedure indent(amount: integer); var i : integer; begin inc(margin, amount); writeln; for i:= 1 to margin do write(' '); end; procedure content; begin indent(2); accept(BEGIN_GROUP,TRUE); indent(2); while current_ch <> END_GROUP do begin if current_ch = ';' then begin accept(current_ch, TRUE); indent(0); end else if current_ch = BEGIN_GROUP then begin content; end else if current_ch = BEGIN_CWORD then begin item; end else accept(current_ch, TRUE); end; indent(-2); accept(END_GROUP, TRUE); indent(-2); end; procedure item; begin repeat if current_ch = BEGIN_GROUP then begin content; end else if current_ch = ';' then begin accept(';', TRUE); indent(0); end else begin while not (current_ch in [BEGIN_GROUP,END_GROUP,';']) do accept(current_ch, TRUE); end; until not (current_ch in [BEGIN_GROUP,';',BEGIN_CWORD]); end; procedure content1; var alpha : string[80]; parm : integer; begin while (current_ch <> END_GROUP) do begin case current_ch of BEGIN_GROUP: group; BEGIN_CWORD: control_word(alpha, parm); else begin {writeln('ERROR: unknown token: ',o(current_ch));} accept(current_ch, TRUE); end; end; end; end; procedure group; begin indent(2); accept(BEGIN_GROUP, TRUE); indent(2); content1; indent(-2); accept(END_GROUP, TRUE); indent(-2); end; procedure version; var alpha : string[80]; begin control_word(alpha, rtf_version); if alpha <> 'rtf' then begin writeln('Not an RTF file'); halt; end; end; procedure character_set; var parm : integer; begin control_word(rtf_charset, parm); end; procedure rtfile; begin accept(BEGIN_GROUP, TRUE); indent(2); version; character_set; content1; indent(-2); accept(END_GROUP, TRUE); end; begin ClrScr; margin := 0; assign(f, ParamStr(1)); reset(f, 1); assign(output, ''); rewrite(output); assign(tagfile, 'tagfile.dat'); rewrite(tagfile); index := BUFSIZE; getch; rtfile; end. +-------------------------------------------------+ | John Day | Computer Science Innovations,Inc | Principal Engineer PHONE: (407) 676-2923 ext:410 | Melbourne, Fl FAX: (407) 676-3255 | WWW: http://www.csihq.com | EMAIL: jday@csihq.com +--------------------------------------------------+