OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [services/] [gfx/] [mw/] [current/] [src/] [nanox/] [client.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*
2
 * Copyright (c) 1999, 2000 Greg Haerr <greg@censoft.com>
3
 * Copyright (c) 1999, 2000 Alex Holden <alex@linuxhacker.org>
4
 * Copyright (c) 1991 David I. Bell
5
 * Copyright (c) 2000 Vidar Hokstad
6
 * Copyright (c) 2000 Morten Rolland <mortenro@screenmedia.no>
7
 *
8
 * Permission is granted to use, distribute, or modify this source,
9
 * provided that this copyright notice remains intact.
10
 *
11
 * Client routines to do graphics with windows and graphics contexts.
12
 *
13
 * Rewritten heavily for speed by Greg Haerr
14
 *
15
 * Whenever you add a new API entry point, please comment it in the same way
16
 * as the rest of the functions in this file. Also add your functions to the
17
 * appropriate section(s) in doc/nano-X/nano-X-sections.txt and regenerate the
18
 * documentation by running make in the doc/nano-X/ directory. If you do not
19
 * have the necessary tools (gtk-doc and the docbook-tools) to rebuild the
20
 * documentation, just skip that step and we will do it for you.
21
 */
22
 
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <unistd.h>
26
#include <string.h>
27
#include <stddef.h>
28
#include <signal.h>
29
#include <errno.h>
30
#include <time.h>
31
#if HAVE_SHAREDMEM_SUPPORT
32
#include <sys/types.h>
33
#include <sys/ipc.h>
34
#include <sys/shm.h>
35
#endif
36
#include <sys/time.h>
37
#include <sys/socket.h>
38
#if ELKS
39
#include <linuxmt/na.h>
40
#include <linuxmt/time.h>
41
#elif __ECOS
42
#include <netinet/in.h>
43
#include <sys/select.h>
44
#include <cyg/kernel/kapi.h>
45
#define _NO_SVR_MAPPING
46
#define getpid()        ((int)cyg_thread_self())
47
#else
48
#include <sys/un.h>
49
#if hpux
50
#include <sys/time.h>
51
#else
52
#ifdef __GLIBC__
53
#include <sys/select.h>
54
#endif
55
#endif
56
#endif
57
#include "nano-X.h"
58
#include "serv.h"
59
#include "nxproto.h"
60
 
61
#define GR_CLOSE_FIX    1       /* dirty hack attempts to fix GrClose hang bug*/
62
 
63
#define SHM_BLOCK_SIZE  4096
64
 
65
#ifndef __ECOS
66
/* exported global data */
67
int        nxSocket = -1;       /* The network socket descriptor */
68
#if HAVE_SHAREDMEM_SUPPORT
69
char *     nxSharedMem = 0;      /* Address of shared memory segment*/
70
static int nxSharedMemSize;     /* Size in bytes of shared mem segment*/
71
#endif
72
 
73
static int regfdmax = -1;       /* GrRegisterInput globals*/
74
static fd_set regfdset;
75
 
76
/* readable error strings*/
77
char *nxErrorStrings[] = {
78
        GR_ERROR_STRINGS
79
};
80
 
81
static EVENT_LIST *     evlist;
82
 
83
/*
84
 * The following is the user defined function for handling errors.
85
 * If this is not set, then the default action is to close the connection
86
 * to the server, describe the error, and then exit.  This error function
87
 * will only be called when the client asks for events.
88
 */
89
static GR_FNCALLBACKEVENT ErrorFunc = GrDefaultErrorHandler;
90
 
91
#else /* __ECOS*/
92
/*
93
 * eCos uses a thread data pointer to store all statics in...
94
 */
95
int ecos_nanox_client_data_index = CYGNUM_KERNEL_THREADS_DATA_MAX;
96
 
97
/* readable error strings*/
98
char *nxErrorStrings[] = {
99
        GR_ERROR_STRINGS
100
};
101
#endif
102
 
103
/*
104
 * Queue an event in FIFO for later retrieval.
105
 */
106
static void
107
QueueEvent(GR_EVENT *ep)
108
{
109
        EVENT_LIST *    elp;
110
        EVENT_LIST *    prevelp;
111
        ACCESS_PER_THREAD_DATA()
112
 
113
        elp = malloc(sizeof(EVENT_LIST));
114
        if (elp) {
115
                elp->event = *ep;
116
                elp->next = NULL;
117
 
118
                /* add as last entry on list*/
119
                if (!evlist) {
120
                        evlist = elp;
121
                        return;
122
                }
123
                prevelp = evlist;
124
                while (prevelp->next)
125
                        prevelp = prevelp->next;
126
                prevelp->next = elp;
127
        }
128
}
129
 
130
/*
131
 * Retrieve first event in FIFO event queue.
132
 */
133
static void
134
GetNextQueuedEvent(GR_EVENT *ep)
135
{
136
        ACCESS_PER_THREAD_DATA()
137
        *ep = evlist->event;
138
        evlist = evlist->next;
139
}
140
 
141
/*
142
 * Read n bytes of data from the server into block *b.  Make sure the data
143
 * you are about to read are actually of the correct type - e.g. make a
144
 * check for the first block of data you read as a response to a command
145
 * with the Typed version of this function. Returns 0 on success or -1 on
146
 * failure.
147
 */
148
static int GrReadBlock(void *b, int n)
149
{
150
        int i = 0;
151
        char *v;
152
        ACCESS_PER_THREAD_DATA()
153
 
154
        v = (char *) b;
155
 
156
        nxFlushReq(0L,0);
157
        while(v < ((char *) b + n)) {
158
                i = read(nxSocket, v, ((char *) b + n - v));
159
                if ( i <= 0 ) {
160
                        if ( i == 0 ) {
161
                                /* We should maybe produce an event here,
162
                                 * if possible.
163
                                 */
164
                                EPRINTF("nxclient: lost connection to Nano-X "
165
                                        "server\n");
166
                                exit(1);
167
                        }
168
                        if ( errno == EINTR || errno == EAGAIN )
169
                                continue;
170
 
171
                        EPRINTF("nxclient: bad readblock %d\n", i);
172
                        return -1;
173
                }
174
                v += i;
175
        }
176
 
177
        return 0;
178
}
179
 
180
/*
181
 * Read a byte of data from the server.
182
 */
183
static int GrReadByte()
184
{
185
        unsigned char c;
186
 
187
        if(GrReadBlock(&c, 1) == -1)
188
                return -1;
189
        else return (int) c;
190
}
191
 
192
/*
193
 * Check if this is a CLIENT_DATA event, in which case we need to read the
194
 * data for the event into a buffer and set the event data pointer to the
195
 * address of it (or NULL if the malloc() fails). We also don't try to read
196
 * any data if datalen is 0.
197
 */
198
static void GrCheckForClientData(GR_EVENT *evp)
199
{
200
        GR_EVENT_CLIENT_DATA *event;
201
 
202
        if(evp->type == GR_EVENT_TYPE_CLIENT_DATA) {
203
                event = (GR_EVENT_CLIENT_DATA *)evp;
204
                if(!event->datalen) {
205
                        event->data = NULL;
206
                        return;
207
                }
208
                if(!(event->data = malloc(event->datalen))) return;
209
                GrReadBlock(event->data, event->datalen);
210
        }
211
}
212
 
213
/*
214
 * Check if the data we are about to read is of the correct type. This
215
 * must be done in order to avoid reading an event as part of the response
216
 * from the server to a command that requires a reply.
217
 */
218
static int GrCheckBlockType(short packettype)
219
{
220
        short           b;
221
        GR_EVENT        event;
222
 
223
        while (GrReadBlock(&b,sizeof(b)) != -1) {
224
                if (b == packettype)
225
                        return b;
226
 
227
                if (b == GrNumGetNextEvent) {
228
                        /*EPRINTF("nxclient %d: Storing event (expected %d)\n",
229
                                getpid(), packettype);*/
230
 
231
#if 0
232
                        /* We only need to handle one event, since the next
233
                         * event won't arrive until the next GrPrepareSelect()
234
                         * has been called, and by then we have already
235
                         * handled this event in GrServiceSelect(). If
236
                         * GrPrepareSelect() is never called, then we should
237
                         * never get here either, so that is cool too.
238
                         */
239
                        GrReadBlock(&storedevent_data,
240
                                    sizeof(storedevent_data));
241
                        GrCheckForClientData(&storedevent_data);
242
                        storedevent = 1;
243
#endif
244
                        /* read event and queue it for later processing*/
245
                        GrReadBlock(&event, sizeof(event));
246
                        QueueEvent(&event);
247
                } else {
248
                        EPRINTF("nxclient %d: Wrong packet type %d "
249
                                "(expected %d)\n", getpid(),b, packettype);
250
                }
251
        }
252
        EPRINTF("nxclient %d: Corrupted packet\n", getpid());
253
        return -1;
254
}
255
 
256
/*
257
 * Actually read a response from the server, much like the GrReadBlock but
258
 * make sure the response is of the right kind, e.g. store the event that
259
 * may have sneaked into the stream.
260
 */
261
static int GrTypedReadBlock(void *b, int n, int type)
262
{
263
        int r;
264
 
265
        r = GrCheckBlockType(type);
266
        if (r != type)
267
                return -1;
268
        return GrReadBlock(b,n);
269
}
270
 
271
/*
272
 * Check if the passed event is an error event, and call the error handler if
273
 * there is one. After calling the handler (if it returns), the event type is
274
 * set to a non-event so that we don't return an error event through the
275
 * GetEvent() mechanism. This solution is simpler than creating a client-side
276
 * event queue.
277
 */
278
static void
279
CheckErrorEvent(GR_EVENT *ep)
280
{
281
        ACCESS_PER_THREAD_DATA()
282
 
283
        if (ep->type == GR_EVENT_TYPE_ERROR) {
284
                if (ErrorFunc) {
285
                        /* call error handler*/
286
                        ErrorFunc(ep);
287
 
288
                        /* then convert to null event*/
289
                        ep->type = GR_EVENT_TYPE_NONE;
290
                }
291
        }
292
}
293
 
294
/**
295
 * GrFlush:
296
 *
297
 * Flush the message buffer of any messages it may contain.
298
 */
299
void
300
GrFlush(void)
301
{
302
        nxFlushReq(0L,1);
303
}
304
 
305
/**
306
 * GrOpen:
307
 * @Returns: the fd of the connection to the server or -1 on failure
308
 *
309
 * Open a connection to the graphics server.
310
 */
311
int
312
GrOpen(void)
313
{
314
        size_t          size;
315
        nxOpenReq       req;
316
        int             tries;
317
        int             ret = 0;
318
#if ELKS
319
        struct sockaddr_na name;
320
#define ADDR_FAM AF_NANO
321
#elif defined(__ECOS)
322
        struct sockaddr_in name;
323
#define ADDR_FAM AF_INET
324
#else
325
        struct sockaddr_un name;
326
#define ADDR_FAM AF_UNIX
327
#endif
328
        ACCESS_PER_THREAD_DATA()
329
 
330
        if (nxSocket == -1) {
331
                if((nxSocket = socket(ADDR_FAM, SOCK_STREAM, 0)) == -1) {
332
                        nxSocket = -1;
333
                        return -1;
334
                }
335
        } else {
336
            return nxSocket;
337
        }
338
 
339
#if ELKS
340
        name.sun_family = AF_NANO;
341
        name.sun_no = GR_NUMB_SOCKET;
342
        size = sizeof(struct sockaddr_na);
343
#elif defined(__ECOS)
344
        name.sin_family = AF_INET;
345
        name.sin_port = htons(6600);                    /* Nano-X server port*/
346
        name.sin_len = sizeof(name);
347
        name.sin_addr.s_addr = inet_addr("127.0.0.1");  /* Loopback address*/
348
        size = sizeof(struct sockaddr_in);
349
#else
350
        name.sun_family = AF_UNIX;
351
        strcpy(name.sun_path, GR_NAMED_SOCKET);
352
        size = (offsetof(struct sockaddr_un, sun_path) +
353
                strlen(name.sun_path) + 1);
354
#endif
355
 
356
        /*
357
         * Try to open the connection for up to a second,
358
         * waiting 1/10 second between attempts.
359
         */
360
        for (tries=1; tries<=10; ++tries) {
361
                struct timespec req;
362
 
363
                ret = connect(nxSocket, (struct sockaddr *) &name, size);
364
                if (ret >= 0)
365
                        break;
366
                req.tv_sec = 0;
367
                req.tv_nsec = 100000000L;
368
                nanosleep(&req, NULL);
369
                EPRINTF("nxclient: retry connect attempt %d\n", tries);
370
        }
371
        if (ret == -1) {
372
                close(nxSocket);
373
                nxSocket = -1;
374
                return -1;
375
        }
376
 
377
        /*
378
         * By Performing the 'GrOpen' without allocating a buffer, just
379
         * shuffeling the struct over the wire, we can postpone the
380
         * allocation of the client size command buffer, which will never be
381
         * allocated if the first command after GrOpen() is
382
         * GrReqShmCmds() which allocates a replacement shared memory
383
         * segment.
384
         * So: Calling GrReqShmCmds() right after GrOpen will prevent the
385
         * traditional command queue buffer from being allocated from
386
         * the process heap - and only the shared memory segment is
387
         * allocated.
388
         */
389
        req.reqType = GrNumOpen;
390
        req.hilength = 0;
391
        req.length = sizeof(req);
392
        /* associate the process ID with the client*/
393
        req.pid = getpid();
394
 
395
        nxWriteSocket((char *)&req,sizeof(req));
396
        return nxSocket;
397
}
398
 
399
#if GR_CLOSE_FIX
400
static void
401
mySignalhandler(int sig)
402
{
403
        if (sig == SIGALRM) {
404
                printf("Oops! nxFlushReq() timed out, cowardly chickening "
405
                                                                "out!\n");
406
                exit(127);
407
        }
408
}
409
#endif
410
 
411
/**
412
 * GrClose:
413
 *
414
 * Close the graphics device, flushing any waiting messages.
415
 */
416
/* Vladimir Cotfas: hang in GrFlush() --> nxFlushReq(0L,1); */
417
void
418
GrClose(void)
419
{
420
        ACCESS_PER_THREAD_DATA()
421
#if GR_CLOSE_FIX
422
        /* allow 1 second to flush*/
423
        void * oldSignalHandler = signal(SIGALRM, mySignalhandler);
424
        alarm(1);
425
#endif
426
        AllocReq(Close);
427
        GrFlush();
428
#if GR_CLOSE_FIX
429
        alarm(0);
430
        signal(SIGALRM, oldSignalHandler);
431
#endif
432
        close(nxSocket);
433
        nxSocket = -1;
434
}
435
 
436
/**
437
 * GrDefaultErrorHandler:
438
 * @ep: the error event structure
439
 *
440
 * The default error handler which is called when the server reports an error
441
 * event and the client hasn't set up a handler of it's own.
442
 *
443
 * Generates a human readable error message on stderr describing what error
444
 * occurred and what function it occured in, then exits.
445
 */
446
void
447
GrDefaultErrorHandler(GR_EVENT *ep)
448
{
449
        if (ep->type == GR_EVENT_TYPE_ERROR) {
450
                EPRINTF("nxclient %d: Error (%s) ", getpid(), ep->error.name);
451
                EPRINTF(nxErrorStrings[ep->error.code], ep->error.id);
452
                GrClose();
453
                exit(1);
454
        }
455
}
456
 
457
/**
458
 * GrSetErrorHandler:
459
 * @fncb: the function to call to handle error events
460
 * @Returns: the address of the previous error handler
461
 *
462
 * Sets an error handling routine that will be called on any errors from
463
 * the server (assuming the client has asked to receive them). If zero is
464
 * used as the argument, errors will be returned as regular events instead.
465
 */
466
GR_FNCALLBACKEVENT
467
GrSetErrorHandler(GR_FNCALLBACKEVENT fncb)
468
{
469
        ACCESS_PER_THREAD_DATA()
470
        GR_FNCALLBACKEVENT orig = ErrorFunc;
471
 
472
        ErrorFunc = fncb;
473
        return orig;
474
}
475
 
476
/**
477
 * GrDelay:
478
 * @msecs: number of milliseconds to delay
479
 *
480
 * This function suspends execution of the program for the specified
481
 * number of milliseconds.
482
 */
483
void
484
GrDelay(GR_TIMEOUT msecs)
485
{
486
        struct timeval timeval;
487
 
488
        timeval.tv_sec = msecs / 1000;
489
        timeval.tv_usec = msecs % 1000;
490
        select(0, NULL, NULL, NULL, &timeval);
491
}
492
 
493
/**
494
 * GrGetScreenInfo:
495
 * @sip: pointer to a GR_SCREEN_INFO structure
496
 *
497
 * Fills in the specified GR_SCREEN_INFO structure.
498
 */
499
void
500
GrGetScreenInfo(GR_SCREEN_INFO *sip)
501
{
502
        AllocReq(GetScreenInfo);
503
        GrTypedReadBlock(sip, sizeof(GR_SCREEN_INFO),GrNumGetScreenInfo);
504
}
505
 
506
/**
507
 * GrGetSysColor:
508
 * @index: an index into the server's colour look up table
509
 * @Returns: the colour found at the specified index
510
 *
511
 * Returns the colour at the specified index into the server's colour look
512
 * up table. The colours in the table are those with names like
513
 * "GR_COLOR_DESKTOP", "GR_COLOR_ACTIVECAPTION", "GR_COLOR_APPWINDOW", etc.
514
 * as listed in nano-X.h
515
 */
516
GR_COLOR
517
GrGetSysColor(int index)
518
{
519
        nxGetSysColorReq *req;
520
        GR_COLOR color;
521
 
522
        req = AllocReq(GetSysColor);
523
        req->index = index;
524
        if(GrTypedReadBlock(&color, sizeof(color),GrNumGetSysColor) == -1)
525
                return 0;
526
        return color;
527
}
528
 
529
/**
530
 * GrGetFontInfo:
531
 * @fontno: the font ID number
532
 * @fip: pointer to a GR_FONT_INFO structure
533
 *
534
 * Fills in the specified GR_FONT_INFO structure with information regarding
535
 * the specified font.
536
 */
537
void
538
GrGetFontInfo(GR_FONT_ID fontno, GR_FONT_INFO *fip)
539
{
540
        nxGetFontInfoReq *req;
541
 
542
        req = AllocReq(GetFontInfo);
543
        req->fontid = fontno;
544
        GrTypedReadBlock(fip, sizeof(GR_FONT_INFO),GrNumGetFontInfo);
545
}
546
 
547
/**
548
 * GrGetGCInfo:
549
 * @gc: a graphics context
550
 * @gcip: pointer to a GR_GC_INFO structure
551
 *
552
 * Fills in the specified GR_GC_INFO structure with information regarding the
553
 * specified graphics context.
554
 */
555
void GrGetGCInfo(GR_GC_ID gc, GR_GC_INFO *gcip)
556
{
557
        nxGetGCInfoReq *req;
558
 
559
        req = AllocReq(GetGCInfo);
560
        req->gcid = gc;
561
        GrTypedReadBlock(gcip, sizeof(GR_GC_INFO),GrNumGetGCInfo);
562
}
563
 
564
/**
565
 * GrGetGCTextSize:
566
 * @gc: the graphics context
567
 * @str: pointer to a text string
568
 * @count: the length of the string
569
 * @flags: text rendering flags (GR_TF*)
570
 * @retwidth: pointer to the variable the width will be returned in
571
 * @retheight: pointer to the variable the height will be returned in
572
 * @retbase: pointer to the variable the baseline height will be returned in
573
 *
574
 * Calculates the dimensions of the specified text string using the current font
575
 * and flags in the specified graphics context. The count argument can be -1
576
 * if the string is null terminated.
577
 */
578
void GrGetGCTextSize(GR_GC_ID gc, void *str, int count, int flags,
579
        GR_SIZE *retwidth, GR_SIZE *retheight, GR_SIZE *retbase)
580
{
581
        nxGetGCTextSizeReq *req;
582
        int size;
583
 
584
        if(count == -1 && (flags&MWTF_PACKMASK) == MWTF_ASCII)
585
                count = strlen((char *)str);
586
 
587
        size = nxCalcStringBytes(str, count, flags);
588
 
589
        req = AllocReqExtra(GetGCTextSize, size);
590
        req->gcid = gc;
591
        req->flags = flags;
592
        memcpy(GetReqData(req), str, size);
593
        GrTypedReadBlock(retwidth, sizeof(*retwidth),GrNumGetGCTextSize);
594
        GrReadBlock(retheight, sizeof(*retheight));
595
        GrReadBlock(retbase, sizeof(*retbase));
596
}
597
 
598
/**
599
 * GrRegisterInput:
600
 * @fd: the file descriptor to monitor
601
 *
602
 * Register an extra file descriptor to monitor in the main select() call.
603
 * An event will be returned when the fd has data waiting to be read if that
604
 * event has been selected for.
605
 */
606
void
607
GrRegisterInput(int fd)
608
{
609
        ACCESS_PER_THREAD_DATA()
610
 
611
        if (fd < 0)
612
                return;
613
        FD_SET(fd, &regfdset);
614
        if (fd > regfdmax) regfdmax = fd + 1;
615
}
616
 
617
/**
618
 * GrUnregisterInput:
619
 * @fd: the file descriptor to stop monitoring
620
 *
621
 * Stop monitoring a file descriptor (previously registered with
622
 * GrRegisterInput()) in the main select() call.
623
 */
624
void
625
GrUnregisterInput(int fd)
626
{
627
        int i, max;
628
        ACCESS_PER_THREAD_DATA()
629
 
630
        /* unregister all inputs if fd is -1 */
631
        if (fd == -1) {
632
                FD_ZERO(&regfdset);
633
                regfdmax = -1;
634
                return;
635
        }
636
 
637
        FD_CLR(fd, &regfdset);
638
        /* recalculate the max file descriptor */
639
        for (i = 0, max = regfdmax, regfdmax = -1; i < max; i++)
640
                if (FD_ISSET(i, &regfdset))
641
                        regfdmax = i + 1;
642
}
643
 
644
/**
645
 * GrPrepareSelect:
646
 * @maxfd: pointer to a variable which the highest in use fd will be written to
647
 * @rfdset: pointer to the file descriptor set structure to use
648
 *
649
 * Prepare for a GrServiceSelect function by asking the server to send the next
650
 * event but not waiting around for it to arrive and initialising the
651
 * specified fd_set structure with the client/server socket descriptor and any
652
 * previously registered external file descriptors. Also compares the current
653
 * contents of maxfd, the client/server socket descriptor, and the previously
654
 * registered external file descriptors, and returns the highest of them in
655
 * maxfd.
656
 */
657
void
658
GrPrepareSelect(int *maxfd,void *rfdset)
659
{
660
        fd_set *rfds = rfdset;
661
        int fd;
662
 
663
        ACCESS_PER_THREAD_DATA()
664
 
665
        AllocReq(GetNextEvent);
666
        GrFlush();
667
 
668
        FD_SET(nxSocket, rfds);
669
        if(nxSocket > *maxfd)
670
                *maxfd = nxSocket;
671
 
672
        /* handle registered input file descriptors*/
673
        for (fd = 0; fd < regfdmax; fd++) {
674
                if (FD_ISSET(fd, &regfdset)) {
675
                        FD_SET(fd, rfds);
676
                        if (fd > *maxfd) *maxfd = fd;
677
                }
678
        }
679
}
680
 
681
/**
682
 * GrServiceSelect:
683
 * @rfdset: pointer to the file descriptor set to monitor
684
 * @fncb: pointer to the function to call when an event needs handling
685
 *
686
 * Used by GrMainLoop() to call the specified callback function when an
687
 * event arrives or there is data waiting on an external fd specified by
688
 * GrRegisterInput().
689
 */
690
void
691
GrServiceSelect(void *rfdset, GR_FNCALLBACKEVENT fncb)
692
{
693
        fd_set *        rfds = rfdset;
694
        int             fd;
695
        GR_EVENT        ev;
696
 
697
        ACCESS_PER_THREAD_DATA()
698
 
699
        /* Clean out any event that might have arrived while waiting
700
         * for other data, for instance by doing Nano-X requests
701
         * between GrPrepareSelect() and GrServiceSelect(), or when
702
         * an event is generated in Nano-X at the same time as the
703
         * client wakes up for some reason and calls Nano-X functions.
704
         */
705
        if (evlist) {
706
                /*DPRINTF("nxclient: Handling queued event\n");*/
707
                GetNextQueuedEvent(&ev);
708
                CheckErrorEvent(&ev);
709
                fncb(&ev);
710
        }
711
        else {
712
                if(FD_ISSET(nxSocket, rfds)) {
713
                        GrTypedReadBlock(&ev, sizeof(ev),GrNumGetNextEvent);
714
                        GrCheckForClientData(&ev);
715
                        CheckErrorEvent(&ev);
716
                        fncb(&ev);
717
                }
718
        }
719
 
720
        /* check for input on registered file descriptors */
721
        for (fd = 0; fd < regfdmax; fd++) {
722
                if (FD_ISSET(fd, &regfdset) && FD_ISSET(fd, rfds)) {
723
                        ev.type = GR_EVENT_TYPE_FDINPUT;
724
                        ev.fdinput.fd = fd;
725
                        fncb(&ev);
726
                }
727
        }
728
}
729
 
730
/**
731
 * GrMainLoop:
732
 * @fncb:
733
 *
734
 * A convenience function which calls the specified callback function whenever
735
 * an event arrives or there is data to be read on a file descriptor previously
736
 * specified by GrRegisterInput(). Currently never returns.
737
 */
738
void
739
GrMainLoop(GR_FNCALLBACKEVENT fncb)
740
{
741
        fd_set  rfds;
742
        int     setsize = 0;
743
 
744
        for(;;) {
745
                FD_ZERO(&rfds);
746
                GrPrepareSelect(&setsize, &rfds);
747
                if(select(setsize+1, &rfds, NULL, NULL, NULL) > 0)
748
                        GrServiceSelect(&rfds, fncb);
749
        }
750
}
751
 
752
/**
753
 * GrGetNextEvent:
754
 * @ep: pointer to the GR_EVENT structure to return the event in
755
 *
756
 * Gets the next event from the event queue and places it in the specified
757
 * GR_EVENT structure. If the queue is currently empty, we sleep until the
758
 * next event arrives from the server or input is read on a file descriptor
759
 * previously specified by GrRegisterInput().
760
 */
761
void
762
GrGetNextEvent(GR_EVENT *ep)
763
{
764
        GrGetNextEventTimeout(ep, 0L);
765
}
766
 
767
/**
768
 * GrGetNextEventTimeout:
769
 * @ep: pointer to the GR_EVENT structure to return the event in
770
 * @timeout: the number of milliseconds to wait before timing out
771
 *
772
 * Gets the next event from the event queue and places it in the specified
773
 * GR_EVENT structure. If the queue is currently empty, we sleep until the
774
 * next event arrives from the server, input is read on a file descriptor
775
 * previously specified by GrRegisterInput(), or a timeout occurs. Note
776
 * that a value of 0 for the timeout parameter doesn't mean "timeout after 0
777
 * milliseconds" but is in fact a magic number meaning "never time out".
778
 */
779
void
780
GrGetNextEventTimeout(GR_EVENT *ep, GR_TIMEOUT timeout)
781
{
782
        fd_set          rfds;
783
        int             setsize = 0;
784
        int             e;
785
        struct timeval  to;
786
        ACCESS_PER_THREAD_DATA()
787
 
788
        if (evlist) {
789
                /*DPRINTF("nxclient %d: Returning queued event\n",getpid());*/
790
                GetNextQueuedEvent(ep);
791
                CheckErrorEvent(ep);
792
                return;
793
        }
794
 
795
        FD_ZERO(&rfds);
796
        /*
797
         * This will cause a GrGetNextEvent to be sent down the wire.
798
         * If we timeout before the server responds, and then
799
         * call this procedure again, and the server has more than
800
         * one event waiting for this process, then more than one
801
         * event will be written on the socket by the server.  At
802
         * that point, a single stored event won't work, and the
803
         * client needs an event queue.
804
         */
805
        GrPrepareSelect(&setsize, &rfds);
806
        if (timeout) {
807
                to.tv_sec = timeout / 1000;
808
                to.tv_usec = (timeout % 1000) * 1000;
809
        }
810
 
811
        if((e = select(setsize+1, &rfds, NULL, NULL, timeout ? &to : NULL))>0) {
812
                int fd;
813
 
814
                if(FD_ISSET(nxSocket, &rfds)) {
815
                        /*
816
                         * This will never be GR_EVENT_NONE with the current
817
                         * implementation.
818
                         */
819
                        GrTypedReadBlock(ep, sizeof(*ep),GrNumGetNextEvent);
820
                        GrCheckForClientData(ep);
821
                        CheckErrorEvent(ep);
822
                        return;
823
                }
824
 
825
                /* check for input on registered file descriptors */
826
                for (fd = 0; fd < regfdmax; fd++) {
827
                        if (FD_ISSET(fd, &regfdset) && FD_ISSET(fd, &rfds)) {
828
                                ep->type = GR_EVENT_TYPE_FDINPUT;
829
                                ep->fdinput.fd = fd;
830
                                break;
831
                        }
832
                }
833
        }
834
        else if (e == 0) {
835
                /*
836
                 * Timeout has occured. We currently return a timeout event
837
                 * regardless of whether the client has selected for it.
838
                 */
839
                ep->type = GR_EVENT_TYPE_TIMEOUT;
840
        } else {
841
                if(errno == EINTR) {
842
                        ep->type = GR_EVENT_TYPE_NONE;
843
                } else {
844
                        EPRINTF("nxclient: select failed\n");
845
                        GrClose();
846
                        exit(1);
847
                }
848
        }
849
}
850
 
851
/**
852
 * GrCheckNextEvent:
853
 * @ep: pointer to the GR_EVENT structure to return the event in
854
 *
855
 * Gets the next event from the event queue if there is one, or returns
856
 * immediately with an event type of GR_EVENT_TYPE_NONE if it is empty.
857
 */
858
void
859
GrCheckNextEvent(GR_EVENT *ep)
860
{
861
        ACCESS_PER_THREAD_DATA()
862
        if (evlist) {
863
                /*DPRINTF("nxclient %d: Returning queued event\n",getpid());*/
864
                GetNextQueuedEvent(ep);
865
                CheckErrorEvent(ep);
866
                return;
867
        }
868
 
869
        AllocReq(CheckNextEvent);
870
        GrTypedReadBlock(ep, sizeof(*ep),GrNumGetNextEvent);
871
        GrCheckForClientData(ep);
872
        CheckErrorEvent(ep);
873
}
874
 
875
/**
876
 * GrPeekEvent:
877
 * @ep: pointer to the GR_EVENT structure to return the event in
878
 * @Returns: 1 if an event was returned, or 0 if the queue was empty
879
 *
880
 * Fills in the specified event structure with a copy of the next event on the
881
 * queue, without actually removing it from the queue. An event type of
882
 * GR_EVENT_TYPE_NONE is given if the queue is empty.
883
 */
884
int
885
GrPeekEvent(GR_EVENT *ep)
886
{
887
        int ret;
888
        ACCESS_PER_THREAD_DATA()
889
 
890
        if (evlist) {
891
                *ep = evlist->event;
892
                CheckErrorEvent(ep);
893
                return 1;
894
        }
895
 
896
        AllocReq(PeekEvent);
897
        GrTypedReadBlock(ep, sizeof(*ep),GrNumPeekEvent);
898
        GrCheckForClientData(ep);
899
        ret = GrReadByte();
900
        CheckErrorEvent(ep);
901
        return ret;
902
}
903
 
904
/**
905
 * GrPeekWaitEvent:
906
 * @ep: pointer to the GR_EVENT structure to return the event in
907
 *
908
 * Wait until an event is available for a client, and then peek at it.
909
 */
910
void
911
GrPeekWaitEvent(GR_EVENT *ep)
912
{
913
        EVENT_LIST *    elp;
914
        ACCESS_PER_THREAD_DATA()
915
 
916
        if (evlist) {
917
                *ep = evlist->event;
918
                CheckErrorEvent(ep);
919
                return;
920
        }
921
 
922
        /* no events, wait for next event*/
923
        GrGetNextEvent(ep);
924
 
925
        /* add event back on head of list*/
926
        elp = malloc(sizeof(EVENT_LIST));
927
        if (elp) {
928
                elp->event = *ep;
929
                elp->next = evlist;
930
        }
931
 
932
        /* peek at it*/
933
        GrPeekEvent(ep);
934
}
935
 
936
/**
937
 * GrSelectEvents:
938
 * @wid: the ID of the window to set the event mask of
939
 * @eventmask: a bit field specifying the desired event mask
940
 *
941
 * Select the event types which should be returned for the specified window.
942
 */
943
void
944
GrSelectEvents(GR_WINDOW_ID wid, GR_EVENT_MASK eventmask)
945
{
946
 
947
        nxSelectEventsReq *req;
948
 
949
        req = AllocReq(SelectEvents);
950
        req->windowid = wid;
951
        req->eventmask = eventmask;
952
}
953
 
954
/**
955
 * GrNewWindow:
956
 * @parent: the ID of the parent window
957
 * @x: the X coordinate of the new window relative to the parent window
958
 * @y: the Y coordinate of the new window relative to the parent window
959
 * @width: the width of the new window
960
 * @height: the height of the new window
961
 * @bordersize: the width of the window border
962
 * @background: the colour of the window background
963
 * @bordercolor: the colour of the window border
964
 * @Returns: the ID of the newly created window
965
 *
966
 * Create a new window with the specified parent and window attributes.
967
 */
968
GR_WINDOW_ID
969
GrNewWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y, GR_SIZE width,
970
        GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
971
        GR_COLOR bordercolor)
