The R Project SVN R

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4394 ripley 1
/*
2
 * GraphApp - Cross-Platform Graphics Programming Library.
3
 *
4
 * File: controls.c -- manipulating scrollbars, buttons, etc.
5
 * Platform: Windows  Version: 2.40  Date: 1998/04/04
6
 *
7
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
8
 * Version: 1.60  Changes: Added clear(), draw(), flashcontrol().
9
 * Version: 2.00  Changes: New object class system.
10
 * Version: 2.15  Changes: Transparent backgrounds added.
11
 * Version: 2.20  Changes: Non-native buttons supported.
12
 * Version: 2.35  Changes: New reference count technique.
13
 * Version: 2.40  Changes: Support for new controls.
14
 */
15
 
16
/* Copyright (C) 1993-1998 Lachlan Patrick
17
 
18
   This file is part of GraphApp, a cross-platform C graphics library.
19
 
20
   GraphApp is free software; you can redistribute it and/or modify it
24283 ripley 21
   under the terms of the GNU Library General Public License.
4394 ripley 22
   GraphApp is distributed in the hope that it will be useful, but
23
   WITHOUT ANY WARRANTY.
24
 
25
   See the file COPYLIB.TXT for details.
26
*/
27
 
9184 ripley 28
/*  Changes for R:
29
 
30
    sort out resize (confused screen and client coords)
31
    add printer and metafile handling
32
 
33
 */
34
 
4394 ripley 35
#include "internal.h"
36
 
37
/*
38
 *  Setting control call-backs.
39
 */
40
void setaction(control obj, actionfn fn)
41
{
42
	if (obj)
43
		obj->action = fn;
44
}
45
 
46
void sethit(control obj, intfn fn)
47
{
48
	if (obj)
49
		obj->hit = fn;
50
}
51
 
52
void setdel(control obj, actionfn fn)
53
{
54
	if (obj)
55
		if (obj->call)
56
			obj->call->die = fn;
57
}
58
 
59
void setclose(control obj, actionfn fn)
60
{
61
	if (obj)
62
		if (obj->call)
63
			obj->call->close = fn;
64
}
65
 
66
void setredraw(control obj, drawfn fn)
67
{
68
	if (obj)
69
		if (obj->call)
70
			obj->call->redraw = fn;
71
}
72
 
73
void setresize(control obj, drawfn fn)
74
{
75
	if (obj)
76
		if (obj->call)
77
			obj->call->resize = fn;
78
}
79
 
80
void setkeydown(control obj, keyfn fn)
81
{
82
	if (obj)
83
		if (obj->call)
84
			obj->call->keydown = fn;
85
}
86
 
87
void setkeyaction(control obj, keyfn fn)
88
{
89
	if (obj)
90
		if (obj->call)
91
			obj->call->keyaction = fn;
92
}
93
 
94
void setmousedown(control obj, mousefn fn)
95
{
96
	if (obj)
97
		if (obj->call)
98
			obj->call->mousedown = fn;
99
}
100
 
101
void setmouseup(control obj, mousefn fn)
102
{
103
	if (obj)
104
		if (obj->call)
105
			obj->call->mouseup = fn;
106
}
107
 
108
void setmousemove(control obj, mousefn fn)
109
{
110
	if (obj)
111
		if (obj->call)
112
			obj->call->mousemove = fn;
113
}
114
 
115
void setmousedrag(control obj, mousefn fn)
116
{
117
	if (obj)
118
		if (obj->call)
119
			obj->call->mousedrag = fn;
120
}
121
 
122
void setmouserepeat(control obj, mousefn fn)
123
{
124
	if (obj)
125
		if (obj->call)
126
			obj->call->mouserepeat = fn;
127
}
128
 
14086 ripley 129
void setdrop(control obj, dropfn fn)
130
{
131
	if (obj)
132
	    if (obj->call) {
133
		DragAcceptFiles(obj->handle, TRUE);
134
		obj->call->drop = fn;
135
	    }
136
}
137
 
