The R Project SVN R

Rev

Rev 4394 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4394 Rev 9184
1
/*
1
/*
2
 * GraphApp - Cross-Platform Graphics Programming Library.
2
 * GraphApp - Cross-Platform Graphics Programming Library.
3
 *
3
 *
4
 * File: context.c -- internal functions for manipulating DCs.
4
 * File: context.c -- internal functions for manipulating DCs.
5
 * Platform: Windows  Version: 2.35  Date: 1998/04/04
5
 * Platform: Windows  Version: 2.35  Date: 1998/04/04
6
 *
6
 *
7
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
7
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
8
 * Version: 1.05  Changes: Added drawstate information.
8
 * Version: 1.05  Changes: Added drawstate information.
9
 * Version: 1.50  Changes: New colour system, dithered grey.
9
 * Version: 1.50  Changes: New colour system, dithered grey.
10
 * Version: 2.00  Changes: New object class and context sub-system.
10
 * Version: 2.00  Changes: New object class and context sub-system.
11
 * Version: 2.01  Changes: get_context is now more bulletproof.
11
 * Version: 2.01  Changes: get_context is now more bulletproof.
12
 * Version: 2.02  Changes: drawto and setwinrgb have been updated.
12
 * Version: 2.02  Changes: drawto and setwinrgb have been updated.
13
 * Version: 2.20  Changes: Added currentrgb, currentfont etc.
13
 * Version: 2.20  Changes: Added currentrgb, currentfont etc.
14
 * Version: 2.35  Changes: New reference count technique.
14
 * Version: 2.35  Changes: New reference count technique.
15
 */
15
 */
16
 
16
 
17
/* Copyright (C) 1993-1998 Lachlan Patrick
17
/* Copyright (C) 1993-1998 Lachlan Patrick
18
 
18
 
19
   This file is part of GraphApp, a cross-platform C graphics library.
19
   This file is part of GraphApp, a cross-platform C graphics library.
20
 
20
 
21
   GraphApp is free software; you can redistribute it and/or modify it
21
   GraphApp is free software; you can redistribute it and/or modify it
22
   under the terms of the GNU Library General Public License.
22
   under the terms of the GNU Library General Public License.
23
   GraphApp is distributed in the hope that it will be useful, but
23
   GraphApp is distributed in the hope that it will be useful, but
24
   WITHOUT ANY WARRANTY.
24
   WITHOUT ANY WARRANTY.
25
 
25
 
26
   See the file COPYLIB.TXT for details.
26
   See the file COPYLIB.TXT for details.
27
*/
27
*/
28
 
28
 
-
 
29
/* Changes for R:  allow 32 contexts not 4 */
-
 
30
 
29
#include "internal.h"
31
#include "internal.h"
30
 
32
 
31
/*
33
/*
32
 *  Private library variables.
34
 *  Private library variables.
33
 */
35
 */
34
 
36
 
35
	PROTECTED drawstruct app_drawstate =
37
	PROTECTED drawstruct app_drawstate =
36
		{
38
		{
37
			NULL,	/* drawing destination */
39
			NULL,	/* drawing destination */
38
			Black,	/* colour */
40
			Black,	/* colour */
39
			S,  	/* drawing mode */
41
			S,  	/* drawing mode */
40
			{0,0},	/* point */
42
			{0,0},	/* point */
41
			1,  	/* line width */
43
			1,  	/* line width */
42
			NULL,	/* font */
44
			NULL,	/* font */
43
			NULL,	/* cursor */
45
			NULL,	/* cursor */
44
		};
46
		};
45
 
47
 
46
	PROTECTED drawstate current = & app_drawstate;
48
	PROTECTED drawstate current = & app_drawstate;
47
	PROTECTED HDC       dc;	/* shared DC variable */
49
	PROTECTED HDC       dc;	/* shared DC variable */
48
	PROTECTED HPEN      the_pen   = 0;
50
	PROTECTED HPEN      the_pen   = 0;
49
	PROTECTED HBRUSH    the_brush = 0;
51
	PROTECTED HBRUSH    the_brush = 0;