972
{
973
        nxNewWindowReq *req;
974
        GR_WINDOW_ID    wid;
975
 
976
        req = AllocReq(NewWindow);
977
        req->parentid = parent;
978
        req->x = x;
979
        req->y = y;
980
        req->width = width;
981
        req->height = height;
982
        req->backgroundcolor = background;
983
        req->bordercolor = bordercolor;
984
        req->bordersize = bordersize;
985
        if(GrTypedReadBlock(&wid, sizeof(wid),GrNumNewWindow) == -1)
986
                return 0;
987
        return wid;
988
}
989
 
990
 
991
/**
992
 * GrNewPixmap:
993
 * @width: the width of the pixmap
994
 * @height: the height of the pixmap
995
 * @addr: currently unused in client/server mode
996
 * @Returns: the ID of the newly created pixmap
997
 *
998
 * Create a new server side pixmap (an offscreen drawing area which can be
999
 * copied into a window using a GrCopyArea call) of the specified width and
1000
 * height.
1001
 */
1002
/* FIXME: Add support for shared memory... */
1003
GR_WINDOW_ID
1004
GrNewPixmap(GR_SIZE width, GR_SIZE height, void *addr)
1005
{
1006
        nxNewPixmapReq *req;
1007
        GR_WINDOW_ID    wid;
1008
 
1009
        req = AllocReq(NewPixmap);
1010
        req->width = width;
1011
        req->height = height;
1012
        if(GrTypedReadBlock(&wid, sizeof(wid), GrNumNewPixmap) == -1)
1013
                return 0;
1014
        return wid;
1015
}
1016
 
