]> git.saurik.com Git - wxWidgets.git/blob - samples/docview/doc.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[wxWidgets.git] / samples / docview / doc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: doc.cpp
3 // Purpose: Implements document functionality
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22 #include "wx/txtstrm.h"
23 #ifdef __WXMAC__
24 #include "wx/filename.h"
25 #endif
26
27 #if !wxUSE_DOC_VIEW_ARCHITECTURE
28 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
29 #endif
30
31 #include "doc.h"
32 #include "view.h"
33 IMPLEMENT_DYNAMIC_CLASS(DrawingDocument, wxDocument)
34
35 DrawingDocument::~DrawingDocument(void)
36 {
37 WX_CLEAR_LIST(wxList, doodleSegments);
38 }
39
40 #if wxUSE_STD_IOSTREAM
41 wxSTD ostream& DrawingDocument::SaveObject(wxSTD ostream& stream)
42 {
43 wxDocument::SaveObject(stream);
44
45 wxInt32 n = doodleSegments.GetCount();
46 stream << n << '\n';
47
48 wxList::compatibility_iterator node = doodleSegments.GetFirst();
49 while (node)
50 {
51 DoodleSegment *segment = (DoodleSegment *)node->GetData();
52 segment->SaveObject(stream);
53 stream << '\n';
54
55 node = node->GetNext();
56 }
57
58 return stream;
59 }
60 #else
61 wxOutputStream& DrawingDocument::SaveObject(wxOutputStream& stream)
62 {
63 wxDocument::SaveObject(stream);
64
65 wxTextOutputStream text_stream( stream );
66
67 wxInt32 n = doodleSegments.GetCount();
68 text_stream << n << '\n';
69
70 wxList::compatibility_iterator node = doodleSegments.GetFirst();
71 while (node)
72 {
73 DoodleSegment *segment = (DoodleSegment *)node->GetData();
74 segment->SaveObject(stream);
75 text_stream << '\n';
76
77 node = node->GetNext();
78 }
79
80 return stream;
81 }
82 #endif
83
84 #if wxUSE_STD_IOSTREAM
85 wxSTD istream& DrawingDocument::LoadObject(wxSTD istream& stream)
86 {
87 wxDocument::LoadObject(stream);
88
89 wxInt32 n = 0;
90 stream >> n;
91
92 for (int i = 0; i < n; i++)
93 {
94 DoodleSegment *segment = new DoodleSegment;
95 segment->LoadObject(stream);
96 doodleSegments.Append(segment);
97 }
98
99 return stream;
100 }
101 #else
102 wxInputStream& DrawingDocument::LoadObject(wxInputStream& stream)
103 {
104 wxDocument::LoadObject(stream);
105
106 wxTextInputStream text_stream( stream );
107
108 wxInt32 n = 0;
109 text_stream >> n;
110
111 for (int i = 0; i < n; i++)
112 {
113 DoodleSegment *segment = new DoodleSegment;
114 segment->LoadObject(stream);
115 doodleSegments.Append(segment);
116 }
117
118 return stream;
119 }
120 #endif
121
122 DoodleSegment::DoodleSegment(const DoodleSegment& seg):wxObject()
123 {
124 wxList::compatibility_iterator node = seg.lines.GetFirst();
125 while (node)
126 {
127 DoodleLine *line = (DoodleLine *)node->GetData();
128 DoodleLine *newLine = new DoodleLine;
129 newLine->x1 = line->x1;
130 newLine->y1 = line->y1;
131 newLine->x2 = line->x2;
132 newLine->y2 = line->y2;
133
134 lines.Append(newLine);
135
136 node = node->GetNext();
137 }
138 }
139
140 DoodleSegment::~DoodleSegment(void)
141 {
142 WX_CLEAR_LIST(wxList, lines);
143 }
144
145 #if wxUSE_STD_IOSTREAM
146 wxSTD ostream& DoodleSegment::SaveObject(wxSTD ostream& stream)
147 {
148 wxInt32 n = lines.GetCount();
149 stream << n << '\n';
150
151 wxList::compatibility_iterator node = lines.GetFirst();
152 while (node)
153 {
154 DoodleLine *line = (DoodleLine *)node->GetData();
155 stream << line->x1 << " " <<
156 line->y1 << " " <<
157 line->x2 << " " <<
158 line->y2 << "\n";
159 node = node->GetNext();
160 }
161
162 return stream;
163 }
164 #else
165 wxOutputStream &DoodleSegment::SaveObject(wxOutputStream& stream)
166 {
167 wxTextOutputStream text_stream( stream );
168
169 wxInt32 n = lines.GetCount();
170 text_stream << n << _T('\n');
171
172 wxList::compatibility_iterator node = lines.GetFirst();
173 while (node)
174 {
175 DoodleLine *line = (DoodleLine *)node->GetData();
176 text_stream << line->x1 << _T(" ") <<
177 line->y1 << _T(" ") <<
178 line->x2 << _T(" ") <<
179 line->y2 << _T("\n");
180 node = node->GetNext();
181 }
182
183 return stream;
184 }
185 #endif
186
187 #if wxUSE_STD_IOSTREAM
188 wxSTD istream& DoodleSegment::LoadObject(wxSTD istream& stream)
189 {
190 wxInt32 n = 0;
191 stream >> n;
192
193 for (int i = 0; i < n; i++)
194 {
195 DoodleLine *line = new DoodleLine;
196 stream >> line->x1 >>
197 line->y1 >>
198 line->x2 >>
199 line->y2;
200 lines.Append(line);
201 }
202
203 return stream;
204 }
205 #else
206 wxInputStream &DoodleSegment::LoadObject(wxInputStream& stream)
207 {
208 wxTextInputStream text_stream( stream );
209
210 wxInt32 n = 0;
211 text_stream >> n;
212
213 for (int i = 0; i < n; i++)
214 {
215 DoodleLine *line = new DoodleLine;
216 text_stream >> line->x1 >>
217 line->y1 >>
218 line->x2 >>
219 line->y2;
220 lines.Append(line);
221 }
222
223 return stream;
224 }
225 #endif
226
227 void DoodleSegment::Draw(wxDC *dc)
228 {
229 wxList::compatibility_iterator node = lines.GetFirst();
230 while (node)
231 {
232 DoodleLine *line = (DoodleLine *)node->GetData();
233 dc->DrawLine(line->x1, line->y1, line->x2, line->y2);
234 node = node->GetNext();
235 }
236 }
237
238 /*
239 * Implementation of drawing command
240 */
241
242 DrawingCommand::DrawingCommand(const wxString& name, int command, DrawingDocument *ddoc, DoodleSegment *seg):
243 wxCommand(true, name)
244 {
245 doc = ddoc;
246 segment = seg;
247 cmd = command;
248 }
249
250 DrawingCommand::~DrawingCommand(void)
251 {
252 if (segment)
253 delete segment;
254 }
255
256 bool DrawingCommand::Do(void)
257 {
258 switch (cmd)
259 {
260 case DOODLE_CUT:
261 {
262 // Cut the last segment
263 if (doc->GetDoodleSegments().GetCount() > 0)
264 {
265 wxList::compatibility_iterator node = doc->GetDoodleSegments().GetLast();
266 if (segment)
267 delete segment;
268
269 segment = (DoodleSegment *)node->GetData();
270 doc->GetDoodleSegments().Erase(node);
271
272 doc->Modify(true);
273 doc->UpdateAllViews();
274 }
275 break;
276 }
277 case DOODLE_ADD:
278 {
279 doc->GetDoodleSegments().Append(new DoodleSegment(*segment));
280 doc->Modify(true);
281 doc->UpdateAllViews();
282 break;
283 }
284 }
285 return true;
286 }
287
288 bool DrawingCommand::Undo(void)
289 {
290 switch (cmd)
291 {
292 case DOODLE_CUT:
293 {
294 // Paste the segment
295 if (segment)
296 {
297 doc->GetDoodleSegments().Append(segment);
298 doc->Modify(true);
299 doc->UpdateAllViews();
300 segment = (DoodleSegment *) NULL;
301 }
302 doc->Modify(true);
303 doc->UpdateAllViews();
304 break;
305 }
306 case DOODLE_ADD:
307 {
308 // Cut the last segment
309 if (doc->GetDoodleSegments().GetCount() > 0)
310 {
311 wxList::compatibility_iterator node = doc->GetDoodleSegments().GetLast();
312 DoodleSegment *seg = (DoodleSegment *)node->GetData();
313 delete seg;
314 doc->GetDoodleSegments().Erase(node);
315
316 doc->Modify(true);
317 doc->UpdateAllViews();
318 }
319 }
320 }
321 return true;
322 }
323
324 IMPLEMENT_DYNAMIC_CLASS(TextEditDocument, wxDocument)
325
326 // Since text windows have their own method for saving to/loading from files,
327 // we override OnSave/OpenDocument instead of Save/LoadObject
328 bool TextEditDocument::OnSaveDocument(const wxString& filename)
329 {
330 TextEditView *view = (TextEditView *)GetFirstView();
331
332 if (!view->textsw->SaveFile(filename))
333 return false;
334 Modify(false);
335 #ifdef __WXMAC__
336 wxFileName fn(filename) ;
337 fn.MacSetDefaultTypeAndCreator() ;
338 #endif
339 return true;
340 }
341
342 bool TextEditDocument::OnOpenDocument(const wxString& filename)
343 {
344 TextEditView *view = (TextEditView *)GetFirstView();
345 if (!view->textsw->LoadFile(filename))
346 return false;
347
348 SetFilename(filename, true);
349 Modify(false);
350 UpdateAllViews();
351 return true;
352 }
353
354 bool TextEditDocument::IsModified(void) const
355 {
356 TextEditView *view = (TextEditView *)GetFirstView();
357 if (view)
358 {
359 return (wxDocument::IsModified() || view->textsw->IsModified());
360 }
361 else
362 return wxDocument::IsModified();
363 }
364
365 void TextEditDocument::Modify(bool mod)
366 {
367 TextEditView *view = (TextEditView *)GetFirstView();
368
369 wxDocument::Modify(mod);
370
371 if (!mod && view && view->textsw)
372 view->textsw->DiscardEdits();
373 }