138
 
4394 ripley 139
/*
140
 *  Drawing controls and windows.
141
 */
142
void clear(control obj)
143
{
144
	drawing prev;
145
	rgb old;
146
 
147
	if (! obj)
148
		return;
149
	if (! isvisible(obj))
150
		return;
151
	if (! isvisible(parentwindow(obj)))
152
		return;
153
	if (obj->bg == Transparent)
154
		return;
155
	prev = current->dest;
156
	drawto(obj);
157
	old = currentrgb();
158
	setrgb(obj->bg);
159
	fillrect(getrect(obj));
160
	setrgb(old);
161
	drawto(prev);
162
}
163
 
164
void draw(control obj)
165
{
166
	drawing prev;
167
	drawstate old;
168
 
169
	if (! obj)
170
		return;
171
	if (obj->kind == MenubarObject) {
172
		DrawMenuBar(obj->parent->handle);
173
		return;
174
	}
175
 
176
	if (! isvisible(obj))
177
		return;
178
	if (! isvisible(parentwindow(obj)))
179
		return;
180
	if ((obj->call == NULL) || (obj->call->redraw == NULL))
181
		return;
182
	prev = current->dest;
183
	drawto(obj);
184
	old = copydrawstate();
185
	moveto(pt(0,0));
186
	obj->call->redraw(obj, getrect(obj));
187
	restoredrawstate(old);
188
	drawto(prev);
189
}
190
 
191
void redraw(control obj)
192
{
193
	clear(obj);
194
	draw(obj);
195
}
196
 
9236 ripley 197
/*  void getscreenrect(control obj, rect *r) */
198
/*  { */
199
/*      RECT W; */
200
/*      GetWindowRect(obj->handle, &W); */
201
/*      r->x = W.left; */
202
/*      r->y = W.top; */
203
/*      r->width = W.right - W.left; */
204
/*      r->height = W.bottom - W.top; */
205
/*  } */
9044 ripley 206
 
207
 
8706 ripley 208
/* The original here used GetWindowRect (which used screen coordinates)
209
   and MoveWindow (which uses client coordinates) so got the positioning
210
   hopelessly wrong.  This version works for WindowObjects, but I would be
211
   suspicious of it for other cases.  BDR 2000/04/05
212
*/
4394 ripley 213
void resize(control obj, rect r)
214
{
8707 ripley 215
        RECT R;
8706 ripley 216
	WINDOWPLACEMENT W;
217
	int dw, dh, dx, dy;
4394 ripley 218
 
219
	if (! obj)
220
		return;
221
	r = rcanon(r);
222
	if (obj->kind == WindowObject) {
8706 ripley 223
	        W.length = sizeof(WINDOWPLACEMENT);
4394 ripley 224
		r.x = obj->rect.x;
225
		r.y = obj->rect.y;
8706 ripley 226
		if (!equalr(r, obj->rect)) {
227
			GetWindowPlacement(obj->handle, &W);
24283 ripley 228
			if (!isvisible(obj)) W.showCmd = SW_HIDE;  /* stops the resize from revealing the window */
8706 ripley 229
			dx = r.x - obj->rect.x;
230
			dy = r.y - obj->rect.y;
8707 ripley 231
			/* don't believe current sizes!
8706 ripley 232
			dw = r.width - obj->rect.width;
233
			dh = r.height - obj->rect.height;
8707 ripley 234
			Rprintf("dw %d dh %d\n", dw, dh); */
235
			GetClientRect(obj->handle, &R);
236
			dw = r.width - (R.right - R.left);
237
			dh = r.height - (R.bottom - R.top);
8706 ripley 238
			W.rcNormalPosition.left += dx;
239
			W.rcNormalPosition.top += dy;
240
			W.rcNormalPosition.right += dx + dw;
241
			W.rcNormalPosition.bottom += dy + dh;
242
			SetWindowPlacement(obj->handle, &W);
4394 ripley 243
		}
244
	}
245
	else {
246
		if (! equalr(r, obj->rect))
247
			MoveWindow(obj->handle, r.x, r.y, r.width, r.height, 1);
248
		obj->rect.x = r.x;
249
		obj->rect.y = r.y;
250
	}
251
	obj->rect.width = r.width;
252
	obj->rect.height = r.height;
253
}
254
 