1017
/**
1018
 * GrNewInputWindow:
1019
 * @parent: the ID of the window to use as the parent of the new window
1020
 * @x: the X coordinate of the new window relative to the parent window
1021
 * @y: the Y coordinate of the new window relative to the parent window
1022
 * @width: the width of the new window
1023
 * @height: the height of the new window
1024
 * @Returns: the ID of the newly created window
1025
 *
1026
 * Create a new input-only window with the specified dimensions which is a
1027
 * child of the specified parent window.
1028
 */
1029
GR_WINDOW_ID
1030
GrNewInputWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y, GR_SIZE width,
1031
        GR_SIZE height)
1032
{
1033
        nxNewInputWindowReq *req;
1034
        GR_WINDOW_ID         wid;
1035
 
1036
        req = AllocReq(NewInputWindow);
1037
        req->parentid = parent;
1038
        req->x = x;
1039
        req->y = y;
1040
        req->width = width;
1041
        req->height = height;
1042
        if(GrTypedReadBlock(&wid, sizeof(wid), GrNumNewInputWindow) == -1)
1043
                return 0;
1044
        return wid;
1045
}
1046
 
1047
/**
1048
 * GrDestroyWindow:
1049
 * @wid: the ID of the window to destroy
1050
 *
1051
 * Recursively unmaps and frees the data structures associated with the
1052
 * specified window and all of its children.
1053
 */
1054
void
1055
GrDestroyWindow(GR_WINDOW_ID wid)
1056
{
1057
        nxDestroyWindowReq *req;
1058
 
1059
        req = AllocReq(DestroyWindow);
1060
        req->windowid = wid;
1061
}
1062
 
1063
/**
1064
 * GrGetWindowInfo:
1065
 * @wid: the ID of the window to retrieve information about
1066
 * @infoptr: pointer to a GR_WINDOW_INFO structure to return the information in
1067
 *
1068
 * Fills in a GR_WINDOW_INFO structure with information regarding the window
1069
 * with the specified window ID.
1070
 */
1071
void
1072
GrGetWindowInfo(GR_WINDOW_ID wid, GR_WINDOW_INFO *infoptr)
1073
{
1074
        nxGetWindowInfoReq *req;
1075
 
1076
        req = AllocReq(GetWindowInfo);
1077
        req->windowid = wid;
1078
        GrTypedReadBlock(infoptr, sizeof(GR_WINDOW_INFO), GrNumGetWindowInfo);
1079
}
1080
 
1081
/**
1082
 * GrNewGC:
1083
 * @Returns: the ID of the newly created graphics context or 0 on error
1084
 *
1085
 * Creates a new graphics context structure and returns the ID used to refer
1086
 * to it. The structure is initialised with a set of default parameters.
1087
 */
1088
GR_GC_ID
1089
GrNewGC(void)
1090
{
1091
        GR_GC_ID    gc;
1092
 
1093
        AllocReq(NewGC);
1094
        if(GrTypedReadBlock(&gc, sizeof(gc),GrNumNewGC) == -1)
1095
                return 0;
1096
        return gc;
1097
}
1098
 
1099
/**
1100
 * GrCopyGC:
1101
 * @gc: the already existing graphics context to copy the parameters from
1102
 * @Returns: the ID of the newly created graphics context or 0 on error
1103
 *
1104
 * Creates a new graphics context structure and fills it in with the values
1105
 * from the specified already existing graphics context.
1106
 */
1107
GR_GC_ID
1108
GrCopyGC(GR_GC_ID gc)
1109
{
1110
        nxCopyGCReq *req;
1111
        GR_GC_ID     newgc;
1112
 
1113
        req = AllocReq(CopyGC);
1114
        req->gcid = gc;
1115
        if(GrTypedReadBlock(&newgc, sizeof(newgc),GrNumCopyGC) == -1)
1116
                return 0;
1117
        return newgc;
1118
}
1119
 
1120
/**
1121
 * GrDestroyGC:
1122
 * @gc: the ID of the graphics context structure to destroy
1123
 *
1124
 * Destroys the graphics context structure with the specified ID.
1125
 */
1126
void
1127
GrDestroyGC(GR_GC_ID gc)
1128
{
1129
        nxDestroyGCReq *req;
1130
 
1131
        req = AllocReq(DestroyGC);
1132
        req->gcid = gc;
1133
}
1134
 
1135
/**
1136
 * GrNewRegion:
1137
 * @Returns: the ID of the newly created region
1138
 *
1139
 * Creates a new region structure and returns the ID used to refer to it.
1140
 * The structure is initialised with a set of default parameters.
1141
 */
1142
GR_REGION_ID
1143
GrNewRegion(void)
1144
{
1145
        GR_REGION_ID    region;
1146
 
1147
        AllocReq(NewRegion);
1148
        if(GrTypedReadBlock(&region, sizeof(region),GrNumNewRegion) == -1)
1149
                return 0;
1150
        return region;
1151
}
1152
 
1153
/**
1154
 * GrDestroyRegion:
1155
 * @region: the ID of the region structure to destroy
1156
 *
1157
 * Destroys the region structure with the specified ID.
1158
 */
1159
void
1160
GrDestroyRegion(GR_REGION_ID region)
1161
{
1162
        nxDestroyRegionReq *req;
1163
 
1164
        req = AllocReq(DestroyRegion);
1165
        req->regionid = region;
1166
}
1167
 
1168
/**
1169
 * GrUnionRectWithRegion:
1170
 * @region: the ID of the region to modify
1171
 * @rect: a pointer to the rectangle to add to the region
1172
 *
1173
 * Makes a union of the specified region and the specified rectangle and
1174
 * places the result back in the source region.
1175
 */
1176
void
1177
GrUnionRectWithRegion(GR_REGION_ID region, GR_RECT *rect)
1178
{
1179
        nxUnionRectWithRegionReq *req;
1180
 
1181
        req = AllocReq(UnionRectWithRegion);
1182
        if(rect)
1183
                memcpy(&req->rect, rect, sizeof(*rect));
1184
        req->regionid = region;
1185
}
1186
 
1187
/**
1188
 * GrUnionRegion:
1189
 * @dst_rgn: the ID of the destination region
1190
 * @src_rgn1: the ID of the first source region
1191
 * @src_rgn2: the ID of the second source region
1192
 *
1193
 * Makes a union of the specified source regions and places the result in the
1194
 * specified destination region.
1195
 */
1196
void
1197
GrUnionRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
1198
        GR_REGION_ID src_rgn2)
1199
{
1200
        nxUnionRegionReq *req;
1201
 
1202
        req = AllocReq(UnionRegion);
1203
        req->regionid = dst_rgn;
1204
        req->srcregionid1 = src_rgn1;
1205
        req->srcregionid2 = src_rgn2;
1206
}
1207
 
1208
/**
1209
 * GrSubtractRegion:
1210
 * @dst_rgn: the ID of the destination region
1211
 * @src_rgn1: the ID of the first source region
1212
 * @src_rgn2: the ID of the second source region
1213
 *
1214
 * Subtracts the second source region from the first source region and places
1215
 * the result in the specified destination region.
1216
 */
1217
void
1218
GrSubtractRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
1219
        GR_REGION_ID src_rgn2)
1220
{
1221
        nxSubtractRegionReq *req;
1222
 
1223
        req = AllocReq(SubtractRegion);
1224
        req->regionid = dst_rgn;
1225
        req->srcregionid1 = src_rgn1;
1226
        req->srcregionid2 = src_rgn2;
1227
}
1228
 
1229
/**
1230
 * GrXorRegion:
1231
 * @dst_rgn: the ID of the destination region
1232
 * @src_rgn1: the ID of the first source region
1233
 * @src_rgn2: the ID of the second source region
1234
 *
1235
 * Performs a logical exclusive OR operation on the specified source regions
1236
 * and places the result in the destination region. The destination region
1237
 * will contain only the parts of the source regions which do not overlap.
1238
 */
1239
void
1240
GrXorRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
1241
        GR_REGION_ID src_rgn2)
1242
{
1243
        nxXorRegionReq *req;
1244
 
1245
        req = AllocReq(XorRegion);
1246
        req->regionid = dst_rgn;
1247
        req->srcregionid1 = src_rgn1;
1248
        req->srcregionid2 = src_rgn2;
1249
}
1250
 
1251
/**
1252
 * GrIntersectRegion:
1253
 * @dst_rgn: the ID of the destination region
1254
 * @src_rgn1: the ID of the first source region
1255
 * @src_rgn2: the ID of the second source region
1256
 *
1257
 * Calculates the intersection of the two specified source regions and places
1258
 * the result in the specified destination region. The destination region
1259
 * will contain only the parts of the source regions which overlap each other.
1260
 */
1261
void
1262
GrIntersectRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
1263
        GR_REGION_ID src_rgn2)
1264
{
1265
        nxIntersectRegionReq *req;
1266
 
1267
        req = AllocReq(IntersectRegion);
1268
        req->regionid = dst_rgn;
1269
        req->srcregionid1 = src_rgn1;
1270
        req->srcregionid2 = src_rgn2;
1271
}
1272
 
1273
/**
1274
 * GrSetGCRegion:
1275
 * @gc: the ID of the graphics context to set the clip mask of
1276
 * @region: the ID of the region to use as the clip mask
1277
 *
1278
 * Sets the clip mask of the specified graphics context to the specified
1279
 * region. Subsequent drawing operations using this graphics context will not
1280
 * draw outside the specified region. The region ID can be set to 0 to remove
1281
 * the clipping region from the specified graphics context.
1282
 */
1283
void
1284
GrSetGCRegion(GR_GC_ID gc, GR_REGION_ID region)
1285
{
1286
        nxSetGCRegionReq *req;
1287
 
1288
        req = AllocReq(SetGCRegion);
1289
        req->gcid = gc;
1290
        req->regionid = region;
1291
}
1292
 
1293
/**
1294
 * GrSetGCClipOrigin:
1295
 * @gc: the ID of the graphics context with user clip region
1296
 * @xoff: new X offset of user clip region
1297
 * @xoff: new Y offset of user clip region
1298
 *
1299
 * Sets the X,Y origin of the user clip region in the specified
1300
 * graphics context.
1301
 */
1302
void
1303
GrSetGCClipOrigin(GR_GC_ID gc, int x, int y)
1304
{
1305
        nxSetGCClipOriginReq *req;
1306
 
1307
        req = AllocReq(SetGCClipOrigin);
1308
        req->gcid = gc;
1309
        req->xoff = x;
1310
        req->yoff = y;
1311
}
1312
 
1313
/**
1314
 * GrPointInRegion:
1315
 * @region: the ID of the region to examine
1316
 * @x: the X coordinate of the point to test for
1317
 * @y: the Y coordinate of the point to test for
1318
 * @Returns: True if the point is within the region, or False otherwise
1319
 *
1320
 * Tests whether the specified point is within the specified region, and
1321
 * then returns either True or False depending on the result.
1322
 */
1323
GR_BOOL
1324
GrPointInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y)
1325
{
1326
        nxPointInRegionReq *req;
1327
        GR_BOOL             ret_value;
1328
 
1329
        req = AllocReq(PointInRegion);
1330
        req->regionid = region;
1331
        req->x = x;
1332
        req->y = y;
1333
        if(GrTypedReadBlock(&ret_value, sizeof(ret_value),
1334
                GrNumPointInRegion) == -1)
1335
                return GR_FALSE;
1336
        return ret_value;
1337
}
1338
 
1339
/**
1340
 * GrRectInRegion:
1341
 * @region: the ID of the region to examine
1342
 * @x: the X coordinates of the rectangle to test
1343
 * @y: the Y coordinates of the rectangle to test
1344
 * @w: the width of the rectangle to test
1345
 * @h: the height of the rectangle to test
1346
 * @Returns: GR_RECT_PARTIN, GR_RECT_ALLIN, or GR_RECT_OUT
1347
 *
1348
 * Tests whether the specified rectangle is contained within the specified
1349
 * region. Returns GR_RECT_OUT if it is not inside it at all, GR_RECT_ALLIN
1350
 * if it is completely contained within the region, or GR_RECT_PARTIN if
1351
 * it is partially contained within the region.
1352
 */
1353
int
1354
GrRectInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y, GR_COORD w,
1355
        GR_COORD h)
1356
{
1357
        nxRectInRegionReq *req;
1358
        unsigned short     ret_value;
1359
 
1360
        req = AllocReq(RectInRegion);
1361
        req->regionid = region;
1362
        req->x = x;
1363
        req->y = y;
1364
        req->w = w;
1365
        req->h = h;
1366
        if(GrTypedReadBlock(&ret_value, sizeof(ret_value),
1367
                GrNumRectInRegion) == -1)
1368
                return 0;
1369
        return (int)ret_value;
1370
}
1371
 
