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

Subversion Repositories openrisc_me

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
/*
2
 * Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
3
 * Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
4
 * Copyright (c) 1991 David I. Bell
5
 * Permission is granted to use, distribute, or modify this source,
6
 * provided that this copyright notice remains intact.
7
 */
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <string.h>
11
#define MWINCLUDECOLORS
12
#include "serv.h"
13
 
14
static int      nextid = GR_ROOT_WINDOW_ID + 1;
15
 
16
static void CheckNextEvent(GR_EVENT *ep, GR_BOOL doSelect);
17
 
18
/*
19
 * Return information about the screen for clients to use.
20
 */
21
void
22
GrGetScreenInfo(GR_SCREEN_INFO *sip)
23
{
24
        GdGetScreenInfo(rootwp->psd, sip);
25
 
26
        /* virtual/workspace screen sizing*/
27
#if 0
28
        /* force small screen for emulation purposes*/
29
        sip->vs_width = 240;    /* PDA*/
30
        sip->vs_height = 320;
31
        sip->ws_width = 240;
32
        sip->ws_height = 298;
33
#else
34
        /* set workspace equal to screen area minus 22 pixel taskbar*/
35
        sip->vs_width = sip->cols;
36
        sip->vs_height = sip->rows;
37
        sip->ws_width = sip->cols;
38
        sip->ws_height = sip->rows - 22;
39
#endif
40
}
41
 
42
/*
43
 * Return the size of a text string for the font in a graphics context.
44
 * This is the width of the string, the height of the string,
45
 * and the height above the bottom of the font of the baseline for the font.
46
 */
47
void
48
GrGetGCTextSize(GR_GC_ID gc, void *str, int count, int flags,
49
        GR_SIZE *retwidth, GR_SIZE *retheight, GR_SIZE *retbase)
50
{
51
        GR_GC           *gcp;
52
        GR_FONT         *fontp;
53
        PMWFONT         pf;
54
 
55
        gcp = GsFindGC(gc);
56
        if (gcp == NULL)
57
                fontp = NULL;
58
        else
59
                fontp = GsFindFont(gcp->fontid);
60
        pf = fontp? fontp->pfont: stdfont;
61
        GdGetTextSize(pf, str, count, retwidth, retheight, retbase, flags);
62
}
63
 
64
#if NONETWORK
65
/*
66
 * Return the next waiting event for a client, or wait for one if there
67
 * is none yet.  The event is copied into the specified structure, and
68
 * then is moved from the event queue to the free event queue.  If there
69
 * is an error event waiting, it is delivered before any other events.
70
 */
71
void
72
GrGetNextEvent(GR_EVENT *ep)
73
{
74
        GrGetNextEventTimeout(ep, 0L);
75
}
76
 
77
/*
78
 * Return the next event from the event queue, or
79
 * wait for a new one if one is not ready.  If timeout
80
 * is nonzero, return timeout event if time elapsed.
81
 */
82
void
83
GrGetNextEventTimeout(GR_EVENT *ep, GR_TIMEOUT timeout)
84
{
85
        /* If no event ready, wait for one*/
86
        /* Note: won't work for multiple clients*/
87
        /* This is OK, since only static linked apps call this function*/
88
        while(curclient->eventhead == NULL)
89
                GsSelect(timeout);
90
        CheckNextEvent(ep, GR_FALSE);
91
}
92
 
93
/*
94
 * Wait until an event is available for a client, and then peek at it.
95
 */
96
void
97
GrPeekWaitEvent(GR_EVENT *ep)
98
{
99
        while(curclient->eventhead == NULL)
100
                GsSelect(0L);
101
        GrPeekEvent(ep);
102
}
103
#endif
104
 
105
/*
106
 * Return the next event from the event queue if one is ready.
107
 * If one is not ready, then the type GR_EVENT_TYPE_NONE is returned.
108
 * If it is an error event, then a user-specified routine is called
109
 * if it was defined, otherwise we clean up and exit.
110
 */
111
void
112
GrCheckNextEvent(GR_EVENT *ep)
113
{
114
        CheckNextEvent(ep, GR_TRUE);
115
}
116
 
117
static void
118
CheckNextEvent(GR_EVENT *ep, GR_BOOL doSelect)
119
{
120
        GR_EVENT_LIST * elp;
121
 
122
#if NONETWORK
123
        /* Since we're bound to server, select() is only called
124
         * thru here
125
         */
126
        if(doSelect)
127
                GsSelect(0L);
128
#endif
129
        /* Copy first event if any*/
130
        if(!GrPeekEvent(ep))
131
                return;
132
 
133
        /* Get first event again*/
134
        elp = curclient->eventhead;
135
 
136
        /* Remove first event from queue*/
137
        curclient->eventhead = elp->next;
138
        if (curclient->eventtail == elp)
139
                curclient->eventtail = NULL;
140
 
141
        elp->next = eventfree;
142
        eventfree = elp;
143
}
144
 
145
/*
146
 * Peek at the event queue for the current client to see if there are any
147
 * outstanding events.  Returns the event at the head of the queue, or
148
 * else a null event type.  The event is still left in the queue, however.
149
 */
150
int
151
GrPeekEvent(GR_EVENT *ep)
152
{
153
        GR_EVENT_LIST * elp;
154
 
155
        elp = curclient->eventhead;
156
        if(elp == NULL) {
157
                ep->type = GR_EVENT_TYPE_NONE;
158
                return 0;
159
        }
160
 
161
        /* copy event out*/
162
        *ep = elp->event;
163
        return 1;
164
}
165
 
166
/*
167
 * Return information about a window id.
168
 */
169
void
170
GrGetWindowInfo(GR_WINDOW_ID wid, GR_WINDOW_INFO *infoptr)
171
{
172
        GR_WINDOW       *wp;            /* window structure */
173
        GR_PIXMAP       *pp;
174
        GR_EVENT_CLIENT *evp;           /* event-client structure */
175
 
176
        /* first check window list*/
177
        wp = GsFindWindow(wid);
178
        if (wp) {
179
                infoptr->wid = wid;
180
                /* report parent-relative x,y coordinates*/
181
                infoptr->x = wp->x - (wp->parent ? wp->parent->x : 0);
182
                infoptr->y = wp->y - (wp->parent ? wp->parent->y : 0);
183
                infoptr->width = wp->width;
184
                infoptr->height = wp->height;
185
                infoptr->parent = wp->parent? wp->parent->id: 0;
186
                infoptr->child = wp->children? wp->children->id: 0;
187
                infoptr->sibling = wp->siblings? wp->siblings->id: 0;
188
                infoptr->mapped = wp->mapped;
189
                infoptr->unmapcount = wp->unmapcount;
190
                infoptr->inputonly = !wp->output;
191
                infoptr->bordersize = wp->bordersize;
192
                infoptr->bordercolor = wp->bordercolor;
193
                infoptr->background = wp->background;
194
                infoptr->props = wp->props;
195
                infoptr->cursor = wp->cursorid;
196
                infoptr->processid = wp->owner? wp->owner->processid: 0;
197
                infoptr->eventmask = 0;
198
 
199
                for (evp = wp->eventclients; evp; evp = evp->next) {
200
                        if (evp->client == curclient)
201
                                infoptr->eventmask = evp->eventmask;
202
                }
203
                return;
204
        }
205
 
206
        /* then pixmap list*/
207
        pp = GsFindPixmap(wid);
208
        if (pp) {
209
                infoptr->wid = wid;
210
                infoptr->x = pp->x;
211
                infoptr->y = pp->y;
212
                infoptr->width = pp->width;
213
                infoptr->height = pp->height;
214
                infoptr->parent = 0;
215
                infoptr->child = 0;
216
                infoptr->sibling = 0;
217
                infoptr->mapped = GR_FALSE;
218
                infoptr->unmapcount = 0;
219
                infoptr->inputonly = GR_FALSE;
220
                infoptr->bordersize = 0;
221
                infoptr->bordercolor = 0;
222
                infoptr->background = 0;
223
                infoptr->eventmask = 0;
224
                infoptr->cursor = 0;
225
                infoptr->processid = pp->owner? pp->owner->processid: 0;
226
                return;
227
        }
228
 
229
        /* No error if window id is invalid.*/
230
        memset(infoptr, 0, sizeof(GR_WINDOW_INFO));
231
}
232
 
233
/*
234
 * Destroy an existing window and all of its children.
235
 * Also used to destroy a pixmap.
236
 */
237
void
238
GrDestroyWindow(GR_WINDOW_ID wid)
239
{
240
        GR_WINDOW       *wp;            /* window structure */
241
        GR_PIXMAP       *pp;
242
        GR_PIXMAP       *prevpp;
243
        PSD             psd;
244
 
245
        wp = GsFindWindow(wid);
246
        if (wp) {
247
                GsWpDestroyWindow(wp);
248
        } else {
249
                pp = GsFindPixmap(wid);
250
                if (pp) {
251
                        psd = pp->psd;
252
                        /* deallocate pixmap memory*/
253
                        if (psd->flags & PSF_ADDRMALLOC)
254
                                free(psd->addr);
255
 
256
                        /* deallocate mem gc*/
257
                        psd->FreeMemGC(psd);
258
 
259
                        /*
260
                         * Remove this pixmap from the complete list of pixmaps.
261
                         */
262
                        prevpp = listpp;
263
                        if (prevpp == pp)
264
                                listpp = pp->next;
265
                        else {
266
                                while (prevpp->next != pp)
267
                                        prevpp = prevpp->next;
268
                                prevpp->next = pp->next;
269
                        }
270
 
271
                        /*
272
                         * Forget various information if they related to this
273
                         * pixmap.  Then finally free the structure.
274
                         */
275
                        if (pp == cachepp) {
276
                                cachepixmapid = 0;
277
                                cachepp = NULL;
278
                        }
279
                        free(pp);
280
                }
281
        }
282
}
283
 
284
 
285
/*
286
 * Raise a window to the highest level among its siblings.
287
 */
288
void
289
GrRaiseWindow(GR_WINDOW_ID wid)
290
{
291
        GR_WINDOW       *wp;            /* window structure */
292
        GR_WINDOW       *prevwp;        /* previous window pointer */
293
        GR_BOOL         overlap;        /* TRUE if there was overlap */
294
 
295
        wp = GsFindWindow(wid);
296
        if ((wp == NULL) || (wp == rootwp))
297
                return;
298
 
299
        /*
300
         * If this is already the highest window then we are done.
301
         */
302
        prevwp = wp->parent->children;
303
        if (prevwp == wp)
304
                return;
305
 
306
        /*
307
         * Find the sibling just before this window so we can unlink it.
308
         * Also, determine if any sibling ahead of us overlaps the window.
309
         * Remember that for exposure events.
310
         */
311
        overlap = GR_FALSE;
312
        while (prevwp->siblings != wp) {
313
                overlap |= GsCheckOverlap(prevwp, wp);
314
                prevwp = prevwp->siblings;
315
        }
316
        overlap |= GsCheckOverlap(prevwp, wp);
317
 
318
        /*
319
         * Now unlink the window and relink it in at the front of the
320
         * sibling chain.
321
         */
322
        prevwp->siblings = wp->siblings;
323
        wp->siblings = wp->parent->children;
324
        wp->parent->children = wp;
325
 
326
        /*
327
         * Finally redraw the window if necessary.
328
         */
329
        if (overlap) {
330
                GsDrawBorder(wp);
331
                GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height, NULL);
332
        }
333
}
334
 
335
/*
336
 * Lower a window to the lowest level among its siblings.
337
 */
338
void GrLowerWindow(GR_WINDOW_ID wid)
339
{
340
        GR_WINDOW       *wp;            /* window structure */
341
        GR_WINDOW       *prevwp;        /* previous window pointer */
342
        GR_WINDOW       *sibwp;         /* sibling window */
343
        GR_WINDOW       *expwp;         /* siblings being exposed */
344
 
345
        wp = GsFindWindow(wid);
346
        if ((wp == NULL) || (wp == rootwp))
347
                return;
348
        if (wp->siblings == NULL)
349
                return;
350
 
351
        /*
352
         * Find the sibling just before this window so we can unlink us.
353
         */
354
        prevwp = wp->parent->children;
355
        if (prevwp != wp) {
356
                while (prevwp->siblings != wp)
357
                        prevwp = prevwp->siblings;
358
        }
359
 
360
        /*
361
         * Remember the first sibling that is after us, so we can
362
         * generate exposure events for the remaining siblings.  Then
363
         * walk down the sibling chain looking for the last sibling.
364
         */
365
        expwp = wp->siblings;
366
        sibwp = wp;
367
        while (sibwp->siblings)
368
                sibwp = sibwp->siblings;
369
 
370
        /*
371
         * Now unlink the window and relink it in at the end of the
372
         * sibling chain.
373
         */
374
        if (prevwp == wp)
375
                wp->parent->children = wp->siblings;
376
        else
377
                prevwp->siblings = wp->siblings;
378
        sibwp->siblings = wp;
379
 
380
        wp->siblings = NULL;
381
 
382
        /*
383
         * Finally redraw the sibling windows which this window covered
384
         * if they overlapped our window.
385
         */
386
        while (expwp && (expwp != wp)) {
387
                if (GsCheckOverlap(wp, expwp)) {
388
                        GsExposeArea(expwp, wp->x - wp->bordersize,
389
                                wp->y - wp->bordersize,
390
                                wp->width + wp->bordersize * 2,
391
                                wp->height + wp->bordersize * 2, NULL);
392
                }
393
                expwp = expwp->siblings;
394
        }
395
}
396
 