255
/*
256
 *  Showing and hiding controls and windows.
257
 */
258
void show(control obj)
259
{
260
	if (! obj)
261
		return;
262
	switch (obj->kind)
263
	{
264
	case CursorObject: case FontObject: case BitmapObject:
265
	case MenubarObject: case MenuObject: case MenuitemObject:
266
		break;
267
	case WindowObject:
268
		obj->state |= Visible;
269
		show_window(obj);
270
		break;
271
	default:
272
		ShowWindow(obj->handle, SW_SHOWNORMAL);
273
		SetFocus(obj->handle);
274
		UpdateWindow(obj->handle);
275
	}
276
	obj->state |= Visible;
277
}
278
 
279
void hide(control obj)
280
{
281
	if (! obj)
282
		return;
283
	switch (obj->kind)
284
	{
285
	case CursorObject: case FontObject: case BitmapObject:
286
	case MenubarObject: case MenuObject: case MenuitemObject:
287
		break;
288
	case WindowObject:
289
		hide_window(obj);
290
		break;
291
	default:
292
		ShowWindow(obj->handle, SW_HIDE);
293
	}
294
	obj->state &= ~Visible;
295
}
296
 
297
int isvisible(control obj)
298
{
299
	if (! obj)
300
		return 0;
301
	return (obj->state & Visible) ? 1 : 0;
302
}
303
 
304
/*
305
 *  Enabling and disabling controls and windows.
306
 */
307
void enable(control obj)
308
{
309
	if (! obj)
310
		return;
311
	switch (obj->kind)
312
	{
313
	case CursorObject: case FontObject: case BitmapObject:
314
	case MenubarObject:
315
		break;
316
	case MenuObject: case MenuitemObject:
317
		EnableMenuItem(obj->parent->handle,
318
			obj->id, MF_ENABLED | MF_BYCOMMAND);
319
		break;
320
	case FieldObject: case TextboxObject:
321
		sendmessage(obj->handle, EM_SETREADONLY, FALSE, 0L);
322
		break;
323
	default:
324
		if (! isenabled(obj)) {
325
			EnableWindow(obj->handle, 1);
326
			obj->state |= Enabled;
327
			draw(obj);
328
		}
329
	}
330
	obj->state |= Enabled;
331
}
332
 
333
void disable(control obj)
334
{
335
	if (! obj)
336
		return;
337
	switch (obj->kind)
338
	{
339
	case CursorObject: case FontObject: case BitmapObject:
340
	case MenubarObject: case MenuObject:
341
		break;
342
	case MenuitemObject:
343
		EnableMenuItem(obj->parent->handle,
344
			obj->id, MF_GRAYED | MF_BYCOMMAND);
345
		break;
346
	case FieldObject: case TextboxObject:
347
		sendmessage(obj->handle, EM_SETREADONLY, TRUE, 0L);
348
		break;
349
	default:
350
		if (isenabled(obj)) {
351
			EnableWindow(obj->handle, 0);
352
			obj->state &= ~Enabled;
353
			draw(obj);
354
		}
355
	}
356
	obj->state &= ~Enabled;
357
}
358
 
359
int isenabled(control obj)
360
{
361
	if (! obj)
362
		return 0;
363
	return (obj->state & Enabled) ? 1 : 0;
364
}
365
 
366
/*
367
 *  Checking and unchecking controls.
368
 */