50
 
52
 
51
	PROTECTED COLORREF win_rgb  = 0L;
53
	PROTECTED COLORREF win_rgb  = 0L;
52
 
54
 
53
/*
55
/*
54
 *  Private drawing context variables.
56
 *  Private drawing context variables.
55
 */
57
 */
56
 
58
 
57
	static	rgb 	prev_pixval	= Black;
59
	static	rgb 	prev_pixval	= Black;
58
	static	int 	prev_width	= 1;
60
	static	int 	prev_width	= 1;
59
 
61
 
60
	static	bitmap	grey_bitmap	= NULL;
62
	static	bitmap	grey_bitmap	= NULL;
61
 
63
 
62
	static rgb grey_cmap [] = {
64
	static rgb grey_cmap [] = {
63
		0x00000000UL,
65
		0x00000000UL,
64
		0x00FFFFFFUL,
66
		0x00FFFFFFUL,
65
	};
67
	};
66
	static byte grey_pixels [] = {
68
	static byte grey_pixels [] = {
67
	  0, 1, 0, 1, 0, 1, 0, 1,
69
	  0, 1, 0, 1, 0, 1, 0, 1,
68
	  1, 0, 1, 0, 1, 0, 1, 0,
70
	  1, 0, 1, 0, 1, 0, 1, 0,
69
	  0, 1, 0, 1, 0, 1, 0, 1,
71
	  0, 1, 0, 1, 0, 1, 0, 1,
70
	  1, 0, 1, 0, 1, 0, 1, 0,
72
	  1, 0, 1, 0, 1, 0, 1, 0,
71
	  0, 1, 0, 1, 0, 1, 0, 1,
73
	  0, 1, 0, 1, 0, 1, 0, 1,
72
	  1, 0, 1, 0, 1, 0, 1, 0,
74
	  1, 0, 1, 0, 1, 0, 1, 0,
73
	  0, 1, 0, 1, 0, 1, 0, 1,
75
	  0, 1, 0, 1, 0, 1, 0, 1,
74
	  1, 0, 1, 0, 1, 0, 1, 0,
76
	  1, 0, 1, 0, 1, 0, 1, 0,
75
	};
77
	};
76
	static imagedata grey_imagedata = {
78
	static imagedata grey_imagedata = {
77
		8,	/* depth */
79
		8,	/* depth */
78
		8,	/* width */
80
		8,	/* width */
79
		8,	/* height */
81
		8,	/* height */
80
		2,	/* cmapsize */
82
		2,	/* cmapsize */
81
		grey_cmap,
83
		grey_cmap,
82
		grey_pixels
84
		grey_pixels
83
	};
85
	};
84
	static image grey_image = & grey_imagedata;
86
	static image grey_image = & grey_imagedata;
85
 
87
 
86
/*
88
/*
87
 *  Private context list structure
89
 *  Private context list structure
88
 */
90
 */
89
	typedef struct contextinfo  contextinfo;
91
	typedef struct contextinfo  contextinfo;
90
 
92
 
91
	struct contextinfo
93
	struct contextinfo
92
	{
94
	{
93
		object	obj;	/* back pointer to drawing object */
95
		object	obj;	/* back pointer to drawing object */
94
		HDC 	dc; 	/* handle to DC used when drawing */
96
		HDC 	dc; 	/* handle to DC used when drawing */
95
		HGDIOBJ old_bitmap; /* bitmap returned by SelectObject() */
97
		HGDIOBJ old_bitmap; /* bitmap returned by SelectObject() */
96
	};
98
	};
97
 
99
 
98
/*
100
/*
99
 *  The constant MAX_CONTEXTS controls how large the
101
 *  The constant MAX_CONTEXTS controls how large the
100
 *  circular array of contexts is, and thus how many
102
 *  circular array of contexts is, and thus how many
101
 *  concurrently active contexts there can be.  This
103
 *  concurrently active contexts there can be.  This
102
 *  number should be at least 2,  since bitblt needs
104
 *  number should be at least 2,  since bitblt needs
103
 *  two contexts for source and destination bitmaps.
105
 *  two contexts for source and destination bitmaps.
104
 */
