1//-------------------------------------------------------------------------
2// Handy InputFilter that dumps all Messages to a file.
3//-------------------------------------------------------------------------
4#include <stdlib.h>
5#include <string.h>
6#include <ctype.h>
7
8#include <Debug.h>
9#include <List.h>
10#include <File.h>
11#include <Message.h>
12#include <String.h>
13#include <OS.h>
14
15#include <add-ons/input_server/InputServerFilter.h>
16
17extern "C" _EXPORT BInputServerFilter* instantiate_input_filter();
18
19class MsgSpy : public BInputServerFilter
20{
21public:
22	         MsgSpy();
23	virtual ~MsgSpy();
24
25    virtual status_t      InitCheck(void);
26	virtual	filter_result Filter(BMessage *message, BList *outList);
27private:
28	const char* MapWhatToString(uint32 w);
29	void        OutputMsgField(const char*  fieldName,
30	                           const uint32 rawType,
31                               int          rawCount,
32                               const void*  rawData);
33
34    status_t m_status;
35    BFile*   m_outfile;
36};
37
38//-------------------------------------------------------------------------
39// Create a new MsgSpy instance and return it to the caller.
40//-------------------------------------------------------------------------
41BInputServerFilter* instantiate_input_filter()
42{
43	return (new MsgSpy() );
44}
45
46
47//-------------------------------------------------------------------------
48//-------------------------------------------------------------------------
49MsgSpy::MsgSpy()
50{
51    // Create the output file and return its status.
52    m_outfile = new BFile("/boot/home/MsgSpy.output", B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
53    //m_status = m_outfile->InitCheck();
54    m_status = B_OK;
55}
56
57//-------------------------------------------------------------------------
58//-------------------------------------------------------------------------
59MsgSpy::~MsgSpy()
60{
61    if (NULL != m_outfile)
62    {
63        // Close and destroy the output file.
64        delete m_outfile;
65    }
66}
67
68//-------------------------------------------------------------------------
69//-------------------------------------------------------------------------
70status_t MsgSpy::InitCheck(void)
71{
72	return m_status;
73}
74
75//-------------------------------------------------------------------------
76//-------------------------------------------------------------------------
77filter_result MsgSpy::Filter(BMessage *message, BList *outList)
78{
79    char*       field_name;
80    uint32      field_type;
81    int32       field_count;
82    const void* field_data;
83    ssize_t     field_data_bytes;
84	char        msg_buffer  [1024];
85
86	// Print out the message constant (what).
87	sprintf(msg_buffer, "%s\n", MapWhatToString(message->what) );
88    m_outfile->Write(msg_buffer, strlen(msg_buffer) );
89
90    // Display each field in the message.
91	sprintf(msg_buffer, "{\n");
92    m_outfile->Write(msg_buffer, strlen(msg_buffer) );
93	for (int32 i = 0;  B_OK == message->GetInfo(B_ANY_TYPE,
94	                                            i,
95	                                            &field_name,
96	                                            &field_type,
97	                                            &field_count);  i++)
98	{
99		message->FindData(field_name, field_type, &field_data, &field_data_bytes);
100		OutputMsgField(field_name, field_type, field_count, field_data);
101	}
102	sprintf(msg_buffer, "}\n");
103    m_outfile->Write(msg_buffer, strlen(msg_buffer) );
104
105	return (B_DISPATCH_MESSAGE);
106}
107
108//-------------------------------------------------------------------------
109//-------------------------------------------------------------------------
110const char* MsgSpy::MapWhatToString(uint32 w)
111{
112    const char* s;
113	switch (w)
114	{
115		// Pointing device event messages.
116		case B_MOUSE_DOWN:					s = "B_MOUSE_DOWN";					break;
117		case B_MOUSE_UP:					s = "B_MOUSE_UP";					break;
118		case B_MOUSE_MOVED:					s = "B_MOUSE_MOVED";				break;
119
120		// Keyboard device event messages.
121		case B_KEY_DOWN:					s = "B_KEY_DOWN";					break;
122		case B_UNMAPPED_KEY_DOWN:			s = "B_UNMAPPED_KEY_DOWN";			break;
123		case B_KEY_UP:						s = "B_KEY_UP";						break;
124		case B_UNMAPPED_KEY_UP:				s = "B_UNMAPPED_KEY_UP";			break;
125		case B_MODIFIERS_CHANGED:			s = "B_MODIFIERS_CHANGED";			break;
126
127		default:							s = "UNKNOWN_MESSAGE";				break;
128	}
129	return s;
130}
131
132//-------------------------------------------------------------------------
133//-------------------------------------------------------------------------
134void MsgSpy::OutputMsgField(const char*  fieldName,
135                            const uint32 rawType,
136                            int          rawCount,
137                            const void*  rawData)
138{
139	char        msg_buffer   [1024];
140	char        value_buffer [256];
141	BString     field_data;
142    const char* field_type;
143    const int   field_count  = rawCount;
144    const char* separator;
145
146	switch (rawType)
147	{
148		case B_CHAR_TYPE:
149		{
150			field_type = "B_CHAR_TYPE";
151			field_data << "{ ";
152			for (const char* data_ptr = (const char*)rawData;
153				rawCount > 0;
154				rawCount--, data_ptr++)
155			{
156				separator = (1 < rawCount) ? ", " : " }";
157				field_data << *data_ptr << separator;
158			}
159			break;
160		}
161
162		case B_INT8_TYPE:
163		{
164			field_type = "B_INT8_TYPE";
165			field_data << "{ ";
166			for (const int8* data_ptr = (const int8*)rawData;
167				rawCount > 0;
168				rawCount--, data_ptr++)
169			{
170				separator = (1 < rawCount) ? ", " : " }";
171				field_data << *data_ptr << separator;
172			}
173			break;
174		}
175
176		case B_INT16_TYPE:
177		{
178			field_type = "B_INT16_TYPE";
179			field_data << "{ ";
180			for (const int16* data_ptr = (const int16*)rawData;
181				rawCount > 0;
182				rawCount--, data_ptr++)
183			{
184				separator = (1 < rawCount) ? ", " : " }";
185				field_data << *data_ptr << separator;
186			}
187			break;
188		}
189
190		case B_INT32_TYPE:
191		{
192			field_type = "B_INT32_TYPE";
193			field_data << "{ ";
194			for (const int32* data_ptr = (const int32*)rawData;
195				rawCount > 0;
196				rawCount--, data_ptr++)
197			{
198				separator = (1 < rawCount) ? ", " : " }";
199				field_data << *data_ptr << separator;
200			}
201			break;
202		}
203
204		case B_INT64_TYPE:
205		{
206			field_type = "B_INT64_TYPE";
207			field_data << "{ ";
208			for (const int64* data_ptr = (const int64*)rawData;
209				rawCount > 0;
210				rawCount--, data_ptr++)
211			{
212				separator = (1 < rawCount) ? ", " : " }";
213				field_data << *data_ptr << separator;
214			}
215			break;
216		}
217
218		case B_UINT8_TYPE:
219		{
220			field_type = "B_UINT8_TYPE";
221			field_data << "{ ";
222			for (const uint8* data_ptr = (const uint8*)rawData;
223				rawCount > 0;
224				rawCount--, data_ptr++)
225			{
226				separator = (1 < rawCount) ? ", " : " }";
227				field_data << (uint32)(*data_ptr) << separator;
228			}
229			break;
230		}
231
232		case B_UINT16_TYPE:
233		{
234			field_type = "B_UINT16_TYPE";
235			field_data << "{ ";
236			for (const uint16* data_ptr = (const uint16*)rawData;
237				rawCount > 0;
238				rawCount--, data_ptr++)
239			{
240				separator = (1 < rawCount) ? ", " : " }";
241				field_data << (uint32)(*data_ptr) << separator;
242			}
243			break;
244		}
245
246		case B_UINT32_TYPE:
247		{
248			field_type = "B_UINT32_TYPE";
249			field_data << "{ ";
250			for (const uint32* data_ptr = (const uint32*)rawData;
251				rawCount > 0;
252				rawCount--, data_ptr++)
253			{
254				separator = (1 < rawCount) ? ", " : " }";
255				field_data << *data_ptr << separator;
256			}
257			break;
258		}
259
260		case B_UINT64_TYPE:
261		{
262			field_type = "B_UINT64_TYPE";
263			field_data << "{ ";
264			for (const uint64* data_ptr = (const uint64*)rawData;
265				rawCount > 0;
266				rawCount--, data_ptr++)
267			{
268				separator = (1 < rawCount) ? ", " : " }";
269				field_data << *data_ptr << separator;
270			}
271			break;
272		}
273
274		case B_FLOAT_TYPE:
275		{
276			field_type = "B_FLOAT_TYPE";
277			field_data << "{ ";
278			for (const float* data_ptr = (const float*)rawData;
279				rawCount > 0;
280				rawCount--, data_ptr++)
281			{
282				separator = (1 < rawCount) ? ", " : " }";
283				field_data << *data_ptr << separator;
284			}
285			break;
286		}
287
288		case B_DOUBLE_TYPE:
289		{
290			field_type = "B_DOUBLE_TYPE";
291			field_data << "{ ";
292			for (const double* data_ptr = (const double*)rawData;
293				rawCount > 0;
294				rawCount--, data_ptr++)
295			{
296				separator = (1 < rawCount) ? ", " : " }";
297				sprintf(value_buffer, "%f", *data_ptr);
298				field_data << value_buffer << separator;
299			}
300			break;
301		}
302
303		case B_BOOL_TYPE:
304		{
305			field_type = "B_BOOL_TYPE";
306			field_data << "{ ";
307			for (const bool* data_ptr = (const bool*)rawData;
308				rawCount > 0;
309				rawCount--, data_ptr++)
310			{
311				separator = (1 < rawCount) ? ", " : " }";
312				sprintf(value_buffer, "%s", (true == *data_ptr) ? "true" : "false");
313				field_data << value_buffer << separator;
314			}
315			break;
316		}
317
318		case B_OFF_T_TYPE:
319		{
320			field_type = "B_OFF_T_TYPE";
321			field_data << "{ ";
322			for (const off_t* data_ptr = (const off_t*)rawData;
323				rawCount > 0;
324				rawCount--, data_ptr++)
325			{
326				separator = (1 < rawCount) ? ", " : " }";
327				field_data << *data_ptr << separator;
328			}
329			break;
330		}
331
332		case B_SIZE_T_TYPE:
333		{
334			field_type = "B_SIZE_T_TYPE";
335			field_data << "{ ";
336			for (const size_t* data_ptr = (const size_t*)rawData;
337				rawCount > 0;
338				rawCount--, data_ptr++)
339			{
340				separator = (1 < rawCount) ? ", " : " }";
341				field_data << *data_ptr << separator;
342			}
343			break;
344		}
345
346		case B_SSIZE_T_TYPE:
347		{
348			field_type = "B_SSIZE_T_TYPE";
349			field_data << "{ ";
350			for (const ssize_t* data_ptr = (const ssize_t*)rawData;
351				rawCount > 0;
352				rawCount--, data_ptr++)
353			{
354				separator = (1 < rawCount) ? ", " : " }";
355				field_data << *data_ptr << separator;
356			}
357			break;
358		}
359
360		case B_POINTER_TYPE:
361		{
362			field_type = "B_POINTER_TYPE";
363			break;
364		}
365
366		case B_OBJECT_TYPE:
367		{
368			field_type = "B_OBJECT_TYPE";
369			break;
370		}
371
372		case B_MESSAGE_TYPE:
373		{
374			field_type = "B_MESSAGE_TYPE";
375			break;
376		}
377
378		case B_MESSENGER_TYPE:
379		{
380			field_type = "B_MESSENGER_TYPE";
381			break;
382		}
383
384		case B_POINT_TYPE:
385		{
386			field_type = "B_POINT_TYPE";
387			field_data << "{ ";
388			for (const BPoint* data_ptr = (const BPoint*)rawData;
389				rawCount > 0;
390				rawCount--, data_ptr++)
391			{
392				separator = (1 < rawCount) ? ", " : " }";
393				field_data << "(" << data_ptr->x << ", " << data_ptr->y << ")" << separator;
394			}
395			break;
396		}
397
398		case B_RECT_TYPE:
399		{
400			field_type = "B_RECT_TYPE";
401			break;
402		}
403
404//		case B_PATH_TYPE:					s = "B_PATH_TYPE";					break;
405
406		case B_REF_TYPE:
407		{
408			field_type = "B_REF_TYPE";
409			break;
410		}
411
412		case B_RGB_COLOR_TYPE:
413		{
414			field_type = "B_RGB_COLOR_TYPE";
415			break;
416		}
417
418		case B_PATTERN_TYPE:
419		{
420			field_type = "B_PATTERN_TYPE";
421			break;
422		}
423
424		case B_STRING_TYPE:
425		{
426			field_type = "B_STRING_TYPE";
427			field_data << "{ ";
428			for (const char* data_ptr = (const char*)rawData;
429				rawCount > 0;
430				rawCount--, data_ptr+= strlen(data_ptr) )
431			{
432				separator = (1 < rawCount) ? ", " : " }";
433				field_data << "\"" << data_ptr << "\"" << separator;
434			}
435			break;
436		}
437
438		case B_MONOCHROME_1_BIT_TYPE:
439		{
440			field_type = "B_MONOCHROME_1_BIT_TYPE";
441			break;
442		}
443
444		case B_GRAYSCALE_8_BIT_TYPE:
445		{
446			field_type = "B_GRAYSCALE_8_BIT_TYPE";
447			break;
448		}
449
450		case B_COLOR_8_BIT_TYPE:
451		{
452			field_type = "B_COLOR_8_BIT_TYPE";
453			break;
454		}
455
456		case B_RGB_32_BIT_TYPE:
457		{
458			field_type = "B_RGB_32_BIT_TYPE";
459			break;
460		}
461
462		case B_TIME_TYPE:
463		{
464			field_type = "B_TIME_TYPE";
465			break;
466		}
467
468		case B_MEDIA_PARAMETER_TYPE:
469		{
470			field_type = "B_MEDIA_PARAMETER_TYPE";
471			break;
472		}
473
474		case B_MEDIA_PARAMETER_WEB_TYPE:
475		{
476			field_type = "B_MEDIA_PARAMETER_WEB_TYPE";
477			break;
478		}
479
480		case B_MEDIA_PARAMETER_GROUP_TYPE:
481		{
482			field_type = "B_MEDIA_PARAMETER_GROUP_TYPE";
483			break;
484		}
485
486		case B_RAW_TYPE:
487		{
488			field_type = "B_RAW_TYPE";
489			break;
490		}
491
492		case B_MIME_TYPE:
493		{
494			field_type = "B_MIME_TYPE";
495			break;
496		}
497
498		case B_ANY_TYPE:
499		{
500			field_type = "B_ANY_TYPE";
501			break;
502		}
503
504		default:
505		{
506			field_type = "UNKNOWN_TYPE";
507			break;
508		}
509	}
510
511    sprintf(msg_buffer,
512            "    %-18s %-18s [%2d] = %s\n",
513            field_type,
514            fieldName,
515            field_count,
516            field_data.String() );
517
518    m_outfile->Write(msg_buffer, strlen(msg_buffer) );
519}
520