369
void check(control obj)
370
{
371
	if (! obj)
372
		return;
373
	switch (obj->kind)
374
	{
375
	case CursorObject: case FontObject: case BitmapObject:
376
	case MenubarObject: case MenuObject:
377
		break;
378
	case MenuitemObject:
379
		CheckMenuItem(obj->parent->handle, obj->id,
380
			MF_CHECKED | MF_BYCOMMAND);
381
		break;
382
#if USE_NATIVE_BUTTONS
383
	case ButtonObject:
384
		sendmessage(obj->handle, BM_SETCHECK, 1, 0L);
385
		break;
386
#endif
387
#if USE_NATIVE_TOGGLES
388
	case CheckboxObject: case RadioObject:
389
		sendmessage(obj->handle, BM_SETCHECK, 1, 0L);
390
		break;
391
#endif
392
	default:
393
		if (! ischecked(obj)) {
394
			obj->state |= Checked;
395
			draw(obj);
396
		}
397
	}
398
	obj->state |= Checked;
399
}
400
 
401
void uncheck(control obj)
402
{
403
	if (! obj)
404
		return;
405
	switch (obj->kind)
406
	{
407
	case CursorObject: case FontObject: case BitmapObject:
408
	case MenubarObject: case MenuObject:
409
		break;
410
	case MenuitemObject:
411
		CheckMenuItem(obj->parent->handle, obj->id,
412
			MF_UNCHECKED | MF_BYCOMMAND);
413
		break;
414
#if USE_NATIVE_BUTTONS
415
	case ButtonObject:
416
		sendmessage(obj->handle, BM_SETCHECK, 0, 0L);
417
		break;
418
#endif
419
#if USE_NATIVE_TOGGLES
420
	case CheckboxObject: case RadioObject:
421
		sendmessage(obj->handle, BM_SETCHECK, 0, 0L);
422
		break;
423
#endif
424
	default:
425
		if (ischecked(obj)) {
426
			obj->state &= ~Checked;
427
			draw(obj);
428
		}
429
	}
430
	obj->state &= ~Checked;
431
}
432
 
433
int ischecked(control obj)
434
{
435
	if (! obj)
436
		return 0;
437
	return (obj->state & Checked) ? 1 : 0;
438
}
439
 
440
/*
441
 *  Highlighting and unhighlighting controls.
442
 */
443
void highlight(control obj)
444
{
445
	if (! obj)
446
		return;
447
	switch (obj->kind)
448
	{
449
	case CursorObject: case FontObject: case BitmapObject:
450
	case MenubarObject: case MenuObject: case MenuitemObject:
451
		break;
452
#if USE_NATIVE_BUTTONS
453
	case ButtonObject:
454
		sendmessage(obj->handle, BM_SETSTATE, 1, 0L);
455
		break;
456
#endif
457
#if USE_NATIVE_TOGGLES
458
	case CheckboxObject: case RadioObject:
459
		sendmessage(obj->handle, BM_SETSTATE, 1, 0L);
460
		break;
461
#endif
462
	case FieldObject: case TextboxObject:
463
		sendmessage(obj->handle, EM_SETSEL, 0, MAKELONG(0,-1));
464
		break;
465
	default:
466
		if (! ishighlighted(obj)) {
467
			obj->state |= Highlighted;
468
			draw(obj);
469
		}
470
	}
471
	obj->state |= Highlighted;
472
}
473
 