106
 */
105
	#define MAX_CONTEXTS 32
107
	#define MAX_CONTEXTS 32
106
 
108
 
107
	static contextinfo context[MAX_CONTEXTS];
109
	static contextinfo context[MAX_CONTEXTS];
108
	static int num_contexts = 0;
110
	static int num_contexts = 0;
109
	static int empty_slot = 0;
111
	static int empty_slot = 0;
110
 
112
 
111
/*
113
/*
112
 *  Create a pen and a brush for use in drawing.
114
 *  Create a pen and a brush for use in drawing.
113
 */
115
 */
114
static void create_pen_and_brush(rgb c, unsigned long winrgb,
116
static void create_pen_and_brush(rgb c, unsigned long winrgb,
115
		int width, int depth)
117
		int width, int depth)
116
{
118
{
117
	the_pen = CreatePen(PS_INSIDEFRAME, width, winrgb);
119
	the_pen = CreatePen(PS_INSIDEFRAME, width, winrgb);
118
 
120
 
119
	if ((depth == 1) && (c == Grey))
121
	if ((depth == 1) && (c == Grey))
120
		the_brush = CreatePatternBrush(grey_bitmap->handle);
122
		the_brush = CreatePatternBrush(grey_bitmap->handle);
121
	else
123
	else
122
		the_brush = CreateSolidBrush(winrgb);
124
		the_brush = CreateSolidBrush(winrgb);
123
}
125
}
124
 
126
 
125
/*
127
/*
126
 *  Delete any created pens and brushes.
128
 *  Delete any created pens and brushes.
127
 *  Assumes they are not selected into any valid DC.
129
 *  Assumes they are not selected into any valid DC.
128
 */
130
 */
129
static void delete_pen_and_brush(void)
131
static void delete_pen_and_brush(void)
130
{
132
{
131
	DeleteObject(the_pen);
133
	DeleteObject(the_pen);
132
	DeleteObject(the_brush);
134
	DeleteObject(the_brush);
133
}
135
}
134
 
136
 
135
/*
137
/*
136
 *  Set Windows drawing globals up.
138
 *  Set Windows drawing globals up.
137
 */
139
 */
138
PROTECTED
140
PROTECTED
139
void init_contexts(void)
141
void init_contexts(void)
140
{
142
{
141
	grey_bitmap = imagetobitmap(grey_image);
143
	grey_bitmap = imagetobitmap(grey_image);
142
	grey_bitmap->text = new_string("grey_bitmap");
144
	grey_bitmap->text = new_string("grey_bitmap");
143
 
145
 
144
	current = & app_drawstate;
146
	current = & app_drawstate;
145
	app_drawstate.fnt = SystemFont;
147
	app_drawstate.fnt = SystemFont;
146
	app_drawstate.crsr = ArrowCursor;
148
	app_drawstate.crsr = ArrowCursor;
147
 
149
 
148
	create_pen_and_brush(Black, Black, 1, 0);
150
	create_pen_and_brush(Black, Black, 1, 0);
149
}
151
}
150
 
152
 
151
static void free_context(contextinfo *c)
153
static void free_context(contextinfo *c)
152
{
154
{
153
	if (! c->dc)
155
	if (! c->dc)
154
		return; /* already been deleted */
156
		return; /* already been deleted */
155
 
157
 
156
	SelectObject(c->dc, GetStockObject(NULL_PEN));
158
	SelectObject(c->dc, GetStockObject(NULL_PEN));
157
	SelectObject(c->dc, GetStockObject(NULL_BRUSH));
159
	SelectObject(c->dc, GetStockObject(NULL_BRUSH));
158
 
160
 
159
	if (c->obj->kind & ControlObject)
161
	if (c->obj->kind & ControlObject)
160
		ReleaseDC(c->obj->handle, c->dc);
162
		ReleaseDC(c->obj->handle, c->dc);
161
	else if (c->obj->kind == BitmapObject) {
163
	else if (c->obj->kind == BitmapObject) {
162
		SelectObject(c->dc, c->old_bitmap);
164
		SelectObject(c->dc, c->old_bitmap);
163
		DeleteDC(c->dc);
165
		DeleteDC(c->dc);
164
	}
166
	}
165
 
167
 
166
	if (dc == c->dc)
168
	if (dc == c->dc)
167
		dc = 0;
169
		dc = 0;
168
 
170
 
169
	c->dc = 0;
171
	c->dc = 0;
170
	c->obj = NULL;
172
	c->obj = NULL;
171
	c->old_bitmap = 0;
173
	c->old_bitmap = 0;
172
}
174
}
173
 
