xref: /aoo41x/main/svtools/source/filter/sgvtext.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #include <rtl/math.h>
32 #include <tools/config.hxx>
33 #include <svtools/filter.hxx>
34 #include "sgffilt.hxx"
35 #include "sgfbram.hxx"
36 #include "sgvmain.hxx"
37 // #include "Debug.c"
38 
39 extern SgfFontLst* pSgfFonts;
40 
41 #ifndef abs
42 #define abs(x) ((x)<0 ? -(x) : (x))
43 #endif
44 
45 
46 ////////////////////////////////////////////////////////////////////////////////////////////////////
47 //
48 //  Einschraenkungen: Schatten nur grau, 2D und mit fixem Abstand.
49 //
50 //
51 //
52 //
53 ////////////////////////////////////////////////////////////////////////////////////////////////////
54 
55 /////////////////////////////////////////////////////////////////////////////////
56 /////////////////////////////////////////////////////////////////////////////////
57 /////////////////////////////////////////////////////////////////////////////////
58 // AbsBase.Pas
59 
60 // die folgenden Werte sind in % vom maximalen Schriftgrad der Zeile   */
61 #define  UndlSpace  5 /* Untersteichungsabstand von der Baseline       */
62 #define  UndlWidth  6 /* Untersteichungsdicke                          */
63 #define  UndlSpac2  7 /* Zwischenraum bei doppelter Unterstreichung    */
64 #define  StrkSpace 25 /* Abstand der Durchstreichlinie von der Baseline*/
65 #define  StrkWidth  5 /* Durchstreichungsliniendicke                   */
66 #define  StrkSpac2  7 /* Zwischenraum bei doppelter Durchstreichung    */
67 #define  OutlWidth  2 /* Strichstaerke ist 2% vom Schriftgrad          */
68 
69 // vvv Sonderzeichen im TextBuffer vvv
70 #define  TextEnd        0 /* ^@ Ende der Zeichenkette                           */
71 #define  HardSpace      6 /* ^F Hartspace (wird nicht umbrochen) ,' '           */
72 #define  GrafText       7 /* ^G Im Text eingebundene Grafik (future)            */
73 #define  Tabulator      9 /* ^I Tabulatorzeichen, Pfeil                         */
74 #define  LineFeed      10 /* ^J Neue Zeile                                      */
75 #define  SoftTrennK    11 /* ^K Zeichen fuer k-c-Austausch bei Trennung, 'k'    */
76 #define  AbsatzEnd     13 /* ^M Neuer Absatz =CR                                */
77 #define  HardTrenn     16 /* ^P Hartes Trennzeichen (wird nicht umbrochen), '-' */
78 #define  SoftTrennAdd  19 /* ^S Zusatz-Zeichen Trennung von z.b."Schiff-fahrt"  */
79 #define  Paragraf      21 /* ^U Zeichen welches fuer Paragraf-Zeichen           */
80 #define  Escape        27 /* ^[ Escapesequenz einleiten                         */
81 #define  SoftTrenn     31 /* ^_ Weiches Trennzeichen, '-' nur Zeilenende        */
82 #define  MaxEscValLen  8
83 #define  MaxEscLen     (MaxEscValLen+3)
84 
85 //==============================================================================
86 // Escapesequenzen: [Esc]<Ident><Value>[Esc]  also mind. 4 Char
87 // Max. Laenge von Value soll sein: 8 Char (7+Vorzeichen). Demnach max. Laenge
88 // einer Escapesequenz: 11 Char.
89 // Identifer:
90 
91 #define  EscFont   'F' /* FontID, z.B. 92500 fuer CG Times                          */
92 #define  EscGrad   'G' /* Schriftgrad 1..255 fuer <<Pt-127<<Pt                      */
93 #define  EscBreit  'B' /* Breite 1..255% des Schriftgrades                          */
94 #define  EscKaptS  'K' /* Kapitaelchengroesse 1..255% des Schriftgrades             */
95 #define  EscLFeed  'L' /* Zeilenabstand 1..32767% vom max. Schriftgrad der Zeile    */
96                         // oder 1..32767 fuer 1..16383<<Pt absolut (Wenn Bit 15=1)
97 #define  EscSlant  'S' /* Kursiv(Winkel) 1..8999 fuer 0.01deg..89.99deg             */
98 #define  EscVPos   'V' /* Zeichen Vertikal-Position  1..255 fuer <<Pt..127<<Pt      */
99 #define  EscZAbst  'Z' /* Zeichenabstand -128..127%                                 */
100 #define  EscHJust  'A' /* H-Justify    Absatz: Links, Zentr, Rechts, Block, Austreibend, Gesperrt (0..5)*/
101 
102 #define  EscFarbe  'C' /* Farbe 0..7                                                */
103 #define  EscBFarb  'U' /* BackFarbe 0..7                                            */
104 #define  EscInts   'I' /* Farbintensitaet 0..100%                                   */
105 #define  EscMustr  'M' /* Muster 0..? inkl. Transp...                               */
106 #define  EscMFarb  'O' /* Musterfarbe 0..7                                          */
107 #define  EscMBFrb  'P' /* 2. Musterfarbe 0..7                                       */
108 #define  EscMInts  'W' /* Musterintensitaet 0..7                                    */
109 
110 #define  EscSMstr  'E' /* Schattenmuster 0..? inkl. Transp...                       */
111 #define  EscSFarb  'R' /* Schattenfarbe 0..7                                        */
112 #define  EscSBFrb  'T' /* 2. Schattenfarbe 0..7                                     */
113 #define  EscSInts  'Q' /* Schattenintensitaet 0..7                                  */
114 
115 #define  EscSXDst  'X' /* Schattenversatz X 0..100%                                 */
116 #define  EscSYDst  'Y' /* Schattenversatz Y 0..100%                                 */
117 #define  EscSDist  'D' /* Schattenversatz X-Y 0..100%                               */
118 
119 #define  EscBold   'f' /* Fett                                                      */
120 #define  EscLSlnt  'l' /* LKursiv                                                   */
121 #define  EscRSlnt  'r' /* RKursiv                                                   */
122 #define  EscUndln  'u' /* Unterstrichen                                             */
123 #define  EscDbUnd  'p' /* doppelt Unterstrichen                                     */
124 #define  EscKaptF  'k' /* Kapitaelchenflag                                          */
125 #define  EscStrik  'd' /* Durchgestrichen                                           */
126 #define  EscDbStk  'e' /* doppelt Durchgestrichen                                   */
127 #define  EscSupSc  'h' /* Hochgestellt                                              */
128 #define  EscSubSc  't' /* Tiefgestellt                                              */
129 #define  Esc2DShd  's' /* 2D-Schatten                                               */
130 #define  Esc3DShd  'j' /* 3D-Schatten                                               */
131 #define  Esc4DShd  'i' /* 4D-Schatten                                               */
132 #define  EscEbShd  'b' /* Embossed                                                  */
133 
134 //  AllEscIdent =[EscFont, EscGrad, EscBreit,EscKaptS,EscLFeed,EscSlant,EscVPos, EscZAbst,EscHJust,
135 //                EscFarbe,EscBFarb,EscInts, EscMustr,EscMFarb,EscMBFrb,EscMInts,
136 //                EscSMstr,EscSFarb,EscSBFrb,EscSInts,EscSXDst,EscSYDst,EscSDist,
137 //                EscBold, EscLSlnt,EscRSlnt,EscUndln,EscDbUnd,EscKaptF,EscStrik,EscDbStk,
138 //                EscSupSc,EscSubSc,Esc2DShd,Esc3DShd,Esc4DShd];
139 // Justify muss spaetestens am Anfang des Absatzes stehen
140 #define  EscSet    '' /* Flag setzen                                               */
141 #define  EscReset  '' /* Flag loeschen                                             */
142 #define  EscDeflt  '\x11' /* Flag auf default setzen                                */
143 #define  EscToggl  '' /* Flag Toggeln                                              */
144 #define  EscRelat  '%'
145 #define  EscNoFlg  0
146 #define  EscNoVal  -2147483647 /* -MaxLongInt */
147 //==============================================================================
148 #define  NoTrenn 0xFFFF   /* Wert fuer Parameter 'Rest' von GetTextChar(), wenn auf keinen Fall getrennt werden soll */
149 #define  DoTrenn 0xFFFE   /* Wert fuer Parameter 'Rest' von GetTextChar(), wenn getrennt werden soll                 */
150 
151 #define  MaxLineChars 1024
152 
153 #define  ChrXPosArrSize (MaxLineChars+1+1)           /* 2k - Beginnt mit 0 im gegensatz zu StarDraw */
154 #define  CharLineSize   (MaxLineChars+1+1)
155 #define  EscStr         (UCHAR[MaxEscLen+1]);
156 
157 #define  MinChar 32
158 #define  MaxChar 255
159 
160 
161 //==============================================================================
162 
163 #define  DefaultCharWidth 4800
164 #define  GradDiv             2
165 #define  CharTopToBase     100 /* wegen Apostrophe und Umlaute mehr als 75% */
166 #define  CharTopToBtm      120 /* Zeilenhoehe ist groesser als Schriftgrad  */
167                                // bei Avanti-Bold 'ue' eigentlich sogar 130%
168 
169 // end of AbsBase.Pas
170 /////////////////////////////////////////////////////////////////////////////////
171 /////////////////////////////////////////////////////////////////////////////////
172 /////////////////////////////////////////////////////////////////////////////////
173 
174 
175 
176 /////////////////////////////////////////////////////////////////////////////////
177 /////////////////////////////////////////////////////////////////////////////////
178 /////////////////////////////////////////////////////////////////////////////////
179 // DefBase.Pas
180 
181 #define  TextBoldBit  0x0001   /* Fett                    */
182 #define  TextRSlnBit  0x0002   /* Kursiv                  */
183 #define  TextUndlBit  0x0004   /* Unterstrichen           */
184 #define  TextStrkBit  0x0008   /* Durchgesteichen         */
185 #define  TextSupSBit  0x0010   /* Hocgestellt             */
186 #define  TextSubSBit  0x0020   /* Tiefgestellt            */
187 #define  TextKaptBit  0x0040   /* Kapitaelchen            */
188 #define  TextLSlnBit  0x0080   /* Linkskursiv             */
189 #define  TextDbUnBit  0x0100   /* Doppelt unterstrichen   */
190 #define  TextDbStBit  0x0200   /* Doppelt durchgestrichen */
191 #define  TextSh2DBit  0x0400   /* 2D-Schatten         2.0 */
192 #define  TextSh3DBit  0x0800   /* 3D-Schatten         2.0 */
193 #define  TextSh4DBit  0x1000   /* 4D-Schatten         2.0 */
194 #define  TextShEbBit  0x2000   /* Embossed-Schatten   2.0 */
195 #define  FontAtrBits  (TextBoldBit | TextRSlnBit)
196 
197 #define  THJustLeft    0x00
198 #define  THJustCenter  0x01
199 #define  THJustRight   0x02
200 #define  THJustBlock   0x03
201 #define  THJustDrvOut  0x04 /* Austreibend          Formatiert */
202 #define  THJustLocked  0x05 /* A l s   S p e r r s c h r i f t */
203 #define  TVJustTop     0x00 /* Future */
204 #define  TVJustCenter  0x10 /* Future */
205 #define  TVJustBottom  0x20 /* Future */
206 #define  TVJustBlock   0x30 /* Future */
207 
208 #define  MaxCharSlant  4200 /* Maximal 42deg kursiv ! */
209 
210 // end of DefBase.Pas
211 /////////////////////////////////////////////////////////////////////////////////
212 /////////////////////////////////////////////////////////////////////////////////
213 /////////////////////////////////////////////////////////////////////////////////
214 
215 
216 sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L);
217 
218 sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L)
219 {
220 	return (F.FIntens!=L.LIntens) ||
221 		   ((F.FFarbe!=L.LFarbe)   && (F.FIntens>0)) ||
222 		   ((F.FBFarbe!=L.LBFarbe) && (F.FIntens<100));
223 }
224 
225 
226 /////////////////////////////////////////////////////////////////////////////////
227 /////////////////////////////////////////////////////////////////////////////////
228 /////////////////////////////////////////////////////////////////////////////////
229 // Misc.Pas
230 
231 short hPoint2Sgf(short a)
232 {
233 	long b;
234 	b=long(a)*127*SgfDpmm/(144*5);
235 	return short(b);
236 }
237 
238 short Sgf2hPoint(short a)
239 {
240 	long b;
241 	b=long(a)*5*144/(127*SgfDpmm);
242 	return short(b);
243 }
244 
245 // End of Misc.Pas
246 /////////////////////////////////////////////////////////////////////////////////
247 /////////////////////////////////////////////////////////////////////////////////
248 /////////////////////////////////////////////////////////////////////////////////
249 
250 
251 
252 /////////////////////////////////////////////////////////////////////////////////
253 /////////////////////////////////////////////////////////////////////////////////
254 /////////////////////////////////////////////////////////////////////////////////
255 // AbsRead.Pas
256 
257 // ======================================================================
258 // Function GetTopToBaseLine()  Function GetBaseLineToBtm()
259 //
260 // Abstand von Zeilenoberkante bis BaseLine bzw. von BaseLine bis
261 // Unterkante berechnen. Alles in SGF-Units.
262 // ======================================================================
263 
264 sal_uInt16 GetTopToBaseLine(sal_uInt16 MaxGrad)
265 {
266 	long ret;
267 	ret=long(MaxGrad)*long(CharTopToBase) /long(100);
268 	return sal_uInt16(ret);
269 }
270 
271 // ======================================================================
272 // Function GetTextChar()   Function GetTextCharConv()
273 //
274 // Liest ein Zeichen aus dem Textbuffer, wertet dabei eventuell
275 // auftretende Escapesequenzen aus und setzt dementsprechend den
276 // Ein-/Ausgabeparameter AktAtr. Index wird entsprechend erhoeht.
277 // Der Parameter Rest muss immer die Anzahl der Zeichen beinhalten,
278 // den angeforderten Zeichen in der aktuellen Zeile noch folgen.
279 // Ansonsten funktioniert die Silbentrennung nicht richtig. Gibt man
280 // stattdessen die Konstante NoTrenn an, wird in keinem Fall
281 // getrennt, die Konstante DoTrenn bewirkt dagegen, dass ueberall dort
282 // getrennt wird, wo ein SoftTrenner vorkommt.
283 //
284 // SoftTrenner werden immer in ein Minuszeichen konvertiert.
285 // GetTextCharConv() konvertiert zusaetzlich HardSpace und AbsatzEnde
286 // in Spaces sowie HardTrenner in Minuszeichen. TextEnde wird immer
287 // als Char(0) geliefert.
288 // ======================================================================
289 
290 
291 
292 UCHAR ConvertTextChar(UCHAR c)
293 {
294 	if (c<32) {
295 		switch (c) {
296 			case HardSpace   : c=' '; break;
297 			case AbsatzEnd   : c=' '; break;
298 			case SoftTrenn   : c='-'; break;
299 			case HardTrenn   : c='-'; break;
300 			case SoftTrennK  : c='-'; break;
301 			case SoftTrennAdd: c='-';
302 		}
303 	}
304 	return c;
305 }
306 
307 
308 
309 sal_uInt16 GetSchnittBit(UCHAR c)
310 {
311 	sal_uInt16 r=0;
312 	switch (c) {
313 		case EscBold : r=TextBoldBit; break;
314 		case EscRSlnt: r=TextRSlnBit; break;
315 		case EscUndln: r=TextUndlBit; break;
316 		case EscStrik: r=TextStrkBit; break;
317 		case EscDbUnd: r=TextDbUnBit; break;
318 		case EscDbStk: r=TextDbStBit; break;
319 		case EscSupSc: r=TextSupSBit; break;
320 		case EscSubSc: r=TextSubSBit; break;
321 		case EscKaptF: r=TextKaptBit; break;
322 		case EscLSlnt: r=TextLSlnBit; break;
323 		case Esc2DShd: r=TextSh2DBit; break;
324 		case Esc3DShd: r=TextSh3DBit; break;
325 		case Esc4DShd: r=TextSh4DBit; break;
326 		case EscEbShd: r=TextShEbBit;
327 	}
328 	return r;
329 }
330 
331 
332 
333 long ChgValue(long Def, long Min, long Max, UCHAR FlgVal, long NumVal)
334 {
335 	long r=0;
336 
337 	if (FlgVal==EscDeflt) {
338         r=Def;                          // zurueck auf Default
339 	} else {
340 		if (NumVal!=EscNoVal) r=NumVal; // Hart setzen
341 	}
342 
343 	if (Min!=0 || Max!=0) {
344 		if (r>Max) r=Max;
345 		if (r<Min) r=Min;
346 	}
347 	return r;
348 }
349 
350 
351 
352 void ChgSchnittBit(sal_uInt16 Bit, sal_uInt16 Radio1, sal_uInt16 Radio2, sal_uInt16 Radio3,
353 				   UCHAR FlgVal, sal_uInt16 Schnitt0, sal_uInt16& Schnitt)
354 {
355 	sal_uInt16 All,Rad;
356 
357 	Rad=Radio1 | Radio2 | Radio3;
358 	All=Bit | Rad;
359 
360 	switch (FlgVal) {
361 		case EscSet  : Schnitt=(Schnitt & ~All) | Bit;              break;
362 		case EscReset: Schnitt=(Schnitt & ~All);                    break;
363 		case EscDeflt: Schnitt=(Schnitt & ~All) | (Schnitt0 & All); break;
364 		case EscToggl: Schnitt=(Schnitt & ~Rad) ^ Bit;
365 	}
366 }
367 
368 
369 
370 UCHAR GetNextChar(UCHAR* TBuf, sal_uInt16 Index)
371 {
372 	sal_uInt16 Cnt;
373 	while (TBuf[Index]==Escape) {
374 		Index++;
375 		Cnt=0;
376 		while (TBuf[Index]!=Escape && Cnt<=MaxEscLen) {
377 			Index++; Cnt++; }
378 		Index++;
379 	}
380 	return TBuf[Index];
381 }
382 
383 
384 
385 UCHAR ProcessOne(UCHAR* TBuf, sal_uInt16& Index,
386 				 ObjTextType& Atr0, ObjTextType& AktAtr,
387 				 sal_Bool ScanEsc)
388 {
389 	UCHAR c;
390 	UCHAR Ident;
391 	sal_Bool  Ende;
392 	sal_Bool  q;
393 	UCHAR FlgVal;
394 	long  NumVal;
395 	long  Sgn;
396 	short i;
397 	sal_Bool  EoVal;
398 
399 	do {
400 		c=TBuf[Index]; Index++;
401 		Ende=(c!=Escape);
402 		if (Ende==sal_False) {
403 			c=TBuf[Index]; Index++;
404 			Ident=c;                          // Identifer merken
405 			FlgVal=EscNoFlg;
406 			NumVal=EscNoVal;
407             c=TBuf[Index]; Index++;            // Hier faengt der Wert an
408 			if (c==EscSet || c==EscReset || c==EscDeflt || c==EscToggl) FlgVal=c; else {
409 				if (c=='-') Sgn=-1; else Sgn=1;
410 				if (c=='+' || c=='-') { c=TBuf[Index]; Index++; }
411 				i=MaxEscValLen;
412 				NumVal=0;
413 				do {
414 					NumVal=10*NumVal+c-'0';
415 					EoVal=(TBuf[Index]<'0' || TBuf[Index]>'9');
416 					if (EoVal==sal_False) { c=TBuf[Index]; Index++; }
417 					i--;
418 				} while (i>0 && EoVal==sal_False);
419 				NumVal=Sgn*NumVal;
420 			}
421 			q=!CheckTextOutl(AktAtr.F,AktAtr.L);
422 
423 			switch (Ident) {
424 				case EscFont : AktAtr.SetFont(sal_uLong (ChgValue(Atr0.GetFont(),0,0          ,FlgVal,NumVal)));break;
425 				case EscGrad : AktAtr.Grad   =sal_uInt16(ChgValue(Atr0.Grad,   2,2000         ,FlgVal,NumVal)); break;
426 				case EscBreit: AktAtr.Breite =sal_uInt16(ChgValue(Atr0.Breite, 1,1000         ,FlgVal,NumVal)); break;
427 				case EscKaptS: AktAtr.Kapit  =(sal_uInt8)(ChgValue(Atr0.Kapit,  1,255          ,FlgVal,NumVal)); break;
428 				case EscLFeed: AktAtr.LnFeed =sal_uInt16(ChgValue(Atr0.LnFeed, 1,65535        ,FlgVal,NumVal)); break;
429 				case EscSlant: AktAtr.Slant  =sal_uInt16(ChgValue(Atr0.Slant,  1,MaxCharSlant ,FlgVal,NumVal)); break;
430 				case EscVPos : AktAtr.ChrVPos=char  (ChgValue(Atr0.ChrVPos,-128,127       ,FlgVal,NumVal)); break;
431 				case EscZAbst: AktAtr.ZAbst  =(sal_uInt8)(ChgValue(Atr0.ZAbst,  1,255          ,FlgVal,NumVal)); break;
432 				case EscHJust: AktAtr.Justify=(sal_uInt8)(ChgValue(Atr0.Justify & 0x0F,0,5     ,FlgVal,NumVal)); break;
433 				case EscFarbe: { AktAtr.L.LFarbe =(sal_uInt8)(ChgValue(Atr0.L.LFarbe,0,7   ,FlgVal,NumVal)); if (q) AktAtr.F.FFarbe =AktAtr.L.LFarbe;  } break;
434 				case EscBFarb: { AktAtr.L.LBFarbe=(sal_uInt8)(ChgValue(Atr0.L.LBFarbe,0,255,FlgVal,NumVal)); if (q) AktAtr.F.FBFarbe=AktAtr.L.LBFarbe; } break;
435 				case EscInts : { AktAtr.L.LIntens=(sal_uInt8)(ChgValue(Atr0.L.LIntens,0,100,FlgVal,NumVal)); if (q) AktAtr.F.FIntens=AktAtr.L.LIntens; } break;
436 
437 				case EscMustr: { AktAtr.F.FMuster=sal_uInt16(ChgValue(Atr0.F.FMuster,0,65535,FlgVal,NumVal)); } break;
438 				case EscMFarb: { AktAtr.F.FFarbe =(sal_uInt8)(ChgValue(Atr0.F.FFarbe,0,7   ,FlgVal,NumVal));   } break;
439 				case EscMBFrb: { AktAtr.F.FBFarbe=(sal_uInt8)(ChgValue(Atr0.F.FBFarbe,0,255,FlgVal,NumVal));   } break;
440 				case EscMInts: { AktAtr.F.FIntens=(sal_uInt8)(ChgValue(Atr0.F.FIntens,0,100,FlgVal,NumVal));   } break;
441 
442 				case EscSMstr: { AktAtr.ShdF.FMuster=sal_uInt16(ChgValue(Atr0.ShdF.FMuster,0,65535,FlgVal,NumVal)); } break;
443 				case EscSFarb: { AktAtr.ShdL.LFarbe =(sal_uInt8)(ChgValue(Atr0.ShdL.LFarbe,0,7   ,FlgVal,NumVal)); AktAtr.ShdF.FFarbe =AktAtr.ShdL.LFarbe;  } break;
444 				case EscSBFrb: { AktAtr.ShdL.LBFarbe=(sal_uInt8)(ChgValue(Atr0.ShdL.LBFarbe,0,255,FlgVal,NumVal)); AktAtr.ShdF.FBFarbe=AktAtr.ShdL.LBFarbe; } break;
445 				case EscSInts: { AktAtr.ShdL.LIntens=(sal_uInt8)(ChgValue(Atr0.ShdL.LIntens,0,100,FlgVal,NumVal)); AktAtr.ShdF.FIntens=AktAtr.ShdL.LIntens; } break;
446 				case EscSDist: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); AktAtr.ShdVers.y=AktAtr.ShdVers.x; }            break;
447 				case EscSXDst: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); }  break;
448 				case EscSYDst: { AktAtr.ShdVers.y=(short)ChgValue(Atr0.ShdVers.y,0,30000,FlgVal,NumVal); }  break;
449 
450 				case EscBold : ChgSchnittBit(TextBoldBit,0,0,0                              ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
451 				case EscRSlnt: ChgSchnittBit(TextRSlnBit,TextLSlnBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
452 				case EscUndln: ChgSchnittBit(TextUndlBit,TextDbUnBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
453 				case EscStrik: ChgSchnittBit(TextStrkBit,TextDbStBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
454 				case EscDbUnd: ChgSchnittBit(TextDbUnBit,TextUndlBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
455 				case EscDbStk: ChgSchnittBit(TextDbStBit,TextStrkBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
456 				case EscSupSc: ChgSchnittBit(TextSupSBit,TextSubSBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
457 				case EscSubSc: ChgSchnittBit(TextSubSBit,TextSupSBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
458 				case EscKaptF: ChgSchnittBit(TextKaptBit,0,0,0                              ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
459 				case EscLSlnt: ChgSchnittBit(TextLSlnBit,TextRSlnBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
460 				case Esc2DShd: ChgSchnittBit(TextSh2DBit,TextSh3DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
461 				case Esc3DShd: ChgSchnittBit(TextSh3DBit,TextSh2DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
462 				case Esc4DShd: ChgSchnittBit(TextSh4DBit,TextSh2DBit,TextSh3DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
463 				case EscEbShd: ChgSchnittBit(TextShEbBit,TextSh2DBit,TextSh3DBit,TextSh4DBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
464 			} //endcase
465 			if (TBuf[Index]==Escape) Index++;         // zweites Esc weglesen }
466 		} // if Ende==sal_False
467 	} while (Ende==sal_False && ScanEsc==sal_False);
468 	if (Ende==sal_False) c=Escape;
469 	return c;
470 } // end of ProcessOne
471 
472 
473 UCHAR GetTextChar(UCHAR* TBuf, sal_uInt16& Index,
474 				  ObjTextType& Atr0, ObjTextType& AktAtr,
475 				  sal_uInt16 Rest, sal_Bool ScanEsc)
476 {
477 	UCHAR c,c0,nc;
478 
479 	c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc);
480 	if (ScanEsc==sal_False) {
481 		if (c==SoftTrennAdd || c==SoftTrennK || c==SoftTrenn) {
482 			nc=GetNextChar(TBuf,Index);
483 			c0=c;
484 			if (Rest==0 || Rest==DoTrenn ||
485 				nc==' ' || nc==AbsatzEnd || nc==TextEnd) c='-';
486 			else {
487                 c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // den Trenner ueberspringen
488 				if (c0==SoftTrennAdd) {
489                     if (c>=32) c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // und hier noch 'nen Buchstaben ueberspringen
490 				}
491 			}
492 		}
493 		if ((Rest==1 || Rest==DoTrenn) && GetNextChar(TBuf,Index)==SoftTrennK) {
494 			if (c=='c') c='k';
495 			else if (c=='C') c='K';
496 		}
497 	}
498 	return c;
499 }
500 
501   // HardSpace und HardTrenn muessen explizit konvertiert werden ! }
502   // if AktAtr.Schnitt and TextKaptBit =TextKaptBit then c:=UpCase(c);(explizit) }
503 
504   // Bei der Trennmethode SoftTrennAdd wird davon ausgegangen, dass der zu }
505   // trennende Konsonant bereits 3x mal im TextBuf vorhanden ist, z.b.:   }
506   // "Schiff-fahrt". Wenn nicht getrennt, dann wird "-f" entfernt.        }
507 
508 
509 
510 UCHAR GetTextCharConv(UCHAR* TBuf, sal_uInt16& Index,
511 					  ObjTextType& Atr0, ObjTextType& AktAtr,
512 					  sal_uInt16 Rest, sal_Bool ScanEsc)
513 {
514 	UCHAR c;
515 
516 	c=GetTextChar(TBuf,Index,Atr0,AktAtr,Rest,ScanEsc);
517 	if (c<32) {
518 		switch (c) {
519 			case HardSpace   : c=' '; break;
520 			case AbsatzEnd   : c=' '; break;
521 			case HardTrenn   : c='-';
522 		}
523 	}
524 	return c;
525 }
526 
527 
528 // ======================================================================
529 // Function GetLineFeed()
530 //
531 // Benoetigter Zeilenabstand in SGF-Units. ChrVPos wird beruecksichtigt.
532 // ======================================================================
533 sal_uInt16 GetLineFeed(UCHAR* TBuf, sal_uInt16 Index, ObjTextType Atr0, ObjTextType AktAtr,
534 				   sal_uInt16 nChar, sal_uInt16& LF, sal_uInt16& MaxGrad)
535 {
536 	UCHAR  c=0;
537 	sal_Bool   AbsEnd=sal_False;
538 	sal_uLong  LF100=0;
539 	sal_uLong  MaxLF100=0;
540 	sal_Bool   LFauto=0;
541 	sal_Bool   First=sal_True;
542 	sal_uInt16 Grad;
543 	sal_uInt16 i=0;
544 	sal_uInt16 r=1;
545 
546 	MaxGrad=0;
547 	while (!AbsEnd && nChar>0) {
548 		nChar--;
549 		c=GetTextChar(TBuf,Index,Atr0,AktAtr,nChar,sal_False);
550 		i++;
551 		AbsEnd=(c==TextEnd || c==AbsatzEnd);
552 		if (First || (!AbsEnd && c!=' ' && c!=HardTrenn)) {
553 			LFauto=(AktAtr.LnFeed & 0x8000)==0;
554 			LF100=AktAtr.LnFeed & 0x7FFF;
555 			if (LFauto) LF100=LF100*AktAtr.Grad; else LF100*=LF100;
556 			if (AktAtr.ChrVPos>0) LF100-=AktAtr.ChrVPos*100;
557 			if (LF100>MaxLF100) MaxLF100=LF100;
558 			Grad=AktAtr.Grad;
559 			if (AktAtr.ChrVPos>0) Grad=Grad-AktAtr.ChrVPos;
560 			if (Grad>MaxGrad) MaxGrad=Grad;
561 			First=sal_False;
562 		}
563 		if (!AbsEnd && c!=' ') r=i;
564 	}
565 	MaxGrad=hPoint2Sgf(MaxGrad);
566 	if (MaxLF100<=4000) {  // sonst Overflowgefahr
567 		LF=sal_uInt16(hPoint2Sgf(short(MaxLF100)) /100);
568 	} else {
569 		LF=sal_uInt16(hPoint2Sgf(short(MaxLF100) /100));
570 	}
571 
572 	return r;
573 }
574 
575 // End of AbsRead.Pas
576 /////////////////////////////////////////////////////////////////////////////////
577 /////////////////////////////////////////////////////////////////////////////////
578 /////////////////////////////////////////////////////////////////////////////////
579 
580 
581 
582 /////////////////////////////////////////////////////////////////////////////////
583 /////////////////////////////////////////////////////////////////////////////////
584 /////////////////////////////////////////////////////////////////////////////////
585 // iFont.Pas
586 
587 #define DefaultSlant 1500   /* Default: Italic ist 15deg                  */
588 #define SuperSubFact 60     /* SuperScript/SubScript: 60% vom Schriftgrad */
589 #define DefaultSpace 40     /* Default: Space ist 40% vom SchriftGrad     */
590 
591 sal_uInt16 SetTextContext(OutputDevice& rOut, ObjTextType& Atr, sal_Bool Kapt, sal_uInt16 Dreh,
592 					  sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
593 {
594 	SgfFontOne* pSgfFont; // Font aus dem IniFile
595 	Font   aFont;
596 	Color  aColor;
597 	sal_uLong  Grad;
598 	sal_uLong  Brei;
599 	String FNam;
600 	sal_uInt16 StdBrei=50;    // Durchschnittliche Zeichenbreite in % von Schriftgrad
601 	sal_Bool   bFit=(FitXMul!=1 || FitXDiv!=1 || FitYMul!=1 || FitYDiv!=1);
602 
603 	pSgfFont = pSgfFonts->GetFontDesc(Atr.GetFont());
604 
605 	if ( pSgfFont!=NULL )
606 	{
607 		FNam   =pSgfFont->SVFName;
608 		StdBrei=pSgfFont->SVWidth;
609 		if (pSgfFont->Fixd) aFont.SetPitch(PITCH_FIXED); else aFont.SetPitch(PITCH_VARIABLE);
610 		aFont.SetFamily(pSgfFont->SVFamil);
611 		aFont.SetCharSet(pSgfFont->SVChSet);
612 		aFont.SetName(FNam);
613 	}
614 	else
615 	{  // Falls nich im Inifile, sind hier einige Fonts hart kodiert
616 		aFont.SetPitch(PITCH_VARIABLE);
617 		switch (Atr.GetFont()) {
618 		  case 92500: case 92501: case 92504: case 92505:
619 		  {
620 #if defined(WNT) || defined(PM2)
621 			  FNam=String::CreateFromAscii( "Times New Roman" );  // CG Times ist unter Windows und OS/2 Times New Roman
622 #else
623 			  FNam=String::CreateFromAscii( "Times" );            // ansonsten ist das einfach Times
624 #endif
625 			  StdBrei=40;
626 			  aFont.SetFamily(FAMILY_ROMAN);
627 		  } break;
628 		  case 94021: case 94022: case 94023: case 94024: {
629 #if defined(WNT)
630 			  FNam=String::CreateFromAscii( "Arial", 5 );            // Univers ist unter Windows Arial
631 #else
632 			  FNam=String::CreateFromAscii( "Helvetica" );        // und ansonsten Helvetica
633 #endif
634 			  aFont.SetFamily(FAMILY_SWISS);
635 			  StdBrei=47;
636 		  } break;
637 		  case 93950: case 93951: case 93952: case 93953: {
638 #if defined(WNT)
639               FNam=String::CreateFromAscii( "Courier New" );      // Der Vector-Courierfont unter Windows heisst Courier New
640 #else
641 			  FNam=String::CreateFromAscii( "Courier" );          // ansonsten ist und bleibt Courier immer Courier
642 #endif
643 			  aFont.SetFamily(FAMILY_ROMAN);
644 			  aFont.SetPitch(PITCH_FIXED);
645 		  } break;
646 		  default: FNam=String::CreateFromAscii( "Helvetica", 9 );
647 		}
648 		aFont.SetName(FNam);
649 		//aFont.SetCharSet(CHARSET_SYSTEM);
650 	}
651 
652 	Grad=sal_uLong(Atr.Grad);
653 	if ((Atr.Schnitt & TextKaptBit) !=0 && Kapt) Grad=Grad*sal_uLong(Atr.Kapit)/100;
654 	if ((Atr.Schnitt & TextSupSBit) !=0 || (Atr.Schnitt & TextSubSBit) !=0) Grad=Grad*SuperSubFact/100;
655 	Brei=Grad;
656 	if (Atr.Breite!=100 || bFit) {
657 		if (bFit) {
658 			Grad=Grad*sal_uLong(FitYMul)/sal_uLong(FitYDiv);
659 			Brei=Brei*sal_uLong(FitXMul)/sal_uLong(FitXDiv);
660 		}
661 		Brei=Brei*sal_uLong(Atr.Breite)/100;
662 		Brei=Brei*sal_uLong(StdBrei)/100;
663 		aFont.SetSize(Size(hPoint2Sgf(sal_uInt16(Brei)),hPoint2Sgf(sal_uInt16(Grad))));
664 	} else {
665 		aFont.SetSize(Size(0,hPoint2Sgf(sal_uInt16(Grad))));
666 	}
667 
668 	aColor=Sgv2SvFarbe(Atr.L.LFarbe,Atr.L.LBFarbe,Atr.L.LIntens); aFont.SetColor(aColor);
669 	aColor=Sgv2SvFarbe(Atr.F.FFarbe,Atr.F.FBFarbe,Atr.F.FIntens); aFont.SetFillColor(aColor);
670 	aFont.SetTransparent(sal_True);
671 	aFont.SetAlign(ALIGN_BASELINE);
672 
673 	Dreh/=10; Dreh=3600-Dreh; if (Dreh==3600) Dreh=0;
674 	aFont.SetOrientation(Dreh);
675 
676 	if ((Atr.Schnitt & TextBoldBit) !=0) aFont.SetWeight(WEIGHT_BOLD);
677 	if ((Atr.Schnitt & TextRSlnBit) !=0) aFont.SetItalic(ITALIC_NORMAL);
678 	if ((Atr.Schnitt & TextUndlBit) !=0) aFont.SetUnderline(UNDERLINE_SINGLE);
679 	if ((Atr.Schnitt & TextDbUnBit) !=0) aFont.SetUnderline(UNDERLINE_DOUBLE);
680 	if ((Atr.Schnitt & TextStrkBit) !=0) aFont.SetStrikeout(STRIKEOUT_SINGLE);
681 	if ((Atr.Schnitt & TextDbStBit) !=0) aFont.SetStrikeout(STRIKEOUT_DOUBLE);
682 	if ((Atr.Schnitt & TextSh2DBit) !=0) aFont.SetShadow(sal_True);
683 	if ((Atr.Schnitt & TextSh3DBit) !=0) aFont.SetShadow(sal_True);
684 	if ((Atr.Schnitt & TextSh4DBit) !=0) aFont.SetShadow(sal_True);
685 	if ((Atr.Schnitt & TextShEbBit) !=0) aFont.SetShadow(sal_True);
686 	if (CheckTextOutl(Atr.F,Atr.L)) aFont.SetOutline(sal_True);
687 
688 	if (aFont!=rOut.GetFont()) rOut.SetFont(aFont);
689 
690 	return 0;
691 }
692 
693 // iFont.Pas
694 /////////////////////////////////////////////////////////////////////////////////
695 /////////////////////////////////////////////////////////////////////////////////
696 /////////////////////////////////////////////////////////////////////////////////
697 
698 
699 /////////////////////////////////////////////////////////////////////////////////
700 /////////////////////////////////////////////////////////////////////////////////
701 /////////////////////////////////////////////////////////////////////////////////
702 // Absatz.Pas
703 
704 struct ProcChrSta {
705 	sal_uInt16 Index;
706 	sal_uInt16 ChrXP;
707 	UCHAR  OutCh;
708 	sal_Bool   Kapt;
709 	ObjTextType Attrib;
710 };
711 
712 void InitProcessCharState(ProcChrSta& State, ObjTextType& AktAtr, sal_uInt16 IndexA)
713 {
714 	State.Attrib=AktAtr;
715 	State.OutCh=0;
716 	State.Index=IndexA;
717 	State.ChrXP=0;
718 	State.Kapt=sal_False;
719 }
720 
721 sal_Bool UpcasePossible(UCHAR c)
722 {
723 	if ((c>='a' && c<='z') || c == 0xe4 || c == 0xf6 || c == 0xfc ) return sal_True;
724 	else return sal_False;
725 }
726 
727 UCHAR Upcase(UCHAR c)
728 {
729 	if ((c>=(UCHAR)'a' && c<=(UCHAR)'z')) c=(c-(UCHAR)'a')+(UCHAR)'A';
730 	else if ( c == 0xe4 ) c = 0xc4;
731 	else if ( c == 0xf6 ) c = 0xd6;
732 	else if ( c == 0xfc ) c = 0xdc;
733 	return c;
734 }
735 
736 sal_uInt16 GetCharWidth(OutputDevice& rOut, UCHAR c)
737 {
738 	UCHAR  c1;
739 	sal_uInt16 ChrWidth;
740 
741 	c1 = ByteString::Convert((char)c,RTL_TEXTENCODING_IBM_437, gsl_getSystemTextEncoding() );
742 	if (c==' ')
743 	{
744 		ChrWidth=(sal_uInt16)rOut.GetTextWidth( String('A') );
745 		if (rOut.GetFont().GetPitch()!=PITCH_FIXED) {
746 			ChrWidth=MulDiv(ChrWidth,DefaultSpace,100);
747 		}
748 	} else {
749          // with MaxChar == 255 c cannot be greater than MaxChar
750          // assert if MaxChar is ever changed
751         OSL_ENSURE( MaxChar == 255, "MaxChar not 255" );
752 		if (c>=MinChar /*&& c<=MaxChar*/)
753         {
754 			ChrWidth=(sal_uInt16)rOut.GetTextWidth(String((char)c1));
755 		}
756         else
757         {
758 			ChrWidth=(sal_uInt16)rOut.GetTextWidth(String('A'));
759 		}
760 	}
761 	return ChrWidth;
762 }
763 
764 UCHAR ProcessChar(OutputDevice& rOut, UCHAR* TBuf, ProcChrSta& R, ObjTextType& Atr0,
765 				  sal_uInt16& nChars, sal_uInt16 Rest,
766 				  short* Line, UCHAR* cLine)
767 {
768     sal_uInt16       KernDist=0;       // Wert fuer Kerning
769 	sal_uInt16       ChrWidth;
770 	UCHAR        c;
771 	UCHAR        c1;
772 	sal_Bool         AbsEnd;
773 
774 	c=GetTextChar(TBuf,R.Index,Atr0,R.Attrib,Rest,sal_False); // versucht evtl. zu trennen, wenn Rest entsprechenden Wert besitzt
775 
776 	AbsEnd=(c==AbsatzEnd || c==TextEnd);
777 	if (AbsEnd==sal_False) {
778 		R.OutCh=ConvertTextChar(c); // von HardTrenn nach '-', ...
779 		R.Kapt=(R.Attrib.Schnitt & TextKaptBit) !=0 && UpcasePossible(R.OutCh);
780 		if (R.Kapt) R.OutCh=Upcase(R.OutCh);
781 		SetTextContext(rOut,R.Attrib,R.Kapt,0,1,1,1,1);
782 
783 		if (R.Kapt) c1=Upcase(c); else c1=c;
784 		ChrWidth=GetCharWidth(rOut,c1);
785 
786 		if (R.Attrib.ZAbst!=100) { // Spezial-Zeichenabstand ?
787 			sal_uLong Temp;
788 			Temp=sal_uLong(ChrWidth)*sal_uLong(R.Attrib.ZAbst)/100;
789 			ChrWidth=sal_uInt16(Temp);
790 		}
791 		nChars++;
792 		if (R.ChrXP>32000) R.ChrXP=32000;
793 		Line[nChars]=R.ChrXP-KernDist;
794 		cLine[nChars]=c;
795         R.ChrXP+=ChrWidth-KernDist; // Position fuer den naechsten Character
796 	}
797 	return c;
798 }
799 
800 void FormatLine(UCHAR* TBuf, sal_uInt16& Index, ObjTextType& Atr0, ObjTextType& AktAtr,
801 				sal_uInt16 UmbWdt, sal_uInt16 AdjWdt,
802 				short* Line, sal_uInt16& nChars,
803 				double, double,
804 				UCHAR* cLine, sal_Bool TextFit)
805 {
806 	VirtualDevice vOut;
807 	UCHAR        c,c0;
808 	UCHAR        ct;
809 	sal_Bool         First;               // erster Char ?
810 	sal_uInt8         Just = 0;                // Absatzformatierung
811 	sal_Bool         Border;              // Rand der Box erreicht ?
812 	sal_Bool         Border0;
813 	sal_Bool         AbsEnd;              // Ende des Absatzes erreicht ?
814 	ProcChrSta*  R=new ProcChrSta;
815 	ProcChrSta*  R0=new ProcChrSta;
816 	ProcChrSta*  WErec=new ProcChrSta;
817 	sal_uInt16       WEnChar;
818 	ProcChrSta*  WErec0=new ProcChrSta;
819 	sal_uInt16       WEnChar0;
820 	ProcChrSta*  TRrec=new ProcChrSta;
821 	sal_uInt16       TRnChar;
822 
823 	sal_uInt16       WordEndCnt;          // Justieren und Trennen
824 	sal_Bool         WordEnd;
825 	sal_Bool         Trenn;
826 
827 	short        BoxRest;             // zum Quetschen und formatieren
828 	sal_uInt16       i,j,k,h;
829 	sal_uInt16       re,li;
830 
831 	vOut.SetMapMode(MapMode(MAP_10TH_MM,Point(),Fraction(1,4),Fraction(1,4)));
832 
833 	nChars=0;
834 	SetTextContext(vOut,AktAtr,sal_False,0,1,1,1,1);
835 	InitProcessCharState(*R,AktAtr,Index);
836 	(*R0)=(*R); (*WErec)=(*R); WEnChar=0; c0=0; Border0=sal_False;
837 	Border=sal_False; First=sal_True;
838 	WordEndCnt=0;
839 
840 	do {               // mal schauen, wieviele Worte so in die Zeile passen
841 		if (Border) c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,DoTrenn,Line,cLine);
842 		else        c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
843 		AbsEnd=(c==AbsatzEnd || c==TextEnd);
844 		//if not AbsEnd then
845 		{
846 			if (First) {
847 				Just=R->Attrib.Justify & 0x0F; // Absatzformat steht wenn, dann am Anfang
848 			}
849 			Border=R->ChrXP>UmbWdt;
850 			WordEnd=(AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0);
851 			Trenn=c=='-';
852 			if (WordEnd && !Border0) {
853 				WordEndCnt++;
854 				(*WErec)=(*R0);
855 				WEnChar=nChars-1;
856 			}
857 			if (Trenn && !Border) {
858 				WordEndCnt++;
859 				(*WErec)=(*R);
860 				WEnChar=nChars;
861 			}
862 		}
863 		(*R0)=(*R); c0=c;
864 		Border0=Border;
865 		First=sal_False;
866 		AbsEnd=AbsEnd || (nChars>=MaxLineChars);
867 	} while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
868 
869 	if (Border) { // Trennen und Quetschen
870 		(*WErec0)=(*WErec); WEnChar0=WEnChar;
871 		AbsEnd=sal_False; c0=0;
872 		(*R)=(*WErec); nChars=WEnChar;
873 		(*TRrec)=(*R); TRnChar=nChars;
874 		Border0=sal_False; Border=sal_False;
875 		do {                // erst mal gucken wieviele Silben noch reinpassen
876 			ct=ProcessChar(vOut,TBuf,*TRrec,Atr0,TRnChar,DoTrenn,Line,cLine);
877 			c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
878 			AbsEnd=(ct==AbsatzEnd) || (ct==TextEnd) || (nChars>=MaxLineChars);
879 
880 			Border=TRrec->ChrXP>UmbWdt;
881 			WordEnd=AbsEnd || ((AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0));
882 			Trenn=ct=='-';
883 			if (WordEnd && (!Border0 || (WordEndCnt==0))) {
884 				WordEndCnt++;
885 				(*WErec)=(*R0);
886 				if (AbsEnd) WEnChar=nChars; else WEnChar=nChars-1;
887 				(*TRrec)=(*R); TRnChar=nChars;                       // zum weitersuchen
888 			}
889 			if (Trenn && (!Border || (WordEndCnt==0))) {
890                 WordEndCnt++;                 // merken, dass man hier trennen kann
891 				(*WErec)=(*TRrec);
892 				WEnChar=TRnChar;
893 				(*TRrec)=(*R); TRnChar=nChars;                       // zum weitersuchen
894 			}
895 			(*R0)=(*R); c0=c;
896 			Border0=Border;
897 			Border=R->ChrXP>UmbWdt;
898 		} while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
899 
900 		while (WErec0->Index<WErec->Index) { // damit Line[] auch garantiert stimmt }
901 			c=ProcessChar(vOut,TBuf,*WErec0,Atr0,WEnChar0,WEnChar-WEnChar0-1,Line,cLine);
902 		}
903 
904 		(*R)=(*WErec); nChars=WEnChar;
905 
906 		if (UmbWdt>=R->ChrXP) {
907 			BoxRest=UmbWdt-R->ChrXP;
908 		} else {                                       // Zusammenquetschen
909             BoxRest=R->ChrXP-UmbWdt;                     // um soviel muss gequetscht werden
910 			for (i=2;i<=nChars;i++) {                  // 1. CharPosition bleibt !
911 				Line[i]-=(i-1)*(BoxRest) /(nChars-1);
912 			}
913 			R->ChrXP=UmbWdt;
914 			Line[nChars+1]=UmbWdt;
915 		}
916 	}
917 
918 	if (!AbsEnd) {
919 		do {                                         // Leerzeichen weglesen
920 			(*WErec)=(*R);
921 			c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False);
922 			nChars++;
923 			Line[nChars]=R->ChrXP;
924 			cLine[nChars]=c;
925 		} while (c==' ');
926 		if (c!=' ' && c!=AbsatzEnd && c!=TextEnd) {
927 			nChars--;
928 			(*R)=(*WErec);
929 		}
930 	}
931 
932     if (AbsEnd && nChars<MaxLineChars) { // Ausrichten, statt Blocksatz aber linksbuendig
933 		if (Just==3) Just=0;
934 		nChars++; Line[nChars]=R->ChrXP; // Damit AbsatzEnde auch weggelesen wird
935 		Line[nChars+1]=R->ChrXP;         // denn die Breite von CR oder #0 ist nun mal sehr klein
936 		if (TBuf[R->Index-1]!=AbsatzEnd &&  TBuf[R->Index-1]!=TextEnd) {
937 			c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False); // Kleine Korrektur. Notig, wenn nur 1 Wort in
938 		}
939 	}
940 
941 	BoxRest=AdjWdt-R->ChrXP;
942 	if (TextFit) Just=THJustLeft;
943 
944 	switch (Just) {
945 		case THJustLeft: break;                                // Links
946 		case THJustCenter: {
947 			BoxRest=BoxRest /2;                                // Mitte
948 			for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
949 		} break;
950 		case THJustRight: {                                    // Rechts
951 			for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
952 		} break;
953 		case THJustDrvOut:
954 		case THJustBlock: {                                    // Block und Austreibend
955 			re=nChars;
956 			if (Just==THJustDrvOut) re--;
957 			while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
958 			li=1;
959 			while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
960 			if (Just==THJustDrvOut) BoxRest=AdjWdt-Line[re+1];
961 
962 			j=0;                        // Anzahl der Spaces ermitteln
963 			for (i=li;i<=re;i++) {
964 				if (cLine[i]==' ') {
965 					j++;
966 				}
967 			}
968 
969 			if (j==0) {                        // nur 1 Wort ?  -> Strecken !
970 				for (i=li+1;i<=re;i++) {       // von links nach rechts
971 				  Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
972 				}
973 			} else {
974 				k=0; h=0;
975 				for (i=li;i<=re;i++) {          // j Spaces aufbohren !
976 					if (cLine[i]==' ') {        // Space gefunden !
977 						k++;
978 						h=MulDiv(k,BoxRest,j);
979 					}
980 					Line[i]=Line[i]+h;
981 				}
982 			}
983 			for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
984 			Line[nChars+1]=AdjWdt;
985 		} break;
986 		case THJustLocked: {                                    //Gesperrt
987 			re=nChars-1;
988 			while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
989 			li=1;
990 			while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
991 			BoxRest=AdjWdt-Line[re+1];
992 			for (i=li+1;i<=re;i++) {         // Strecken von links nach rechts
993 				Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
994 			}
995 			for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
996 			Line[nChars+1]=AdjWdt;
997 		} break;
998 	}
999 	Index=R->Index;
1000 	AktAtr=R->Attrib;
1001 	delete R;
1002 	delete R0;
1003 	delete WErec;
1004 	delete WErec0;
1005 	delete TRrec;
1006 }
1007 
1008 
1009 
1010 // End of Absatz.Pas
1011 /////////////////////////////////////////////////////////////////////////////////
1012 /////////////////////////////////////////////////////////////////////////////////
1013 /////////////////////////////////////////////////////////////////////////////////
1014 
1015 
1016 /////////////////////////////////////////////////////////////////////////////////
1017 /////////////////////////////////////////////////////////////////////////////////
1018 /////////////////////////////////////////////////////////////////////////////////
1019 // DrawText.Pas
1020 
1021 void DrawChar(OutputDevice& rOut, UCHAR c, ObjTextType T, PointType Pos, sal_uInt16 DrehWink,
1022 			  sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
1023 {
1024 	SetTextContext(rOut,T,UpcasePossible(c),DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
1025 	if ((T.Schnitt & TextKaptBit)!=0 && UpcasePossible(c)) c=Upcase(c);
1026 	String s( (char)c, RTL_TEXTENCODING_IBM_437 );
1027 	rOut.DrawText( Point( Pos.x, Pos.y ), s );
1028 }
1029 
1030 /*************************************************************************
1031 |*
1032 |*    TextType::Draw()
1033 |*
1034 |*    Beschreibung
1035 |*    Ersterstellung    JOE 09.08.93
1036 |*    Letzte Aenderung  JOE 09.08.93
1037 |*
1038 *************************************************************************/
1039 void TextType::Draw(OutputDevice& rOut)
1040 {
1041     if ((Flags & TextOutlBit)!=0) return;   // Sourcetext fuer Outliner !!
1042 
1043 	ObjTextType T1,T2;
1044 	sal_uInt16 Index1;
1045 	sal_uInt16 Index2;
1046 	UCHAR  c = TextEnd;
1047 	sal_uInt16 l;                // Anzahl der Zeichen in der Zeile
1048 	sal_uInt16 i;
1049 	short  yPos0;
1050 	short  xPos;
1051 	short  yPos;
1052 	sal_uInt16 LF;
1053 	sal_uInt16 MaxGrad;
1054 	short  xSize;
1055 	short  xSAdj;
1056 	short  ySize;
1057 	double sn,cs;
1058 	sal_uInt16 TopToBase;
1059 	sal_Bool   Ende = 0;
1060 	sal_uInt16 lc;
1061 	sal_Bool   LineFit; // FitSize.x=0? oder Flags -> jede Zeile stretchen
1062 	sal_Bool   TextFit;
1063 	short* xLine;
1064     UCHAR* cLine;   // Buffer fuer FormatLine
1065 	sal_uInt16 FitXMul;
1066 	sal_uInt16 FitXDiv;
1067 	sal_uInt16 FitYMul;
1068 	sal_uInt16 FitYDiv;
1069 	sal_Bool   Fehler;
1070 	UCHAR* Buf=Buffer; // Zeiger auf die Buchstaben
1071 
1072 	pSgfFonts->ReadList();
1073 	xLine=new short[ChrXPosArrSize];
1074 	cLine=new UCHAR[CharLineSize];
1075 
1076 	TextFit=(Flags & TextFitBits)!=0;
1077 	LineFit=sal_False;
1078 	LineFit=((Flags & TextFitZBit)!=0);
1079 	if (TextFit && FitSize.x==0) LineFit=sal_True;
1080 
1081 	if (DrehWink==0) {
1082 		sn=0.0;
1083 		cs=1.0;
1084 	} else {
1085 		sn=sin(double(DrehWink)*3.14159265359/18000);
1086 		cs=cos(double(DrehWink)*3.14159265359/18000);
1087 	}
1088 
1089 	T1=T; Index1=0; yPos=0; xPos=0;
1090 	if (TextFit) {
1091 		ySize=Pos2.y-Pos1.y;
1092 		xSize=32000 /2;      // Umbruch
1093 		xSAdj=Pos2.x-Pos1.x; // zum Ausrichten bei Zentriert/Blocksatz
1094 		//if (xSize<=0) { xSize=32000 /2; LineFit=sal_True; }
1095 		FitXMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.x-Pos1.x)); FitXDiv=FitSize.x; if (FitXDiv==0) FitXDiv=1;
1096 		FitYMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.y-Pos1.y)); FitYDiv=FitSize.y; if (FitYDiv==0) FitYDiv=1;
1097 	} else {
1098 		xSize=Pos2.x-Pos1.x;
1099 		xSAdj=xSize;
1100 		ySize=Pos2.y-Pos1.y;
1101 		FitXMul=1; FitXDiv=1;
1102 		FitYMul=1; FitYDiv=1;
1103 	}
1104 	if (xSize<0) xSize=0;
1105 	if (xSAdj<0) xSAdj=0;
1106 
1107 	do {
1108 		T2=T1; Index2=Index1;
1109 		FormatLine(Buf,Index2,T,T2,xSize,xSAdj,xLine,l,sn,cs,cLine,LineFit);
1110 		Fehler=(Index2==Index1);
1111 		if (!Fehler) {
1112 			lc=GetLineFeed(Buf,Index1,T,T1,l,LF,MaxGrad);
1113 			if (TextFit) {
1114 				if (LineFit) FitXDiv=xLine[lc+1];
1115 				if (FitXDiv>0) {
1116 					long Temp;
1117 					for (i=1;i<=l+1;i++) {
1118 						Temp=long(xLine[i])*long(FitXMul) /long(FitXDiv);
1119 						xLine[i]=short(Temp);
1120 					}
1121 					LF=MulDiv(LF,FitYMul,FitYDiv);
1122 					MaxGrad=MulDiv(MaxGrad,FitYMul,FitYDiv);
1123 				} else {
1124 					FitXDiv=1; // 0 gibts nicht
1125 				}
1126 			}
1127 			yPos0=yPos;
1128 			TopToBase=GetTopToBaseLine(MaxGrad);
1129 			yPos=yPos+TopToBase;
1130 			Ende=(yPos0+short(MulDiv(MaxGrad,CharTopToBtm,100))>ySize) && !TextFit;
1131 			if (!Ende) {
1132 				T2=T1; Index2=Index1;
1133 				i=1;
1134 				while (i<=l) {
1135 					c=GetTextCharConv(Buf,Index2,T,T2,l-i,sal_False);
1136 					long xp1,yp1;       // wegen Overflowgefahr
1137 					PointType Pos;
1138 					xp1=long(Pos1.x)+xPos+long(xLine[i]);
1139 					yp1=long(Pos1.y)+yPos;
1140 					if (xp1>32000) xp1=32000; if (xp1<-12000) xp1=-12000;
1141 					if (yp1>32000) yp1=32000; if (yp1<-12000) yp1=-12000;
1142 					Pos.x=short(xp1);
1143 					Pos.y=short(yp1);
1144 
1145 					if (DrehWink!=0) RotatePoint(Pos,Pos1.x,Pos1.y,sn,cs);
1146 					DrawChar(rOut,c,T2,Pos,DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
1147 					i++;
1148 				} // while i<=l
1149 				yPos=yPos0+LF;
1150                 T1=T2; Index1=Index2; // Fuer die naechste Zeile
1151 			} // if ObjMin.y+yPos<=Obj_Max.y
1152 		} // if !Fehler
1153 	} while (c!=TextEnd && !Ende && !Fehler);
1154 	delete[] cLine;
1155 	delete[] xLine;
1156 }
1157 
1158 // End of DrawText.Pas
1159 /////////////////////////////////////////////////////////////////////////////////
1160 /////////////////////////////////////////////////////////////////////////////////
1161 /////////////////////////////////////////////////////////////////////////////////
1162 
1163 // nicht mehr benoetigt, da der Pointer nun extra gefuehrt wird
1164 // (DEC Alpha hat naemlich 64Bit-Pointer!)
1165 //UCHAR* TextType::GetBufPtr()
1166 //{
1167 //    sal_uLong Temp;
1168 //    Temp=sal_uLong(BufLo)+0x00010000*sal_uLong(BufHi);
1169 //    return (UCHAR*)Temp;
1170 //}
1171 //
1172 //void TextType::SetBufPtr(UCHAR* Ptr)
1173 //{
1174 //    sal_uLong Temp=(sal_uLong)Ptr;
1175 //    BufLo=sal_uInt16(Temp & 0x0000FFFF);
1176 //    BufHi=sal_uInt16((Temp & 0xFFFF0000)>>16);
1177 //}
1178 
1179 sal_uInt32 ObjTextType::GetFont()
1180 {
1181 	return sal_uLong(FontLo)+0x00010000*sal_uLong(FontHi);
1182 }
1183 
1184 void ObjTextType::SetFont(sal_uInt32 FontID)
1185 {
1186 	FontLo=sal_uInt16(FontID & 0x0000FFFF);
1187 	FontHi=sal_uInt16((FontID & 0xFFFF0000)>>16);
1188 }
1189 
1190 
1191 /////////////////////////////////////////////////////////////////////////////////
1192 // SGF.Ini lesen ////////////////////////////////////////////////////////////////
1193 /////////////////////////////////////////////////////////////////////////////////
1194 SgfFontOne::SgfFontOne()
1195 {
1196 	Next=NULL;
1197 	IFID=0;
1198 	Bold=sal_False;
1199 	Ital=sal_False;
1200 	Sans=sal_False;
1201 	Serf=sal_False;
1202 	Fixd=sal_False;
1203 	SVFamil=FAMILY_DONTKNOW;
1204 	SVChSet=RTL_TEXTENCODING_DONTKNOW;
1205 	SVWidth=40;
1206 }
1207 
1208 void SgfFontOne::ReadOne( ByteString& ID, ByteString& Dsc )
1209 {
1210 	sal_uInt16 i,j,n;
1211 	ByteString s;
1212 
1213 	if ( Dsc.Len() < 4 || ( Dsc.GetChar( 0 ) != '(' ) )
1214 		return;
1215 	i=1;   // Erster Buchstabe des IF-Fontnamen. Davor ist eine '('
1216 	while ( i < Dsc.Len() && ( Dsc.GetChar( i ) !=')' ) )
1217 		i++;
1218     Dsc.Erase(0,i+1);                                // IF-Fontname loeschen inkl. ()
1219 
1220 	if ( Dsc.Len() < 2 || ( Dsc.GetChar( Dsc.Len() - 1 ) !=')' ) )
1221 		return;
1222 	i=Dsc.Len()-2;                                   // hier ist die ')' des SV-Fontnames
1223 	j=0;
1224 	while ( i > 0 && ( Dsc.GetChar( i ) != '(' ) )
1225 	{
1226 		i--;
1227 		j++;
1228 	}
1229 	SVFName=String(Dsc,i+1,j);                       // SV-Fontname rausholen
1230 	Dsc.Erase(i,j);
1231 
1232 	IFID = (sal_uInt32)ID.ToInt32();
1233 	n=Dsc.GetTokenCount(' ');
1234 	for (i=0;i<n;i++)
1235 	{
1236 		s = Dsc.GetToken( i,' ' );
1237 		if ( s.Len() )
1238 		{
1239 			s.ToUpperAscii();
1240 			if      ( s.CompareTo( "BOLD", 4 ) == COMPARE_EQUAL ) Bold=sal_True;
1241 			else if ( s.CompareTo( "ITAL", 4 ) == COMPARE_EQUAL ) Ital=sal_True;
1242 			else if ( s.CompareTo( "SERF", 4 ) == COMPARE_EQUAL ) Serf=sal_True;
1243 			else if ( s.CompareTo( "SANS", 4 ) == COMPARE_EQUAL ) Sans=sal_True;
1244 			else if ( s.CompareTo( "FIXD", 4 ) == COMPARE_EQUAL ) Fixd=sal_True;
1245 			else if ( s.CompareTo( "ROMAN", 5 ) == COMPARE_EQUAL ) SVFamil=FAMILY_ROMAN;
1246 			else if ( s.CompareTo( "SWISS", 5 ) == COMPARE_EQUAL ) SVFamil=FAMILY_SWISS;
1247 			else if ( s.CompareTo( "MODERN", 6 ) == COMPARE_EQUAL ) SVFamil=FAMILY_MODERN;
1248 			else if ( s.CompareTo( "SCRIPT", 6 ) == COMPARE_EQUAL ) SVFamil=FAMILY_SCRIPT;
1249 			else if ( s.CompareTo( "DECORA", 6 ) == COMPARE_EQUAL ) SVFamil=FAMILY_DECORATIVE;
1250 			else if ( s.CompareTo( "ANSI", 4 ) == COMPARE_EQUAL ) SVChSet=RTL_TEXTENCODING_MS_1252;
1251 			else if ( s.CompareTo( "IBMPC", 5 ) == COMPARE_EQUAL ) SVChSet=RTL_TEXTENCODING_IBM_850;
1252 			else if ( s.CompareTo( "MAC", 3 ) == COMPARE_EQUAL ) SVChSet=RTL_TEXTENCODING_APPLE_ROMAN;
1253 			else if ( s.CompareTo( "SYMBOL", 6 ) == COMPARE_EQUAL ) SVChSet=RTL_TEXTENCODING_SYMBOL;
1254 			else if ( s.CompareTo( "SYSTEM", 6 ) == COMPARE_EQUAL ) SVChSet = gsl_getSystemTextEncoding();
1255 			else if ( s.IsNumericAscii() ) SVWidth=sal::static_int_cast< sal_uInt16 >(s.ToInt32());
1256 		}
1257 	}
1258 }
1259 
1260 /////////////////////////////////////////////////////////////////////////////////
1261 
1262 SgfFontLst::SgfFontLst()
1263 {
1264 	pList=NULL;
1265 	Last=NULL;
1266 	LastID=0;
1267 	LastLn=NULL;
1268 	Tried=sal_False;
1269 }
1270 
1271 SgfFontLst::~SgfFontLst()
1272 {
1273 	RausList();
1274 }
1275 
1276 void SgfFontLst::RausList()
1277 {
1278 	SgfFontOne* P;
1279 	SgfFontOne* P1;
1280 	P=pList;
1281 	while (P!=NULL) {
1282 		P1=P->Next;
1283 		delete P;
1284 		P=P1;
1285 	}
1286 	pList=NULL;
1287 	Last=NULL;
1288 	Tried=sal_False;
1289 	LastID=0;
1290 	LastLn=NULL;
1291 }
1292 
1293 void SgfFontLst::AssignFN(const String& rFName)
1294 {   FNam=rFName;   }
1295 
1296 void SgfFontLst::ReadList()
1297 {
1298 	if (!Tried) {
1299 		Tried=sal_True;
1300 		LastID=0;
1301 		LastLn=NULL;
1302 		SgfFontOne* P,P1;
1303 		Config aCfg(FNam);
1304 		aCfg.SetGroup("SGV Fonts fuer StarView");
1305 		sal_uInt16 Anz=aCfg.GetKeyCount();
1306 		sal_uInt16 i;
1307 		ByteString FID,Dsc;
1308 
1309 		for (i=0;i<Anz;i++)
1310 		{
1311 			FID = aCfg.GetKeyName( i );
1312 			FID = FID.EraseAllChars(); // Leerzeichen weg
1313 			Dsc = aCfg.ReadKey( i );
1314 			if ( FID.IsNumericAscii() )
1315 			{
1316 				P=new SgfFontOne;                                   // neuer Eintrag
1317 				if (Last!=NULL) Last->Next=P; else pList=P; Last=P; // einklinken
1318 				P->ReadOne(FID,Dsc);                                // und Zeile interpretieren
1319 			}
1320 		}
1321 	}
1322 }
1323 
1324 SgfFontOne* SgfFontLst::GetFontDesc(sal_uInt32 ID)
1325 {
1326 	if (ID!=LastID) {
1327 		SgfFontOne* P;
1328 		P=pList;
1329 		while (P!=NULL && P->IFID!=ID) P=P->Next;
1330 		LastID=ID;
1331 		LastLn=P;
1332 	}
1333 	return LastLn;
1334 }
1335