The R Project SVN R

Rev

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

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