(* TEXTS.PAS -- translate GEOS text pages ** Copyright (c) 1995,1996 Jochen Metzinger ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2, or (at your option) ** any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *) UNIT Texts; INTERFACE USES global, errors, geos, coding, cvt, fontname, textbuf; PROCEDURE open_text(fname: STRING; verbose: BOOLEAN); (* open text system to output to FNAME and return kind of text *) FUNCTION last_chain: ShortInt; (* last chain which can include text *) PROCEDURE text_page(chain: BYTE); (* output text in chain *) PROCEDURE close_text; (* close text system *) IMPLEMENTATION TYPE TEXT_TYPE = (NO_TEXT, WRITE_DOC, TEXT_SCRAP, TEXT_ALBUM, NOTES); TEXT_INFOS = RECORD name: STRING; min, max: BYTE; chain: ShortInt; END; CONST info: ARRAY [TEXT_TYPE] OF TEXT_INFOS = ((name: 'File'; min: 00; max: $FF; chain: -1), (name: 'Write Image'; min: 10; max: 20; chain: 60), (name: 'Text Scrap'; min: 10; max: 20; chain: 0), (name: 'Text Album'; min: 10; max: 20; chain: 126), (name: 'Notes'; min: 10; max: 10; chain: 126)); TYPE GraphicType = RECORD width: BYTE; height: WORD; chain: BYTE; END; (* GraphicType *) NcsType = RECORD font_size: WORD; kind: BYTE; END; (* NcsType *) RulerType = RECORD left, right: WORD; tab: ARRAY [1..8] OF WORD; indent: WORD; form: BYTE; color: BYTE; __unused: WORD; END; VAR style: TEXT_TYPE; version: BYTE; (* kind of document *) max_chain: ShortInt; (* chain range *) do_verbose: BOOLEAN; (* verbose output? *) FUNCTION last_chain: ShortInt; BEGIN last_chain := max_chain; END; (* last_chain *) PROCEDURE get_type(VAR style: TEXT_TYPE; VAR version: BYTE); VAR base: STRING; BEGIN cvt_class_version(base, version); IF base = 'Write Image' THEN style := WRITE_DOC ELSE IF base = 'text album' THEN style := TEXT_ALBUM ELSE IF base = 'Text Scrap' THEN style := TEXT_SCRAP ELSE IF base = 'Notes' THEN style := NOTES ELSE style := NO_TEXT; END; (* get_type *) PROCEDURE DoGraphicEscape; VAR pic: GraphicType; result: WORD; line: STRING; BEGIN cvt_read(pic, SizeOf(pic), result); IF result <> SizeOf(pic) THEN FATAL('bad graphic escape'); WITH pic DO BEGIN line := '### photo scrap $'+HexStr(chain,2); line := line+' ['+long2str(8*width,0)+'x'+long2str(height,0)+']'; buf_break(line); END; (* with *) END; (* DoGraphicEscape *) PROCEDURE DoNewCardSet; VAR ncs: NcsType; result: WORD; line: STRING; BEGIN cvt_read(ncs, SizeOf(ncs), result); IF result <> SizeOf(ncs) THEN FATAL('bad NEWCARDSET'); WITH ncs DO BEGIN SetFontCoding(font_size SHR 6); IF do_verbose THEN BEGIN line := '### NEWCARDSET '+font_name; line := line + '['+long2str(font_size AND $3F,0)+']'; IF kind AND $80 <> 0 THEN line := line + ' underline'; IF kind AND $40 <> 0 THEN line := line + ' bold'; IF kind AND $20 <> 0 THEN line := line + ' reverse'; IF kind AND $10 <> 0 THEN line := line + ' italics'; IF kind AND $08 <> 0 THEN line := line + ' outline'; IF version = 2 THEN BEGIN IF kind AND $04 <> 0 THEN line := line + ' superscript'; IF kind AND $40 <> 0 THEN line := line + ' subscript'; END; (* if *) buf_break(line); END; (* if *) END; (* with *) END; (* DoNewCardSet *) FUNCTION adjust(l: LongInt): LongInt; BEGIN adjust := (DEFAULT_LINE*l) DIV 480; END; (* adjust *) PROCEDURE DoRuler(VAR ruler: RulerType); VAR i: BYTE; BEGIN WITH ruler DO BEGIN buf_margin(adjust(left), adjust(indent), adjust(right), form AND $03); FOR i := 1 TO 8 DO buf_set_tab(adjust(tab[i])); buf_line_space(1+ORD((form AND $18) <> 0)); END; (* with *) END; (* DoRuler *) PROCEDURE DoRulerEscape; VAR ruler: RulerType; result: WORD; line: STRING; i: BYTE; BEGIN cvt_read(ruler, SizeOf(ruler), result); IF result <> SizeOf(ruler) THEN FATAL('bad ruler escape'); IF do_verbose THEN WITH ruler DO BEGIN line := '###RULER [ '+long2str(left,0)+' '+long2str(left+indent,0)+' | '; FOR i := 1 TO 8 DO BEGIN line := line + long2str(tab[i] AND $7FFF,0); IF tab[i] AND $8000 <> 0 THEN line := line + 'd'; tab[i] := tab[i] AND $7FFF; line := line + ' '; END; (* for *) buf_break(line+'| '+long2str(right,0)+' ]'); line := '###RULER'; CASE form AND $03 OF $00: line := line + ' flushleft'; $01: line := line + ' center'; $02: line := line + ' flushright'; $03: line := line + ' block'; END; (* case *) line := line+' line space: '+real2str(1.0+((form SHR 2) AND $03)/2,3,1); line := line+' color: $'+HexStr(color,2); buf_break(line+' reserved: $'+HexStr(__unused,4)); END; (* with *) DoRuler(ruler); END; (* DoRulerEscape *) PROCEDURE DoWriteHeader; VAR header: RulerType; result: WORD; line: STRING; i: BYTE; BEGIN FillChar(header, SizeOf(header), 0); cvt_read(header, 20, result); IF result <> 20 THEN FATAL('no write image header'); IF do_verbose THEN WITH header DO BEGIN line := '### [ '+long2str(left,0)+' | '; FOR i := 1 TO 8 DO line := line + long2str(tab[i],0) + ' '; buf_break(line+'| '+long2str(right,0)+' ]'); END; (* with *) DoRuler(header); END; (* DoWriteHeader *) PROCEDURE DoPage; VAR ch: CHAR; BEGIN WHILE cvt_getch(ch) DO BEGIN CASE ch OF #$00, #$01: IF cvt_eof THEN IF do_verbose THEN buf_break('### new page') ELSE buf_break('') ELSE buf_add(TransChr(ch)); #$09: buf_tab; #$0D: BEGIN buf_nl; buf_indent; END; #$10: DoGraphicEscape; #$11: IF version > 1 THEN DoRulerEscape ELSE buf_add(TransChr(ch)); #$17: DoNewCardSet; ELSE buf_add(TransChr(ch)); END; (* case *) END; (* while *) END; (* DoPage *) PROCEDURE DoWritePage(chain: BYTE); BEGIN IF do_verbose THEN buf_break('### page '+long2str(chain+1,0)); IF version < 2 THEN DoWriteHeader; DoPage; END; (* DoWritePage *) PROCEDURE DoScrapHeader(chain: BYTE); VAR h_size, result: WORD; i: LongInt; BEGIN cvt_read(h_size, SizeOf(h_size), result); IF result <> SizeOf(h_size) THEN FATAL('no scrap header'); INC(h_size, 2); IF cvt_size(chain) <> h_size THEN BEGIN IF do_verbose THEN buf_break('### '+long2str(cvt_size(chain),0)+' <> '+long2str(h_size,0)); cvt_resize(h_size); END; (* if *) buf_margin(0,0,0,0); FOR i := 1 TO 8 DO buf_set_tab((DEFAULT_LINE*i) DIV 10); END; (* DoScrapHeader *) PROCEDURE WriteScrap(chain: BYTE); BEGIN IF style = TEXT_ALBUM THEN buf_break('### scrap '+long2str(chain+1,0)); DoScrapHeader(chain); DoPage; END; (* BeginScrap *) PROCEDURE WriteNote(chain: BYTE); VAR ch: CHAR; line: STRING; BEGIN buf_margin(0,0,0,0); buf_break('### note '+long2str(chain+1,0)); WHILE cvt_getch(ch) DO IF ch = #13 THEN buf_nl ELSE IF ch <> #0 THEN buf_add(TransStr(ch)) ELSE BEGIN buf_break(''); EXIT; END; (* else *) buf_break(''); END; (* WriteNote *) PROCEDURE text_page(chain: BYTE); BEGIN IF chain > max_chain THEN EXIT; IF cvt_size(chain) < 0 THEN EXIT; cvt_chain(chain); CASE style OF WRITE_DOC: DoWritePage(chain); TEXT_SCRAP, TEXT_ALBUM: WriteScrap(chain); NOTES: WriteNote(chain); ELSE FATAL('INTERN [text_page without text]'); END; (* case *) END; (* text_page *) PROCEDURE open_text(fname: STRING; verbose: BOOLEAN); BEGIN get_type(style, version); IF style = NO_TEXT THEN FATAL('no text file'); WITH info[style] DO BEGIN IF (version < min) THEN FATAL('unsupported text version'); IF (version > max) THEN FATAL('unsupported text version'); buf_open(fname); IF verbose THEN buf_break('### '+name+' V'+real2str(version/10,3,1)+': '+cvt_name); version := version DIV 10; max_chain := chain; IF (style = WRITE_DOC) AND (version = 2) THEN Inc(max_chain, 2); do_verbose := verbose; END; (* with *) END; (* open_text *) PROCEDURE close_text; BEGIN buf_break(''); IF do_verbose THEN buf_break('### End of '+info[style].name); buf_close; END; (* close_text *) BEGIN style := NO_TEXT; max_chain := -1; do_verbose := TRUE; END. (* texts *)