1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/


#include <rtl/math.h>
#include <comphelper/string.hxx>
#include <tools/config.hxx>
#include <svtools/filter.hxx>
#include "sgffilt.hxx"
#include "sgfbram.hxx"
#include "sgvmain.hxx"

extern SgfFontLst* pSgfFonts;

#ifndef abs
#define abs(x) ((x)<0 ? -(x) : (x))
#endif


////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Einschraenkungen: Schatten nur grau, 2D und mit fixem Abstand.
//
//
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// AbsBase.Pas

// die folgenden Werte sind in % vom maximalen Schriftgrad der Zeile   */
#define  UndlSpace  5 /* Untersteichungsabstand von der Baseline       */
#define  UndlWidth  6 /* Untersteichungsdicke                          */
#define  UndlSpac2  7 /* Zwischenraum bei doppelter Unterstreichung    */
#define  StrkSpace 25 /* Abstand der Durchstreichlinie von der Baseline*/
#define  StrkWidth  5 /* Durchstreichungsliniendicke                   */
#define  StrkSpac2  7 /* Zwischenraum bei doppelter Durchstreichung    */
#define  OutlWidth  2 /* Strichstaerke ist 2% vom Schriftgrad          */

// vvv Sonderzeichen im TextBuffer vvv
#define  TextEnd        0 /* ^@ Ende der Zeichenkette                           */
#define  HardSpace      6 /* ^F Hartspace (wird nicht umbrochen) ,' '           */
#define  GrafText       7 /* ^G Im Text eingebundene Grafik (future)            */
#define  Tabulator      9 /* ^I Tabulatorzeichen, Pfeil                         */
#define  LineFeed      10 /* ^J Neue Zeile                                      */
#define  SoftTrennK    11 /* ^K Zeichen fuer k-c-Austausch bei Trennung, 'k'    */
#define  AbsatzEnd     13 /* ^M Neuer Absatz =CR                                */
#define  HardTrenn     16 /* ^P Hartes Trennzeichen (wird nicht umbrochen), '-' */
#define  SoftTrennAdd  19 /* ^S Zusatz-Zeichen Trennung von z.b."Schiff-fahrt"  */
#define  Paragraf      21 /* ^U Zeichen welches fuer Paragraf-Zeichen           */
#define  Escape        27 /* ^[ Escapesequenz einleiten                         */
#define  SoftTrenn     31 /* ^_ Weiches Trennzeichen, '-' nur Zeilenende        */
#define  MaxEscValLen  8
#define  MaxEscLen     (MaxEscValLen+3)

//==============================================================================
// Escapesequenzen: [Esc]<Ident><Value>[Esc]  also mind. 4 Char
// Max. Laenge von Value soll sein: 8 Char (7+Vorzeichen). Demnach max. Laenge
// einer Escapesequenz: 11 Char.
// Identifer:

#define  EscFont   'F' /* FontID, z.B. 92500 fuer CG Times                          */
#define  EscGrad   'G' /* Schriftgrad 1..255 fuer <<Pt-127<<Pt                      */
#define  EscBreit  'B' /* Breite 1..255% des Schriftgrades                          */
#define  EscKaptS  'K' /* Kapitaelchengroesse 1..255% des Schriftgrades             */
#define  EscLFeed  'L' /* Zeilenabstand 1..32767% vom max. Schriftgrad der Zeile    */
                        // oder 1..32767 fuer 1..16383<<Pt absolut (Wenn Bit 15=1)
#define  EscSlant  'S' /* Kursiv(Winkel) 1..8999 fuer 0.01deg..89.99deg             */
#define  EscVPos   'V' /* Zeichen Vertikal-Position  1..255 fuer <<Pt..127<<Pt      */
#define  EscZAbst  'Z' /* Zeichenabstand -128..127%                                 */
#define  EscHJust  'A' /* H-Justify    Absatz: Links, Zentr, Rechts, Block, Austreibend, Gesperrt (0..5)*/

#define  EscFarbe  'C' /* Farbe 0..7                                                */
#define  EscBFarb  'U' /* BackFarbe 0..7                                            */
#define  EscInts   'I' /* Farbintensitaet 0..100%                                   */
#define  EscMustr  'M' /* Muster 0..? inkl. Transp...                               */
#define  EscMFarb  'O' /* Musterfarbe 0..7                                          */
#define  EscMBFrb  'P' /* 2. Musterfarbe 0..7                                       */
#define  EscMInts  'W' /* Musterintensitaet 0..7                                    */

#define  EscSMstr  'E' /* Schattenmuster 0..? inkl. Transp...                       */
#define  EscSFarb  'R' /* Schattenfarbe 0..7                                        */
#define  EscSBFrb  'T' /* 2. Schattenfarbe 0..7                                     */
#define  EscSInts  'Q' /* Schattenintensitaet 0..7                                  */

#define  EscSXDst  'X' /* Schattenversatz X 0..100%                                 */
#define  EscSYDst  'Y' /* Schattenversatz Y 0..100%                                 */
#define  EscSDist  'D' /* Schattenversatz X-Y 0..100%                               */

#define  EscBold   'f' /* Fett                                                      */
#define  EscLSlnt  'l' /* LKursiv                                                   */
#define  EscRSlnt  'r' /* RKursiv                                                   */
#define  EscUndln  'u' /* Unterstrichen                                             */
#define  EscDbUnd  'p' /* doppelt Unterstrichen                                     */
#define  EscKaptF  'k' /* Kapitaelchenflag                                          */
#define  EscStrik  'd' /* Durchgestrichen                                           */
#define  EscDbStk  'e' /* doppelt Durchgestrichen                                   */
#define  EscSupSc  'h' /* Hochgestellt                                              */
#define  EscSubSc  't' /* Tiefgestellt                                              */
#define  Esc2DShd  's' /* 2D-Schatten                                               */
#define  Esc3DShd  'j' /* 3D-Schatten                                               */
#define  Esc4DShd  'i' /* 4D-Schatten                                               */
#define  EscEbShd  'b' /* Embossed                                                  */

//  AllEscIdent =[EscFont, EscGrad, EscBreit,EscKaptS,EscLFeed,EscSlant,EscVPos, EscZAbst,EscHJust,
//                EscFarbe,EscBFarb,EscInts, EscMustr,EscMFarb,EscMBFrb,EscMInts,
//                EscSMstr,EscSFarb,EscSBFrb,EscSInts,EscSXDst,EscSYDst,EscSDist,
//                EscBold, EscLSlnt,EscRSlnt,EscUndln,EscDbUnd,EscKaptF,EscStrik,EscDbStk,
//                EscSupSc,EscSubSc,Esc2DShd,Esc3DShd,Esc4DShd];
// Justify muss spaetestens am Anfang des Absatzes stehen
#define  EscSet    '\x1e' /* Flag setzen                                               */
#define  EscReset  '\x1f' /* Flag loeschen                                             */
#define  EscDeflt  '\x11' /* Flag auf default setzen                                */
#define  EscToggl  '\x1d' /* Flag Toggeln                                              */
#define  EscRelat  '%'
#define  EscNoFlg  0
#define  EscNoVal  -2147483647 /* -MaxLongInt */
//==============================================================================
#define  NoTrenn 0xFFFF   /* Wert fuer Parameter 'Rest' von GetTextChar(), wenn auf keinen Fall getrennt werden soll */
#define  DoTrenn 0xFFFE   /* Wert fuer Parameter 'Rest' von GetTextChar(), wenn getrennt werden soll                 */

