// @(#)root/base:$Id$
// Author: Rene Brun   05/09/99

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//______________________________________________________________________________
//
// TVirtualPS is an abstract interface to a Postscript, PDF and SVG drivers
//

#include "Riostream.h"
#include "TVirtualPS.h"

TVirtualPS *gVirtualPS = 0;

const Int_t  kMaxBuffer = 250;

ClassImp(TVirtualPS)


//______________________________________________________________________________
TVirtualPS::TVirtualPS()
{
   // VirtualPS default constructor.

   fStream    = 0;
   fNByte     = 0;
   fSizBuffer = kMaxBuffer;
   fBuffer    = new char[fSizBuffer+1];
   fLenBuffer = 0;
   fPrinted   = kFALSE;
   fImplicitCREsc = 0;
}


//______________________________________________________________________________
TVirtualPS::TVirtualPS(const char *name, Int_t)
          : TNamed(name,"Postscript interface")
{
   // VirtualPS constructor.

   fStream    = 0;
   fNByte     = 0;
   fSizBuffer = kMaxBuffer;
   fBuffer    = new char[fSizBuffer+1];
   fLenBuffer = 0;
   fPrinted   = kFALSE;
   fImplicitCREsc = 0;
}


//______________________________________________________________________________
TVirtualPS::~TVirtualPS()
{
   // VirtualPS destructor

   if (fBuffer) delete [] fBuffer;
}


//______________________________________________________________________________
void TVirtualPS::PrintStr(const char *str)
{
   // Output the string str in the output buffer

   if (!str || !str[0])
      return;
   Int_t len = strlen(str);
   while (len) {
      if (str[0] == '@') {
         if (fLenBuffer) {
            fStream->write(fBuffer, fLenBuffer);
            fNByte += fLenBuffer;
            fLenBuffer = 0;
            fStream->write("\n", 1);
            fNByte++;
            fPrinted = kTRUE;
         }
         len--;
         str++;
      } else {
         Int_t lenText = len;
         if (str[len-1] == '@') lenText--;
         PrintFast(lenText, str);
         len -= lenText;
         str += lenText;
      }
   }
}


//______________________________________________________________________________
void TVirtualPS::PrintFast(Int_t len, const char *str)
{
   // Fast version of Print
   if (!len || !str) return;
   while ((len + fLenBuffer) > kMaxBuffer) {
      Int_t nWrite = kMaxBuffer;
      if (fImplicitCREsc) {
         if (fLenBuffer > 0) nWrite = fLenBuffer;
      } else {
         if ((len + fLenBuffer) > nWrite) {
            // Search for the nearest preceding space to break a line, if there is no instruction to escape the <end-of-line>.
            while ((nWrite >= fLenBuffer) && (str[nWrite - fLenBuffer] != ' ')) nWrite--;
            if (nWrite < fLenBuffer) {
               while ((nWrite >= 0) && (fBuffer[nWrite] != ' ')) nWrite--;
            }
            if (nWrite <= 0) {
               // Cannot find a convenient place to break a line, so we just break at this location.
               nWrite = kMaxBuffer;
            }
         }
      }
      if (nWrite >= fLenBuffer) {
         if (fLenBuffer > 0) {
            fStream->write(fBuffer, fLenBuffer);
            fNByte += fLenBuffer;
            nWrite -= fLenBuffer;
            fLenBuffer = 0;
         }
         if (nWrite > 0) {
            fStream->write(str, nWrite);
            len -= nWrite;
            str += nWrite;
            fNByte += nWrite;
         }
      } else {
         if (nWrite > 0) {
            fStream->write(fBuffer, nWrite);
            fNByte += nWrite;
            memmove(fBuffer, fBuffer + nWrite, fLenBuffer - nWrite); // not strcpy because source and destination overlap
            fBuffer[fLenBuffer - nWrite] = 0; // not sure if this is needed, but just in case
            fLenBuffer -= nWrite;
         }
      }
      if (fImplicitCREsc) {
         // Write escape characters (if any) before an end-of-line is enforced.
         // For example, in PostScript the <new line> character must be escaped inside strings.
         Int_t crlen = strlen(fImplicitCREsc);
         fStream->write(fImplicitCREsc, crlen);
         fNByte += crlen;
      }
      fStream->write("\n",1);
      fNByte++;
   }
   if (len > 0) {
      strlcpy(fBuffer + fLenBuffer, str, len+1);
      fLenBuffer += len;
      fBuffer[fLenBuffer] = 0;
   }
   fPrinted = kTRUE;
}


