1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // class platform_support
17 //
18 //----------------------------------------------------------------------------
19 
20 #include "platform/agg_platform_support.h"
21 #include "util/agg_color_conv_rgb8.h"
22 
23 #include <sys/time.h>
24 #include <cstring>
25 
26 #include <classes/requester.h>
27 #include <classes/window.h>
28 #include <datatypes/pictureclass.h>
29 #include <proto/exec.h>
30 #include <proto/datatypes.h>
31 #include <proto/dos.h>
32 #include <proto/graphics.h>
33 #include <proto/intuition.h>
34 #include <proto/keymap.h>
35 #include <proto/Picasso96API.h>
36 #include <proto/utility.h>
37 
38 Library* DataTypesBase = 0;
39 Library* GraphicsBase = 0;
40 Library* IntuitionBase = 0;
41 Library* KeymapBase = 0;
42 Library* P96Base = 0;
43 
44 DataTypesIFace* IDataTypes = 0;
45 GraphicsIFace* IGraphics = 0;
46 IntuitionIFace* IIntuition = 0;
47 KeymapIFace* IKeymap = 0;
48 P96IFace* IP96 = 0;
49 
50 Class* RequesterClass = 0;
51 Class* WindowClass = 0;
52 
53 
54 namespace agg
55 {
56 	void handle_idcmp(Hook* hook, APTR win, IntuiMessage* msg);
57 
58 	//------------------------------------------------------------------------
59 	class platform_specific
60 	{
61 	public:
62 		platform_specific(platform_support& support, pix_format_e format,
63 			bool flip_y);
64 		~platform_specific();
65 		bool handle_input();
66 		bool load_img(const char* file, unsigned idx, rendering_buffer* rbuf);
67 		bool create_img(unsigned idx, rendering_buffer* rbuf, unsigned width,
68 			unsigned height);
69 		bool make_bitmap();
70 	public:
71 		platform_support& m_support;
72 		RGBFTYPE m_ftype;
73 		pix_format_e m_format;
74 		unsigned m_bpp;
75 		BitMap* m_bitmap;
76 		bool m_flip_y;
77 		uint16 m_width;
78 		uint16 m_height;
79 		APTR m_window_obj;
80 		Window* m_window;
81 		Hook* m_idcmp_hook;
82 		unsigned m_input_flags;
83 		bool m_dragging;
84 		double m_start_time;
85 		uint16 m_last_key;
86 		BitMap* m_img_bitmaps[platform_support::max_images];
87 	};
88 
89 	//------------------------------------------------------------------------
platform_specific(platform_support & support,pix_format_e format,bool flip_y)90 	platform_specific::platform_specific(platform_support& support,
91 		pix_format_e format, bool flip_y) :
92 		m_support(support),
93 		m_ftype(RGBFB_NONE),
94 		m_format(format),
95 		m_bpp(0),
96 		m_bitmap(0),
97 		m_flip_y(flip_y),
98 		m_width(0),
99 		m_height(0),
100 		m_window_obj(0),
101 		m_window(0),
102 		m_idcmp_hook(0),
103 		m_input_flags(0),
104 		m_dragging(false),
105 		m_start_time(0.0),
106 		m_last_key(0)
107 	{
108 		switch ( format )
109 		{
110 		case pix_format_gray8:
111 			// Not supported.
112 			break;
113 		case pix_format_rgb555:
114 			m_ftype = RGBFB_R5G5B5;
115 			m_bpp = 15;
116 			break;
117 		case pix_format_rgb565:
118 			m_ftype = RGBFB_R5G6B5;
119 			m_bpp = 16;
120 			break;
121 		case pix_format_rgb24:
122 			m_ftype = RGBFB_R8G8B8;
123 			m_bpp = 24;
124 			break;
125 		case pix_format_bgr24:
126 			m_ftype = RGBFB_B8G8R8;
127 			m_bpp = 24;
128 			break;
129 		case pix_format_bgra32:
130 			m_ftype = RGBFB_B8G8R8A8;
131 			m_bpp = 32;
132 			break;
133 		case pix_format_abgr32:
134 			m_ftype = RGBFB_A8B8G8R8;
135 			m_bpp = 32;
136 			break;
137 		case pix_format_argb32:
138 			m_ftype = RGBFB_A8R8G8B8;
139 			m_bpp = 32;
140 			break;
141         case pix_format_rgba32:
142 			m_ftype = RGBFB_R8G8B8A8;
143 			m_bpp = 32;
144 			break;
145 		}
146 
147 		for ( unsigned i = 0; i < platform_support::max_images; ++i )
148 		{
149 			m_img_bitmaps[i] = 0;
150 		}
151 	}
152 
153 	//------------------------------------------------------------------------
~platform_specific()154 	platform_specific::~platform_specific()
155 	{
156 		IIntuition->DisposeObject(m_window_obj);
157 
158 		IP96->p96FreeBitMap(m_bitmap);
159 
160 		for ( unsigned i = 0; i < platform_support::max_images; ++i )
161 		{
162 			IP96->p96FreeBitMap(m_img_bitmaps[i]);
163 		}
164 
165 		if ( m_idcmp_hook != 0 )
166 		{
167 			IExec->FreeSysObject(ASOT_HOOK, m_idcmp_hook);
168 		}
169 	}
170 
171 	//------------------------------------------------------------------------
handle_input()172 	bool platform_specific::handle_input()
173 	{
174 		int16 code = 0;
175 		uint32 result = 0;
176 		Object* obj = reinterpret_cast<Object*>(m_window_obj);
177 
178 		while ( (result = IIntuition->IDoMethod(obj, WM_HANDLEINPUT,
179 				&code)) != WMHI_LASTMSG )
180 		{
181 			switch ( result & WMHI_CLASSMASK )
182 			{
183 			case WMHI_CLOSEWINDOW:
184 				return true;
185 				break;
186 			case WMHI_INTUITICK:
187 				if ( !m_support.wait_mode() )
188 				{
189 					m_support.on_idle();
190 				}
191 				break;
192 			case WMHI_NEWSIZE:
193 				if ( make_bitmap() )
194 				{
195 					m_support.trans_affine_resizing(m_width, m_height);
196 					m_support.on_resize(m_width, m_height);
197 					m_support.force_redraw();
198 				}
199 				break;
200 			}
201 		}
202 
203 		return false;
204 	}
205 
206 	//------------------------------------------------------------------------
load_img(const char * file,unsigned idx,rendering_buffer * rbuf)207 	bool platform_specific::load_img(const char* file, unsigned idx,
208 		rendering_buffer* rbuf)
209 	{
210 		if ( m_img_bitmaps[idx] != 0 )
211 		{
212 			IP96->p96FreeBitMap(m_img_bitmaps[idx]);
213 			m_img_bitmaps[idx] = 0;
214 		}
215 
216 		bool result = false;
217 
218 		Object* picture = IDataTypes->NewDTObject(const_cast<STRPTR>(file),
219 			DTA_GroupID, GID_PICTURE,
220 			PDTA_DestMode, PMODE_V43,
221 			PDTA_Remap, FALSE,
222 			TAG_END);
223 		if ( picture != 0 )
224 		{
225 			gpLayout layout;
226 			layout.MethodID = DTM_PROCLAYOUT;
227 			layout.gpl_GInfo = 0;
228 			layout.gpl_Initial = 1;
229 			ULONG loaded = IDataTypes->DoDTMethodA(picture, 0, 0,
230 				reinterpret_cast<Msg>(&layout));
231 			if ( loaded != 0 )
232 			{
233 				BitMap* src_bitmap = 0;
234 				IDataTypes->GetDTAttrs(picture,
235 					PDTA_ClassBitMap, &src_bitmap,
236 					TAG_END);
237 
238 				bool supported = false;
239 
240 				RGBFTYPE ftype = static_cast<RGBFTYPE>(IP96->p96GetBitMapAttr(
241 					src_bitmap, P96BMA_RGBFORMAT));
242 
243 				switch ( ftype )
244 				{
245 				case RGBFB_R8G8B8:
246 					supported = true;
247 					break;
248 				default:
249 					m_support.message("File uses unsupported graphics mode.");
250 					break;
251 				}
252 
253 				if ( supported )  {
254 					uint16 width = IP96->p96GetBitMapAttr(src_bitmap,
255 						P96BMA_WIDTH);
256 					uint16 height = IP96->p96GetBitMapAttr(src_bitmap,
257 						P96BMA_HEIGHT);
258 
259 					m_img_bitmaps[idx] = IP96->p96AllocBitMap(width, height,
260 						m_bpp, BMF_USERPRIVATE, 0, m_ftype);
261 					if ( m_img_bitmaps[idx] != 0 )
262 					{
263 						int8u* buf = reinterpret_cast<int8u*>(
264 							IP96->p96GetBitMapAttr(m_img_bitmaps[idx],
265 							P96BMA_MEMORY));
266 						int bpr = IP96->p96GetBitMapAttr(m_img_bitmaps[idx],
267 							P96BMA_BYTESPERROW);
268 						int stride = (m_flip_y) ? -bpr : bpr;
269 						rbuf->attach(buf, width, height, stride);
270 
271 						// P96 sets the alpha to zero so it can't be used to
272 						// color convert true color modes.
273 						if ( m_bpp == 32 )
274 						{
275 							RenderInfo ri;
276 							int32 lock = IP96->p96LockBitMap(src_bitmap,
277 								reinterpret_cast<uint8*>(&ri),
278 								sizeof(RenderInfo));
279 
280 							rendering_buffer rbuf_src;
281 							rbuf_src.attach(
282 								reinterpret_cast<int8u*>(ri.Memory),
283 								width, height, (m_flip_y) ?
284 									-ri.BytesPerRow : ri.BytesPerRow);
285 
286 							switch ( m_format )
287 							{
288 							case pix_format_bgra32:
289 								color_conv(rbuf, &rbuf_src,
290 									color_conv_rgb24_to_bgra32());
291 								break;
292 							case pix_format_abgr32:
293 								color_conv(rbuf, &rbuf_src,
294 									color_conv_rgb24_to_abgr32());
295 								break;
296 							case pix_format_argb32:
297 								color_conv(rbuf, &rbuf_src,
298 									color_conv_rgb24_to_argb32());
299 								break;
300 							case pix_format_rgba32:
301 								color_conv(rbuf, &rbuf_src,
302 									color_conv_rgb24_to_rgba32());
303 								break;
304 							}
305 
306 							IP96->p96UnlockBitMap(src_bitmap, lock);
307 						}
308 						else
309 						{
310 							IGraphics->BltBitMap(src_bitmap, 0, 0,
311 								m_img_bitmaps[idx], 0, 0, width, height,
312 								ABC|ABNC, 0xFF, 0);
313 						}
314 
315 						result = true;
316 					}
317 				}
318 			}
319 		}
320 
321 		IGraphics->WaitBlit();
322 		IDataTypes->DisposeDTObject(picture);
323 
324 		return result;
325 	}
326 
327 	//------------------------------------------------------------------------
create_img(unsigned idx,rendering_buffer * rbuf,unsigned width,unsigned height)328 	bool platform_specific::create_img(unsigned idx, rendering_buffer* rbuf,
329 		unsigned width, unsigned height)
330 	{
331 		if ( m_img_bitmaps[idx] != 0 )
332 		{
333 			IP96->p96FreeBitMap(m_img_bitmaps[idx]);
334 			m_img_bitmaps[idx] = 0;
335 		}
336 
337 		m_img_bitmaps[idx] = IP96->p96AllocBitMap(width, height,
338 			m_bpp, BMF_USERPRIVATE, m_bitmap, m_ftype);
339 		if ( m_img_bitmaps[idx] != 0 )
340 		{
341 			int8u* buf = reinterpret_cast<int8u*>(
342 				IP96->p96GetBitMapAttr(m_img_bitmaps[idx],
343 				P96BMA_MEMORY));
344 			int bpr = IP96->p96GetBitMapAttr(m_img_bitmaps[idx],
345 				P96BMA_BYTESPERROW);
346 			int stride = (m_flip_y) ? -bpr : bpr;
347 
348 			rbuf->attach(buf, width, height, stride);
349 
350 			return true;
351 		}
352 
353 		return false;
354 	}
355 
356 	//------------------------------------------------------------------------
make_bitmap()357 	bool platform_specific::make_bitmap()
358 	{
359 		uint32 width = 0;
360 		uint32 height = 0;
361 		IIntuition->GetWindowAttrs(m_window,
362 			WA_InnerWidth, &width,
363 			WA_InnerHeight, &height,
364 			TAG_END);
365 
366 		BitMap* bm = IP96->p96AllocBitMap(width, height, m_bpp,
367 			BMF_USERPRIVATE|BMF_CLEAR, 0, m_ftype);
368 		if ( bm == 0 )
369 		{
370 			return false;
371 		}
372 
373 		int8u* buf = reinterpret_cast<int8u*>(
374 			IP96->p96GetBitMapAttr(bm, P96BMA_MEMORY));
375 		int bpr = IP96->p96GetBitMapAttr(bm, P96BMA_BYTESPERROW);
376 		int stride = (m_flip_y) ? -bpr : bpr;
377 
378 		m_support.rbuf_window().attach(buf, width, height, stride);
379 
380 		if ( m_bitmap != 0 )
381 		{
382 			IP96->p96FreeBitMap(m_bitmap);
383 			m_bitmap = 0;
384 		}
385 
386 		m_bitmap = bm;
387 		m_width = width;
388 		m_height = height;
389 
390 		return true;
391 	}
392 
393 	//------------------------------------------------------------------------
platform_support(pix_format_e format,bool flip_y)394 	platform_support::platform_support(pix_format_e format, bool flip_y) :
395 		m_specific(new platform_specific(*this, format, flip_y)),
396 		m_format(format),
397 		m_bpp(m_specific->m_bpp),
398 		m_window_flags(0),
399 		m_wait_mode(true),
400 		m_flip_y(flip_y),
401 		m_initial_width(10),
402 		m_initial_height(10)
403 	{
404 		std::strncpy(m_caption, "Anti-Grain Geometry", 256);
405 	}
406 
407 	//------------------------------------------------------------------------
~platform_support()408 	platform_support::~platform_support()
409 	{
410 		delete m_specific;
411 	}
412 
413 	//------------------------------------------------------------------------
caption(const char * cap)414 	void platform_support::caption(const char* cap)
415 	{
416 		std::strncpy(m_caption, cap, 256);
417 		if ( m_specific->m_window != 0 )
418 		{
419 			const char* ignore = reinterpret_cast<const char*>(-1);
420 			IIntuition->SetWindowAttr(m_specific->m_window,
421 				WA_Title, m_caption, sizeof(char*));
422 		}
423 	}
424 
425 	//------------------------------------------------------------------------
start_timer()426 	void platform_support::start_timer()
427 	{
428 		timeval tv;
429 		gettimeofday(&tv, 0);
430 		m_specific->m_start_time = tv.tv_secs + tv.tv_micro/1e6;
431 	}
432 
433 	//------------------------------------------------------------------------
elapsed_time() const434 	double platform_support::elapsed_time() const
435 	{
436 		timeval tv;
437 		gettimeofday(&tv, 0);
438 		double end_time = tv.tv_secs + tv.tv_micro/1e6;
439 
440 		double elasped_seconds = end_time - m_specific->m_start_time;
441 		double elasped_millis = elasped_seconds*1e3;
442 
443 		return elasped_millis;
444 	}
445 
446 	//------------------------------------------------------------------------
raw_display_handler()447 	void* platform_support::raw_display_handler()
448 	{
449 		return 0;	// Not available.
450 	}
451 
452 	//------------------------------------------------------------------------
message(const char * msg)453 	void platform_support::message(const char* msg)
454 	{
455 		APTR req = IIntuition->NewObject(RequesterClass, 0,
456 			REQ_TitleText, "Anti-Grain Geometry",
457 			REQ_Image, REQIMAGE_INFO,
458 			REQ_BodyText, msg,
459 			REQ_GadgetText, "_Ok",
460 			TAG_END);
461 		if ( req == 0 )
462 		{
463 			IDOS->Printf("Message: %s\n", msg);
464 			return;
465 		}
466 
467 		orRequest reqmsg;
468 		reqmsg.MethodID = RM_OPENREQ;
469 		reqmsg.or_Attrs = 0;
470 		reqmsg.or_Window = m_specific->m_window;
471 		reqmsg.or_Screen = 0;
472 
473 		IIntuition->IDoMethodA(reinterpret_cast<Object*>(req),
474 			reinterpret_cast<Msg>(&reqmsg));
475 		IIntuition->DisposeObject(req);
476 	}
477 
478 	//------------------------------------------------------------------------
init(unsigned width,unsigned height,unsigned flags)479 	bool platform_support::init(unsigned width, unsigned height,
480 		unsigned flags)
481 	{
482 		if( m_specific->m_ftype == RGBFB_NONE )
483 		{
484 			message("Unsupported mode requested.");
485 			return false;
486 		}
487 
488 		m_window_flags = flags;
489 
490 		m_specific->m_idcmp_hook = reinterpret_cast<Hook*>(
491 			IExec->AllocSysObjectTags(ASOT_HOOK,
492 				ASOHOOK_Entry, handle_idcmp,
493 				ASOHOOK_Data, this,
494 				TAG_END));
495 		if ( m_specific->m_idcmp_hook == 0 )
496 		{
497 			return false;
498 		}
499 
500 		m_specific->m_window_obj = IIntuition->NewObject(WindowClass, 0,
501 				WA_Title, m_caption,
502 				WA_AutoAdjustDClip, TRUE,
503 				WA_InnerWidth, width,
504 				WA_InnerHeight, height,
505 				WA_Activate, TRUE,
506 				WA_SmartRefresh, TRUE,
507 				WA_NoCareRefresh, TRUE,
508 				WA_CloseGadget, TRUE,
509 				WA_DepthGadget, TRUE,
510 				WA_SizeGadget, (flags & agg::window_resize) ? TRUE : FALSE,
511 				WA_DragBar, TRUE,
512 				WA_AutoAdjust, TRUE,
513 				WA_ReportMouse, TRUE,
514 				WA_RMBTrap, TRUE,
515 				WA_MouseQueue, 1,
516 				WA_IDCMP,
517 					IDCMP_NEWSIZE |
518 					IDCMP_MOUSEBUTTONS |
519 					IDCMP_MOUSEMOVE |
520 					IDCMP_RAWKEY |
521 					IDCMP_INTUITICKS,
522 				WINDOW_IDCMPHook, m_specific->m_idcmp_hook,
523 				WINDOW_IDCMPHookBits,
524 					IDCMP_MOUSEBUTTONS |
525 					IDCMP_MOUSEMOVE |
526 					IDCMP_RAWKEY,
527 				TAG_END);
528 		if ( m_specific->m_window_obj == 0 )
529 		{
530 			return false;
531 		}
532 
533 		Object* obj = reinterpret_cast<Object*>(m_specific->m_window_obj);
534 		m_specific->m_window =
535 			reinterpret_cast<Window*>(IIntuition->IDoMethod(obj, WM_OPEN));
536 		if ( m_specific->m_window == 0 )
537 		{
538 			return false;
539 		}
540 
541 		RGBFTYPE ftype = static_cast<RGBFTYPE>(IP96->p96GetBitMapAttr(
542 			m_specific->m_window->RPort->BitMap, P96BMA_RGBFORMAT));
543 
544 		switch ( ftype )
545 		{
546 		case RGBFB_A8R8G8B8:
547 		case RGBFB_B8G8R8A8:
548 		case RGBFB_R5G6B5PC:
549 			break;
550 		default:
551 			message("Unsupported screen mode.\n");
552 			return false;
553 		}
554 
555 		if ( !m_specific->make_bitmap() )
556 		{
557 			return false;
558 		}
559 
560 		m_initial_width = width;
561 		m_initial_height = height;
562 
563 		on_init();
564 		on_resize(width, height);
565 		force_redraw();
566 
567 		return true;
568 	}
569 
570 	//------------------------------------------------------------------------
run()571 	int platform_support::run()
572 	{
573 		uint32 window_mask = 0;
574 		IIntuition->GetAttr(WINDOW_SigMask, m_specific->m_window_obj,
575 			&window_mask);
576 		uint32 wait_mask = window_mask | SIGBREAKF_CTRL_C;
577 
578 		bool done = false;
579 
580 		while ( !done )
581 		{
582 			uint32 sig_mask = IExec->Wait(wait_mask);
583 			if ( sig_mask & SIGBREAKF_CTRL_C )
584 			{
585 				done = true;
586 			}
587 			else
588 			{
589 				done = m_specific->handle_input();
590 			}
591 		}
592 
593 		return 0;
594 	}
595 
596 	//------------------------------------------------------------------------
img_ext() const597 	const char* platform_support::img_ext() const
598 	{
599 		return ".bmp";
600 	}
601 
602 	//------------------------------------------------------------------------
full_file_name(const char * file_name)603 	const char* platform_support::full_file_name(const char* file_name)
604 	{
605 		return file_name;
606 	}
607 
608 	//------------------------------------------------------------------------
load_img(unsigned idx,const char * file)609 	bool platform_support::load_img(unsigned idx, const char* file)
610 	{
611 		if ( idx < max_images )
612 		{
613 			static char fn[1024];
614 			std::strncpy(fn, file, 1024);
615 			int len = std::strlen(fn);
616 			if ( len < 4 || std::strcmp(fn + len - 4, ".bmp") != 0 )
617 			{
618 				std::strncat(fn, ".bmp", 1024);
619 			}
620 
621 			return m_specific->load_img(fn, idx, &m_rbuf_img[idx]);
622 		}
623 
624 		return false;
625 	}
626 
627 	//------------------------------------------------------------------------
save_img(unsigned idx,const char * file)628 	bool platform_support::save_img(unsigned idx, const char* file)
629 	{
630 		message("Not supported");
631 		return false;
632 	}
633 
634 	//------------------------------------------------------------------------
create_img(unsigned idx,unsigned width,unsigned height)635 	bool platform_support::create_img(unsigned idx, unsigned width,
636 		unsigned height)
637 	{
638 		if ( idx < max_images )
639 		{
640 			if ( width == 0 )
641 			{
642 				width = m_specific->m_width;
643 			}
644 
645 			if ( height == 0 )
646 			{
647 				height = m_specific->m_height;
648 			}
649 
650 			return m_specific->create_img(idx, &m_rbuf_img[idx], width,
651 				height);
652 		}
653 
654 		return false;
655 	}
656 
657 	//------------------------------------------------------------------------
force_redraw()658 	void platform_support::force_redraw()
659 	{
660 		on_draw();
661 		update_window();
662 	}
663 
664 	//------------------------------------------------------------------------
update_window()665 	void platform_support::update_window()
666 	{
667 		// Note this function does automatic color conversion.
668 		IGraphics->BltBitMapRastPort(m_specific->m_bitmap, 0, 0,
669 			m_specific->m_window->RPort, m_specific->m_window->BorderLeft,
670 			m_specific->m_window->BorderTop, m_specific->m_width,
671 			m_specific->m_height, ABC|ABNC);
672 	}
673 
674 	//------------------------------------------------------------------------
on_init()675 	void platform_support::on_init() {}
on_resize(int sx,int sy)676 	void platform_support::on_resize(int sx, int sy) {}
on_idle()677 	void platform_support::on_idle() {}
on_mouse_move(int x,int y,unsigned flags)678 	void platform_support::on_mouse_move(int x, int y, unsigned flags) {}
on_mouse_button_down(int x,int y,unsigned flags)679 	void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {}
on_mouse_button_up(int x,int y,unsigned flags)680 	void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {}
on_key(int x,int y,unsigned key,unsigned flags)681 	void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {}
on_ctrl_change()682 	void platform_support::on_ctrl_change() {}
on_draw()683 	void platform_support::on_draw() {}
on_post_draw(void * raw_handler)684 	void platform_support::on_post_draw(void* raw_handler) {}
685 
686 	//------------------------------------------------------------------------
handle_idcmp(Hook * hook,APTR obj,IntuiMessage * msg)687 	void handle_idcmp(Hook* hook, APTR obj, IntuiMessage* msg)
688 	{
689 		platform_support* app =
690 			reinterpret_cast<platform_support*>(hook->h_Data);
691 		Window* window = app->m_specific->m_window;
692 
693 		int16 x = msg->MouseX - window->BorderLeft;
694 
695 		int16 y = 0;
696 		if ( app->flip_y() )
697 		{
698 			y = window->Height - window->BorderBottom - msg->MouseY;
699 		}
700 		else
701 		{
702 			y = msg->MouseY - window->BorderTop;
703 		}
704 
705 		switch ( msg->Class )
706 		{
707 		case IDCMP_MOUSEBUTTONS:
708 			if ( msg->Code & IECODE_UP_PREFIX )
709 			{
710 				if ( msg->Code == SELECTUP )
711 				{
712 					app->m_specific->m_input_flags = mouse_left;
713 					app->m_specific->m_dragging = false;
714 				}
715 				else if ( msg->Code == MENUUP )
716 				{
717 					app->m_specific->m_input_flags = mouse_right;
718 					app->m_specific->m_dragging = false;
719 				}
720 				else
721 				{
722 					return;
723 				}
724 
725 
726 				if ( app->m_ctrls.on_mouse_button_up(x, y) )
727 				{
728 					app->on_ctrl_change();
729 					app->force_redraw();
730 				}
731 
732 				app->on_mouse_button_up(x, y, app->m_specific->m_input_flags);
733 			}
734 			else
735 			{
736 				if ( msg->Code == SELECTDOWN )
737 				{
738 					app->m_specific->m_input_flags = mouse_left;
739 					app->m_specific->m_dragging = true;
740 				}
741 				else if ( msg->Code == MENUDOWN )
742 				{
743 					app->m_specific->m_input_flags = mouse_right;
744 					app->m_specific->m_dragging = true;
745 				}
746 				else
747 				{
748 					return;
749 				}
750 
751 				app->m_ctrls.set_cur(x, y);
752 				if ( app->m_ctrls.on_mouse_button_down(x, y) )
753 				{
754 					app->on_ctrl_change();
755 					app->force_redraw();
756 				}
757 				else
758 				{
759 					if ( app->m_ctrls.in_rect(x, y) )
760 					{
761 						if ( app->m_ctrls.set_cur(x, y) )
762 						{
763 							app->on_ctrl_change();
764 							app->force_redraw();
765 						}
766 					}
767 					else
768 					{
769 						app->on_mouse_button_down(x, y,
770 							app->m_specific->m_input_flags);
771 					}
772 				}
773 			}
774 			break;
775 		case IDCMP_MOUSEMOVE:
776 			if ( app->m_specific->m_dragging )  {
777 				if ( app->m_ctrls.on_mouse_move(x, y,
778 					 app->m_specific->m_input_flags & mouse_left) != 0 )
779 				{
780 					app->on_ctrl_change();
781 					app->force_redraw();
782 				}
783 				else
784 				{
785 					if ( !app->m_ctrls.in_rect(x, y) )
786 					{
787 						app->on_mouse_move(x, y,
788 							app->m_specific->m_input_flags);
789 					}
790 				}
791 			}
792 			break;
793 		case IDCMP_RAWKEY:
794 		{
795 			static InputEvent ie = { 0 };
796 			ie.ie_Class = IECLASS_RAWKEY;
797 			ie.ie_Code = msg->Code;
798 			ie.ie_Qualifier = msg->Qualifier;
799 
800 			static const unsigned BUF_SIZE = 16;
801 			static char key_buf[BUF_SIZE];
802 			int16 num_chars = IKeymap->MapRawKey(&ie, key_buf, BUF_SIZE, 0);
803 
804 			uint32 code = 0x00000000;
805 			switch ( num_chars )
806 			{
807 			case 1:
808 				code = key_buf[0];
809 				break;
810 			case 2:
811 				code = key_buf[0]<<8 | key_buf[1];
812 				break;
813 			case 3:
814 				code = key_buf[0]<<16 | key_buf[1]<<8 | key_buf[2];
815 				break;
816 			}
817 
818 			uint16 key_code = 0;
819 
820 			if ( num_chars == 1 )
821 			{
822 				if ( code >= IECODE_ASCII_FIRST && code <= IECODE_ASCII_LAST )
823 				{
824 					key_code = code;
825 				}
826 			}
827 
828 			if ( key_code == 0 )
829 			{
830 				switch ( code )
831 				{
832 				case 0x00000008: key_code = key_backspace;	break;
833 				case 0x00000009: key_code = key_tab;		break;
834 				case 0x0000000D: key_code = key_return;		break;
835 				case 0x0000001B: key_code = key_escape;		break;
836 				case 0x0000007F: key_code = key_delete;		break;
837 				case 0x00009B41:
838 				case 0x00009B54: key_code = key_up;			break;
839 				case 0x00009B42:
840 				case 0x00009B53: key_code = key_down;		break;
841 				case 0x00009B43:
842 				case 0x009B2040: key_code = key_right;		break;
843 				case 0x00009B44:
844 				case 0x009B2041: key_code = key_left;		break;
845 				case 0x009B307E: key_code = key_f1;			break;
846 				case 0x009B317E: key_code = key_f2;			break;
847 				case 0x009B327E: key_code = key_f3;			break;
848 				case 0x009B337E: key_code = key_f4;			break;
849 				case 0x009B347E: key_code = key_f5;			break;
850 				case 0x009B357E: key_code = key_f6;			break;
851 				case 0x009B367E: key_code = key_f7;			break;
852 				case 0x009B377E: key_code = key_f8;			break;
853 				case 0x009B387E: key_code = key_f9;			break;
854 				case 0x009B397E: key_code = key_f10;		break;
855 				case 0x009B3F7E: key_code = key_scrollock;	break;
856 				}
857 			}
858 
859 			if ( ie.ie_Code & IECODE_UP_PREFIX )
860 			{
861 				if ( app->m_specific->m_last_key != 0 )
862 				{
863 					bool left = (key_code == key_left) ? true : false;
864 					bool right = (key_code == key_right) ? true : false;
865 					bool down = (key_code == key_down) ? true : false;
866 					bool up = (key_code == key_up) ? true : false;
867 
868 					if ( app->m_ctrls.on_arrow_keys(left, right, down, up) )
869 					{
870 						app->on_ctrl_change();
871 						app->force_redraw();
872 					}
873 					else
874 					{
875 						app->on_key(x, y, app->m_specific->m_last_key, 0);
876 					}
877 
878 					app->m_specific->m_last_key = 0;
879 				}
880 			}
881 			else
882 			{
883 				app->m_specific->m_last_key = key_code;
884 			}
885 			break;
886 		}
887 		default:
888 			break;
889 		}
890 	}
891 }
892 
893 //----------------------------------------------------------------------------
894 int agg_main(int argc, char* argv[]);
895 bool open_libs();
896 void close_libs();
897 
898 //----------------------------------------------------------------------------
open_libs()899 bool open_libs()
900 {
901 	DataTypesBase = IExec->OpenLibrary("datatypes.library", 51);
902 	GraphicsBase = IExec->OpenLibrary("graphics.library", 51);
903 	IntuitionBase = IExec->OpenLibrary("intuition.library", 51);
904 	KeymapBase = IExec->OpenLibrary("keymap.library", 51);
905 	P96Base = IExec->OpenLibrary("Picasso96API.library", 2);
906 
907 	IDataTypes = reinterpret_cast<DataTypesIFace*>(
908 		IExec->GetInterface(DataTypesBase, "main", 1, 0));
909 	IGraphics = reinterpret_cast<GraphicsIFace*>(
910 		IExec->GetInterface(GraphicsBase, "main", 1, 0));
911 	IIntuition = reinterpret_cast<IntuitionIFace*>(
912 		IExec->GetInterface(IntuitionBase, "main", 1, 0));
913 	IKeymap = reinterpret_cast<KeymapIFace*>(
914 		IExec->GetInterface(KeymapBase, "main", 1, 0));
915 	IP96 = reinterpret_cast<P96IFace*>(
916 		IExec->GetInterface(P96Base, "main", 1, 0));
917 
918 	if ( IDataTypes == 0 ||
919 		 IGraphics == 0 ||
920 		 IIntuition == 0 ||
921 		 IKeymap == 0 ||
922 		 IP96 == 0 )
923 	{
924 		close_libs();
925 		return false;
926 	}
927 	else
928 	{
929 		return true;
930 	}
931 }
932 
933 //----------------------------------------------------------------------------
close_libs()934 void close_libs()
935 {
936 	IExec->DropInterface(reinterpret_cast<Interface*>(IP96));
937 	IExec->DropInterface(reinterpret_cast<Interface*>(IKeymap));
938 	IExec->DropInterface(reinterpret_cast<Interface*>(IIntuition));
939 	IExec->DropInterface(reinterpret_cast<Interface*>(IGraphics));
940 	IExec->DropInterface(reinterpret_cast<Interface*>(IDataTypes));
941 
942 	IExec->CloseLibrary(P96Base);
943 	IExec->CloseLibrary(KeymapBase);
944 	IExec->CloseLibrary(IntuitionBase);
945 	IExec->CloseLibrary(GraphicsBase);
946 	IExec->CloseLibrary(DataTypesBase);
947 }
948 
949 //----------------------------------------------------------------------------
main(int argc,char * argv[])950 int main(int argc, char* argv[])
951 {
952 	if ( !open_libs() )  {
953 		IDOS->Printf("Can't open libraries.\n");
954 		return -1;
955 	}
956 
957 	ClassLibrary* requester =
958 		IIntuition->OpenClass("requester.class", 51, &RequesterClass);
959 	ClassLibrary* window =
960 		IIntuition->OpenClass("window.class", 51, &WindowClass);
961 	if ( requester == 0 || window == 0 )
962 	{
963 		IDOS->Printf("Can't open classes.\n");
964 		IIntuition->CloseClass(requester);
965 		IIntuition->CloseClass(window);
966 		close_libs();
967 		return -1;
968 	}
969 
970 	int rc = agg_main(argc, argv);
971 
972 	IIntuition->CloseClass(window);
973 	IIntuition->CloseClass(requester);
974 	close_libs();
975 
976 	return rc;
977 }
978