175
 
174
/*
176
/*
175
 *  Add a new DC into our list of DCs.
177
 *  Add a new DC into our list of DCs.
176
 */
178
 */
177
PROTECTED
179
PROTECTED
178
void add_context(object obj, HDC dc, HGDIOBJ old)
180
void add_context(object obj, HDC dc, HGDIOBJ old)
179
{
181
{
180
	contextinfo *c;
182
	contextinfo *c;
181
 
183
 
182
	/* Clear a spot for the new DC if the array is full. */
184
	/* Clear a spot for the new DC if the array is full. */
183
	if (num_contexts == MAX_CONTEXTS) {
185
	if (num_contexts == MAX_CONTEXTS) {
184
		c = & context[empty_slot];
186
		c = & context[empty_slot];
185
		free_context(c);
187
		free_context(c);
186
		empty_slot = (empty_slot+1) % MAX_CONTEXTS;
188
		empty_slot = (empty_slot+1) % MAX_CONTEXTS;
187
	} else {
189
	} else {
188
		c = & context[num_contexts];
190
		c = & context[num_contexts];
189
		num_contexts++;
191
		num_contexts++;
190
	}
192
	}
191
	/* Add this context to the list. */
193
	/* Add this context to the list. */
192
	c->obj = obj;
194
	c->obj = obj;
193
	c->dc = dc;
195
	c->dc = dc;
194
	c->old_bitmap = old;
196
	c->old_bitmap = old;
195
}
197
}
196
 
198
 
197
/*
199
/*
198
 *  Find and return a DC for a window or a bitmap.
200
 *  Find and return a DC for a window or a bitmap.
199
 *  Also keep track of which DCs have been created.
201
 *  Also keep track of which DCs have been created.
200
 */
202
 */
201
PROTECTED
203
PROTECTED
202
HDC get_context(object obj)
204
HDC get_context(object obj)
203
{
205
{
204
	int i;
206
	int i;
205
	HDC dc;
207
	HDC dc;
206
	HGDIOBJ old;
208
	HGDIOBJ old;
207
 
209
 
208
	/* Determine if a DC for this object already exists. */
210
	/* Determine if a DC for this object already exists. */
209
	for (i = 0; i < num_contexts; i++) {
211
	for (i = 0; i < num_contexts; i++) {
210
		if (context[i].obj == obj)
212
		if (context[i].obj == obj)
211
			return context[i].dc;
213
			return context[i].dc;
212
	}
214
	}
213
 
215
 
214
	/* Use GetDC or CreateCompatibleDC to return a DC. */
216
	/* Use GetDC or CreateCompatibleDC to return a DC. */
215
	if (obj->kind & ControlObject) {
217
	if (obj->kind & ControlObject) {
216
		dc = GetDC(obj->handle);
218
		dc = GetDC(obj->handle);
217
		add_context(obj, dc, 0);
219
		add_context(obj, dc, 0);
218
	}
220
	}
219
	else if (obj->kind == BitmapObject) {
221
	else if (obj->kind == BitmapObject) {
220
		dc = CreateCompatibleDC(0);
222
		dc = CreateCompatibleDC(0);
221
		old = SelectObject(dc, obj->handle);
223
		old = SelectObject(dc, obj->handle);
222
		add_context(obj, dc, old);
224
		add_context(obj, dc, old);
223
	}
225
	}
224
	else {
226
	else {
225
		return NULL;
227
		return NULL;
226
	/* apperror("Cannot find DC for non-drawable object."); */
228
	/* apperror("Cannot find DC for non-drawable object."); */
227
	}
229
	}
228
 
230
 
229
	/* We only select in the brush or pen we need, when we
231
	/* We only select in the brush or pen we need, when we
230
	 * need it. Thus at all other times, they are NULL.
232
	 * need it. Thus at all other times, they are NULL.
231
	 * This ensures we can delete objects when we want, and
233
	 * This ensures we can delete objects when we want, and
232
	 * also makes correct context possible. */
234
	 * also makes correct context possible. */
233
	SelectObject(dc, GetStockObject(NULL_PEN));
235
	SelectObject(dc, GetStockObject(NULL_PEN));
234
	SelectObject(dc, GetStockObject(NULL_BRUSH));
236
	SelectObject(dc, GetStockObject(NULL_BRUSH));
235
 
237
 
236
	return dc;
238
	return dc;
237
}
239
}
238
 
