/* * Copyright (C) 1998,1999 David Stes. * * 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 of the License, 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "richtext.h" #include "lexan.h" #include "richfont.h" #include "state.h" #include "style.h" #include "textline.h" #include "fontchange.h" #include "charblk.h" @implementation Richtext int papersize; typedef struct { char *name;int x;int y; } PAPERSIZE; PAPERSIZE papsizes[] = {{"A4",595,842},{"Letter",612,792}}; int twips2points(int x) { return ((x)/20); } int points2twips(int x) { return ((x)*20); } - docdefaults { paperw = PAPERW; paperh = PAPERH; margl = MARGL; margr = MARGR; margt = MARGT; margb = MARGB; return self; } - empty { if (paragraphs) { [[paragraphs freeContents] free]; } [self docdefaults]; [self paragraphs:[OrdCltn new]]; [self newparagraph]; return self; } #ifndef NDEBUG - check { if (paralines) { int i,n; n = [paragraphs size]; assert([paralines size] == n); for(i=0;i= 0) return [self charBlockForIndex:pi:ci-1]; if (pi-1 >= 0) { m = [[[paragraphs at:pi-1] text] size]; if (m) --m; return [self charBlockForIndex:pi-1:m]; } return [b copy]; /* mmh */ } /* below/above could be improved to work line by line */ - blockBelow:b { int m,n; int pi = [b parindex]; int ci = [b stringindex]; n = [paragraphs size]; if (++pi < n) { m = [[[paragraphs at:pi] text] size]; if (m) --m; if (ci > m) ci=m; return [self charBlockForIndex:pi:ci]; } return [b copy]; } - blockAbove:b { int m,n; int pi = [b parindex]; int ci = [b stringindex]; n = [paragraphs size]; if (--pi >= 0) { m = [[[paragraphs at:pi] text] size]; if (m) --m; if (ci > m) ci=m; return [self charBlockForIndex:pi:ci]; } return [b copy]; } - composeLine:(int)i from:(int)from in:paragraph { return [self shouldNotImplement]; } - startpage:(int)n:(int)x:(int)y { return [self shouldNotImplement]; } - showpage { return [self shouldNotImplement]; } - displayLine:lines num:(int)i in:paragraph at:(int)liney { return [self shouldNotImplement]; } - composeAll { int i,n; if (paralines) { [paralines elementsPerform:@selector(freeContents)]; [paralines freeContents]; } else { paralines = [OrdCltn new]; } /* feed chars into external (platform specific) composition scanner */ for(i=0,n=[paragraphs size];i (p.y-2*PSMARGIN)) { y=0;[psdisplayscanner showpage]; [psdisplayscanner startpage:++pagecount:p.x:p.y]; } [psdisplayscanner displayLine:line num:j in:[paragraphs at:i] at:y]; y += lineheight; } } [psdisplayscanner showpage]; [psparalines elementsPerform:@selector(freeContents)]; [psparalines freeContents]; return self; } - (int)bottomOfLines:cLines { int h = 0; int i,n = [cLines size]; for(i=0;i totalh - min) [self error:"top larger than totalh - paperh"]; #endif top = v; return self; } - (int)totalheight { int h = 0; int i,n = [paralines size]; if (!paralines) [self composeAll]; for(i=0;i a) { [displayscanner displayLine:line num:j in:[paragraphs at:i] at:y]; } y += lineheight; if (y > b) return self; } } return self; } - errormsg:x { if (errormsg) [errormsg free]; errormsg = x; return self; } - (char*)errormsg { return [errormsg str]; } static jmp_buf jb; static void readgroup(IOD d,id state) { while (1) { int c; curstate = state; c = lexanlex(); switch(c) { case OPENGR : { readgroup(d,[state copy]); break; } case EOF : case CLOSEGR : { [state free]; return; } case PANICS : { longjmp(jb,1); } default : { lexanerrmsg=[String sprintf:"File not in RTF format.\nExpected '}' but got '%c'\n",c]; longjmp(jb,1); } } } } - readrtf:(IOD)d { lexanin = d; lineno = 1; lexanerrmsg = nil; /* start reading by default into destination 'self' */ curstate = [[State new] richtext:self]; if (lexanlex() == OPENGR) { if (lexanlex() == RTFWORD) { if (setjmp(jb) == 0) { readgroup(d,curstate); return self; } } else { [[self empty] adobefonts]; } } else { [[self empty] adobefonts]; } curstate = [curstate free]; [self errormsg:(lexanerrmsg)?lexanerrmsg:[String str:"File not in RTF format"]]; return nil; } static void writertfchar(IOD d,int c) { switch(c) { case '\\' : fprintf(d,"\\\\"); break; case '\n' : fprintf(d,"\\\n"); break; case '{' : fprintf(d,"\\{"); break; case '}' : fprintf(d,"\\}"); break; default : fputc(c,d); break; } } static void writekeyw(IOD d,id a) { if ([a respondsTo:@selector(writertf:)]) [a writertf:d]; } static BOOL isempty(id c) { int cnt = 0; int i,n = [c size]; for(i=0;i