397
/* Offset a window position and all children by offx,offy*/
398
static void
399
OffsetWindow(GR_WINDOW *wp, GR_COORD offx, GR_COORD offy)
400
{
401
        GR_WINDOW       *cp;
402
 
403
        wp->x += offx;
404
        wp->y += offy;
405
        for(cp=wp->children; cp; cp=cp->siblings)
406
                OffsetWindow(cp, offx, offy);
407
}
408
 
409
/* deliver an update move event to window and all children*/
410
static void
411
DeliverUpdateMoveEventAndChildren(GR_WINDOW *wp)
412
{
413
        GR_WINDOW *     childwp;
414
 
415
        GsDeliverUpdateEvent(wp, GR_UPDATE_MOVE, wp->x, wp->y,
416
                wp->width, wp->height);
417
 
418
        for (childwp = wp->children; childwp; childwp = childwp->siblings)
419
                DeliverUpdateMoveEventAndChildren(childwp);
420
}
421
 
422
/*
423
 * Move the window to the specified position relative to its parent.
424
 */
425
void
426
GrMoveWindow(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y)
427
{
428
        GR_WINDOW       *wp;            /* window structure */
429
        GR_COORD        offx, offy;
430
 
431
        wp = GsFindWindow(wid);
432
        if (wp == NULL)
433
                return;
434
        if (wp == rootwp) {
435
                GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
436
                return;
437
        }
438
 
439
        x += wp->parent->x;
440
        y += wp->parent->y;
441
        offx = x - wp->x;
442
        offy = y - wp->y;
443
 
444
        if (wp->x == x && wp->y == y)
445
                return;
446
 
447
        /*** move algorithms not requiring unmap/map ***/
448
#if 1
449
        /* perform screen blit if topmost and mapped - no flicker!*/
450
        if (wp->mapped && wp == wp->parent->children
451
                && wp->parent->id == GR_ROOT_WINDOW_ID
452
 
453
                /* temp don't blit in portrait mode, still buggy*/
454
                && !(wp->psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT))
455
           ) {
456
                int             oldx = wp->x;
457
                int             oldy = wp->y;
458
                GR_WINDOW_ID    pixid = GrNewPixmap(wp->width, wp->height,NULL);
459
                GR_GC_ID        gc = GrNewGC();
460
                GR_WINDOW *     stopwp = wp;
461
                int             X, Y, W, H;
462
 
463
                /* must hide cursor first or GdFixCursor() will show it*/
464
                GdHideCursor(rootwp->psd);
465
 
466
                /* turn off clipping of root's children*/
467
                GrSetGCMode(gc, GR_MODE_COPY|GR_MODE_EXCLUDECHILDREN);
468
 
469
                /* copy topmost window contents offscreen*/
470
                GrCopyArea(pixid, gc, 0, 0, wp->width, wp->height,
471
                        GR_ROOT_WINDOW_ID, oldx, oldy, MWROP_COPY);
472
 
473
                /* calc new window offsets*/
474
                OffsetWindow(wp, offx, offy);
475
 
476
                /* force recalc of clip region*/
477
                clipwp = NULL;
478
 
479
                /* copy window bits to new location*/
480
                GrCopyArea(GR_ROOT_WINDOW_ID, gc, wp->x, wp->y, wp->width,
481
                        wp->height, pixid, 0, 0, MWROP_COPY);
482
 
483
                /*
484
                 * If any portion of the window was offscreen
485
                 * and is coming onscreen, must send expose events
486
                 * to this window as well.
487
                 */
488
                if ((oldx < 0 && wp->x > oldx) ||
489
                    (oldy < 0 && wp->y > oldy) ||
490
                    (oldx+wp->width > rootwp->width && wp->x < oldx) ||
491
                    (oldy+wp->height > rootwp->height && wp->y < oldy))
492
                        stopwp = NULL;
493
 
494
                /*
495
                 * Calculate bounded exposed area and
496
                 * redraw anything lower than stopwp window.
497
                 */
498
                X = MWMIN(oldx, wp->x);
499
                Y = MWMIN(oldy, wp->y);
500
                W = MWMAX(oldx, wp->x) + wp->width - X;
501
                H = MWMAX(oldy, wp->y) + wp->height - Y;
502
                GsExposeArea(rootwp, X, Y, W, H, stopwp);
503
 
504
                GdShowCursor(rootwp->psd);
505
                GrDestroyGC(gc);
506
                GrDestroyWindow(pixid);
507
                DeliverUpdateMoveEventAndChildren(wp);
508
                return;
509
        }
510
#endif
511
#if 0
512
        /* perform quick move and expose if topmost and mapped - no blit*/
513
        if (wp->mapped && wp == wp->parent->children) {
514
                int     oldx = wp->x;
515
                int     oldy = wp->y;
516
                int     X, Y, W, H;
517
 
518
                OffsetWindow(wp, offx, offy);
519
 
520
                /* force recalc of clip region*/
521
                clipwp = NULL;
522
 
523
                X = MWMIN(oldx, wp->x);
524
                Y = MWMIN(oldy, wp->y);
525
                W = MWMAX(oldx, wp->x) + wp->width - X;
526
                H = MWMAX(oldy, wp->y) + wp->height - Y;
527
                GsExposeArea(rootwp, X, Y, W, H, NULL);
528
                DeliverUpdateMoveEventAndChildren(wp);
529
                return;
530
        }
531
#endif
532
        /*
533
         * This method will redraw the window entirely,
534
         * resulting in considerable flicker.
535
         */
536
        GsWpUnmapWindow(wp, GR_TRUE);
537
        OffsetWindow(wp, offx, offy);
538
        GsWpMapWindow(wp, GR_FALSE);
539
        DeliverUpdateMoveEventAndChildren(wp);
540
}
541
 
542
/*
543
 * Resize the window to be the specified size.
544
 */
545
void
546
GrResizeWindow(GR_WINDOW_ID wid, GR_SIZE width, GR_SIZE height)
547
{
548
        GR_WINDOW       *wp;            /* window structure */
549
 
550
        wp = GsFindWindow(wid);
551
        if (wp == NULL)
552
                return;
553
        if (wp == rootwp) {
554
                GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
555
                return;
556
        }
557
        if ((width <= 0) || (height <= 0)) {
558
                GsError(GR_ERROR_BAD_WINDOW_SIZE, wid);
559
                return;
560
        }
561
 
562
        if ((wp->width == width) && (wp->height == height))
563
                return;
564
 
565
        if (wp->unmapcount || !wp->output) {
566
                wp->width = width;
567
                wp->height = height;
568
                return;
569
        }
570
 
571
        /*
572
         * This should be optimized to not require redrawing of the window
573
         * when possible.
574
         */
575
        GsWpUnmapWindow(wp, GR_TRUE);
576
        wp->width = width;
577
        wp->height = height;
578
        GsWpMapWindow(wp, GR_FALSE);
579
        GsDeliverUpdateEvent(wp, GR_UPDATE_SIZE, wp->x, wp->y, width, height);
580
}
581
 
582
/* set unmapcount for a window and all its children*/
583
static void
584
SetUnmapCountTree(GR_WINDOW *wp, int value, GR_BOOL increment)
585
{
586
        GR_WINDOW *     childwp;
587
 
588
        if (increment)
589
                wp->unmapcount += value;
590
        else wp->unmapcount = value;
591
 
592
        for (childwp = wp->children; childwp; childwp = childwp->siblings)
593
                SetUnmapCountTree(childwp, value, increment);
594
}
595
 
596
/*
597
 * Reparent window to new parent, position at passed x, y
598
 *
599
 * NOTE: currently, the new parent must be mapped before
600
 * reparenting, or the children of the newly parented window
601
 * will have bad unmapcount values due to the GrMapWindow
602
 * being called on the parent afterwards, and chaining down
603
 * through the children.
604
 */
605
void
606
GrReparentWindow(GR_WINDOW_ID wid, GR_WINDOW_ID pwid, GR_COORD x, GR_COORD y)
607
{
608
        GR_WINDOW       *wp;            /* window structure */
609
        GR_WINDOW       *pwp;           /* parent window structure */
610
        GR_WINDOW       **mysibptr;     /* handle to my sibling ptr */
611
        GR_COORD        offx, offy;
612
        GR_BOOL         wasmapped;
613
 
614
        wp = GsFindWindow(wid);
615
        pwp = GsFindWindow(pwid);
616
        if (wp == NULL || pwp == NULL || wp == pwp)
617
                return;
618
        if (wp == rootwp) {
619
                GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid);
620
                return;
621
        }
622
 
623
        x += pwp->x;
624
        y += pwp->y;
625
        offx = x - wp->x;
626
        offy = y - wp->y;
627
 
628
/*printf("pid %d wid %d (oldpid %d) %d,%d\n", pwid, wid, wp->parent->id, pwp->unmapcount, wp->unmapcount);*/
629
        /*
630
         * Always unmap window, can't hurt if not mapped.
631
         */
632
        wasmapped = (wp->unmapcount == 0);
633
        GsWpUnmapWindow(wp, GR_TRUE);
634
 
635
        for(mysibptr = &(wp->parent->children); *mysibptr != wp;
636
                mysibptr = &((*mysibptr)->siblings))
637
                        continue;
638
        *mysibptr = wp->siblings;
639
        wp->parent = pwp;
640
        wp->siblings = pwp->children;
641
        pwp->children = wp;
642
        OffsetWindow(wp, offx, offy);
643
#if 1   /* temp fix to bad mapcount reparenting code below*/
644
        GsWpMapWindow(wp, GR_FALSE);
645
#else
646
        /*
647
         * If parent mapped and window was mapped, set unmapcount
648
         * to 0 and remap window.
649
         */
650
        if (!pwp->unmapcount && wasmapped) {
651
                SetUnmapCountTree(wp, 0, GR_FALSE);
652
                GsWpMapWindow(wp, GR_FALSE);
653
        } else {
654
                if (wasmapped)
655
                        SetUnmapCountTree(wp, pwp->unmapcount, GR_FALSE);
656
                else SetUnmapCountTree(wp, pwp->unmapcount+1, GR_FALSE);
657
        }
658
#endif
659
}
660
 
661
static int nextgcid = 1000;
662
/*
663
 * Allocate a new GC with default parameters.
664
 * The GC is owned by the current client.
665
 */
666
GR_GC_ID
667
GrNewGC(void)
668
{
669
        GR_GC   *gcp;
670
 
671
        gcp = (GR_GC *) malloc(sizeof(GR_GC));
672
        if (gcp == NULL) {
673
                GsError(GR_ERROR_MALLOC_FAILED, 0);
674
                return 0;
675
        }
676
 
677
        gcp->id = nextgcid++;
678
        gcp->mode = GR_MODE_COPY;
679
        gcp->regionid = 0;       /* no region*/
680
        gcp->xoff = 0;           /* no offset*/
681
        gcp->yoff = 0;
682
        gcp->fontid = 0; /* 0 is default font*/
683
        gcp->foreground = WHITE;
684
        gcp->background = BLACK;
685
        gcp->usebackground = GR_TRUE;
686
        gcp->changed = GR_TRUE;
687
        gcp->owner = curclient;
688
        gcp->next = listgcp;
689
 
690
        listgcp = gcp;
691
 
692
        return gcp->id;
693
}
694
 
695
/*
696
 * Destroy an existing graphics context.
697
 */
698
void
699
GrDestroyGC(GR_GC_ID gc)
700
{
701
        GR_GC           *gcp;           /* graphics context */
702
        GR_GC           *prevgcp;       /* previous graphics context */
703
 
704
        gcp = GsFindGC(gc);
705
        if (gcp == NULL)
706
                return;
707
 
708
        if (gc == cachegcid) {
709
                cachegcid = 0;
710
                cachegcp = NULL;
711
        }
712
        if (gcp == curgcp)
713
                curgcp = NULL;
714
 
715
        if (listgcp == gcp)
716
                listgcp = gcp->next;
717
        else {
718
                prevgcp = listgcp;
719
                while (prevgcp->next != gcp)
720
                        prevgcp = prevgcp->next;
721
 
722
                prevgcp->next = gcp->next;
723
        }
724
        free(gcp);
725
}
726
 
727
/*
728
 * Allocate a new GC which is a copy of another one.
729
 * The GC is owned by the current client.
730
 */
731
GR_GC_ID
732
GrCopyGC(GR_GC_ID gc)
733
{
734
        GR_GC           *oldgcp;        /* old graphics context */
735
        GR_GC           *gcp;           /* new graphics context */
736
 
737
        oldgcp = GsFindGC(gc);
738
        if (oldgcp == NULL)
739
                return 0;
740
 
741
        gcp = (GR_GC *) malloc(sizeof(GR_GC));
742
        if (gcp == NULL) {
743
                GsError(GR_ERROR_MALLOC_FAILED, 0);
744
                return 0;
745
        }
746
 
747
        /*
748
         * Copy all the old gcp values into the new one, except allocate
749
         * a new id for it and link it into the list of GCs.
750
         */
751
        *gcp = *oldgcp;
752
        gcp->id = nextgcid++;
753
        gcp->changed = GR_TRUE;
754
        gcp->owner = curclient;
755
        gcp->next = listgcp;
756
        listgcp = gcp;
757
 
758
        return gcp->id;
759
}
760
 
