/src/libreoffice/vcl/source/gdi/jobset.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <rtl/ustring.hxx> |
21 | | #include <sal/log.hxx> |
22 | | #include <tools/solar.h> |
23 | | #include <tools/stream.hxx> |
24 | | #include <vcl/jobset.hxx> |
25 | | #include <jobset.h> |
26 | | #include <memory> |
27 | | |
28 | 2.10k | #define JOBSET_FILE364_SYSTEM (sal_uInt16(0xFFFF)) |
29 | 1.38k | #define JOBSET_FILE605_SYSTEM (sal_uInt16(0xFFFE)) |
30 | | |
31 | | namespace { |
32 | | |
33 | | // used only for compatibility with older versions, |
34 | | // printer/driver name are truncated if too long, |
35 | | // device name and port name are completely unused |
36 | | struct ImplOldJobSetupData |
37 | | { |
38 | | char cPrinterName[64]; |
39 | | char cDeviceName[32]; |
40 | | char cPortName[32]; |
41 | | char cDriverName[32]; |
42 | | }; |
43 | | |
44 | | struct Impl364JobSetupData |
45 | | { |
46 | | SVBT16 nSize; |
47 | | SVBT16 nSystem; |
48 | | SVBT32 nDriverDataLen; |
49 | | SVBT16 nOrientation; |
50 | | SVBT16 nPaperBin; |
51 | | SVBT16 nPaperFormat; |
52 | | SVBT32 nPaperWidth; |
53 | | SVBT32 nPaperHeight; |
54 | | }; |
55 | | |
56 | | } |
57 | | |
58 | | ImplJobSetup::ImplJobSetup() |
59 | 12 | { |
60 | 12 | mnSystem = 0; |
61 | 12 | meOrientation = Orientation::Portrait; |
62 | 12 | meDuplexMode = DuplexMode::Unknown; |
63 | 12 | mnPaperBin = 0; |
64 | 12 | mePaperFormat = PAPER_USER; |
65 | 12 | mnPaperWidth = 0; |
66 | 12 | mnPaperHeight = 0; |
67 | 12 | mnDriverDataLen = 0; |
68 | 12 | mbPapersizeFromSetup = false; |
69 | 12 | meSetupMode = PrinterSetupMode::DocumentGlobal; |
70 | 12 | } |
71 | | |
72 | | ImplJobSetup::ImplJobSetup( const ImplJobSetup& rJobSetup ) : |
73 | 703 | mnSystem( rJobSetup.GetSystem() ), |
74 | 703 | maPrinterName( rJobSetup.GetPrinterName() ), |
75 | 703 | maDriver( rJobSetup.GetDriver() ), |
76 | 703 | meOrientation( rJobSetup.GetOrientation() ), |
77 | 703 | meDuplexMode( rJobSetup.GetDuplexMode() ), |
78 | 703 | mnPaperBin( rJobSetup.GetPaperBin() ), |
79 | 703 | mePaperFormat( rJobSetup.GetPaperFormat() ), |
80 | 703 | mnPaperWidth( rJobSetup.GetPaperWidth() ), |
81 | 703 | mnPaperHeight( rJobSetup.GetPaperHeight() ), |
82 | 703 | mnDriverDataLen( rJobSetup.GetDriverDataLen() ), |
83 | 703 | mpDriverData(), |
84 | 703 | mbPapersizeFromSetup( rJobSetup.GetPapersizeFromSetup() ), |
85 | 703 | meSetupMode( rJobSetup.GetPrinterSetupMode() ), |
86 | 703 | maValueMap( rJobSetup.GetValueMap() ) |
87 | 703 | { |
88 | 703 | if ( rJobSetup.GetDriverData() ) |
89 | 0 | { |
90 | 0 | mpDriverData.reset( new sal_uInt8[mnDriverDataLen] ); |
91 | 0 | memcpy( mpDriverData.get(), rJobSetup.GetDriverData(), mnDriverDataLen ); |
92 | 0 | } |
93 | 703 | else |
94 | 703 | mpDriverData = nullptr; |
95 | 703 | } |
96 | | |
97 | | ImplJobSetup::~ImplJobSetup() |
98 | 712 | { |
99 | 712 | } |
100 | | |
101 | | void ImplJobSetup::SetSystem(sal_uInt16 nSystem) |
102 | 685 | { |
103 | 685 | mnSystem = nSystem; |
104 | 685 | } |
105 | | |
106 | | void ImplJobSetup::SetPrinterName(const OUString& rPrinterName) |
107 | 703 | { |
108 | 703 | maPrinterName = rPrinterName; |
109 | 703 | } |
110 | | |
111 | | void ImplJobSetup::SetDriver(const OUString& rDriver) |
112 | 703 | { |
113 | 703 | maDriver = rDriver; |
114 | 703 | } |
115 | | |
116 | | void ImplJobSetup::SetOrientation(Orientation eOrientation) |
117 | 685 | { |
118 | 685 | meOrientation = eOrientation; |
119 | 685 | } |
120 | | |
121 | | void ImplJobSetup::SetDuplexMode(DuplexMode eDuplexMode) |
122 | 685 | { |
123 | 685 | meDuplexMode = eDuplexMode; |
124 | 685 | } |
125 | | |
126 | | void ImplJobSetup::SetPaperBin(sal_uInt16 nPaperBin) |
127 | 685 | { |
128 | 685 | mnPaperBin = nPaperBin; |
129 | 685 | } |
130 | | |
131 | | void ImplJobSetup::SetPaperFormat(Paper ePaperFormat) |
132 | 359 | { |
133 | 359 | mePaperFormat = ePaperFormat; |
134 | 359 | } |
135 | | |
136 | | void ImplJobSetup::SetPaperWidth(tools::Long nPaperWidth) |
137 | 685 | { |
138 | 685 | mnPaperWidth = nPaperWidth; |
139 | 685 | } |
140 | | |
141 | | void ImplJobSetup::SetPaperHeight(tools::Long nPaperHeight) |
142 | 685 | { |
143 | 685 | mnPaperHeight = nPaperHeight; |
144 | 685 | } |
145 | | |
146 | | void ImplJobSetup::SetDriverData(std::unique_ptr<sal_uInt8[]> pDriverData, sal_uInt32 nDriverDataLen) |
147 | 236 | { |
148 | 236 | mpDriverData = std::move(pDriverData); |
149 | 236 | mnDriverDataLen = nDriverDataLen; |
150 | 236 | } |
151 | | |
152 | | void ImplJobSetup::SetPapersizeFromSetup(bool bPapersizeFromSetup) |
153 | 0 | { |
154 | 0 | mbPapersizeFromSetup = bPapersizeFromSetup; |
155 | 0 | } |
156 | | |
157 | | void ImplJobSetup::SetPrinterSetupMode(PrinterSetupMode eMode) |
158 | 0 | { |
159 | 0 | meSetupMode = eMode; |
160 | 0 | } |
161 | | |
162 | | void ImplJobSetup::SetValueMap( const OUString& rKey, const OUString& rValue ) |
163 | 7.85k | { |
164 | 7.85k | maValueMap [ rKey ] = rValue; |
165 | 7.85k | } |
166 | | |
167 | 0 | JobSetup& JobSetup::operator=( const JobSetup& ) = default; |
168 | | |
169 | 0 | JobSetup& JobSetup::operator=( JobSetup&& ) = default; |
170 | | |
171 | | bool ImplJobSetup::operator==( const ImplJobSetup& rImplJobSetup ) const |
172 | 0 | { |
173 | 0 | return mnSystem == rImplJobSetup.mnSystem && |
174 | 0 | maPrinterName == rImplJobSetup.maPrinterName && |
175 | 0 | maDriver == rImplJobSetup.maDriver && |
176 | 0 | meOrientation == rImplJobSetup.meOrientation && |
177 | 0 | meDuplexMode == rImplJobSetup.meDuplexMode && |
178 | 0 | mnPaperBin == rImplJobSetup.mnPaperBin && |
179 | 0 | mePaperFormat == rImplJobSetup.mePaperFormat && |
180 | 0 | mnPaperWidth == rImplJobSetup.mnPaperWidth && |
181 | 0 | mnPaperHeight == rImplJobSetup.mnPaperHeight && |
182 | 0 | mbPapersizeFromSetup == rImplJobSetup.mbPapersizeFromSetup && |
183 | 0 | mnDriverDataLen == rImplJobSetup.mnDriverDataLen && |
184 | 0 | maValueMap == rImplJobSetup.maValueMap && |
185 | 0 | memcmp( mpDriverData.get(), |
186 | 0 | rImplJobSetup.mpDriverData.get(), |
187 | 0 | std::min(mnDriverDataLen, rImplJobSetup.mnDriverDataLen)) == 0; |
188 | 0 | } |
189 | | |
190 | | namespace |
191 | | { |
192 | | JobSetup::ImplType& GetGlobalDefault() |
193 | 28.5k | { |
194 | 28.5k | static JobSetup::ImplType gDefault; |
195 | 28.5k | return gDefault; |
196 | 28.5k | } |
197 | | } |
198 | | |
199 | 28.4k | JobSetup::JobSetup() : mpData(GetGlobalDefault()) |
200 | 28.4k | { |
201 | 28.4k | } |
202 | | |
203 | 0 | JobSetup::JobSetup( const JobSetup& ) = default; |
204 | | |
205 | 28.4k | JobSetup::~JobSetup() = default; |
206 | | |
207 | | bool JobSetup::operator==( const JobSetup& rJobSetup ) const |
208 | 0 | { |
209 | 0 | return mpData == rJobSetup.mpData; |
210 | 0 | } |
211 | | |
212 | | const ImplJobSetup& JobSetup::ImplGetConstData() const |
213 | 1.66k | { |
214 | 1.66k | return *mpData; |
215 | 1.66k | } |
216 | | |
217 | | ImplJobSetup& JobSetup::ImplGetData() |
218 | 703 | { |
219 | 703 | return *mpData; |
220 | 703 | } |
221 | | |
222 | | OUString const & JobSetup::GetPrinterName() const |
223 | 3.18k | { |
224 | 3.18k | return mpData->GetPrinterName(); |
225 | 3.18k | } |
226 | | |
227 | | bool JobSetup::IsDefault() const |
228 | 69 | { |
229 | 69 | return mpData.same_object(GetGlobalDefault()); |
230 | 69 | } |
231 | | |
232 | | SvStream& ReadJobSetup( SvStream& rIStream, JobSetup& rJobSetup ) |
233 | 1.59k | { |
234 | 1.59k | { |
235 | 1.59k | sal_uInt16 nLen = 0; |
236 | 1.59k | rIStream.ReadUInt16( nLen ); |
237 | 1.59k | if (nLen <= 4) |
238 | 0 | return rIStream; |
239 | | |
240 | 1.59k | sal_uInt16 nSystem = 0; |
241 | 1.59k | rIStream.ReadUInt16( nSystem ); |
242 | 1.59k | size_t nRead = nLen - sizeof(nLen) - sizeof(nSystem); |
243 | 1.59k | if (nRead > rIStream.remainingSize()) |
244 | 888 | { |
245 | 888 | SAL_WARN("vcl", "Parsing error: " << rIStream.remainingSize() << |
246 | 888 | " max possible entries, but " << nRead << " claimed, truncating"); |
247 | 888 | return rIStream; |
248 | 888 | } |
249 | 704 | sal_uInt64 const nFirstPos = rIStream.Tell(); |
250 | 704 | std::unique_ptr<char[]> pTempBuf(new char[nRead]); |
251 | 704 | nRead = rIStream.ReadBytes(pTempBuf.get(), nRead); |
252 | 704 | if (nRead >= sizeof(ImplOldJobSetupData)) |
253 | 703 | { |
254 | 703 | ImplOldJobSetupData* pData = reinterpret_cast<ImplOldJobSetupData*>(pTempBuf.get()); |
255 | | |
256 | 703 | rtl_TextEncoding aStreamEncoding = RTL_TEXTENCODING_UTF8; |
257 | 703 | if( nSystem == JOBSET_FILE364_SYSTEM ) |
258 | 0 | aStreamEncoding = rIStream.GetStreamEncoding(); |
259 | | |
260 | 703 | ImplJobSetup& rJobData = rJobSetup.ImplGetData(); |
261 | | |
262 | | // use (potentially truncated) printer/driver name from ImplOldJobSetupData as fallback, |
263 | | // gets overwritten below if PRINTER_NAME/DRIVER_NAME keys are set |
264 | 703 | pData->cPrinterName[std::size(pData->cPrinterName) - 1] = 0; |
265 | 703 | rJobData.SetPrinterName( OStringToOUString(pData->cPrinterName, aStreamEncoding) ); |
266 | 703 | pData->cDriverName[std::size(pData->cDriverName) - 1] = 0; |
267 | 703 | rJobData.SetDriver( OStringToOUString(pData->cDriverName, aStreamEncoding) ); |
268 | | |
269 | | // Are these our new JobSetup files? |
270 | 703 | if ( nSystem == JOBSET_FILE364_SYSTEM || |
271 | 703 | nSystem == JOBSET_FILE605_SYSTEM ) |
272 | 685 | { |
273 | 685 | if (nRead < sizeof(ImplOldJobSetupData) + sizeof(Impl364JobSetupData)) |
274 | 0 | { |
275 | 0 | SAL_WARN("vcl", "Parsing error: " << sizeof(ImplOldJobSetupData) + sizeof(Impl364JobSetupData) << |
276 | 0 | " required, but " << nRead << " available"); |
277 | 0 | return rIStream; |
278 | 0 | } |
279 | | |
280 | 685 | Impl364JobSetupData* pOldJobData = reinterpret_cast<Impl364JobSetupData*>(pTempBuf.get() + sizeof( ImplOldJobSetupData )); |
281 | 685 | sal_uInt16 nOldJobDataSize = SVBT16ToUInt16( pOldJobData->nSize ); |
282 | 685 | rJobData.SetSystem( SVBT16ToUInt16( pOldJobData->nSystem ) ); |
283 | 685 | const sal_uInt32 nDriverDataLen = SVBT32ToUInt32( pOldJobData->nDriverDataLen ); |
284 | 685 | rJobData.SetOrientation( static_cast<Orientation>(SVBT16ToUInt16( pOldJobData->nOrientation )) ); |
285 | 685 | rJobData.SetDuplexMode( DuplexMode::Unknown ); |
286 | 685 | rJobData.SetPaperBin( SVBT16ToUInt16( pOldJobData->nPaperBin ) ); |
287 | 685 | sal_uInt16 nPaperFormat = SVBT16ToUInt16(pOldJobData->nPaperFormat); |
288 | 685 | if (nPaperFormat < NUM_PAPER_ENTRIES) |
289 | 359 | rJobData.SetPaperFormat(static_cast<Paper>(nPaperFormat)); |
290 | 326 | else |
291 | 326 | { |
292 | 326 | SAL_WARN("vcl", "Parsing error: " << nPaperFormat << |
293 | 326 | " paper format, but legal max is " << NUM_PAPER_ENTRIES); |
294 | 326 | } |
295 | 685 | rJobData.SetPaperWidth( static_cast<tools::Long>(SVBT32ToUInt32( pOldJobData->nPaperWidth )) ); |
296 | 685 | rJobData.SetPaperHeight( static_cast<tools::Long>(SVBT32ToUInt32( pOldJobData->nPaperHeight )) ); |
297 | 685 | if ( nDriverDataLen ) |
298 | 586 | { |
299 | 586 | const char* pDriverData = reinterpret_cast<const char*>(pOldJobData) + nOldJobDataSize; |
300 | 586 | const char* pDriverDataEnd = pDriverData + nDriverDataLen; |
301 | 586 | if (pDriverDataEnd > pTempBuf.get() + nRead) |
302 | 350 | { |
303 | 350 | SAL_WARN("vcl", "corrupted job setup"); |
304 | 350 | } |
305 | 236 | else |
306 | 236 | { |
307 | 236 | auto pNewDriverData = std::make_unique<sal_uInt8[]>( nDriverDataLen ); |
308 | 236 | memcpy( pNewDriverData.get(), pDriverData, nDriverDataLen ); |
309 | 236 | rJobData.SetDriverData( std::move(pNewDriverData), nDriverDataLen ); |
310 | 236 | } |
311 | 586 | } |
312 | 685 | if( nSystem == JOBSET_FILE605_SYSTEM ) |
313 | 685 | { |
314 | 685 | rIStream.Seek( nFirstPos + sizeof( ImplOldJobSetupData ) + |
315 | 685 | sizeof( Impl364JobSetupData ) + rJobData.GetDriverDataLen() ); |
316 | 8.72k | while( rIStream.Tell() < nFirstPos + nRead ) |
317 | 8.04k | { |
318 | 8.04k | OUString aKey = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStream, RTL_TEXTENCODING_UTF8); |
319 | 8.04k | OUString aValue = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStream, RTL_TEXTENCODING_UTF8); |
320 | 8.04k | if( aKey == "COMPAT_DUPLEX_MODE" ) |
321 | 189 | { |
322 | 189 | if( aValue == "DuplexMode::Unknown" ) |
323 | 0 | rJobData.SetDuplexMode( DuplexMode::Unknown ); |
324 | 189 | else if( aValue == "DuplexMode::Off" ) |
325 | 0 | rJobData.SetDuplexMode( DuplexMode::Off ); |
326 | 189 | else if( aValue == "DuplexMode::ShortEdge" ) |
327 | 0 | rJobData.SetDuplexMode( DuplexMode::ShortEdge ); |
328 | 189 | else if( aValue == "DuplexMode::LongEdge" ) |
329 | 0 | rJobData.SetDuplexMode( DuplexMode::LongEdge ); |
330 | 189 | } |
331 | 7.85k | else if (aKey == u"PRINTER_NAME") |
332 | 0 | rJobData.SetPrinterName(aValue); |
333 | 7.85k | else if (aKey == u"DRIVER_NAME") |
334 | 0 | rJobData.SetDriver(aValue); |
335 | 7.85k | else |
336 | 7.85k | rJobData.SetValueMap(aKey, aValue); |
337 | 8.04k | } |
338 | 685 | SAL_WARN_IF( rIStream.Tell() != nFirstPos+nRead, "vcl", "corrupted job setup" ); |
339 | | // ensure correct stream position |
340 | 685 | rIStream.Seek(nFirstPos + nRead); |
341 | 685 | } |
342 | 685 | } |
343 | 703 | } |
344 | 704 | } |
345 | | |
346 | 704 | return rIStream; |
347 | 704 | } |
348 | | |
349 | | SvStream& WriteJobSetup( SvStream& rOStream, const JobSetup& rJobSetup ) |
350 | 69 | { |
351 | 69 | { |
352 | 69 | sal_uInt16 nLen = 0; |
353 | 69 | if ( rJobSetup.IsDefault() ) |
354 | 69 | rOStream.WriteUInt16( nLen ); |
355 | 0 | else |
356 | 0 | { |
357 | 0 | const ImplJobSetup& rJobData = rJobSetup.ImplGetConstData(); |
358 | 0 | Impl364JobSetupData aOldJobData; |
359 | 0 | sal_uInt16 nOldJobDataSize = sizeof( aOldJobData ); |
360 | 0 | ShortToSVBT16( nOldJobDataSize, aOldJobData.nSize ); |
361 | 0 | ShortToSVBT16( rJobData.GetSystem(), aOldJobData.nSystem ); |
362 | 0 | UInt32ToSVBT32( rJobData.GetDriverDataLen(), aOldJobData.nDriverDataLen ); |
363 | 0 | ShortToSVBT16( static_cast<sal_uInt16>(rJobData.GetOrientation()), aOldJobData.nOrientation ); |
364 | 0 | ShortToSVBT16( rJobData.GetPaperBin(), aOldJobData.nPaperBin ); |
365 | 0 | ShortToSVBT16( static_cast<sal_uInt16>(rJobData.GetPaperFormat()), aOldJobData.nPaperFormat ); |
366 | 0 | UInt32ToSVBT32( static_cast<sal_uInt32>(rJobData.GetPaperWidth()), aOldJobData.nPaperWidth ); |
367 | 0 | UInt32ToSVBT32( static_cast<sal_uInt32>(rJobData.GetPaperHeight()), aOldJobData.nPaperHeight ); |
368 | |
|
369 | 0 | ImplOldJobSetupData aOldData = {}; |
370 | 0 | OString aPrnByteName(OUStringToOString(rJobData.GetPrinterName(), RTL_TEXTENCODING_UTF8)); |
371 | 0 | strncpy(aOldData.cPrinterName, aPrnByteName.getStr(), std::size(aOldData.cPrinterName) - 1); |
372 | 0 | OString aDriverByteName(OUStringToOString(rJobData.GetDriver(), RTL_TEXTENCODING_UTF8)); |
373 | 0 | strncpy(aOldData.cDriverName, aDriverByteName.getStr(), std::size(aOldData.cDriverName) - 1); |
374 | 0 | int nPos = rOStream.Tell(); |
375 | 0 | rOStream.WriteUInt16( 0 ); |
376 | 0 | rOStream.WriteUInt16( JOBSET_FILE605_SYSTEM ); |
377 | 0 | rOStream.WriteBytes( &aOldData, sizeof( aOldData ) ); |
378 | 0 | rOStream.WriteBytes( &aOldJobData, nOldJobDataSize ); |
379 | 0 | rOStream.WriteBytes( rJobData.GetDriverData(), rJobData.GetDriverDataLen() ); |
380 | |
|
381 | 0 | const std::unordered_map< OUString, OUString >& rValueMap( |
382 | 0 | rJobData.GetValueMap()); |
383 | |
|
384 | 0 | for (auto const& value : rValueMap) |
385 | 0 | { |
386 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, value.first, RTL_TEXTENCODING_UTF8); |
387 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, value.second, RTL_TEXTENCODING_UTF8); |
388 | 0 | } |
389 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "COMPAT_DUPLEX_MODE"); |
390 | 0 | switch( rJobData.GetDuplexMode() ) |
391 | 0 | { |
392 | 0 | case DuplexMode::Unknown: |
393 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "DuplexMode::Unknown"); |
394 | 0 | break; |
395 | 0 | case DuplexMode::Off: |
396 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "DuplexMode::Off"); |
397 | 0 | break; |
398 | 0 | case DuplexMode::ShortEdge: |
399 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "DuplexMode::ShortEdge"); |
400 | 0 | break; |
401 | 0 | case DuplexMode::LongEdge: |
402 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "DuplexMode::LongEdge"); |
403 | 0 | break; |
404 | 0 | } |
405 | | // write printer, driver name in full, the ones in aOldData may be truncated |
406 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, u"PRINTER_NAME", RTL_TEXTENCODING_UTF8); |
407 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, rJobData.GetPrinterName(), RTL_TEXTENCODING_UTF8); |
408 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, u"DRIVER_NAME", RTL_TEXTENCODING_UTF8); |
409 | 0 | write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, rJobData.GetDriver(), RTL_TEXTENCODING_UTF8); |
410 | |
|
411 | 0 | nLen = sal::static_int_cast<sal_uInt16>(rOStream.Tell() - nPos); |
412 | 0 | rOStream.Seek( nPos ); |
413 | 0 | rOStream.WriteUInt16( nLen ); |
414 | 0 | rOStream.Seek( nPos + nLen ); |
415 | 0 | } |
416 | 69 | } |
417 | | |
418 | 69 | return rOStream; |
419 | 69 | } |
420 | | |
421 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |