xref: /haiku/src/kits/app/LinkSender.cpp (revision 18b5424c5f12197d3979cf38dc69149c5e98150c)
1 /*
2  * Copyright 2001-2005, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Pahtz <pahtz@yahoo.com.au>
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 /** Class for low-overhead port-based messaging */
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <new>
16 
17 #include <ServerProtocol.h>
18 #include <LinkMsgSender.h>
19 
20 #include "link_message.h"
21 
22 
23 //#define DEBUG_BPORTLINK
24 #ifdef DEBUG_BPORTLINK
25 #	include <stdio.h>
26 #	define STRACE(x) printf x
27 	const char *strcode(int32 code);
28 	const char *bstrcode(int32 code);
29 #else
30 #	define STRACE(x) ;
31 #endif
32 
33 static const size_t kWatermark = kInitialBufferSize - 24;
34 	// if a message is started after this mark, the buffer is flushed automatically
35 
36 namespace BPrivate {
37 
38 LinkSender::LinkSender(port_id port)
39 	:
40 	fPort(port),
41 	fBuffer(NULL),
42 	fBufferSize(0),
43 
44 	fCurrentEnd(0),
45 	fCurrentStart(0),
46 	fCurrentStatus(B_OK)
47 {
48 }
49 
50 
51 LinkSender::~LinkSender()
52 {
53 	free(fBuffer);
54 }
55 
56 
57 void
58 LinkSender::SetPort(port_id port)
59 {
60 	fPort = port;
61 }
62 
63 
64 status_t
65 LinkSender::StartMessage(int32 code, size_t minSize)
66 {
67 	// end previous message
68 	if (EndMessage() < B_OK)
69 		CancelMessage();
70 
71 	if (minSize > kMaxBufferSize - sizeof(message_header))
72 		return fCurrentStatus = B_BUFFER_OVERFLOW;
73 
74 	minSize += sizeof(message_header);
75 
76 	// Eventually flush buffer to make space for the new message.
77 	// Note, we do not take the actual buffer size into account to not
78 	// delay the time between buffer flushes too much.
79 	if (fBufferSize > 0 && (minSize > SpaceLeft() || fCurrentStart >= kWatermark)) {
80 		status_t status = Flush();
81 		if (status < B_OK)
82 			return status;
83 	}
84 
85 	if (minSize > fBufferSize) {
86 		if (AdjustBuffer(minSize) != B_OK)
87 			return fCurrentStatus = B_NO_MEMORY;
88 	}
89 
90 	message_header *header = (message_header *)(fBuffer + fCurrentStart);
91 	header->size = 0;
92 		// will be set later
93 	header->code = code;
94 	header->flags = 0;
95 
96 	STRACE(("info: LinkSender buffered header %s (%lx) [%lu %lu %lu].\n",
97 		strcode(code), code, header->size, header->code, header->flags));
98 
99 	fCurrentEnd += sizeof(message_header);
100 	return B_OK;
101 }
102 
103 
104 status_t
105 LinkSender::EndMessage(bool needsReply)
106 {
107 	if (fCurrentEnd == fCurrentStart || fCurrentStatus < B_OK)
108 		return fCurrentStatus;
109 
110 	// record the size of the message
111 	message_header *header = (message_header *)(fBuffer + fCurrentStart);
112 	header->size = CurrentMessageSize();
113 	if (needsReply)
114 		header->flags |= needsReply;
115 
116 	STRACE(("info: LinkSender EndMessage() of size %ld.\n", header->size));
117 
118 	// bump to start of next message
119 	fCurrentStart = fCurrentEnd;
120 	return B_OK;
121 }
122 
123 
124 void
125 LinkSender::CancelMessage()
126 {
127 	fCurrentEnd = fCurrentStart;
128 	fCurrentStatus = B_OK;
129 }
130 
131 
132 status_t
133 LinkSender::Attach(const void *data, size_t size)
134 {
135 	if (fCurrentStatus < B_OK)
136 		return fCurrentStatus;
137 
138 	if (size == 0)
139 		return fCurrentStatus = B_BAD_VALUE;
140 
141 	if (fCurrentEnd == fCurrentStart)
142 		return B_NO_INIT;	// need to call StartMessage() first
143 
144 	if (SpaceLeft() < size) {
145 		// we have to make space for the data
146 
147 		status_t status = FlushCompleted(size + CurrentMessageSize());
148 		if (status < B_OK)
149 			return fCurrentStatus = status;
150 	}
151 
152 	memcpy(fBuffer + fCurrentEnd, data, size);
153 	fCurrentEnd += size;
154 
155 	return B_OK;
156 }
157 
158 
159 status_t
160 LinkSender::AttachString(const char *string, int32 length)
161 {
162 	if (string == NULL)
163 		string = "";
164 
165 	if (length == -1)
166 		length = strlen(string);
167 
168 	status_t status = Attach<int32>(length);
169 	if (status < B_OK)
170 		return status;
171 
172 	if (length > 0) {
173 		status = Attach(string, length);
174 		if (status < B_OK)
175 			fCurrentEnd -= sizeof(int32);	// rewind the transaction
176 	}
177 
178 	return status;
179 }
180 
181 
182 status_t
183 LinkSender::AdjustBuffer(size_t newSize, char **_oldBuffer)
184 {
185 	// make sure the new size is within bounds
186 	if (newSize <= kInitialBufferSize)
187 		newSize = kInitialBufferSize;
188 	else if (newSize > kMaxBufferSize)
189 		return B_BUFFER_OVERFLOW;
190 	else if (newSize > kInitialBufferSize)
191 		newSize = (newSize + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
192 
193 	char *buffer = NULL;
194 	if (newSize == fBufferSize) {
195 		// keep existing buffer
196 		if (_oldBuffer)
197 			*_oldBuffer = fBuffer;
198 		return B_OK;
199 	}
200 
201 	// create new larger buffer
202 	buffer = (char *)malloc(newSize);
203 	if (buffer == NULL)
204 		return B_NO_MEMORY;
205 
206 	if (_oldBuffer)
207 		*_oldBuffer = fBuffer;
208 	else
209 		free(fBuffer);
210 
211 	fBuffer = buffer;
212 	fBufferSize = newSize;
213 	return B_OK;
214 }
215 
216 
217 status_t
218 LinkSender::FlushCompleted(size_t newBufferSize)
219 {
220 	// we need to hide the incomplete message so that it's not flushed
221 	int32 end = fCurrentEnd;
222 	int32 start = fCurrentStart;
223 	fCurrentEnd = fCurrentStart;
224 
225 	status_t status = Flush();
226 	if (status < B_OK) {
227 		fCurrentEnd = end;
228 		return status;
229 	}
230 
231 	char *oldBuffer = NULL;
232 	status = AdjustBuffer(newBufferSize, &oldBuffer);
233 	if (status != B_OK)
234 		return status;
235 
236 	// move the incomplete message to the start of the buffer
237 	fCurrentEnd = end - start;
238 	if (oldBuffer != fBuffer) {
239 		memcpy(fBuffer, oldBuffer + start, fCurrentEnd);
240 		free(oldBuffer);
241 	} else
242 		memmove(fBuffer, fBuffer + start, fCurrentEnd);
243 
244 	return B_OK;
245 }
246 
247 
248 status_t
249 LinkSender::Flush(bigtime_t timeout, bool needsReply)
250 {
251 	if (fCurrentStatus < B_OK)
252 		return fCurrentStatus;
253 
254 	EndMessage(needsReply);
255 	if (fCurrentStart == 0)
256 		return B_OK;
257 
258 	STRACE(("info: LinkSender Flush() waiting to send messages of %ld bytes on port %ld.\n",
259 		fCurrentEnd, fPort));
260 
261 	status_t err;
262 	if (timeout != B_INFINITE_TIMEOUT) {
263 		do {
264 			err = write_port_etc(fPort, kLinkCode, fBuffer,
265 				fCurrentEnd, B_RELATIVE_TIMEOUT, timeout);
266 		} while (err == B_INTERRUPTED);
267 	} else {
268 		do {
269 			err = write_port(fPort, kLinkCode, fBuffer, fCurrentEnd);
270 		} while (err == B_INTERRUPTED);
271 	}
272 
273 	if (err < B_OK) {
274 		STRACE(("error info: LinkSender Flush() failed for %ld bytes (%s) on port %ld.\n",
275 			fCurrentEnd, strerror(err), fPort));
276 		return err;
277 	}
278 
279 	STRACE(("info: LinkSender Flush() messages total of %ld bytes on port %ld.\n",
280 		fCurrentEnd, fPort));
281 
282 	fCurrentEnd = 0;
283 	fCurrentStart = 0;
284 
285 	return B_OK;
286 }
287 
288 }	// namespace BPrivate
289 
290 //	#pragma mark -
291 
292 
293 #ifdef DEBUG_BPORTLINK
294 #include <ServerProtocol.h>
295 #include <AppDefs.h>
296 
297 static const char *kASCodeNames[] = {
298 	"SERVER_TRUE",
299 	"SERVER_FALSE",
300 	"AS_SERVER_BMESSAGE",
301 	"AS_SERVER_AREALINK",
302 	"AS_SERVER_SESSION",
303 	"AS_SERVER_PORTLINK",
304 	"AS_CLIENT_DEAD",
305 	"AS_CREATE_APP",
306 	"AS_DELETE_APP",
307 	"AS_QUIT_APP",
308 	"AS_ACTIVATE_APP",
309 	"AS_SET_SERVER_PORT",
310 	"AS_CREATE_WINDOW",
311 	"AS_DELETE_WINDOW",
312 	"AS_CREATE_BITMAP",
313 	"AS_DELETE_BITMAP",
314 	"AS_SET_CURSOR_DATA",
315 	"AS_SET_CURSOR_BCURSOR",
316 	"AS_SET_CURSOR_BBITMAP",
317 	"AS_SET_CURSOR_SYSTEM",
318 	"AS_SET_SYSCURSOR_DATA",
319 	"AS_SET_SYSCURSOR_BCURSOR",
320 	"AS_SET_SYSCURSOR_BBITMAP",
321 	"AS_SET_SYSCURSOR_DEFAULTS",
322 	"AS_GET_SYSCURSOR",
323 	"AS_SHOW_CURSOR",
324 	"AS_HIDE_CURSOR",
325 	"AS_OBSCURE_CURSOR",
326 	"AS_QUERY_CURSOR_HIDDEN",
327 	"AS_CREATE_BCURSOR",
328 	"AS_DELETE_BCURSOR",
329 	"AS_BEGIN_RECT_TRACKING",
330 	"AS_END_RECT_TRACKING",
331 	"AS_SHOW_WINDOW",
332 	"AS_HIDE_WINDOW",
333 	"AS_QUIT_WINDOW",
334 	"AS_SEND_BEHIND",
335 	"AS_SET_LOOK",
336 	"AS_SET_FEEL",
337 	"AS_SET_FLAGS",
338 	"AS_DISABLE_UPDATES",
339 	"AS_ENABLE_UPDATES",
340 	"AS_BEGIN_UPDATE",
341 	"AS_END_UPDATE",
342 	"AS_NEEDS_UPDATE",
343 	"AS_WINDOW_TITLE",
344 	"AS_ADD_TO_SUBSET",
345 	"AS_REM_FROM_SUBSET",
346 	"AS_SET_ALIGNMENT",
347 	"AS_GET_ALIGNMENT",
348 	"AS_GET_WORKSPACES",
349 	"AS_SET_WORKSPACES",
350 	"AS_WINDOW_RESIZE",
351 	"AS_WINDOW_MOVE",
352 	"AS_SET_SIZE_LIMITS",
353 	"AS_ACTIVATE_WINDOW",
354 	"AS_WINDOW_MINIMIZE",
355 	"AS_UPDATE_IF_NEEDED",
356 	"_ALL_UPDATED_",
357 	"AS_CREATE_PICTURE",
358 	"AS_DELETE_PICTURE",
359 	"AS_CLONE_PICTURE",
360 	"AS_DOWNLOAD_PICTURE",
361 	"AS_QUERY_FONTS_CHANGED",
362 	"AS_UPDATED_CLIENT_FONTLIST",
363 	"AS_GET_FAMILY_ID",
364 	"AS_GET_STYLE_ID",
365 	"AS_GET_STYLE_FOR_FACE",
366 	"AS_GET_SCREEN_MODE",
367 	"AS_SET_UI_COLORS",
368 	"AS_GET_UI_COLORS",
369 	"AS_GET_UI_COLOR",
370 	"AS_SET_DECORATOR",
371 	"AS_GET_DECORATOR",
372 	"AS_R5_SET_DECORATOR",
373 	"AS_COUNT_WORKSPACES",
374 	"AS_SET_WORKSPACE_COUNT",
375 	"AS_CURRENT_WORKSPACE",
376 	"AS_ACTIVATE_WORKSPACE",
377 	"AS_SET_SCREEN_MODE",
378 	"AS_GET_SCROLLBAR_INFO",
379 	"AS_SET_SCROLLBAR_INFO",
380 	"AS_IDLE_TIME",
381 	"AS_SELECT_PRINTER_PANEL",
382 	"AS_ADD_PRINTER_PANEL",
383 	"AS_RUN_BE_ABOUT",
384 	"AS_SET_FOCUS_FOLLOWS_MOUSE",
385 	"AS_FOCUS_FOLLOWS_MOUSE",
386 	"AS_SET_MOUSE_MODE",
387 	"AS_GET_MOUSE_MODE",
388 	"AS_WORKSPACE_ACTIVATED",
389 	"AS_WORKSPACES_CHANGED",
390 	"AS_WINDOW_ACTIVATED",
391 	"AS_SCREENMODE_CHANGED",
392 	"AS_BEGIN_TRANSACTION",
393 	"AS_END_TRANSACTION",
394 	"AS_SET_HIGH_COLOR",
395 	"AS_SET_LOW_COLOR",
396 	"AS_SET_VIEW_COLOR",
397 	"AS_STROKE_ARC",
398 	"AS_STROKE_BEZIER",
399 	"AS_STROKE_ELLIPSE",
400 	"AS_STROKE_LINE",
401 	"AS_STROKE_LINEARRAY",
402 	"AS_STROKE_POLYGON",
403 	"AS_STROKE_RECT",
404 	"AS_STROKE_ROUNDRECT",
405 	"AS_STROKE_SHAPE",
406 	"AS_STROKE_TRIANGLE",
407 	"AS_FILL_ARC",
408 	"AS_FILL_BEZIER",
409 	"AS_FILL_ELLIPSE",
410 	"AS_FILL_POLYGON",
411 	"AS_FILL_RECT",
412 	"AS_FILL_REGION",
413 	"AS_FILL_ROUNDRECT",
414 	"AS_FILL_SHAPE",
415 	"AS_FILL_TRIANGLE",
416 	"AS_MOVEPENBY",
417 	"AS_MOVEPENTO",
418 	"AS_SETPENSIZE",
419 	"AS_DRAW_STRING",
420 	"AS_SET_FONT",
421 	"AS_SET_FONT_SIZE",
422 	"AS_FLUSH",
423 	"AS_SYNC",
424 	"AS_LAYER_CREATE",
425 	"AS_LAYER_DELETE",
426 	"AS_LAYER_CREATE_ROOT",
427 	"AS_LAYER_DELETE_ROOT",
428 	"AS_LAYER_ADD_CHILD",
429 	"AS_LAYER_REMOVE_CHILD",
430 	"AS_LAYER_REMOVE_SELF",
431 	"AS_LAYER_SHOW",
432 	"AS_LAYER_HIDE",
433 	"AS_LAYER_MOVE",
434 	"AS_LAYER_RESIZE",
435 	"AS_LAYER_INVALIDATE",
436 	"AS_LAYER_DRAW",
437 	"AS_LAYER_GET_TOKEN",
438 	"AS_LAYER_ADD",
439 	"AS_LAYER_REMOVE",
440 	"AS_LAYER_GET_COORD",
441 	"AS_LAYER_SET_FLAGS",
442 	"AS_LAYER_SET_ORIGIN",
443 	"AS_LAYER_GET_ORIGIN",
444 	"AS_LAYER_RESIZE_MODE",
445 	"AS_LAYER_CURSOR",
446 	"AS_LAYER_BEGIN_RECT_TRACK",
447 	"AS_LAYER_END_RECT_TRACK",
448 	"AS_LAYER_DRAG_RECT",
449 	"AS_LAYER_DRAG_IMAGE",
450 	"AS_LAYER_GET_MOUSE_COORDS",
451 	"AS_LAYER_SCROLL",
452 	"AS_LAYER_SET_LINE_MODE",
453 	"AS_LAYER_GET_LINE_MODE",
454 	"AS_LAYER_PUSH_STATE",
455 	"AS_LAYER_POP_STATE",
456 	"AS_LAYER_SET_SCALE",
457 	"AS_LAYER_GET_SCALE",
458 	"AS_LAYER_SET_DRAW_MODE",
459 	"AS_LAYER_GET_DRAW_MODE",
460 	"AS_LAYER_SET_BLEND_MODE",
461 	"AS_LAYER_GET_BLEND_MODE",
462 	"AS_LAYER_SET_PEN_LOC",
463 	"AS_LAYER_GET_PEN_LOC",
464 	"AS_LAYER_SET_PEN_SIZE",
465 	"AS_LAYER_GET_PEN_SIZE",
466 	"AS_LAYER_SET_HIGH_COLOR",
467 	"AS_LAYER_SET_LOW_COLOR",
468 	"AS_LAYER_SET_VIEW_COLOR",
469 	"AS_LAYER_GET_COLORS",
470 	"AS_LAYER_PRINT_ALIASING",
471 	"AS_LAYER_CLIP_TO_PICTURE",
472 	"AS_LAYER_CLIP_TO_INVERSE_PICTURE",
473 	"AS_LAYER_GET_CLIP_REGION",
474 	"AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT",
475 	"AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT",
476 	"AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT",
477 	"AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT",
478 	"AS_LAYER_DRAW_STRING",
479 	"AS_LAYER_SET_CLIP_REGION",
480 	"AS_LAYER_LINE_ARRAY",
481 	"AS_LAYER_BEGIN_PICTURE",
482 	"AS_LAYER_APPEND_TO_PICTURE",
483 	"AS_LAYER_END_PICTURE",
484 	"AS_LAYER_COPY_BITS",
485 	"AS_LAYER_DRAW_PICTURE",
486 	"AS_LAYER_INVAL_RECT",
487 	"AS_LAYER_INVAL_REGION",
488 	"AS_LAYER_INVERT_RECT",
489 	"AS_LAYER_MOVETO",
490 	"AS_LAYER_RESIZETO",
491 	"AS_LAYER_SET_STATE",
492 	"AS_LAYER_SET_FONT_STATE",
493 	"AS_LAYER_GET_STATE",
494 	"AS_LAYER_SET_VIEW_IMAGE",
495 	"AS_LAYER_SET_PATTERN",
496 	"AS_SET_CURRENT_LAYER",
497 };
498 
499 const char *
500 strcode(int32 code)
501 {
502 	code = code - SERVER_TRUE;
503 	if (code >= 0 && code <= AS_SET_CURRENT_LAYER - SERVER_TRUE)
504 		return kASCodeNames[code];
505 
506 	return bstrcode(code);
507 }
508 
509 
510 const char *
511 bstrcode(int32 code)
512 {
513 	switch (code) {
514 		case B_ABOUT_REQUESTED:
515 			return "B_ABOUT_REQUESTED";
516 		case B_APP_ACTIVATED:
517 			return "B_APP_ACTIVATED/B_WINDOW_ACTIVATED";
518 		case B_ARGV_RECEIVED :
519 			return "B_ARGV_RECEIVED";
520 		case B_QUIT_REQUESTED :
521 			return "B_QUIT_REQUESTED";
522 		case B_CANCEL:
523 			return "B_CANCEL";
524 		case B_KEY_DOWN :
525 			return "B_KEY_DOWN";
526 		case B_KEY_UP :
527 			return "B_KEY_UP";
528 		case B_UNMAPPED_KEY_DOWN :
529 			return "B_UNMAPPED_KEY_DOWN";
530 		case B_UNMAPPED_KEY_UP :
531 			return "B_UNMAPPED_KEY_UP";
532 		case B_MODIFIERS_CHANGED:
533 			return "B_MODIFIERS_CHANGED";
534 		case B_MINIMIZE:
535 			return "B_MINIMIZE";
536 		case B_MOUSE_DOWN :
537 			return "B_MOUSE_DOWN";
538 		case B_MOUSE_MOVED :
539 			return "B_MOUSE_MOVED";
540 		case B_MOUSE_ENTER_EXIT:
541 			return "B_MOUSE_ENTER_EXIT";
542 		case B_MOUSE_UP :
543 			return "B_MOUSE_UP";
544 		case B_MOUSE_WHEEL_CHANGED:
545 			return "B_MOUSE_WHEEL_CHANGED";
546 		case B_OPEN_IN_WORKSPACE:
547 			return "B_OPEN_IN_WORKSPACE";
548 		case B_PRINTER_CHANGED:
549 			return "B_PRINTER_CHANGED";
550 		case B_PULSE :
551 			return "B_PULSE";
552 		case B_READY_TO_RUN :
553 			return "B_READY_TO_RUN";
554 		case B_REFS_RECEIVED :
555 			return "B_REFS_RECEIVED";
556 		case B_RELEASE_OVERLAY_LOCK:
557 			return "B_RELEASE_OVERLAY_LOCK";
558 		case B_ACQUIRE_OVERLAY_LOCK:
559 			return "B_ACQUIRE_OVERLAY_LOCK";
560 		case B_SCREEN_CHANGED :
561 			return "B_SCREEN_CHANGED";
562 		case B_VALUE_CHANGED :
563 			return "B_VALUE_CHANGED";
564 		case B_VIEW_MOVED :
565 			return "B_VIEW_MOVED";
566 		case B_VIEW_RESIZED :
567 			return "B_VIEW_RESIZED";
568 		case B_WINDOW_MOVED :
569 			return "B_WINDOW_MOVED";
570 		case B_WINDOW_RESIZED :
571 			return "B_WINDOW_RESIZED";
572 		case B_WORKSPACES_CHANGED:
573 			return "B_WORKSPACES_CHANGED";
574 		case B_WORKSPACE_ACTIVATED:
575 			return "B_WORKSPACE_ACTIVATED";
576 		case B_ZOOM:
577 			return "B_ZOOM";
578 		case _APP_MENU_:
579 			return "_APP_MENU";
580 		case _BROWSER_MENUS_:
581 			return "_BROWSER_MENUS_";
582 		case _MENU_EVENT_ :
583 			return "_MENU_EVENT";
584 		case _PING_:
585 			return "_PING_";
586 		case _QUIT_ :
587 			return "_QUIT_";
588 		case _VOLUME_MOUNTED_ :
589 			return "_VOLUME_MOUNTED";
590 		case _VOLUME_UNMOUNTED_:
591 			return "_VOLUME_UNMOUNTED";
592 		case _MESSAGE_DROPPED_ :
593 			return "_MESSAGE_DROPPED";
594 		case _DISPOSE_DRAG_ :
595 			return "_DISPOSE_DRAG";
596 		case _MENUS_DONE_:
597 			return "_MENUS_DONE_";
598 		case _SHOW_DRAG_HANDLES_:
599 			return "_SHOW_DRAG_HANDLES_";
600 		case _EVENTS_PENDING_ :
601 			return "_EVENTS_PENDING_";
602 		case _UPDATE_ :
603 			return "_UPDATE_";
604 		case _UPDATE_IF_NEEDED_:
605 			return "_UPDATE_IF_NEEDED_";
606 		case _PRINTER_INFO_:
607 			return "_PRINTER_INFO_";
608 		case _SETUP_PRINTER_:
609 			return "_SETUP_PRINTER_";
610 		case _SELECT_PRINTER_:
611 			return "_SELECT_PRINTER_";
612 		case B_SET_PROPERTY:
613 			return "B_SET_PROPERTY";
614 		case B_GET_PROPERTY:
615 			return "B_GET_PROERTY";
616 		case B_CREATE_PROPERTY:
617 			return "B_CREATE_PROPERTY";
618 		case B_DELETE_PROPERTY:
619 			return "B_DELETE_PROPERTY";
620 		case B_COUNT_PROPERTIES:
621 			return "B_COUNT_PROPERTIES";
622 		case B_EXECUTE_PROPERTY:
623 			return "B_EXECUTE_PROPERTY";
624 		case B_GET_SUPPORTED_SUITES:
625 			return "B_GET_SUPPORTED_SUITES";
626 		case B_UNDO:
627 			return "B_UNDO";
628 		case B_CUT :
629 			return "B_CUT";
630 		case B_COPY :
631 			return "B_COPY";
632 		case B_PASTE :
633 			return "B_PASTE";
634 		case B_SELECT_ALL:
635 			return "B_SELECT_ALL";
636 		case B_SAVE_REQUESTED :
637 			return "B_SAVE_REQUESTED";
638 		case B_MESSAGE_NOT_UNDERSTOOD:
639 			return "B_MESSAGE_NOT_UNDERSTOOD";
640 		case B_NO_REPLY :
641 			return "B_NO_REPLY";
642 		case B_REPLY :
643 			return "B_REPLY";
644 		case B_SIMPLE_DATA:
645 			return "B_SIMPLE_DATA";
646 		case B_MIME_DATA:
647 			return "B_MIME_DATA";
648 		case B_ARCHIVED_OBJECT:
649 			return "B_ARCHIVED_OBJECT";
650 		case B_UPDATE_STATUS_BAR:
651 			return "B_UPDATE_STATUS_BAR";
652 		case B_RESET_STATUS_BAR:
653 			return "B_RESET_STATUS_BAR";
654 		case B_NODE_MONITOR:
655 			return "B_NODE_MONITOR";
656 		case B_QUERY_UPDATE:
657 			return "B_QUERY_UPDATE";
658 		case B_ENDORSABLE:
659 			return "B_ENDORSABLE";
660 		case B_COPY_TARGET:
661 			return "B_COPY_TARGET";
662 		case B_MOVE_TARGET:
663 			return "B_MOVE_TARGET";
664 		case B_TRASH_TARGET:
665 			return "B_TRASH_TARGET";
666 		case B_LINK_TARGET:
667 			return "B_LINK_TARGET";
668 		case B_INPUT_DEVICES_CHANGED:
669 			return "B_INPUT_DEVICES_CHANGED";
670 		case B_INPUT_METHOD_EVENT:
671 			return "B_INPUT_METHOD_EVENT";
672 		case B_WINDOW_MOVE_TO:
673 			return "B_WINDOW_MOVE_TO";
674 		case B_WINDOW_MOVE_BY:
675 			return "B_WINDOW_MOVE_BY";
676 		case B_SILENT_RELAUNCH:
677 			return "B_SILENT_RELAUNCH";
678 		case B_OBSERVER_NOTICE_CHANGE :
679 			return "B_OBSERVER_NOTICE_CHANGE";
680 		case B_CONTROL_INVOKED:
681 			return "B_CONTROL_INVOKED";
682 		case B_CONTROL_MODIFIED:
683 			return "B_CONTROL_MODIFIED";
684 		default:
685 			return "Unknown";
686 	}
687 }
688 #endif //DEBUG_BPORTLINK
689 
690