#define  MaxLineChars 1024

#define  ChrXPosArrSize (MaxLineChars+1+1)           /* 2k - Beginnt mit 0 im gegensatz zu StarDraw */
#define  CharLineSize   (MaxLineChars+1+1)
#define  EscStr         (UCHAR[MaxEscLen+1]);

#define  MinChar 32
#define  MaxChar 255


//==============================================================================

#define  DefaultCharWidth 4800
#define  GradDiv             2
#define  CharTopToBase     100 /* wegen Apostrophe und Umlaute mehr als 75% */
#define  CharTopToBtm      120 /* Zeilenhoehe ist groesser als Schriftgrad  */
                               // bei Avanti-Bold 'ue' eigentlich sogar 130%

// end of AbsBase.Pas
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// DefBase.Pas

#define  TextBoldBit  0x0001   /* Fett                    */
#define  TextRSlnBit  0x0002   /* Kursiv                  */
#define  TextUndlBit  0x0004   /* Unterstrichen           */
#define  TextStrkBit  0x0008   /* Durchgesteichen         */
#define  TextSupSBit  0x0010   /* Hocgestellt             */
#define  TextSubSBit  0x0020   /* Tiefgestellt            */
#define  TextKaptBit  0x0040   /* Kapitaelchen            */
#define  TextLSlnBit  0x0080   /* Linkskursiv             */
#define  TextDbUnBit  0x0100   /* Doppelt unterstrichen   */
#define  TextDbStBit  0x0200   /* Doppelt durchgestrichen */
#define  TextSh2DBit  0x0400   /* 2D-Schatten         2.0 */
#define  TextSh3DBit  0x0800   /* 3D-Schatten         2.0 */
#define  TextSh4DBit  0x1000   /* 4D-Schatten         2.0 */
#define  TextShEbBit  0x2000   /* Embossed-Schatten   2.0 */
#define  FontAtrBits  (TextBoldBit | TextRSlnBit)

#define  THJustLeft    0x00
#define  THJustCenter  0x01
#define  THJustRight   0x02
#define  THJustBlock   0x03
#define  THJustDrvOut  0x04 /* Austreibend          Formatiert */
#define  THJustLocked  0x05 /* A l s   S p e r r s c h r i f t */
#define  TVJustTop     0x00 /* Future */
#define  TVJustCenter  0x10 /* Future */
#define  TVJustBottom  0x20 /* Future */
#define  TVJustBlock   0x30 /* Future */

#define  MaxCharSlant  4200 /* Maximal 42deg kursiv ! */

// end of DefBase.Pas
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////


sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L);

sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L)
{
    return (F.FIntens!=L.LIntens) ||
           ((F.FFarbe!=L.LFarbe)   && (F.FIntens>0)) ||
           ((F.FBFarbe!=L.LBFarbe) && (F.FIntens<100));
}


/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// Misc.Pas

short hPoint2Sgf(short a)
{
    long b;
    b=long(a)*127*SgfDpmm/(144*5);
    return short(b);
}

// End of Misc.Pas
// AbsRead.Pas

// ======================================================================
// Function GetTopToBaseLine()  Function GetBaseLineToBtm()
//
// Abstand von Zeilenoberkante bis BaseLine bzw. von BaseLine bis
// Unterkante berechnen. Alles in SGF-Units.
// ======================================================================

sal_uInt16 GetTopToBaseLine(sal_uInt16 MaxGrad)
{
    long ret;
    ret=long(MaxGrad)*long(CharTopToBase) /long(100);
    return sal_uInt16(ret);
}

// ======================================================================
// Function GetTextChar()   Function GetTextCharConv()
//
// Liest ein Zeichen aus dem Textbuffer, wertet dabei eventuell
// auftretende Escapesequenzen aus und setzt dementsprechend den
// Ein-/Ausgabeparameter AktAtr. Index wird entsprechend erhoeht.
// Der Parameter Rest muss immer die Anzahl der Zeichen beinhalten,
// den angeforderten Zeichen in der aktuellen Zeile noch folgen.
// Ansonsten funktioniert die Silbentrennung nicht richtig. Gibt man
// stattdessen die Konstante NoTrenn an, wird in keinem Fall
// getrennt, die Konstante DoTrenn bewirkt dagegen, dass ueberall dort
// getrennt wird, wo ein SoftTrenner vorkommt.
//
// SoftTrenner werden immer in ein Minuszeichen konvertiert.
// GetTextCharConv() konvertiert zusaetzlich HardSpace und AbsatzEnde
// in Spaces sowie HardTrenner in Minuszeichen. TextEnde wird immer
// als Char(0) geliefert.
// ======================================================================



UCHAR ConvertTextChar(UCHAR c)
{
    if (c<32) {
        switch (c) {
            case HardSpace   : c=' '; break;
            case AbsatzEnd   : c=' '; break;
            case SoftTrenn   : c='-'; break;
            case HardTrenn   : c='-'; break;
            case SoftTrennK  : c='-'; break;
            case SoftTrennAdd: c='-';
        }
    }
    return c;
}

long ChgValue(long Def, long Min, long Max, UCHAR FlgVal, long NumVal)
{
    long r=0;

    if (FlgVal==EscDeflt) {
        r=Def;                          // zurueck auf Default
    } else {
        if (NumVal!=EscNoVal) r=NumVal; // Hart setzen
    }

    if (Min!=0 || Max!=0) {
        if (r>Max) r=Max;
        if (r<Min) r=Min;
    }
    return r;
}



void ChgSchnittBit(sal_uInt16 Bit, sal_uInt16 Radio1, sal_uInt16 Radio2, sal_uInt16 Radio3,
                   UCHAR FlgVal, sal_uInt16 Schnitt0, sal_uInt16& Schnitt)
{
    sal_uInt16 All,Rad;

    Rad=Radio1 | Radio2 | Radio3;
    All=Bit | Rad;

    switch (FlgVal) {
        case EscSet  : Schnitt=(Schnitt & ~All) | Bit;              break;
        case EscReset: Schnitt=(Schnitt & ~All);                    break;
        case EscDeflt: Schnitt=(Schnitt & ~All) | (Schnitt0 & All); break;
        case EscToggl: Schnitt=(Schnitt & ~Rad) ^ Bit;
    }
}



UCHAR GetNextChar(UCHAR* TBuf, sal_uInt16 Index)
{
    sal_uInt16 Cnt;
    while (TBuf[Index]==Escape) {
        Index++;
        Cnt=0;
        while (TBuf[Index]!=Escape && Cnt<=MaxEscLen) {
            Index++; Cnt++; }
        Index++;
    }
    return TBuf[Index];
}