1372
/**
1373
 * GrEmptyRegion:
1374
 * @region: the ID of the region to examine
1375
 * @Returns: GR_TRUE if the region is empty, or GR_FALSE if it is not
1376
 *
1377
 * Determines whether the specified region is empty, and returns GR_TRUE
1378
 * if it is, or GR_FALSE otherwise.
1379
 */
1380
GR_BOOL
1381
GrEmptyRegion(GR_REGION_ID region)
1382
{
1383
        nxEmptyRegionReq *req;
1384
        GR_BOOL           ret_value;
1385
 
1386
        req = AllocReq(EmptyRegion);
1387
        req->regionid = region;
1388
        if(GrTypedReadBlock(&ret_value, sizeof(ret_value),
1389
                GrNumEmptyRegion) == -1)
1390
                return GR_FALSE;
1391
        return ret_value;
1392
}
1393
 
1394
/**
1395
 * GrEqualRegion:
1396
 * @rgn1: the ID of the first region to examine
1397
 * @rgn2: the ID of the second region to examine
1398
 * @Returns: GR_TRUE if the regions are equal, or GR_FALSE otherwise
1399
 *
1400
 * Determines whether the specified regions are identical, and returns GR_TRUE
1401
 * if it is, or GR_FALSE otherwise.
1402
 */
1403
GR_BOOL
1404
GrEqualRegion(GR_REGION_ID rgn1, GR_REGION_ID rgn2)
1405
{
1406
        nxEqualRegionReq *req;
1407
        GR_BOOL           ret_value;
1408
 
1409
        req = AllocReq(EqualRegion);
1410
        req->region1 = rgn1;
1411
        req->region2 = rgn2;
1412
        if(GrTypedReadBlock(&ret_value, sizeof(ret_value),
1413
                GrNumEqualRegion) == -1)
1414
                return GR_FALSE;
1415
        return ret_value;
1416
}
1417
 
1418
/**
1419
 * GrOffsetRegion:
1420
 * @region: the ID of the region to offset
1421
 * @dx: the distance to offset the region by in the X axis
1422
 * @dy: the distance to offset the region by in the Y axis
1423
 *
1424
 * Offsets the specified region by the specified distance.
1425
 */
1426
void
1427
GrOffsetRegion(GR_REGION_ID region, GR_SIZE dx, GR_SIZE dy)
1428
{
1429
        nxOffsetRegionReq *req;
1430
 
1431
        req = AllocReq(OffsetRegion);
1432
        req->region = region;
1433
        req->dx = dx;
1434
        req->dy = dy;
1435
}
1436
 
1437
/**
1438
 * GrGetRegionBox:
1439
 * @region: the ID of the region to get the bounding box of
1440
 * @rect: pointer to a rectangle structure
1441
 * @Returns: the region type
1442
 *
1443
 * Fills in the specified rectangle structure with a bounding box that would
1444
 * completely enclose the specified region, and also returns the type of the
1445
 * specified region.
1446
 */
1447
int
1448
GrGetRegionBox(GR_REGION_ID region, GR_RECT *rect)
1449
{
1450
        nxGetRegionBoxReq *req;
1451
        unsigned short     ret_value;
1452
 
1453
        if (!rect)
1454
                return GR_FALSE;
1455
        req = AllocReq(GetRegionBox);
1456
        req->regionid = region;
1457
        if(GrTypedReadBlock(rect, sizeof(*rect), GrNumGetRegionBox) == -1)
1458
                return GR_FALSE;
1459
        if(GrTypedReadBlock(&ret_value, sizeof(ret_value),
1460
                GrNumGetRegionBox) == -1)
1461
                return GR_FALSE;
1462
        return ret_value;
1463
}
1464
 
1465
/**
1466
 * GrNewPolygonRegion:
1467
 * @mode: the polygon mode to use (GR_POLY_EVENODD or GR_POLY_WINDING)
1468
 * @count: the number of points in the polygon
1469
 * @points: pointer to an array of point structures describing the polygon
1470
 * @Returns: the ID of the newly allocated region structure, or 0 on error
1471
 *
1472
 * Creates a new region structure, fills it with the region described by the
1473
 * specified polygon, and returns the ID used to refer to it.
1474
 */
1475
GR_REGION_ID
1476
GrNewPolygonRegion(int mode, GR_COUNT count, GR_POINT *points)
1477
{
1478
        nxNewPolygonRegionReq   *req;
1479
        long                    size;
1480
        GR_REGION_ID            region;
1481
 
1482
        if(count == 0)
1483
                return GrNewRegion();
1484
 
1485
        if(points == NULL)
1486
                return 0;
1487
 
1488
        size = (long)count * sizeof(GR_POINT);
1489
        req = AllocReqExtra(NewPolygonRegion, size);
1490
        req->mode = mode;
1491
        /* FIXME: unportable method, depends on sizeof(int) in GR_POINT*/
1492
        memcpy(GetReqData(req), points, size);
1493
 
1494
        if(GrTypedReadBlock(&region, sizeof(region),
1495
                GrNumNewPolygonRegion) == -1)
1496
                return 0;
1497
        return region;
1498
}
1499
 
1500
/**
1501
 * GrMapWindow:
1502
 * @wid: the ID of the window to map
1503
 *
1504
 * Recursively maps (makes visible) the specified window and all of the
1505
 * child windows which have a sufficient map count. The border and background
1506
 * of the window are painted, and an exposure event is generated for the
1507
 * window and every child which becomes visible.
1508
 */
1509
void
1510
GrMapWindow(GR_WINDOW_ID wid)
1511
{
1512
        nxMapWindowReq *req;
1513
 
1514
        req = AllocReq(MapWindow);
1515
        req->windowid = wid;
1516
}
1517
 
1518
/**
1519
 * GrUnmapWindow:
1520
 * @wid: the ID of the window to unmap
1521
 *
1522
 * Recursively unmaps (makes invisible) the specified window and all of the
1523
 * child windows.
1524
 */
1525
void
1526
GrUnmapWindow(GR_WINDOW_ID wid)
1527
{
1528
        nxUnmapWindowReq *req;
1529
 
1530
        req = AllocReq(UnmapWindow);
1531
        req->windowid = wid;
1532
}
1533
 
1534
/**
1535
 * GrRaiseWindow:
1536
 * @wid: the ID of the window to raise
1537
 *
1538
 * Places the specified window at the top of its parents drawing stack, above
1539
 * all of its sibling windows.
1540
 */
1541
void
1542
GrRaiseWindow(GR_WINDOW_ID wid)
1543
{
1544
        nxRaiseWindowReq *req;
1545
 
1546
        req = AllocReq(RaiseWindow);
1547
        req->windowid = wid;
1548
}
1549
 
1550
/**
1551
 * GrLowerWindow:
1552
 * @wid: the ID of the window to lower
1553
 *
1554
 * Places the specified window at the bottom of its parents drawing stack,
1555
 * below all of its sibling windows.
1556
 */
1557
void
1558
GrLowerWindow(GR_WINDOW_ID wid)
1559
{
1560
        nxLowerWindowReq *req;
1561
 
1562
        req = AllocReq(LowerWindow);
1563
        req->windowid = wid;
1564
}
1565
 
1566
/**
1567
 * GrMoveWindow:
1568
 * @wid: the ID of the window to move
1569
 * @x: the X coordinate to move the window to relative to its parent.
1570
 * @y: the Y coordinate to move the window to relative to its parent.
1571
 *
1572
 * Moves the specified window to the specified position relative to its
1573
 * parent window.
1574
 */
1575
void
1576
GrMoveWindow(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y)
1577
{
1578
        nxMoveWindowReq *req;
1579
 
1580
        req = AllocReq(MoveWindow);
1581
        req->windowid = wid;
1582
        req->x = x;
1583
        req->y = y;
1584
}
1585
 
1586
/**
1587
 * GrResizeWindow:
1588
 * @wid: the ID of the window to resize
1589
 * @width: the width to resize the window to
1590
 * @height: the height to resize the window to
1591
 *
1592
 * Resizes the specified window to be the specified width and height.
1593
 */
1594
void
1595
GrResizeWindow(GR_WINDOW_ID wid, GR_SIZE width, GR_SIZE height)
1596
{
1597
        nxResizeWindowReq *req;
1598
 
1599
        req = AllocReq(ResizeWindow);
1600
        req->windowid = wid;
1601
        req->width = width;
1602
        req->height = height;
1603
}
1604
 
1605
/**
1606
 * GrReparentWindow:
1607
 * @wid: the ID of the window to reparent
1608
 * @pwid: the ID of the new parent window
1609
 * @x: the X coordinate to place the window at relative to the new parent
1610
 * @y: the Y coordinate to place the window at relative to the new parent
1611
 *
1612
 * Changes the parent window of the specified window to the specified parent
1613
 * window and places it at the specified coordinates relative to the new
1614
 * parent.
1615
 */
1616
void
1617
GrReparentWindow(GR_WINDOW_ID wid, GR_WINDOW_ID pwid, GR_COORD x, GR_COORD y)
1618
{
1619
        nxReparentWindowReq *req;
1620
 
1621
        req = AllocReq(ReparentWindow);
1622
        req->windowid = wid;
1623
        req->parentid = pwid;
1624
        req->x = x;
1625
        req->y = y;
1626
}
1627
 
1628
/**
1629
 * GrClearArea:
1630
 * @wid: window ID
1631
 * @exposeflag: a flag indicating whether to also generate an exposure event
1632
 *
1633
 * Clears the specified window by to its background color or pixmap.
1634
 * If exposeflag is non zero, an exposure event is generated for
1635
 * the window after it has been cleared.
1636
 */
1637
void
1638
GrClearArea(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y, GR_SIZE width,
1639
        GR_SIZE height, GR_BOOL exposeflag)
1640
{
1641
        nxClearAreaReq *req;
1642
 
1643
        req = AllocReq(ClearArea);
1644
        req->windowid = wid;
1645
        req->x = x;
1646
        req->y = y;
1647
        req->width = width;
1648
        req->height = height;
1649
        req->exposeflag = exposeflag;
1650
}
1651
 
1652
/**
1653
 * GrGetFocus:
1654
 * @Returns: the ID of the window which currently has the keyboard focus
1655
 *
1656
 * Returns the ID of the window which currently has the keyboard focus.
1657
 */
1658
GR_WINDOW_ID
1659
GrGetFocus(void)
1660
{
1661
        GR_WINDOW_ID    wid;
1662
 
1663
        AllocReq(GetFocus);
1664
        if(GrTypedReadBlock(&wid, sizeof(wid), GrNumGetFocus) == -1)
1665
                return 0;
1666
        return wid;
1667
}
1668
 
1669
/**
1670
 * GrSetFocus:
1671
 * @wid: the ID of the window to set the focus to
1672
 *
1673
 * Sets the keyboard focus to the specified window.
1674
 */
1675
void
1676
GrSetFocus(GR_WINDOW_ID wid)
1677
{
1678
        nxSetFocusReq *req;
1679
 
1680
        req = AllocReq(SetFocus);
1681
        req->windowid = wid;
1682
}
1683
 
1684
/**
1685
 * GrSetWindowCursor:
1686
 * @wid: the ID of the window to set the cursor for
1687
 * @cid: the cursor ID
1688
 *
1689
 * Specify a cursor for a window.
1690
 * This cursor will only be used within that window, and by default
1691
 * for its new children.  If the cursor is currently within this
1692
 * window, it will be changed to the new one immediately.
1693
 * If the new cursor ID is 0, revert to the root window cursor.
1694
 */
1695
void
1696
GrSetWindowCursor(GR_WINDOW_ID wid, GR_CURSOR_ID cid)
1697
{
1698
        nxSetWindowCursorReq *req;
1699
 
1700
        req = AllocReq(SetWindowCursor);
1701
        req->windowid = wid;
1702
        req->cursorid = cid;
1703
}
1704
 
1705
/**
1706
 * GrNewCursor:
1707
 * @width: the width of the pointer bitmap
1708
 * @height: the height of the pointer bitmap
1709
 * @hotx: the X coordinate within the bitmap used as the target of the pointer
1710
 * @hoty: the Y coordinate within the bitmap used as the target of the pointer
1711
 * @foreground: the colour to use for the foreground of the pointer
1712
 * @background: the colour to use for the background of the pointer
1713
 * @fgbitmap: pointer to bitmap data specifying the foreground of the pointer
1714
 * @bgbitmap: pointer to bitmap data specifying the background of the pointer
1715
 *
1716
 * Creates a server-based cursor (mouse graphic) resource.
1717
 */
1718
GR_CURSOR_ID
1719
GrNewCursor(GR_SIZE width, GR_SIZE height, GR_COORD hotx, GR_COORD hoty,
1720
        GR_COLOR foreground, GR_COLOR background,
1721
        GR_BITMAP *fgbitmap, GR_BITMAP *bgbitmap)
1722
{
1723
        nxNewCursorReq *req;
1724
        int             bitmapsize;
1725
        char *          data;
1726
        GR_CURSOR_ID    cursorid;
1727
 
1728
        bitmapsize = GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP);
1729
        req = AllocReqExtra(NewCursor, bitmapsize*2);
1730
        req->width = width;
1731
        req->height = height;
1732
        req->hotx = hotx;
1733
        req->hoty = hoty;
1734
        req->fgcolor = foreground;
1735
        req->bgcolor = background;
1736
        data = GetReqData(req);
1737
        memcpy(data, fgbitmap, bitmapsize);
1738
        memcpy(data+bitmapsize, bgbitmap, bitmapsize);
1739
 
1740
        if(GrTypedReadBlock(&cursorid, sizeof(cursorid), GrNumNewCursor) == -1)
1741
                return 0;
1742
        return cursorid;
1743
}
1744
 
1745
/**
1746
 * GrMoveCursor:
1747
 * @x: the X coordinate to move the pointer to
1748
 * @y: the Y coordinate to move the pointer to
1749
 *
1750
 * Moves the cursor (mouse pointer) to the specified coordinates.
1751
 * The coordinates are relative to the root window, where (0,0) is the upper
1752
 * left hand corner of the screen. The reference point used for the pointer
1753
 * is that of the "hot spot". After moving the pointer, the graphic used for
1754
 * the pointer will change to the graphic defined for use in the window which
1755
 * it is over.
1756
 */
1757
void
1758
GrMoveCursor(GR_COORD x, GR_COORD y)
1759
{
1760
        nxMoveCursorReq *req;
1761
 
1762
        req = AllocReq(MoveCursor);
1763
        req->x = x;
1764
        req->y = y;
1765
}
1766
 
1767
/**
1768
 * GrSetGCForeground:
1769
 * @gc: the ID of the graphics context to set the foreground colour of
1770
 * @foreground: the colour to use as the new foreground colour
1771
 *
1772
 * Changes the foreground colour of the specified graphics context to the
1773
 * specified colour.
1774
 */
1775
void
1776
GrSetGCForeground(GR_GC_ID gc, GR_COLOR foreground)
1777
{
1778
        nxSetGCForegroundReq *req;
1779
 
1780
        req = AllocReq(SetGCForeground);
1781
        req->gcid = gc;
1782
        req->color = foreground;
1783
}
1784
 
1785
/**
1786
 * GrSetGCBackground:
1787
 * @gc: the ID of the graphics context to set the background colour of
1788
 * @background: the colour to use as the new background colour
1789
 *
1790
 * Changes the background colour of the specified graphics context to the
1791
 * specified colour.
1792
 */
1793
void
1794
GrSetGCBackground(GR_GC_ID gc, GR_COLOR background)
1795
{
1796
        nxSetGCBackgroundReq *req;
1797
 
1798
        req = AllocReq(SetGCBackground);
1799
        req->gcid = gc;
1800
        req->color = background;
1801
}
1802
 
1803
/**
1804
 * GrSetGCMode:
1805
 * @gc: the ID of the graphics context to set the drawing mode of
1806
 * @mode: the new drawing mode
1807
 *
1808
 * Changes the drawing mode (SET, XOR, OR, AND, etc.) of the specified
1809
 * graphics context to the specified mode.
1810
 */
