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

Subversion Repositories or1k

[/] [or1k/] [tags/] [MW_0_8_9PRE7/] [mw/] [src/] [nanox/] [client.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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