]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/services/gfx/mw/v2_0/src/nanox/srvnet.c
Initial revision
[karo-tx-redboot.git] / packages / services / gfx / mw / v2_0 / src / nanox / srvnet.c
1 /*
2  * Copyright (c) 1999-2001 Greg Haerr <greg@censoft.com>
3  * Copyright (c) 1999 Alex Holden <alex@linuxhacker.org>
4  * Copyright (c) 2000 Vidar Hokstad
5  * Copyright (c) 2000 Morten Rolland <mortenro@screenmedia.no>
6  * Portions Copyright (c) 1991 David I. Bell
7  *
8  * Permission is granted to use, distribute, or modify this source,
9  * provided that this copyright notice remains intact.
10  *
11  * Completely rewritten for speed by Greg Haerr
12  *
13  * This is the server side of the network interface, which accepts
14  * connections from clients, receives functions from them, and dispatches
15  * events to them.
16  */
17 #include <stdio.h>
18 #include <stddef.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/socket.h>
24 #if HAVE_SHAREDMEM_SUPPORT
25 #include <sys/types.h>
26 #include <sys/ipc.h>
27 #include <sys/shm.h>
28 #endif
29 #if ELKS
30 #include <linuxmt/na.h>
31 #elif __ECOS
32 #include <netinet/in.h>
33
34 #else
35 #include <sys/un.h>
36 #endif
37 #include "serv.h"
38 #include "nxproto.h"
39
40 /* fix bad MIPS sys headers...*/
41 #ifndef SOCK_STREAM
42 #define SOCK_STREAM     2       /* <asm/socket.h>*/
43 #endif
44
45 extern  int             un_sock;
46 extern  GR_CLIENT       *root_client;
47 extern  int             current_fd;
48
49 static int GsWriteType(int,short);
50
51 /*
52  * Wrapper functions called after full packet read
53  */
54 static void 
55 GrOpenWrapper(void *r)
56 {
57         nxOpenReq *req = r;
58
59         /* store process id of client*/
60         curclient->processid = req->pid;
61
62         GrOpen();
63 }
64
65 static void
66 GrCloseWrapper(void *r)
67 {
68         GrClose();
69 }
70
71 static void
72 GrGetScreenInfoWrapper(void *r)
73 {
74         GR_SCREEN_INFO si;
75
76         GrGetScreenInfo(&si);
77         GsWriteType(current_fd,GrNumGetScreenInfo);
78         GsWrite(current_fd, &si, sizeof(si));
79 }
80
81 static void
82 GrGetSysColorWrapper(void *r)
83 {
84         nxGetSysColorReq *req = r;
85         GR_COLOR color = GrGetSysColor(req->index);
86
87         GsWriteType(current_fd, GrNumGetSysColor);
88         GsWrite(current_fd, &color, sizeof(color));
89 }
90
91 static void
92 GrNewWindowWrapper(void *r)
93 {
94         nxNewWindowReq *req = r;
95         GR_WINDOW_ID    wid;
96
97         wid = GrNewWindow(req->parentid, req->x, req->y, req->width,
98                 req->height, req->bordersize, req->backgroundcolor,
99                 req->bordercolor);
100
101         GsWriteType(current_fd,GrNumNewWindow);
102         GsWrite(current_fd, &wid, sizeof(wid));
103 }
104
105
106 static void
107 GrNewPixmapWrapper(void *r)
108 {
109         nxNewPixmapReq *req = r;
110         GR_WINDOW_ID    wid;
111
112         /* FIXME: Add support for passing info about shared memory
113          * segment
114          */
115         wid = GrNewPixmap(req->width, req->height, 0);
116
117         GsWriteType(current_fd,GrNumNewPixmap);
118         GsWrite(current_fd, &wid, sizeof(wid));
119 }
120
121 static void
122 GrNewInputWindowWrapper(void *r)
123 {
124         nxNewInputWindowReq *req = r;
125         GR_WINDOW_ID         wid;
126
127         wid = GrNewInputWindow(req->parentid, req->x, req->y, req->width,
128                 req->height);
129         GsWriteType(current_fd,GrNumNewInputWindow);
130         GsWrite(current_fd, &wid, sizeof(wid));
131 }
132
133 static void
134 GrDestroyWindowWrapper(void *r)
135 {
136         nxDestroyWindowReq *req = r;
137
138         GrDestroyWindow(req->windowid);
139 }
140
141 static void
142 GrNewGCWrapper(void *r)
143 {
144         GR_GC_ID gc = GrNewGC();
145
146         GsWriteType(current_fd,GrNumNewGC);
147         GsWrite(current_fd, &gc, sizeof(gc));
148 }
149
150 static void
151 GrCopyGCWrapper(void *r)
152 {
153         nxCopyGCReq *req = r;
154         GR_GC_ID     gcnew;
155
156         gcnew = GrCopyGC(req->gcid);
157         GsWriteType(current_fd,GrNumCopyGC);
158         GsWrite(current_fd, &gcnew, sizeof(gcnew));
159 }
160
161 static void
162 GrGetGCInfoWrapper(void *r)
163 {
164         nxGetGCInfoReq *req = r;
165         GR_GC_INFO      gcinfo;
166
167         GrGetGCInfo(req->gcid, &gcinfo);
168         GsWriteType(current_fd,GrNumGetGCInfo);
169         GsWrite(current_fd, &gcinfo, sizeof(gcinfo));
170 }
171
172 static void
173 GrDestroyGCWrapper(void *r)
174 {
175         nxDestroyGCReq *req = r;
176
177         GrDestroyGC(req->gcid);
178 }
179
180 static void
181 GrNewRegionWrapper(void *r)
182 {
183         GR_REGION_ID region = GrNewRegion();
184
185         GsWriteType(current_fd, GrNumNewRegion);
186         GsWrite(current_fd, &region, sizeof(region));
187 }
188
189 static void
190 GrDestroyRegionWrapper(void *r)
191 {
192         nxDestroyRegionReq *req = r;
193
194         GrDestroyRegion(req->regionid);
195 }
196
197 static void
198 GrIntersectRegionWrapper(void *r)
199 {
200         nxIntersectRegionReq *req = r;
201
202         GrIntersectRegion(req->regionid, req->srcregionid1,
203                 req->srcregionid2);
204 }
205
206 static void
207 GrUnionRectWithRegionWrapper(void *r)
208 {
209         nxUnionRectWithRegionReq *req = r;
210
211         GrUnionRectWithRegion(req->regionid, &(req->rect));
212 }
213
214 static void
215 GrUnionRegionWrapper(void *r)
216 {
217         nxUnionRegionReq *req = r;
218
219         GrUnionRegion(req->regionid, req->srcregionid1, req->srcregionid2);
220 }
221
222 static void
223 GrSubtractRegionWrapper(void *r)
224 {
225         nxSubtractRegionReq *req = r;
226
227         GrSubtractRegion(req->regionid, req->srcregionid1, req->srcregionid2);
228 }
229
230 static void
231 GrXorRegionWrapper(void *r)
232 {
233         nxXorRegionReq *req = r;
234
235         GrXorRegion(req->regionid, req->srcregionid1, req->srcregionid2);
236 }
237
238 static void
239 GrPointInRegionWrapper(void *r)
240 {
241         nxPointInRegionReq *req = r;
242         GR_BOOL ret_value = GrPointInRegion(req->regionid, req->x, req->y);
243                 
244         GsWriteType(current_fd, GrNumPointInRegion);
245         GsWrite(current_fd, &ret_value, sizeof(ret_value));
246 }
247
248 static void
249 GrRectInRegionWrapper(void *r)
250 {
251         nxRectInRegionReq *req = r;
252         unsigned short ret_value;
253         
254         ret_value = (unsigned short)GrRectInRegion(req->regionid,
255                 req->x, req->y, req->w, req->h);
256                 
257         GsWriteType(current_fd, GrNumRectInRegion);
258         GsWrite(current_fd, &ret_value, sizeof(ret_value));
259 }
260
261 static void
262 GrEmptyRegionWrapper(void *r)
263 {
264         nxEmptyRegionReq *req = r;
265         GR_BOOL           ret_value;
266         
267         ret_value = GrEmptyRegion(req->regionid);
268         GsWriteType(current_fd, GrNumEmptyRegion);
269         GsWrite(current_fd, &ret_value, sizeof(ret_value));
270 }
271
272 static void
273 GrEqualRegionWrapper(void *r)
274 {
275         nxEqualRegionReq *req = r;
276         GR_BOOL           ret_value;
277         
278         ret_value = GrEqualRegion(req->region1, req->region2);
279         GsWriteType(current_fd, GrNumEqualRegion);
280         GsWrite(current_fd, &ret_value, sizeof(ret_value));
281 }
282
283 static void
284 GrOffsetRegionWrapper(void *r)
285 {
286         nxOffsetRegionReq *req = r;
287         
288         GrOffsetRegion(req->region, req->dx, req->dy);
289 }
290
291 static void
292 GrSetGCRegionWrapper(void *r)
293 {
294         nxSetGCRegionReq *req = r;
295
296         GrSetGCRegion(req->gcid, req->regionid);
297 }
298
299 static void
300 GrSetGCClipOriginWrapper(void *r)
301 {
302         nxSetGCClipOriginReq *req = r;
303         GrSetGCClipOrigin(req->gcid, req->xoff, req->yoff);
304 }
305
306 static void
307 GrGetRegionBoxWrapper(void *r)
308 {
309         nxRectInRegionReq *req = r;
310         GR_BOOL            ret_value;
311         GR_RECT            ret_rect;
312
313         ret_value = GrGetRegionBox(req->regionid, &ret_rect);
314                 
315         GsWriteType(current_fd, GrNumGetRegionBox);
316         GsWrite(current_fd, &ret_rect, sizeof(ret_rect));
317         GsWriteType(current_fd, GrNumGetRegionBox);
318         GsWrite(current_fd, &ret_value, sizeof(ret_value));
319 }
320
321 static void
322 GrNewPolygonRegionWrapper(void *r)
323 {
324         GR_REGION_ID region;
325         nxNewPolygonRegionReq *req = r;
326         int count;
327         
328         /* FIXME: unportable method, depends on sizeof(int) in GR_POINT*/
329         count = GetReqVarLen(req) / sizeof(GR_POINT);   
330         region = GrNewPolygonRegion(req->mode, count,
331                 (GR_POINT *)GetReqData(req));
332         
333         GsWriteType(current_fd, GrNumNewPolygonRegion);
334         GsWrite(current_fd, &region, sizeof(region));
335 }
336
337 static void
338 GrMapWindowWrapper(void *r)
339 {
340         nxMapWindowReq *req = r;
341
342         GrMapWindow(req->windowid);
343 }
344
345 static void
346 GrUnmapWindowWrapper(void *r)
347 {
348         nxUnmapWindowReq *req = r;
349
350         GrUnmapWindow(req->windowid);
351 }
352
353 static void
354 GrRaiseWindowWrapper(void *r)
355 {
356         nxRaiseWindowReq *req = r;
357
358         GrRaiseWindow(req->windowid);
359 }
360
361 static void
362 GrLowerWindowWrapper(void *r)
363 {
364         nxLowerWindowReq *req = r;
365
366         GrLowerWindow(req->windowid);
367 }
368
369 static void
370 GrMoveWindowWrapper(void *r)
371 {
372         nxMoveWindowReq *req = r;
373
374         GrMoveWindow(req->windowid, req->x, req->y);
375 }
376
377 static void
378 GrResizeWindowWrapper(void *r)
379 {
380         nxResizeWindowReq *req = r;
381
382         GrResizeWindow(req->windowid, req->width, req->height);
383 }
384
385 static void
386 GrReparentWindowWrapper(void *r)
387 {
388         nxReparentWindowReq *req = r;
389
390         GrReparentWindow(req->windowid, req->parentid, req->x, req->y);
391 }
392
393 static void
394 GrGetWindowInfoWrapper(void *r)
395 {
396         nxGetWindowInfoReq *req = r;
397         GR_WINDOW_INFO      wi;
398
399         GrGetWindowInfo(req->windowid, &wi);
400         GsWriteType(current_fd,GrNumGetWindowInfo);
401         GsWrite(current_fd, &wi, sizeof(wi));
402 }
403
404 static void
405 GrGetFontInfoWrapper(void *r)
406 {
407         nxGetFontInfoReq *req = r;
408         GR_FONT_INFO      fi;
409
410         GrGetFontInfo(req->fontid, &fi);
411         GsWriteType(current_fd,GrNumGetFontInfo);
412         GsWrite(current_fd, &fi, sizeof(fi));
413 }
414
415 static void
416 GrGetFocusWrapper(void *r)
417 {
418         GR_WINDOW_ID wid = GrGetFocus();
419
420         GsWriteType(current_fd, GrNumGetFocus);
421         GsWrite(current_fd, &wid, sizeof(wid));
422 }
423
424 static void
425 GrSetFocusWrapper(void *r)
426 {
427         nxSetFocusReq *req = r;
428
429         GrSetFocus(req->windowid);
430 }
431
432 static void
433 GrSetWindowCursorWrapper(void *r)
434 {
435         nxSetWindowCursorReq *req = r;
436
437         GrSetWindowCursor(req->windowid, req->cursorid);
438 }
439
440 static void
441 GrClearAreaWrapper(void *r)
442 {
443         nxClearAreaReq *req = r;
444
445         GrClearArea(req->windowid, req->x, req->y, req->width,
446                 req->height, req->exposeflag);
447 }
448
449 static void
450 GrSelectEventsWrapper(void *r)
451 {
452         nxSelectEventsReq *req = r;
453
454         GrSelectEvents(req->windowid, req->eventmask);
455 }
456
457 static void
458 GrGetNextEventWrapper(void *r)
459 {
460 #if 1
461         /* tell main loop to call Finish routine on event*/
462         curclient->waiting_for_event = TRUE;
463 #else
464         GR_EVENT evt;
465
466         /* first check if any event ready*/
467         GrCheckNextEvent(&evt);
468         if(evt.type == GR_EVENT_TYPE_NONE) {
469                 /* tell main loop to call Finish routine on event*/
470                 curclient->waiting_for_event = TRUE;
471                 return;
472         }
473
474         GsWriteType(current_fd, GrNumGetNextEvent);
475         GsWrite(current_fd, &evt, sizeof(evt));
476         if(evt.type == GR_EVENT_TYPE_CLIENT_DATA) {
477                 GsWrite(fd, evt.data, evt.datalen);
478                 free(evt.data);
479         }
480 #endif
481 }
482
483 /* Complete the GrGetNextEvent call from client.
484  * The client is still waiting on a read at this point.
485  */
486 void
487 GrGetNextEventWrapperFinish(int fd)
488 {
489         GR_EVENT evt;
490         GR_EVENT_CLIENT_DATA *cde;
491
492         /* get the event and pass it to client*/
493         /* this will never be GR_EVENT_TYPE_NONE*/
494         GrCheckNextEvent(&evt);
495
496         GsWriteType(fd,GrNumGetNextEvent);
497         GsWrite(fd, &evt, sizeof(evt));
498         if(evt.type == GR_EVENT_TYPE_CLIENT_DATA) {
499                 cde = (GR_EVENT_CLIENT_DATA *)&evt;
500                 if(cde->data) {
501                         GsWrite(fd, cde->data, cde->datalen);
502                         free(cde->data);
503                 } cde->datalen = 0;
504         }
505 }
506
507 static void
508 GrCheckNextEventWrapper(void *r)
509 {
510         GR_EVENT evt;
511         GR_EVENT_CLIENT_DATA *cde;
512
513         GrCheckNextEvent(&evt);
514
515         GsWriteType(current_fd,GrNumGetNextEvent);
516         GsWrite(current_fd, &evt, sizeof(evt));
517         if(evt.type == GR_EVENT_TYPE_CLIENT_DATA) {
518                 cde = (GR_EVENT_CLIENT_DATA *)&evt;
519                 if(cde->data) {
520                         GsWrite(current_fd, cde->data, cde->datalen);
521                         free(cde->data);
522                 } cde->datalen = 0;
523         }
524 }
525
526 static void
527 GrPeekEventWrapper(void *r)
528 {
529         GR_EVENT evt;
530         GR_CHAR  ret;
531         GR_EVENT_CLIENT_DATA *cde;
532
533         ret = GrPeekEvent(&evt);
534
535         GsWriteType(current_fd,GrNumPeekEvent);
536         GsWrite(current_fd, &evt, sizeof(evt));
537         if(evt.type == GR_EVENT_TYPE_CLIENT_DATA) {
538                 cde = (GR_EVENT_CLIENT_DATA *)&evt;
539                 if(cde->data) {
540                         GsWrite(current_fd, cde->data, cde->datalen);
541                         free(cde->data);
542                 } cde->datalen = 0;
543         }
544         GsWrite(current_fd, &ret, sizeof(GR_CHAR));
545 }
546
547 static void
548 GrLineWrapper(void *r)
549 {
550         nxLineReq *req = r;
551
552         GrLine(req->drawid, req->gcid, req->x1, req->y1, req->x2, req->y2);
553 }
554
555 static void
556 GrPointWrapper(void *r)
557 {
558         nxPointReq *req = r;
559
560         GrPoint(req->drawid, req->gcid, req->x, req->y);
561
562 }
563
564 static void
565 GrPointsWrapper(void *r)
566 {
567         nxPointsReq *req = r;
568         int        count;
569
570         count = GetReqVarLen(req) / sizeof(GR_POINT);
571         GrPoints(req->drawid, req->gcid, count, (GR_POINT *)GetReqData(req));
572 }
573
574 static void
575 GrRectWrapper(void *r)
576 {
577         nxRectReq *req = r;
578
579         GrRect(req->drawid, req->gcid, req->x, req->y, req->width, req->height);
580 }
581
582 static void
583 GrFillRectWrapper(void *r)
584 {
585         nxFillRectReq *req = r;
586
587         GrFillRect(req->drawid, req->gcid, req->x, req->y, req->width,
588                 req->height);
589 }
590
591 static void
592 GrPolyWrapper(void *r)
593 {
594         nxPolyReq *req = r;
595         int        count;
596
597         count = GetReqVarLen(req) / sizeof(GR_POINT);
598         GrPoly(req->drawid, req->gcid, count, (GR_POINT *)GetReqData(req));
599 }
600
601 /* FIXME: fails with pointtable size > 64k if sizeof(int) == 2*/
602 static void
603 GrFillPolyWrapper(void *r)
604 {
605         nxPolyReq *req = r;
606         int        count;
607
608         count = GetReqVarLen(req) / sizeof(GR_POINT);
609         GrFillPoly(req->drawid, req->gcid, count, (GR_POINT *)GetReqData(req));
610 }
611
612 static void
613 GrEllipseWrapper(void *r)
614 {
615         nxEllipseReq *req = r;
616
617         GrEllipse(req->drawid, req->gcid, req->x, req->y, req->rx, req->ry);
618 }
619
620 static void
621 GrFillEllipseWrapper(void *r)
622 {
623         nxFillEllipseReq *req = r;
624
625         GrFillEllipse(req->drawid, req->gcid, req->x, req->y, req->rx, req->ry);
626 }
627
628 static void
629 GrArcWrapper(void *r)
630 {
631         nxArcReq *req = r;
632
633         GrArc(req->drawid, req->gcid, req->x, req->y, req->rx, req->ry,
634                 req->ax, req->ay, req->bx, req->by, req->type);
635 }
636
637 static void
638 GrArcAngleWrapper(void *r)
639 {
640         nxArcAngleReq *req = r;
641
642         GrArcAngle(req->drawid, req->gcid, req->x, req->y, req->rx, req->ry,
643                 req->angle1, req->angle2, req->type);
644 }
645
646 static void
647 GrSetGCForegroundWrapper(void *r)
648 {
649         nxSetGCForegroundReq *req = r;
650
651         GrSetGCForeground(req->gcid, req->color);
652 }
653
654 static void
655 GrSetGCBackgroundWrapper(void *r)
656 {
657         nxSetGCBackgroundReq *req = r;
658
659         GrSetGCBackground(req->gcid, req->color);
660 }
661
662 static void
663 GrSetGCUseBackgroundWrapper(void *r)
664 {
665         nxSetGCUseBackgroundReq *req = r;
666
667         GrSetGCUseBackground(req->gcid, req->flag);
668 }
669
670 static void
671 GrSetGCModeWrapper(void *r)
672 {
673         nxSetGCModeReq *req = r;
674
675         GrSetGCMode(req->gcid, req->mode);
676 }
677
678 static void
679 GrCreateFontWrapper(void *r)
680 {
681         nxCreateFontReq *req = r;
682         GR_FONT_ID      fontid;
683
684         if(req->lf_used)
685                 fontid = GrCreateFont(NULL, 0, &req->lf);
686         else
687                 fontid = GrCreateFont(req->lf.lfFaceName, req->height, NULL);
688
689         GsWriteType(current_fd,GrNumCreateFont);
690         GsWrite(current_fd, &fontid, sizeof(fontid));
691 }
692
693 static void
694 GrSetFontSizeWrapper(void *r)
695 {
696         nxSetFontSizeReq *req = r;
697
698         GrSetFontSize(req->fontid, req->fontsize);
699 }
700
701 static void
702 GrSetFontRotationWrapper(void *r)
703 {
704         nxSetFontRotationReq *req = r;
705
706         GrSetFontRotation(req->fontid, req->tenthdegrees);
707 }
708
709 static void
710 GrSetFontAttrWrapper(void *r)
711 {
712         nxSetFontAttrReq *req = r;
713
714         GrSetFontAttr(req->fontid, req->setflags, req->clrflags);
715 }
716
717 static void
718 GrDestroyFontWrapper(void *r)
719 {
720         nxDestroyFontReq *req = r;
721
722         GrDestroyFont(req->fontid);
723 }
724
725 static void
726 GrSetGCFontWrapper(void *r)
727 {
728         nxSetGCFontReq *req = r;
729
730         GrSetGCFont(req->gcid, req->fontid);
731 }
732
733 static void
734 GrGetGCTextSizeWrapper(void *r)
735 {
736         nxGetGCTextSizeReq *req = r;
737         GR_SIZE             retwidth, retheight, retbase;
738
739         GrGetGCTextSize(req->gcid, GetReqData(req), GetReqVarLen(req),
740                 req->flags, &retwidth, &retheight, &retbase);
741
742         GsWriteType(current_fd,GrNumGetGCTextSize);
743         GsWrite(current_fd, &retwidth, sizeof(retwidth));
744         GsWrite(current_fd, &retheight, sizeof(retheight));
745         GsWrite(current_fd, &retbase, sizeof(retbase));
746 }
747
748 /* FIXME: fails with size > 64k if sizeof(int) == 2*/
749 static void
750 GsReadAreaWrapper(void *r)
751 {
752         nxReadAreaReq *req = r;
753         int            size;
754         GR_PIXELVAL *   area;
755
756         /* FIXME: optimize for smaller pixelvals*/
757         size = req->width * req->height * sizeof(GR_PIXELVAL);
758
759         if(!(area = malloc(size))) {
760                 /*GsPutCh(current_fd, GrRetENoMem);*/ /* FIXME*/
761                 /*return;*/
762         }
763
764         GrReadArea(req->drawid, req->x, req->y, req->width, req->height, area);
765         GsWriteType(current_fd,GrNumReadArea);
766         GsWrite(current_fd, area, size);
767         free(area);
768 }
769
770 /* FIXME: fails with size > 64k if sizeof(int) == 2*/
771 static void
772 GrAreaWrapper(void *r)
773 {
774         nxAreaReq *req = r;
775
776         GrArea(req->drawid, req->gcid, req->x, req->y, req->width, req->height,
777                 GetReqData(req), req->pixtype);
778 }
779
780 /* FIXME: fails with bitmapsize > 64k if sizeof(int) == 2*/
781 static void
782 GrBitmapWrapper(void *r)
783 {
784         nxBitmapReq *req = r;
785
786         GrBitmap(req->drawid, req->gcid, req->x, req->y, req->width,
787                 req->height, GetReqData(req));
788 }
789
790 static void
791 GrDrawImageBitsWrapper(void *r)
792 {
793         nxDrawImageBitsReq *req = r;
794         char *              addr;
795         int                 imagesize;
796         GR_IMAGE_HDR        hdr;
797
798         hdr.width = req->width;
799         hdr.height = req->height;
800         hdr.planes = req->planes;
801         hdr.bpp = req->bpp;
802         hdr.pitch = req->pitch;
803         hdr.bytesperpixel = req->bytesperpixel;
804         hdr.compression = req->compression;
805         hdr.palsize = req->palsize;
806         hdr.transcolor = req->transcolor;
807         addr = GetReqData(req);
808         hdr.imagebits = (MWUCHAR *)addr;
809         imagesize = hdr.pitch * hdr.height;
810         hdr.palette = (MWPALENTRY *)(addr + imagesize);
811         GrDrawImageBits(req->drawid, req->gcid, req->x, req->y, &hdr);
812 }
813
814 static void
815 GrCopyAreaWrapper(void *r)
816 {
817         nxCopyAreaReq *req = r;
818
819         GrCopyArea(req->drawid, req->gcid, req->x, req->y, req->width, req->height,
820                 req->srcid, req->srcx, req->srcy, req->op);
821 }
822
823 static void
824 GrTextWrapper(void *r)
825 {
826         nxTextReq *req = r;
827
828         GrText(req->drawid, req->gcid, req->x, req->y, GetReqData(req),
829                 req->count, req->flags);
830 }
831
832 static void
833 GrNewCursorWrapper(void *r)
834 {
835         nxNewCursorReq *req = r;
836         int             varlen;
837         char *          bitmap;
838         GR_CURSOR_ID    cursorid;
839
840         varlen = GetReqVarLen(req);
841         bitmap = GetReqData(req);
842
843         cursorid = GrNewCursor(req->width, req->height,
844                 req->hotx, req->hoty, req->fgcolor, req->bgcolor,
845                 (GR_BITMAP *)bitmap, (GR_BITMAP *)(bitmap+varlen/2));
846
847         GsWriteType(current_fd, GrNumNewCursor);
848         GsWrite(current_fd, &cursorid, sizeof(cursorid));
849 }
850
851 static void
852 GrMoveCursorWrapper(void *r)
853 {
854         nxMoveCursorReq *req = r;
855
856         GrMoveCursor(req->x, req->y);
857 }
858
859 static void
860 GrGetSystemPaletteWrapper(void *r)
861 {
862         GR_PALETTE             pal;
863
864         GrGetSystemPalette(&pal);
865         GsWriteType(current_fd,GrNumGetSystemPalette);
866         GsWrite(current_fd, &pal, sizeof(pal));
867 }
868
869 static void
870 GrSetSystemPaletteWrapper(void *r)
871 {
872         nxSetSystemPaletteReq *req = r;
873         GR_PALETTE             pal;
874
875         pal.count = req->count;
876         memcpy(pal.palette, req->palette, sizeof(pal.palette));
877         GrSetSystemPalette(req->first, &pal);
878 }
879
880 static void
881 GrFindColorWrapper(void *r)
882 {
883         nxFindColorReq *req = r;
884         GR_PIXELVAL     pixel;
885
886         GrFindColor(req->color, &pixel);
887         GsWriteType(current_fd,GrNumFindColor);
888         GsWrite(current_fd, &pixel, sizeof(pixel));
889 }
890
891 static void
892 GrInjectEventWrapper(void *r)
893 {
894         nxInjectEventReq *req = r;
895
896         switch(req->event_type) {
897         case GR_INJECT_EVENT_POINTER:
898                 GrInjectPointerEvent(req->event.pointer.x,
899                                      req->event.pointer.y,
900                                      req->event.pointer.button,
901                                      req->event.pointer.visible);
902                 break;
903
904         case GR_INJECT_EVENT_KEYBOARD:
905                 GrInjectKeyboardEvent(req->event.keyboard.wid,
906                                       req->event.keyboard.keyvalue,
907                                       req->event.keyboard.modifier,
908                                       req->event.keyboard.scancode,
909                                       req->event.keyboard.pressed);
910                 break;
911         }
912 }
913
914 static void
915 GrSetWMPropertiesWrapper(void *r)
916 {
917         nxSetWMPropertiesReq *req = r;
918         GR_WM_PROPERTIES *props = GetReqData(req);
919
920         if(GetReqVarLen(req) - sizeof(GR_WM_PROPERTIES)) 
921                 props->title = (char *)props + sizeof(GR_WM_PROPERTIES);
922         else
923                 props->title = NULL;
924         GrSetWMProperties(req->windowid, props);
925 }
926
927 static void
928 GrGetWMPropertiesWrapper(void *r)
929 {
930         nxGetWMPropertiesReq *req = r;
931         UINT16 textlen;
932         GR_WM_PROPERTIES props;
933         
934         GrGetWMProperties(req->windowid, &props);
935
936         if(props.title)
937                 textlen = strlen(props.title) + 1;
938         else textlen = 0;
939
940         GsWriteType(current_fd,GrNumGetWMProperties);
941         GsWrite(current_fd, &props, sizeof(props));
942         GsWrite(current_fd, &textlen, sizeof(textlen));
943         if(textlen)
944                 GsWrite(current_fd, props.title, textlen);
945 }
946
947 static void
948 GrCloseWindowWrapper(void *r)
949 {
950         nxCloseWindowReq *req = r;
951
952         GrCloseWindow(req->windowid);
953 }
954
955 static void
956 GrKillWindowWrapper(void *r)
957 {
958         nxKillWindowReq *req = r;
959
960         GrKillWindow(req->windowid);
961 }
962
963 static void
964 GrDrawImageFromFileWrapper(void *r)
965 {
966         nxDrawImageFromFileReq *req = r;
967
968         GrDrawImageFromFile(req->drawid, req->gcid, req->x, req->y, req->width,
969                 req->height, GetReqData(req), req->flags);
970 }
971
972 static void
973 GrLoadImageFromFileWrapper(void *r)
974 {
975         nxLoadImageFromFileReq *req = r;
976         GR_IMAGE_ID             id;
977
978         id = GrLoadImageFromFile(GetReqData(req), req->flags);
979         GsWriteType(current_fd, GrNumLoadImageFromFile);
980         GsWrite(current_fd, &id, sizeof(id));
981 }
982
983 static void
984 GrDrawImageToFitWrapper(void *r)
985 {
986         nxDrawImageToFitReq *req = r;
987
988         GrDrawImageToFit(req->drawid, req->gcid, req->x, req->y, req->width,
989                 req->height, req->imageid);
990 }
991
992 static void
993 GrFreeImageWrapper(void *r)
994 {
995         nxFreeImageReq *req = r;
996
997         GrFreeImage(req->id);
998 }
999
1000 static void
1001 GrGetImageInfoWrapper(void *r)
1002 {
1003         nxGetImageInfoReq *req = r;
1004         GR_IMAGE_INFO      info;
1005
1006         GrGetImageInfo(req->id, &info);
1007         GsWriteType(current_fd, GrNumGetImageInfo);
1008         GsWrite(current_fd, &info, sizeof(info));
1009 }
1010
1011 static void
1012 GrSetScreenSaverTimeoutWrapper(void *r)
1013 {
1014         nxSetScreenSaverTimeoutReq *req = r;
1015
1016         GrSetScreenSaverTimeout(req->timeout);
1017 }
1018
1019 static void
1020 GrSetSelectionOwnerWrapper(void *r)
1021 {
1022         nxSetSelectionOwnerReq *req = r;
1023
1024         GrSetSelectionOwner(req->wid, GetReqData(req));
1025 }
1026
1027 static void
1028 GrGetSelectionOwnerWrapper(void *r)
1029 {
1030         GR_CHAR *typelist;
1031         GR_WINDOW_ID wid;
1032         unsigned short len;
1033
1034         wid = GrGetSelectionOwner(&typelist);
1035         GsWriteType(current_fd, GrNumGetSelectionOwner);
1036         GsWrite(current_fd, &wid, sizeof(wid));
1037
1038         if(wid) {
1039                 len = strlen(typelist) + 1;
1040                 GsWrite(current_fd, &len, sizeof(len));
1041                 GsWrite(current_fd, typelist, len);
1042         }
1043 }
1044
1045 static void
1046 GrRequestClientDataWrapper(void *r)
1047 {
1048         nxRequestClientDataReq *req = r;
1049
1050         GrRequestClientData(req->wid, req->rid, req->serial, req->mimetype);
1051 }
1052
1053 static void
1054 GrSendClientDataWrapper(void *r)
1055 {
1056         nxSendClientDataReq *req = r;
1057
1058         GrSendClientData(req->wid, req->did, req->serial, req->len,
1059                 GetReqVarLen(req), GetReqData(req));
1060 }
1061
1062 static void
1063 GrBellWrapper(void *r)
1064 {
1065         GrBell();
1066 }
1067
1068 static void
1069 GrSetBackgroundPixmapWrapper(void *r)
1070 {
1071         nxSetBackgroundPixmapReq *req = r;
1072
1073         GrSetBackgroundPixmap(req->wid, req->pixmap, req->flags);
1074 }
1075
1076 static void
1077 GrDestroyCursorWrapper(void *r)
1078 {
1079         nxDestroyCursorReq *req = r;
1080
1081         GrDestroyCursor(req->cursorid);
1082 }
1083
1084 static void
1085 GrQueryTreeWrapper(void *r)
1086 {
1087         nxQueryTreeReq *req = r;
1088         GR_WINDOW_ID    parentid;
1089         GR_WINDOW_ID *  children;
1090         GR_COUNT        nchildren;
1091
1092         GrQueryTree(req->windowid, &parentid, &children, &nchildren);
1093
1094         GsWriteType(current_fd, GrNumQueryTree);
1095         GsWrite(current_fd, &parentid, sizeof(parentid));
1096         GsWrite(current_fd, &nchildren, sizeof(nchildren));
1097         if (nchildren) {
1098                 GsWrite(current_fd, children, nchildren * sizeof(GR_WINDOW_ID));
1099                 free(children);
1100         }
1101 }
1102
1103 static void
1104 GrCreateTimerWrapper(void *r)
1105 {
1106     nxCreateTimerReq *req = r;
1107     GR_TIMER_ID  timerid;
1108
1109     timerid = GrCreateTimer(req->wid, req->period);
1110
1111     GsWriteType(current_fd, GrNumCreateTimer);
1112     GsWrite(current_fd, &timerid, sizeof (timerid));
1113 }
1114
1115 typedef struct image_list {
1116  void *data;
1117  int id;
1118  int size;
1119  int offset;
1120
1121  struct image_list *next;
1122 } imagelist_t;
1123
1124 static imagelist_t *imageListHead = 0;
1125 static imagelist_t *imageListTail = 0;
1126 static int imageListId = 0;
1127
1128 static void freeImageBuffer(imagelist_t *buffer) {
1129
1130  imagelist_t *prev = 0;
1131  imagelist_t *ptr = imageListHead;
1132
1133  while(ptr) {
1134    if (ptr == buffer) {
1135      if (prev) 
1136         prev->next = buffer->next;
1137      else 
1138         imageListHead = buffer->next;
1139      
1140      if (!imageListHead) imageListTail = 0;
1141      
1142      free(buffer->data);
1143      free(buffer);
1144      return;
1145    }
1146    
1147    prev = ptr;
1148    ptr = ptr->next;
1149  }  
1150 }
1151
1152 static void GrImageBufferAllocWrapper(void *r) {
1153  nxImageBufferAllocReq *req = r;
1154  
1155  /* Add a new buffer to the end of the list */
1156
1157  if (!imageListTail) {
1158    imageListHead = imageListTail = (imagelist_t *) malloc(sizeof(imagelist_t));
1159  }
1160  else {
1161    imageListTail->next = (imagelist_t *) malloc(sizeof(imagelist_t));
1162    imageListTail = imageListTail->next;
1163  }
1164
1165  imageListTail->id = ++imageListId;
1166  imageListTail->data = (void *) malloc(req->size);
1167  imageListTail->size = req->size;
1168  imageListTail->offset = 0;
1169
1170  imageListTail->next = 0;
1171
1172  GsWriteType(current_fd,GrNumImageBufferAlloc);
1173  GsWrite(current_fd, &imageListTail->id, sizeof(int));
1174 }
1175
1176 static void GrImageBufferSendWrapper(void *r) {
1177
1178  int csize = 0;
1179
1180  imagelist_t *buffer = 0;
1181  nxImageBufferSendReq *req = r;
1182
1183  for(buffer = imageListHead; buffer; buffer = buffer->next)
1184    if (buffer->id == req->buffer_id) break;
1185
1186  if (!buffer) return;
1187
1188  if (buffer->offset + req->size >= buffer->size) 
1189    csize = buffer->size - buffer->offset;
1190  else
1191    csize = req->size;
1192
1193  if (!csize) return;
1194
1195  memcpy((void *) (buffer->data + buffer->offset), 
1196          GetReqData(req), csize);
1197  
1198  buffer->offset += csize;
1199 }
1200
1201 void GrLoadImageFromBufferWrapper(void *r) {
1202
1203  GR_IMAGE_ID            id;
1204  imagelist_t *buffer = 0;
1205
1206  nxLoadImageFromBufferReq *req = r;
1207  
1208  for(buffer = imageListHead; buffer; buffer = buffer->next)
1209    if (buffer->id == req->buffer) break;
1210  
1211  if (!buffer) return;
1212
1213  id = GrLoadImageFromBuffer(buffer->data, buffer->size, req->flags);
1214
1215  GsWriteType(current_fd, GrNumLoadImageFromBuffer);
1216  GsWrite(current_fd, &id, sizeof(id));
1217
1218  freeImageBuffer(buffer);
1219 }
1220
1221 void GrDrawImageFromBufferWrapper(void *r) {
1222
1223  imagelist_t *buffer = 0;
1224
1225  nxDrawImageFromBufferReq *req = r;
1226  
1227  for(buffer = imageListHead; buffer; buffer = buffer->next)
1228    if (buffer->id == req->buffer) break;
1229  
1230  if (!buffer) return;
1231
1232  GrDrawImageFromBuffer(req->drawid, req->gcid, req->x, req->y, req->width, 
1233                         req->height, buffer->data, buffer->size, 
1234                         req->flags);
1235  
1236  freeImageBuffer(buffer);
1237 }
1238
1239  
1240
1241 static void
1242 GrDestroyTimerWrapper(void *r)
1243 {
1244     nxDestroyTimerReq *req = r;
1245     
1246     GrDestroyTimer(req->timerid);
1247 }
1248
1249 static void
1250 GrSetPortraitModeWrapper(void *r)
1251 {
1252     nxSetPortraitModeReq *req = r;
1253     
1254     GrSetPortraitMode(req->portraitmode);
1255 }
1256
1257 /*
1258  * This function makes the Nano-X server set up a shared memory segment
1259  * that the client can use when feeding the Nano-X server with requests.
1260  * There is a corresponding GrShmCmdsFlush function that will make the
1261  * server execute the batched commands.
1262  */
1263 #define SHMKEY_BASE 1000000
1264 #define SHMKEY_MAX 256
1265
1266 void
1267 GrReqShmCmdsWrapper(void *r)
1268 {
1269 #if HAVE_SHAREDMEM_SUPPORT
1270         nxReqShmCmdsReq *req = r;
1271         int             key, shmid;
1272         char            *tmp;
1273
1274         if ( curclient->shm_cmds != 0 )
1275                 goto bad;
1276
1277         for ( key=SHMKEY_BASE; key < SHMKEY_BASE+SHMKEY_MAX; key++ ) {
1278                 shmid = shmget(key,req->size,IPC_CREAT|IPC_EXCL|0666);
1279                 if ( shmid == -1 ) {
1280                         if ( errno != EEXIST )
1281                                 goto bad;
1282                 } else {
1283                         tmp = shmat(shmid,0,0);
1284                         if ( tmp == (char *)-1 )
1285                                 goto bad;
1286                         curclient->shm_cmds = tmp;
1287                         curclient->shm_cmds_shmid = shmid;
1288                         curclient->shm_cmds_size = req->size;
1289                         goto finish;
1290                 }
1291         }
1292
1293  bad:
1294         key = 0;
1295
1296  finish:
1297         DPRINTF("Shm: Request key granted=%d\n",key);
1298         GsWrite(current_fd, &key, sizeof(key));
1299 #else
1300         /* return no shared memory support*/
1301         int key = 0;
1302         GsWrite(current_fd, &key, sizeof(key));
1303 #endif /* HAVE_SHAREDMEM_SUPPORT*/
1304 }
1305
1306 static void 
1307 GrGetFontListWrapper(void *r)
1308 {
1309         MWFONTLIST **list;
1310         int num;
1311         int i, ttlen, mwlen;
1312
1313         GrGetFontList(&list, &num);
1314
1315         GsWriteType(current_fd, GrNumGetFontList);
1316
1317         /* the number of strings comming in */
1318         GsWrite(current_fd, &num, sizeof(int));
1319
1320         if(num != -1) {
1321                 for(i = 0; i < num; i++) {
1322                         ttlen = strlen(list[i]->ttname) + 1;
1323                         mwlen = strlen(list[i]->mwname) + 1;
1324
1325                         GsWrite(current_fd, &ttlen, sizeof(int));
1326                         GsWrite(current_fd, list[i]->ttname, ttlen * sizeof(char));
1327
1328                         GsWrite(current_fd, &mwlen, sizeof(int));
1329                         GsWrite(current_fd, list[i]->mwname, mwlen * sizeof(char));
1330                 }
1331                 
1332                 GrFreeFontList(&list, num);
1333         }
1334 }
1335
1336 void GrShmCmdsFlushWrapper(void *r);
1337
1338 /*
1339  * Handler functions, ordered by reqType
1340  */
1341 struct GrFunction {
1342         void            (*func)(void *);
1343         GR_FUNC_NAME    name;
1344 } GrFunctions[] = {
1345         /*   0 */ {GrOpenWrapper, "GrOpen"},
1346         /*   1 */ {GrCloseWrapper, "GrClose"},
1347         /*   2 */ {GrGetScreenInfoWrapper, "GrGetScreenInfo"},
1348         /*   3 */ {GrNewWindowWrapper, "GrNewWindow"},
1349         /*   4 */ {GrNewInputWindowWrapper, "GrNewInputWindow"},
1350         /*   5 */ {GrDestroyWindowWrapper, "GrDestroyWindow"},
1351         /*   6 */ {GrNewGCWrapper, "GrNewGC"},
1352         /*   7 */ {GrCopyGCWrapper, "GrCopyGC"},
1353         /*   8 */ {GrGetGCInfoWrapper, "GrGetGCInfo"},
1354         /*   9 */ {GrDestroyGCWrapper, "GrDestroyGC"},
1355         /*  10 */ {GrMapWindowWrapper, "GrMapWindow"},
1356         /*  11 */ {GrUnmapWindowWrapper, "GrUnmapWindow"},
1357         /*  12 */ {GrRaiseWindowWrapper, "GrRaiseWindow"},
1358         /*  13 */ {GrLowerWindowWrapper, "GrLowerWindow"},
1359         /*  14 */ {GrMoveWindowWrapper, "GrMoveWindow"},
1360         /*  15 */ {GrResizeWindowWrapper, "GrResizeWindow"},
1361         /*  16 */ {GrGetWindowInfoWrapper, "GrGetWindowInfo"},
1362         /*  17 */ {GrGetFontInfoWrapper, "GrGetFontInfo"},
1363         /*  18 */ {GrSetFocusWrapper, "GrSetFocus"},
1364         /*  19 */ {GrSetWindowCursorWrapper, "GrSetWindowCursor"},
1365         /*  20 */ {GrClearAreaWrapper, "GrClearAreaWrapper"},
1366         /*  21 */ {GrSelectEventsWrapper, "GrSelectEvents"},
1367         /*  22 */ {GrGetNextEventWrapper, "GrGetNextEvent"},
1368         /*  23 */ {GrCheckNextEventWrapper, "GrCheckNextEvent"},
1369         /*  24 */ {GrPeekEventWrapper, "GrPeekEvent"},
1370         /*  25 */ {GrLineWrapper, "GrLine"},
1371         /*  26 */ {GrPointWrapper, "GrPoint"},
1372         /*  27 */ {GrRectWrapper, "GrRect"},
1373         /*  28 */ {GrFillRectWrapper, "GrFillRect"},
1374         /*  29 */ {GrPolyWrapper, "GrPoly"},
1375         /*  30 */ {GrFillPolyWrapper, "GrFillPoly"},
1376         /*  31 */ {GrEllipseWrapper, "GrEllipse"},
1377         /*  32 */ {GrFillEllipseWrapper, "GrFillEllipse"},
1378         /*  33 */ {GrSetGCForegroundWrapper, "GrSetGCForeground"},
1379         /*  34 */ {GrSetGCBackgroundWrapper, "GrSetGCBackGround"},
1380         /*  35 */ {GrSetGCUseBackgroundWrapper, "GrSetGCUseBackGround"},
1381         /*  36 */ {GrSetGCModeWrapper, "GrSetGCMode"},
1382         /*  37 */ {GrSetGCFontWrapper, "GrSetGCFont"},
1383         /*  38 */ {GrGetGCTextSizeWrapper, "GrGetGCTextSize"},
1384         /*  39 */ {GsReadAreaWrapper, "GsReadArea"},
1385         /*  40 */ {GrAreaWrapper, "GrArea"},
1386         /*  41 */ {GrBitmapWrapper, "GrBitmap"},
1387         /*  42 */ {GrTextWrapper, "GrText"},
1388         /*  43 */ {GrNewCursorWrapper, "GrNewCursor"},
1389         /*  44 */ {GrMoveCursorWrapper, "GrMoveCursor"},
1390         /*  45 */ {GrGetSystemPaletteWrapper, "GrGetSystemPalette"},
1391         /*  46 */ {GrFindColorWrapper, "GrFindColor"},
1392         /*  47 */ {GrReparentWindowWrapper, "GrReparentWindow"},
1393         /*  48 */ {GrDrawImageFromFileWrapper, "GrDrawImageFromFile"},
1394         /*  49 */ {GrLoadImageFromFileWrapper, "GrLoadImageFromFile"},
1395         /*  50 */ {GrNewPixmapWrapper, "GrNewPixmap"},
1396         /*  51 */ {GrCopyAreaWrapper, "GrCopyArea"},
1397         /*  52 */ {GrSetFontSizeWrapper, "GrSetFontSize"},
1398         /*  53 */ {GrCreateFontWrapper, "GrCreateFont"},
1399         /*  54 */ {GrDestroyFontWrapper, "GrDestroyFont"},
1400         /*  55 */ {GrReqShmCmdsWrapper, "GrReqShmCmds"},
1401         /*  56 */ {GrShmCmdsFlushWrapper, "GrShmCmdsFlush"},
1402         /*  57 */ {GrSetFontRotationWrapper, "GrSetFontRotation"},
1403         /*  58 */ {GrSetFontAttrWrapper, "GrSetFontAttr"},
1404         /*  59 */ {GrSetSystemPaletteWrapper, "GrSetSystemPalette"},
1405         /*  60 */ {GrInjectEventWrapper, "GrInjectEvent"},
1406         /*  61 */ {GrNewRegionWrapper, "GrNewRegion"},
1407         /*  62 */ {GrDestroyRegionWrapper, "GrDestroyRegion"},
1408         /*  63 */ {GrUnionRectWithRegionWrapper, "GrUnionRectWithRegion"},
1409         /*  64 */ {GrUnionRegionWrapper, "GrUnionRegion"},
1410         /*  65 */ {GrIntersectRegionWrapper, "GrIntersectRegion"},
1411         /*  66 */ {GrSetGCRegionWrapper, "GrSetGCRegion"},
1412         /*  67 */ {GrSubtractRegionWrapper, "GrSubtractRegion"},
1413         /*  68 */ {GrXorRegionWrapper, "GrXorRegion"},
1414         /*  69 */ {GrPointInRegionWrapper, "GrPointInRegion"},
1415         /*  70 */ {GrRectInRegionWrapper, "GrRectInRegion"},    
1416         /*  71 */ {GrEmptyRegionWrapper, "GrEmptyRegion"},      
1417         /*  72 */ {GrEqualRegionWrapper, "GrEqualRegion"},      
1418         /*  73 */ {GrOffsetRegionWrapper, "GrOffsetRegion"},    
1419         /*  74 */ {GrGetRegionBoxWrapper, "GrGetRegionBox"},    
1420         /*  75 */ {GrNewPolygonRegionWrapper, "GrNewPolygonRegion"},    
1421         /*  76 */ {GrArcWrapper, "GrArc"},
1422         /*  77 */ {GrArcAngleWrapper, "GrArcAngle"},
1423         /*  78 */ {GrSetWMPropertiesWrapper, "GrSetWMProperties"},
1424         /*  79 */ {GrGetWMPropertiesWrapper, "GrGetWMProperties"},
1425         /*  80 */ {GrCloseWindowWrapper, "GrCloseWindow"},
1426         /*  81 */ {GrKillWindowWrapper, "GrKillWindow"},
1427         /*  82 */ {GrDrawImageToFitWrapper, "GrDrawImageToFit"},
1428         /*  83 */ {GrFreeImageWrapper, "GrFreeImage"},
1429         /*  84 */ {GrGetImageInfoWrapper, "GrGetImageInfo"},
1430         /*  85 */ {GrDrawImageBitsWrapper, "GrDrawImageBits"},
1431         /*  86 */ {GrPointsWrapper, "GrPoints"},
1432         /*  87 */ {GrGetFocusWrapper, "GrGetFocus"},
1433         /*  88 */ {GrGetSysColorWrapper, "GrGetSysColor"},
1434         /*  89 */ {GrSetScreenSaverTimeoutWrapper, "GrSetScreenSaverTimeout"},
1435         /*  90 */ {GrSetSelectionOwnerWrapper, "GrSetSelectionOwner"},
1436         /*  91 */ {GrGetSelectionOwnerWrapper, "GrGetSelectionOwner"},
1437         /*  92 */ {GrRequestClientDataWrapper, "GrRequestClientData"},
1438         /*  93 */ {GrSendClientDataWrapper, "GrSendClientData"},
1439         /*  94 */ {GrBellWrapper, "GrBell"},
1440         /*  95 */ {GrSetBackgroundPixmapWrapper, "GrSetBackgroundPixmap"},
1441         /*  96 */ {GrDestroyCursorWrapper, "GrDestroyCursor"},
1442         /*  97 */ {GrQueryTreeWrapper, "GrQueryTree"},
1443         /*  98 */ {GrCreateTimerWrapper, "GrCreateTimer"},
1444         /*  99 */ {GrDestroyTimerWrapper, "GrDestroyTimer"},
1445         /* 100 */ {GrSetPortraitModeWrapper, "GrSetPortraitMode"},
1446         /* 101 */ {GrImageBufferAllocWrapper, "GrImageBufferAlloc"},
1447         /* 102 */ {GrImageBufferSendWrapper, "GrImageBufferSend"},
1448         /* 103 */ {GrLoadImageFromBufferWrapper, "GrLoadImageFromBuffer"},
1449         /* 104 */ {GrDrawImageFromBufferWrapper, "GrDrawImageFromBuffer"},
1450         /* 105 */ {GrGetFontListWrapper, "GrGetFontList"},
1451         /* 106 */ {GrSetGCClipOriginWrapper, "GrSetGCClipOrigin"},
1452 };
1453
1454 void
1455 GrShmCmdsFlushWrapper(void *r)
1456 {
1457         nxShmCmdsFlushReq *req = r;
1458         unsigned char   reply;
1459 #if HAVE_SHAREDMEM_SUPPORT
1460         nxReq           *pr;
1461         int             length;
1462         unsigned char   *do_req, *do_req_last;
1463
1464         if ( current_shm_cmds == 0 || current_shm_cmds_size < req->size ) {
1465                 /* No or short shm present serverside, bug or mischief */
1466                 EPRINTF("nano-X: Ill behaved client assumes shm ok\n");
1467                 if ( req->reply ) {
1468                         reply = 0;
1469                         GsWrite(current_fd, &reply, 1);
1470                 }
1471                 return;
1472         }
1473
1474         do_req = current_shm_cmds;
1475         do_req_last = current_shm_cmds + req->size;
1476
1477         while ( do_req < do_req_last ) {
1478                 pr = (nxReq *)do_req;
1479                 length = GetReqAlignedLen(pr);
1480                 if ( pr->reqType < GrTotalNumCalls ) {
1481                         GrFunctions[pr->reqType].func(pr);
1482                 } else {
1483                         EPRINTF("nano-X: Error bad shm function!\n");
1484                 }
1485                 do_req += length;
1486         }
1487
1488         if ( req->reply ) {
1489                 reply = 1;
1490                 GsWrite(current_fd, &reply, 1);
1491         }
1492 #else
1493         /* no shared memory support*/
1494         if ( req->reply ) {
1495                 reply = 0;
1496                 GsWrite(current_fd, &reply, 1);
1497         }
1498 #endif /* HAVE_SHAREDMEM_SUPPORT*/
1499 }
1500
1501 /*
1502  * This function is used to bind to the named socket which is used to
1503  * accept connections from the clients.
1504  */
1505 int 
1506 GsOpenSocket(void)
1507 {
1508 #if ELKS
1509         struct sockaddr_na sckt;
1510 #ifndef SUN_LEN
1511 #define SUN_LEN(ptr)    (sizeof(sckt))
1512 #endif
1513 #elif __ECOS
1514         struct sockaddr_in sckt;
1515 #ifndef SUN_LEN
1516 #define SUN_LEN(ptr)    (sizeof(sckt))
1517 #endif
1518 #else
1519         struct sockaddr_un sckt;
1520 #ifndef SUN_LEN
1521 #define SUN_LEN(ptr)    ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
1522                                 + strlen ((ptr)->sun_path))
1523 #endif
1524 #endif /* ELKS */
1525
1526 #if ELKS
1527         if((un_sock = socket(AF_NANO, SOCK_STREAM, 0)) == -1)
1528                 return -1;
1529
1530         sckt.sun_family = AF_NANO;
1531         sckt.sun_no = GR_NUMB_SOCKET;
1532 #elif __ECOS
1533         // Create the socket
1534         if((un_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1535             return -1;
1536
1537         // Bind to any/all local IP addresses
1538         memset( &sckt, '\0', sizeof(sckt) );
1539         sckt.sin_family = AF_INET;
1540         sckt.sin_len = sizeof(sckt);
1541         sckt.sin_port = htons(6600);
1542         sckt.sin_addr.s_addr = INADDR_ANY;
1543 #else
1544         if (access(GR_NAMED_SOCKET, F_OK) == 0) {
1545                 /* FIXME: should try connecting to see if server is active */
1546                 if(unlink(GR_NAMED_SOCKET))
1547                         return -1;
1548         }
1549
1550         /* Create the socket: */
1551         if((un_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
1552                 return -1;
1553
1554         /* Bind a name to the socket: */
1555         sckt.sun_family = AF_UNIX;
1556         strncpy(sckt.sun_path, GR_NAMED_SOCKET, sizeof(sckt.sun_path));
1557 #endif /* ELKS */
1558         if(bind(un_sock, (struct sockaddr *) &sckt, SUN_LEN(&sckt)) < 0)
1559                 return -1;
1560
1561         /* Start listening on the socket: */
1562         if(listen(un_sock, 5) == -1)
1563                 return -1;
1564         return 1;
1565 }
1566
1567 void
1568 GsCloseSocket(void)
1569 {
1570         if(un_sock != -1)
1571                 close(un_sock);
1572         un_sock = -1;
1573         unlink(GR_NAMED_SOCKET);
1574 }
1575
1576 /*
1577  * This function is used to accept a connnection from a client.
1578  */
1579 void
1580 GsAcceptClient(void)
1581 {
1582         int i;
1583 #if ELKS
1584         struct sockaddr_na sckt;
1585 #elif __ECOS
1586         struct sockaddr_in sckt;
1587 #else
1588         struct sockaddr_un sckt;
1589 #endif
1590         size_t size = sizeof(sckt);
1591
1592         if((i = accept(un_sock, (struct sockaddr *) &sckt, &size)) == -1) {
1593 #ifdef __ECOS
1594             // All ports should do this
1595                 EPRINTF("nano-X: Error accept failed (%s)\n", strerror(errno));
1596 #else
1597                 EPRINTF("nano-X: Error accept failed (%d)\n", errno);
1598 #endif
1599                 return;
1600         }
1601         GsAcceptClientFd(i);
1602 }
1603
1604 /*
1605  * This function accepts a client ID, and searches through the
1606  * linked list of clients, returning a pointer to the relevant
1607  * structure or NULL if not found.
1608  */
1609 GR_CLIENT *
1610 GsFindClient(int fd)
1611 {
1612         GR_CLIENT *client;
1613
1614         client = root_client;
1615
1616         while(client) {
1617                 if(client->id == fd)
1618                         return(client);
1619                 client = client->next;
1620         }
1621         
1622         return 0;
1623 }
1624
1625 /*
1626  * Destroy windows and eventclient structures used by client.
1627  * Called by GsDropClient after a client has exited to clean
1628  * up resources.
1629  */
1630 void
1631 GsDestroyClientResources(GR_CLIENT * client)
1632 {
1633         GR_WINDOW     * wp, *nwp;
1634         GR_PIXMAP     * pp, *npp;
1635         GR_GC         * gp, *ngp;
1636         GR_REGION     * rp, *nrp;
1637         GR_FONT       * fp, *nfp;
1638         GR_IMAGE      * ip, *nip;
1639         GR_CURSOR     * cp, *ncp;
1640         GR_EVENT_CLIENT *ecp, *necp;
1641         GR_EVENT_CLIENT *pecp = NULL;
1642         GR_EVENT_LIST   *evp;
1643
1644 printf("Destroy client %d resources\n", client->id);
1645         /* search window list, destroy windows owned by client*/
1646         for(wp=listwp; wp; wp=nwp) {
1647                 nwp = wp->next;
1648                 /*
1649                  * Remove eventclient structures for this client
1650                  */
1651                 ecp = wp->eventclients;
1652                 while (ecp) {
1653                         necp = ecp->next;
1654                         if (ecp->client == client) {
1655 printf( "  Destroy window %d eventclient mask %08lx\n", wp->id, ecp->eventmask);
1656                                 if (ecp == wp->eventclients)
1657                                         wp->eventclients = ecp->next;
1658                                 else
1659                                         pecp->next = ecp->next;
1660                                 free(ecp);
1661                         } else
1662                                 pecp = ecp;
1663                         ecp = necp;
1664                 }
1665                 if (wp->owner == client) {
1666 printf("  Destroy window %d\n", wp->id);
1667                         GrDestroyWindow(wp->id);
1668                 }
1669         }
1670
1671         /* search pixmap list, destroy pixmaps owned by client*/
1672         for(pp=listpp; pp; pp=npp) {
1673                 npp = pp->next;
1674                 if (pp->owner == client) {
1675 printf("  Destroy pixmap %d\n", pp->id);
1676                         GrDestroyWindow(pp->id);
1677                 }
1678         }
1679
1680         /* free gc's owned by client*/
1681         for(gp=listgcp; gp; gp=ngp) {
1682                 ngp = gp->next;
1683                 if (gp->owner == client) {
1684 printf("  Destroy gc %d\n", gp->id);
1685                         GrDestroyGC(gp->id);
1686                 }
1687         }
1688
1689         /* free fonts owned by client*/
1690         for(fp=listfontp; fp; fp=nfp) {
1691                 nfp = fp->next;
1692                 if (fp->owner == client) {
1693 printf("  Destroy font %d\n", fp->id);
1694                         GrDestroyFont(fp->id);
1695                 }
1696         }
1697
1698         /* free regions owned by client*/
1699         for(rp=listregionp; rp; rp=nrp) {
1700                 nrp = rp->next;
1701                 if (rp->owner == client) {
1702 printf("  Destroy region %d\n", rp->id);
1703                         GrDestroyRegion(rp->id);
1704                 }
1705         }
1706
1707         /* free images owned by client*/
1708         for(ip=listimagep; ip; ip=nip) {
1709                 nip = ip->next;
1710                 if (ip->owner == client) {
1711 printf("  Destroy image %d\n", ip->id);
1712                         GrFreeImage(ip->id);
1713                 }
1714         }
1715
1716         /* free cursors owned by client*/
1717         for(cp=listcursorp; cp; cp=ncp) {
1718                 ncp = cp->next;
1719                 if (cp->owner == client) {
1720 printf("  Destroy cursor %d\n", cp->id);
1721                         GrDestroyCursor(cp->id);
1722                 }
1723         }
1724
1725         /* Free events associated with client*/
1726         evp = client->eventhead;
1727         while (evp) {
1728 printf("  Destroy event %d\n", evp->event.type);
1729                 client->eventhead = evp->next;
1730                 evp->next = eventfree;
1731                 eventfree = evp;
1732                 evp = client->eventhead;
1733         }
1734 }
1735
1736 /*
1737  * Display window, pixmap, gc, font, region lists
1738  */
1739 void
1740 GsPrintResources(void)
1741 {
1742         GR_WINDOW *wp;
1743         GR_PIXMAP *pp;
1744         GR_GC *gp;
1745         GR_REGION *rp;
1746         GR_FONT *fp;
1747         GR_IMAGE *ip;
1748
1749         /* window list*/
1750         printf("Window list:\n");
1751         for(wp=listwp; wp; wp=wp->next) {
1752                 printf("%d(%d),", wp->id, wp->owner? wp->owner->id: 0);
1753         }
1754         printf("\nPixmap list:\n");
1755         for(pp=listpp; pp; pp=pp->next) {
1756                 printf("%d(%d),", pp->id, pp->owner->id);
1757         }
1758         printf("\nGC list:\n");
1759         for(gp=listgcp; gp; gp=gp->next) {
1760                 printf("%d(%d),", gp->id, gp->owner->id);
1761         }
1762         printf("\nFont list:\n");
1763         for(fp=listfontp; fp; fp=fp->next) {
1764                 printf("%d(%d),", fp->id, fp->owner->id);
1765         }
1766         printf("\nRegion list:\n");
1767         for(rp=listregionp; rp; rp=rp->next) {
1768                 printf("%d(%d),", rp->id, rp->owner->id);
1769         }
1770         printf("\nImage list:\n");
1771         for(ip=listimagep; ip; ip=ip->next) {
1772                 printf("%d(%d),", ip->id, ip->owner->id);
1773         }
1774         printf("\n");
1775 }
1776
1777 /*
1778  * This is used to drop a client when it is detected that the connection to it
1779  * has been lost.
1780  */
1781 void
1782 GsDropClient(int fd)
1783 {
1784         GR_CLIENT *client;
1785
1786         if((client = GsFindClient(fd))) { /* If it exists */
1787                 close(fd);      /* Close the socket */
1788
1789                 GsDestroyClientResources(client);
1790                 if(client == root_client)
1791                         root_client = client->next;
1792                 /* Link the prev to the next */
1793                 if(client->prev) client->prev->next = client->next;
1794
1795                 /* Link the next to the prev */
1796                 if(client->next) client->next->prev = client->prev;
1797
1798 #if HAVE_SHAREDMEM_SUPPORT
1799                 if ( client->shm_cmds != 0 ) {
1800                         /* Free shared memory */
1801                         shmctl(client->shm_cmds_shmid,IPC_RMID,0);
1802                         shmdt(client->shm_cmds);
1803                 }
1804 #endif
1805 GsPrintResources();
1806                 free(client);   /* Free the structure */
1807
1808                 clipwp = NULL;  /* reset clip window*/
1809                 --connectcount;
1810         } else EPRINTF("nano-X: trying to drop non-existent client %d.\n", fd);
1811 }
1812
1813 /*
1814  * This is a wrapper to read() which handles error conditions, and
1815  * returns 0 for both error conditions and no data.
1816  */
1817 int
1818 #if ELKS
1819 GsRead(int fd, char *buf, int c)
1820 #else
1821 GsRead(int fd, void *buf, int c)
1822 #endif
1823 {
1824         int e, n;
1825
1826         n = 0;
1827
1828         while(n < c) {
1829                 e = read(fd, (buf + n), (c - n));
1830                 if(e <= 0) {
1831                         if (e == 0)
1832                                 EPRINTF("nano-X: client closed socket: %d\n", fd);
1833                         else EPRINTF("nano-X: GsRead failed %d %d: %d\r\n",
1834                                e, n, errno);
1835                         GsClose(fd);
1836                         return -1;
1837                 }
1838                 n += e;
1839         }
1840
1841         return 0;
1842 }
1843
1844 /*
1845  * This is a wrapper to write().
1846  */
1847 int GsWrite(int fd, void *buf, int c)
1848 {
1849         int e, n;
1850
1851         n = 0;
1852
1853         while(n < c) {
1854                 e = write(fd, ((char *) buf + n), (c - n));
1855                 if(e <= 0) {
1856                         GsClose(fd);
1857                         return -1;
1858                 }
1859                 n += e;
1860         }
1861
1862         return 0;
1863 }
1864
1865 int GsWriteType(int fd, short type)
1866 {
1867         return GsWrite(fd,&type,sizeof(type));
1868 }
1869
1870 /*
1871  * This function is used to parse and dispatch requests from the clients.
1872  * Note that the maximum request size is allocated from the stack
1873  * in this function.
1874  */
1875 void
1876 GsHandleClient(int fd)
1877 {
1878         nxReq * req;
1879         long    len;
1880         char    buf[MAXREQUESTSZ];
1881
1882         current_fd = fd;
1883 #if HAVE_SHAREDMEM_SUPPORT
1884         current_shm_cmds = curclient->shm_cmds;
1885         current_shm_cmds_size = curclient->shm_cmds_size;
1886 #endif
1887         /* read request header*/
1888         if(GsRead(fd, buf, sizeof(nxReq)))
1889                 return;
1890
1891         len = GetReqAlignedLen((nxReq *)&buf[0]);
1892         if(len > sizeof(nxReq)) {
1893                 if(len > MAXREQUESTSZ) {
1894                         EPRINTF("nano-X: GsHandleClient request too large: %ld > %d\n",
1895                                 len, MAXREQUESTSZ);
1896                         exit(1);
1897                 }
1898                 /* read additional request data*/
1899                 if(GsRead(fd, &buf[sizeof(nxReq)], len-sizeof(nxReq)))
1900                         return;
1901         }
1902         req = (nxReq *)&buf[0];
1903
1904         if(req->reqType < GrTotalNumCalls) {
1905                 curfunc = GrFunctions[req->reqType].name;
1906                 /*DPRINTF("HandleClient %s\n", curfunc);*/
1907                 GrFunctions[req->reqType].func(req);
1908         } else {
1909                 EPRINTF("nano-X: GsHandleClient bad function\n");
1910         }
1911 }