xref: /haiku/src/add-ons/input_server/methods/pen/DumpMessage.cpp (revision a94e61350c94119de9924f3de6c704a10a96c0d6)
1 #include <string.h>
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <BeBuild.h>
5 #include <Font.h>
6 #include <Message.h>
7 #include <String.h>
8 #include "DumpMessage.h"
9 
10 //#define WHAT_ALWAYS_HEX 1
11 
12 const char *msg_header_comment = "// new BMessage\n"; // avoids mime to think it's a .bmp ("BM")
13 
14 // '_' also widely used in what codes
myisprint(int c)15 inline int myisprint(int c)
16 {
17 	if (isalnum(c))
18 		return 1;
19 	return (c == '_')?1:0;
20 }
21 
HexDumpToStream(const void * data,size_t len,BDataIO & stream,const char * prefix=NULL)22 status_t HexDumpToStream(const void *data, size_t len, BDataIO &stream, const char *prefix = NULL)
23 {
24 	const unsigned char *p = (unsigned char *)data;
25 	char buffer[100];
26 	size_t i, j;
27 	for (i=0; i<len; i+=16) {
28 		if (prefix) stream.Write(prefix, strlen(prefix));
29 		sprintf(buffer, "0x%06lx: ", i);
30 		stream.Write(buffer, strlen(buffer));
31 		for (j=0; j<16; j++) {
32 			if (i+j < len)
33 				sprintf(buffer, "%02x", p[i+j]);
34 			else
35 				sprintf(buffer, "  ");
36 			if (j % 4 == 3)
37 				sprintf(buffer+strlen(buffer), " ");
38 			stream.Write(buffer, strlen(buffer));
39 		}
40 		sprintf(buffer, " '");
41 		stream.Write(buffer, strlen(buffer));
42 		for (j=0; j<16; j++) {
43 			if (i+j >= len)
44 				sprintf(buffer, " ");
45 			//else if (p[i+j] < 255 && p[i+j] >= 0x20)
46 			else if (isalpha(p[i+j]))
47 				sprintf(buffer, "%c", p[i+j]);
48 			else
49 				sprintf(buffer, ".");
50 			stream.Write(buffer, 1);
51 		}
52 		sprintf(buffer, "'\n");
53 		stream.Write(buffer, strlen(buffer));
54 	}
55 	return B_OK;
56 }
57 
58 /* look up human readable names from an other BMessage */
LookUpFieldName(const char ** name,const char * field_name,BMessage * names)59 bool LookUpFieldName(const char **name, const char *field_name, BMessage *names)
60 {
61 	if (names == NULL)
62 		return false;
63 	if (names->FindString(field_name, name) == B_OK)
64 		return true;
65 	return false;
66 }
67 
DumpMessageToStream(BMessage * message,BDataIO & stream,int tabCount,BMessage * names)68 status_t DumpMessageToStream(BMessage *message, BDataIO &stream, int tabCount, BMessage *names)
69 {
70 	int32 index;
71 	void *cookie = NULL;
72 	const char *field_name;
73 	type_code field_code;
74 	int32 field_count;
75 	char buffer[80];
76 	char tabs[20];
77 	const char *easy_name;
78 
79 	if (message == NULL)
80 		return EINVAL;
81 
82 	if (tabCount < 1)
83 		stream.Write(msg_header_comment, strlen(msg_header_comment));
84 
85 	memset(tabs, '\t', (++tabCount) + 1);
86 	tabs[tabCount+1] = '\0';
87 	//tabCount;
88 
89 #ifndef WHAT_ALWAYS_HEX
90 	if (	myisprint(message->what & 0x0ff) &&
91 		myisprint((message->what >> 8) & 0x0ff) &&
92 		myisprint((message->what >> 16) & 0x0ff) &&
93 		myisprint((message->what >> 24) & 0x0ff))
94 		sprintf(buffer, "BMessage('%c%c%c%c') {\n",
95 			(char)(message->what >> 24) & 0x0ff,
96 			(char)(message->what >> 16) & 0x0ff,
97 			(char)(message->what >> 8) & 0x0ff,
98 			(char)message->what & 0x0ff);
99 	else
100 #endif
101 		sprintf(buffer, "BMessage(0x%08lx) {\n", message->what);
102 //	stream.Write(tabs+2, tabCount-2);
103 	stream.Write(buffer, strlen(buffer));
104 
105 #ifdef B_BEOS_VERSION_DANO
106 	while (message->GetNextName(&cookie,
107 				&field_name,
108 				&field_code,
109 				&field_count) == B_OK) {
110 #else
111 #warning mem leak likely! (name=char *)
112 	for (int which=0; message->GetInfo(B_ANY_TYPE, which,
113 			(char **)&field_name, &field_code, &field_count) == B_OK; which++) {
114 #endif
115 		if (LookUpFieldName(&easy_name, field_name, names)) {
116 			stream.Write(tabs+1, tabCount);
117 			stream.Write("// ", 3);
118 			stream.Write(easy_name, strlen(easy_name));
119 			stream.Write("\n", 1);
120 		}
121 
122 		for (index=0; index < field_count; index++) {
123 			stream.Write(tabs+1, tabCount);
124 			stream.Write(field_name, strlen(field_name));
125 			if (field_count > 1) {
126 				sprintf(buffer, "[%ld]", index);
127 				stream.Write(buffer, strlen(buffer));
128 			}
129 			stream.Write(" = ", 3);
130 
131 			switch (field_code) {
132 			case 'MSGG':
133 				{
134 					BMessage m;
135 					if (message->FindMessage(field_name, index, &m) >= B_OK)
136 						DumpMessageToStream(&m, stream, tabCount, names);
137 				}
138 				break;
139 #ifdef B_BEOS_VERSION_DANO
140 			case 'FONt':
141 				{
142 					BFont f;
143 					if (message->FindFlat(field_name, index, &f) >= B_OK)
144 						stream << f;
145 					stream.Write("\n", 1);
146 				}
147 				break;
148 			case B_RGB_COLOR_TYPE:
149 				{
150 					rgb_color c;
151 					if (message->FindRGBColor(field_name, index, &c) >= B_OK) {
152 						sprintf(buffer, "rgb_color(%d,%d,%d,%d)",
153 							c.red, c.green, c.blue, c.alpha);
154 						stream.Write(buffer, strlen(buffer));
155 					}
156 					stream.Write("\n", 1);
157 				}
158 				break;
159 #else
160 #warning IMPLEMENT ME
161 #endif
162 			case B_BOOL_TYPE:
163 				{
164 					bool value;
165 					if (message->FindBool(field_name, index, &value) >= B_OK) {
166 						sprintf(buffer, "bool(%s)", value?"true":"false");
167 						stream.Write(buffer, strlen(buffer));
168 					}
169 					stream.Write("\n", 1);
170 				}
171 				break;
172 			case B_INT32_TYPE:
173 				{
174 					int32 value;
175 					if (message->FindInt32(field_name, index, &value) >= B_OK) {
176 #if 1
177 						if (value == 0)
178 							sprintf(buffer, "int32(0 or (nil))");
179 						else
180 #endif
181 //							sprintf(buffer, "int32(%d)", value);
182 							sprintf(buffer, "int32(%ld or 0x%lx)", value, value);
183 						stream.Write(buffer, strlen(buffer));
184 					}
185 					stream.Write("\n", 1);
186 				}
187 				break;
188 			case B_FLOAT_TYPE:
189 				{
190 					float value;
191 					if (message->FindFloat(field_name, index, &value) >= B_OK) {
192 							sprintf(buffer, "float(%f)", value);
193 						stream.Write(buffer, strlen(buffer));
194 					}
195 					stream.Write("\n", 1);
196 				}
197 				break;
198 			case B_STRING_TYPE:
199 				{
200 					const char *value;
201 					if (message->FindString(field_name, index, &value) >= B_OK) {
202 						BString str(value);
203 						str.CharacterEscape("\\\"\n", '\\');
204 						//sprintf(buffer, "string(\"%s\", %ld bytes)", str.String(), strlen(value));
205 						// DO NOT use buffer!
206 						str.Prepend("string(\"");
207 						str << "\", " << strlen(value) << " bytes)";
208 						stream.Write(str.String(), strlen(str.String()));
209 					}
210 					stream.Write("\n", 1);
211 				}
212 				break;
213 			case B_POINT_TYPE:
214 				{
215 					BPoint value;
216 					if (message->FindPoint(field_name, index, &value) >= B_OK) {
217 						sprintf(buffer, "BPoint(%1.1f, %1.1f)", value.x, value.y);
218 						stream.Write(buffer, strlen(buffer));
219 					}
220 					stream.Write("\n", 1);
221 				}
222 				break;
223 			default:
224 				{
225 					const void *data;
226 					ssize_t numBytes = 0;
227 					if (message->FindData(field_name, field_code, index, &data, &numBytes) != B_OK) {
228 						//stream.Write("\n", 1);
229 						break;
230 					}
231 
232 					if (	isalnum(field_code & 0x0ff) &&
233 						isalnum((field_code >> 8) & 0x0ff) &&
234 						isalnum((field_code >> 16) & 0x0ff) &&
235 						isalnum((field_code >> 24) & 0x0ff))
236 						sprintf(buffer, "'%c%c%c%c' %ld bytes:\n",
237 							(char)(field_code >> 24) & 0x0ff,
238 							(char)(field_code >> 16) & 0x0ff,
239 							(char)(field_code >> 8) & 0x0ff,
240 							(char)field_code & 0x0ff,
241 							numBytes);
242 					else
243 						sprintf(buffer, "0x%08lx %ld bytes:\n", field_code, numBytes);
244 					stream.Write(buffer, strlen(buffer));
245 					stream.Write("\n", 1);
246 					HexDumpToStream(data, numBytes, stream, tabs);
247 				}
248 				break;
249 			}
250 		}
251 	}
252 	stream.Write(tabs+2, tabCount-1);
253 	stream.Write("}\n", 2);
254 	return B_OK;
255 }
256 
257