1811
void
1812
GrSetGCMode(GR_GC_ID gc, int mode)
1813
{
1814
        nxSetGCModeReq *req;
1815
 
1816
        req = AllocReq(SetGCMode);
1817
        req->gcid = gc;
1818
        req->mode = mode;
1819
}
1820
 
1821
/**
1822
 * GrSetGCUseBackground:
1823
 * @gc: the ID of the graphics context to change the "use background" flag of
1824
 * @flag: flag specifying whether to use the background colour or not
1825
 *
1826
 * Sets the flag which chooses whether or not the background colour is used
1827
 * when drawing bitmaps and text using the specified graphics context to the
1828
 * specified value.
1829
 */
1830
void
1831
GrSetGCUseBackground(GR_GC_ID gc, GR_BOOL flag)
1832
{
1833
        nxSetGCUseBackgroundReq *req;
1834
 
1835
        req = AllocReq(SetGCUseBackground);
1836
        req->gcid = gc;
1837
        req->flag = flag;
1838
}
1839
 
1840
/**
1841
 * GrCreateFont:
1842
 * @name: string containing the name of a built in font to look for
1843
 * @height: the desired height of the font
1844
 * @plogfont: pointer to a LOGFONT structure
1845
 * @Returns: a font ID number which can be used to refer to the font
1846
 *
1847
 * Attempts to locate a font with the desired attributes and returns a font
1848
 * ID number which can be used to refer to it. If the plogfont argument is
1849
 * not NULL, the values in that structure will be used to choose a font.
1850
 * Otherwise, if the height is non zero, the built in font with the closest
1851
 * height to that specified will be used. If the height is zero, the built
1852
 * in font with the specified name will be used. If the desired font is not
1853
 * found, the first built in font will be returned as a last resort.
1854
 */
1855
GR_FONT_ID
1856
GrCreateFont(GR_CHAR *name, GR_COORD height, GR_LOGFONT *plogfont)
1857
{
1858
        nxCreateFontReq *req;
1859
        GR_FONT_ID      fontid;
1860
 
1861
        req = AllocReq(CreateFont);
1862
        if (plogfont) {
1863
                memcpy(&req->lf, plogfont, sizeof(*plogfont));
1864
                req->height = 0;
1865
                req->lf_used = 1;
1866
        } else {
1867
                if (name)
1868
                        strcpy(req->lf.lfFaceName, name);
1869
                else req->lf.lfFaceName[0] = '\0';
1870
                req->height = height;
1871
                req->lf_used = 0;
1872
        }
1873
 
1874
        if(GrTypedReadBlock(&fontid, sizeof(fontid),GrNumCreateFont) == -1)
1875
                return 0;
1876
        return fontid;
1877
}
1878
 
1879
/**
1880
 * GrGetFontList:
1881
 * @fonts: pointer used to return an array of font names.
1882
 * @numfonts: pointer used to return the number of names found.
1883
 *
1884
 * Returns an array of strings containing the names of available fonts and an
1885
 * integer that specifies the number of strings returned.
1886
 */
1887
void
1888
GrGetFontList(GR_FONTLIST ***fonts, int *numfonts)
1889
{
1890
        nxGetFontListReq *req;
1891
        char *tmpstr;
1892
        GR_FONTLIST **flist;
1893
        int num, len, i;
1894
 
1895
        req = AllocReq(GetFontList);
1896
 
1897
        GrTypedReadBlock(&num, sizeof(int), GrNumGetFontList);
1898
 
1899
        *numfonts = num;
1900
 
1901
        if(num == -1)
1902
                return;
1903
 
1904
        flist = (GR_FONTLIST**)malloc(num * sizeof(GR_FONTLIST*));
1905
 
1906
        for(i = 0; i < num; i++)
1907
                flist[i] = (GR_FONTLIST*)malloc(sizeof(GR_FONTLIST*));
1908
 
1909
        for(i = 0; i < num; i++) {
1910
                GrReadBlock(&len, sizeof(int));
1911
                tmpstr = (char*)malloc(len * sizeof(char));
1912
                GrReadBlock(tmpstr, len * sizeof(char));
1913
                flist[i]->ttname = tmpstr;
1914
 
1915
                GrReadBlock(&len, sizeof(int));
1916
                tmpstr = (char*)malloc(len * sizeof(char));
1917
                GrReadBlock(tmpstr, len * sizeof(char));
1918
                flist[i]->mwname = tmpstr;
1919
 
1920
        }
1921
 
1922
        *fonts = flist;
1923
}
1924
 
1925
/**
1926
 * GrFreeFontList:
1927
 * @fonts: pointer to array returned by GrGetFontList
1928
 * @numfonts: the number of font names in the array
1929
 *
1930
 * free's the specified array.
1931
 */
1932
void
1933
GrFreeFontList(GR_FONTLIST ***fonts, int n)
1934
{
1935
        int i;
1936
        MWFONTLIST *g, **list = *fonts;
1937
 
1938
        for (i = 0; i < n; i++) {
1939
                g = list[i];
1940
                if(g) {
1941
                        if(g->mwname)
1942
                                free(g->mwname);
1943
                        if(g->ttname)
1944
                                free(g->ttname);
1945
                        free(g);
1946
                }
1947
        }
1948
        free(list);
1949
        *fonts = 0;
1950
}
1951
 
1952
/**
1953
 * GrSetFontSize:
1954
 * @fontid: the ID number of the font to change the size of
1955
 * @fontsize: the size to change the font to
1956
 *
1957
 * Changes the size of the specified font to the specified size.
1958
 */
1959
void
1960
GrSetFontSize(GR_FONT_ID fontid, GR_COORD fontsize)
1961
{
1962
        nxSetFontSizeReq *req;
1963
 
1964
        req = AllocReq(SetFontSize);
1965
        req->fontid = fontid;
1966
        req->fontsize = fontsize;
1967
}
1968
 
1969
/**
1970
 * GrSetFontRotation:
1971
 * @fontid: the ID number of the font to rotate
1972
 * @tenthdegrees: the angle to set the rotation to in tenths of a degree
1973
 *
1974
 * Changes the rotation of the specified font to the specified angle.
1975
 */
1976
void
1977
GrSetFontRotation(GR_FONT_ID fontid, int tenthdegrees)
1978
{
1979
        nxSetFontRotationReq *req;
1980
 
1981
        req = AllocReq(SetFontRotation);
1982
        req->fontid = fontid;
1983
        req->tenthdegrees = tenthdegrees;
1984
}
1985
 
1986
/**
1987
 * GrSetFontAttr:
1988
 * @fontid: the ID of the font to set the attributes of
1989
 * @setflags: mask specifying attribute flags to set
1990
 * @clrflags: mask specifying attribute flags to clear
1991
 *
1992
 * Changes the attributes (GR_TFKERNING, GR_TFANTIALIAS, GR_TFUNDERLINE, etc.)
1993
 * of the specified font according to the set and clear mask arguments.
1994
 */
1995
void
1996
GrSetFontAttr(GR_FONT_ID fontid, int setflags, int clrflags)
1997
{
1998
        nxSetFontAttrReq *req;
1999
 
2000
        req = AllocReq(SetFontAttr);
2001
        req->fontid = fontid;
2002
        req->setflags = setflags;
2003
        req->clrflags = clrflags;
2004
}
2005
 
2006
/**
2007
 * GrDestroyFont:
2008
 * @fontid: the ID of the font to destroy
2009
 *
2010
 * Frees all resources associated with the specified font ID, and if the font
2011
 * is a non built in type and this is the last ID referring to it, unloads the
2012
 * font from memory.
2013
 */
2014
void
2015
GrDestroyFont(GR_FONT_ID fontid)
2016
{
2017
        nxDestroyFontReq *req;
2018
 
2019
        req = AllocReq(DestroyFont);
2020
        req->fontid = fontid;
2021
}
2022
 
2023
/**
2024
 * GrSetGCFont:
2025
 * @gc: the ID of the graphics context to set the font of
2026
 * @font: the ID of the font
2027
 *
2028
 * Sets the font to be used for text drawing in the specified graphics
2029
 * context to the specified font ID.
2030
 */
2031
void
2032
GrSetGCFont(GR_GC_ID gc, GR_FONT_ID font)
2033
{
2034
        nxSetGCFontReq *req;
2035
 
2036
        req = AllocReq(SetGCFont);
2037
        req->gcid = gc;
2038
        req->fontid = font;
2039
}
2040
 
2041
/**
2042
 * GrLine:
2043
 * @id: the ID of the drawable to draw the line on
2044
 * @gc: the ID of the graphics context to use when drawing the line
2045
 * @x1: the X coordinate of the start of the line relative to the drawable
2046
 * @y1: the Y coordinate of the start of the line relative to the drawable
2047
 * @x2: the X coordinate of the end of the line relative to the drawable
2048
 * @y2: the Y coordinate of the end of the line relative to the drawable
2049
 *
2050
 * Draws a line using the specified graphics context on the specified drawable
2051
 * from (x1, y1) to (x2, y2), with coordinates given relative to the drawable.
2052
 */
2053
void
2054
GrLine(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x1, GR_COORD y1, GR_COORD x2,
2055
        GR_COORD y2)
2056
{
2057
        nxLineReq *req;
2058
 
2059
        req = AllocReq(Line);
2060
        req->drawid = id;
2061
        req->gcid = gc;
2062
        req->x1 = x1;
2063
        req->y1 = y1;
2064
        req->x2 = x2;
2065
        req->y2 = y2;
2066
}
2067
 
2068
/**
2069
 * GrRect:
2070
 * @id: the ID of the drawable to draw the rectangle on
2071
 * @gc: the ID of the graphics context to use when drawing the rectangle
2072
 * @x: the X coordinate of the rectangle relative to the drawable
2073
 * @y: the Y coordinate of the rectangle relative to the drawable
2074
 * @width: the width of the rectangle
2075
 * @height: the height of the rectangle
2076
 *
2077
 * Draw the boundary of a rectangle of the specified dimensions and position
2078
 * on the specified drawable using the specified graphics context.
2079
 */
2080
void
2081
GrRect(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
2082
        GR_SIZE height)
2083
{
2084
        nxRectReq *req;
2085
 
2086
        req = AllocReq(Rect);
2087
        req->drawid = id;
2088
        req->gcid = gc;
2089
        req->x = x;
2090
        req->y = y;
2091
        req->width = width;
2092
        req->height = height;
2093
}
2094
 
2095
/**
2096
 * GrFillRect:
2097
 * @id: the ID of the drawable to draw the rectangle on
2098
 * @gc: the ID of the graphics context to use when drawing the rectangle
2099
 * @x: the X coordinate of the rectangle relative to the drawable
2100
 * @y: the Y coordinate of the rectangle relative to the drawable
2101
 * @width: the width of the rectangle
2102
 * @height: the height of the rectangle
2103
 *
2104
 * Draw a filled rectangle of the specified dimensions and position on the
2105
 * specified drawable using the specified graphics context.
2106
 */
2107
void
2108
GrFillRect(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2109
        GR_SIZE width, GR_SIZE height)
2110
{
2111
        nxFillRectReq *req;
2112
 
2113
        req = AllocReq(FillRect);
2114
        req->drawid = id;
2115
        req->gcid = gc;
2116
        req->x = x;
2117
        req->y = y;
2118
        req->width = width;
2119
        req->height = height;
2120
}
2121
 
2122
/**
2123
 * GrEllipse:
2124
 * @id: the ID of the drawable to draw the ellipse on
2125
 * @gc: the ID of the graphics context to use when drawing the ellipse
2126
 * @x: the X coordinate to draw the ellipse at relative to the drawable
2127
 * @y: the Y coordinate to draw the ellipse at relative to the drawable
2128
 * @rx: the radius of the ellipse on the X axis
2129
 * @ry: the radius of the ellipse on the Y axis
2130
 *
2131
 * Draws the boundary of ellipse at the specified position using the specified
2132
 * dimensions and graphics context on the specified drawable.
2133
 */
2134
void
2135
GrEllipse(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE rx,
2136
        GR_SIZE ry)
2137
{
2138
        nxEllipseReq *req;
2139
 
2140
        req = AllocReq(Ellipse);
2141
        req->drawid = id;
2142
        req->gcid = gc;
2143
        req->x = x;
2144
        req->y = y;
2145
        req->rx = rx;
2146
        req->ry = ry;
2147
}
2148
 
2149
/**
2150
 * GrFillEllipse:
2151
 * @id: the ID of the drawable to draw the filled ellipse on
2152
 * @gc: the ID of the graphics context to use when drawing the ellipse
2153
 * @x: the X coordinate to draw the ellipse at relative to the drawable
2154
 * @y: the Y coordinate to draw the ellipse at relative to the drawable
2155
 * @rx: the radius of the ellipse on the X axis
2156
 * @ry: the radius of the ellipse on the Y axis
2157
 *
2158
 * Draws a filled ellipse at the specified position using the specified
2159
 * dimensions and graphics context on the specified drawable.
2160
 */
2161
void
2162
GrFillEllipse(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2163
        GR_SIZE rx, GR_SIZE ry)
2164
{
2165
        nxFillEllipseReq *req;
2166
 
2167
        req = AllocReq(FillEllipse);
2168
        req->drawid = id;
2169
        req->gcid = gc;
2170
        req->x = x;
2171
        req->y = y;
2172
        req->rx = rx;
2173
        req->ry = ry;
2174
}
2175
 
2176
/**
2177
 * GrArc:
2178
 * @id: the ID of the drawable to draw the arc on
2179
 * @gc: the graphics context to use when drawing the arc
2180
 * @x: the X coordinate to draw the arc at relative to the drawable
2181
 * @y: the Y coordinate to draw the arc at relative to the drawable
2182
 * @rx: the radius of the arc on the X axis
2183
 * @ry: the radius of the arc on the Y axis
2184
 * @ax: the X coordinate of the start of the arc relative to the drawable
2185
 * @ay: the Y coordinate of the start of the arc relative to the drawable
2186
 * @bx: the X coordinate of the end of the arc relative to the drawable
2187
 * @by: the Y coordinate of the end of the arc relative to the drawable
2188
 * @type: the fill style to use when drawing the arc
2189
 *
2190
 * Draws an arc with the specified dimensions at the specified position
2191
 * on the specified drawable using the specified graphics context.
2192
 * The type specifies the fill type. Possible values include GR_ARC and
2193
 * GR_PIE.
2194
 */
2195
void
2196
GrArc(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2197
        GR_SIZE rx, GR_SIZE ry, GR_COORD ax, GR_COORD ay,
2198
        GR_COORD bx, GR_COORD by, int type)
2199
{
2200
        nxArcReq *req;
2201
 
2202
        req = AllocReq(Arc);
2203
        req->drawid = id;
2204
        req->gcid = gc;
2205
        req->x = x;
2206
        req->y = y;
2207
        req->rx = rx;
2208
        req->ry = ry;
2209
        req->ax = ax;
2210
        req->ay = ay;
2211
        req->bx = bx;
2212
        req->by = by;
2213
        req->type = type;
2214
}
2215
 
2216
/**
2217
 * GrArcAngle:
2218
 * @id: the ID of the drawable to draw the arc on
2219
 * @gc: the graphics context to use when drawing the arc
2220
 * @x: the X coordinate to draw the arc at relative to the drawable
2221
 * @y: the Y coordinate to draw the arc at relative to the drawable
2222
 * @rx: the radius of the arc on the X axis
2223
 * @ry: the radius of the arc on the Y axis
2224
 * @angle1: the angle of the start of the arc
2225
 * @angle2: the angle of the end of the arc
2226
 * @type: the fill style to use when drawing the arc
2227
 *
2228
 * Draws an arc with the specified dimensions at the specified position
2229
 * on the specified drawable using the specified graphics context.
2230
 * The type specifies the fill type. Possible values include GR_ARC and
2231
 * GR_PIE. This function requires floating point support, and is slightly
2232
 * slower than the GrArc() function which does not require floating point.
2233
 */
