xref: /haiku/src/kits/app/PortLink.cpp (revision db10640de90f7f9519ba2da9577b7c1af3c64f6b)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		PortLink.cpp
23 //	Author:			Pahtz <pahtz@yahoo.com.au>
24 //	Description:	Class for low-overhead port-based messaging
25 //
26 //------------------------------------------------------------------------------
27 #include <stdlib.h>
28 #include <string.h>
29 #include <new>
30 
31 #include <ServerProtocol.h>
32 #include "PortLink.h"
33 
34 #define DEBUG_BPORTLINK
35 #ifdef DEBUG_BPORTLINK
36 #	include <stdio.h>
37 #	define STRACE(x) printf x
38 	const char *strcode(int32 code);
39 	const char *bstrcode(int32 code);
40 #else
41 #	define STRACE(x) ;
42 #endif
43 
44 //set Initial==Max for a fixed buffer size
45 static const int32 kInitialSendBufferSize = 2048;
46 static const int32 kMaxSendBufferSize = 2048;
47 static const int32 kInitialReceiveBufferSize = 2048;
48 static const int32 kMaxReceiveBufferSize = 2048;
49 //make the max receive buffer at least as large as max send
50 
51 static const int32 kHeaderSize = sizeof(int32) * 3; //size + code + flags
52 
53 BPortLink::BPortLink(port_id send, port_id receive) :
54 	fSendPort(send), fReceivePort(receive), fSendBuffer(NULL), fRecvBuffer(NULL),
55 	fSendPosition(0), fRecvPosition(0), fSendStart(0), fRecvStart(0),
56 	fSendBufferSize(0), fRecvBufferSize(0), fSendCount(0), fDataSize(0),
57 	fReplySize(0), fWriteError(B_OK), fReadError(B_OK)
58 {
59 	/*	*/
60 }
61 
62 BPortLink::~BPortLink()
63 {
64 	if (fSendBuffer)
65 		free(fSendBuffer);
66 	if (fRecvBuffer)
67 		free(fRecvBuffer);
68 }
69 
70 status_t BPortLink::StartMessage(int32 code)
71 {
72 	if (EndMessage() < B_OK)	//end previous message
73 		CancelMessage();	//abandon previous message
74 
75 	if (fSendBufferSize == 0)
76 	{
77 		fSendBuffer = (char *)malloc(kInitialSendBufferSize);
78 		if (fSendBuffer == NULL)
79 		{
80 			fWriteError = B_NO_MEMORY;
81 			return B_NO_MEMORY;
82 		}
83 		fSendBufferSize = kInitialSendBufferSize;
84 	}
85 
86 	status_t err;
87 	//must have space for at least size + code + flags
88 	if (fSendBufferSize - fSendPosition < kHeaderSize)
89 	{
90 		err = Flush();	//will set fSendPosition and fSendStart to 0
91 		if (err < B_OK)
92 			return err;
93 	}
94 
95 	int32 *p = (int32 *)(fSendBuffer + fSendStart);	//start of current message
96 	*p = 0;	//size
97 	*(++p) = code;	//code
98 	*(++p) = 0;	//flags
99 	fSendPosition += kHeaderSize;	//size + code + flags
100 
101 	STRACE(("info: BPortLink buffered header %s [%ld %ld %ld].\n", strcode(code), (int32)0, *(p-1), *p));
102 
103 	return B_OK;
104 }
105 
106 status_t BPortLink::EndMessage()
107 {
108 	if (fSendPosition == fSendStart || fWriteError < B_OK)
109 		return fWriteError;
110 
111 	int32 *p = (int32 *)(fSendBuffer + fSendStart);	//start of the message
112 	*p = fSendPosition - fSendStart;	//record the size of the message
113 	fSendCount++;	//increase the number of completed messages
114 
115 	fSendStart = fSendPosition;	//start of next new message
116 
117 	return B_OK;
118 	STRACE(("info: BPortLink EndMessage() of size %ld.\n", *p));
119 }
120 
121 void BPortLink::CancelMessage()
122 {
123 	fSendPosition = fSendStart;
124 	fWriteError = B_OK;
125 }
126 
127 status_t BPortLink::Attach(const void *data, ssize_t size)
128 {
129 	if (fWriteError < B_OK)
130 		return fWriteError;
131 
132 	if (size <= 0)
133 	{
134 		fWriteError = B_BAD_VALUE;
135 		return B_BAD_VALUE;
136 	}
137 
138 	if (fSendPosition == fSendStart)
139 		return B_NO_INIT;	//need to call StartMessage() first
140 
141 	int32 remaining = fSendBufferSize - fSendPosition;
142 	if (remaining < size)	//we have to make space for the data
143 	{
144 		int32 total = size + (fSendPosition - fSendStart);
145 			//resulting size of current message
146 
147 		int32 newbuffersize;
148 		if (total <= fSendBufferSize)
149 			newbuffersize = fSendBufferSize;	//no change
150 		else if (total > kMaxSendBufferSize)
151 		{
152 			fWriteError = B_BAD_VALUE;
153 			return B_BAD_VALUE;
154 		}
155 		else if (total <= kInitialSendBufferSize)
156 			newbuffersize = kInitialSendBufferSize;
157 		else
158 			newbuffersize = (total + B_PAGE_SIZE) - (total % B_PAGE_SIZE);
159 
160 		//FlushCompleted() to make space
161 		status_t err;
162 		err = FlushCompleted(newbuffersize);
163 		if (err < B_OK)
164 		{
165 			fWriteError = err;
166 			return err;
167 		}
168 	}
169 
170 	memcpy(fSendBuffer + fSendPosition, data, size);
171 	fSendPosition += size;
172 	return fWriteError;
173 }
174 
175 status_t BPortLink::FlushCompleted(ssize_t newbuffersize)
176 {
177 	char *buffer = NULL;
178 	if (newbuffersize == fSendBufferSize)
179 		buffer = fSendBuffer;	//keep existing buffer
180 	else
181 	{
182 		//create new larger buffer
183 		buffer = (char *)malloc(newbuffersize);
184 		if (buffer == NULL)
185 			return B_NO_MEMORY;
186 	}
187 
188 	int32 position = fSendPosition;
189 	int32 start = fSendStart;
190 	fSendPosition = fSendStart;	//trick to hide the incomplete message
191 
192 	status_t err;
193 	err = Flush();
194 	if (err < B_OK)
195 	{
196 		fSendPosition = position;
197 		if (buffer != fSendBuffer)
198 			free(buffer);
199 		return err;
200 	}
201 
202 	//move the incomplete message to the start of the buffer
203 	fSendPosition = min_c(position - start, newbuffersize);
204 	memcpy(buffer, fSendBuffer + start, fSendPosition);
205 
206 	if (fSendBuffer != buffer)
207 	{
208 		free(fSendBuffer);
209 		fSendBuffer = buffer;
210 		fSendBufferSize = newbuffersize;
211 	}
212 
213 	return B_OK;
214 }
215 
216 
217 void BPortLink::SetSendPort( port_id port )
218 {
219 	fSendPort=port;
220 }
221 
222 port_id BPortLink::GetSendPort()
223 {
224 	return fSendPort;
225 }
226 
227 void BPortLink::SetReplyPort( port_id port )
228 {
229 	fReceivePort=port;
230 }
231 
232 port_id BPortLink::GetReplyPort()
233 {
234 	return fReceivePort;
235 }
236 
237 status_t BPortLink::Flush(bigtime_t timeout)
238 {
239 	if (fWriteError < B_OK)
240 		return fWriteError;
241 
242 	EndMessage();
243 	if (fSendCount == 0)
244 		return B_OK;
245 
246 	STRACE(("info: BPortLink Flush() waiting to send %ld messages of %ld bytes on port %ld.\n", fSendCount, fSendPosition, fSendPort));
247 
248 	//TODO: we only need AS_SERVER_PORTLINK when all OBOS uses BPortLink
249 	int32 protocol = (fSendCount > 1 ? AS_SERVER_SESSION : AS_SERVER_PORTLINK);
250 
251 	status_t err;
252 	if(timeout != B_INFINITE_TIMEOUT)
253 	{
254 		do {
255 			err = write_port_etc(fSendPort, protocol, fSendBuffer,
256 									fSendPosition, B_RELATIVE_TIMEOUT, timeout);
257 		} while(err == B_INTERRUPTED);
258 	}
259 	else
260 	{
261 		do {
262 			err = write_port(fSendPort, protocol, fSendBuffer, fSendPosition);
263 		} while(err == B_INTERRUPTED);
264 	}
265 
266 	if (err == B_OK)
267 	{
268 		STRACE(("info: BPortLink Flush() %ld messages total of %ld bytes on port %ld.\n", fSendCount, fSendPosition, fSendPort));
269 		fSendPosition = 0;
270 		fSendStart = 0;
271 		fSendCount = 0;
272 		return B_OK;
273 	}
274 
275 	STRACE(("error info: BPortLink Flush() failed for %ld bytes (%s) on port %ld.\n", fSendPosition, strerror(err), fSendPort));
276 	return err;
277 }
278 
279 status_t BPortLink::GetNextReply(int32 *code, bigtime_t timeout)
280 {
281 	int32 remaining;
282 
283 	fReadError = B_OK;
284 
285 	remaining = fDataSize - (fRecvStart + fReplySize);
286 	STRACE(("info: BPortLink GetNextReply() reports %ld bytes remaining in buffer.\n", remaining));
287 
288 	//find the position of the next message header in the buffer
289 	int32 *header;
290 	if (remaining <= 0)
291 	{
292 		status_t err = ReadFromPort(timeout);
293 		if (err < B_OK)
294 			return err;
295 		remaining = fDataSize;
296 		header = (int32 *)fRecvBuffer;
297 	}
298 	else
299 	{
300 		fRecvStart += fReplySize;	//start of the next message
301 		fRecvPosition = fRecvStart;
302 		header = (int32 *)(fRecvBuffer + fRecvStart);
303 	}
304 
305 	//check we have a well-formed message
306 	if (remaining < kHeaderSize)
307 		//we don't have enough data for a complete header
308 	{
309 		STRACE(("error info: BPortLink remaining %ld bytes is less than header size.\n", remaining));
310 		ResetReplyBuffer();
311 		return B_ERROR;
312 	}
313 
314 	fReplySize = *header;	//size of the first message
315 	if (fReplySize > remaining || fReplySize < kHeaderSize)
316 		//the header info declares more data than we have OR
317 		//the header info declares less data than kHeaderSize
318 	{
319 		STRACE(("error info: BPortLink message size of %ld bytes smaller than header size.\n", fReplySize));
320 		ResetReplyBuffer();
321 		return B_ERROR;
322 	}
323 
324 	*code = *(++header);
325 	fRecvPosition += kHeaderSize;	//size + code + flags
326 
327 	STRACE(("info: BPortLink got header %s [%ld %ld %ld] from port %ld.\n", strcode(*code), fReplySize, *code, *(header + 1), fReceivePort));
328 
329 	return B_OK;
330 }
331 
332 void BPortLink::ResetReplyBuffer()
333 {
334 	fRecvPosition = 0;
335 	fRecvStart = 0;
336 	fDataSize = 0;
337 	fReplySize = 0;
338 }
339 
340 status_t BPortLink::AdjustReplyBuffer(bigtime_t timeout)
341 {
342 	//Here we take advantage of the compiler's dead-code elimination
343 	if (kInitialReceiveBufferSize == kMaxReceiveBufferSize) //fixed buffer size
344 	{
345 		if (fRecvBuffer != NULL)
346 			return B_OK;
347 
348 		fRecvBuffer = (char *)malloc(kInitialReceiveBufferSize);
349 		if (fRecvBuffer == NULL)
350 			return B_NO_MEMORY;
351 		fRecvBufferSize = kInitialReceiveBufferSize;
352 	}
353 	else //if (kInitialReceiveBufferSize < kMaxReceiveBufferSize)
354 	{
355 		STRACE(("info: BPortLink getting port_buffer_size().\n"));
356 		ssize_t buffersize;
357 		if (timeout == B_INFINITE_TIMEOUT)
358 			buffersize = port_buffer_size(fReceivePort);
359 		else
360 			buffersize = port_buffer_size_etc(fReceivePort, B_TIMEOUT, timeout);
361 		STRACE(("info: BPortLink got port_buffer_size() = %ld.\n", buffersize));
362 
363 		if (buffersize < 0)
364 			return (status_t)buffersize;
365 
366 		//make sure our receive buffer is large enough
367 		if (buffersize > fRecvBufferSize)
368 		{
369 			if (buffersize <= kInitialReceiveBufferSize)
370 				buffersize = kInitialReceiveBufferSize;
371 			else
372 				buffersize = (buffersize + B_PAGE_SIZE) - (buffersize % B_PAGE_SIZE);
373 			if (buffersize > kMaxReceiveBufferSize)
374 				return B_ERROR;	//we can't continue
375 
376 			STRACE(("info: BPortLink setting receive buffersize to %ld.\n", buffersize));
377 			char *buffer = (char *)malloc(buffersize);
378 			if (buffer == NULL)
379 				return B_NO_MEMORY;
380 			if (fRecvBuffer)
381 				free(fRecvBuffer);
382 			fRecvBuffer = buffer;
383 			fRecvBufferSize = buffersize;
384 		}
385 	}
386 
387 	return B_OK;
388 }
389 
390 status_t BPortLink::ReadFromPort(bigtime_t timeout)
391 {
392 	//we are here so it means we finished reading the buffer contents
393 	ResetReplyBuffer();
394 
395 	status_t err = AdjustReplyBuffer(timeout);
396 	if (err < B_OK)
397 		return err;
398 
399 	int32 protocol;
400 	ssize_t bytesread;
401 	STRACE(("info: BPortLink reading port %ld.\n", fReceivePort));
402 	if (timeout != B_INFINITE_TIMEOUT)
403 	{
404 		do {
405 			bytesread = read_port_etc(fReceivePort, &protocol, fRecvBuffer,
406 				fRecvBufferSize, B_TIMEOUT, timeout);
407 		} while(bytesread == B_INTERRUPTED);
408 	}
409 	else
410 	{
411 		do {
412 			bytesread = read_port(fReceivePort, &protocol, fRecvBuffer,
413 				fRecvBufferSize);
414 		} while(bytesread == B_INTERRUPTED);
415 	}
416 
417 	STRACE(("info: BPortLink read %ld bytes.\n", bytesread));
418 	if (bytesread < B_OK)
419 		return bytesread;
420 
421 	//TODO: we only need AS_SERVER_PORTLINK when all OBOS uses BPortLink
422 	if (protocol != AS_SERVER_PORTLINK && protocol != AS_SERVER_SESSION)
423 		return B_ERROR;
424 	if (protocol == AS_SERVER_PORTLINK && bytesread != *((int32 *)fRecvBuffer))
425 		//should only be one message for PORTLINK so the size declared in the header
426 		//(the first int32 in the header) should be the same as bytesread
427 		return B_ERROR;
428 
429 	fDataSize = bytesread;
430 	return B_OK;
431 }
432 
433 status_t BPortLink::Read(void *data, ssize_t size)
434 {
435 //	STRACE(("info: BPortLink Read()ing %ld bytes...\n", size));
436 	if (fReadError < B_OK)
437 		return fReadError;
438 
439 	if (size < 1)
440 	{
441 		fReadError = B_BAD_VALUE;
442 		return B_BAD_VALUE;
443 	}
444 
445 	if (fDataSize == 0 || fReplySize == 0)
446 		return B_NO_INIT;	//need to call GetNextReply() first
447 
448 	if (fRecvPosition + size > fRecvStart + fReplySize)
449 	{
450 		//reading past the end of current message
451 		fReadError = B_BAD_VALUE;
452 		return B_BAD_VALUE;
453 	}
454 
455 	memcpy(data, fRecvBuffer + fRecvPosition, size);
456 	fRecvPosition += size;
457 	return fReadError;
458 }
459 
460 status_t BPortLink::ReadString(char **string)
461 {
462 	status_t err;
463 	int32 len = 0;
464 
465 	err = Read<int32>(&len);
466 	if (err < B_OK)
467 		return err;
468 
469 	if (len)
470 	{
471 		*string = (char *)malloc(len);
472 		if (*string == NULL)
473 		{
474 			fRecvPosition -= sizeof(int32);	//rewind the transaction
475 			return B_NO_MEMORY;
476 		}
477 
478 		err = Read(*string, len);
479 		if (err < B_OK)
480 		{
481 			free(*string);
482 			*string = NULL;
483 			fRecvPosition -= sizeof(int32);	//rewind the transaction
484 			return err;
485 		}
486 		(*string)[len-1] = '\0';
487 		return B_OK;
488 	}
489 	else
490 	{
491 		fRecvPosition -= sizeof(int32);	//rewind the transaction
492 		return B_ERROR;
493 	}
494 }
495 
496 status_t BPortLink::AttachString(const char *string)
497 {
498 	status_t err;
499 	if (string == NULL)
500 		return B_BAD_VALUE;
501 
502 	int32 len = strlen(string)+1;
503 	err = Attach<int32>(len);
504 	if (err < B_OK)
505 		return err;
506 
507 	err = Attach(string, len);
508 	if (err < B_OK)
509 		fSendPosition -= sizeof(int32);	//rewind the transaction
510 
511 	return err;
512 }
513 
514 #ifdef DEBUG_BPORTLINK
515 #include <ServerProtocol.h>
516 #include <AppDefs.h>
517 
518 static const char *kASCodeNames[] =
519 {
520 "SERVER_TRUE",
521 "SERVER_FALSE",
522 "AS_SERVER_BMESSAGE",
523 "AS_SERVER_AREALINK",
524 "AS_SERVER_SESSION",
525 "AS_SERVER_PORTLINK",
526 "AS_CLIENT_DEAD",
527 "AS_CREATE_APP",
528 "AS_DELETE_APP",
529 "AS_QUIT_APP",
530 "AS_SET_SERVER_PORT",
531 "AS_CREATE_WINDOW",
532 "AS_DELETE_WINDOW",
533 "AS_CREATE_BITMAP",
534 "AS_DELETE_BITMAP",
535 "AS_SET_CURSOR_DATA",
536 "AS_SET_CURSOR_BCURSOR",
537 "AS_SET_CURSOR_BBITMAP",
538 "AS_SET_CURSOR_SYSTEM",
539 "AS_SET_SYSCURSOR_DATA",
540 "AS_SET_SYSCURSOR_BCURSOR",
541 "AS_SET_SYSCURSOR_BBITMAP",
542 "AS_SET_SYSCURSOR_DEFAULTS",
543 "AS_GET_SYSCURSOR",
544 "AS_SHOW_CURSOR",
545 "AS_HIDE_CURSOR",
546 "AS_OBSCURE_CURSOR",
547 "AS_QUERY_CURSOR_HIDDEN",
548 "AS_CREATE_BCURSOR",
549 "AS_DELETE_BCURSOR",
550 "AS_BEGIN_RECT_TRACKING",
551 "AS_END_RECT_TRACKING",
552 "AS_SHOW_WINDOW",
553 "AS_HIDE_WINDOW",
554 "AS_QUIT_WINDOW",
555 "AS_SEND_BEHIND",
556 "AS_SET_LOOK",
557 "AS_SET_FEEL",
558 "AS_SET_FLAGS",
559 "AS_DISABLE_UPDATES",
560 "AS_ENABLE_UPDATES",
561 "AS_BEGIN_UPDATE",
562 "AS_END_UPDATE",
563 "AS_NEEDS_UPDATE",
564 "AS_WINDOW_TITLE",
565 "AS_ADD_TO_SUBSET",
566 "AS_REM_FROM_SUBSET",
567 "AS_SET_ALIGNMENT",
568 "AS_GET_ALIGNMENT",
569 "AS_GET_WORKSPACES",
570 "AS_SET_WORKSPACES",
571 "AS_WINDOW_RESIZE",
572 "AS_WINDOW_MOVE",
573 "AS_SET_SIZE_LIMITS",
574 "AS_ACTIVATE_WINDOW",
575 "AS_WINDOW_MINIMIZE",
576 "AS_UPDATE_IF_NEEDED",
577 "_ALL_UPDATED_",
578 "AS_CREATE_PICTURE",
579 "AS_DELETE_PICTURE",
580 "AS_CLONE_PICTURE",
581 "AS_DOWNLOAD_PICTURE",
582 "AS_QUERY_FONTS_CHANGED",
583 "AS_UPDATED_CLIENT_FONTLIST",
584 "AS_GET_FAMILY_ID",
585 "AS_GET_STYLE_ID",
586 "AS_GET_STYLE_FOR_FACE",
587 "AS_GET_SCREEN_MODE",
588 "AS_SET_UI_COLORS",
589 "AS_GET_UI_COLORS",
590 "AS_GET_UI_COLOR",
591 "AS_SET_DECORATOR",
592 "AS_GET_DECORATOR",
593 "AS_R5_SET_DECORATOR",
594 "AS_COUNT_WORKSPACES",
595 "AS_SET_WORKSPACE_COUNT",
596 "AS_CURRENT_WORKSPACE",
597 "AS_ACTIVATE_WORKSPACE",
598 "AS_SET_SCREEN_MODE",
599 "AS_GET_SCROLLBAR_INFO",
600 "AS_SET_SCROLLBAR_INFO",
601 "AS_IDLE_TIME",
602 "AS_SELECT_PRINTER_PANEL",
603 "AS_ADD_PRINTER_PANEL",
604 "AS_RUN_BE_ABOUT",
605 "AS_SET_FOCUS_FOLLOWS_MOUSE",
606 "AS_FOCUS_FOLLOWS_MOUSE",
607 "AS_SET_MOUSE_MODE",
608 "AS_GET_MOUSE_MODE",
609 "AS_WORKSPACE_ACTIVATED",
610 "AS_WORKSPACES_CHANGED",
611 "AS_WINDOW_ACTIVATED",
612 "AS_SCREENMODE_CHANGED",
613 "AS_BEGIN_TRANSACTION",
614 "AS_END_TRANSACTION",
615 "AS_SET_HIGH_COLOR",
616 "AS_SET_LOW_COLOR",
617 "AS_SET_VIEW_COLOR",
618 "AS_STROKE_ARC",
619 "AS_STROKE_BEZIER",
620 "AS_STROKE_ELLIPSE",
621 "AS_STROKE_LINE",
622 "AS_STROKE_LINEARRAY",
623 "AS_STROKE_POLYGON",
624 "AS_STROKE_RECT",
625 "AS_STROKE_ROUNDRECT",
626 "AS_STROKE_SHAPE",
627 "AS_STROKE_TRIANGLE",
628 "AS_FILL_ARC",
629 "AS_FILL_BEZIER",
630 "AS_FILL_ELLIPSE",
631 "AS_FILL_POLYGON",
632 "AS_FILL_RECT",
633 "AS_FILL_REGION",
634 "AS_FILL_ROUNDRECT",
635 "AS_FILL_SHAPE",
636 "AS_FILL_TRIANGLE",
637 "AS_MOVEPENBY",
638 "AS_MOVEPENTO",
639 "AS_SETPENSIZE",
640 "AS_DRAW_STRING",
641 "AS_SET_FONT",
642 "AS_SET_FONT_SIZE",
643 "AS_FLUSH",
644 "AS_SYNC",
645 "AS_LAYER_CREATE",
646 "AS_LAYER_DELETE",
647 "AS_LAYER_CREATE_ROOT",
648 "AS_LAYER_DELETE_ROOT",
649 "AS_LAYER_ADD_CHILD",
650 "AS_LAYER_REMOVE_CHILD",
651 "AS_LAYER_REMOVE_SELF",
652 "AS_LAYER_SHOW",
653 "AS_LAYER_HIDE",
654 "AS_LAYER_MOVE",
655 "AS_LAYER_RESIZE",
656 "AS_LAYER_INVALIDATE",
657 "AS_LAYER_DRAW",
658 "AS_LAYER_GET_TOKEN",
659 "AS_LAYER_ADD",
660 "AS_LAYER_REMOVE",
661 "AS_LAYER_GET_COORD",
662 "AS_LAYER_SET_FLAGS",
663 "AS_LAYER_SET_ORIGIN",
664 "AS_LAYER_GET_ORIGIN",
665 "AS_LAYER_RESIZE_MODE",
666 "AS_LAYER_CURSOR",
667 "AS_LAYER_BEGIN_RECT_TRACK",
668 "AS_LAYER_END_RECT_TRACK",
669 "AS_LAYER_DRAG_RECT",
670 "AS_LAYER_DRAG_IMAGE",
671 "AS_LAYER_GET_MOUSE_COORDS",
672 "AS_LAYER_SCROLL",
673 "AS_LAYER_SET_LINE_MODE",
674 "AS_LAYER_GET_LINE_MODE",
675 "AS_LAYER_PUSH_STATE",
676 "AS_LAYER_POP_STATE",
677 "AS_LAYER_SET_SCALE",
678 "AS_LAYER_GET_SCALE",
679 "AS_LAYER_SET_DRAW_MODE",
680 "AS_LAYER_GET_DRAW_MODE",
681 "AS_LAYER_SET_BLEND_MODE",
682 "AS_LAYER_GET_BLEND_MODE",
683 "AS_LAYER_SET_PEN_LOC",
684 "AS_LAYER_GET_PEN_LOC",
685 "AS_LAYER_SET_PEN_SIZE",
686 "AS_LAYER_GET_PEN_SIZE",
687 "AS_LAYER_SET_HIGH_COLOR",
688 "AS_LAYER_SET_LOW_COLOR",
689 "AS_LAYER_SET_VIEW_COLOR",
690 "AS_LAYER_GET_COLORS",
691 "AS_LAYER_PRINT_ALIASING",
692 "AS_LAYER_CLIP_TO_PICTURE",
693 "AS_LAYER_CLIP_TO_INVERSE_PICTURE",
694 "AS_LAYER_GET_CLIP_REGION",
695 "AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT",
696 "AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT",
697 "AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT",
698 "AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT",
699 "AS_LAYER_DRAW_STRING",
700 "AS_LAYER_SET_CLIP_REGION",
701 "AS_LAYER_LINE_ARRAY",
702 "AS_LAYER_BEGIN_PICTURE",
703 "AS_LAYER_APPEND_TO_PICTURE",
704 "AS_LAYER_END_PICTURE",
705 "AS_LAYER_COPY_BITS",
706 "AS_LAYER_DRAW_PICTURE",
707 "AS_LAYER_INVAL_RECT",
708 "AS_LAYER_INVAL_REGION",
709 "AS_LAYER_INVERT_RECT",
710 "AS_LAYER_MOVETO",
711 "AS_LAYER_RESIZETO",
712 "AS_LAYER_SET_STATE",
713 "AS_LAYER_SET_FONT_STATE",
714 "AS_LAYER_GET_STATE",
715 "AS_LAYER_SET_VIEW_IMAGE",
716 "AS_LAYER_SET_PATTERN",
717 "AS_SET_CURRENT_LAYER",
718 };
719 
720 const char *strcode(int32 code)
721 {
722 	code = code - SERVER_TRUE;
723 	if (code >= 0 && code <= AS_SET_CURRENT_LAYER - SERVER_TRUE)
724 		return kASCodeNames[code];
725 	else
726 		return bstrcode(code);
727 }
728 
729 const char *bstrcode(int32 code)
730 {
731 	switch(code)
732 	{
733 		case B_ABOUT_REQUESTED:
734 		{
735 			return "B_ABOUT_REQUESTED";
736 		}
737 		case B_APP_ACTIVATED:
738 		{
739 			return "B_APP_ACTIVATED/B_WINDOW_ACTIVATED";
740 		}
741 		case B_ARGV_RECEIVED:
742 		{
743 			return "B_ARGV_RECEIVED";
744 		}
745 		case B_QUIT_REQUESTED:
746 		{
747 			return "B_QUIT_REQUESTED";
748 		}
749 		case B_CANCEL:
750 		{
751 			return "B_CANCEL";
752 		}
753 		case B_KEY_DOWN:
754 		{
755 			return "B_KEY_DOWN";
756 		}
757 		case B_KEY_UP:
758 		{
759 			return "B_KEY_UP";
760 		}
761 		case B_UNMAPPED_KEY_DOWN:
762 		{
763 			return "B_UNMAPPED_KEY_DOWN";
764 		}
765 		case B_UNMAPPED_KEY_UP:
766 		{
767 			return "B_UNMAPPED_KEY_UP";
768 		}
769 		case B_MODIFIERS_CHANGED:
770 		{
771 			return "B_MODIFIERS_CHANGED";
772 		}
773 		case B_MINIMIZE:
774 		{
775 			return "B_MINIMIZE";
776 		}
777 		case B_MOUSE_DOWN:
778 		{
779 			return "B_MOUSE_DOWN";
780 		}
781 		case B_MOUSE_MOVED:
782 		{
783 			return "B_MOUSE_MOVED";
784 		}
785 		case B_MOUSE_ENTER_EXIT:
786 		{
787 			return "B_MOUSE_ENTER_EXIT";
788 		}
789 		case B_MOUSE_UP:
790 		{
791 			return "B_MOUSE_UP";
792 		}
793 		case B_MOUSE_WHEEL_CHANGED:
794 		{
795 			return "B_MOUSE_WHEEL_CHANGED";
796 		}
797 		case B_OPEN_IN_WORKSPACE:
798 		{
799 			return "B_OPEN_IN_WORKSPACE";
800 		}
801 		case B_PRINTER_CHANGED:
802 		{
803 			return "B_PRINTER_CHANGED";
804 		}
805 		case B_PULSE:
806 		{
807 			return "B_PULSE";
808 		}
809 		case B_READY_TO_RUN:
810 		{
811 			return "B_READY_TO_RUN";
812 		}
813 		case B_REFS_RECEIVED:
814 		{
815 			return "B_REFS_RECEIVED";
816 		}
817 		case B_RELEASE_OVERLAY_LOCK:
818 		{
819 			return "B_RELEASE_OVERLAY_LOCK";
820 		}
821 		case B_ACQUIRE_OVERLAY_LOCK:
822 		{
823 			return "B_ACQUIRE_OVERLAY_LOCK";
824 		}
825 		case B_SCREEN_CHANGED:
826 		{
827 			return "B_SCREEN_CHANGED";
828 		}
829 		case B_VALUE_CHANGED:
830 		{
831 			return "B_VALUE_CHANGED";
832 		}
833 		case B_VIEW_MOVED:
834 		{
835 			return "B_VIEW_MOVED";
836 		}
837 		case B_VIEW_RESIZED:
838 		{
839 			return "B_VIEW_RESIZED";
840 		}
841 		case B_WINDOW_MOVED:
842 		{
843 			return "B_WINDOW_MOVED";
844 		}
845 		case B_WINDOW_RESIZED:
846 		{
847 			return "B_WINDOW_RESIZED";
848 		}
849 		case B_WORKSPACES_CHANGED:
850 		{
851 			return "B_WORKSPACES_CHANGED";
852 		}
853 		case B_WORKSPACE_ACTIVATED:
854 		{
855 			return "B_WORKSPACE_ACTIVATED";
856 		}
857 		case B_ZOOM:
858 		{
859 			return "B_ZOOM";
860 		}
861 		case _APP_MENU_:
862 		{
863 			return "_APP_MENU";
864 		}
865 		case _BROWSER_MENUS_:
866 		{
867 			return "_BROWSER_MENUS_";
868 		}
869 		case _MENU_EVENT_:
870 		{
871 			return "_MENU_EVENT";
872 		}
873 		case _PING_:
874 		{
875 			return "_PING_";
876 		}
877 		case _QUIT_:
878 		{
879 			return "_QUIT_";
880 		}
881 		case _VOLUME_MOUNTED_:
882 		{
883 			return "_VOLUME_MOUNTED";
884 		}
885 		case _VOLUME_UNMOUNTED_:
886 		{
887 			return "_VOLUME_UNMOUNTED";
888 		}
889 		case _MESSAGE_DROPPED_:
890 		{
891 			return "_MESSAGE_DROPPED";
892 		}
893 		case _DISPOSE_DRAG_:
894 		{
895 			return "_DISPOSE_DRAG";
896 		}
897 		case _MENUS_DONE_:
898 		{
899 			return "_MENUS_DONE_";
900 		}
901 		case _SHOW_DRAG_HANDLES_:
902 		{
903 			return "_SHOW_DRAG_HANDLES_";
904 		}
905 		case _EVENTS_PENDING_:
906 		{
907 			return "_EVENTS_PENDING_";
908 		}
909 		case _UPDATE_:
910 		{
911 			return "_UPDATE_";
912 		}
913 		case _UPDATE_IF_NEEDED_:
914 		{
915 			return "_UPDATE_IF_NEEDED_";
916 		}
917 		case _PRINTER_INFO_:
918 		{
919 			return "_PRINTER_INFO_";
920 		}
921 		case _SETUP_PRINTER_:
922 		{
923 			return "_SETUP_PRINTER_";
924 		}
925 		case _SELECT_PRINTER_:
926 		{
927 			return "_SELECT_PRINTER_";
928 		}
929 		case B_SET_PROPERTY:
930 		{
931 			return "B_SET_PROPERTY";
932 		}
933 		case B_GET_PROPERTY:
934 		{
935 			return "B_GET_PROERTY";
936 		}
937 		case B_CREATE_PROPERTY:
938 		{
939 			return "B_CREATE_PROPERTY";
940 		}
941 		case B_DELETE_PROPERTY:
942 		{
943 			return "B_DELETE_PROPERTY";
944 		}
945 		case B_COUNT_PROPERTIES:
946 		{
947 			return "B_COUNT_PROPERTIES";
948 		}
949 		case B_EXECUTE_PROPERTY:
950 		{
951 			return "B_EXECUTE_PROPERTY";
952 		}
953 		case B_GET_SUPPORTED_SUITES:
954 		{
955 			return "B_GET_SUPPORTED_SUITES";
956 		}
957 		case B_UNDO:
958 		{
959 			return "B_UNDO";
960 		}
961 		case B_CUT:
962 		{
963 			return "B_CUT";
964 		}
965 		case B_COPY:
966 		{
967 			return "B_COPY";
968 		}
969 		case B_PASTE:
970 		{
971 			return "B_PASTE";
972 		}
973 		case B_SELECT_ALL:
974 		{
975 			return "B_SELECT_ALL";
976 		}
977 		case B_SAVE_REQUESTED:
978 		{
979 			return "B_SAVE_REQUESTED";
980 		}
981 		case B_MESSAGE_NOT_UNDERSTOOD:
982 		{
983 			return "B_MESSAGE_NOT_UNDERSTOOD";
984 		}
985 		case B_NO_REPLY:
986 		{
987 			return "B_NO_REPLY";
988 		}
989 		case B_REPLY:
990 		{
991 			return "B_REPLY";
992 		}
993 		case B_SIMPLE_DATA:
994 		{
995 			return "B_SIMPLE_DATA";
996 		}
997 		case B_MIME_DATA:
998 		{
999 			return "B_MIME_DATA";
1000 		}
1001 		case B_ARCHIVED_OBJECT:
1002 		{
1003 			return "B_ARCHIVED_OBJECT";
1004 		}
1005 		case B_UPDATE_STATUS_BAR:
1006 		{
1007 			return "B_UPDATE_STATUS_BAR";
1008 		}
1009 		case B_RESET_STATUS_BAR:
1010 		{
1011 			return "B_RESET_STATUS_BAR";
1012 		}
1013 		case B_NODE_MONITOR:
1014 		{
1015 			return "B_NODE_MONITOR";
1016 		}
1017 		case B_QUERY_UPDATE:
1018 		{
1019 			return "B_QUERY_UPDATE";
1020 		}
1021 		case B_ENDORSABLE:
1022 		{
1023 			return "B_ENDORSABLE";
1024 		}
1025 		case B_COPY_TARGET:
1026 		{
1027 			return "B_COPY_TARGET";
1028 		}
1029 		case B_MOVE_TARGET:
1030 		{
1031 			return "B_MOVE_TARGET";
1032 		}
1033 		case B_TRASH_TARGET:
1034 		{
1035 			return "B_TRASH_TARGET";
1036 		}
1037 		case B_LINK_TARGET:
1038 		{
1039 			return "B_LINK_TARGET";
1040 		}
1041 		case B_INPUT_DEVICES_CHANGED:
1042 		{
1043 			return "B_INPUT_DEVICES_CHANGED";
1044 		}
1045 		case B_INPUT_METHOD_EVENT:
1046 		{
1047 			return "B_INPUT_METHOD_EVENT";
1048 		}
1049 		case B_WINDOW_MOVE_TO:
1050 		{
1051 			return "B_WINDOW_MOVE_TO";
1052 		}
1053 		case B_WINDOW_MOVE_BY:
1054 		{
1055 			return "B_WINDOW_MOVE_BY";
1056 		}
1057 		case B_SILENT_RELAUNCH:
1058 		{
1059 			return "B_SILENT_RELAUNCH";
1060 		}
1061 		case B_OBSERVER_NOTICE_CHANGE:
1062 		{
1063 			return "B_OBSERVER_NOTICE_CHANGE";
1064 		}
1065 		case B_CONTROL_INVOKED:
1066 		{
1067 			return "B_CONTROL_INVOKED";
1068 		}
1069 		case B_CONTROL_MODIFIED:
1070 		{
1071 			return "B_CONTROL_MODIFIED";
1072 		}
1073 		default:
1074 		{
1075 			return "Unknown";
1076 		}
1077 	}
1078 }
1079 #endif //DEBUG_BPORTLINK
1080 
1081 
1082