761
/*
762
 * Return information about the specified graphics context.
763
 */
764
void
765
GrGetGCInfo(GR_GC_ID gcid, GR_GC_INFO *gcip)
766
{
767
        GR_GC           *gcp;
768
 
769
        /*
770
         * Find the GC manually so that an error is not generated.
771
         */
772
        for (gcp = listgcp; gcp && (gcp->id != gcid); gcp = gcp->next)
773
                continue;
774
 
775
        if (gcp == NULL) {
776
                memset(gcip, 0, sizeof(GR_GC_INFO));
777
                return;
778
        }
779
 
780
        gcip->gcid = gcid;
781
        gcip->mode = gcp->mode;
782
        gcip->region = gcp->regionid;
783
        gcip->xoff = gcp->xoff;
784
        gcip->yoff = gcp->yoff;
785
        gcip->font = gcp->fontid;
786
        gcip->foreground = gcp->foreground;
787
        gcip->background = gcp->background;
788
        gcip->usebackground = gcp->usebackground;
789
}
790
 
791
static int nextregionid = 1000;
792
/*
793
 * Allocate a new REGION with default parameters.
794
 * The REGION is owned by the current client.
795
 */
796
GR_REGION_ID
797
GrNewRegion(void)
798
{
799
        GR_REGION *regionp;
800
 
801
        regionp = (GR_REGION *) malloc(sizeof(GR_REGION));
802
        if (regionp == NULL) {
803
                GsError(GR_ERROR_MALLOC_FAILED, 0);
804
                return 0;
805
        }
806
 
807
        regionp->rgn = GdAllocRegion();
808
        regionp->id = nextregionid++;
809
        regionp->owner = curclient;
810
        regionp->next = listregionp;
811
 
812
        listregionp = regionp;
813
        return regionp->id;
814
}
815
 
816
/*
817
 * Allocate a new region from a set of points interpreted as a polygon.
818
 * The REGION is owned by the current client.
819
 */
820
GR_REGION_ID
821
GrNewPolygonRegion(int mode, GR_COUNT count, GR_POINT *points)
822
{
823
#if POLYREGIONS
824
        GR_REGION *regionp;
825
 
826
        regionp = (GR_REGION *) malloc(sizeof(GR_REGION));
827
        if (regionp == NULL) {
828
                GsError(GR_ERROR_MALLOC_FAILED, 0);
829
                return 0;
830
        }
831
 
832
        regionp->rgn = GdAllocPolygonRegion(points, count, mode);
833
        regionp->id = nextregionid++;
834
        regionp->owner = curclient;
835
        regionp->next = listregionp;
836
 
837
        listregionp = regionp;
838
        return regionp->id;
839
#else
840
        return 0;
841
#endif
842
}
843
 
844
/*
845
 * Destroy an existing region.
846
 */
847
void
848
GrDestroyRegion(GR_REGION_ID region)
849
{
850
        GR_REGION       *regionp;       /* region */
851
        GR_REGION       *prevregionp;   /* previous region */
852
 
853
        regionp = GsFindRegion(region);
854
        if (regionp == NULL)
855
                return;
856
 
857
        if (listregionp == regionp)
858
                listregionp = regionp->next;
859
        else {
860
                prevregionp = listregionp;
861
                while (prevregionp->next != regionp)
862
                        prevregionp = prevregionp->next;
863
 
864
                prevregionp->next = regionp->next;
865
        }
866
        GdDestroyRegion(regionp->rgn);
867
        free(regionp);
868
}
869
 
870
/*
871
 * Updates the region from a union of the specified rectangle
872
 * and the original region.
873
 */
874
void
875
GrUnionRectWithRegion(GR_REGION_ID region, GR_RECT *rect)
876
{
877
        GR_REGION       *regionp;
878
        MWRECT          rc;
879
 
880
        regionp = GsFindRegion(region);
881
        if (regionp) {
882
                /* convert Nano-X rect to MW rect*/
883
                rc.left = rect->x;
884
                rc.top = rect->y;
885
                rc.right = rect->x + rect->width;
886
                rc.bottom = rect->y + rect->height;
887
                GdUnionRectWithRegion(&rc, regionp->rgn);
888
        }
889
}
890
 
891
/*
892
 * Updates the region from a union of two regions.
893
 */
894
void
895
GrUnionRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
896
        GR_REGION_ID src_rgn2)
897
{
898
        GR_REGION       *regionp;
899
        GR_REGION       *srcregionp1;
900
        GR_REGION       *srcregionp2;
901
 
902
        regionp = GsFindRegion(dst_rgn);
903
        if (regionp == NULL)
904
                return;
905
 
906
        srcregionp1 = GsFindRegion(src_rgn1);
907
        if (srcregionp1 == NULL)
908
                return;
909
 
910
        srcregionp2 = GsFindRegion(src_rgn2);
911
        if (srcregionp2 == NULL)
912
                return;
913
 
914
        GdUnionRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
915
}
916
 
917
/*
918
 * Updates the region by subtracting a region from another.
919
 */
920
void
921
GrSubtractRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
922
        GR_REGION_ID src_rgn2)
923
{
924
        GR_REGION       *regionp;
925
        GR_REGION       *srcregionp1;
926
        GR_REGION       *srcregionp2;
927
 
928
        regionp = GsFindRegion(dst_rgn);
929
        if (regionp == NULL)
930
                return;
931
 
932
        srcregionp1 = GsFindRegion(src_rgn1);
933
        if (srcregionp1 == NULL)
934
                return;
935
 
936
        srcregionp2 = GsFindRegion(src_rgn2);
937
        if (srcregionp2 == NULL)
938
                return;
939
 
940
        GdSubtractRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
941
}
942
 
943
/*
944
 * Updates the region to the difference of two regions.
945
 */
946
void
947
GrXorRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
948
        GR_REGION_ID src_rgn2)
949
{
950
        GR_REGION       *regionp;
951
        GR_REGION       *srcregionp1;
952
        GR_REGION       *srcregionp2;
953
 
954
        regionp = GsFindRegion(dst_rgn);
955
        if (regionp == NULL)
956
                return;
957
 
958
        srcregionp1 = GsFindRegion(src_rgn1);
959
        if (srcregionp1 == NULL)
960
                return;
961
 
962
        srcregionp2 = GsFindRegion(src_rgn2);
963
        if (srcregionp2 == NULL)
964
                return;
965
 
966
        GdXorRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
967
}
968
 
969
/*
970
 * Updates the region from a intersection of two regions.
971
 */
972
void
973
GrIntersectRegion(GR_REGION_ID dst_rgn, GR_REGION_ID src_rgn1,
974
        GR_REGION_ID src_rgn2)
975
{
976
        GR_REGION       *regionp;
977
        GR_REGION       *srcregionp1;
978
        GR_REGION       *srcregionp2;
979
 
980
        regionp = GsFindRegion(dst_rgn);
981
        if (regionp == NULL)
982
                return;
983
 
984
        srcregionp1 = GsFindRegion(src_rgn1);
985
        if (srcregionp1 == NULL)
986
                return;
987
 
988
        srcregionp2 = GsFindRegion(src_rgn2);
989
        if (srcregionp2 == NULL)
990
                return;
991
 
992
        GdIntersectRegion(regionp->rgn, srcregionp1->rgn, srcregionp2->rgn);
993
}
994
 
995
/*
996
 * Sets the clip-mask in the GC to the specified region.
997
 */
998
void
999
GrSetGCRegion(GR_GC_ID gc, GR_REGION_ID region)
1000
{
1001
        GR_GC           *gcp;
1002
 
1003
        gcp = GsFindGC(gc);
1004
        if(gcp == NULL)
1005
                return;
1006
 
1007
        gcp->regionid = region;
1008
        gcp->changed = GR_TRUE;
1009
}
1010
 
1011
/*
1012
 * Set the x,y origin of user clip region in GC.
1013
 */
1014
void
1015
GrSetGCClipOrigin(GR_GC_ID gc, int xoff, int yoff)
1016
{
1017
        GR_GC           *gcp;
1018
 
1019
        gcp = GsFindGC(gc);
1020
        if(gcp == NULL)
1021
                return;
1022
 
1023
        gcp->xoff = xoff;
1024
        gcp->yoff = yoff;
1025
        gcp->changed = GR_TRUE;
1026
}
1027
 
1028
/*
1029
 * Determines whether a specified point resides in a region.
1030
 */
1031
GR_BOOL
1032
GrPointInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y)
1033
{
1034
        GR_REGION       *regionp;
1035
 
1036
        regionp =  GsFindRegion(region);
1037
        if (regionp == NULL)
1038
                return GR_FALSE;
1039
 
1040
        return GdPtInRegion(regionp->rgn, x, y);
1041
}
1042
 
1043
/*
1044
 * Determines whether a specified rectangle at least partly resides
1045
 * in a region.
1046
 */
1047
int
1048
GrRectInRegion(GR_REGION_ID region, GR_COORD x, GR_COORD y, GR_COORD w,
1049
        GR_COORD h)
1050
{
1051
        GR_REGION       *regionp;
1052
        MWRECT          rect;
1053
 
1054
        regionp =  GsFindRegion(region);
1055
        if (regionp == NULL)
1056
                return MWRECT_OUT;
1057
 
1058
        rect.left = x;
1059
        rect.top = y;
1060
        rect.right = x + w;
1061
        rect.bottom = y + h;
1062
        return GdRectInRegion(regionp->rgn, &rect);
1063
}
1064
 
1065
/*
1066
 * Return GR_TRUE if a region is empty.
1067
 */
1068
GR_BOOL
1069
GrEmptyRegion(GR_REGION_ID region)
1070
{
1071
        GR_REGION       *regionp;
1072
 
1073
        regionp =  GsFindRegion(region);
1074
        if (regionp == NULL)
1075
                return GR_TRUE;
1076
 
1077
        return GdEmptyRegion(regionp->rgn);
1078
}
1079
 
1080
/*
1081
 * Return GR_TRUE if two regions are identical.
1082
 */
1083
GR_BOOL
1084
GrEqualRegion(GR_REGION_ID rgn1, GR_REGION_ID rgn2)
1085
{
1086
        GR_REGION       *prgn1;
1087
        GR_REGION       *prgn2;
1088
 
1089
        prgn1 = GsFindRegion(rgn1);
1090
        prgn2 = GsFindRegion(rgn2);
1091
 
1092
        if (!prgn1 && !prgn2)
1093
                return GR_TRUE;
1094
        if (!prgn1 || !prgn2)
1095
                return GR_FALSE;
1096
 
1097
        return GdEqualRegion(prgn1->rgn, prgn2->rgn);
1098
}
1099
 
1100
/*
1101
 * Offset a region by dx, dy.
1102
 */
1103
void
1104
GrOffsetRegion(GR_REGION_ID region, GR_SIZE dx, GR_SIZE dy)
1105
{
1106
        GR_REGION       *regionp;
1107
 
1108
        regionp =  GsFindRegion(region);
1109
        if (regionp)
1110
                GdOffsetRegion(regionp->rgn, dx, dy);
1111
}
1112
 
1113
/*
1114
 * Return the bounding box for the specified region.
1115
 */
1116
int
1117
GrGetRegionBox(GR_REGION_ID region, GR_RECT *rect)
1118
{
1119
        GR_REGION       *regionp;
1120
        MWRECT          rc;
1121
        int             ret_val;
1122
 
1123
        regionp =  GsFindRegion(region);
1124
        if (regionp == NULL) {
1125
                memset(rect, 0, sizeof(GR_RECT));
1126
                return MWREGION_ERROR;
1127
        }
1128
 
1129
        ret_val = GdGetRegionBox(regionp->rgn, &rc);
1130
        /* convert MW rect to Nano-X rect*/
1131
        rect->x = rc.left;
1132
        rect->y = rc.top;
1133
        rect->width = rc.right - rc.left;
1134
        rect->height = rc.bottom - rc.top;
1135
        return ret_val;
1136
}
1137
 
1138
static int nextfontid = 1000;
1139
/*
1140
 * Allocate a new GC with default parameters.
1141
 * The GC is owned by the current client.
1142
 */
1143
GR_FONT_ID
1144
GrCreateFont(GR_CHAR *name, GR_COORD height, GR_LOGFONT *plogfont)
1145
{
1146
        GR_FONT *fontp;
1147
 
1148
        fontp = (GR_FONT *) malloc(sizeof(GR_FONT));
1149
        if (fontp == NULL) {
1150
                GsError(GR_ERROR_MALLOC_FAILED, 0);
1151
                return 0;
1152
        }
1153
 
1154
        if (plogfont)
1155
                fontp->pfont = GdCreateFont(&scrdev, NULL, 0, plogfont);
1156
        else
1157
                fontp->pfont = GdCreateFont(&scrdev, name, height, NULL);
1158
        fontp->id = nextfontid++;
1159
        fontp->owner = curclient;
1160
        fontp->next = listfontp;
1161
 
1162
        listfontp = fontp;
1163
 
1164
        return fontp->id;
1165
}
1166
 
1167
/* Set the font size for the passed font*/
1168
void
1169
GrSetFontSize(GR_FONT_ID fontid, GR_COORD size)
1170
{
1171
        GR_FONT         *fontp;
1172
 
1173
        fontp = GsFindFont(fontid);
1174
        if (fontp)
1175
                GdSetFontSize(fontp->pfont, size);
1176
}
1177
 