2234
void
2235
GrArcAngle(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2236
        GR_SIZE rx, GR_SIZE ry, GR_COORD angle1, GR_COORD angle2, int type)
2237
{
2238
        nxArcAngleReq *req;
2239
 
2240
        req = AllocReq(ArcAngle);
2241
        req->drawid = id;
2242
        req->gcid = gc;
2243
        req->x = x;
2244
        req->y = y;
2245
        req->rx = rx;
2246
        req->ry = ry;
2247
        req->angle1 = angle1;
2248
        req->angle2 = angle2;
2249
        req->type = type;
2250
}
2251
 
2252
/**
2253
 * GrBitmap:
2254
 * @id: the ID of the drawable to draw the bitmap onto
2255
 * @gc: the ID of the graphics context to use when drawing the bitmap
2256
 * @x: the X coordinate to draw the bitmap at relative to the drawable
2257
 * @y: the Y coordinate to draw the bitmap at relative to the drawable
2258
 * @width: the width of the bitmap
2259
 * @height: the height of the bitmap
2260
 * @bitmaptable: pointer to the bitmap data
2261
 *
2262
 * Draws the monochrome bitmap data provided in the bitmaptable argument
2263
 * at the specified position on the specified drawable using the specified
2264
 * graphics context. Note that the bitmap data should be an array of aligned
2265
 * 16 bit words. The usebackground flag in the graphics context specifies
2266
 * whether to draw the background colour wherever a bit value is zero.
2267
 */
2268
void
2269
GrBitmap(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
2270
        GR_SIZE height, GR_BITMAP *bitmaptable)
2271
{
2272
        nxBitmapReq *req;
2273
        long         bitmapsize;
2274
 
2275
        bitmapsize = (long)GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP);
2276
        req = AllocReqExtra(Bitmap, bitmapsize);
2277
        req->drawid = id;
2278
        req->gcid = gc;
2279
        req->x = x;
2280
        req->y = y;
2281
        req->width = width;
2282
        req->height = height;
2283
        memcpy(GetReqData(req), bitmaptable, bitmapsize);
2284
}
2285
 
2286
/**
2287
 * GrDrawImageBits:
2288
 * @id: the ID of the drawable to draw the image onto
2289
 * @gc: the ID of the graphics context to use when drawing the image
2290
 * @x: the X coordinate to draw the image at relative to the drawable
2291
 * @y: the Y coordinate to draw the image at relative to the drawable
2292
 * @pimage: pointer to the image structure
2293
 *
2294
 * Draws the image contained in the specified image structure onto the
2295
 * specified drawable at the specified coordinates using the specified
2296
 * graphics context.
2297
 */
2298
void
2299
GrDrawImageBits(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2300
        GR_IMAGE_HDR *pimage)
2301
{
2302
        nxDrawImageBitsReq      *req;
2303
        int                     imagesize;
2304
        int                     palsize;
2305
        char                    *addr;
2306
 
2307
        imagesize = pimage->pitch * pimage->height;
2308
        palsize = pimage->palsize * sizeof(MWPALENTRY);
2309
        req = AllocReqExtra(DrawImageBits, imagesize + palsize);
2310
        req->drawid = id;
2311
        req->gcid = gc;
2312
        req->x = x;
2313
        req->y = y;
2314
        /* fill MWIMAGEHDR items passed externally*/
2315
        req->width = pimage->width;
2316
        req->height = pimage->height;
2317
        req->planes = pimage->planes;
2318
        req->bpp = pimage->bpp;
2319
        req->pitch = pimage->pitch;
2320
        req->bytesperpixel = pimage->bytesperpixel;
2321
        req->compression = pimage->compression;
2322
        req->palsize = pimage->palsize;
2323
        req->transcolor = pimage->transcolor;
2324
        addr = GetReqData(req);
2325
        memcpy(addr, pimage->imagebits, imagesize);
2326
        memcpy(addr+imagesize, pimage->palette, palsize);
2327
}
2328
 
2329
/**
2330
 * GrDrawImageFromFile:
2331
 * @id: the ID of the drawable to draw the image onto
2332
 * @gc: the ID of the graphics context to use when drawing the image
2333
 * @x: the X coordinate to draw the image at relative to the drawable
2334
 * @y: the Y coordinate to draw the image at relative to the drawable
2335
 * @width: the maximum image width
2336
 * @height: the maximum image height
2337
 * @path: string containing the filename of the image to load
2338
 * @flags: flags specific to the particular image loader
2339
 *
2340
 * Loads the specified image file and draws it at the specified position
2341
 * on the specified drawable using the specified graphics context. The
2342
 * width and height values specify the size of the image to draw- if the
2343
 * actual image is a different size, it will be scaled to fit. The image type
2344
 * is automatically detected using the magic numbers in the image header (ie.
2345
 * the filename extension is irrelevant). The currently supported image types
2346
 * include GIF, JPEG, Windows BMP, PNG, XPM, and both ascii and binary
2347
 * variants of PBM, PGM, and PPM. However the image types supported by a
2348
 * particular server depend on which image types were enabled in the server
2349
 * configuration at build time.
2350
 */
2351
void
2352
GrDrawImageFromFile(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2353
        GR_SIZE width, GR_SIZE height, char* path, int flags)
2354
{
2355
        nxDrawImageFromFileReq *req;
2356
 
2357
        req = AllocReqExtra(DrawImageFromFile, strlen(path)+1);
2358
        req->drawid = id;
2359
        req->gcid = gc;
2360
        req->x = x;
2361
        req->y = y;
2362
        req->width = width;
2363
        req->height = height;
2364
        req->flags = flags;
2365
        memcpy(GetReqData(req), path, strlen(path)+1);
2366
}
2367
 
2368
/**
2369
 * GrLoadImageFromFile:
2370
 * @path: string containing the filename of the image to load
2371
 * @flags: flags specific to the particular image loader
2372
 * @Returns: ID of the image buffer the image was loaded into
2373
 *
2374
 * Loads the specified image file into a newly created server image buffer
2375
 * and returns the ID of the buffer. The image type is automatically detected
2376
 * using the magic numbers in the image header (ie. the filename extension is
2377
 * irrelevant). The currently supported image types include GIF, JPEG, Windows
2378
 * BMP, PNG, XPM, and both ascii and binary variants of PBM, PGM, and PPM.
2379
 * However the image types supported by a particular server depend on which
2380
 * image types were enabled in the server configuration at build time.
2381
 */
2382
GR_IMAGE_ID
2383
GrLoadImageFromFile(char *path, int flags)
2384
{
2385
        nxLoadImageFromFileReq *req;
2386
        GR_IMAGE_ID             imageid;
2387
 
2388
        req = AllocReqExtra(LoadImageFromFile, strlen(path)+1);
2389
        req->flags = flags;
2390
        memcpy(GetReqData(req), path, strlen(path)+1);
2391
 
2392
        if(GrTypedReadBlock(&imageid, sizeof(imageid),
2393
                GrNumLoadImageFromFile) == -1)
2394
                        return 0;
2395
        return imageid;
2396
}
2397
 
2398
/**
2399
 * GrDrawImageToFit:
2400
 * @id: the ID of the drawable to draw the image onto
2401
 * @gc: the ID of the graphics context to use when drawing the image
2402
 * @x: the X coordinate to draw the image at relative to the drawable
2403
 * @y: the Y coordinate to draw the image at relative to the drawable
2404
 * @width: the maximum image width
2405
 * @height: the maximum image height
2406
 * @imageid: the ID of the image buffer containing the image to display
2407
 *
2408
 * Draws the image from the specified image buffer at the specified position
2409
 * on the specified drawable using the specified graphics context. The
2410
 * width and height values specify the size of the image to draw- if the
2411
 * actual image is a different size, it will be scaled to fit.
2412
 */
2413
void
2414
GrDrawImageToFit(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2415
        GR_SIZE width, GR_SIZE height, GR_IMAGE_ID imageid)
2416
{
2417
        nxDrawImageToFitReq *req;
2418
 
2419
        req = AllocReq(DrawImageToFit);
2420
        req->drawid = id;
2421
        req->gcid = gc;
2422
        req->x = x;
2423
        req->y = y;
2424
        req->width = width;
2425
        req->height = height;
2426
        req->imageid = imageid;
2427
}
2428
 
2429
/**
2430
 * GrFreeImage:
2431
 * @id: ID of the image buffer to free
2432
 *
2433
 * Destroys the specified image buffer and reclaims the memory used by it.
2434
 */
2435
void
2436
GrFreeImage(GR_IMAGE_ID id)
2437
{
2438
        nxFreeImageReq *req;
2439
 
2440
        req = AllocReq(FreeImage);
2441
        req->id = id;
2442
}
2443
 
2444
/**
2445
 * GrGetImageInfo:
2446
 * @id: ID of an image buffer
2447
 * @iip: pointer to a GR_IMAGE_INFO structure
2448
 *
2449
 * Fills in the specified image information structure with the details of the
2450
 * specified image buffer.
2451
 */
2452
void
2453
GrGetImageInfo(GR_IMAGE_ID id, GR_IMAGE_INFO *iip)
2454
{
2455
        nxGetImageInfoReq *req;
2456
 
2457
        req = AllocReq(GetImageInfo);
2458
        req->id = id;
2459
        GrTypedReadBlock(iip, sizeof(GR_IMAGE_INFO), GrNumGetImageInfo);
2460
}
2461
 
2462
static int sendImageBuffer(void *buffer, int size) {
2463
 
2464
  int bufid;
2465
  int bufsize = size;
2466
  void *bufptr = buffer;
2467
 
2468
  nxImageBufferAllocReq *alloc;
2469
  nxImageBufferSendReq *send;
2470
 
2471
  /* Step 1 - Allocate a buffer on the other side */
2472
 
2473
  alloc = AllocReq(ImageBufferAlloc);
2474
  alloc->size = size;
2475
 
2476
  GrTypedReadBlock(&bufid, sizeof(bufid), GrNumImageBufferAlloc);
2477
 
2478
  if (bufid < 0) return(0);
2479
 
2480
  /* step 2 - Send the buffer across */
2481
 
2482
  while(bufsize > 0) {
2483
    int chunk = (MAXREQUESTSZ - sizeof(nxImageBufferSendReq));
2484
    if (chunk > bufsize) chunk=bufsize;
2485
 
2486
    send = AllocReqExtra(ImageBufferSend, chunk);
2487
    send->buffer_id = bufid;
2488
    send->size = chunk;
2489
 
2490
    memcpy(GetReqData(send), bufptr, chunk);
2491
    bufptr += chunk;
2492
    bufsize -= chunk;
2493
  }
2494
 
2495
  return(bufid);
2496
}
2497
 
2498
GR_IMAGE_ID GrLoadImageFromBuffer(void *buffer, int size, int flags) {
2499
 
2500
  int bufid;
2501
  nxLoadImageFromBufferReq *req;
2502
  GR_IMAGE_ID imageid;
2503
 
2504
  /* Step 1 - Send the buffer to the other side */
2505
  bufid = sendImageBuffer(buffer, size);
2506
 
2507
  if (!bufid) return(0);
2508
 
2509
  /* Step 2 - Send the command to load the image */
2510
  /* Note - This will free the buffer automagically */
2511
 
2512
  req = AllocReq(LoadImageFromBuffer);
2513
  req->flags = flags;
2514
  req->buffer = bufid;
2515
 
2516
  if(GrTypedReadBlock(&imageid, sizeof(imageid),
2517
                      GrNumLoadImageFromBuffer) == -1)
2518
    return(0);
2519
  else
2520
    return(imageid);
2521
}
2522
 
2523
void GrDrawImageFromBuffer(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2524
                           GR_SIZE width, GR_SIZE height,
2525
                           void *buffer, int size, int flags) {
2526
 
2527
  int bufid;
2528
  nxDrawImageFromBufferReq *req;
2529
 
2530
  /* Step 1 - Send the buffer to the other side */
2531
  bufid = sendImageBuffer(buffer, size);
2532
 
2533
  if (!bufid) return;
2534
 
2535
  /* Step 2 - Send the command to load/draw the image */
2536
  /* Note - This will free the buffer automagically */
2537
 
2538
  req = AllocReq(DrawImageFromBuffer);
2539
  req->flags = flags;
2540
  req->drawid = id;
2541
  req->gcid = gc;
2542
  req->x = x;
2543
  req->y = y;
2544
  req->width = width;
2545
  req->height = height;
2546
  req->flags = flags;
2547
  req->buffer = bufid;
2548
}
2549
 
2550
 
2551
/*
2552
 * Draw a rectangular area in the specified drawable using the specified
2553
 * graphics context.  This differs from rectangle drawing in that the
2554
 * color values for each pixel in the rectangle are specified.
2555
 * The color table is indexed
2556
 * row by row.  Values whose color matches the background color are only
2557
 * written if the usebackground flag is set in the GC.
2558
 *
2559
 * The pixels are packed according to pixtype:
2560
 *
2561
 * pixtype              array of
2562
 * MWPF_RGB             MWCOLORVAL (unsigned long)
2563
 * MWPF_PIXELVAL        MWPIXELVAL (compile-time dependent)
2564
 * MWPF_PALETTE         unsigned char
2565
 * MWPF_TRUECOLOR0888   unsigned long
2566
 * MWPF_TRUECOLOR888    packed struct {char r,char g,char b} (24 bits)
2567
 * MWPF_TRUECOLOR565    unsigned short
2568
 * MWPF_TRUECOLOR555    unsigned short
2569
 * MWPF_TRUECOLOR332    unsigned char
2570
 * MWPF_TRUECOLOR223    unsigned char
2571
 */
2572
/**
2573
 * GrArea:
2574
 * @id: the ID of the drawable to draw the area onto
2575
 * @gc: the ID of the graphics context to use when drawing the area
2576
 * @x: the X coordinate to draw the area at relative to the drawable
2577
 * @y: the Y coordinate to draw the area at relative to the drawable
2578
 * @width: the width of the area
2579
 * @height: the height of the area
2580
 * @pixels: pointer to an array containing the pixel data
2581
 * @pixtype: the format of the pixel data
2582
 *
2583
 * Draws the specified pixel array of the specified size and format onto the
2584
 * specified drawable using the specified graphics context at the specified
2585
 * position. Note that colour conversion is currently only performed when using
2586
 * the GR_PF_RGB format, which is an unsigned long containing RGBX data.
2587
 */
2588
void
2589
GrArea(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
2590
        GR_SIZE height, void *pixels, int pixtype)
2591
{
2592
        nxAreaReq *req;
2593
        long       size;
2594
        long       chunk_y;
2595
        int        pixsize;
2596
 
2597
        /* Calculate size of packed pixels*/
2598
        switch(pixtype) {
2599
        case MWPF_RGB:
2600
                pixsize = sizeof(MWCOLORVAL);
2601
                break;
2602
        case MWPF_PIXELVAL:
2603
                pixsize = sizeof(MWPIXELVAL);
2604
                break;
2605
        case MWPF_PALETTE:
2606
        case MWPF_TRUECOLOR332:
2607
        case MWPF_TRUECOLOR233:
2608
                pixsize = sizeof(unsigned char);
2609
                break;
2610
        case MWPF_TRUECOLOR0888:
2611
                pixsize = sizeof(unsigned long);
2612
                break;
2613
        case MWPF_TRUECOLOR888:
2614
                pixsize = 3;
2615
                break;
2616
        case MWPF_TRUECOLOR565:
2617
        case MWPF_TRUECOLOR555:
2618
                pixsize = sizeof(unsigned short);
2619
                break;
2620
        default:
2621
                return;
2622
        }
2623
 
2624
        /* Break request into MAXREQUESTSZ size packets*/
2625
        while(height > 0) {
2626
                chunk_y = (MAXREQUESTSZ - sizeof(nxAreaReq)) /
2627
                        ((long)width * pixsize);
2628
                if(chunk_y > height)
2629
                        chunk_y = height;
2630
                size = chunk_y * ((long)width * pixsize);
2631
                req = AllocReqExtra(Area, size);
2632
                req->drawid = id;
2633
                req->gcid = gc;
2634
                req->x = x;
2635
                req->y = y;
2636
                req->width = width;
2637
                req->height = chunk_y;
2638
                req->pixtype = pixtype;
2639
                memcpy(GetReqData(req), pixels, size);
2640
                pixels = (void *)(((char *)pixels) + size);
2641
                y += chunk_y;
2642
                height -= chunk_y;
2643
        }
2644
}
2645
 
