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