474
void unhighlight(control obj)
475
{
476
	if (! obj)
477
		return;
478
	switch (obj->kind)
479
	{
480
	case CursorObject: case FontObject: case BitmapObject:
481
	case MenubarObject: case MenuObject: case MenuitemObject:
482
		break;
483
#if USE_NATIVE_BUTTONS
484
	case ButtonObject:
485
		sendmessage(obj->handle, BM_SETSTATE, 0, 0L);
486
		break;
487
#endif
488
#if USE_NATIVE_TOGGLES
489
	case CheckboxObject: case RadioObject:
490
		sendmessage(obj->handle, BM_SETSTATE, 0, 0L);
491
		break;
492
#endif
493
	case FieldObject: case TextboxObject:
494
		sendmessage(obj->handle, EM_SETSEL, 0, MAKELONG(0,0));
495
		break;
496
	default:
497
		if (ishighlighted(obj)) {
498
			obj->state &= ~Highlighted;
499
			draw(obj);
500
		}
501
	}
502
	obj->state &= ~Highlighted;
503
}
504
 
505
int ishighlighted(control obj)
506
{
507
	if (! obj)
508
		return 0;
509
	return (obj->state & Highlighted) ? 1 : 0;
510
}
511
 
512
/*
513
 *  The flashcontrol function highlights a control as if the user
514
 *  just used it, e.g. a button will become pressed down for a
515
 *  moment. Used in conjunction with activatecontrol() below,
516
 *  it can simulate a mouse-click on a button.
517
 */
518
void flashcontrol(control obj)
519
{
520
	highlight(obj);
521
	delay(150);
522
	unhighlight(obj);
523
}
524
 
525
/*
526
 *  The activatecontrol function is really useful. It causes
527
 *  a variety of controls to call their 'action functions.'
528
 *
529
 *  There are two types of action functions which a control can use.
530
 *  The first (obj->action) takes one argument, the control itself,
531
 *  and is used in buttons, checkboxes and the like as a response
532
 *  to a user clicking on these controls. The second function,
533
 *  (obj->hit) function, takes two arguments: the control and its
534
 *  current 'value'. A scrollbar's value changes as the user scrolls,
535
 *  and so its hit function is called whenever that happens.
536
 *
537
 *  The activatecontrol function tries to call the action function,
538
 *  and if that doesn't exist, calls the hit function, passing the
539
 *  object's value to it.
540
 */
541
void activatecontrol(control obj)
542
{
543
	if (! obj)
544
		return;
545
	drawto(obj);
546
	if (obj->action != NULL)
547
		obj->action(obj);
548
	else if (obj->hit != NULL)
549
		obj->hit(obj, obj->value);
550
}
551
 
552
/*
553
 *  Changing and determining the state of an object.
554
 *  These functions do not automatically redraw the object.
555
 */
556
#if 0
557
void setstate(control obj, long state)
558
{
559
	if (obj)
560
		obj->state = state;
561
}
562
 
563
long getstate(control obj)
564
{
565
	if (obj)
566
		return obj->state;
567
	else
568
		return 0;
569
}
570
#endif
571
 
572
void setvalue(control obj, int value)
573
{
574
	if (obj)
575
		obj->value = value;
576
}
577
 
578
int getvalue(control obj)
579
{
580
	if (obj)
581
		return obj->value;
582
	else
583
		return 0;
584
}
585
 
586
void setforeground(control obj, rgb fg)
587
{
588
	if (! obj)
589
		return;
590
	obj->fg = fg;
591
	InvalidateRect(obj->handle, NULL, TRUE);
592
	redraw(obj);
593
}
594
 
595
rgb getforeground(control obj)
596
{
597
	if (obj)
598
		return obj->fg;
599
	else
600
		return Black;
601
}
602
 
603
void setbackground(control obj, rgb bg)
604
{
605
#if USE_NATIVE_CONTROLS
606
	COLORREF wincolour;
607
 
21104 ripley 608
	wincolour = RGB((bg&gaRed)>>16,(bg&gaGreen)>>8,(bg&gaBlue));
4394 ripley 609
 
610
	if (! obj)
611
		return;
612
	if (obj->bgbrush)
613
		DeleteObject(obj->bgbrush);
614
	obj->bgbrush = CreateSolidBrush(wincolour);
615
#endif
616
	if (! obj)
617
		return;
618
	obj->bg = bg;
619
	InvalidateRect(obj->handle, NULL, TRUE);
620
	redraw(obj);
621
}
622
 