1178
/* Set the font rotation in tenths of degrees for the passed font*/
1179
void
1180
GrSetFontRotation(GR_FONT_ID fontid, int tenthdegrees)
1181
{
1182
        GR_FONT         *fontp;
1183
 
1184
        fontp = GsFindFont(fontid);
1185
        if (fontp)
1186
                GdSetFontRotation(fontp->pfont, tenthdegrees);
1187
}
1188
 
1189
/* Set the font size for the passed font*/
1190
void
1191
GrSetFontAttr(GR_FONT_ID fontid, int setflags, int clrflags)
1192
{
1193
        GR_FONT         *fontp;
1194
 
1195
        fontp = GsFindFont(fontid);
1196
        if (fontp)
1197
                GdSetFontAttr(fontp->pfont, setflags, clrflags);
1198
}
1199
 
1200
/*
1201
 * Unload and deallocate an existing font.
1202
 */
1203
void
1204
GrDestroyFont(GR_FONT_ID fontid)
1205
{
1206
        GR_FONT         *fontp;
1207
        GR_FONT         *prevfontp;
1208
 
1209
        fontp = GsFindFont(fontid);
1210
        if (fontp == NULL)
1211
                return;
1212
 
1213
        if (listfontp == fontp)
1214
                listfontp = fontp->next;
1215
        else {
1216
                prevfontp = listfontp;
1217
                while (prevfontp->next != fontp)
1218
                        prevfontp = prevfontp->next;
1219
 
1220
                prevfontp->next = fontp->next;
1221
        }
1222
        GdDestroyFont(fontp->pfont);
1223
        free(fontp);
1224
}
1225
 
1226
/*
1227
 * Return useful information about the specified font.
1228
 * Font #0 returns info about the standard font.
1229
 */
1230
void
1231
GrGetFontInfo(GR_FONT_ID font, GR_FONT_INFO *fip)
1232
{
1233
        GR_FONT *fontp;
1234
        PMWFONT pf;
1235
 
1236
        if (font == 0)
1237
                pf = stdfont;
1238
        else {
1239
                fontp = GsFindFont(font);
1240
                if (!fontp) {
1241
                        memset(fip, 0, sizeof(GR_FONT_INFO));
1242
                        return;
1243
                }
1244
                pf = fontp->pfont;
1245
        }
1246
        GdGetFontInfo(pf, fip);
1247
}
1248
 
1249
/*
1250
 * Select events for a window for this client.
1251
 * The events are a bitmask for the events desired.
1252
 */
1253
void
1254
GrSelectEvents(GR_WINDOW_ID wid, GR_EVENT_MASK eventmask)
1255
{
1256
        GR_WINDOW       *wp;            /* window structure */
1257
        GR_EVENT_CLIENT *evp;           /* event-client structure */
1258
 
1259
        wp = GsFindWindow(wid);
1260
        if (wp == NULL)
1261
                return;
1262
 
1263
        /*
1264
         * See if this client is already in the event client list.
1265
         * If so, then just replace the events he is selecting for.
1266
         */
1267
        for (evp = wp->eventclients; evp; evp = evp->next) {
1268
                if (evp->client == curclient) {
1269
                        evp->eventmask = eventmask;
1270
                        return;
1271
                }
1272
        }
1273
 
1274
        /*
1275
         * A new client for this window, so allocate a new event client
1276
         * structure and insert it into the front of the list in the window.
1277
         */
1278
        evp = (GR_EVENT_CLIENT *) malloc(sizeof(GR_EVENT_CLIENT));
1279
        if (evp == NULL) {
1280
                GsError(GR_ERROR_MALLOC_FAILED, wid);
1281
                return;
1282
        }
1283
 
1284
        evp->client = curclient;
1285
        evp->eventmask = eventmask;
1286
        evp->next = wp->eventclients;
1287
        wp->eventclients = evp;
1288
 
1289
        /*
1290
         * If it's a request for child updates to the root window,
1291
         * then search entire list and send map events for
1292
         * mapped windows now.  This allows a window manager
1293
         * to get the mapped window list without another API call.
1294
         */
1295
        if (wid==GR_ROOT_WINDOW_ID && (eventmask & GR_EVENT_MASK_CHLD_UPDATE)) {
1296
                for (wp = listwp; wp; wp = wp->next) {
1297
                        if (wp->unmapcount == 0)
1298
                                GsDeliverUpdateEvent(wp, GR_UPDATE_MAP,
1299
                                        wp->x, wp->y, wp->width, wp->height);
1300
                }
1301
        }
1302
}
1303
 
1304
static GR_WINDOW *
1305
NewWindow(GR_WINDOW *pwp, GR_COORD x, GR_COORD y, GR_SIZE width,
1306
        GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
1307
        GR_COLOR bordercolor)
1308
{
1309
        GR_WINDOW       *wp;    /* new window*/
1310
 
1311
        if (width <= 0 || height <= 0 || bordersize < 0) {
1312
                GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);
1313
                return NULL;
1314
        }
1315
 
1316
        wp = (GR_WINDOW *) malloc(sizeof(GR_WINDOW));
1317
        if (wp == NULL) {
1318
                GsError(GR_ERROR_MALLOC_FAILED, 0);
1319
                return NULL;
1320
        }
1321
 
1322
        wp->id = nextid++;
1323
        wp->psd = rootwp->psd;
1324
        wp->parent = pwp;
1325
        wp->children = NULL;
1326
        wp->siblings = pwp->children;
1327
        wp->next = listwp;
1328
        wp->x = pwp->x + x;
1329
        wp->y = pwp->y + y;
1330
        wp->width = width;
1331
        wp->height = height;
1332
        wp->bordersize = bordersize;
1333
        wp->background = background;
1334
        wp->bgpixmap = NULL;
1335
        wp->bgpixmapflags = GR_BACKGROUND_TILE;
1336
        wp->bordercolor = bordercolor;
1337
        wp->nopropmask = 0;
1338
        wp->eventclients = NULL;
1339
        wp->owner = curclient;
1340
        wp->cursorid = pwp->cursorid;
1341
        wp->mapped = GR_FALSE;
1342
        wp->unmapcount = pwp->unmapcount + 1;
1343
        wp->output = GR_TRUE;
1344
        wp->props = 0;
1345
        wp->title = NULL;
1346
 
1347
        pwp->children = wp;
1348
        listwp = wp;
1349
 
1350
        return wp;
1351
}
1352
 
1353
/*
1354
 * Allocate a new window which is a child of the specified window.
1355
 * The window inherits the cursor of the parent window.
1356
 * The window is owned by the current client.
1357
 */
1358
GR_WINDOW_ID
1359
GrNewWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y, GR_SIZE width,
1360
        GR_SIZE height, GR_SIZE bordersize, GR_COLOR background,
1361
        GR_COLOR bordercolor)
1362
{
1363
        GR_WINDOW       *pwp;           /* parent window */
1364
        GR_WINDOW       *wp;            /* new window */
1365
 
1366
        pwp = GsFindWindow(parent);
1367
        if (pwp == NULL)
1368
                return 0;
1369
 
1370
        if (!pwp->output) {
1371
                GsError(GR_ERROR_INPUT_ONLY_WINDOW, pwp->id);
1372
                return 0;
1373
        }
1374
 
1375
        wp = NewWindow(pwp, x, y, width, height, bordersize, background,
1376
                bordercolor);
1377
        return wp? wp->id: 0;
1378
}
1379
 
1380
/*
1381
 * Allocate a new input-only window which is a child of the specified window.
1382
 * Such a window is invisible, cannot be drawn into, and is only used to
1383
 * return events.  The window inherits the cursor of the parent window.
1384
 * The window is owned by the current client.
1385
 */
1386
GR_WINDOW_ID
1387
GrNewInputWindow(GR_WINDOW_ID parent, GR_COORD x, GR_COORD y,
1388
        GR_SIZE width, GR_SIZE height)
1389
{
1390
        GR_WINDOW       *pwp;           /* parent window */
1391
        GR_WINDOW       *wp;            /* new window */
1392
 
1393
        pwp = GsFindWindow(parent);
1394
        if (pwp == NULL)
1395
                return 0;
1396
 
1397
        wp = NewWindow(pwp, x, y, width, height, 0, BLACK, BLACK);
1398
        if (wp) {
1399
                /* convert to input-only window*/
1400
                wp->output = GR_FALSE;
1401
                return wp->id;
1402
        }
1403
        return 0;
1404
}
1405
 
1406
/*
1407
 * Allocate a pixmap, can be used with any drawing functions
1408
 * for offscreen drawing
1409
 */
1410
GR_WINDOW_ID
1411
GrNewPixmap(GR_SIZE width, GR_SIZE height, void * pixels)
1412
{
1413
        GR_PIXMAP       *pp;
1414
        PSD             psd;
1415
        int             size, linelen, bpp, planes;
1416
 
1417
        if (width <= 0 || height <= 0) {
1418
                /* no error for now, server will desynchronize w/app*/
1419
                /*GsError(GR_ERROR_BAD_WINDOW_SIZE, 0);*/
1420
                return 0;
1421
        }
1422
 
1423
        /*
1424
         * allocate offscreen psd.  If screen driver doesn't
1425
         * support blitting, this will fail.  Use root window screen
1426
         * device for compatibility for now.
1427
         */
1428
        planes = rootwp->psd->planes;
1429
        bpp = rootwp->psd->bpp;
1430
        psd = rootwp->psd->AllocateMemGC(rootwp->psd);
1431
        if (!psd)
1432
                return 0;
1433
 
1434
        pp = (GR_PIXMAP *) malloc(sizeof(GR_PIXMAP));
1435
        if (pp == NULL) {
1436
                GsError(GR_ERROR_MALLOC_FAILED, 0);
1437
                psd->FreeMemGC(psd);
1438
                return 0;
1439
        }
1440
 
1441
        GdCalcMemGCAlloc(psd, width, height, 0, 0, &size, &linelen);
1442
 
1443
        /* Allocate space for pixel values */
1444
        if (!pixels) {
1445
                pixels = calloc(size, 1);
1446
                psd->flags |= PSF_ADDRMALLOC;
1447
        }
1448
        if (!pixels) {
1449
                free(pp);
1450
                psd->FreeMemGC(psd);
1451
                GsError(GR_ERROR_MALLOC_FAILED, 0);
1452
                return 0;
1453
        }
1454
 
1455
        pp->id = nextid++;
1456
        pp->next = listpp;
1457
        pp->psd = psd;
1458
        pp->x = 0;
1459
        pp->y = 0;
1460
        pp->width = width;
1461
        pp->height = height;
1462
        pp->owner = curclient;
1463
 
1464
        psd->MapMemGC(psd, width, height, planes, bpp, linelen, size,
1465
                pixels);
1466
 
1467
        listpp = pp;
1468
        return pp->id;
1469
}
1470
 
1471
/*
1472
 * Map the window to make it (and possibly its children) visible on the screen.
1473
 */
1474
void
1475
GrMapWindow(GR_WINDOW_ID wid)
1476
{
1477
        GR_WINDOW       *wp;            /* window structure */
1478
 
1479
        wp = GsFindWindow(wid);
1480
        if (!wp || wp->mapped)
1481
                return;
1482
 
1483
        wp->mapped = GR_TRUE;
1484
 
1485
        GsWpMapWindow(wp, GR_FALSE);
1486
}
1487
 
1488
/*
1489
 * Unmap the window to make it and its children invisible on the screen.
1490
 */
1491
void
1492
GrUnmapWindow(GR_WINDOW_ID wid)
1493
{
1494
        GR_WINDOW       *wp;            /* window structure */
1495
 
1496
        wp = GsFindWindow(wid);
1497
        if (!wp || !wp->mapped)
1498
                return;
1499
 
1500
        GsWpUnmapWindow(wp, GR_FALSE);
1501
 
1502
        wp->mapped = GR_FALSE;
1503
}
1504
 
1505
/*
1506
 * Clear the associated area of a window to its background color
1507
 * or pixmap.  Generate expose event for window if exposeflag set.
1508
 */
1509
void
1510
GrClearArea(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y, GR_SIZE width,
1511
        GR_SIZE height, GR_BOOL exposeflag)
1512
{
1513
        GR_WINDOW               *wp;    /* window structure */
1514
 
1515
        wp = GsPrepareWindow(wid);
1516
        if (wp) {
1517
                if (width == 0)
1518
                        width = wp->width;
1519
                if (height == 0)
1520
                        height = wp->height;
1521
                GsWpClearWindow(wp, x, y, width, height, exposeflag);
1522
        }
1523
}
1524
 
1525
/* Return window with keyboard focus.*/
1526
GR_WINDOW_ID
1527
GrGetFocus(void)
1528
{
1529
        return focuswp->id;
1530
}
1531
 
1532
/*
1533
 * Set the focus to a particular window.
1534
 * This makes keyboard events only visible to that window or children of it,
1535
 * depending on the pointer location.
1536
 */
1537
void
1538
GrSetFocus(GR_WINDOW_ID wid)
1539
{
1540
        GR_WINDOW       *wp;            /* window structure */
1541
 
1542
        wp = GsFindWindow(wid);
1543
        if (wp == NULL)
1544
                return;
1545
 
1546
        if (wp->unmapcount) {
1547
                GsError(GR_ERROR_UNMAPPED_FOCUS_WINDOW, wid);
1548
                return;
1549
        }
1550
 
1551
        /* Check if window wants focus, if not, ignore call*/
1552
        if (wp->props & GR_WM_PROPS_NOFOCUS)
1553
                return;
1554
 
1555
        focusfixed = (wp != rootwp);
1556
        GsWpSetFocus(wp);
1557
}
1558
 