UCHAR ProcessOne(UCHAR* TBuf, sal_uInt16& Index,
                 ObjTextType& Atr0, ObjTextType& AktAtr,
                 sal_Bool ScanEsc)
{
    UCHAR c;
    UCHAR Ident;
    sal_Bool  Ende;
    sal_Bool  q;
    UCHAR FlgVal;
    long  NumVal;
    long  Sgn;
    short i;
    sal_Bool  EoVal;

    do {
        c=TBuf[Index]; Index++;
        Ende=(c!=Escape);
        if (Ende==sal_False) {
            c=TBuf[Index]; Index++;
            Ident=c;                          // Identifer merken
            FlgVal=EscNoFlg;
            NumVal=EscNoVal;
            c=TBuf[Index]; Index++;            // Hier faengt der Wert an
            if (c==EscSet || c==EscReset || c==EscDeflt || c==EscToggl) FlgVal=c; else {
                if (c=='-') Sgn=-1; else Sgn=1;
                if (c=='+' || c=='-') { c=TBuf[Index]; Index++; }
                i=MaxEscValLen;
                NumVal=0;
                do {
                    NumVal=10*NumVal+c-'0';
                    EoVal=(TBuf[Index]<'0' || TBuf[Index]>'9');
                    if (EoVal==sal_False) { c=TBuf[Index]; Index++; }
                    i--;
                } while (i>0 && EoVal==sal_False);
                NumVal=Sgn*NumVal;
            }
            q=!CheckTextOutl(AktAtr.F,AktAtr.L);

            switch (Ident) {
                case EscFont : AktAtr.SetFont(sal_uLong (ChgValue(Atr0.GetFont(),0,0          ,FlgVal,NumVal)));break;
                case EscGrad : AktAtr.Grad   =sal_uInt16(ChgValue(Atr0.Grad,   2,2000         ,FlgVal,NumVal)); break;
                case EscBreit: AktAtr.Breite =sal_uInt16(ChgValue(Atr0.Breite, 1,1000         ,FlgVal,NumVal)); break;
                case EscKaptS: AktAtr.Kapit  =(sal_uInt8)(ChgValue(Atr0.Kapit,  1,255          ,FlgVal,NumVal)); break;
                case EscLFeed: AktAtr.LnFeed =sal_uInt16(ChgValue(Atr0.LnFeed, 1,65535        ,FlgVal,NumVal)); break;
                case EscSlant: AktAtr.Slant  =sal_uInt16(ChgValue(Atr0.Slant,  1,MaxCharSlant ,FlgVal,NumVal)); break;
                case EscVPos : AktAtr.ChrVPos=char  (ChgValue(Atr0.ChrVPos,-128,127       ,FlgVal,NumVal)); break;
                case EscZAbst: AktAtr.ZAbst  =(sal_uInt8)(ChgValue(Atr0.ZAbst,  1,255          ,FlgVal,NumVal)); break;
                case EscHJust: AktAtr.Justify=(sal_uInt8)(ChgValue(Atr0.Justify & 0x0F,0,5     ,FlgVal,NumVal)); break;
                case EscFarbe: { AktAtr.L.LFarbe =(sal_uInt8)(ChgValue(Atr0.L.LFarbe,0,7   ,FlgVal,NumVal)); if (q) AktAtr.F.FFarbe =AktAtr.L.LFarbe;  } break;
                case EscBFarb: { AktAtr.L.LBFarbe=(sal_uInt8)(ChgValue(Atr0.L.LBFarbe,0,255,FlgVal,NumVal)); if (q) AktAtr.F.FBFarbe=AktAtr.L.LBFarbe; } break;
                case EscInts : { AktAtr.L.LIntens=(sal_uInt8)(ChgValue(Atr0.L.LIntens,0,100,FlgVal,NumVal)); if (q) AktAtr.F.FIntens=AktAtr.L.LIntens; } break;

                case EscMustr: { AktAtr.F.FMuster=sal_uInt16(ChgValue(Atr0.F.FMuster,0,65535,FlgVal,NumVal)); } break;
                case EscMFarb: { AktAtr.F.FFarbe =(sal_uInt8)(ChgValue(Atr0.F.FFarbe,0,7   ,FlgVal,NumVal));   } break;
                case EscMBFrb: { AktAtr.F.FBFarbe=(sal_uInt8)(ChgValue(Atr0.F.FBFarbe,0,255,FlgVal,NumVal));   } break;
                case EscMInts: { AktAtr.F.FIntens=(sal_uInt8)(ChgValue(Atr0.F.FIntens,0,100,FlgVal,NumVal));   } break;

                case EscSMstr: { AktAtr.ShdF.FMuster=sal_uInt16(ChgValue(Atr0.ShdF.FMuster,0,65535,FlgVal,NumVal)); } break;
                case EscSFarb: { AktAtr.ShdL.LFarbe =(sal_uInt8)(ChgValue(Atr0.ShdL.LFarbe,0,7   ,FlgVal,NumVal)); AktAtr.ShdF.FFarbe =AktAtr.ShdL.LFarbe;  } break;
                case EscSBFrb: { AktAtr.ShdL.LBFarbe=(sal_uInt8)(ChgValue(Atr0.ShdL.LBFarbe,0,255,FlgVal,NumVal)); AktAtr.ShdF.FBFarbe=AktAtr.ShdL.LBFarbe; } break;
                case EscSInts: { AktAtr.ShdL.LIntens=(sal_uInt8)(ChgValue(Atr0.ShdL.LIntens,0,100,FlgVal,NumVal)); AktAtr.ShdF.FIntens=AktAtr.ShdL.LIntens; } break;
                case EscSDist: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); AktAtr.ShdVers.y=AktAtr.ShdVers.x; }            break;
                case EscSXDst: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); }  break;
                case EscSYDst: { AktAtr.ShdVers.y=(short)ChgValue(Atr0.ShdVers.y,0,30000,FlgVal,NumVal); }  break;

                case EscBold : ChgSchnittBit(TextBoldBit,0,0,0                              ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscRSlnt: ChgSchnittBit(TextRSlnBit,TextLSlnBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscUndln: ChgSchnittBit(TextUndlBit,TextDbUnBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscStrik: ChgSchnittBit(TextStrkBit,TextDbStBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscDbUnd: ChgSchnittBit(TextDbUnBit,TextUndlBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscDbStk: ChgSchnittBit(TextDbStBit,TextStrkBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscSupSc: ChgSchnittBit(TextSupSBit,TextSubSBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscSubSc: ChgSchnittBit(TextSubSBit,TextSupSBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscKaptF: ChgSchnittBit(TextKaptBit,0,0,0                              ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscLSlnt: ChgSchnittBit(TextLSlnBit,TextRSlnBit,0,0                    ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case Esc2DShd: ChgSchnittBit(TextSh2DBit,TextSh3DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case Esc3DShd: ChgSchnittBit(TextSh3DBit,TextSh2DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case Esc4DShd: ChgSchnittBit(TextSh4DBit,TextSh2DBit,TextSh3DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
                case EscEbShd: ChgSchnittBit(TextShEbBit,TextSh2DBit,TextSh3DBit,TextSh4DBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
            } //endcase
            if (TBuf[Index]==Escape) Index++;         // zweites Esc weglesen }
        } // if Ende==sal_False
    } while (Ende==sal_False && ScanEsc==sal_False);
    if (Ende==sal_False) c=Escape;
    return c;
} // end of ProcessOne


UCHAR GetTextChar(UCHAR* TBuf, sal_uInt16& Index,
                  ObjTextType& Atr0, ObjTextType& AktAtr,
                  sal_uInt16 Rest, sal_Bool ScanEsc)
{
    UCHAR c,c0,nc;

    c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc);
    if (ScanEsc==sal_False) {
        if (c==SoftTrennAdd || c==SoftTrennK || c==SoftTrenn) {
            nc=GetNextChar(TBuf,Index);
            c0=c;
            if (Rest==0 || Rest==DoTrenn ||
                nc==' ' || nc==AbsatzEnd || nc==TextEnd) c='-';
            else {
                c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // den Trenner ueberspringen
                if (c0==SoftTrennAdd) {
                    if (c>=32) c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // und hier noch 'nen Buchstaben ueberspringen
                }
            }
        }
        if ((Rest==1 || Rest==DoTrenn) && GetNextChar(TBuf,Index)==SoftTrennK) {
            if (c=='c') c='k';
            else if (c=='C') c='K';
        }
    }
    return c;
}

  // HardSpace und HardTrenn muessen explizit konvertiert werden ! }
  // if AktAtr.Schnitt and TextKaptBit =TextKaptBit then c:=UpCase(c);(explizit) }

  // Bei der Trennmethode SoftTrennAdd wird davon ausgegangen, dass der zu }
  // trennende Konsonant bereits 3x mal im TextBuf vorhanden ist, z.b.:   }
  // "Schiff-fahrt". Wenn nicht getrennt, dann wird "-f" entfernt.        }



UCHAR GetTextCharConv(UCHAR* TBuf, sal_uInt16& Index,
                      ObjTextType& Atr0, ObjTextType& AktAtr,
                      sal_uInt16 Rest, sal_Bool ScanEsc)
{
    UCHAR c;

    c=GetTextChar(TBuf,Index,Atr0,AktAtr,Rest,ScanEsc);
    if (c<32) {
        switch (c) {
            case HardSpace   : c=' '; break;
            case AbsatzEnd   : c=' '; break;
            case HardTrenn   : c='-';
        }
    }
    return c;
}


// ======================================================================
// Function GetLineFeed()
//
// Benoetigter Zeilenabstand in SGF-Units. ChrVPos wird beruecksichtigt.
// ======================================================================
sal_uInt16 GetLineFeed(UCHAR* TBuf, sal_uInt16 Index, ObjTextType Atr0, ObjTextType AktAtr,
                   sal_uInt16 nChar, sal_uInt16& LF, sal_uInt16& MaxGrad)
{
    UCHAR  c=0;
    sal_Bool   AbsEnd=sal_False;
    sal_uLong  LF100=0;
    sal_uLong  MaxLF100=0;
    sal_Bool   LFauto=0;
    sal_Bool   First=sal_True;
    sal_uInt16 Grad;
    sal_uInt16 i=0;
    sal_uInt16 r=1;

    MaxGrad=0;
    while (!AbsEnd && nChar>0) {
        nChar--;
        c=GetTextChar(TBuf,Index,Atr0,AktAtr,nChar,sal_False);
        i++;
        AbsEnd=(c==TextEnd || c==AbsatzEnd);
        if (First || (!AbsEnd && c!=' ' && c!=HardTrenn)) {
            LFauto=(AktAtr.LnFeed & 0x8000)==0;
            LF100=AktAtr.LnFeed & 0x7FFF;
            if (LFauto) LF100=LF100*AktAtr.Grad; else LF100*=LF100;
            if (AktAtr.ChrVPos>0) LF100-=AktAtr.ChrVPos*100;
            if (LF100>MaxLF100) MaxLF100=LF100;
            Grad=AktAtr.Grad;
            if (AktAtr.ChrVPos>0) Grad=Grad-AktAtr.ChrVPos;
            if (Grad>MaxGrad) MaxGrad=Grad;
            First=sal_False;
        }
        if (!AbsEnd && c!=' ') r=i;
    }
    MaxGrad=hPoint2Sgf(MaxGrad);
    if (MaxLF100<=4000) {  // sonst Overflowgefahr
        LF=sal_uInt16(hPoint2Sgf(short(MaxLF100)) /100);
    } else {
        LF=sal_uInt16(hPoint2Sgf(short(MaxLF100) /100));
    }

    return r;
}

// End of AbsRead.Pas
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// iFont.Pas

#define DefaultSlant 1500   /* Default: Italic ist 15deg                  */
#define SuperSubFact 60     /* SuperScript/SubScript: 60% vom Schriftgrad */
#define DefaultSpace 40     /* Default: Space ist 40% vom SchriftGrad     */

sal_uInt16 SetTextContext(OutputDevice& rOut, ObjTextType& Atr, sal_Bool Kapt, sal_uInt16 Dreh,
                      sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
{
    SgfFontOne* pSgfFont; // Font aus dem IniFile
    Font   aFont;
    Color  aColor;
    sal_uLong  Grad;
    sal_uLong  Brei;
    String FNam;
    sal_uInt16 StdBrei=50;    // Durchschnittliche Zeichenbreite in % von Schriftgrad
    sal_Bool   bFit=(FitXMul!=1 || FitXDiv!=1 || FitYMul!=1 || FitYDiv!=1);

    pSgfFont = pSgfFonts->GetFontDesc(Atr.GetFont());

    if ( pSgfFont!=NULL )
    {
        FNam   =pSgfFont->SVFName;
        StdBrei=pSgfFont->SVWidth;
        if (pSgfFont->Fixd) aFont.SetPitch(PITCH_FIXED); else aFont.SetPitch(PITCH_VARIABLE);
        aFont.SetFamily(pSgfFont->SVFamil);
        aFont.SetCharSet(pSgfFont->SVChSet);
        aFont.SetName(FNam);
    }
    else
    {  // Falls nich im Inifile, sind hier einige Fonts hart kodiert
        aFont.SetPitch(PITCH_VARIABLE);
        switch (Atr.GetFont()) {
          case 92500: case 92501: case 92504: case 92505:
          {
#if defined(WNT)
              FNam=String::CreateFromAscii( "Times New Roman" );  // CG Times ist unter Windows Times New Roman
#else
              FNam=String::CreateFromAscii( "Times" );            // ansonsten ist das einfach Times
#endif
              StdBrei=40;
              aFont.SetFamily(FAMILY_ROMAN);
          } break;
          case 94021: case 94022: case 94023: case 94024: {
#if defined(WNT)
              FNam=String::CreateFromAscii( "Arial", 5 );            // Univers ist unter Windows Arial
#else
              FNam=String::CreateFromAscii( "Helvetica" );        // und ansonsten Helvetica
#endif
              aFont.SetFamily(FAMILY_SWISS);
              StdBrei=47;
          } break;
          case 93950: case 93951: case 93952: case 93953: {
#if defined(WNT)
              FNam=String::CreateFromAscii( "Courier New" );      // Der Vector-Courierfont unter Windows heisst Courier New
#else
              FNam=String::CreateFromAscii( "Courier" );          // ansonsten ist und bleibt Courier immer Courier
#endif
              aFont.SetFamily(FAMILY_ROMAN);
              aFont.SetPitch(PITCH_FIXED);
          } break;
          default: FNam=String::CreateFromAscii( "Helvetica", 9 );
        }
        aFont.SetName(FNam);
        //aFont.SetCharSet(CHARSET_SYSTEM);
    }

    Grad=sal_uLong(Atr.Grad);
    if ((Atr.Schnitt & TextKaptBit) !=0 && Kapt) Grad=Grad*sal_uLong(Atr.Kapit)/100;
    if ((Atr.Schnitt & TextSupSBit) !=0 || (Atr.Schnitt & TextSubSBit) !=0) Grad=Grad*SuperSubFact/100;
    Brei=Grad;
    if (Atr.Breite!=100 || bFit) {
        if (bFit) {
            Grad=Grad*sal_uLong(FitYMul)/sal_uLong(FitYDiv);
            Brei=Brei*sal_uLong(FitXMul)/sal_uLong(FitXDiv);
        }
        Brei=Brei*sal_uLong(Atr.Breite)/100;
        Brei=Brei*sal_uLong(StdBrei)/100;
        aFont.SetSize(Size(hPoint2Sgf(sal_uInt16(Brei)),hPoint2Sgf(sal_uInt16(Grad))));
    } else {
        aFont.SetSize(Size(0,hPoint2Sgf(sal_uInt16(Grad))));
    }

    aColor=Sgv2SvFarbe(Atr.L.LFarbe,Atr.L.LBFarbe,Atr.L.LIntens); aFont.SetColor(aColor);
    aColor=Sgv2SvFarbe(Atr.F.FFarbe,Atr.F.FBFarbe,Atr.F.FIntens); aFont.SetFillColor(aColor);
    aFont.SetTransparent(sal_True);
    aFont.SetAlign(ALIGN_BASELINE);

    Dreh/=10; Dreh=3600-Dreh; if (Dreh==3600) Dreh=0;
    aFont.SetOrientation(Dreh);

    if ((Atr.Schnitt & TextBoldBit) !=0) aFont.SetWeight(WEIGHT_BOLD);
    if ((Atr.Schnitt & TextRSlnBit) !=0) aFont.SetItalic(ITALIC_NORMAL);
    if ((Atr.Schnitt & TextUndlBit) !=0) aFont.SetUnderline(UNDERLINE_SINGLE);
    if ((Atr.Schnitt & TextDbUnBit) !=0) aFont.SetUnderline(UNDERLINE_DOUBLE);
    if ((Atr.Schnitt & TextStrkBit) !=0) aFont.SetStrikeout(STRIKEOUT_SINGLE);
    if ((Atr.Schnitt & TextDbStBit) !=0) aFont.SetStrikeout(STRIKEOUT_DOUBLE);
    if ((Atr.Schnitt & TextSh2DBit) !=0) aFont.SetShadow(sal_True);
    if ((Atr.Schnitt & TextSh3DBit) !=0) aFont.SetShadow(sal_True);
    if ((Atr.Schnitt & TextSh4DBit) !=0) aFont.SetShadow(sal_True);
    if ((Atr.Schnitt & TextShEbBit) !=0) aFont.SetShadow(sal_True);
    if (CheckTextOutl(Atr.F,Atr.L)) aFont.SetOutline(sal_True);

    if (aFont!=rOut.GetFont()) rOut.SetFont(aFont);

    return 0;
}

// iFont.Pas
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// Absatz.Pas

struct ProcChrSta {
    sal_uInt16 Index;
    sal_uInt16 ChrXP;
    UCHAR  OutCh;
    sal_Bool   Kapt;
    ObjTextType Attrib;
};

void InitProcessCharState(ProcChrSta& State, ObjTextType& AktAtr, sal_uInt16 IndexA)
{
    State.Attrib=AktAtr;
    State.OutCh=0;
    State.Index=IndexA;
    State.ChrXP=0;
    State.Kapt=sal_False;
}

sal_Bool UpcasePossible(UCHAR c)
{
    if ((c>='a' && c<='z') || c == 0xe4 || c == 0xf6 || c == 0xfc ) return sal_True;
    else return sal_False;
}

UCHAR Upcase(UCHAR c)
{
    if ((c>=(UCHAR)'a' && c<=(UCHAR)'z')) c=(c-(UCHAR)'a')+(UCHAR)'A';
    else if ( c == 0xe4 ) c = 0xc4;
    else if ( c == 0xf6 ) c = 0xd6;
    else if ( c == 0xfc ) c = 0xdc;
    return c;
}

sal_uInt16 GetCharWidth(OutputDevice& rOut, UCHAR c)
{
    sal_uInt16 ChrWidth;

    if (c==' ')
    {
        ChrWidth=(sal_uInt16)rOut.GetTextWidth( String('A') );
        if (rOut.GetFont().GetPitch()!=PITCH_FIXED) {
            ChrWidth=MulDiv(ChrWidth,DefaultSpace,100);
        }
    }
    else
    {
         // with MaxChar == 255 c cannot be greater than MaxChar
         // assert if MaxChar is ever changed
        OSL_ENSURE( MaxChar == 255, "MaxChar not 255" );
        OSL_ENSURE(sizeof(UCHAR) == 1, "should be 1");
        if (c>=MinChar /*&& c<=MaxChar*/)
        {
            ChrWidth=(sal_uInt16)rOut.GetTextWidth(rtl::OUString(reinterpret_cast<sal_Char*>(&c), 1, RTL_TEXTENCODING_IBM_437));
        }
        else
        {
            ChrWidth=(sal_uInt16)rOut.GetTextWidth(rtl::OUString(static_cast<sal_Unicode>('A')));
        }
    }
    return ChrWidth;
}

UCHAR ProcessChar(OutputDevice& rOut, UCHAR* TBuf, ProcChrSta& R, ObjTextType& Atr0,
                  sal_uInt16& nChars, sal_uInt16 Rest,
                  short* Line, UCHAR* cLine)
{
    sal_uInt16       KernDist=0;       // Wert fuer Kerning<--- The scope of the variable 'KernDist' can be reduced
    sal_uInt16       ChrWidth;
    UCHAR        c;
    UCHAR        c1;
    sal_Bool         AbsEnd;

    c=GetTextChar(TBuf,R.Index,Atr0,R.Attrib,Rest,sal_False); // versucht evtl. zu trennen, wenn Rest entsprechenden Wert besitzt

    AbsEnd=(c==AbsatzEnd || c==TextEnd);
    if (AbsEnd==sal_False) {
        R.OutCh=ConvertTextChar(c); // von HardTrenn nach '-', ...
        R.Kapt=(R.Attrib.Schnitt & TextKaptBit) !=0 && UpcasePossible(R.OutCh);
        if (R.Kapt) R.OutCh=Upcase(R.OutCh);
        SetTextContext(rOut,R.Attrib,R.Kapt,0,1,1,1,1);

        if (R.Kapt) c1=Upcase(c); else c1=c;
        ChrWidth=GetCharWidth(rOut,c1);

        if (R.Attrib.ZAbst!=100) { // Spezial-Zeichenabstand ?
            sal_uLong Temp;
            Temp=sal_uLong(ChrWidth)*sal_uLong(R.Attrib.ZAbst)/100;
            ChrWidth=sal_uInt16(Temp);
        }
        nChars++;
        if (R.ChrXP>32000) R.ChrXP=32000;
        Line[nChars]=R.ChrXP-KernDist;
        cLine[nChars]=c;
        R.ChrXP+=ChrWidth-KernDist; // Position fuer den naechsten Character
    }
    return c;
}

void 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)
{
    VirtualDevice vOut;
    UCHAR        c,c0;
    UCHAR        ct;
    sal_Bool         First;               // erster Char ?
    sal_uInt8         Just = 0;                // Absatzformatierung
    sal_Bool         Border;              // Rand der Box erreicht ?
    sal_Bool         Border0;
    sal_Bool         AbsEnd;              // Ende des Absatzes erreicht ?
    ProcChrSta*  R=new ProcChrSta;
    ProcChrSta*  R0=new ProcChrSta;
    ProcChrSta*  WErec=new ProcChrSta;
    sal_uInt16       WEnChar;
    ProcChrSta*  WErec0=new ProcChrSta;
    sal_uInt16       WEnChar0;
    ProcChrSta*  TRrec=new ProcChrSta;
    sal_uInt16       TRnChar;

    sal_uInt16       WordEndCnt;          // Justieren und Trennen
    sal_Bool         WordEnd;
    sal_Bool         Trenn;

    short        BoxRest;             // zum Quetschen und formatieren
    sal_uInt16       i,j,k,h;
    sal_uInt16       re,li;

    vOut.SetMapMode(MapMode(MAP_10TH_MM,Point(),Fraction(1,4),Fraction(1,4)));

    nChars=0;
    SetTextContext(vOut,AktAtr,sal_False,0,1,1,1,1);
    InitProcessCharState(*R,AktAtr,Index);
    (*R0)=(*R); (*WErec)=(*R); WEnChar=0; c0=0; Border0=sal_False;
    Border=sal_False; First=sal_True;
    WordEndCnt=0;

    do {               // mal schauen, wieviele Worte so in die Zeile passen
        if (Border) c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,DoTrenn,Line,cLine);
        else        c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
        AbsEnd=(c==AbsatzEnd || c==TextEnd);
        //if not AbsEnd then
        {
            if (First) {
                Just=R->Attrib.Justify & 0x0F; // Absatzformat steht wenn, dann am Anfang
            }
            Border=R->ChrXP>UmbWdt;
            WordEnd=(AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0);
            Trenn=c=='-';
            if (WordEnd && !Border0) {
                WordEndCnt++;
                (*WErec)=(*R0);
                WEnChar=nChars-1;
            }
            if (Trenn && !Border) {
                WordEndCnt++;
                (*WErec)=(*R);
                WEnChar=nChars;
            }
        }
        (*R0)=(*R); c0=c;
        Border0=Border;
        First=sal_False;
        AbsEnd=AbsEnd || (nChars>=MaxLineChars);
    } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));

    if (Border) { // Trennen und Quetschen
        (*WErec0)=(*WErec); WEnChar0=WEnChar;
        AbsEnd=sal_False; c0=0;
        (*R)=(*WErec); nChars=WEnChar;
        (*TRrec)=(*R); TRnChar=nChars;
        Border0=sal_False; Border=sal_False;
        do {                // erst mal gucken wieviele Silben noch reinpassen
            ct=ProcessChar(vOut,TBuf,*TRrec,Atr0,TRnChar,DoTrenn,Line,cLine);
            c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
            AbsEnd=(ct==AbsatzEnd) || (ct==TextEnd) || (nChars>=MaxLineChars);

            Border=TRrec->ChrXP>UmbWdt;
            WordEnd=AbsEnd || ((AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0));
            Trenn=ct=='-';
            if (WordEnd && (!Border0 || (WordEndCnt==0))) {
                WordEndCnt++;
                (*WErec)=(*R0);
                if (AbsEnd) WEnChar=nChars; else WEnChar=nChars-1;
                (*TRrec)=(*R); TRnChar=nChars;                       // zum weitersuchen
            }
            if (Trenn && (!Border || (WordEndCnt==0))) {
                WordEndCnt++;                 // merken, dass man hier trennen kann
                (*WErec)=(*TRrec);
                WEnChar=TRnChar;
                (*TRrec)=(*R); TRnChar=nChars;                       // zum weitersuchen
            }
            (*R0)=(*R); c0=c;
            Border0=Border;
            Border=R->ChrXP>UmbWdt;
        } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));

        while (WErec0->Index<WErec->Index) { // damit Line[] auch garantiert stimmt }
            c=ProcessChar(vOut,TBuf,*WErec0,Atr0,WEnChar0,WEnChar-WEnChar0-1,Line,cLine);
        }

        (*R)=(*WErec); nChars=WEnChar;

        if (UmbWdt>=R->ChrXP) {
            BoxRest=UmbWdt-R->ChrXP;
        } else {                                       // Zusammenquetschen
            BoxRest=R->ChrXP-UmbWdt;                     // um soviel muss gequetscht werden
            for (i=2;i<=nChars;i++) {                  // 1. CharPosition bleibt !
                Line[i]-=(i-1)*(BoxRest) /(nChars-1);
            }
            R->ChrXP=UmbWdt;
            Line[nChars+1]=UmbWdt;
        }
    }

    if (!AbsEnd) {
        do {                                         // Leerzeichen weglesen
            (*WErec)=(*R);
            c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False);
            nChars++;
            Line[nChars]=R->ChrXP;
            cLine[nChars]=c;
        } while (c==' ');
        if (c!=' ' && c!=AbsatzEnd && c!=TextEnd) {
            nChars--;
            (*R)=(*WErec);
        }
    }

    if (AbsEnd && nChars<MaxLineChars) { // Ausrichten, statt Blocksatz aber linksbuendig
        if (Just==3) Just=0;
        nChars++; Line[nChars]=R->ChrXP; // Damit AbsatzEnde auch weggelesen wird
        Line[nChars+1]=R->ChrXP;         // denn die Breite von CR oder #0 ist nun mal sehr klein
        if (TBuf[R->Index-1]!=AbsatzEnd &&  TBuf[R->Index-1]!=TextEnd) {
            c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False); // Kleine Korrektur. Notig, wenn nur 1 Wort in
        }
    }

    BoxRest=AdjWdt-R->ChrXP;
    if (TextFit) Just=THJustLeft;

    switch (Just) {
        case THJustLeft: break;                                // Links
        case THJustCenter: {
            BoxRest=BoxRest /2;                                // Mitte
            for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
        } break;
        case THJustRight: {                                    // Rechts
            for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
        } break;
        case THJustDrvOut:
        case THJustBlock: {                                    // Block und Austreibend
            re=nChars;
            if (Just==THJustDrvOut) re--;
            while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
            li=1;
            while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
            if (Just==THJustDrvOut) BoxRest=AdjWdt-Line[re+1];

            j=0;                        // Anzahl der Spaces ermitteln
            for (i=li;i<=re;i++) {
                if (cLine[i]==' ') {
                    j++;
                }
            }

            if (j==0) {                        // nur 1 Wort ?  -> Strecken !
                for (i=li+1;i<=re;i++) {       // von links nach rechts
                  Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
                }
            } else {
                k=0; h=0;
                for (i=li;i<=re;i++) {          // j Spaces aufbohren !
                    if (cLine[i]==' ') {        // Space gefunden !
                        k++;
                        h=MulDiv(k,BoxRest,j);
                    }
                    Line[i]=Line[i]+h;
                }
            }
            for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
            Line[nChars+1]=AdjWdt;
        } break;
        case THJustLocked: {                                    //Gesperrt
            re=nChars-1;
            while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
            li=1;
            while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
            BoxRest=AdjWdt-Line[re+1];
            for (i=li+1;i<=re;i++) {         // Strecken von links nach rechts
                Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
            }
            for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
            Line[nChars+1]=AdjWdt;
        } break;
    }
    Index=R->Index;
    AktAtr=R->Attrib;
    delete R;
    delete R0;
    delete WErec;
    delete WErec0;
    delete TRrec;
}



// End of Absatz.Pas
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// DrawText.Pas

void DrawChar(OutputDevice& rOut, UCHAR c, ObjTextType T, PointType Pos, sal_uInt16 DrehWink,
              sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
{
    SetTextContext(rOut,T,UpcasePossible(c),DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
    if ((T.Schnitt & TextKaptBit)!=0 && UpcasePossible(c)) c=Upcase(c);
    rtl::OUString s(reinterpret_cast<const sal_Char*>(&c), 1,
        RTL_TEXTENCODING_IBM_437);
    rOut.DrawText( Point( Pos.x, Pos.y ), s );
}

/*************************************************************************
|*
|*    TextType::Draw()
|*
*************************************************************************/
void TextType::Draw(OutputDevice& rOut)
{
    if ((Flags & TextOutlBit)!=0) return;   // Sourcetext fuer Outliner !!

    ObjTextType T1,T2;
    sal_uInt16 Index1;
    sal_uInt16 Index2;
    UCHAR  c = TextEnd;
    sal_uInt16 l;                // Anzahl der Zeichen in der Zeile
    sal_uInt16 i;
    short  yPos0;
    short  xPos;
    short  yPos;
    sal_uInt16 LF;
    sal_uInt16 MaxGrad;
    short  xSize;
    short  xSAdj;
    short  ySize;
    double sn,cs;
    sal_uInt16 TopToBase;
    sal_Bool   Ende = 0;
    sal_uInt16 lc;
    sal_Bool   LineFit; // FitSize.x=0? oder Flags -> jede Zeile stretchen
    sal_Bool   TextFit;
    short* xLine;
    UCHAR* cLine;   // Buffer fuer FormatLine
    sal_uInt16 FitXMul;
    sal_uInt16 FitXDiv;
    sal_uInt16 FitYMul;
    sal_uInt16 FitYDiv;
    sal_Bool   Fehler;
    UCHAR* Buf=Buffer; // Zeiger auf die Buchstaben

    pSgfFonts->ReadList();
    xLine=new short[ChrXPosArrSize];
    cLine=new UCHAR[CharLineSize];

    TextFit=(Flags & TextFitBits)!=0;
    LineFit=sal_False;
    LineFit=((Flags & TextFitZBit)!=0);
    if (TextFit && FitSize.x==0) LineFit=sal_True;

    if (DrehWink==0) {
        sn=0.0;
        cs=1.0;
    } else {
        sn=sin(double(DrehWink)*3.14159265359/18000);
        cs=cos(double(DrehWink)*3.14159265359/18000);
    }

    T1=T; Index1=0; yPos=0; xPos=0;
    if (TextFit) {
        ySize=Pos2.y-Pos1.y;
        xSize=32000 /2;      // Umbruch
        xSAdj=Pos2.x-Pos1.x; // zum Ausrichten bei Zentriert/Blocksatz
        //if (xSize<=0) { xSize=32000 /2; LineFit=sal_True; }
        FitXMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.x-Pos1.x)); FitXDiv=FitSize.x; if (FitXDiv==0) FitXDiv=1;
        FitYMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.y-Pos1.y)); FitYDiv=FitSize.y; if (FitYDiv==0) FitYDiv=1;
    } else {
        xSize=Pos2.x-Pos1.x;
        xSAdj=xSize;
        ySize=Pos2.y-Pos1.y;
        FitXMul=1; FitXDiv=1;
        FitYMul=1; FitYDiv=1;
    }
    if (xSize<0) xSize=0;
    if (xSAdj<0) xSAdj=0;

    do {
        T2=T1; Index2=Index1;
        FormatLine(Buf,Index2,T,T2,xSize,xSAdj,xLine,l,sn,cs,cLine,LineFit);
        Fehler=(Index2==Index1);
        if (!Fehler) {
            lc=GetLineFeed(Buf,Index1,T,T1,l,LF,MaxGrad);
            if (TextFit) {
                if (LineFit) FitXDiv=xLine[lc+1];
                if (FitXDiv>0) {
                    long Temp;
                    for (i=1;i<=l+1;i++) {
                        Temp=long(xLine[i])*long(FitXMul) /long(FitXDiv);
                        xLine[i]=short(Temp);
                    }
                    LF=MulDiv(LF,FitYMul,FitYDiv);
                    MaxGrad=MulDiv(MaxGrad,FitYMul,FitYDiv);
                } else {
                    FitXDiv=1; // 0 gibts nicht
                }
            }
            yPos0=yPos;
            TopToBase=GetTopToBaseLine(MaxGrad);
            yPos=yPos+TopToBase;
            Ende=(yPos0+short(MulDiv(MaxGrad,CharTopToBtm,100))>ySize) && !TextFit;
            if (!Ende) {
                T2=T1; Index2=Index1;
                i=1;
                while (i<=l) {
                    c=GetTextCharConv(Buf,Index2,T,T2,l-i,sal_False);
                    long xp1,yp1;       // wegen Overflowgefahr
                    PointType Pos;
                    xp1=long(Pos1.x)+xPos+long(xLine[i]);
                    yp1=long(Pos1.y)+yPos;
                    if (xp1>32000) xp1=32000; if (xp1<-12000) xp1=-12000;
                    if (yp1>32000) yp1=32000; if (yp1<-12000) yp1=-12000;
                    Pos.x=short(xp1);
                    Pos.y=short(yp1);

                    if (DrehWink!=0) RotatePoint(Pos,Pos1.x,Pos1.y,sn,cs);
                    DrawChar(rOut,c,T2,Pos,DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
                    i++;
                } // while i<=l
                yPos=yPos0+LF;
                T1=T2; Index1=Index2; // Fuer die naechste Zeile
            } // if ObjMin.y+yPos<=Obj_Max.y
        } // if !Fehler
    } while (c!=TextEnd && !Ende && !Fehler);
    delete[] cLine;
    delete[] xLine;
}

// End of DrawText.Pas
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

// nicht mehr benoetigt, da der Pointer nun extra gefuehrt wird
// (DEC Alpha hat naemlich 64Bit-Pointer!)
//UCHAR* TextType::GetBufPtr()
//{
//    sal_uLong Temp;
//    Temp=sal_uLong(BufLo)+0x00010000*sal_uLong(BufHi);
//    return (UCHAR*)Temp;
//}
//
//void TextType::SetBufPtr(UCHAR* Ptr)
//{
//    sal_uLong Temp=(sal_uLong)Ptr;
//    BufLo=sal_uInt16(Temp & 0x0000FFFF);
//    BufHi=sal_uInt16((Temp & 0xFFFF0000)>>16);
//}

sal_uInt32 ObjTextType::GetFont()
{
    return sal_uLong(FontLo)+0x00010000*sal_uLong(FontHi);
}

void ObjTextType::SetFont(sal_uInt32 FontID)
{
    FontLo=sal_uInt16(FontID & 0x0000FFFF);
    FontHi=sal_uInt16((FontID & 0xFFFF0000)>>16);
}


/////////////////////////////////////////////////////////////////////////////////
// SGF.Ini lesen ////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
SgfFontOne::SgfFontOne()
{
    Next=NULL;
    IFID=0;
    Bold=sal_False;
    Ital=sal_False;
    Sans=sal_False;
    Serf=sal_False;
    Fixd=sal_False;
    SVFamil=FAMILY_DONTKNOW;
    SVChSet=RTL_TEXTENCODING_DONTKNOW;
    SVWidth=40;
}

void SgfFontOne::ReadOne( const rtl::OString& rID, rtl::OString& Dsc )
{
    if ( Dsc.getLength() < 4 || ( Dsc[0] != '(' ) )
        return;
    sal_Int32 i=1;   // Erster Buchstabe des IF-Fontnamen. Davor ist eine '('
    while ( i < Dsc.getLength() && ( Dsc[i] !=')' ) )
        i++;
    Dsc = Dsc.copy(i+1);                                // IF-Fontname loeschen inkl. ()

    if ( Dsc.getLength() < 2 || ( Dsc[Dsc.getLength() - 1] !=')' ) )
        return;
    i=Dsc.getLength()-2;                                // hier ist die ')' des SV-Fontnames
    sal_Int32 j=0;
    while ( i > 0 && ( Dsc[i] != '(' ) )
    {
        i--;
        j++;
    }
    SVFName=String(Dsc,i+1,j);                       // SV-Fontname rausholen
    Dsc = rtl::OStringBuffer(Dsc).remove(i,j).makeStringAndClear();

    IFID = (sal_uInt32)rID.toInt32();
    sal_Int32 nTokenCount = comphelper::string::getTokenCount(Dsc, ' ');
    for (sal_Int32 nIdx = 0; nIdx < nTokenCount; ++nIdx)
    {
        rtl::OString s(Dsc.getToken(nIdx, ' '));
        if (!s.isEmpty())
        {
            s = s.toAsciiUpperCase();
            if      (s.matchL(RTL_CONSTASCII_STRINGPARAM("BOLD"))) Bold=sal_True;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ITAL"))) Ital=sal_True;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SERF"))) Serf=sal_True;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SANS"))) Sans=sal_True;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("FIXD"))) Fixd=sal_True;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ROMAN"))) SVFamil=FAMILY_ROMAN;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SWISS"))) SVFamil=FAMILY_SWISS;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("MODERN"))) SVFamil=FAMILY_MODERN;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SCRIPT"))) SVFamil=FAMILY_SCRIPT;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("DECORA"))) SVFamil=FAMILY_DECORATIVE;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ANSI"))) SVChSet=RTL_TEXTENCODING_MS_1252;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("IBMPC"))) SVChSet=RTL_TEXTENCODING_IBM_850;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("MAC"))) SVChSet=RTL_TEXTENCODING_APPLE_ROMAN;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SYMBOL"))) SVChSet=RTL_TEXTENCODING_SYMBOL;
            else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SYSTEM"))) SVChSet = osl_getThreadTextEncoding();
            else if (comphelper::string::isdigitAsciiString(s) ) SVWidth=sal::static_int_cast< sal_uInt16 >(s.toInt32());
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////

