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
8 * Permission is granted to use, distribute, or modify this source,
9 * provided that this copyright notice remains intact.
11 * Completely rewritten for speed by Greg Haerr
13 * This is the server side of the network interface, which accepts
14 * connections from clients, receives functions from them, and dispatches
23 #include <sys/socket.h>
24 #if HAVE_SHAREDMEM_SUPPORT
25 #include <sys/types.h>
30 #include <linuxmt/na.h>
32 #include <netinet/in.h>
40 /* fix bad MIPS sys headers...*/
42 #define SOCK_STREAM 2 /* <asm/socket.h>*/
46 extern GR_CLIENT *root_client;
47 extern int current_fd;
49 static int GsWriteType(int,short);
52 * Wrapper functions called after full packet read
55 GrOpenWrapper(void *r)
59 /* store process id of client*/
60 curclient->processid = req->pid;
66 GrCloseWrapper(void *r)
72 GrGetScreenInfoWrapper(void *r)
77 GsWriteType(current_fd,GrNumGetScreenInfo);
78 GsWrite(current_fd, &si, sizeof(si));
82 GrGetSysColorWrapper(void *r)
84 nxGetSysColorReq *req = r;
85 GR_COLOR color = GrGetSysColor(req->index);
87 GsWriteType(current_fd, GrNumGetSysColor);
88 GsWrite(current_fd, &color, sizeof(color));
92 GrNewWindowWrapper(void *r)
94 nxNewWindowReq *req = r;
97 wid = GrNewWindow(req->parentid, req->x, req->y, req->width,
98 req->height, req->bordersize, req->backgroundcolor,
101 GsWriteType(current_fd,GrNumNewWindow);
102 GsWrite(current_fd, &wid, sizeof(wid));
107 GrNewPixmapWrapper(void *r)
109 nxNewPixmapReq *req = r;
112 /* FIXME: Add support for passing info about shared memory
115 wid = GrNewPixmap(req->width, req->height, 0);
117 GsWriteType(current_fd,GrNumNewPixmap);
118 GsWrite(current_fd, &wid, sizeof(wid));
122 GrNewInputWindowWrapper(void *r)
124 nxNewInputWindowReq *req = r;
127 wid = GrNewInputWindow(req->parentid, req->x, req->y, req->width,
129 GsWriteType(current_fd,GrNumNewInputWindow);
130 GsWrite(current_fd, &wid, sizeof(wid));
134 GrDestroyWindowWrapper(void *r)
136 nxDestroyWindowReq *req = r;
138 GrDestroyWindow(req->windowid);
142 GrNewGCWrapper(void *r)
144 GR_GC_ID gc = GrNewGC();
146 GsWriteType(current_fd,GrNumNewGC);
147 GsWrite(current_fd, &gc, sizeof(gc));
151 GrCopyGCWrapper(void *r)
153 nxCopyGCReq *req = r;
156 gcnew = GrCopyGC(req->gcid);
157 GsWriteType(current_fd,GrNumCopyGC);
158 GsWrite(current_fd, &gcnew, sizeof(gcnew));
162 GrGetGCInfoWrapper(void *r)
164 nxGetGCInfoReq *req = r;
167 GrGetGCInfo(req->gcid, &gcinfo);
168 GsWriteType(current_fd,GrNumGetGCInfo);
169 GsWrite(current_fd, &gcinfo, sizeof(gcinfo));
173 GrDestroyGCWrapper(void *r)
175 nxDestroyGCReq *req = r;
177 GrDestroyGC(req->gcid);
181 GrNewRegionWrapper(void *r)
183 GR_REGION_ID region = GrNewRegion();
185 GsWriteType(current_fd, GrNumNewRegion);
186 GsWrite(current_fd, ®ion, sizeof(region));
190 GrDestroyRegionWrapper(void *r)
192 nxDestroyRegionReq *req = r;
194 GrDestroyRegion(req->regionid);
198 GrIntersectRegionWrapper(void *r)
200 nxIntersectRegionReq *req = r;
202 GrIntersectRegion(req->regionid, req->srcregionid1,
207 GrUnionRectWithRegionWrapper(void *r)
209 nxUnionRectWithRegionReq *req = r;
211 GrUnionRectWithRegion(req->regionid, &(req->rect));
215 GrUnionRegionWrapper(void *r)
217 nxUnionRegionReq *req = r;
219 GrUnionRegion(req->regionid, req->srcregionid1, req->srcregionid2);
223 GrSubtractRegionWrapper(void *r)
225 nxSubtractRegionReq *req = r;
227 GrSubtractRegion(req->regionid, req->srcregionid1, req->srcregionid2);
231 GrXorRegionWrapper(void *r)
233 nxXorRegionReq *req = r;
235 GrXorRegion(req->regionid, req->srcregionid1, req->srcregionid2);
239 GrPointInRegionWrapper(void *r)
241 nxPointInRegionReq *req = r;
242 GR_BOOL ret_value = GrPointInRegion(req->regionid, req->x, req->y);
244 GsWriteType(current_fd, GrNumPointInRegion);
245 GsWrite(current_fd, &ret_value, sizeof(ret_value));
249 GrRectInRegionWrapper(void *r)
251 nxRectInRegionReq *req = r;
252 unsigned short ret_value;
254 ret_value = (unsigned short)GrRectInRegion(req->regionid,
255 req->x, req->y, req->w, req->h);
257 GsWriteType(current_fd, GrNumRectInRegion);
258 GsWrite(current_fd, &ret_value, sizeof(ret_value));
262 GrEmptyRegionWrapper(void *r)
264 nxEmptyRegionReq *req = r;
267 ret_value = GrEmptyRegion(req->regionid);
268 GsWriteType(current_fd, GrNumEmptyRegion);
269 GsWrite(current_fd, &ret_value, sizeof(ret_value));
273 GrEqualRegionWrapper(void *r)
275 nxEqualRegionReq *req = r;
278 ret_value = GrEqualRegion(req->region1, req->region2);
279 GsWriteType(current_fd, GrNumEqualRegion);
280 GsWrite(current_fd, &ret_value, sizeof(ret_value));
284 GrOffsetRegionWrapper(void *r)
286 nxOffsetRegionReq *req = r;
288 GrOffsetRegion(req->region, req->dx, req->dy);
292 GrSetGCRegionWrapper(void *r)
294 nxSetGCRegionReq *req = r;
296 GrSetGCRegion(req->gcid, req->regionid);
300 GrSetGCClipOriginWrapper(void *r)
302 nxSetGCClipOriginReq *req = r;
303 GrSetGCClipOrigin(req->gcid, req->xoff, req->yoff);
307 GrGetRegionBoxWrapper(void *r)
309 nxRectInRegionReq *req = r;
313 ret_value = GrGetRegionBox(req->regionid, &ret_rect);
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));
322 GrNewPolygonRegionWrapper(void *r)
325 nxNewPolygonRegionReq *req = r;
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));
333 GsWriteType(current_fd, GrNumNewPolygonRegion);
334 GsWrite(current_fd, ®ion, sizeof(region));
338 GrMapWindowWrapper(void *r)
340 nxMapWindowReq *req = r;
342 GrMapWindow(req->windowid);
346 GrUnmapWindowWrapper(void *r)
348 nxUnmapWindowReq *req = r;
350 GrUnmapWindow(req->windowid);
354 GrRaiseWindowWrapper(void *r)
356 nxRaiseWindowReq *req = r;
358 GrRaiseWindow(req->windowid);
362 GrLowerWindowWrapper(void *r)
364 nxLowerWindowReq *req = r;
366 GrLowerWindow(req->windowid);
370 GrMoveWindowWrapper(void *r)
372 nxMoveWindowReq *req = r;
374 GrMoveWindow(req->windowid, req->x, req->y);
378 GrResizeWindowWrapper(void *r)
380 nxResizeWindowReq *req = r;
382 GrResizeWindow(req->windowid, req->width, req->height);
386 GrReparentWindowWrapper(void *r)
388 nxReparentWindowReq *req = r;
390 GrReparentWindow(req->windowid, req->parentid, req->x, req->y);
394 GrGetWindowInfoWrapper(void *r)
396 nxGetWindowInfoReq *req = r;
399 GrGetWindowInfo(req->windowid, &wi);
400 GsWriteType(current_fd,GrNumGetWindowInfo);
401 GsWrite(current_fd, &wi, sizeof(wi));
405 GrGetFontInfoWrapper(void *r)
407 nxGetFontInfoReq *req = r;
410 GrGetFontInfo(req->fontid, &fi);
411 GsWriteType(current_fd,GrNumGetFontInfo);
412 GsWrite(current_fd, &fi, sizeof(fi));
416 GrGetFocusWrapper(void *r)
418 GR_WINDOW_ID wid = GrGetFocus();
420 GsWriteType(current_fd, GrNumGetFocus);
421 GsWrite(current_fd, &wid, sizeof(wid));
425 GrSetFocusWrapper(void *r)
427 nxSetFocusReq *req = r;
429 GrSetFocus(req->windowid);
433 GrSetWindowCursorWrapper(void *r)
435 nxSetWindowCursorReq *req = r;
437 GrSetWindowCursor(req->windowid, req->cursorid);
441 GrClearAreaWrapper(void *r)
443 nxClearAreaReq *req = r;
445 GrClearArea(req->windowid, req->x, req->y, req->width,
446 req->height, req->exposeflag);
450 GrSelectEventsWrapper(void *r)
452 nxSelectEventsReq *req = r;
454 GrSelectEvents(req->windowid, req->eventmask);
458 GrGetNextEventWrapper(void *r)
461 /* tell main loop to call Finish routine on event*/
462 curclient->waiting_for_event = TRUE;
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;
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);
483 /* Complete the GrGetNextEvent call from client.
484 * The client is still waiting on a read at this point.
487 GrGetNextEventWrapperFinish(int fd)
490 GR_EVENT_CLIENT_DATA *cde;
492 /* get the event and pass it to client*/
493 /* this will never be GR_EVENT_TYPE_NONE*/
494 GrCheckNextEvent(&evt);
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;
501 GsWrite(fd, cde->data, cde->datalen);
508 GrCheckNextEventWrapper(void *r)
511 GR_EVENT_CLIENT_DATA *cde;
513 GrCheckNextEvent(&evt);
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;
520 GsWrite(current_fd, cde->data, cde->datalen);
527 GrPeekEventWrapper(void *r)
531 GR_EVENT_CLIENT_DATA *cde;
533 ret = GrPeekEvent(&evt);
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;
540 GsWrite(current_fd, cde->data, cde->datalen);
544 GsWrite(current_fd, &ret, sizeof(GR_CHAR));
548 GrLineWrapper(void *r)
552 GrLine(req->drawid, req->gcid, req->x1, req->y1, req->x2, req->y2);
556 GrPointWrapper(void *r)
560 GrPoint(req->drawid, req->gcid, req->x, req->y);
565 GrPointsWrapper(void *r)
567 nxPointsReq *req = r;
570 count = GetReqVarLen(req) / sizeof(GR_POINT);
571 GrPoints(req->drawid, req->gcid, count, (GR_POINT *)GetReqData(req));
575 GrRectWrapper(void *r)
579 GrRect(req->drawid, req->gcid, req->x, req->y, req->width, req->height);
583 GrFillRectWrapper(void *r)
585 nxFillRectReq *req = r;
587 GrFillRect(req->drawid, req->gcid, req->x, req->y, req->width,
592 GrPolyWrapper(void *r)
597 count = GetReqVarLen(req) / sizeof(GR_POINT);
598 GrPoly(req->drawid, req->gcid, count, (GR_POINT *)GetReqData(req));
601 /* FIXME: fails with pointtable size > 64k if sizeof(int) == 2*/
603 GrFillPolyWrapper(void *r)
608 count = GetReqVarLen(req) / sizeof(GR_POINT);
609 GrFillPoly(req->drawid, req->gcid, count, (GR_POINT *)GetReqData(req));
613 GrEllipseWrapper(void *r)
615 nxEllipseReq *req = r;
617 GrEllipse(req->drawid, req->gcid, req->x, req->y, req->rx, req->ry);
621 GrFillEllipseWrapper(void *r)
623 nxFillEllipseReq *req = r;
625 GrFillEllipse(req->drawid, req->gcid, req->x, req->y, req->rx, req->ry);
629 GrArcWrapper(void *r)
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);
638 GrArcAngleWrapper(void *r)
640 nxArcAngleReq *req = r;
642 GrArcAngle(req->drawid, req->gcid, req->x, req->y, req->rx, req->ry,
643 req->angle1, req->angle2, req->type);
647 GrSetGCForegroundWrapper(void *r)
649 nxSetGCForegroundReq *req = r;
651 GrSetGCForeground(req->gcid, req->color);
655 GrSetGCBackgroundWrapper(void *r)
657 nxSetGCBackgroundReq *req = r;
659 GrSetGCBackground(req->gcid, req->color);
663 GrSetGCUseBackgroundWrapper(void *r)
665 nxSetGCUseBackgroundReq *req = r;
667 GrSetGCUseBackground(req->gcid, req->flag);
671 GrSetGCModeWrapper(void *r)
673 nxSetGCModeReq *req = r;
675 GrSetGCMode(req->gcid, req->mode);
679 GrCreateFontWrapper(void *r)
681 nxCreateFontReq *req = r;
685 fontid = GrCreateFont(NULL, 0, &req->lf);
687 fontid = GrCreateFont(req->lf.lfFaceName, req->height, NULL);
689 GsWriteType(current_fd,GrNumCreateFont);
690 GsWrite(current_fd, &fontid, sizeof(fontid));
694 GrSetFontSizeWrapper(void *r)
696 nxSetFontSizeReq *req = r;
698 GrSetFontSize(req->fontid, req->fontsize);
702 GrSetFontRotationWrapper(void *r)
704 nxSetFontRotationReq *req = r;
706 GrSetFontRotation(req->fontid, req->tenthdegrees);
710 GrSetFontAttrWrapper(void *r)
712 nxSetFontAttrReq *req = r;
714 GrSetFontAttr(req->fontid, req->setflags, req->clrflags);
718 GrDestroyFontWrapper(void *r)
720 nxDestroyFontReq *req = r;
722 GrDestroyFont(req->fontid);
726 GrSetGCFontWrapper(void *r)
728 nxSetGCFontReq *req = r;
730 GrSetGCFont(req->gcid, req->fontid);
734 GrGetGCTextSizeWrapper(void *r)
736 nxGetGCTextSizeReq *req = r;
737 GR_SIZE retwidth, retheight, retbase;
739 GrGetGCTextSize(req->gcid, GetReqData(req), GetReqVarLen(req),
740 req->flags, &retwidth, &retheight, &retbase);
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));
748 /* FIXME: fails with size > 64k if sizeof(int) == 2*/
750 GsReadAreaWrapper(void *r)
752 nxReadAreaReq *req = r;
756 /* FIXME: optimize for smaller pixelvals*/
757 size = req->width * req->height * sizeof(GR_PIXELVAL);
759 if(!(area = malloc(size))) {
760 /*GsPutCh(current_fd, GrRetENoMem);*/ /* FIXME*/
764 GrReadArea(req->drawid, req->x, req->y, req->width, req->height, area);
765 GsWriteType(current_fd,GrNumReadArea);
766 GsWrite(current_fd, area, size);
770 /* FIXME: fails with size > 64k if sizeof(int) == 2*/
772 GrAreaWrapper(void *r)
776 GrArea(req->drawid, req->gcid, req->x, req->y, req->width, req->height,
777 GetReqData(req), req->pixtype);
780 /* FIXME: fails with bitmapsize > 64k if sizeof(int) == 2*/
782 GrBitmapWrapper(void *r)
784 nxBitmapReq *req = r;
786 GrBitmap(req->drawid, req->gcid, req->x, req->y, req->width,
787 req->height, GetReqData(req));
791 GrDrawImageBitsWrapper(void *r)
793 nxDrawImageBitsReq *req = r;
798 hdr.width = req->width;
799 hdr.height = req->height;
800 hdr.planes = req->planes;
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);
815 GrCopyAreaWrapper(void *r)
817 nxCopyAreaReq *req = r;
819 GrCopyArea(req->drawid, req->gcid, req->x, req->y, req->width, req->height,
820 req->srcid, req->srcx, req->srcy, req->op);
824 GrTextWrapper(void *r)
828 GrText(req->drawid, req->gcid, req->x, req->y, GetReqData(req),
829 req->count, req->flags);
833 GrNewCursorWrapper(void *r)
835 nxNewCursorReq *req = r;
838 GR_CURSOR_ID cursorid;
840 varlen = GetReqVarLen(req);
841 bitmap = GetReqData(req);
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));
847 GsWriteType(current_fd, GrNumNewCursor);
848 GsWrite(current_fd, &cursorid, sizeof(cursorid));
852 GrMoveCursorWrapper(void *r)
854 nxMoveCursorReq *req = r;
856 GrMoveCursor(req->x, req->y);
860 GrGetSystemPaletteWrapper(void *r)
864 GrGetSystemPalette(&pal);
865 GsWriteType(current_fd,GrNumGetSystemPalette);
866 GsWrite(current_fd, &pal, sizeof(pal));
870 GrSetSystemPaletteWrapper(void *r)
872 nxSetSystemPaletteReq *req = r;
875 pal.count = req->count;
876 memcpy(pal.palette, req->palette, sizeof(pal.palette));
877 GrSetSystemPalette(req->first, &pal);
881 GrFindColorWrapper(void *r)
883 nxFindColorReq *req = r;
886 GrFindColor(req->color, &pixel);
887 GsWriteType(current_fd,GrNumFindColor);
888 GsWrite(current_fd, &pixel, sizeof(pixel));
892 GrInjectEventWrapper(void *r)
894 nxInjectEventReq *req = r;
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);
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);
915 GrSetWMPropertiesWrapper(void *r)
917 nxSetWMPropertiesReq *req = r;
918 GR_WM_PROPERTIES *props = GetReqData(req);
920 if(GetReqVarLen(req) - sizeof(GR_WM_PROPERTIES))
921 props->title = (char *)props + sizeof(GR_WM_PROPERTIES);
924 GrSetWMProperties(req->windowid, props);
928 GrGetWMPropertiesWrapper(void *r)
930 nxGetWMPropertiesReq *req = r;
932 GR_WM_PROPERTIES props;
934 GrGetWMProperties(req->windowid, &props);
937 textlen = strlen(props.title) + 1;
940 GsWriteType(current_fd,GrNumGetWMProperties);
941 GsWrite(current_fd, &props, sizeof(props));
942 GsWrite(current_fd, &textlen, sizeof(textlen));
944 GsWrite(current_fd, props.title, textlen);
948 GrCloseWindowWrapper(void *r)
950 nxCloseWindowReq *req = r;
952 GrCloseWindow(req->windowid);
956 GrKillWindowWrapper(void *r)
958 nxKillWindowReq *req = r;
960 GrKillWindow(req->windowid);
964 GrDrawImageFromFileWrapper(void *r)
966 nxDrawImageFromFileReq *req = r;
968 GrDrawImageFromFile(req->drawid, req->gcid, req->x, req->y, req->width,
969 req->height, GetReqData(req), req->flags);
973 GrLoadImageFromFileWrapper(void *r)
975 nxLoadImageFromFileReq *req = r;
978 id = GrLoadImageFromFile(GetReqData(req), req->flags);
979 GsWriteType(current_fd, GrNumLoadImageFromFile);
980 GsWrite(current_fd, &id, sizeof(id));
984 GrDrawImageToFitWrapper(void *r)
986 nxDrawImageToFitReq *req = r;
988 GrDrawImageToFit(req->drawid, req->gcid, req->x, req->y, req->width,
989 req->height, req->imageid);
993 GrFreeImageWrapper(void *r)
995 nxFreeImageReq *req = r;
997 GrFreeImage(req->id);
1001 GrGetImageInfoWrapper(void *r)
1003 nxGetImageInfoReq *req = r;
1006 GrGetImageInfo(req->id, &info);
1007 GsWriteType(current_fd, GrNumGetImageInfo);
1008 GsWrite(current_fd, &info, sizeof(info));
1012 GrSetScreenSaverTimeoutWrapper(void *r)
1014 nxSetScreenSaverTimeoutReq *req = r;
1016 GrSetScreenSaverTimeout(req->timeout);
1020 GrSetSelectionOwnerWrapper(void *r)
1022 nxSetSelectionOwnerReq *req = r;
1024 GrSetSelectionOwner(req->wid, GetReqData(req));
1028 GrGetSelectionOwnerWrapper(void *r)
1034 wid = GrGetSelectionOwner(&typelist);
1035 GsWriteType(current_fd, GrNumGetSelectionOwner);
1036 GsWrite(current_fd, &wid, sizeof(wid));
1039 len = strlen(typelist) + 1;
1040 GsWrite(current_fd, &len, sizeof(len));
1041 GsWrite(current_fd, typelist, len);
1046 GrRequestClientDataWrapper(void *r)
1048 nxRequestClientDataReq *req = r;
1050 GrRequestClientData(req->wid, req->rid, req->serial, req->mimetype);
1054 GrSendClientDataWrapper(void *r)
1056 nxSendClientDataReq *req = r;
1058 GrSendClientData(req->wid, req->did, req->serial, req->len,
1059 GetReqVarLen(req), GetReqData(req));
1063 GrBellWrapper(void *r)
1069 GrSetBackgroundPixmapWrapper(void *r)
1071 nxSetBackgroundPixmapReq *req = r;
1073 GrSetBackgroundPixmap(req->wid, req->pixmap, req->flags);
1077 GrDestroyCursorWrapper(void *r)
1079 nxDestroyCursorReq *req = r;
1081 GrDestroyCursor(req->cursorid);
1085 GrQueryTreeWrapper(void *r)
1087 nxQueryTreeReq *req = r;
1088 GR_WINDOW_ID parentid;
1089 GR_WINDOW_ID * children;
1092 GrQueryTree(req->windowid, &parentid, &children, &nchildren);
1094 GsWriteType(current_fd, GrNumQueryTree);
1095 GsWrite(current_fd, &parentid, sizeof(parentid));
1096 GsWrite(current_fd, &nchildren, sizeof(nchildren));
1098 GsWrite(current_fd, children, nchildren * sizeof(GR_WINDOW_ID));
1104 GrCreateTimerWrapper(void *r)
1106 nxCreateTimerReq *req = r;
1107 GR_TIMER_ID timerid;
1109 timerid = GrCreateTimer(req->wid, req->period);
1111 GsWriteType(current_fd, GrNumCreateTimer);
1112 GsWrite(current_fd, &timerid, sizeof (timerid));
1115 typedef struct image_list {
1121 struct image_list *next;
1124 static imagelist_t *imageListHead = 0;
1125 static imagelist_t *imageListTail = 0;
1126 static int imageListId = 0;
1128 static void freeImageBuffer(imagelist_t *buffer) {
1130 imagelist_t *prev = 0;
1131 imagelist_t *ptr = imageListHead;
1134 if (ptr == buffer) {
1136 prev->next = buffer->next;
1138 imageListHead = buffer->next;
1140 if (!imageListHead) imageListTail = 0;
1152 static void GrImageBufferAllocWrapper(void *r) {
1153 nxImageBufferAllocReq *req = r;
1155 /* Add a new buffer to the end of the list */
1157 if (!imageListTail) {
1158 imageListHead = imageListTail = (imagelist_t *) malloc(sizeof(imagelist_t));
1161 imageListTail->next = (imagelist_t *) malloc(sizeof(imagelist_t));
1162 imageListTail = imageListTail->next;
1165 imageListTail->id = ++imageListId;
1166 imageListTail->data = (void *) malloc(req->size);
1167 imageListTail->size = req->size;
1168 imageListTail->offset = 0;
1170 imageListTail->next = 0;
1172 GsWriteType(current_fd,GrNumImageBufferAlloc);
1173 GsWrite(current_fd, &imageListTail->id, sizeof(int));
1176 static void GrImageBufferSendWrapper(void *r) {
1180 imagelist_t *buffer = 0;
1181 nxImageBufferSendReq *req = r;
1183 for(buffer = imageListHead; buffer; buffer = buffer->next)
1184 if (buffer->id == req->buffer_id) break;
1186 if (!buffer) return;
1188 if (buffer->offset + req->size >= buffer->size)
1189 csize = buffer->size - buffer->offset;
1195 memcpy((void *) (buffer->data + buffer->offset),
1196 GetReqData(req), csize);
1198 buffer->offset += csize;
1201 void GrLoadImageFromBufferWrapper(void *r) {
1204 imagelist_t *buffer = 0;
1206 nxLoadImageFromBufferReq *req = r;
1208 for(buffer = imageListHead; buffer; buffer = buffer->next)
1209 if (buffer->id == req->buffer) break;
1211 if (!buffer) return;
1213 id = GrLoadImageFromBuffer(buffer->data, buffer->size, req->flags);
1215 GsWriteType(current_fd, GrNumLoadImageFromBuffer);
1216 GsWrite(current_fd, &id, sizeof(id));
1218 freeImageBuffer(buffer);
1221 void GrDrawImageFromBufferWrapper(void *r) {
1223 imagelist_t *buffer = 0;
1225 nxDrawImageFromBufferReq *req = r;
1227 for(buffer = imageListHead; buffer; buffer = buffer->next)
1228 if (buffer->id == req->buffer) break;
1230 if (!buffer) return;
1232 GrDrawImageFromBuffer(req->drawid, req->gcid, req->x, req->y, req->width,
1233 req->height, buffer->data, buffer->size,
1236 freeImageBuffer(buffer);
1242 GrDestroyTimerWrapper(void *r)
1244 nxDestroyTimerReq *req = r;
1246 GrDestroyTimer(req->timerid);
1250 GrSetPortraitModeWrapper(void *r)
1252 nxSetPortraitModeReq *req = r;
1254 GrSetPortraitMode(req->portraitmode);
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.
1263 #define SHMKEY_BASE 1000000
1264 #define SHMKEY_MAX 256
1267 GrReqShmCmdsWrapper(void *r)
1269 #if HAVE_SHAREDMEM_SUPPORT
1270 nxReqShmCmdsReq *req = r;
1274 if ( curclient->shm_cmds != 0 )
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 )
1283 tmp = shmat(shmid,0,0);
1284 if ( tmp == (char *)-1 )
1286 curclient->shm_cmds = tmp;
1287 curclient->shm_cmds_shmid = shmid;
1288 curclient->shm_cmds_size = req->size;
1297 DPRINTF("Shm: Request key granted=%d\n",key);
1298 GsWrite(current_fd, &key, sizeof(key));
1300 /* return no shared memory support*/
1302 GsWrite(current_fd, &key, sizeof(key));
1303 #endif /* HAVE_SHAREDMEM_SUPPORT*/
1307 GrGetFontListWrapper(void *r)
1311 int i, ttlen, mwlen;
1313 GrGetFontList(&list, &num);
1315 GsWriteType(current_fd, GrNumGetFontList);
1317 /* the number of strings comming in */
1318 GsWrite(current_fd, &num, sizeof(int));
1321 for(i = 0; i < num; i++) {
1322 ttlen = strlen(list[i]->ttname) + 1;
1323 mwlen = strlen(list[i]->mwname) + 1;
1325 GsWrite(current_fd, &ttlen, sizeof(int));
1326 GsWrite(current_fd, list[i]->ttname, ttlen * sizeof(char));
1328 GsWrite(current_fd, &mwlen, sizeof(int));
1329 GsWrite(current_fd, list[i]->mwname, mwlen * sizeof(char));
1332 GrFreeFontList(&list, num);
1336 void GrShmCmdsFlushWrapper(void *r);
1339 * Handler functions, ordered by reqType
1342 void (*func)(void *);
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"},
1455 GrShmCmdsFlushWrapper(void *r)
1457 nxShmCmdsFlushReq *req = r;
1458 unsigned char reply;
1459 #if HAVE_SHAREDMEM_SUPPORT
1462 unsigned char *do_req, *do_req_last;
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");
1469 GsWrite(current_fd, &reply, 1);
1474 do_req = current_shm_cmds;
1475 do_req_last = current_shm_cmds + req->size;
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);
1483 EPRINTF("nano-X: Error bad shm function!\n");
1490 GsWrite(current_fd, &reply, 1);
1493 /* no shared memory support*/
1496 GsWrite(current_fd, &reply, 1);
1498 #endif /* HAVE_SHAREDMEM_SUPPORT*/
1502 * This function is used to bind to the named socket which is used to
1503 * accept connections from the clients.
1509 struct sockaddr_na sckt;
1511 #define SUN_LEN(ptr) (sizeof(sckt))
1514 struct sockaddr_in sckt;
1516 #define SUN_LEN(ptr) (sizeof(sckt))
1519 struct sockaddr_un sckt;
1521 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
1522 + strlen ((ptr)->sun_path))
1527 if((un_sock = socket(AF_NANO, SOCK_STREAM, 0)) == -1)
1530 sckt.sun_family = AF_NANO;
1531 sckt.sun_no = GR_NUMB_SOCKET;
1533 // Create the socket
1534 if((un_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
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;
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))
1550 /* Create the socket: */
1551 if((un_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
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));
1558 if(bind(un_sock, (struct sockaddr *) &sckt, SUN_LEN(&sckt)) < 0)
1561 /* Start listening on the socket: */
1562 if(listen(un_sock, 5) == -1)
1573 unlink(GR_NAMED_SOCKET);
1577 * This function is used to accept a connnection from a client.
1580 GsAcceptClient(void)
1584 struct sockaddr_na sckt;
1586 struct sockaddr_in sckt;
1588 struct sockaddr_un sckt;
1590 size_t size = sizeof(sckt);
1592 if((i = accept(un_sock, (struct sockaddr *) &sckt, &size)) == -1) {
1594 // All ports should do this
1595 EPRINTF("nano-X: Error accept failed (%s)\n", strerror(errno));
1597 EPRINTF("nano-X: Error accept failed (%d)\n", errno);
1601 GsAcceptClientFd(i);
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.
1610 GsFindClient(int fd)
1614 client = root_client;
1617 if(client->id == fd)
1619 client = client->next;
1626 * Destroy windows and eventclient structures used by client.
1627 * Called by GsDropClient after a client has exited to clean
1631 GsDestroyClientResources(GR_CLIENT * client)
1633 GR_WINDOW * wp, *nwp;
1634 GR_PIXMAP * pp, *npp;
1636 GR_REGION * rp, *nrp;
1638 GR_IMAGE * ip, *nip;
1639 GR_CURSOR * cp, *ncp;
1640 GR_EVENT_CLIENT *ecp, *necp;
1641 GR_EVENT_CLIENT *pecp = NULL;
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) {
1649 * Remove eventclient structures for this client
1651 ecp = wp->eventclients;
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;
1659 pecp->next = ecp->next;
1665 if (wp->owner == client) {
1666 printf(" Destroy window %d\n", wp->id);
1667 GrDestroyWindow(wp->id);
1671 /* search pixmap list, destroy pixmaps owned by client*/
1672 for(pp=listpp; pp; pp=npp) {
1674 if (pp->owner == client) {
1675 printf(" Destroy pixmap %d\n", pp->id);
1676 GrDestroyWindow(pp->id);
1680 /* free gc's owned by client*/
1681 for(gp=listgcp; gp; gp=ngp) {
1683 if (gp->owner == client) {
1684 printf(" Destroy gc %d\n", gp->id);
1685 GrDestroyGC(gp->id);
1689 /* free fonts owned by client*/
1690 for(fp=listfontp; fp; fp=nfp) {
1692 if (fp->owner == client) {
1693 printf(" Destroy font %d\n", fp->id);
1694 GrDestroyFont(fp->id);
1698 /* free regions owned by client*/
1699 for(rp=listregionp; rp; rp=nrp) {
1701 if (rp->owner == client) {
1702 printf(" Destroy region %d\n", rp->id);
1703 GrDestroyRegion(rp->id);
1707 /* free images owned by client*/
1708 for(ip=listimagep; ip; ip=nip) {
1710 if (ip->owner == client) {
1711 printf(" Destroy image %d\n", ip->id);
1712 GrFreeImage(ip->id);
1716 /* free cursors owned by client*/
1717 for(cp=listcursorp; cp; cp=ncp) {
1719 if (cp->owner == client) {
1720 printf(" Destroy cursor %d\n", cp->id);
1721 GrDestroyCursor(cp->id);
1725 /* Free events associated with client*/
1726 evp = client->eventhead;
1728 printf(" Destroy event %d\n", evp->event.type);
1729 client->eventhead = evp->next;
1730 evp->next = eventfree;
1732 evp = client->eventhead;
1737 * Display window, pixmap, gc, font, region lists
1740 GsPrintResources(void)
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);
1754 printf("\nPixmap list:\n");
1755 for(pp=listpp; pp; pp=pp->next) {
1756 printf("%d(%d),", pp->id, pp->owner->id);
1758 printf("\nGC list:\n");
1759 for(gp=listgcp; gp; gp=gp->next) {
1760 printf("%d(%d),", gp->id, gp->owner->id);
1762 printf("\nFont list:\n");
1763 for(fp=listfontp; fp; fp=fp->next) {
1764 printf("%d(%d),", fp->id, fp->owner->id);
1766 printf("\nRegion list:\n");
1767 for(rp=listregionp; rp; rp=rp->next) {
1768 printf("%d(%d),", rp->id, rp->owner->id);
1770 printf("\nImage list:\n");
1771 for(ip=listimagep; ip; ip=ip->next) {
1772 printf("%d(%d),", ip->id, ip->owner->id);
1778 * This is used to drop a client when it is detected that the connection to it
1782 GsDropClient(int fd)
1786 if((client = GsFindClient(fd))) { /* If it exists */
1787 close(fd); /* Close the socket */
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;
1795 /* Link the next to the prev */
1796 if(client->next) client->next->prev = client->prev;
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);
1806 free(client); /* Free the structure */
1808 clipwp = NULL; /* reset clip window*/
1810 } else EPRINTF("nano-X: trying to drop non-existent client %d.\n", fd);
1814 * This is a wrapper to read() which handles error conditions, and
1815 * returns 0 for both error conditions and no data.
1819 GsRead(int fd, char *buf, int c)
1821 GsRead(int fd, void *buf, int c)
1829 e = read(fd, (buf + n), (c - n));
1832 EPRINTF("nano-X: client closed socket: %d\n", fd);
1833 else EPRINTF("nano-X: GsRead failed %d %d: %d\r\n",
1845 * This is a wrapper to write().
1847 int GsWrite(int fd, void *buf, int c)
1854 e = write(fd, ((char *) buf + n), (c - n));
1865 int GsWriteType(int fd, short type)
1867 return GsWrite(fd,&type,sizeof(type));
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
1876 GsHandleClient(int fd)
1880 char buf[MAXREQUESTSZ];
1883 #if HAVE_SHAREDMEM_SUPPORT
1884 current_shm_cmds = curclient->shm_cmds;
1885 current_shm_cmds_size = curclient->shm_cmds_size;
1887 /* read request header*/
1888 if(GsRead(fd, buf, sizeof(nxReq)))
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",
1898 /* read additional request data*/
1899 if(GsRead(fd, &buf[sizeof(nxReq)], len-sizeof(nxReq)))
1902 req = (nxReq *)&buf[0];
1904 if(req->reqType < GrTotalNumCalls) {
1905 curfunc = GrFunctions[req->reqType].name;
1906 /*DPRINTF("HandleClient %s\n", curfunc);*/
1907 GrFunctions[req->reqType].func(req);
1909 EPRINTF("nano-X: GsHandleClient bad function\n");