1 #include "cfg.h"
2 
3 #ifdef GRDRV_ATHEOS
4 
5 #include <atheos/threads.h>
6 #include <gui/view.h>
7 #include <gui/window.h>
8 #include <gui/desktop.h>
9 #include <gui/bitmap.h>
10 #include <util/locker.h>
11 #include <util/application.h>
12 #include <string>
13 
14 using namespace std;
15 
16 extern "C" {
17 #include "links.h"
18 }
19 
20 #define WINDOW_TITLE_SIZE	16
21 #define TOP_PANEL_SIZE		32
22 #define NEW_WINDOW_X_ADD	16
23 #define NEW_WINDOW_Y_ADD	16
24 #define NEW_WINDOW_X_MIN	8
25 #define NEW_WINDOW_Y_MIN	8
26 
27 #ifdef debug
28 #undef debug
29 #endif
30 #ifdef debug2
31 #undef debug2
32 #endif
33 #define debug(x)
34 #define debug2(x)
35 
36 extern struct graphics_driver atheos_driver;
37 
38 using namespace os;
39 
40 class LinksApplication : public Application {
41 	public:
LinksApplication()42 	LinksApplication():Application("application/x-vnd.links"){}
OkToQuit()43 	virtual bool OkToQuit(){return false;}
44 };
45 
46 class LinksView;
47 
48 class LinksWindow : public Window {
49 	public:
50 	LinksWindow(Rect r);
51 	~LinksWindow();
52 	virtual void FrameSized(const Point &d);
53 	virtual bool OkToQuit();
54 	int resized;
55 	LinksView *view;
56 };
57 
58 class LinksView : public View {
59 	public:
60 	LinksView(LinksWindow *w);
61 	~LinksView();
62 	virtual void Paint(const Rect &r);
63 	virtual void MouseDown(const Point &p, uint32 b);
64 	virtual void MouseUp(const Point &p, uint32 b, Message *m);
65 	virtual void MouseMove(const Point &p, int c, uint32 b, Message *m);
66 	virtual void KeyDown(const char *s, const char *rs, uint32 q);
67 	virtual void WheelMoved(const Point &d);
68 	LinksWindow *win;
69 	struct graphics_device *dev;
70 	void d_flush();
71 	int flushing;
72 	int last_x, last_y;
73 };
74 
75 #define lv(dev) ((LinksView *)(dev)->driver_data)
76 
77 #define lock_dev(dev) do { if (lv(dev)->win->Lock()) return; } while (0)
78 #define lock_dev0(dev) do { if (lv(dev)->win->Lock()) return 0; } while (0)
79 #define unlock_dev(dev) do { lv(dev)->win->Unlock(); } while (0)
80 
81 static LinksApplication *ath_links_app;
82 static Locker *ath_lock = NULL;
83 
84 static int msg_pipe[2];
85 
86 static thread_id ath_app_thread_id;
87 
88 #define rpipe (msg_pipe[0])
89 #define wpipe (msg_pipe[1])
90 
91 #define small_color (sizeof(Color32_s) <= sizeof(long))
92 #define get_color32(c, rgb) Color32_s c((rgb >> 16) & 255, (rgb >> 8) & 255, rgb & 255, 255)
93 
94 static color_space ath_cs_desktop, ath_cs_bmp;
95 
96 static int ath_x_size, ath_y_size;
97 static int ath_y_panel;
98 
99 static int ath_win_x_size, ath_win_y_size;
100 static int ath_win_x_pos, ath_win_y_pos;
101 
LinksWindow(Rect r)102 LinksWindow::LinksWindow(Rect r):Window(r, "links_wnd", "Links")
103 {
104 	debug2("LINKSWINDOW\n");
105 	resized = 0;
106 	view = NULL;
107 }
108 
~LinksWindow()109 LinksWindow::~LinksWindow()
110 {
111 	view = NULL;
112 	debug2("~LINKSWINDOW\n");
113 }
114 
FrameSized(const Point & d)115 void LinksWindow::FrameSized(const Point &d)
116 {
117 	resized = 1;
118 }
119 
OkToQuit()120 bool LinksWindow::OkToQuit()
121 {
122 	ath_lock->Lock();
123 	Lock();
124 	if (view) if (view->dev) view->dev->keyboard_handler(view->dev, KBD_CTRL_C, 0);
125 	Unlock();
126 	ath_lock->Unlock();
127 	write(wpipe, " ", 1);
128 	/*debug2("key: :%s: :%s: %d %d\n", s, rs, q, c);*/
129 	return false;
130 }
131 
do_flush(void * p_dev)132 static void do_flush(void *p_dev)
133 {
134 	struct graphics_device *dev = (struct graphics_device *)p_dev;
135 	LinksView *v = lv(dev);
136 	v->win->Lock();
137 	v->win->Flush();
138 	v->win->Unlock();
139 	v->flushing = 0;
140 }
141 
LinksView(LinksWindow * w)142 LinksView::LinksView(LinksWindow *w):View(w->GetBounds(), "Links", CF_FOLLOW_ALL, WID_WILL_DRAW | WID_FULL_UPDATE_ON_RESIZE)
143 {
144 	debug2("LINKSVIEW\n");
145 	(win = w)->AddChild(this);
146 	w->SetFocusChild(this);
147 	w->view = this;
148 	flushing = 0;
149 	last_x = last_y = 0;
150 }
151 
~LinksView()152 LinksView::~LinksView()
153 {
154 	win->view = NULL;
155 	debug2("~LINKSVIEW\n");
156 }
157 
d_flush()158 void LinksView::d_flush()
159 {
160 	if (flushing) return;
161 	register_bottom_half(do_flush, this->dev);
162 	flushing = 1;
163 }
164 
165 #undef select
166 
ath_select(int n,fd_set * r,fd_set * w,fd_set * e,struct timeval * t)167 int ath_select(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
168 {
169 	int v;
170 	if (ath_lock) ath_lock->Unlock();
171 	v = select(n, r, w, e, t);
172 	if (ath_lock) {
173 		ath_lock->Lock();
174 		check_bottom_halves();
175 	}
176 	return v;
177 }
178 
ath_get_event(void * dummy)179 static void ath_get_event(void *dummy)
180 {
181 	char dummy_buffer[256];
182 	read(rpipe, dummy_buffer, 256);
183 	debug2("GETE\n");
184 }
185 
ath_get_size(struct graphics_device * dev)186 static void ath_get_size(struct graphics_device *dev)
187 {
188 	Rect r = lv(dev)->GetBounds();
189 	dev->size.x1 = dev->size.y1 = 0;
190 	dev->size.x2 = (int)r.Width() + 1;
191 	dev->size.y2 = (int)r.Height() + 1;
192 }
193 
Paint(const Rect & r)194 void LinksView::Paint(const Rect &r)
195 {
196 	struct rect rr;
197 	win->Unlock();
198 	ath_lock->Lock();
199 	win->Lock();
200 	rr.x1 = (int)r.left;
201 	rr.x2 = (int)r.right + 1;
202 	rr.y1 = (int)r.top;
203 	rr.y2 = (int)r.bottom + 1;
204 	/*debug2("paint: %d %d %d %d\n", rr.x1, rr.x2, rr.y1, rr.y2);*/
205 	if (dev) {
206 		if (!win->resized) dev->redraw_handler(dev, &rr);
207 		else {
208 			ath_get_size(dev);
209 			win->resized = 0;
210 			dev->resize_handler(dev);
211 		}
212 	}
213 	check_bottom_halves();
214 	ath_lock->Unlock();
215 	write(wpipe, " ", 1);
216 }
217 
218 
MouseDown(const Point & p,uint32 b)219 void LinksView::MouseDown(const Point &p, uint32 b)
220 {
221 	win->Unlock();
222 	ath_lock->Lock();
223 	win->Lock();
224 	if (dev) dev->mouse_handler(dev, last_x = (int)p.x, last_y = (int)p.y, B_DOWN | (b == 2 ? B_RIGHT : b == 3 ? B_MIDDLE : B_LEFT));
225 	ath_lock->Unlock();
226 	write(wpipe, " ", 1);
227 }
228 
MouseUp(const Point & p,uint32 b,Message * m)229 void LinksView::MouseUp(const Point &p, uint32 b, Message *m)
230 {
231 	win->Unlock();
232 	ath_lock->Lock();
233 	win->Lock();
234 	if (dev) dev->mouse_handler(dev, last_x = (int)p.x, last_y = (int)p.y, B_UP | (b == 2 ? B_RIGHT : b == 3 ? B_MIDDLE : B_LEFT));
235 	ath_lock->Unlock();
236 	write(wpipe, " ", 1);
237 }
238 
MouseMove(const Point & p,int c,uint32 b,Message * m)239 void LinksView::MouseMove(const Point &p, int c, uint32 b, Message *m)
240 {
241 	win->Unlock();
242 	ath_lock->Lock();
243 	win->Lock();
244 	if (dev) dev->mouse_handler(dev, last_x = (int)p.x, last_y = (int)p.y, !b ? B_MOVE : B_DRAG | (b & 1 ? B_LEFT : b & 2 ? B_RIGHT : b & 4 ? B_MIDDLE : B_LEFT));
245 	ath_lock->Unlock();
246 	write(wpipe, " ", 1);
247 }
248 
WheelMoved(const Point & d)249 void LinksView::WheelMoved(const Point &d)
250 {
251 	win->Unlock();
252 	ath_lock->Lock();
253 	win->Lock();
254 	if (d.y) if (dev) dev->mouse_handler(dev, last_x, last_y, B_MOVE | (d.y > 0 ? B_WHEELDOWN : B_WHEELUP));
255 	if (d.x) if (dev) dev->mouse_handler(dev, last_x, last_y, B_MOVE | (d.x < 0 ? B_WHEELLEFT : B_WHEELRIGHT));
256 	ath_lock->Unlock();
257 	write(wpipe, " ", 1);
258 }
259 
KeyDown(const char * s,const char * rs,uint32 q)260 void LinksView::KeyDown(const char *s, const char *rs, uint32 q)
261 {
262 	int c;
263 	unsigned char *ss = q & (QUAL_CTRL | QUAL_ALT) ? (unsigned char *)rs : (unsigned char *)s;
264 	win->Unlock();
265 	ath_lock->Lock();
266 	win->Lock();
267 	GET_UTF_8(ss, c);
268 	switch (c) {
269 		case VK_BACKSPACE: c = KBD_BS; break;
270 		case VK_ENTER: c = KBD_ENTER; break;
271 		case VK_SPACE: c = ' '; break;
272 		case VK_TAB: c = KBD_TAB; break;
273 		case VK_ESCAPE: c = KBD_ESC; break;
274 		case VK_LEFT_ARROW: c = KBD_LEFT; break;
275 		case VK_RIGHT_ARROW: c = KBD_RIGHT; break;
276 		case VK_UP_ARROW: c = KBD_UP; break;
277 		case VK_DOWN_ARROW: c = KBD_DOWN; break;
278 		case VK_INSERT: c = KBD_INS; break;
279 		case VK_DELETE: c = KBD_DEL; break;
280 		case VK_HOME: c = KBD_HOME; break;
281 		case VK_END: c = KBD_END; break;
282 		case VK_PAGE_UP: c = KBD_PAGE_UP; break;
283 		case VK_PAGE_DOWN: c = KBD_PAGE_DOWN; break;
284 		default: if (c < 32) c = 0;
285 			 else q &= ~QUAL_SHIFT;
286 			 break;
287 	}
288 	if (c) if (dev) dev->keyboard_handler(dev, c, (q & QUAL_SHIFT ? KBD_SHIFT : 0) | (q & QUAL_CTRL ? KBD_CTRL : 0) | (q & QUAL_ALT ? KBD_ALT : 0));
289 	ath_lock->Unlock();
290 	write(wpipe, " ", 1);
291 	/*debug2("key: :%s: :%s: %d %d\n", s, rs, q, c);*/
292 }
293 
ath_app_thread(void * p)294 static uint32 ath_app_thread(void *p)
295 {
296 	ath_links_app->Run();
297 	delete ath_links_app;
298 	return 0;
299 }
300 
ath_init_driver(unsigned char * param,unsigned char * display)301 static unsigned char *ath_init_driver(unsigned char *param, unsigned char *display)
302 {
303 	Desktop *d;
304 	ath_links_app = new LinksApplication();
305 	if (!ath_links_app) {
306 		return stracpy((unsigned char *)"Unable to allocate Application object.\n");
307 	}
308 	ath_lock = new Locker("links_sem", false, false);
309 	if (!ath_lock || ath_lock->Lock()) {
310 		delete ath_links_app;
311 		return stracpy((unsigned char *)"Could not create lock.\n");
312 	}
313 	if (c_pipe(msg_pipe)) {
314 		delete ath_lock; ath_lock = NULL;
315 		delete ath_links_app;
316 		return stracpy((unsigned char *)"Could not create pipe.\n");
317 	}
318 	set_nonblock(rpipe);
319 	set_nonblock(wpipe);
320 	set_handlers(rpipe, ath_get_event, NULL, NULL);
321 	ath_app_thread_id = spawn_thread("links_app", (void *)ath_app_thread, 0, 0, NULL);
322 	if (ath_app_thread_id == -1) {
323 		int r;
324 		EINTRLOOP(r, close(rpipe));
325 		EINTRLOOP(r, close(wpipe));
326 		delete ath_lock; ath_lock = NULL;
327 		delete ath_links_app;
328 		return stracpy((unsigned char *)"Could not spawn thread.\n");
329 	}
330 	resume_thread(ath_app_thread_id);
331 	if ((d = new Desktop)) {
332 		ath_cs_desktop = d->GetColorSpace();
333 		ath_x_size = d->GetResolution().x;
334 		ath_y_size = d->GetResolution().y;
335 		delete d;
336 	} else {
337 		ath_cs_desktop = CS_NO_COLOR_SPACE;
338 		ath_x_size = 640;
339 		ath_y_size = 480;
340 	}
341 	ath_y_panel = WINDOW_TITLE_SIZE;
342 #ifdef __SYLLABLE__
343 	ath_y_panel += TOP_PANEL_SIZE;
344 #endif
345 	if (ath_y_panel > ath_y_size) ath_y_panel = 0;
346 	ath_win_y_size = (ath_y_size - ath_y_panel) * 9 / 10;
347 	ath_win_x_size = ath_win_y_size;
348 	/*
349 	debug2("%d %d\n", ath_x_size, ath_y_size);
350 	debug2("%d %d\n", ath_win_x_size, ath_win_y_size);
351 	*/
352 	ath_win_y_pos = (ath_y_size - ath_y_panel - ath_win_y_size) / 2 + ath_y_panel;
353 	ath_win_x_pos = ath_x_size - ath_win_x_size - ath_win_y_pos;
354 	if (/*ath_cs_desktop == CS_RGB32 ||*/ ath_cs_desktop == CS_RGB24 || ath_cs_desktop == CS_RGB16 || ath_cs_desktop == CS_RGB15)
355 		ath_cs_bmp = ath_cs_desktop;
356 	else if (ath_cs_desktop == CS_RGB32 || ath_cs_desktop == CS_RGBA32) ath_cs_bmp = CS_RGB24;
357 	else ath_cs_bmp = CS_RGB15;
358 	switch (ath_cs_bmp) {
359 		case CS_RGB24:
360 			atheos_driver.depth = 0xc3;
361 			break;
362 		case CS_RGB16:
363 			atheos_driver.depth = 0x82;
364 			break;
365 		case CS_RGB15:
366 			atheos_driver.depth = 0x7a;
367 			break;
368 		default:
369 			internal_error("unknown depth");
370 	}
371 	return NULL;
372 }
373 
ath_shutdown_driver()374 static void ath_shutdown_driver()
375 {
376 	int r;
377 	debug((unsigned char *)"D");
378 	set_handlers(rpipe, NULL, NULL, NULL);
379 	EINTRLOOP(r, close(rpipe));
380 	EINTRLOOP(r, close(wpipe));
381 	ath_lock->Unlock();
382 	debug((unsigned char *)"DD");
383 	ath_links_app->PostMessage(M_TERMINATE);
384 	debug((unsigned char *)"E");
385 	/*delete ath_lock; ath_lock = NULL;*/
386 	debug((unsigned char *)"F");
387 }
388 
ath_after_fork()389 static void ath_after_fork()
390 {
391 	int r;
392 	EINTRLOOP(r, close(rpipe));
393 	EINTRLOOP(r, close(wpipe));
394 }
395 
ath_init_device()396 static struct graphics_device *ath_init_device()
397 {
398 	LinksView *view;
399 	LinksWindow *win;
400 	struct graphics_device *dev = (struct graphics_device *)mem_calloc(sizeof(struct graphics_device));
401 	if (!dev) return NULL;
402 	debug((unsigned char *)"1");
403 	retry:
404 	win = new LinksWindow(Rect(ath_win_x_pos, ath_win_y_pos, ath_win_x_pos + ath_win_x_size, ath_win_y_pos + ath_win_y_size));
405 	debug((unsigned char *)"2");
406 	if (!win) {
407 		if (out_of_memory(0, NULL, 0))
408 			goto retry;
409 		mem_free(dev);
410 		return NULL;
411 	}
412 	debug((unsigned char *)"3");
413 	retry2:
414 	view = new LinksView(win);
415 	if (!view) {
416 		if (out_of_memory(0, NULL, 0))
417 			goto retry2;
418 		delete win;
419 		mem_free(dev);
420 		return NULL;
421 	}
422 	view->dev = dev;
423 	dev->driver_data = view;
424 	ath_get_size(dev);
425 	memcpy(&dev->clip, &dev->size, sizeof(struct rect));
426 	debug((unsigned char *)"4");
427 	win->Show();
428 	win->MakeFocus();
429 	debug((unsigned char *)"5");
430 
431 	ath_win_x_pos += NEW_WINDOW_X_ADD;
432 	ath_win_y_pos += NEW_WINDOW_Y_ADD;
433 	if (ath_win_x_pos + ath_win_x_size > ath_x_size - NEW_WINDOW_X_MIN)
434 		ath_win_x_pos = NEW_WINDOW_X_MIN;
435 	if (ath_win_y_pos + ath_win_y_size > ath_y_size - NEW_WINDOW_Y_MIN)
436 		ath_win_y_pos = ath_y_panel + NEW_WINDOW_Y_MIN;
437 
438 	return dev;
439 }
440 
ath_shutdown_device(struct graphics_device * dev)441 static void ath_shutdown_device(struct graphics_device *dev)
442 {
443 	LinksWindow *win = lv(dev)->win;
444 	unregister_bottom_half(do_flush, dev);
445 	lv(dev)->dev = NULL;
446 	win->PostMessage(M_TERMINATE);
447 	mem_free(dev);
448 }
449 
ath_set_title(struct graphics_device * dev,unsigned char * title)450 static void ath_set_title(struct graphics_device *dev, unsigned char *title)
451 {
452 	LinksWindow *win = lv(dev)->win;
453 	lock_dev(dev);
454 	win->SetTitle(string((char *)title));
455 	lv(dev)->d_flush();
456 	unlock_dev(dev);
457 }
458 
ath_get_empty_bitmap(struct bitmap * bmp)459 static int ath_get_empty_bitmap(struct bitmap *bmp)
460 {
461 	debug2("bmp\n");
462 	Bitmap *b;
463 	retry:
464 	b = new Bitmap(bmp->x, bmp->y, ath_cs_bmp, Bitmap::SHARE_FRAMEBUFFER);
465 	if (!b) {
466 		if (out_of_memory(0, NULL, 0))
467 			goto retry;
468 		bmp->data = NULL;
469 		bmp->flags = NULL;
470 		return -1;
471 	}
472 	bmp->data = b->LockRaster();
473 	bmp->skip = b->GetBytesPerRow();
474 	bmp->flags = b;
475 	return 0;
476 }
477 
ath_register_bitmap(struct bitmap * bmp)478 static void ath_register_bitmap(struct bitmap *bmp)
479 {
480 	Bitmap *b = (Bitmap *)bmp->flags;
481 	if (!b) return;
482 	b->UnlockRaster();
483 }
484 
ath_prepare_strip(struct bitmap * bmp,int top,int lines)485 static void *ath_prepare_strip(struct bitmap *bmp, int top, int lines)
486 {
487 	debug2("preps\n");
488 	Bitmap *b = (Bitmap *)bmp->flags;
489 	if (!b) return NULL;
490 	bmp->data = b->LockRaster();
491 	bmp->skip = b->GetBytesPerRow();
492 	return ((char *)bmp->data) + bmp->skip * top;
493 }
494 
ath_commit_strip(struct bitmap * bmp,int top,int lines)495 static void ath_commit_strip(struct bitmap *bmp, int top, int lines)
496 {
497 	Bitmap *b = (Bitmap *)bmp->flags;
498 	if (!b) return;
499 	b->UnlockRaster();
500 }
501 
ath_unregister_bitmap(struct bitmap * bmp)502 static void ath_unregister_bitmap(struct bitmap *bmp)
503 {
504 	debug2("unb\n");
505 	Bitmap *b = (Bitmap *)bmp->flags;
506 	if (!b) return;
507 	delete b;
508 }
509 
ath_draw_bitmap(struct graphics_device * dev,struct bitmap * bmp,int x,int y)510 static void ath_draw_bitmap(struct graphics_device *dev, struct bitmap *bmp, int x, int y)
511 {
512 	debug2("drawb\n");
513 	Bitmap *b = (Bitmap *)bmp->flags;
514 	if (!b) return;
515 	CLIP_DRAW_BITMAP
516 	lock_dev(dev);
517 	lv(dev)->DrawBitmap(b, b->GetBounds(), Rect(x, y, x + bmp->x - 1, y + bmp->y - 1));
518 	lv(dev)->d_flush();
519 	unlock_dev(dev);
520 }
521 
ath_get_color(int rgb)522 static long ath_get_color(int rgb)
523 {
524 	if (small_color) {
525 		get_color32(c, rgb);
526 		return *(long *)(void *)&c;
527 	} else return rgb & 0xffffff;
528 }
529 
ath_fill_area(struct graphics_device * dev,int x1,int y1,int x2,int y2,long color)530 static void ath_fill_area(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color)
531 {
532 	debug2("fill\n");
533 	CLIP_FILL_AREA
534 	lock_dev(dev);
535 	if (small_color)
536 		lv(dev)->FillRect(Rect(x1, y1, x2 - 1, y2 - 1), *(Color32_s *)(void *)&color);
537 	else
538 		lv(dev)->FillRect(Rect(x1, y1, x2 - 1, y2 - 1), get_color32(, color));
539 	lv(dev)->d_flush();
540 	unlock_dev(dev);
541 }
542 
ath_draw_hline(struct graphics_device * dev,int x1,int y,int x2,long color)543 static void ath_draw_hline(struct graphics_device *dev, int x1, int y, int x2, long color)
544 {
545 	debug2("hline\n");
546 	CLIP_DRAW_HLINE
547 	lock_dev(dev);
548 	if (small_color)
549 		lv(dev)->SetFgColor(*(Color32_s *)(void *)&color);
550 	else
551 		lv(dev)->SetFgColor(get_color32(, color));
552 	lv(dev)->DrawLine(Point(IPoint(x1, y)), Point(IPoint(x2 - 1, y)));
553 	lv(dev)->d_flush();
554 	unlock_dev(dev);
555 }
556 
ath_draw_vline(struct graphics_device * dev,int x,int y1,int y2,long color)557 static void ath_draw_vline(struct graphics_device *dev, int x, int y1, int y2, long color)
558 {
559 	debug2("vline\n");
560 	CLIP_DRAW_VLINE
561 	lock_dev(dev);
562 	if (small_color)
563 		lv(dev)->SetFgColor(*(Color32_s *)(void *)&color);
564 	else
565 		lv(dev)->SetFgColor(get_color32(, color));
566 	lv(dev)->DrawLine(Point(IPoint(x, y1)), Point(IPoint(x, y2 - 1)));
567 	lv(dev)->d_flush();
568 	unlock_dev(dev);
569 }
570 
ath_scroll(struct graphics_device * dev,struct rect_set ** ignore,int scx,int scy)571 static int ath_scroll(struct graphics_device *dev, struct rect_set **ignore, int scx, int scy)
572 {
573 	debug2("hscroll\n");
574 	lock_dev0(dev);
575 	lv(dev)->ScrollRect(
576 		Rect(	dev->clip.x1 - (scx < 0 ? scx : 0),
577 			dev->clip.y1 - (scy < 0 ? scy : 0),
578 			dev->clip.x2 - (scx >= 0 ? scx : 0) - 1,
579 			dev->clip.y2 - (scy >= 0 ? scy : 0) - 1),
580 		Rect(	dev->clip.x1 + (scx >= 0 ? scx : 0),
581 			dev->clip.y1 + (scy >= 0 ? scy : 0),
582 			dev->clip.x2 + (scx < 0 ? scx : 0) - 1,
583 			dev->clip.y2 + (scy < 0 ? scy : 0) - 1)
584 	);
585 	lv(dev)->d_flush();
586 	unlock_dev(dev);
587 	return 1;
588 }
589 
ath_set_clip_area(struct graphics_device * dev)590 static void ath_set_clip_area(struct graphics_device *dev)
591 {
592 	debug2("setc\n");
593 	lock_dev(dev);
594 	lv(dev)->SetDrawingRegion(Region(IRect(dev->clip.x1, dev->clip.y1, dev->clip.x2 - 1, dev->clip.y2 - 1)));
595 	unlock_dev(dev);
596 }
597 
ath_flush(struct graphics_device * dev)598 static void ath_flush(struct graphics_device *dev)
599 {
600 	unregister_bottom_half(do_flush, dev);
601 	do_flush(dev);
602 }
603 
604 struct graphics_driver atheos_driver = {
605 	(unsigned char *)"atheos",
606 	ath_init_driver,
607 	ath_init_device,
608 	ath_shutdown_device,
609 	ath_shutdown_driver,
610 	NULL,
611 	ath_after_fork,
612 	NULL,
613 	NULL,
614 	NULL,
615 	NULL,
616 	ath_get_empty_bitmap,
617 	ath_register_bitmap,
618 	ath_prepare_strip,
619 	ath_commit_strip,
620 	ath_unregister_bitmap,
621 	ath_draw_bitmap,
622 	ath_get_color,
623 	ath_fill_area,
624 	ath_draw_hline,
625 	ath_draw_vline,
626 	ath_scroll,
627 	ath_set_clip_area,
628 	ath_flush,
629 	NULL,				/* block */
630 	NULL,				/* unblock */
631 	NULL,				/* set_palette */
632 	NULL,				/* get_real_colors */
633 	ath_set_title,
634 	NULL,				/* exec */
635 	NULL,				/* set_clipboard_text */
636 	NULL,				/* get_clipboard_text */
637 	0,				/* depth */
638 	0, 0,				/* size */
639 	GD_UNICODE_KEYS | GD_NO_OS_SHELL | GD_NO_LIBEVENT,/* flags */
640 	NULL,				/* param */
641 };
642 
643 #endif
644