1559
/*
1560
 * Create a new server-based cursor resource.
1561
 */
1562
static int nextcursorid = 1000;
1563
GR_CURSOR_ID
1564
GrNewCursor(GR_SIZE width, GR_SIZE height, GR_COORD hotx, GR_COORD hoty,
1565
        GR_COLOR foreground, GR_COLOR background, GR_BITMAP *fgbitmap,
1566
        GR_BITMAP *bgbitmap)
1567
{
1568
        GR_CURSOR       *cp;
1569
        int             bytes;
1570
 
1571
        /*
1572
         * Make sure the size of the bitmap is reasonable.
1573
         */
1574
        if (width <= 0 || width > MWMAX_CURSOR_SIZE ||
1575
            height <= 0 || height > MWMAX_CURSOR_SIZE) {
1576
                GsError(GR_ERROR_BAD_CURSOR_SIZE, 0);
1577
                return 0;
1578
        }
1579
 
1580
        cp = (GR_CURSOR *)malloc(sizeof(GR_CURSOR));
1581
        if (cp == NULL) {
1582
                GsError(GR_ERROR_MALLOC_FAILED, 0);
1583
                return 0;
1584
        }
1585
 
1586
        /* fill in cursor structure*/
1587
        cp->cursor.width = width;
1588
        cp->cursor.height = height;
1589
        cp->cursor.hotx = hotx;
1590
        cp->cursor.hoty = hoty;
1591
        cp->cursor.fgcolor = foreground;
1592
        cp->cursor.bgcolor = background;
1593
        bytes = GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP);
1594
        memcpy(&cp->cursor.image, fgbitmap, bytes);
1595
        memcpy(&cp->cursor.mask, bgbitmap, bytes);
1596
 
1597
        cp->id = nextcursorid++;
1598
        cp->owner = curclient;
1599
        cp->next = listcursorp;
1600
        listcursorp = cp;
1601
 
1602
        return cp->id;
1603
}
1604
 
1605
/*
1606
 * Destroy a server-based cursor.
1607
 */
1608
void
1609
GrDestroyCursor(GR_CURSOR_ID cid)
1610
{
1611
        GR_CURSOR       *cursorp;
1612
        GR_CURSOR       *prevcursorp;
1613
 
1614
        cursorp = GsFindCursor(cid);
1615
        if (cursorp == NULL)
1616
                return;
1617
 
1618
        if (listcursorp == cursorp)
1619
                listcursorp = cursorp->next;
1620
        else {
1621
                prevcursorp = listcursorp;
1622
                while (prevcursorp->next != cursorp)
1623
                        prevcursorp = prevcursorp->next;
1624
 
1625
                prevcursorp->next = cursorp->next;
1626
        }
1627
 
1628
        if (curcursor == cursorp)
1629
                curcursor = NULL;
1630
 
1631
        free(cursorp);
1632
        GsCheckCursor();
1633
}
1634
 
1635
/*
1636
 * Specify a cursor for a window.
1637
 * This cursor will only be used within that window, and by default
1638
 * for its new children.  If the cursor is currently within this
1639
 * window, it will be changed to the new one immediately.
1640
 * If the new cursor id is 0, revert to the root window cursor.
1641
 */
1642
void
1643
GrSetWindowCursor(GR_WINDOW_ID wid, GR_CURSOR_ID cid)
1644
{
1645
        GR_WINDOW       *wp;
1646
        GR_CURSOR       *cp;            /* cursor structure */
1647
 
1648
        wp = GsFindWindow(wid);
1649
        if (wp == NULL)
1650
                return;
1651
 
1652
        if (cid == 0)
1653
                cp = stdcursor;
1654
        else {
1655
                cp = GsFindCursor(cid);
1656
                if (!cp)
1657
                        return;         /* FIXME add server errmsg*/
1658
        }
1659
        wp->cursorid = cid;
1660
 
1661
        /*
1662
         * If this was the current cursor, then draw the new one.
1663
         */
1664
        if (cp == curcursor || curcursor == NULL) {
1665
                GdMoveCursor(cursorx - cp->cursor.hotx,
1666
                        cursory - cp->cursor.hoty);
1667
                GdSetCursor(&cp->cursor);
1668
        }
1669
 
1670
        GsCheckCursor();
1671
}
1672
 
1673
/*
1674
 * Move the cursor to the specified absolute screen coordinates.
1675
 * The coordinates are that of the defined hot spot of the cursor.
1676
 * The cursor's appearance is changed to that defined for the window
1677
 * in which the cursor is moved to.  In addition, mouse enter, mouse
1678
 * exit, focus in, and focus out events are generated if necessary.
1679
 * The current mouse location is also changed.
1680
 */
1681
void
1682
GrMoveCursor(GR_COORD x, GR_COORD y)
1683
{
1684
        /*
1685
         * Move the cursor only if necessary, offsetting it to
1686
         * place the hot spot at the specified coordinates.
1687
         */
1688
        if ((x != cursorx) || (y != cursory)) {
1689
                if(curcursor) {
1690
                        GdMoveCursor(x - curcursor->cursor.hotx,
1691
                                y - curcursor->cursor.hoty);
1692
                        GdMoveMouse(x, y);
1693
                }
1694
                cursorx = x;
1695
                cursory = y;
1696
        }
1697
 
1698
        /*
1699
         * Now check to see which window the mouse is in, whether or
1700
         * not the cursor shape should be changed, and whether or not
1701
         * the input focus window should be changed.
1702
         */
1703
        GsCheckMouseWindow();
1704
        GsCheckFocusWindow();
1705
        GsCheckCursor();
1706
}
1707
 
1708
/*
1709
 * Set the foreground color in a graphics context.
1710
 */
1711
void
1712
GrSetGCForeground(GR_GC_ID gc, GR_COLOR foreground)
1713
{
1714
        GR_GC           *gcp;           /* graphics context */
1715
 
1716
        gcp = GsFindGC(gc);
1717
        if (!gcp || gcp->foreground == foreground)
1718
                return;
1719
 
1720
        gcp->foreground = foreground;
1721
        gcp->changed = GR_TRUE;
1722
}
1723
 
1724
/*
1725
 * Set the background color in a graphics context.
1726
 */
1727
void
1728
GrSetGCBackground(GR_GC_ID gc, GR_COLOR background)
1729
{
1730
        GR_GC           *gcp;           /* graphics context */
1731
 
1732
        gcp = GsFindGC(gc);
1733
        if (!gcp || gcp->background == background)
1734
                return;
1735
 
1736
        gcp->background = background;
1737
        gcp->changed = GR_TRUE;
1738
}
1739
 
1740
/*
1741
 * Set whether or not the background color is drawn in bitmaps and text.
1742
 */
1743
void
1744
GrSetGCUseBackground(GR_GC_ID gc, GR_BOOL flag)
1745
{
1746
        GR_GC           *gcp;           /* graphics context */
1747
 
1748
        flag = (flag != 0);
1749
        gcp = GsFindGC(gc);
1750
        if (!gcp || gcp->usebackground == flag)
1751
                return;
1752
 
1753
        gcp->usebackground = flag;
1754
        gcp->changed = GR_TRUE;
1755
}
1756
 
1757
/*
1758
 * Set the drawing mode in a graphics context.
1759
 */
1760
void
1761
GrSetGCMode(GR_GC_ID gc, int mode)
1762
{
1763
        GR_GC           *gcp;           /* graphics context */
1764
 
1765
        gcp = GsFindGC(gc);
1766
        if (!gcp || gcp->mode == mode)
1767
                return;
1768
        if ((mode & GR_MODE_DRAWMASK) > GR_MAX_MODE) {
1769
                GsError(GR_ERROR_BAD_DRAWING_MODE, gc);
1770
                return;
1771
        }
1772
 
1773
        gcp->mode = mode;
1774
        gcp->changed = GR_TRUE;
1775
}
1776
 
1777
/*
1778
 * Set the text font in a graphics context.
1779
 */
1780
void
1781
GrSetGCFont(GR_GC_ID gc, GR_FONT_ID font)
1782
{
1783
        GR_GC           *gcp;           /* graphics context */
1784
        GR_FONT         *fontp;
1785
 
1786
        gcp = GsFindGC(gc);
1787
        if (!gcp || gcp->fontid == font)
1788
                return;
1789
 
1790
        fontp = GsFindFont(font);
1791
        gcp->fontid = font;
1792
        gcp->changed = GR_TRUE;
1793
}
1794
 
1795
/*
1796
 * Draw a line in the specified drawable using the specified graphics context.
1797
 */
1798
 
1799
void
1800
GrLine(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x1, GR_COORD y1, GR_COORD x2,
1801
        GR_COORD y2)
1802
{
1803
        GR_DRAWABLE     *dp;
1804
 
1805
        switch (GsPrepareDrawing(id, gc, &dp)) {
1806
                case GR_DRAW_TYPE_WINDOW:
1807
                case GR_DRAW_TYPE_PIXMAP:
1808
                        GdLine(dp->psd, dp->x + x1, dp->y + y1,
1809
                                dp->x + x2, dp->y + y2, TRUE);
1810
                        break;
1811
        }
1812
}
1813
 
1814
/*
1815
 * Draw the boundary of a rectangle in the specified drawable using the
1816
 * specified graphics context.
1817
 * NOTE: this function draws a rectangle 1 pixel wider and higher
1818
 * than Xlib's XDrawRectangle().
1819
 */
1820
void
1821
GrRect(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
1822
        GR_SIZE height)
1823
{
1824
        GR_DRAWABLE     *dp;
1825
 
1826
        switch (GsPrepareDrawing(id, gc, &dp)) {
1827
                case GR_DRAW_TYPE_WINDOW:
1828
                case GR_DRAW_TYPE_PIXMAP:
1829
                        GdRect(dp->psd, dp->x + x, dp->y + y, width, height);
1830
                        break;
1831
        }
1832
}
1833
 
1834
/*
1835
 * Fill a rectangle in the specified drawable using the specified
1836
 * graphics context.
1837
 */
1838
void
1839
GrFillRect(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
1840
        GR_SIZE width, GR_SIZE height)
1841
{
1842
        GR_DRAWABLE     *dp;
1843
 
1844
        switch (GsPrepareDrawing(id, gc, &dp)) {
1845
                case GR_DRAW_TYPE_WINDOW:
1846
                case GR_DRAW_TYPE_PIXMAP:
1847
                        GdFillRect(dp->psd, dp->x + x, dp->y + y, width,height);
1848
                        break;
1849
        }
1850
}
1851
 
1852
/*
1853
 * Draw the boundary of an ellipse in the specified drawable with
1854
 * the specified graphics context.  Integer only.
1855
 */
1856
void
1857
GrEllipse(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE rx,
1858
        GR_SIZE ry)
1859
{
1860
        GR_DRAWABLE     *dp;
1861
 
1862
        switch (GsPrepareDrawing(id, gc, &dp)) {
1863
                case GR_DRAW_TYPE_WINDOW:
1864
                case GR_DRAW_TYPE_PIXMAP:
1865
                        GdEllipse(dp->psd, dp->x + x, dp->y + y, rx, ry, FALSE);
1866
                        break;
1867
        }
1868
}
1869
 
1870
/*
1871
 * Fill an ellipse in the specified drawable using the specified
1872
 * graphics context.  Integer only.
1873
 */
1874
void
1875
GrFillEllipse(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE rx,
1876
        GR_SIZE ry)
1877
{
1878
        GR_DRAWABLE     *dp;
1879
 
1880
        switch (GsPrepareDrawing(id, gc, &dp)) {
1881
                case GR_DRAW_TYPE_WINDOW:
1882
                case GR_DRAW_TYPE_PIXMAP:
1883
                        GdEllipse(dp->psd, dp->x + x, dp->y + y, rx, ry, TRUE);
1884
                        break;
1885
        }
1886
}
1887
 
1888
/*
1889
 * Draw an arc, pie or ellipse in the specified drawable using
1890
 * the specified graphics context.  Integer only.
1891
 */
1892
void
1893
GrArc(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
1894
        GR_SIZE rx, GR_SIZE ry, GR_COORD ax, GR_COORD ay,
1895
        GR_COORD bx, GR_COORD by, int type)
1896
{
1897
        GR_DRAWABLE     *dp;
1898
 
1899
        switch (GsPrepareDrawing(id, gc, &dp)) {
1900
                case GR_DRAW_TYPE_WINDOW:
1901
                case GR_DRAW_TYPE_PIXMAP:
1902
                        GdArc(dp->psd, dp->x + x, dp->y + y, rx, ry,
1903
                                dp->x+ax, dp->y+ay, dp->x+bx, dp->y+by, type);
1904
                        break;
1905
        }
1906
}
1907
 
1908
/*
1909
 * Draw an arc or pie in the specified drawable using
1910
 * the specified graphics context.  Requires floating point.
1911
 */
1912
void
1913
GrArcAngle(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
1914
        GR_SIZE rx, GR_SIZE ry, GR_COORD angle1, GR_COORD angle2, int type)
1915
{
1916
        GR_DRAWABLE     *dp;
1917
 
1918
        switch (GsPrepareDrawing(id, gc, &dp)) {
1919
                case GR_DRAW_TYPE_WINDOW:
1920
                case GR_DRAW_TYPE_PIXMAP:
1921
                        GdArcAngle(dp->psd, dp->x + x, dp->y + y, rx, ry,
1922
                                angle1, angle2, type);
1923
                        break;
1924
        }
1925
}
1926
 
