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