240
 
239
/*
241
/*
240
 *  Remove the context from the list by blanking its fields.
242
 *  Remove the context from the list by blanking its fields.
241
 *  It is assumed that the DC has previously been released,
243
 *  It is assumed that the DC has previously been released,
242
 *  for example by EndPaint() in the events.c file.
244
 *  for example by EndPaint() in the events.c file.
243
 */
245
 */
244
PROTECTED
246
PROTECTED
245
void remove_context(object obj)
247
void remove_context(object obj)
246
{
248
{
247
	int i;
249
	int i;
248
	contextinfo *c;
250
	contextinfo *c;
249
 
251
 
250
	for (i = 0; i < num_contexts; i++) {
252
	for (i = 0; i < num_contexts; i++) {
251
		c = & context[i];
253
		c = & context[i];
252
		if (c->obj == obj) {
254
		if (c->obj == obj) {
253
			c->obj = NULL;
255
			c->obj = NULL;
254
			c->dc = 0;
256
			c->dc = 0;
255
			c->old_bitmap = 0;
257
			c->old_bitmap = 0;
256
			empty_slot = i;
258
			empty_slot = i;
257
		}
259
		}
258
	}
260
	}
259
}
261
}
260
 
262
 
261
/*
263
/*
262
 *  Free the DC associated with a given object.
264
 *  Free the DC associated with a given object.
263
 */
265
 */
264
PROTECTED
266
PROTECTED
265
void del_context(object obj)
267
void del_context(object obj)
266
{
268
{
267
	int i;
269
	int i;
268
	contextinfo *c;
270
	contextinfo *c;
269
 
271
 
270
	for (i = 0; i < num_contexts; i++) {
272
	for (i = 0; i < num_contexts; i++) {
271
		c = & context[i];
273
		c = & context[i];
272
		if (c->obj == obj) {
274
		if (c->obj == obj) {
273
			free_context(c);
275
			free_context(c);
274
			c->obj = NULL;
276
			c->obj = NULL;
275
			c->dc = 0;
277
			c->dc = 0;
276
			c->old_bitmap = 0;
278
			c->old_bitmap = 0;
277
			empty_slot = i;
279
			empty_slot = i;
278
		}
280
		}
279
	}
281
	}
280
}
282
}
281
 
283
 
282
/*
284
/*
283
 *  Get rid of all DCs.
285
 *  Get rid of all DCs.
284
 */
286
 */
285
PROTECTED
287
PROTECTED
286
void del_all_contexts(void)
288
void del_all_contexts(void)
287
{
289
{
288
	int i;
290
	int i;
289
	contextinfo *c;
291
	contextinfo *c;
290
 
292
 
291
	for (i = 0; i < num_contexts; i++) {
293
	for (i = 0; i < num_contexts; i++) {
292
		c = & context[i];
294
		c = & context[i];
293
		free_context(c);
295
		free_context(c);
294
		c->obj = NULL;
296
		c->obj = NULL;
295
		c->dc = 0;
297
		c->dc = 0;
296
		c->old_bitmap = 0;
298
		c->old_bitmap = 0;
297
	}
299
	}
298
	num_contexts = 0;
300
	num_contexts = 0;
299
	empty_slot = 0;
301
	empty_slot = 0;
300
}
302
}
301
 