//______________________________________________________________________________
void TVirtualPS::WriteInteger(Int_t n, Bool_t space )
{
   // Write one Integer to the file
   //
   // n: Integer to be written in the file.
   // space: If TRUE, a space in written before the integer.

   char str[15];
   if (space) {
      snprintf(str,15," %d", n);
   } else {
      snprintf(str,15,"%d", n);
   }
   PrintStr(str);
}


//______________________________________________________________________________
void TVirtualPS::WriteReal(Float_t z, Bool_t space)
{
   // Write a Real number to the file

   char str[15];
   if (space) {
      snprintf(str,15," %g", z);
   } else {
      snprintf(str,15,"%g", z);
   }
   PrintStr(str);
}


//______________________________________________________________________________
void TVirtualPS::PrintRaw(Int_t len, const char *str)
{
   // Print a raw

   fNByte += len;
   if ((len + fLenBuffer) > kMaxBuffer - 1) {
      fStream->write(fBuffer, fLenBuffer);
      while(len > kMaxBuffer-1) {
         fStream->write(str,kMaxBuffer);
         len -= kMaxBuffer;
         str += kMaxBuffer;
      }
      memcpy(fBuffer, str, len);
      fLenBuffer = len;
   } else {
      memcpy(fBuffer + fLenBuffer, str, len);
      fLenBuffer += len;
   }
   fPrinted = kTRUE;
}
 TVirtualPS.cxx:1
 TVirtualPS.cxx:2
 TVirtualPS.cxx:3
 TVirtualPS.cxx:4
 TVirtualPS.cxx:5
 TVirtualPS.cxx:6
 TVirtualPS.cxx:7
 TVirtualPS.cxx:8
 TVirtualPS.cxx:9
 TVirtualPS.cxx:10
 TVirtualPS.cxx:11
 TVirtualPS.cxx:12
 TVirtualPS.cxx:13
 TVirtualPS.cxx:14
 TVirtualPS.cxx:15
 TVirtualPS.cxx:16
 TVirtualPS.cxx:17
 TVirtualPS.cxx:18
 TVirtualPS.cxx:19
 TVirtualPS.cxx:20
 TVirtualPS.cxx:21
 TVirtualPS.cxx:22
 TVirtualPS.cxx:23
 TVirtualPS.cxx:24
 TVirtualPS.cxx:25
 TVirtualPS.cxx:26
 TVirtualPS.cxx:27
 TVirtualPS.cxx:28
 TVirtualPS.cxx:29
 TVirtualPS.cxx:30
 TVirtualPS.cxx:31
 TVirtualPS.cxx:32
 TVirtualPS.cxx:33
 TVirtualPS.cxx:34
 TVirtualPS.cxx:35
 TVirtualPS.cxx:36
 TVirtualPS.cxx:37
 TVirtualPS.cxx:38
 TVirtualPS.cxx:39
 TVirtualPS.cxx:40
 TVirtualPS.cxx:41
 TVirtualPS.cxx:42
 TVirtualPS.cxx:43
 TVirtualPS.cxx:44
 TVirtualPS.cxx:45
 TVirtualPS.cxx:46
 TVirtualPS.cxx:47
 TVirtualPS.cxx:48
 TVirtualPS.cxx:49
 TVirtualPS.cxx:50
 TVirtualPS.cxx:51
 TVirtualPS.cxx:52
 TVirtualPS.cxx:53
 TVirtualPS.cxx:54
 TVirtualPS.cxx:55
 TVirtualPS.cxx:56
 TVirtualPS.cxx:57
 TVirtualPS.cxx:58
 TVirtualPS.cxx:59
 TVirtualPS.cxx:60
 TVirtualPS.cxx:61
 TVirtualPS.cxx:62
 TVirtualPS.cxx:63
 TVirtualPS.cxx:64
 TVirtualPS.cxx:65
 TVirtualPS.cxx:66
 TVirtualPS.cxx:67
 TVirtualPS.cxx:68
 TVirtualPS.cxx:69
 TVirtualPS.cxx:70
 TVirtualPS.cxx:71
 TVirtualPS.cxx:72
 TVirtualPS.cxx:73
 TVirtualPS.cxx:74
 TVirtualPS.cxx:75
 TVirtualPS.cxx:76
 TVirtualPS.cxx:77
 TVirtualPS.cxx:78
 TVirtualPS.cxx:79
 TVirtualPS.cxx:80
 TVirtualPS.cxx:81
 TVirtualPS.cxx:82
 TVirtualPS.cxx:83
 TVirtualPS.cxx:84
 TVirtualPS.cxx:85
 TVirtualPS.cxx:86
 TVirtualPS.cxx:87
 TVirtualPS.cxx:88
 TVirtualPS.cxx:89
 TVirtualPS.cxx:90
 TVirtualPS.cxx:91
 TVirtualPS.cxx:92
 TVirtualPS.cxx:93
 TVirtualPS.cxx:94
 TVirtualPS.cxx:95
 TVirtualPS.cxx:96
 TVirtualPS.cxx:97
 TVirtualPS.cxx:98
 TVirtualPS.cxx:99
 TVirtualPS.cxx:100
 TVirtualPS.cxx:101
 TVirtualPS.cxx:102
 TVirtualPS.cxx:103
 TVirtualPS.cxx:104
 TVirtualPS.cxx:105
 TVirtualPS.cxx:106
 TVirtualPS.cxx:107
 TVirtualPS.cxx:108
 TVirtualPS.cxx:109
 TVirtualPS.cxx:110
 TVirtualPS.cxx:111
 TVirtualPS.cxx:112
 TVirtualPS.cxx:113
 TVirtualPS.cxx:114
 TVirtualPS.cxx:115
 TVirtualPS.cxx:116
 TVirtualPS.cxx:117
 TVirtualPS.cxx:118
 TVirtualPS.cxx:119
 TVirtualPS.cxx:120
 TVirtualPS.cxx:121
 TVirtualPS.cxx:122
 TVirtualPS.cxx:123
 TVirtualPS.cxx:124
 TVirtualPS.cxx:125
 TVirtualPS.cxx:126
 TVirtualPS.cxx:127
 TVirtualPS.cxx:128
 TVirtualPS.cxx:129
 TVirtualPS.cxx:130
 TVirtualPS.cxx:131
 TVirtualPS.cxx:132
 TVirtualPS.cxx:133
 TVirtualPS.cxx:134
 TVirtualPS.cxx:135
 TVirtualPS.cxx:136
 TVirtualPS.cxx:137
 TVirtualPS.cxx:138
 TVirtualPS.cxx:139
 TVirtualPS.cxx:140
 TVirtualPS.cxx:141
 TVirtualPS.cxx:142
 TVirtualPS.cxx:143
 TVirtualPS.cxx:144
 TVirtualPS.cxx:145
 TVirtualPS.cxx:146
 TVirtualPS.cxx:147
 TVirtualPS.cxx:148
 TVirtualPS.cxx:149
 TVirtualPS.cxx:150
 TVirtualPS.cxx:151
 TVirtualPS.cxx:152
 TVirtualPS.cxx:153
 TVirtualPS.cxx:154
 TVirtualPS.cxx:155
 TVirtualPS.cxx:156
 TVirtualPS.cxx:157
 TVirtualPS.cxx:158
 TVirtualPS.cxx:159
 TVirtualPS.cxx:160
 TVirtualPS.cxx:161
 TVirtualPS.cxx:162
 TVirtualPS.cxx:163
 TVirtualPS.cxx:164
 TVirtualPS.cxx:165
 TVirtualPS.cxx:166
 TVirtualPS.cxx:167
 TVirtualPS.cxx:168
 TVirtualPS.cxx:169
 TVirtualPS.cxx:170
 TVirtualPS.cxx:171
 TVirtualPS.cxx:172
 TVirtualPS.cxx:173
 TVirtualPS.cxx:174
 TVirtualPS.cxx:175
 TVirtualPS.cxx:176
 TVirtualPS.cxx:177
 TVirtualPS.cxx:178
 TVirtualPS.cxx:179
 TVirtualPS.cxx:180
 TVirtualPS.cxx:181
 TVirtualPS.cxx:182
 TVirtualPS.cxx:183
 TVirtualPS.cxx:184
 TVirtualPS.cxx:185
 TVirtualPS.cxx:186
 TVirtualPS.cxx:187
 TVirtualPS.cxx:188
 TVirtualPS.cxx:189
 TVirtualPS.cxx:190
 TVirtualPS.cxx:191
 TVirtualPS.cxx:192
 TVirtualPS.cxx:193
 TVirtualPS.cxx:194
 TVirtualPS.cxx:195
 TVirtualPS.cxx:196
 TVirtualPS.cxx:197
 TVirtualPS.cxx:198
 TVirtualPS.cxx:199
 TVirtualPS.cxx:200
 TVirtualPS.cxx:201
 TVirtualPS.cxx:202
 TVirtualPS.cxx:203
 TVirtualPS.cxx:204
 TVirtualPS.cxx:205
 TVirtualPS.cxx:206
 TVirtualPS.cxx:207
 TVirtualPS.cxx:208
 TVirtualPS.cxx:209
 TVirtualPS.cxx:210
 TVirtualPS.cxx:211
 TVirtualPS.cxx:212
 TVirtualPS.cxx:213
 TVirtualPS.cxx:214