1927
/*
1928
 * Draw a rectangular area in the specified drawable using the specified
1929
 * graphics, as determined by the specified bit map.  This differs from
1930
 * rectangle drawing in that the rectangle is drawn using the foreground
1931
 * color and possibly the background color as determined by the bit map.
1932
 * Each row of bits is aligned to the next bitmap word boundary (so there
1933
 * is padding at the end of the row).  The background bit values are only
1934
 * written if the usebackground flag is set in the GC.
1935
 */
1936
void
1937
GrBitmap(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
1938
        GR_SIZE height, GR_BITMAP *imagebits)
1939
{
1940
        GR_DRAWABLE     *dp;
1941
 
1942
        switch (GsPrepareDrawing(id, gc, &dp)) {
1943
                case GR_DRAW_TYPE_WINDOW:
1944
                case GR_DRAW_TYPE_PIXMAP:
1945
                        GdBitmap(dp->psd, dp->x + x, dp->y + y, width, height,
1946
                                imagebits);
1947
                        break;
1948
        }
1949
}
1950
 
1951
/* draw a multicolor image at x, y*/
1952
void
1953
GrDrawImageBits(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
1954
        GR_IMAGE_HDR *pimage)
1955
{
1956
        GR_DRAWABLE     *dp;
1957
 
1958
        switch (GsPrepareDrawing(id, gc, &dp)) {
1959
                case GR_DRAW_TYPE_WINDOW:
1960
                case GR_DRAW_TYPE_PIXMAP:
1961
                        GdDrawImage(dp->psd, dp->x + x, dp->y + y, pimage);
1962
                        break;
1963
        }
1964
}
1965
 
1966
#if !((DOS_DJGPP) || (__PACIFIC__) || (DOS_TURBOC))
1967
/* Load an image file from disk and display it at the specified coordinates*/
1968
void
1969
GrDrawImageFromFile(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
1970
        GR_SIZE width, GR_SIZE height, char* path, int flags)
1971
{
1972
#if defined(HAVE_FILEIO)
1973
        GR_DRAWABLE     *dp;
1974
 
1975
        switch (GsPrepareDrawing(id, gc, &dp)) {
1976
                case GR_DRAW_TYPE_WINDOW:
1977
                case GR_DRAW_TYPE_PIXMAP:
1978
                        GdDrawImageFromFile(dp->psd, dp->x + x, dp->y + y,
1979
                                width, height, path, flags);
1980
                        break;
1981
        }
1982
#endif
1983
}
1984
 
1985
/* load image from file and cache it*/
1986
GR_IMAGE_ID
1987
GrLoadImageFromFile(char *path, int flags)
1988
{
1989
#if defined(HAVE_FILEIO)
1990
        GR_IMAGE_ID     id;
1991
        GR_IMAGE *      imagep;
1992
 
1993
        id = GdLoadImageFromFile(&scrdev, path, flags);
1994
        if (!id)
1995
                return 0;
1996
 
1997
        imagep = (GR_IMAGE *) malloc(sizeof(GR_IMAGE));
1998
        if (imagep == NULL) {
1999
                GsError(GR_ERROR_MALLOC_FAILED, 0);
2000
                GdFreeImage(id);
2001
                return 0;
2002
        }
2003
 
2004
        imagep->id = id;
2005
        imagep->owner = curclient;
2006
        imagep->next = listimagep;
2007
 
2008
        listimagep = imagep;
2009
        return id;
2010
#else
2011
        return 0;
2012
#endif 
2013
}
2014
 
2015
/* Draw an image from a buffer */
2016
 
2017
void
2018
GrDrawImageFromBuffer(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2019
                      GR_SIZE width, GR_SIZE height,
2020
                      void *buffer, int size, int flags)
2021
{
2022
  GR_DRAWABLE   *dp;
2023
 
2024
  switch (GsPrepareDrawing(id, gc, &dp)) {
2025
  case GR_DRAW_TYPE_WINDOW:
2026
  case GR_DRAW_TYPE_PIXMAP:
2027
    GdDrawImageFromBuffer(dp->psd, dp->x + x, dp->y + y,
2028
                        width, height, buffer, size, flags);
2029
    break;
2030
  }
2031
}
2032
 
2033
/* load image from the given buffer and cache it*/
2034
 
2035
GR_IMAGE_ID
2036
GrLoadImageFromBuffer(void *buffer, int size, int flags)
2037
{
2038
  GR_IMAGE_ID   id;
2039
  GR_IMAGE *    imagep;
2040
 
2041
  id = GdLoadImageFromBuffer(&scrdev, buffer, size, flags);
2042
  if (!id) return(0);
2043
 
2044
  imagep = (GR_IMAGE *) malloc(sizeof(GR_IMAGE));
2045
  if (imagep == NULL) {
2046
    GsError(GR_ERROR_MALLOC_FAILED, 0);
2047
    GdFreeImage(id);
2048
    return 0;
2049
  }
2050
 
2051
  imagep->id = id;
2052
  imagep->owner = curclient;
2053
  imagep->next = listimagep;
2054
 
2055
  listimagep = imagep;
2056
  return id;
2057
}
2058
 
2059
 
2060
/* draw cached image*/
2061
void
2062
GrDrawImageToFit(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2063
        GR_SIZE width, GR_SIZE height, GR_IMAGE_ID imageid)
2064
{
2065
#if defined(HAVE_FILEIO)
2066
        GR_DRAWABLE     *dp;
2067
 
2068
        switch (GsPrepareDrawing(id, gc, &dp)) {
2069
                case GR_DRAW_TYPE_WINDOW:
2070
                case GR_DRAW_TYPE_PIXMAP:
2071
                        GdDrawImageToFit(dp->psd, dp->x + x, dp->y + y,
2072
                                width, height, imageid);
2073
                        break;
2074
 
2075
        }
2076
#endif
2077
}
2078
 
2079
/* free cached image*/
2080
void
2081
GrFreeImage(GR_IMAGE_ID id)
2082
{
2083
#if defined(HAVE_FILEIO)
2084
        GR_IMAGE        *imagep;
2085
        GR_IMAGE        *previmagep;
2086
 
2087
        for (imagep = listimagep; imagep; imagep = imagep->next) {
2088
                if (imagep->id == id) {
2089
 
2090
                        if (listimagep == imagep)
2091
                                listimagep = imagep->next;
2092
                        else {
2093
                                previmagep = listimagep;
2094
                                while (previmagep->next != imagep)
2095
                                        previmagep = previmagep->next;
2096
 
2097
                                previmagep->next = imagep->next;
2098
                        }
2099
 
2100
                        GdFreeImage(imagep->id);
2101
                        free(imagep);
2102
                        return;
2103
                }
2104
        }
2105
#endif
2106
}
2107
 
2108
/* return cached image information*/
2109
void
2110
GrGetImageInfo(GR_IMAGE_ID id, GR_IMAGE_INFO *iip)
2111
{
2112
#if defined(HAVE_FILEIO)
2113
        GdGetImageInfo(id, iip);
2114
#else
2115
        memset(iip, 0, sizeof(GR_IMAGE_INFO));
2116
#endif
2117
}
2118
#endif /* !defined (DOS_DJGPP)|| (__PACIFIC__) || (DOS_TURBOC)) */
2119
 
2120
/*
2121
 * Draw a rectangular area in the specified drawable using the specified
2122
 * graphics context.  This differs from rectangle drawing in that the
2123
 * color values for each pixel in the rectangle are specified.
2124
 * The color table is indexed row by row.
2125
 */
2126
void
2127
GrArea(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, GR_SIZE width,
2128
        GR_SIZE height, void *pixels, int pixtype)
2129
{
2130
        GR_DRAWABLE     *dp;
2131
 
2132
        switch (GsPrepareDrawing(id, gc, &dp)) {
2133
                case GR_DRAW_TYPE_WINDOW:
2134
                case GR_DRAW_TYPE_PIXMAP:
2135
                        GdArea(dp->psd, dp->x + x, dp->y + y, width, height,
2136
                                pixels, pixtype);
2137
                        break;
2138
        }
2139
}
2140
 
2141
/*
2142
 * Copy a rectangle from one drawable to another or the same
2143
 */
2144
void
2145
GrCopyArea(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y,
2146
        GR_SIZE width, GR_SIZE height, GR_DRAW_ID source,
2147
        GR_COORD srcx, GR_COORD srcy, int op)
2148
{
2149
        GR_DRAWABLE     *dp;
2150
        GR_WINDOW       *swp;
2151
        GR_PIXMAP       *spp = NULL;
2152
        GR_DRAW_TYPE    type;
2153
        PSD             srcpsd;
2154
 
2155
        srcpsd = NULL;
2156
 
2157
        swp = GsFindWindow(source);
2158
        type = GsPrepareDrawing(id, gc, &dp);
2159
        if (type == GR_DRAW_TYPE_NONE)
2160
                return;
2161
 
2162
        if (swp) {
2163
                srcpsd = swp->psd;
2164
                srcx += swp->x;
2165
                srcy += swp->y;
2166
        } else {
2167
               spp = GsFindPixmap(source);
2168
               if (spp)
2169
                     srcpsd = spp->psd;
2170
        }
2171
        if (!srcpsd)
2172
                return;
2173
 
2174
#if DYNAMICREGIONS
2175
        /*
2176
         * Skip blit and send expose event if window is partly
2177
         * obscured and source and destination are onscreen.
2178
         * Also check that receiving window's first client has
2179
         * selected for expose events.  This keeps brain-dead
2180
         * programs that don't process exposure events somewhat working.
2181
         */
2182
        if (swp && (srcpsd == dp->psd) && swp->eventclients &&
2183
            (swp->eventclients->eventmask & GR_EVENT_MASK_EXPOSURE)) {
2184
                MWRECT          rc;
2185
                extern MWCLIPREGION *clipregion;
2186
 
2187
                /* clip blit rectangle to source screen/bitmap size*/
2188
                if(srcx+width > srcpsd->xvirtres)
2189
                        width = srcpsd->xvirtres - srcx;
2190
                if(srcy+height > srcpsd->yvirtres)
2191
                        height = srcpsd->yvirtres - srcy;
2192
 
2193
                rc.left = srcx;
2194
                rc.top = srcy;
2195
                rc.right = srcx + width;
2196
                rc.bottom = srcy + height;
2197
 
2198
                /*
2199
                 * if source isn't entirely within clip region, then
2200
                 * the blit is partly obscured and will copy some garbage.
2201
                 * In this case, skip the blit, punt, and deliver an
2202
                 * exposure event instead for proper display.
2203
                 */
2204
                if (GdRectInRegion(clipregion, &rc) != MWRECT_ALLIN) {
2205
                        GsDeliverExposureEvent(swp, dp->x+x, dp->y+y,
2206
                                width, height);
2207
                        return;
2208
                }
2209
        }
2210
#endif
2211
        /* perform blit*/
2212
        GdCheckCursor(srcpsd, srcx, srcy, srcx+width, srcy+height); /* FIXME*/
2213
        GdBlit(dp->psd, dp->x+x, dp->y+y, width, height, srcpsd, srcx, srcy,op);
2214
        GdFixCursor(srcpsd); /* FIXME*/
2215
}
2216
 
2217
 
2218
/*
2219
 * Read the color values from the specified rectangular area of the
2220
 * specified drawable into a supplied buffer.  If the drawable is a
2221
 * window which is obscured by other windows, then the returned values
2222
 * will include the values from the covering windows.  Regions outside
2223
 * of the screen boundaries, or unmapped windows will return black.
2224
 */
2225
void
2226
GrReadArea(GR_DRAW_ID id,GR_COORD x,GR_COORD y,GR_SIZE width,GR_SIZE height,
2227
        GR_PIXELVAL *pixels)
2228
{
2229
        GR_WINDOW       *wp;
2230
        GR_PIXMAP       *pp = NULL;
2231
 
2232
        if ((wp = GsFindWindow(id)) == NULL && (pp = GsFindPixmap(id)) == NULL){
2233
                GsError(GR_ERROR_BAD_WINDOW_ID, id);
2234
                return;
2235
        }
2236
 
2237
        if (wp != NULL) {
2238
                if (wp->unmapcount || (x >= wp->width) || (y >= wp->height) ||
2239
                   (x + width <= 0) || (y + height <= 0)) {
2240
                        /* long         count;
2241
                        * GR_PIXELVAL   black;
2242
                        *
2243
                        * black = GdFindColor(BLACK);
2244
                        * count = width * height;
2245
                        * while (count-- > 0)
2246
                        *       *pixels++ = black;
2247
                        */
2248
                        return;
2249
                }
2250
                GdReadArea(wp->psd, wp->x+x, wp->y+y, width, height, pixels);
2251
        }
2252
        if (pp != NULL) {
2253
                if ((x >= pp->width) || (y >= pp->height) ||
2254
                    (x + width <= 0) || (y + height <= 0)) {
2255
                        return;
2256
                }
2257
                GdReadArea(pp->psd, x, y, width, height, pixels);
2258
        }
2259
}
2260
 
2261
/*
2262
 * Draw a point in the specified drawable using the specified
2263
 * graphics context.
2264
 */