303
 
302
/*
304
/*
303
 *  De-initialise drawing variables.
305
 *  De-initialise drawing variables.
304
 */
306
 */
305
PROTECTED
307
PROTECTED
306
void finish_contexts(void)
308
void finish_contexts(void)
307
{
309
{
308
	del_all_contexts();
310
	del_all_contexts();
309
	DeleteObject(the_pen);
311
	DeleteObject(the_pen);
310
	DeleteObject(the_brush);
312
	DeleteObject(the_brush);
311
}
313
}
312
 
314
 
313
/*
315
/*
314
 *  Set up a pen and a brush for use in colouring things, and return
316
 *  Set up a pen and a brush for use in colouring things, and return
315
 *  the Windows RGB value equivalent to the library rgb value.
317
 *  the Windows RGB value equivalent to the library rgb value.
316
 */
318
 */
317
static unsigned long set_win_rgb(rgb c, int width)
319
static unsigned long set_win_rgb(rgb c, int width)
318
{
320
{
319
	int r, g, b;
321
	int r, g, b;
320
	long luminance;
322
	long luminance;
321
	int depth;
323
	int depth;
322
	unsigned long winrgb;
324
	unsigned long winrgb;
323
 
325
 
324
	if (current->mode == Ones)
326
	if (current->mode == Ones)
325
		c = White;
327
		c = White;
326
	else if (current->mode == Zeros)
328
	else if (current->mode == Zeros)
327
		c = Black;
329
		c = Black;
328
 
330
 
329
	r = (int) ((c >> 16) & 0x000000FFL);
331
	r = (int) ((c >> 16) & 0x000000FFL);
330
	g = (int) ((c >>  8) & 0x000000FFL);
332
	g = (int) ((c >>  8) & 0x000000FFL);
331
	b = (int) ((c >>  0) & 0x000000FFL);
333
	b = (int) ((c >>  0) & 0x000000FFL);
332
 
334
 
333
	depth = getdepth(current->dest);
335
	depth = getdepth(current->dest);
334
 
336
 
335
	if (depth <= 2)	/* map to black or white, or grey if c == Grey */
337
	if (depth <= 2)	/* map to black or white, or grey if c == Grey */
336
	{
338
	{
337
		luminance = (r*3 + g*5 + b) / 9;
339
		luminance = (r*3 + g*5 + b) / 9;
338
		if (luminance > 0x0087)		r = g = b = 0x00FF;
340
		if (luminance > 0x0087)		r = g = b = 0x00FF;
339
		else if (luminance <= 0x0077)	r = g = b = 0x0000;
341
		else if (luminance <= 0x0077)	r = g = b = 0x0000;
340
		else				r = g = b = 0x0080;
342
		else				r = g = b = 0x0080;
341
		c = rgb(r,g,b);
343
		c = rgb(r,g,b);
342
	}
344
	}
343
 
345
 
344
	winrgb = RGB(r, g, b);
346
	winrgb = RGB(r, g, b);
345
 
347
 
346
	/* Has a colour or width change occured? */
348
	/* Has a colour or width change occured? */
347
	if ((c != prev_pixval) || (width != prev_width))
349
	if ((c != prev_pixval) || (width != prev_width))
348
	{
350
	{
349
		prev_pixval = c;
351
		prev_pixval = c;
350
		prev_width = width;
352
		prev_width = width;
351
 
353
 
352
		/* delete any old objects */
354
		/* delete any old objects */
353
		delete_pen_and_brush();
355
		delete_pen_and_brush();
354
 
356
 
355
		/* set up new objects */
357
		/* set up new objects */
356
		create_pen_and_brush(c, winrgb, width, depth);
358
		create_pen_and_brush(c, winrgb, width, depth);
357
	}
359
	}
358
	return winrgb;
360
	return winrgb;
359
}
361
}
360
 
362
 