623
rgb getbackground(control obj)
624
{
625
	if (obj)
626
		return obj->bg;
627
	else
628
		return Transparent;
629
}
630
 
631
void setdata(control obj, void *data)
632
{
633
	if (obj)
634
		obj->data = data;
635
}
636
 
637
void *getdata(control obj)
638
{
639
	if (obj)
640
		return obj->data;
641
	else
642
		return NULL;
643
}
644
 
645
void _setextradata(control obj, void *data)
646
{
647
	if (obj)
648
		obj->extra = data;
649
}
650
 
651
void *_getextradata(control obj)
652
{
653
	if (obj)
654
		return obj->extra;
655
	else
656
		return NULL;
657
}
658
 
659
/*
660
 *  Set the text of an object. This will set the names appearing
661
 *  in a window's title bar, a button, checkbox or radio button,
662
 *  or the value in a textbox or a text field.
663
 */
664
void settext(control obj, char *text)
665
{
666
	if (! obj)
667
		return;
668
	if (! text)
669
		text = "";
670
	if (strcmp(gettext(obj), text) == 0)
671
		return; /* no changes to be made */
672
	if (obj->text) {
673
		/* discard prior information */
674
		discard(obj->text);
675
		obj->text = NULL;
676
	}
677
	/* Set the new text. */
678
	obj->text = new_string(text);
679
	if (text) {
680
		if (obj->kind & ControlObject) {
681
			text = to_dos_string(text);
682
			SetWindowText(obj->handle, text);
683
			discard(text);
684
		}
685
                if (obj->kind==MenuitemObject) {
686
                        ModifyMenu(obj->parent->handle, obj->id,
687
                                   MF_BYCOMMAND|MF_STRING,obj->id,
688
                                   text);
689
                }
690
 
691
	}
692
	/* Redraw it if it's a redrawable object. */
693
	if (obj->call && obj->call->redraw)
694
		redraw(obj);
695
}
696
 
697
/*
698
 *  Get the text string from a window's title bar or from a
699
 *  control. This may be a button's name, for example, or
700
 *  the value inside a text field.
701
 */
702
char *gettext(control obj)
703
{
704
	static char *empty = "";
705
	char *text;
706
	int length, index;
707
	HWND hwnd;
708
	UINT len_msg, gettext_msg;
709
	WPARAM arg1, arg2;
710
 
711
	if (! obj)
712
		return empty;
713
	if ((obj->kind & ControlObject) == 0)
714
		return obj->text ? obj->text : empty;
715
 
716
	hwnd = obj->handle;
717
 
718
	switch (obj->kind) {
719
	  case ListboxObject:
720
	  case MultilistObject:
721
		len_msg = LB_GETTEXTLEN;
722
		gettext_msg = LB_GETTEXT;
723
		index = getlistitem(obj);
724
		if (index < 0) return empty;
725
		arg1 = arg2 = index;
726
		break;
727
	  case DroplistObject:
728
		len_msg = CB_GETLBTEXTLEN;
729
		gettext_msg = CB_GETLBTEXT;
730
		index = getlistitem(obj);
731
		if (index < 0) return empty;
732
		arg1 = arg2 = index;
733
		break;
734
	  case DropfieldObject:
735
		// use default mechanism
736
	  default:
737
		len_msg = WM_GETTEXTLENGTH;
738
		gettext_msg = WM_GETTEXT;
739
		arg1 = 0;
740
		arg2 = sendmessage(hwnd, len_msg, 0, 0L)+1;
741
		break;
742
	}
743
 
744
	/* Free any previous information. */
745
	if (obj->text)
746
	    discard(obj->text);
747
	/* Find the length of the string. */
748
	length = sendmessage(obj->handle, len_msg, arg1, 0L);
749
	if (length == 0)
750
		return (obj->text = new_string(NULL));
751
	/* Copy the text from the object. */
752
	text = array(length+2, char);
753
	sendmessage(obj->handle, gettext_msg, arg2, (LPCSTR) text);
754
	obj->text = to_c_string(text);
755
	discard(text);
756
	/* Return the resultant string. */
757
	if (! obj->text)
758
		obj->text = new_string(NULL);
759
	return obj->text;
760
}
761
 