2265
void
2266
GrPoint(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y)
2267
{
2268
        GR_DRAWABLE     *dp;
2269
 
2270
        switch (GsPrepareDrawing(id, gc, &dp)) {
2271
                case GR_DRAW_TYPE_WINDOW:
2272
                case GR_DRAW_TYPE_PIXMAP:
2273
                        GdPoint(dp->psd, dp->x + x, dp->y + y);
2274
                        break;
2275
        }
2276
}
2277
 
2278
/*
2279
 * Draw points in the specified drawable using the specified
2280
 * graphics context.
2281
 */
2282
void
2283
GrPoints(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
2284
{
2285
        GR_DRAWABLE     *dp;
2286
        GR_POINT        *pp;
2287
        GR_COUNT        i;
2288
        PSD             psd;
2289
 
2290
        switch (GsPrepareDrawing(id, gc, &dp)) {
2291
                case GR_DRAW_TYPE_WINDOW:
2292
                case GR_DRAW_TYPE_PIXMAP:
2293
                        psd = dp->psd;
2294
                        break;
2295
                default:
2296
                        return;
2297
        }
2298
 
2299
        pp = pointtable;
2300
        for (i = count; i-- > 0; pp++) {
2301
                GdPoint(psd, pp->x + dp->x, pp->y + dp->y);
2302
        }
2303
}
2304
 
2305
/*
2306
 * Draw a polygon in the specified drawable using the specified
2307
 * graphics context.  The polygon is only complete if the first
2308
 * point is repeated at the end.
2309
 */
2310
void
2311
GrPoly(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
2312
{
2313
        GR_DRAWABLE     *dp;
2314
        GR_POINT        *pp;
2315
        GR_COUNT        i;
2316
        PSD             psd;
2317
 
2318
        switch (GsPrepareDrawing(id, gc, &dp)) {
2319
                case GR_DRAW_TYPE_WINDOW:
2320
                case GR_DRAW_TYPE_PIXMAP:
2321
                        psd = dp->psd;
2322
                        break;
2323
                default:
2324
                        return;
2325
        }
2326
 
2327
        /*
2328
         * Here for drawing to a window.
2329
         * Relocate all the points relative to the window.
2330
         */
2331
        pp = pointtable;
2332
        for (i = count; i-- > 0; pp++) {
2333
                pp->x += dp->x;
2334
                pp->y += dp->y;
2335
        }
2336
 
2337
        GdPoly(psd, count, pointtable);
2338
 
2339
#ifdef NONETWORK   
2340
        /*
2341
         * The following is only necessary when the server
2342
         * isn't a separate process.  We don't want to change the
2343
         * user's arguments!
2344
         */
2345
        pp = pointtable;
2346
        for (i = count; i-- > 0; pp++) {
2347
                pp->x -= dp->x;
2348
                pp->y -= dp->y;
2349
        }
2350
#endif
2351
}
2352
 
2353
/*
2354
 * Draw a filled polygon in the specified drawable using the specified
2355
 * graphics context.  The last point may be a duplicate of the first
2356
 * point, but this is not required.
2357
 */
2358
void
2359
GrFillPoly(GR_DRAW_ID id, GR_GC_ID gc, GR_COUNT count, GR_POINT *pointtable)
2360
{
2361
        GR_DRAWABLE     *dp;
2362
        GR_POINT        *pp;
2363
        GR_COUNT        i;
2364
        PSD             psd;
2365
 
2366
        switch (GsPrepareDrawing(id, gc, &dp)) {
2367
                case GR_DRAW_TYPE_WINDOW:
2368
                case GR_DRAW_TYPE_PIXMAP:
2369
                        psd = dp->psd;
2370
                        break;
2371
                default:
2372
                        return;
2373
        }
2374
 
2375
        /*
2376
         * Here for drawing to a window.
2377
         * Relocate all the points relative to the window.
2378
         */
2379
        pp = pointtable;
2380
        for (i = count; i-- > 0; pp++) {
2381
                pp->x += dp->x;
2382
                pp->y += dp->y;
2383
        }
2384
 
2385
        GdFillPoly(psd, count, pointtable);
2386
 
2387
#ifdef NONETWORK
2388
        /*
2389
         * The following is only necessary when the server
2390
         * isn't a separate process.  We don't want to change the
2391
         * user's arguments!
2392
         */
2393
        pp = pointtable;
2394
        for (i = count; i-- > 0; pp++) {
2395
                pp->x -= dp->x;
2396
                pp->y -= dp->y;
2397
        }
2398
#endif   
2399
}
2400
 
2401
/*
2402
 * Draw a text string in the specified drawable using the
2403
 * specified graphics context.
2404
 */
2405
void
2406
GrText(GR_DRAW_ID id, GR_GC_ID gc, GR_COORD x, GR_COORD y, void *str,
2407
        GR_COUNT count, int flags)
2408
{
2409
        GR_DRAWABLE     *dp;
2410
 
2411
        /* default to baseline alignment if none specified*/
2412
        if((flags&(MWTF_TOP|MWTF_BASELINE|MWTF_BOTTOM)) == 0)
2413
                flags |= MWTF_BASELINE;
2414
 
2415
        switch (GsPrepareDrawing(id, gc, &dp)) {
2416
                case GR_DRAW_TYPE_WINDOW:
2417
                case GR_DRAW_TYPE_PIXMAP:
2418
                        GdText(dp->psd, dp->x + x, dp->y + y, str, count,flags);
2419
                        break;
2420
        }
2421
}
2422
 
2423
/* Return the system palette entries*/
2424
void
2425
GrGetSystemPalette(GR_PALETTE *pal)
2426
{
2427
        /* return 0 count if not in palettized mode*/
2428
        memset(pal, 0, sizeof(GR_PALETTE *));
2429
 
2430
        if(rootwp->psd->pixtype == MWPF_PALETTE) {
2431
                pal->count = (int)rootwp->psd->ncolors;
2432
                GdGetPalette(rootwp->psd, 0, pal->count, pal->palette);
2433
        }
2434
}
2435
 
2436
/* Set the system palette entries from first for count*/
2437
void
2438
GrSetSystemPalette(GR_COUNT first, GR_PALETTE *pal)
2439
{
2440
        GdSetPalette(rootwp->psd, first, pal->count, pal->palette);
2441
        if (first == 0)
2442
                GsRedrawScreen();
2443
}
2444
 
2445
/* Convert passed color value to pixel value, depending on system mode*/
2446
void
2447
GrFindColor(GR_COLOR c, GR_PIXELVAL *retpixel)
2448
{
2449
        *retpixel = GdFindColor(c);
2450
}
2451
 
2452
/* visible =0, no cursor change; =1, show; else hide*/
2453
void
2454
GrInjectPointerEvent(GR_COORD x, GR_COORD y, int button, int visible)
2455
{
2456
        if (visible != 0) {
2457
                if (visible == 1)
2458
                        GdShowCursor(&scrdev);
2459
                else
2460
                        GdHideCursor(&scrdev);
2461
        }
2462
 
2463
        GdMoveMouse(x, y);
2464
        GsHandleMouseStatus(x, y, button);
2465
}
2466
 
2467
void
2468
GrInjectKeyboardEvent(GR_WINDOW_ID wid, GR_KEY keyvalue, GR_KEYMOD modifiers,
2469
        GR_SCANCODE scancode, GR_BOOL pressed)
2470
{
2471
        /* create a keyboard event */
2472
        GsDeliverKeyboardEvent(wid,
2473
                pressed? GR_EVENT_TYPE_KEY_DOWN: GR_EVENT_TYPE_KEY_UP,
2474
                keyvalue, modifiers, scancode);
2475
}
2476
 
2477
/*
2478
 * Set certain window properties, according to flags value
2479
 * passed in props.
2480
 */
2481
void
2482
GrSetWMProperties(GR_WINDOW_ID wid, GR_WM_PROPERTIES *props)
2483
{
2484
        GR_WINDOW *wp;
2485
        int tl = 0;    /* Initialized to avoid warning */
2486
 
2487
        /* Find the window structure (generate an error if it doesn't exist) */
2488
        wp = GsFindWindow(wid);
2489
        if(!wp) {
2490
                GsError(GR_ERROR_BAD_WINDOW_ID, wid);
2491
                return;
2492
        }
2493
 
2494
        /* Set window properties*/
2495
        if (props->flags & GR_WM_FLAGS_PROPS)
2496
                wp->props = props->props;
2497
 
2498
        /* Set window title*/
2499
        if (props->flags & GR_WM_FLAGS_TITLE) {
2500
                /* Remove the old title if it exists */
2501
                if(wp->title)
2502
                        free(wp->title);
2503
 
2504
                /* Calculate the space needed to store the new title */
2505
                if(props->title)
2506
                        tl = strlen(props->title) + 1;
2507
 
2508
                /* Check for empty title*/
2509
                if(!props->title || tl == 1) {
2510
                        wp->title = NULL;
2511
                } else {
2512
                        /* Otherwise, allocate some space for the new title */
2513
                        if(!(wp->title = malloc(tl)))
2514
                                GsError(GR_ERROR_MALLOC_FAILED, wid);
2515
                        else
2516
                                memcpy(wp->title, props->title, tl);
2517
                }
2518
        }
2519
 
2520
        /* Set window background*/
2521
        if (props->flags & GR_WM_FLAGS_BACKGROUND) {
2522
                if (wp->background != props->background) {
2523
                        wp->background = props->background;
2524
                        GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height,
2525
                                NULL);
2526
                }
2527
        }
2528
 
2529
        /* Set window border size*/
2530
        if (props->flags & GR_WM_FLAGS_BORDERSIZE) {
2531
                if (wp->bordersize != props->bordersize) {
2532
                        GsWpUnmapWindow(wp, GR_TRUE);
2533
                        wp->bordersize = props->bordersize;
2534
                        GsWpMapWindow(wp, GR_TRUE);
2535
                }
2536
        }
2537
 
2538
        /* Set window border color*/
2539
        if (props->flags & GR_WM_FLAGS_BORDERCOLOR) {
2540
                if (wp->bordercolor != props->bordercolor) {
2541
                        wp->bordercolor = props->bordercolor;
2542
                        if (wp->bordersize)
2543
                                GsDrawBorder(wp);
2544
                }
2545
        }
2546
}
2547
 
2548
/*
2549
 * Return all window properties
2550
 */
2551
void
2552
GrGetWMProperties(GR_WINDOW_ID wid, GR_WM_PROPERTIES *props)
2553
{
2554
        GR_WINDOW *wp;
2555
 
2556
        /* Find the window structure, no error on invalid window id*/
2557
        wp = GsFindWindow(wid);
2558
        if(!wp) {
2559
                /* set flags to 0 on bad window id*/
2560
                memset(props, 0, sizeof(GR_WM_PROPERTIES));
2561
                return;
2562
        }
2563
 
2564
        /* Return everything, regardless of props->flags*/
2565
        props->flags = GR_WM_FLAGS_PROPS | GR_WM_FLAGS_TITLE |
2566
                GR_WM_FLAGS_BACKGROUND | GR_WM_FLAGS_BORDERSIZE |
2567
                GR_WM_FLAGS_BORDERCOLOR;
2568
        props->props = wp->props;
2569
        props->title = wp->title;
2570
        props->background = wp->background;
2571
        props->bordersize = wp->bordersize;
2572
        props->bordercolor = wp->bordercolor;
2573
}
2574
 
2575
void
2576
GrCloseWindow(GR_WINDOW_ID wid)
2577
{
2578
        GR_WINDOW *wp;
2579
 
2580
        /* Find the window structure (generate an error if it doesn't exist) */
2581
        wp = GsFindWindow(wid);
2582
        if(!wp) {
2583
                /*
2584
                 * no error for now, client/server problems
2585
                 * with nxwm when sent
2586
                 */
2587
                /*GsError(GR_ERROR_BAD_WINDOW_ID, wid);*/
2588
                return;
2589
        }
2590
 
2591
        /* Send a CLOSE_REQ event to the client */
2592
        GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_CLOSE_REQ, NULL);
2593
}
2594
 
2595
void
2596
GrKillWindow(GR_WINDOW_ID wid)
2597
{
2598
        GR_WINDOW *wp;
2599
 
2600
        /* Find the window structure (generate an error if it doesn't exist) */
2601
        wp = GsFindWindow(wid);
2602
        if(!wp) {
2603
                GsError(GR_ERROR_BAD_WINDOW_ID, wid);
2604
                return;
2605
        }
2606
 
2607
        /* Forcibly kill the connection to the client */
2608
        GsClose(wp->owner->id);
2609
}
2610
 
2611
/*
2612
 * GrGetSystemColor color scheme definitions
2613
 */
2614
/* define color scheme: A (tan), B (winstd) or C (old)*/
2615
#define A
2616
 
2617
#define A_RGB(r,g,b)
2618
#define B_RGB(r,g,b)
2619
#define C_RGB(r,g,b)
2620
 
2621
#ifdef A
2622
#undef  A_RGB
2623
#define A_RGB(r,g,b)    GR_RGB(r,g,b),
2624
#endif
2625
#ifdef B
2626
#undef  B_RGB
2627
#define B_RGB(r,g,b)    GR_RGB(r,g,b),
2628
#endif
2629
#ifdef C
2630
#undef  C_RGB
2631
#define C_RGB(r,g,b)    GR_RGB(r,g,b),
2632
#endif
2633
 
2634
#define MAXSYSCOLORS    20      /* # of GR_COLOR_* system colors*/
2635
 