361
void setcursor(cursor c)
363
void setcursor(cursor c)
362
{
364
{
363
	decrease_refcount(current->crsr);
365
	decrease_refcount(current->crsr);
364
	current->crsr = c;
366
	current->crsr = c;
365
	if (c) SetCursor((HCURSOR) c->handle);
367
	if (c) SetCursor((HCURSOR) c->handle);
366
	increase_refcount(c);
368
	increase_refcount(c);
367
}
369
}
368
 
370
 
369
void setfont(font f)
371
void setfont(font f)
370
{
372
{
371
	decrease_refcount(current->fnt);
373
	decrease_refcount(current->fnt);
372
	current->fnt = f;
374
	current->fnt = f;
373
	increase_refcount(f);
375
	increase_refcount(f);
374
}
376
}
375
 
377
 
376
/*
378
/*
377
 *  Set the way that source and destination pixels are combined
379
 *  Set the way that source and destination pixels are combined
378
 *  when drawing.
380
 *  when drawing.
379
 */
381
 */
380
void setdrawmode(int mode)
382
void setdrawmode(int mode)
381
{
383
{
382
	current->mode = mode & 0x0F; /* must be between 0x00 and 0x0F */
384
	current->mode = mode & 0x0F; /* must be between 0x00 and 0x0F */
383
}
385
}
384
 
386
 
385
/*
387
/*
386
 *  Set the colour.
388
 *  Set the colour.
387
 */
389
 */
388
void setrgb(rgb hue)
390
void setrgb(rgb hue)
389
{
391
{
390
	current->hue = hue;
392
	current->hue = hue;
391
	win_rgb = set_win_rgb(hue, current->linewidth);
393
	win_rgb = set_win_rgb(hue, current->linewidth);
392
}
394
}
393
 
395
 
394
/*
396
/*
395
 *  Set the line width.
397
 *  Set the line width.
396
 */
398
 */
397
void setlinewidth(int width)
399
void setlinewidth(int width)
398
{
400
{
399
	if (width < 1)
401
	if (width < 1)
400
		width = 1;
402
		width = 1;
401
	current->linewidth = width;
403
	current->linewidth = width;
402
	win_rgb = set_win_rgb(current->hue, current->linewidth);
404
	win_rgb = set_win_rgb(current->hue, current->linewidth);
403
}
405
}
404
 
406
 
405
/*
407
/*
406
 *  Set which window/menubar/menu to add new objects too.
408
 *  Set which window/menubar/menu to add new objects too.
407
 */
409
 */
408
void addto(object obj)
410
void addto(object obj)
409
{
411
{
410
	if (! obj)
412
	if (! obj)
411
		return;
413
		return;
412
	switch (obj->kind) {
414
	switch (obj->kind) {
413
		case WindowObject:	current_window = obj;	break;
415
		case WindowObject:	current_window = obj;	break;
414
		case MenubarObject:	current_menubar = obj;	break;
416
		case MenubarObject:	current_menubar = obj;	break;
415
		case MenuObject:	current_menu = obj;	break;
417
		case MenuObject:	current_menu = obj;	break;
416
	}
418
	}
417
}
419
}
418
 
420
 
419
/*
421
/*
420
 *  Set which bitmap or window to draw to; allocate a DC too.
422
 *  Set which bitmap or window to draw to; allocate a DC too.
421
 */
423
 */
422
void drawto(drawing d)
424
void drawto(drawing d)
423
{
425
{
424
	if (! d) {
426
	if (! d) {
425
		current = & app_drawstate;
427
		current = & app_drawstate;
426
		current->dest = NULL;
428
		current->dest = NULL;
427
		return;
429
		return;
428
	}
430
	}
429
 
431
 
430
	dc = get_context(d);
432
	dc = get_context(d);
431
 
433
 
432
	if (d->drawstate) {
434
	if (d->drawstate) {
433
		/* Change the current drawing state to this one. */
435
		/* Change the current drawing state to this one. */
434
		current = d->drawstate;
436
		current = d->drawstate;
435
		current->dest = d;
437
		current->dest = d;
436
		win_rgb = set_win_rgb(current->hue, current->linewidth);
438
		win_rgb = set_win_rgb(current->hue, current->linewidth);
437
	}
439
	}
438
	else {
440
	else {
439
		/* Otherwise just use the current drawing state. */
441
		/* Otherwise just use the current drawing state. */
440
		current->dest = d;
442
		current->dest = d;
441
	}
443
	}
442
}
444
}
443
 
