xref: /haiku/src/libs/icon/message/MessageImporter.cpp (revision c90684742e7361651849be4116d0e5de3a817194)
1 /*
2  * Copyright 2006-2007, Haiku. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  */
8 #include "MessageImporter.h"
9 
10 #include <new>
11 #include <stdio.h>
12 
13 #include <Archivable.h>
14 #include <ByteOrder.h>
15 #include <DataIO.h>
16 #include <Message.h>
17 
18 #include "Defines.h"
19 #include "Icon.h"
20 #include "PathContainer.h"
21 #include "Shape.h"
22 #include "Style.h"
23 #include "StyleContainer.h"
24 #include "VectorPath.h"
25 
26 using std::nothrow;
27 
28 // constructor
29 MessageImporter::MessageImporter()
30 #ifdef ICON_O_MATIC
31 	: Importer()
32 #endif
33 {
34 }
35 
36 // destructor
37 MessageImporter::~MessageImporter()
38 {
39 }
40 
41 // Import
42 status_t
43 MessageImporter::Import(Icon* icon, BPositionIO* stream)
44 {
45 #ifdef ICON_O_MATIC
46 	status_t ret = Init(icon);
47 	if (ret < B_OK) {
48 		printf("MessageImporter::Import() - "
49 			   "Init() error: %s\n", strerror(ret));
50 		return ret;
51 	}
52 #else
53 	status_t ret;
54 #endif
55 
56 	uint32 magic = 0;
57 	ssize_t size = sizeof(magic);
58 	off_t position = stream->Position();
59 	ssize_t read = stream->Read(&magic, size);
60 	if (read != size) {
61 		if (read < 0)
62 			ret = (status_t)read;
63 		else
64 			ret = B_IO_ERROR;
65 		return ret;
66 	}
67 
68 	if (B_BENDIAN_TO_HOST_INT32(magic) != kNativeIconMagicNumber) {
69 		// this might be an old native icon file, where
70 		// we didn't prepend the magic number yet, seek back
71 		if (stream->Seek(position, SEEK_SET) != position) {
72 			printf("MessageImporter::Import() - "
73 				   "failed to seek back to beginning of stream\n");
74 			return B_IO_ERROR;
75 		}
76 	}
77 
78 	BMessage archive;
79 	ret = archive.Unflatten(stream);
80 	if (ret < B_OK) {
81 		printf("MessageImporter::Import() - "
82 			   "error unflattening icon archive: %s\n", strerror(ret));
83 		return ret;
84 	}
85 
86 	// paths
87 	PathContainer* paths = icon->Paths();
88 	ret = _ImportPaths(&archive, paths);
89 	if (ret < B_OK) {
90 		printf("MessageImporter::Import() - "
91 			   "error importing paths: %s\n", strerror(ret));
92 		return ret;
93 	}
94 
95 	// styles
96 	StyleContainer* styles = icon->Styles();
97 	ret = _ImportStyles(&archive, styles);
98 	if (ret < B_OK) {
99 		printf("MessageImporter::Import() - "
100 			   "error importing styles: %s\n", strerror(ret));
101 		return ret;
102 	}
103 
104 	// shapes
105 	ret = _ImportShapes(&archive, paths, styles, icon->Shapes());
106 	if (ret < B_OK) {
107 		printf("MessageImporter::Import() - "
108 			   "error importing shapes: %s\n", strerror(ret));
109 		return ret;
110 	}
111 
112 	return B_OK;
113 }
114 
115 // #pragma mark -
116 
117 // _ImportPaths
118 status_t
119 MessageImporter::_ImportPaths(const BMessage* archive,
120 							  PathContainer* paths) const
121 {
122 	BMessage allPaths;
123 	status_t ret = archive->FindMessage("paths", &allPaths);
124 	if (ret < B_OK)
125 		return ret;
126 
127 	BMessage pathArchive;
128 	for (int32 i = 0;
129 		 allPaths.FindMessage("path", i, &pathArchive) == B_OK; i++) {
130 		VectorPath* path = new (nothrow) VectorPath(&pathArchive);
131 		if (!path || !paths->AddPath(path)) {
132 			delete path;
133 			ret = B_NO_MEMORY;
134 		}
135 		if (ret < B_OK)
136 			break;
137 	}
138 
139 	return ret;
140 }
141 
142 // _ImportStyles
143 status_t
144 MessageImporter::_ImportStyles(const BMessage* archive,
145 							   StyleContainer* styles) const
146 {
147 	BMessage allStyles;
148 	status_t ret = archive->FindMessage("styles", &allStyles);
149 	if (ret < B_OK)
150 		return ret;
151 
152 	BMessage styleArchive;
153 	for (int32 i = 0;
154 		 allStyles.FindMessage("style", i, &styleArchive) == B_OK; i++) {
155 		Style* style = new (nothrow) Style(&styleArchive);
156 		if (!style || !styles->AddStyle(style)) {
157 			delete style;
158 			ret = B_NO_MEMORY;
159 		}
160 		if (ret < B_OK)
161 			break;
162 	}
163 
164 	return ret;
165 }
166 
167 // _ImportShapes
168 status_t
169 MessageImporter::_ImportShapes(const BMessage* archive,
170 							   PathContainer* paths,
171 							   StyleContainer* styles,
172 							   ShapeContainer* shapes) const
173 {
174 	BMessage allShapes;
175 	status_t ret = archive->FindMessage("shapes", &allShapes);
176 	if (ret < B_OK)
177 		return ret;
178 
179 	BMessage shapeArchive;
180 	for (int32 i = 0;
181 		 allShapes.FindMessage("shape", i, &shapeArchive) == B_OK; i++) {
182 		// find the right style
183 		int32 styleIndex;
184 		if (shapeArchive.FindInt32("style ref", &styleIndex) < B_OK) {
185 			printf("MessageImporter::_ImportShapes() - "
186 				   "Shape %ld doesn't reference a Style!", i);
187 			continue;
188 		}
189 #ifdef ICON_O_MATIC
190 		Style* style = styles->StyleAt(StyleIndexFor(styleIndex));
191 #else
192 		Style* style = styles->StyleAt(styleIndex);
193 #endif
194 		if (!style) {
195 			printf("MessageImporter::_ImportShapes() - "
196 				   "Shape %ld wants Style %ld, which does not exist\n",
197 				i, styleIndex);
198 			continue;
199 		}
200 
201 		// create shape
202 		Shape* shape = new (nothrow) Shape(style);
203 		if (!shape || shape->InitCheck() < B_OK || !shapes->AddShape(shape)) {
204 			delete shape;
205 			ret = B_NO_MEMORY;
206 		}
207 		if (ret < B_OK)
208 			break;
209 
210 		// find the referenced paths
211 		int32 pathIndex;
212 		for (int32 j = 0;
213 			 shapeArchive.FindInt32("path ref", j, &pathIndex) == B_OK;
214 			 j++) {
215 #ifdef ICON_O_MATIC
216 			VectorPath* path = paths->PathAt(PathIndexFor(pathIndex));
217 #else
218 			VectorPath* path = paths->PathAt(pathIndex);
219 #endif
220 			if (!path) {
221 				printf("MessageImporter::_ImportShapes() - "
222 					   "Shape %ld referenced path %ld, "
223 					   "which does not exist\n", i, pathIndex);
224 				continue;
225 			}
226 			shape->Paths()->AddPath(path);
227 		}
228 
229 		// Shape properties
230 		if (ret == B_OK)
231 			shape->Unarchive(&shapeArchive);
232 	}
233 
234 	return ret;
235 }
236 
237