2636
static GR_COLOR sysColors[MAXSYSCOLORS] = {
2637
        /* desktop background*/
2638
        GR_RGB(  0, 128, 128),  /* GR_COLOR_DESKTOP             */
2639
 
2640
        /* caption colors*/
2641
        A_RGB(128,   0,   0)      /* GR_COLOR_ACTIVECAPTION       */
2642
        B_RGB(128,   0, 128)     /* GR_COLOR_ACTIVECAPTION       */
2643
        C_RGB(128,   0, 128)     /* GR_COLOR_ACTIVECAPTION       */
2644
        GR_RGB(255, 255, 255),  /* GR_COLOR_ACTIVECAPTIONTEXT   */
2645
        A_RGB(162, 141, 104)    /* GR_COLOR_INACTIVECAPTION     */
2646
        B_RGB(128, 128, 128)    /* GR_COLOR_INACTIVECAPTION     */
2647
        C_RGB(  0,  64, 128)     /* GR_COLOR_INACTIVECAPTION     */
2648
        GR_RGB(192, 192, 192),  /* GR_COLOR_INACTIVECAPTIONTEXT */
2649
 
2650
        /* 3d border shades*/
2651
        GR_RGB(  0,   0,   0),  /* GR_COLOR_WINDOWFRAME         */
2652
        A_RGB(162, 141, 104)    /* GR_COLOR_BTNSHADOW           */
2653
        B_RGB(128, 128, 128)    /* GR_COLOR_BTNSHADOW           */
2654
        C_RGB(128, 128, 128)    /* GR_COLOR_BTNSHADOW           */
2655
        A_RGB(213, 204, 187)    /* GR_COLOR_3DLIGHT             */
2656
        B_RGB(223, 223, 223)    /* GR_COLOR_3DLIGHT             */
2657
        C_RGB(192, 192, 192)    /* GR_COLOR_3DLIGHT             */
2658
        A_RGB(234, 230, 221)    /* GR_COLOR_BTNHIGHLIGHT        */
2659
        B_RGB(255, 255, 255)    /* GR_COLOR_BTNHIGHLIGHT        */
2660
        C_RGB(223, 223, 223)    /* GR_COLOR_BTNHIGHLIGHT        */
2661
 
2662
        /* top level application window backgrounds/text*/
2663
        A_RGB(213, 204, 187)    /* GR_COLOR_APPWINDOW           */
2664
        B_RGB(192, 192, 192)    /* GR_COLOR_APPWINDOW           */
2665
        C_RGB(160, 160, 160)    /* GR_COLOR_APPWINDOW           */
2666
        GR_RGB(  0,   0,   0),  /* GR_COLOR_APPTEXT             */
2667
 
2668
        /* button control backgrounds/text (usually same as app window colors)*/
2669
        A_RGB(213, 204, 187)    /* GR_COLOR_BTNFACE             */
2670
        B_RGB(192, 192, 192)    /* GR_COLOR_BTNFACE             */
2671
        C_RGB(160, 160, 160)    /* GR_COLOR_BTNFACE             */
2672
        GR_RGB(  0,   0,   0),  /* GR_COLOR_BTNTEXT             */
2673
 
2674
        /* edit/listbox control backgrounds/text, selected highlights*/
2675
        GR_RGB(255, 255, 255),  /* GR_COLOR_WINDOW              */
2676
        GR_RGB(  0,   0,   0),  /* GR_COLOR_WINDOWTEXT          */
2677
        GR_RGB(128,   0,   0),  /* GR_COLOR_HIGHLIGHT           */
2678
        GR_RGB(255, 255, 255),  /* GR_COLOR_HIGHLIGHTTEXT       */
2679
        GR_RGB( 64,  64,  64),  /* GR_COLOR_GRAYTEXT            */
2680
 
2681
        /* menu backgrounds/text*/
2682
        A_RGB(213, 204, 187)    /* GR_COLOR_MENU                */
2683
        B_RGB(192, 192, 192)    /* GR_COLOR_MENU                */
2684
        C_RGB(160, 160, 160)    /* GR_COLOR_MENU                */
2685
        GR_RGB(  0,   0,   0),  /* GR_COLOR_MENUTEXT            */
2686
};
2687
 
2688
/* Return system-defined color*/
2689
GR_COLOR
2690
GrGetSysColor(int index)
2691
{
2692
        if(index >= 0 && index < MAXSYSCOLORS)
2693
                return sysColors[index];
2694
        return 0;
2695
}
2696
 
2697
void
2698
GrSetScreenSaverTimeout(GR_TIMEOUT timeout)
2699
{
2700
        MWTIMER *timer;
2701
 
2702
        screensaver_delay = timeout * 1000;
2703
 
2704
        if((timer = GdFindTimer(GsActivateScreenSaver)))
2705
                GdDestroyTimer(timer);
2706
 
2707
        /* 0 timeout cancels timer*/
2708
        if (timeout == 0)
2709
                return;
2710
 
2711
        GdAddTimer(screensaver_delay, GsActivateScreenSaver,
2712
                                        GsActivateScreenSaver);
2713
}
2714
 
2715
void
2716
GrSetSelectionOwner(GR_WINDOW_ID wid, GR_CHAR *typelist)
2717
{
2718
        GR_WINDOW_ID oldwid = selection_owner.wid;
2719
 
2720
        if(selection_owner.typelist) free(selection_owner.typelist);
2721
 
2722
        selection_owner.wid = wid;
2723
 
2724
        if(wid) {
2725
                if(!(selection_owner.typelist = strdup(typelist))) {
2726
                        GsError(GR_ERROR_MALLOC_FAILED, wid);
2727
                        selection_owner.wid = 0;
2728
                }
2729
        } else selection_owner.typelist = NULL;
2730
 
2731
        GsDeliverSelectionChangedEvent(oldwid, wid);
2732
}
2733
 
2734
GR_WINDOW_ID
2735
GrGetSelectionOwner(GR_CHAR **typelist)
2736
{
2737
        *typelist = selection_owner.typelist;
2738
        return selection_owner.wid;
2739
}
2740
 
2741
void
2742
GrRequestClientData(GR_WINDOW_ID wid, GR_WINDOW_ID rid, GR_SERIALNO serial,
2743
                                                        GR_MIMETYPE mimetype)
2744
{
2745
        GsDeliverClientDataReqEvent(rid, wid, serial, mimetype);
2746
}
2747
 
2748
void
2749
GrSendClientData(GR_WINDOW_ID wid, GR_WINDOW_ID did, GR_SERIALNO serial,
2750
                                GR_LENGTH len, GR_LENGTH thislen, void *data)
2751
{
2752
        void *p;
2753
 
2754
        if(!(p = malloc(len))) {
2755
                GsError(GR_ERROR_MALLOC_FAILED, wid);
2756
                return;         /* FIXME note no error to application*/
2757
        }
2758
        memcpy(p, data, thislen);
2759
 
2760
        GsDeliverClientDataEvent(did, wid, serial, len, thislen, p);
2761
}
2762
 
2763
/*
2764
 * Set a window's background pixmap.  Note that this doesn't
2765
 * cause a screen refresh, use GrClearWindow if required.
2766
 */
2767
void
2768
GrSetBackgroundPixmap(GR_WINDOW_ID wid, GR_WINDOW_ID pixmap, int flags)
2769
{
2770
        GR_WINDOW *wp;
2771
        GR_PIXMAP *pp = NULL;
2772
 
2773
        if (!(wp = GsFindWindow(wid))) {
2774
                GsError(GR_ERROR_BAD_WINDOW_ID, wid);
2775
                return;
2776
        }
2777
 
2778
        if (pixmap && !(pp = GsFindPixmap(pixmap))) {
2779
                GsError(GR_ERROR_BAD_WINDOW_ID, pixmap);
2780
                return;
2781
        }
2782
        wp->bgpixmap = pp;
2783
        wp->bgpixmapflags = flags;
2784
}
2785
 
2786
void
2787
GrGetFontList(GR_FONTLIST ***fonts, int *numfonts)
2788
{
2789
        GdGetFontList(fonts,numfonts);
2790
}
2791
 
2792
void
2793
GrFreeFontList(GR_FONTLIST ***fonts, int num)
2794
{
2795
        GdFreeFontList(fonts, num);
2796
}
2797
 
2798
/*
2799
 * Return window parent and list of children.
2800
 * Caller must free() children list after use.
2801
 */
2802
void
2803
GrQueryTree(GR_WINDOW_ID wid, GR_WINDOW_ID *parentid, GR_WINDOW_ID **children,
2804
        GR_COUNT *nchildren)
2805
{
2806
        GR_WINDOW       *wp;
2807
        GR_WINDOW       *cp;
2808
        GR_WINDOW_ID    *retarray;
2809
        GR_COUNT        n = 0;
2810
 
2811
        wp = GsFindWindow(wid);
2812
        if (!wp) {
2813
                *parentid = 0;
2814
nochildren:
2815
                *children = NULL;
2816
                *nchildren = 0;
2817
                return;
2818
        }
2819
        *parentid = wp->parent? wp->parent->id: 0;
2820
 
2821
        /* count children for alloc*/
2822
        for(cp=wp->children; cp; cp=cp->siblings)
2823
                ++n;
2824
        if (n == 0)
2825
                goto nochildren;
2826
 
2827
        /* alloc return child array*/
2828
        retarray = (GR_WINDOW_ID *)malloc(n * sizeof(GR_WINDOW_ID));
2829
        if (!retarray) {
2830
                GsError(GR_ERROR_MALLOC_FAILED, 0);
2831
                goto nochildren;
2832
        }
2833
 
2834
        /* fill in return array*/
2835
        n = 0;
2836
        for(cp=wp->children; cp; cp=cp->siblings) {
2837
                retarray[n++] = cp->id;
2838
        }
2839
        *children = retarray;
2840
        *nchildren = n;
2841
}
2842
 
2843
 
2844
static int next_timer_id = 1000;
2845
 
2846
/**
2847
 * GrCreateTimer:
2848
 * @wid: the ID of the window to use as a destination for GR_TIMER_EVENT
2849
 *      events that result from this timer.
2850
 * @period: the timer period in milliseconds
2851
 * @Returns: the ID of the newly created timer, or 0 if failure.
2852
 *
2853
 * Creates a Nano-X timer with the specified period.
2854
 * NOTE: There is a potential for more GR_TIMER_EVENTS to be queued
2855
 * in the connection between the Nano-X server and client.  The client
2856
 * should be able to handle late arriving GR_TIMER_EVENTs.
2857
 */
2858
GR_TIMER_ID
2859
GrCreateTimer (GR_WINDOW_ID wid, GR_TIMEOUT period)
2860
{
2861
    GR_TIMER  *timer;
2862
 
2863
    /* Create a nano-X layer timr */
2864
    timer = (GR_TIMER*) malloc (sizeof (GR_TIMER));
2865
    if (timer == NULL)
2866
    {
2867
        GsError (GR_ERROR_MALLOC_FAILED, 0);
2868
        return 0;
2869
    }
2870
 
2871
    /* Create a device independent layer timer */
2872
    timer->timer = GdAddPeriodicTimer (period, GsTimerCB, timer);
2873
    if (timer->timer == NULL)
2874
    {
2875
        free (timer);
2876
        GsError (GR_ERROR_MALLOC_FAILED, 0);
2877
        return 0;
2878
    }
2879
 
2880
    /*
2881
     * Fill in the rest of the timer structure, and
2882
     * link the new timer into the servers list of timers.
2883
     */
2884
    timer->id    = next_timer_id++;
2885
    timer->owner = curclient;
2886
    timer->wid   = wid;
2887
    timer->next  = list_timer;
2888
    list_timer   = timer;
2889
 
2890
    return timer->id;
2891
}
2892
 
2893
/**
2894
 * GrDestroyTimer:
2895
 * @tid: the ID of the timer to destroy
2896
 *
2897
 * Destroys a timer previously created with GrCreateTimer().
2898
 */
2899
void
2900
GrDestroyTimer (GR_TIMER_ID tid)
2901
{
2902
    GR_TIMER  *timer;
2903
    GR_TIMER  *prev_timer;
2904
 
2905
    /* Find the timer structure that corresponds to "tid" */
2906
    timer = GsFindTimer (tid);
2907
    if (timer == NULL)
2908
        return;
2909
 
2910
    if (tid == cache_timer_id)
2911
    {
2912
        cache_timer_id = 0;
2913
        cache_timer = NULL;
2914
    }
2915
 
2916
    /* Delete the timer from the device independent engine layer */
2917
    GdDestroyTimer (timer->timer);
2918
 
2919
    /* Pull the timer out of the servers list */
2920
    if (list_timer == timer)
2921
    {
2922
        list_timer = timer->next;
2923
    }
2924
    else
2925
    {
2926
        prev_timer = list_timer;
2927
        while (prev_timer->next != timer)
2928
        {
2929
            prev_timer = prev_timer->next;
2930
        }
2931
        prev_timer->next = timer->next;
2932
    }
2933
    free (timer);
2934
}
2935
 
2936
/**
2937
 * GrSetPortraitMode
2938
 * @newmode: new portrait mode
2939
 *
2940
 * Sets new server portrait mode and redraws all windows.
2941
 */
2942
void
2943
GrSetPortraitMode(int portraitmode)
2944
{
2945
        GsSetPortraitMode(portraitmode);
2946
}

powered by: WebSVN 2.1.0

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