445
 
444
/*
446
/*
445
 *  Ensure drawing variables are set up.
447
 *  Ensure drawing variables are set up.
446
 */
448
 */
447
void setdrawstate(drawstate s)
449
void setdrawstate(drawstate s)
448
{
450
{
449
	if (! s)
451
	if (! s)
450
		return;
452
		return;
451
	moveto(s->p);
453
	moveto(s->p);
452
	setdrawmode(s->mode);
454
	setdrawmode(s->mode);
453
	setcursor(s->crsr);
455
	setcursor(s->crsr);
454
	setfont(s->fnt);
456
	setfont(s->fnt);
455
	setlinewidth(s->linewidth);
457
	setlinewidth(s->linewidth);
456
	setrgb(s->hue);
458
	setrgb(s->hue);
457
}
459
}
458
 
460
 
459
/*
461
/*
460
 *  Change the current drawstate to the specified one.
462
 *  Change the current drawstate to the specified one.
461
 */
463
 */
462
void restoredrawstate(drawstate s)
464
void restoredrawstate(drawstate s)
463
{
465
{
464
	if (! s)
466
	if (! s)
465
		return;
467
		return;
466
	setdrawstate(s);
468
	setdrawstate(s);
467
	discard(s);
469
	discard(s);
468
}
470
}
469
 
471
 
470
/*
472
/*
471
 *  Reset drawing variables to initial values.
473
 *  Reset drawing variables to initial values.
472
 */
474
 */
473
void resetdrawstate(void)
475
void resetdrawstate(void)
474
{
476
{
475
	setrgb(Black);
477
	setrgb(Black);
476
	setlinewidth(1);
478
	setlinewidth(1);
477
	setcursor(ArrowCursor);
479
	setcursor(ArrowCursor);
478
	moveto(pt(0,0));
480
	moveto(pt(0,0));
479
	setfont(SystemFont);
481
	setfont(SystemFont);
480
	setdrawmode(S);
482
	setdrawmode(S);
481
}
483
}
482
 
484
 
483
/*
485
/*
484
 *  Return a new copy of the current drawing state.
486
 *  Return a new copy of the current drawing state.
485
 */
487
 */
486
drawstate copydrawstate(void)
488
drawstate copydrawstate(void)
487
{
489
{
488
	drawstate s = NULL;
490
	drawstate s = NULL;
489
 
491
 
490
	if (current) {
492
	if (current) {
491
		s = create(drawstruct);
493
		s = create(drawstruct);
492
		if (s)
494
		if (s)
493
			*s = *current;
495
			*s = *current;
494
	}
496
	}
495
	return s;
497
	return s;
496
}
498
}
497
 
499
 
498
/*
500
/*
499
 *  Return drawing state information.
501
 *  Return drawing state information.
500
 */
502
 */
501
 
503
 
502
drawing	currentdrawing(void)    { return current->dest; }
504
drawing	currentdrawing(void)    { return current->dest; }
503
rgb 	currentrgb(void)        { return current->hue; }
505
rgb 	currentrgb(void)        { return current->hue; }
504
int 	currentmode(void)       { return current->mode; }
506
int 	currentmode(void)       { return current->mode; }
505
point	currentpoint(void)      { return current->p; }
507
point	currentpoint(void)      { return current->p; }
506
int 	currentlinewidth(void)  { return current->linewidth; }
508
int 	currentlinewidth(void)  { return current->linewidth; }
507
font	currentfont(void)       { return current->fnt; }
509
font	currentfont(void)       { return current->fnt; }
508
cursor	currentcursor(void)     { return current->crsr; }
510
cursor	currentcursor(void)     { return current->crsr; }
509
 
511
 
510
int 	getkeystate(void)       { return keystate; }
512
int 	getkeystate(void)       { return keystate; }