762
/*
763
 *  Set the font used by a control.
764
 */
765
void settextfont(object obj, font f)
766
{
767
	if (! obj)
768
		return;
769
	if (! f)
770
		f = SystemFont;
771
	if (obj->drawstate) {
772
		decrease_refcount(obj->drawstate->fnt);
773
		obj->drawstate->fnt = f;
774
		increase_refcount(f);
775
	}
776
	else {
777
		sendmessage(obj->handle, WM_SETFONT, f->handle, 0L);
778
	}
779
}
780
 
781
/*
782
 *  Get the font used by a control.
783
 */
784
font gettextfont(object obj)
785
{
786
	font f = NULL;
787
	if (obj) {
788
		if (obj->drawstate)
789
			f = obj->drawstate->fnt;
790
	}
791
	if (! f)
792
		f = SystemFont;
793
	return f;
794
}
795
 
796
/*
797
 *  Control and window functions.
798
 *  Parentwindow of a window is itself.
799
 */
800
window parentwindow(control obj)
801
{
802
	while (obj) {
803
		if (obj->kind == WindowObject)
804
			break;
805
		obj = obj->parent;
806
	}
807
	return (window) obj;
808
}
809
 
810
/*
811
 *  Polymorphic functions:
812
 */
813
rect objrect(object obj)
814
{
815
	rect r;
816
	image img;
817
 
818
	if (! obj)
819
		return rect(0,0,0,0);
820
 
821
	switch (obj->kind)
822
	{
823
	  case Image8: case Image32:
824
		img = (image) obj;
825
		r = rect(0,0,img->width,img->height);
826
		break;
827
	  case BitmapObject:
828
	  case FontObject: case CursorObject:
829
	 case PrinterObject:
830
		r = obj->rect;
831
		break;
832
	 case MetafileObject:
833
		r = obj->rect;
24283 ripley 834
		break;
4394 ripley 835
	  default:
836
		GetClientRect(obj->handle, (RECT *) &r);
837
		break;
838
	}
839
	return r;
840
}
841
 
842
int objwidth(object obj)
843
{
844
	rect r = objrect(obj);
845
	return r.width;
846
}
847
 
848
int objheight(object obj)
849
{
850
	rect r = objrect(obj);
851
	return r.height;
852
}
853
 
854
int objdepth(object obj)
855
{
856
	HDC screendc;
857
	int depth;
858
 
859
	if (! obj)
860
		return 0;
861
 
862
	switch (obj->kind)
863
	{
864
	  case Image8: case Image32:
865
		depth = ((image)obj)->depth;
866
		break;
867
	  case BitmapObject:
868
	  case FontObject: case CursorObject:
869
		depth = obj->depth;
870
		break;
871
	  default:
872
		screendc = GetDC(NULL);
873
		depth = GetDeviceCaps(screendc, BITSPIXEL) *
874
			GetDeviceCaps(screendc, PLANES);
875
		ReleaseDC(NULL, screendc);
876
		break;
877
	}
878
 
879
	return depth;
880
}
881
 
882
void delobj(object obj)
883
{
884
	if (! obj)
885
		return;
886
	switch (obj->kind)
887
	{
888
	  case Image8:
889
	  case Image32:
890
		delimage((image)obj);
891
		break;
892
	  default:
24308 ripley 893
		/* if (obj->refcount == 1)   why would this test be here?? */
4394 ripley 894
			decrease_refcount(obj);
895
		break;
896
	}
897
}