The R Project SVN R

Rev

Rev 42521 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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