]> git.saurik.com Git - wxWidgets.git/blame - src/tiff/libtiff/tif_stream.cxx
fix for r56618: toolbar event handlers can toggle or disable tools again (patch ...
[wxWidgets.git] / src / tiff / libtiff / tif_stream.cxx
CommitLineData
8414a40c
VZ
1/* $Id: tif_stream.cxx,v 1.5 2005/07/26 08:11:13 dron Exp $ */
2
3/*
4 * Copyright (c) 1988-1996 Sam Leffler
5 * Copyright (c) 1991-1996 Silicon Graphics, Inc.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and
8 * its documentation for any purpose is hereby granted without fee, provided
9 * that (i) the above copyright notices and this permission notice appear in
10 * all copies of the software and related documentation, and (ii) the names of
11 * Sam Leffler and Silicon Graphics may not be used in any advertising or
12 * publicity relating to the software without the specific, prior written
13 * permission of Sam Leffler and Silicon Graphics.
14 *
15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 */
26
27/*
28 * TIFF Library UNIX-specific Routines.
29 */
30#include "tiffiop.h"
31#include <iostream>
32
33using namespace std;
34
35class tiffis_data
36{
37 public:
38
39 istream *myIS;
40 long myStreamStartPos;
41};
42
43class tiffos_data
44{
45 public:
46
47 ostream *myOS;
48 long myStreamStartPos;
49};
50
51static tsize_t
52_tiffosReadProc(thandle_t, tdata_t, tsize_t)
53{
54 return 0;
55}
56
57static tsize_t
58_tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size)
59{
60 tiffis_data *data = (tiffis_data *)fd;
61
62 data->myIS->read((char *)buf, (int)size);
63
64 return data->myIS->gcount();
65}
66
67static tsize_t
68_tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
69{
70 tiffos_data *data = (tiffos_data *)fd;
71 ostream *os = data->myOS;
72 int pos = os->tellp();
73
74 os->write((const char *)buf, size);
75
76 return ((int)os->tellp()) - pos;
77}
78
79static tsize_t
80_tiffisWriteProc(thandle_t, tdata_t, tsize_t)
81{
82 return 0;
83}
84
85static toff_t
86_tiffosSeekProc(thandle_t fd, toff_t off, int whence)
87{
88 tiffos_data *data = (tiffos_data *)fd;
89 ostream *os = data->myOS;
90
91 // if the stream has already failed, don't do anything
92 if( os->fail() )
93 return os->tellp();
94
95 switch(whence) {
96 case SEEK_SET:
97 os->seekp(data->myStreamStartPos + off, ios::beg);
98 break;
99 case SEEK_CUR:
100 os->seekp(off, ios::cur);
101 break;
102 case SEEK_END:
103 os->seekp(off, ios::end);
104 break;
105 }
106
107 // Attempt to workaround problems with seeking past the end of the
108 // stream. ofstream doesn't have a problem with this but
109 // ostrstream/ostringstream does. In that situation, add intermediate
110 // '\0' characters.
111 if( os->fail() ) {
112 ios::iostate old_state;
113 toff_t origin;
114
115 old_state = os->rdstate();
116 // reset the fail bit or else tellp() won't work below
117 os->clear(os->rdstate() & ~ios::failbit);
118 switch( whence ) {
119 case SEEK_SET:
120 origin = data->myStreamStartPos;
121 break;
122 case SEEK_CUR:
123 origin = os->tellp();
124 break;
125 case SEEK_END:
126 os->seekp(0, ios::end);
127 origin = os->tellp();
128 break;
129 }
130 // restore original stream state
131 os->clear(old_state);
132
133 // only do something if desired seek position is valid
134 if( origin + off > data->myStreamStartPos ) {
135 toff_t num_fill;
136
137 // clear the fail bit
138 os->clear(os->rdstate() & ~ios::failbit);
139
140 // extend the stream to the expected size
141 os->seekp(0, ios::end);
142 num_fill = origin + off - (toff_t)os->tellp();
143 for( toff_t i = 0; i < num_fill; i++ )
144 os->put('\0');
145
146 // retry the seek
147 os->seekp(origin + off, ios::beg);
148 }
149 }
150
151 return os->tellp();
152}
153
154static toff_t
155_tiffisSeekProc(thandle_t fd, toff_t off, int whence)
156{
157 tiffis_data *data = (tiffis_data *)fd;
158
159 switch(whence) {
160 case SEEK_SET:
161 data->myIS->seekg(data->myStreamStartPos + off, ios::beg);
162 break;
163 case SEEK_CUR:
164 data->myIS->seekg(off, ios::cur);
165 break;
166 case SEEK_END:
167 data->myIS->seekg(off, ios::end);
168 break;
169 }
170
171 return ((long)data->myIS->tellg()) - data->myStreamStartPos;
172}
173
174static toff_t
175_tiffosSizeProc(thandle_t fd)
176{
177 tiffos_data *data = (tiffos_data *)fd;
178 ostream *os = data->myOS;
179 toff_t pos = os->tellp();
180 toff_t len;
181
182 os->seekp(0, ios::end);
183 len = os->tellp();
184 os->seekp(pos);
185
186 return len;
187}
188
189static toff_t
190_tiffisSizeProc(thandle_t fd)
191{
192 tiffis_data *data = (tiffis_data *)fd;
193 int pos = data->myIS->tellg();
194 int len;
195
196 data->myIS->seekg(0, ios::end);
197 len = data->myIS->tellg();
198 data->myIS->seekg(pos);
199
200 return len;
201}
202
203static int
204_tiffosCloseProc(thandle_t fd)
205{
206 // Our stream was not allocated by us, so it shouldn't be closed by us.
207 delete (tiffos_data *)fd;
208 return 0;
209}
210
211static int
212_tiffisCloseProc(thandle_t fd)
213{
214 // Our stream was not allocated by us, so it shouldn't be closed by us.
215 delete (tiffis_data *)fd;
216 return 0;
217}
218
219static int
220_tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
221{
222 return (0);
223}
224
225static void
226_tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
227{
228}
229
230/*
231 * Open a TIFF file descriptor for read/writing.
232 */
233static TIFF*
234_tiffStreamOpen(const char* name, const char* mode, void *fd)
235{
236 TIFF* tif;
237
238 if( strchr(mode, 'w') ) {
239 tiffos_data *data = new tiffos_data;
240 data->myOS = (ostream *)fd;
241 data->myStreamStartPos = data->myOS->tellp();
242
243 // Open for writing.
244 tif = TIFFClientOpen(name, mode,
245 (thandle_t) data,
246 _tiffosReadProc, _tiffosWriteProc,
247 _tiffosSeekProc, _tiffosCloseProc,
248 _tiffosSizeProc,
249 _tiffDummyMapProc, _tiffDummyUnmapProc);
250 } else {
251 tiffis_data *data = new tiffis_data;
252 data->myIS = (istream *)fd;
253 data->myStreamStartPos = data->myIS->tellg();
254 // Open for reading.
255 tif = TIFFClientOpen(name, mode,
256 (thandle_t) data,
257 _tiffisReadProc, _tiffisWriteProc,
258 _tiffisSeekProc, _tiffisCloseProc,
259 _tiffisSizeProc,
260 _tiffDummyMapProc, _tiffDummyUnmapProc);
261 }
262
263 return (tif);
264}
265
266TIFF*
267TIFFStreamOpen(const char* name, ostream *os)
268{
269 // If os is either a ostrstream or ostringstream, and has no data
270 // written to it yet, then tellp() will return -1 which will break us.
271 // We workaround this by writing out a dummy character and
272 // then seek back to the beginning.
273 if( !os->fail() && (int)os->tellp() < 0 ) {
274 *os << '\0';
275 os->seekp(0);
276 }
277
278 // NB: We don't support mapped files with streams so add 'm'
279 return _tiffStreamOpen(name, "wm", os);
280}
281
282TIFF*
283TIFFStreamOpen(const char* name, istream *is)
284{
285 // NB: We don't support mapped files with streams so add 'm'
286 return _tiffStreamOpen(name, "rm", is);
287}
288
289/* vim: set ts=8 sts=8 sw=8 noet: */