2646
/**
2647
 * GrCopyArea:
2648
 * @id: the ID of the drawable to copy the area to
2649
 * @gc: the ID of the graphics context to use when copying the area
2650
 * @x: the X coordinate to copy the area to within the destination drawable
2651
 * @y: the Y coordinate to copy the area to within the destination drawable
2652
 * @width: the width of the area to copy
2653
 * @height: the height of the area to copy
2654
 * @srcid: the ID of the drawable to copy the area from
2655
 * @srcx: the X coordinate to copy the area from within the source drawable
2656
 * @srcy: the Y coordinate to copy the area from within the source drawable
2657
 * @op: the ROP codes to pass to the blitter when performing the copy
2658
 *
2659
 * Copies the specified area of the specified size between the specified
2660
 * drawables at the specified positions using the specified graphics context
2661
 * and ROP codes. 0 is a sensible default ROP code in most cases.
2662
 */
2663
void
2664
GrCopyArea(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2665
        GR_SIZE width, GR_SIZE height, GR_DRAW_ID srcid,
2666
        GR_COORD srcx, GR_COORD srcy, int op)
2667
{
2668
        nxCopyAreaReq *req;
2669
 
2670
        req = AllocReq(CopyArea);
2671
        req->drawid = id;
2672
        req->gcid = gc;
2673
        req->x = x;
2674
        req->y = y;
2675
        req->width = width;
2676
        req->height = height;
2677
        req->srcid = srcid;
2678
        req->srcx = srcx;
2679
        req->srcy = srcy;
2680
        req->op = op;
2681
}
2682
 
2683
 
2684
/**
2685
 * GrReadArea:
2686
 * @id: the ID of the drawable to read an area from
2687
 * @x: the X coordinate to read the area from relative to the drawable
2688
 * @y: the Y coordinate to read the area from relative to the drawable
2689
 * @width: the width of the area to read
2690
 * @height: the height of the area to read
2691
 * @pixels: pointer to an area of memory to place the pixel data in
2692
 *
2693
 * Reads the pixel data of the specified size from the specified position on
2694
 * the specified drawable into the specified pixel array. If the drawable is
2695
 * a window, the data returned will be the pixel values from the relevant
2696
 * position on the screen regardless of whether the window is obscured by other
2697
 * windows. If the window is unmapped, or partially or fully outside a window
2698
 * boundary, black pixel values will be returned.
2699
 */
2700
void
2701
GrReadArea(GR_DRAW_ID id,GR_COORD x,GR_COORD y,GR_SIZE width,
2702
        GR_SIZE height, GR_PIXELVAL *pixels)
2703
{
2704
        nxReadAreaReq *req;
2705
        long           size;
2706
 
2707
        req = AllocReq(ReadArea);
2708
        req->drawid = id;
2709
        req->x = x;
2710
        req->y = y;
2711
        req->width = width;
2712
        req->height = height;
2713
        size = (long)width * height * sizeof(MWPIXELVAL);
2714
        GrTypedReadBlock(pixels, size, GrNumReadArea);
2715
}
2716
 
2717
/**
2718
 * GrPoint:
2719
 * @id: the ID of the drawable to draw a point on
2720
 * @gc: the ID of the graphics context to use when drawing the point
2721
 * @x: the X coordinate to draw the point at relative to the drawable
2722
 * @y: the Y coordinate to draw the point at relative to the drawable
2723
 *
2724
 * Draws a point using the specified graphics context at the specified position
2725
 * on the specified drawable.
2726
 */
2727
void
2728
GrPoint(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y)
2729
{
2730
        nxPointReq *req;
2731
 
2732
        req = AllocReq(Point);
2733
        req->drawid = id;
2734
        req->gcid = gc;
2735
        req->x = x;
2736
        req->y = y;
2737
 
2738
}
2739
 
2740
/**
2741
 * GrPoints:
2742
 * @id: the ID of the drawable to draw a point on
2743
 * @gc: the ID of the graphics context to use when drawing the point
2744
 * @count: the number of points in the point table
2745
 * @pointtable: pointer to a GR_POINT array which lists the points to draw
2746
 *
2747
 * Draws a set of points using the specified graphics context at the positions
2748
 * specified by the point table on the specified drawable.
2749
 */
2750
void
2751
GrPoints(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
2752
{
2753
        nxPointsReq *req;
2754
        long    size;
2755
 
2756
        size = (long)count * sizeof(GR_POINT);
2757
        req = AllocReqExtra(Points, size);
2758
        req->drawid = id;
2759
        req->gcid = gc;
2760
        memcpy(GetReqData(req), pointtable, size);
2761
}
2762
 
2763
/**
2764
 * GrPoly:
2765
 * @id: the ID of the drawable to draw the polygon onto
2766
 * @gc: the ID of the graphics context to use when drawing the polygon
2767
 * @count: the number of points in the point array
2768
 * @pointtable: pointer to an array of points describing the polygon
2769
 *
2770
 * Draws an unfilled polygon on the specified drawable using the specified
2771
 * graphics context. The polygon is specified by an array of point structures.
2772
 * The polygon is not automatically closed- if a closed polygon is desired,
2773
 * the last point must be the same as the first.
2774
 */
2775
void
2776
GrPoly(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
2777
{
2778
        nxPolyReq *req;
2779
        long       size;
2780
 
2781
        size = (long)count * sizeof(GR_POINT);
2782
        req = AllocReqExtra(Poly, size);
2783
        req->drawid = id;
2784
        req->gcid = gc;
2785
        memcpy(GetReqData(req), pointtable, size);
2786
}
2787
 
2788
/**
2789
 * GrFillPoly:
2790
 * @id: the ID of the drawable to draw the polygon onto
2791
 * @gc: the ID of the graphics context to use when drawing the polygon
2792
 * @count: the number of points in the point array
2793
 * @pointtable: pointer to an array of points describing the polygon
2794
 *
2795
 * Draws a filled polygon on the specified drawable using the specified
2796
 * graphics context. The polygon is specified by an array of point structures.
2797
 * The polygon is automatically closed- the last point need not be the same as
2798
 * the first in order for the polygon to be closed.
2799
 */
2800
void
2801
GrFillPoly(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count,GR_POINT *pointtable)
2802
{
2803
        nxFillPolyReq *req;
2804
        long           size;
2805
 
2806
        size = (long)count * sizeof(GR_POINT);
2807
        req = AllocReqExtra(FillPoly, size);
2808
        req->drawid = id;
2809
        req->gcid = gc;
2810
        memcpy(GetReqData(req), pointtable, size);
2811
}
2812
 
2813
/**
2814
 * GrText:
2815
 * @id: the ID of the drawable to draw the text string onto
2816
 * @gc: the ID of the graphics context to use when drawing the text string
2817
 * @x: the X coordinate to draw the string at relative to the drawable
2818
 * @y: the Y coordinate to draw the string at relative to the drawable
2819
 * @str: the text string to draw
2820
 * @count: the number of characters (not bytes) in the string
2821
 * @flags: flags specifying text encoding, alignment, etc.
2822
 *
2823
 * Draws the specified text string at the specified position on the specified
2824
 * drawable using the specified graphics context and flags. The default flags
2825
 * specify ASCII encoding and baseline alignment.
2826
 */
2827
void
2828
GrText(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, void *str,
2829
        GR_COUNT count, int flags)
2830
{
2831
        nxTextReq *req;
2832
        int        size;
2833
 
2834
        if(count == -1 && (flags&MWTF_PACKMASK) == MWTF_ASCII)
2835
                count = strlen((char *)str);
2836
 
2837
        size = nxCalcStringBytes(str, count, flags);
2838
 
2839
        req = AllocReqExtra(Text, size);
2840
        req->drawid = id;
2841
        req->gcid = gc;
2842
        req->x = x;
2843
        req->y = y;
2844
        req->count = count;
2845
        req->flags = flags;
2846
        memcpy(GetReqData(req), str, size);
2847
}
2848
 
2849
 
2850
/**
2851
 * GrGetSystemPalette:
2852
 * @pal: pointer to a palette structure to fill in with the system palette
2853
 *
2854
 * Retrieves the system palette and places it in the specified palette
2855
 * structure.
2856
 */
2857
void
2858
GrGetSystemPalette(GR_PALETTE *pal)
2859
{
2860
        AllocReq(GetSystemPalette);
2861
        GrTypedReadBlock(pal, sizeof(*pal), GrNumGetSystemPalette);
2862
}
2863
 
2864
/**
2865
 * GrSetSystemPalette:
2866
 * @first: the first palette value to set
2867
 * @pal: pointer to a palette structure containing the new values
2868
 *
2869
 * Sets the system palette to the values stored in the specified palette
2870
 * structure. The values before the specified first value are not set.
2871
 */
2872
void
2873
GrSetSystemPalette(GR_COUNT first, GR_PALETTE *pal)
2874
{
2875
        nxSetSystemPaletteReq *req;
2876
 
2877
        req = AllocReq(SetSystemPalette);
2878
        req->first = first;
2879
        req->count = pal->count;
2880
        memcpy(req->palette, pal->palette, sizeof(GR_PALENTRY) * pal->count);
2881
}
2882
 
2883
/**
2884
 * GrFindColor:
2885
 * @c: the colour value to find
2886
 * @retpixel: pointer to the returned pixel value
2887
 *
2888
 * Calculates the pixel value to use to display the specified colour value.
2889
 * The colour value is specified as a GR_COLOR, which is a 32 bit truecolour
2890
 * value stored as RGBX. The pixel value size depends on the architecture.
2891
 */
2892
void
2893
GrFindColor(GR_COLOR c, GR_PIXELVAL *retpixel)
2894
{
2895
        nxFindColorReq *req;
2896
 
2897
        req = AllocReq(FindColor);
2898
        req->color = c;
2899
        GrTypedReadBlock(retpixel, sizeof(*retpixel), GrNumFindColor);
2900
}
2901
 
2902
/**
2903
 * GrReqShmCmds:
2904
 * @shmsize: the size of the shared memory area to allocate
2905
 *
2906
 * Requests a shared memory area of the specified size to use for transferring
2907
 * command arguments. This is faster but less portable than the standard BSD
2908
 * sockets method of communication (and of course will only work if the client
2909
 * and server are on the same machine). Apart from the initial allocation of
2910
 * the area using this call, the use of shared memory is completely
2911
 * transparent. Additionally, if the allocation fails we silently and
2912
 * automatically fall back on socket communication. It is safe to call this
2913
 * function even if shared memory support is not compiled in; it will simply
2914
 * do nothing.
2915
 *
2916
 * FIXME: how does the user decide what size of shared memory area to allocate?
2917
 */
2918
void
2919
GrReqShmCmds(long shmsize)
2920
{
2921
#if HAVE_SHAREDMEM_SUPPORT
2922
        nxReqShmCmdsReq req;
2923
        int key, shmid;
2924
 
2925
        if ( nxSharedMem != 0 )
2926
                return;
2927
 
2928
        GrFlush();
2929
 
2930
        shmsize = (shmsize+SHM_BLOCK_SIZE-1) & ~(SHM_BLOCK_SIZE-1);
2931
 
2932
        req.reqType = GrNumReqShmCmds;
2933
        req.hilength = 0;
2934
        req.length = sizeof(req);
2935
        req.size = shmsize;
2936
 
2937
        nxWriteSocket((char *)&req,sizeof(req));
2938
        GrReadBlock(&key,sizeof(key));
2939
 
2940
        if ( !key ) {
2941
                EPRINTF("nxclient: no shared memory support on server\n");
2942
                return;
2943
        }
2944
 
2945
        shmid = shmget(key,shmsize,0);
2946
        if ( shmid == -1 ) {
2947
                EPRINTF("nxclient: Can't shmget key %d: %m\n", key);
2948
                return;
2949
        }
2950
 
2951
        nxSharedMem = shmat(shmid,0,0);
2952
        shmctl(shmid,IPC_RMID,0);        /* Prevent other from attaching */
2953
        if ( nxSharedMem == (char *)-1 )
2954
                return;
2955
 
2956
        nxSharedMemSize = shmsize;
2957
        nxAssignReqbuffer(nxSharedMem, shmsize);
2958
#endif /* HAVE_SHAREDMEM_SUPPORT*/
2959
}
2960
 
2961
/**
2962
 * GrInjectPointerEvent:
2963
 * @x: the X coordinate of the pointer event relevant to the root window
2964
 * @y: the Y coordinate of the pointer event relevant to the root window
2965
 * @button: the pointer button status
2966
 * @visible: whether to display the pointer after the event
2967
 *
2968
 * Sets the pointer invisible if the visible parameter is GR_FALSE, or visible
2969
 * if it is GR_TRUE, then moves the pointer to the specified position and
2970
 * generates a mouse event with the specified button status. Also performs
2971
 * a GrFlush() so that the event takes effect immediately.
2972
 */
2973
void
2974
GrInjectPointerEvent(GR_COORD x, GR_COORD y, int button, int visible)
2975
{
2976
        nxInjectEventReq *req;
2977
 
2978
        req = AllocReq(InjectEvent);
2979
        req->event_type = GR_INJECT_EVENT_POINTER;
2980
        req->event.pointer.visible = visible;
2981
        req->event.pointer.x = x;
2982
        req->event.pointer.y = y;
2983
        req->event.pointer.button = button;
2984
 
2985
        GrFlush();
2986
}
2987
 
2988
/**
2989
 * GrInjectKeyboardEvent:
2990
 * @wid: ID of the window to send the event to, or 0
2991
 * @uch: 32 bit Unicode keystroke value to inject
2992
 * @ch: 8 bit ascii keystroke value to inject
2993
 * @modifier: modifiers (shift, ctrl, alt, etc.) to inject
2994
 * @special: special keys to inject
2995
 * @content: mask specifying which arguments are valid
2996
 *
2997
 * Sends a keyboard event to the specified window, or to the window with the
2998
 * current keyboard focus if 0 is used as the ID. The other arguments
2999
 * correspond directly to the fields of the same names in the keyboard event
3000
 * structure.
3001
 */
3002
void
3003
GrInjectKeyboardEvent(GR_WINDOW_ID wid, GR_KEY keyvalue,
3004
        GR_KEYMOD modifier, GR_SCANCODE scancode, GR_BOOL pressed)
3005
{
3006
        nxInjectEventReq *req;
3007
 
3008
        req = AllocReq(InjectEvent);
3009
        req->event_type = GR_INJECT_EVENT_KEYBOARD;
3010
        req->event.keyboard.wid = wid;
3011
        req->event.keyboard.keyvalue = keyvalue;
3012
        req->event.keyboard.modifier = modifier;
3013
        req->event.keyboard.scancode = scancode;
3014
        req->event.keyboard.pressed = pressed;
3015
 
3016
        GrFlush();
3017
}
3018
 
3019
/**
3020
 * GrSetWMProperties:
3021
 * @wid: the ID of the window to set the WM properties of
3022
 * @props: pointer to a GR_WM_PROPERTIES structure
3023
 *
3024
 * Copies the provided GR_WM_PROPERTIES structure into the the GR_WM_PROPERTIES
3025
 * structure of the specified window id.
3026
 */
3027
void
3028
GrSetWMProperties(GR_WINDOW_ID wid, GR_WM_PROPERTIES *props)
3029
{
3030
        nxSetWMPropertiesReq *req;
3031
        char            *addr;
3032
        int             s;
3033
 
3034
        if ((props->flags & GR_WM_FLAGS_TITLE) && props->title)
3035
                s = strlen(props->title) + 1;
3036
        else s = 0;
3037
 
3038
        req = AllocReqExtra(SetWMProperties, s + sizeof(GR_WM_PROPERTIES));
3039
        req->windowid = wid;
3040
        addr = GetReqData(req);
3041
        memcpy(addr, props, sizeof(GR_WM_PROPERTIES));
3042
        if (s)
3043
                memcpy(addr + sizeof(GR_WM_PROPERTIES), props->title, s);
3044
}
3045
 
3046
/**
3047
 * GrGetWMProperties:
3048
 * @wid: the ID of the window to retreive the WM properties of
3049
 * @props: pointer to a GR_WM_PROPERTIES structure to fill in
3050
 *
3051
 * Reads the GR_WM_PROPERTIES structure for the window with the specified
3052
 * id and fills in the provided structure with the information.
3053
 * It is the callers responsibility to free the title member as it is allocated
3054
 * dynamically. The title field will be set to NULL if the window has no title.
3055
 */
3056
void
3057
GrGetWMProperties(GR_WINDOW_ID wid, GR_WM_PROPERTIES *props)
3058
{
3059
        nxGetWMPropertiesReq *req;
3060
        UINT16 textlen;
3061
        GR_CHAR c;
3062
 
3063
        req = AllocReq(GetWMProperties);
3064
        req->windowid = wid;
3065
 
3066
        GrTypedReadBlock(props, sizeof(GR_WM_PROPERTIES), GrNumGetWMProperties);
3067
        GrReadBlock(&textlen, sizeof(textlen));
3068
        if(!textlen) {
3069
                props->title = NULL;
3070
                return;
3071
        }
3072
        if(!(props->title = malloc(textlen))) {
3073
                /* Oh dear, we're out of memory but still have to purge the
3074
                   requested data (and throw it away) */
3075
                while(textlen--) GrReadBlock(&c, 1);
3076
        } else {
3077
                GrReadBlock(props->title, textlen);
3078
        }
3079
}
3080
 
3081
/**
3082
 * GrCloseWindow:
3083
 * @wid: the ID of the window to send the CLOSE_REQ event to
3084
 *
3085
 * Sends a CLOSE_REQ event to the specified window if the client has selected
3086
 * to receive CLOSE_REQ events on this window. Used to request an application
3087
 * to shut down but not force it to do so immediately, so the application can
3088
 * ask whether to save changed files before shutting down cleanly.
3089
 */
3090
void
3091
GrCloseWindow(GR_WINDOW_ID wid)
3092
{
3093
        nxCloseWindowReq *req;
3094
 
3095
        req = AllocReq(CloseWindow);
3096
        req->windowid = wid;
3097
}
3098
 
3099
/**
3100
 * GrKillWindow:
3101
 * @wid: the ID of the window to kill
3102
 *
3103
 * Forcibly disconnects the client which owns this window with the specified
3104
 * ID number. Used to kill an application which has locked up and is not
3105
 * responding to CLOSE_REQ events.
3106
 */
3107
void
3108
GrKillWindow(GR_WINDOW_ID wid)
3109
{
3110
        nxKillWindowReq *req;
3111
 
3112
        req = AllocReq(KillWindow);
3113
        req->windowid = wid;
3114
}
3115
 
3116
/**
3117
 * GrSetScreenSaverTimeout:
3118
 * @timeout: the number of seconds of inactivity before screen saver activates
3119
 *
3120
 * Sets the number of seconds of inactivity before a screen saver activate
3121
 * event is sent to the root window ID. A value of 0 activates the
3122
 * screen saver immediately, and a value of -1 disables the screen saver
3123
 * function.
3124
 */
3125
void
3126
GrSetScreenSaverTimeout(GR_TIMEOUT timeout)
3127
{
3128
        nxSetScreenSaverTimeoutReq *req;
3129
 
3130
        req = AllocReq(SetScreenSaverTimeout);
3131
        req->timeout = timeout;
3132
}
3133
 
3134
/**
3135
 * GrSetSelectionOwner:
3136
 * @wid: the ID of the window to set the selection owner to
3137
 * @typelist: list of mime types selection data can be supplied as
3138
 *
3139
 * Sets the current selection (otherwise known as the clipboard) ownership
3140
 * to the specified window. Specifying an owner of 0 disowns the selection.
3141
 * The typelist argument is a list of mime types (seperated by space
3142
 * characters) which the window is able to supply the data as. At least one
3143
 * type must be specified unless you are disowning the selection (typically
3144
 * text/plain for plain ASCII text or text/uri-list for a filename).
3145
 *
3146
 * The window which owns the current selection must be prepared to handle
3147
 * SELECTION_LOST events (received when another window takes ownership of the
3148
 * selection) and CLIENT_DATA_REQ events (received when a client wishes to
3149
 * retreive the selection data).
3150
 */
3151
void
3152
GrSetSelectionOwner(GR_WINDOW_ID wid, GR_CHAR *typelist)
3153
{
3154
        nxSetSelectionOwnerReq *req;
3155
        char *p;
3156
        int len;
3157
 
3158
        if(wid) {
3159
                len = strlen(typelist) + 1;
3160
                req = AllocReqExtra(SetSelectionOwner, len);
3161
                p = GetReqData(req);
3162
                memcpy(p, typelist, len);
3163
        } else {
3164
                req = AllocReq(SetSelectionOwner);
3165
        }
3166
 
3167
        req->wid = wid;
3168
}
3169
 
3170
/**
3171
 * GrGetSelectionOwner:
3172
 * @typelist: pointer used to return the list of available mime types
3173
 * @Returns: the ID of the window which currently owns the selection, or 0
3174
 *
3175
 * Finds the window which currently owns the selection and returns its ID,
3176
 * or 0 if no window currently owns the selection. A pointer to the list of
3177
 * mime types the selection owner is capable of supplying is placed in the
3178
 * pointer specified by the typelist argument. The typelist is null terminated,
3179
 * and the fields are seperated by space characters. It is the callers
3180
 * responsibility to free the typelist string, as it is allocated dynamically.
3181
 * If the allocation fails, it will be set to a NULL pointer, so remember to
3182
 * check the value of it before using it.
3183
 */
3184
GR_WINDOW_ID
3185
GrGetSelectionOwner(GR_CHAR **typelist)
3186
{
3187
        nxGetSelectionOwnerReq *req;
3188
        UINT16 textlen;
3189
        GR_CHAR c;
3190
        GR_WINDOW_ID wid;
3191
 
3192
        req = AllocReq(GetSelectionOwner);
3193
        GrTypedReadBlock(&wid, sizeof(wid), GrNumGetSelectionOwner);
3194
        if(wid) {
3195
                GrReadBlock(&textlen, sizeof(textlen));
3196
                if(!(*typelist = malloc(textlen))) {
3197
                        /* Oh dear, we're out of memory but still have to
3198
                        purge the requested data (and throw it away) */
3199
                        while(textlen--) GrReadBlock(&c, 1);
3200
                } else {
3201
                        GrReadBlock(*typelist, textlen);
3202
                }
3203
        }
3204
 
3205
        return wid;
3206
}
3207
 
3208
/**
3209
 * GrRequestClientData:
3210
 * @wid: the ID of the window requesting the data
3211
 * @rid: the ID of the window to request the data from
3212
 * @serial: the serial number of the request
3213
 * @mimetype: the number of the desired mime type to request
3214
 *
3215
 * Sends a CLIENT_DATA_REQ event to the specified window. Used for requesting
3216
 * both selection and "drag and drop" data. The mimetype argument specifies
3217
 * the format of the data you would like to receive, as an index into the list
3218
 * returned by GrGetSelectionOwner (the first type in the list is index 0).
3219
 * The server makes no guarantees as to when, or even if, the client will
3220
 * reply to the request. If the client does reply, the reply will take the
3221
 * form of one or more CLIENT_DATA events. The request serial number is
3222
 * typically a unique ID which the client can assign to a request in order for
3223
 * it to be able to keep track of transfers (CLIENT_DATA events contain the
3224
 * same number in the sid field). Remember to free the data field of the
3225
 * CLIENT_DATA events as they are dynamically allocated. Also note that if
3226
 * the allocation fails the data field will be set to NULL, so you should
3227
 * check the value before using it.
3228
 */
3229
void
3230
GrRequestClientData(GR_WINDOW_ID wid, GR_WINDOW_ID rid, GR_SERIALNO serial,
3231
                                                        GR_MIMETYPE mimetype)
3232
{
3233
        nxRequestClientDataReq *req;
3234
 
3235
        req = AllocReq(RequestClientData);
3236
        req->wid = wid;
3237
        req->rid = rid;
3238
        req->serial = serial;
3239
        req->mimetype = mimetype;
3240
}
3241
 
3242
/**
3243
 * GrSendClientData:
3244
 * @wid: the ID of the window sending the data
3245
 * @did: the ID of the destination window
3246
 * @sid: the serial number of the request
3247
 * @len: the number of bytes of data to transfer
3248
 * @thislen: the number of bytes in this packet
3249
 * @data: pointer to the data to transfer
3250
 *
3251
 * Used as the response to a CLIENT_DATA_REQ event. Sends the specified data
3252
 * of the specified length to the specified window using the specified source
3253
 * window ID and transfer serial number. Any fragmentation of the data into
3254
 * multiple CLIENT_DATA events which is required is handled automatically.
3255
 * The serial number should always be set to the value supplied by the
3256
 * CLIENT_DATA_REQ event. The thislen parameter is used internally to split
3257
 * the data up into packets. It should be set to the same value as the len
3258
 * parameter.
3259
 *
3260
 */
3261
void
3262
GrSendClientData(GR_WINDOW_ID wid, GR_WINDOW_ID did, GR_SERIALNO serial,
3263
                        GR_LENGTH len, GR_LENGTH thislen, void *data)
3264
{
3265
        nxSendClientDataReq *req;
3266
        char *p;
3267
        GR_LENGTH l, pos = 0;
3268
 
3269
        while(pos < len) {
3270
                l = MAXREQUESTSZ - sizeof(nxSendClientDataReq);
3271
                if(l > (len - pos)) l = len - pos;
3272
                req = AllocReqExtra(SendClientData, l);
3273
                req->wid = wid;
3274
                req->did = did;
3275
                req->serial = serial;
3276
                req->len = len;
3277
                p = GetReqData(req);
3278
                memcpy(p, data + pos, l);
3279
                pos += l;
3280
        }
3281
}
3282
 
3283
/**
3284
 * GrBell:
3285
 *
3286
 * Asks the server to ring the console bell on behalf of the client (intended
3287
 * for terminal apps to be able to ring the bell on the server even if they
3288
 * are running remotely).
3289
 */
3290
void
3291
GrBell(void)
3292
{
3293
        AllocReq(Bell);
3294
}
3295
 
3296
/**
3297
 * GrSetBackgroundPixmap:
3298
 * @wid: ID of the window to set the background of
3299
 * @pixmap: ID of the pixmap to use as the background
3300
 * @flags: flags specifying how to draw the pixmap onto the window
3301
 *
3302
 * Sets the background of the specified window to the specified pixmap.
3303
 * The flags which specify how to draw the pixmap (in the top left of the
3304
 * window, in the centre of the window, tiled, etc.) are those which start with
3305
 * GR_BACKGROUND_ in nano-X.h. If the pixmap value is 0, the server will
3306
 * disable the background pixmap and return to using a solid colour fill.
3307
 */
3308
void
3309
GrSetBackgroundPixmap(GR_WINDOW_ID wid, GR_WINDOW_ID pixmap, int flags)
3310
{
3311
        nxSetBackgroundPixmapReq *req;
3312
 
3313
        req = AllocReq(SetBackgroundPixmap);
3314
        req->wid = wid;
3315
        req->pixmap = pixmap;
3316
        req->flags = flags;
3317
}
3318
 
3319
/**
3320
 * GrDestroyCursor:
3321
 * @id: ID of the cursor to destory
3322
 *
3323
 * Destroys the specified server-based cursor and
3324
 * reclaims the memory used by it.
3325
 */
3326
void
3327
GrDestroyCursor(GR_CURSOR_ID cid)
3328
{
3329
        nxDestroyCursorReq *req;
3330
 
3331
        req = AllocReq(DestroyCursor);
3332
        req->cursorid = cid;
3333
}
3334
 
3335
/**
3336
 * GrQueryTree:
3337
 * @wid: window ID for query
3338
 * @parentid: returned parent ID
3339
 * @children: returned children ID list
3340
 * @nchildren: returned children count
3341
 *
3342
 * Return window parent and list of children.
3343
 * Caller must free() children list after use.
3344
 */
3345
void
3346
GrQueryTree(GR_WINDOW_ID wid, GR_WINDOW_ID *parentid, GR_WINDOW_ID **children,
3347
        GR_COUNT *nchildren)
3348
{
3349
        nxQueryTreeReq *req;
3350
        GR_COUNT        count;
3351
        GR_WINDOW_ID    dummy;
3352
 
3353
        req = AllocReq(QueryTree);
3354
        req->windowid = wid;
3355
 
3356
        GrTypedReadBlock(parentid, sizeof(*parentid), GrNumQueryTree);
3357
        GrReadBlock(nchildren, sizeof(*nchildren));
3358
        if (!*nchildren) {
3359
                *children = NULL;
3360
                return;
3361
        }
3362
        count = *nchildren;
3363
        if(!(*children = malloc(count * sizeof(GR_WINDOW_ID)))) {
3364
                /* We're out of memory but still have to purge the
3365
                   requested data (and throw it away) */
3366
                while(count--)
3367
                        GrReadBlock(&dummy, sizeof(GR_WINDOW_ID));
3368
        } else {
3369
                GrReadBlock(*children, count * sizeof(GR_WINDOW_ID));
3370
        }
3371
}
3372
 
3373
#if YOU_WANT_TO_IMPLEMENT_DRAG_AND_DROP
3374
/**
3375
 * GrRegisterDragAndDropWindow:
3376
 * @wid: the ID of the window to use as the drag and drop source window
3377
 * @iid: the ID of the pixmap to use as the drag and drop icon
3378
 * @typelist: list of mime types the drag and drop data can be supplied as
3379
 *
3380
 * Enables the specified window to be used as a drag and drop source. The
3381
 * specified pixmap will be used as the icon shown whilst dragging, and the
3382
 * null terminated, newline seperated list of mime types which the data can
3383
 * be supplied as is specified by the typelist argument. At least one type
3384
 * (typically text/plain for plain ASCII or text/uri-list for a filename or
3385
 * list of filenames) must be specified. When the icon is dropped,
3386
 * the window which it is dropped on will receive a DROP event (providing it
3387
 * has selected for DROP events), and if the client wishes to accept the data
3388
 * and is able to handle one of the mime types in the type list, it should use
3389
 * GrRequestClientData() to retrieve the data from the drag and drop source
3390
 * window. Remember to free the typelist field of the DROP event as it is
3391
 * dynamically allocated. It is possible for a client to select for DROP events
3392
 * on the Root window if it is desired to allow dropping icons on the desktop.
3393
 */
3394
void
3395
GrRegisterDragAndDropWindow(GR_WINDOW_ID wid, GR_WINDOW_ID iid,
3396
                                GR_CHAR *typelist)
3397
{
3398
}
3399
#endif
3400
 
3401
 
3402
GR_TIMER_ID
3403
GrCreateTimer (GR_WINDOW_ID wid, GR_TIMEOUT period)
3404
{
3405
    nxCreateTimerReq  *req;
3406
    GR_TIMER_ID  timerid;
3407
 
3408
    req = AllocReq(CreateTimer);
3409
 
3410
    req->wid = wid;
3411
    req->period = period;
3412
 
3413
    if (GrTypedReadBlock(&timerid, sizeof (timerid), GrNumCreateTimer) == -1)
3414
        return 0;
3415
    return timerid;
3416
}
3417
 
3418
void
3419
GrDestroyTimer (GR_TIMER_ID tid)
3420
{
3421
    nxDestroyTimerReq *req;
3422
 
3423
    req = AllocReq(DestroyTimer);
3424
    req->timerid = tid;
3425
}
3426
 
3427
void
3428
GrSetPortraitMode(int portraitmode)
3429
{
3430
    nxSetPortraitModeReq *req;
3431
 
3432
    req = AllocReq(SetPortraitMode);
3433
    req->portraitmode = portraitmode;
3434
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.