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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [gfx/] [mw/] [v2_0/] [src/] [nanox/] [client.c] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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