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