SgfFontLst::SgfFontLst()
{
    pList=NULL;
    Last=NULL;
    LastID=0;
    LastLn=NULL;
    Tried=sal_False;
}

SgfFontLst::~SgfFontLst()
{
    RausList();
}

void SgfFontLst::RausList()
{
    SgfFontOne* P;
    SgfFontOne* P1;
    P=pList;
    while (P!=NULL) {
        P1=P->Next;
        delete P;
        P=P1;
    }
    pList=NULL;
    Last=NULL;
    Tried=sal_False;
    LastID=0;
    LastLn=NULL;
}

void SgfFontLst::AssignFN(const String& rFName)
{   FNam=rFName;   }

void SgfFontLst::ReadList()
{
    if (!Tried)
    {
        Tried=sal_True;
        LastID=0;
        LastLn=NULL;
        SgfFontOne* P,P1;
        Config aCfg(FNam);
        aCfg.SetGroup("SGV Fonts fuer StarView");
        sal_uInt16 Anz=aCfg.GetKeyCount();
        sal_uInt16 i;
        rtl::OString FID;
        rtl::OString Dsc;

        for (i=0;i<Anz;i++)
        {
            FID = comphelper::string::remove(aCfg.GetKeyName(i), ' ');
            Dsc = aCfg.ReadKey( i );
            if (comphelper::string::isdigitAsciiString(FID))
            {
                P=new SgfFontOne;                                   // neuer Eintrag
                if (Last!=NULL) Last->Next=P; else pList=P; Last=P; // einklinken
                P->ReadOne(FID,Dsc);                                // und Zeile interpretieren
            }
        }
    }
}

SgfFontOne* SgfFontLst::GetFontDesc(sal_uInt32 ID)
{
    if (ID!=LastID) {
        SgfFontOne* P;
        P=pList;
        while (P!=NULL && P->IFID!=ID) P=P->Next;
        LastID=ID;
        LastLn=P;
    }
    return LastLn;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */