~ubuntu-branches/ubuntu/vivid/imaze/vivid

« back to all changes in this revision

Viewing changes to source/lab_edit_w.c

  • Committer: Bazaar Package Importer
  • Author(s): Hans Freitag
  • Date: 2002-11-28 13:24:12 UTC
  • Revision ID: james.westby@ubuntu.com-20021128132412-lw82xl9oq1j36g8b
Tags: upstream-1.4
ImportĀ upstreamĀ versionĀ 1.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** - - -  iMaze  - - -
 
3
**
 
4
** Copyright (c) 1993-2001 by Hans-Ulrich Kiel & Joerg Czeranski
 
5
** All rights reserved.
 
6
**
 
7
** Redistribution and use in source and binary forms, with or without
 
8
** modification, are permitted provided that the following conditions are
 
9
** met:
 
10
**
 
11
** 1. Redistributions of source code must retain the above copyright
 
12
**    notice, this list of conditions and the following disclaimer.
 
13
** 2. Redistributions in binary form must reproduce the above copyright
 
14
**    notice, this list of conditions and the following disclaimer in the
 
15
**    documentation and/or other materials provided with the distribution.
 
16
** 3. The name of the authors may not be used to endorse or promote
 
17
**    products derived from this software without specific prior written
 
18
**    permission.
 
19
** 4. The name ``iMaze'' may not be used for products derived from this
 
20
**    software unless a prefix or a suffix is added to the name.
 
21
**
 
22
** THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
 
23
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
24
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
25
** DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
 
26
** INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
27
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
28
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
29
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
30
** STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 
31
** IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
32
** POSSIBILITY OF SUCH DAMAGE.
 
33
*/
 
34
 
 
35
#include <stdio.h>
 
36
#include <stdlib.h>
 
37
#include <X11/StringDefs.h>
 
38
#include <X11/IntrinsicP.h>
 
39
 
 
40
#include "lab_edit_wp.h"
 
41
#include "global.h"
 
42
 
 
43
static char sccsid[] = "@(#)lab_edit_w.c        3.3 12/04/01";
 
44
 
 
45
 
 
46
/*
 
47
**      macros
 
48
*/
 
49
 
 
50
#define DEFAULT_WALL 5
 
51
 
 
52
#define WALL_WIDTH 3
 
53
#define DOOR_CORNER_WIDTH (2 * WALL_WIDTH)
 
54
 
 
55
#define DOOR_COLOR1 (N_WALL_COLORS + 1)
 
56
 
 
57
#define IS_DOOR_COLOR(x) ((x) >= DOOR_COLOR1)
 
58
 
 
59
 
 
60
/*
 
61
**      local prototypes
 
62
*/
 
63
 
 
64
static void LabEditInit(Widget request_w, Widget new_w, ArgList arg_list,
 
65
        Cardinal *n_args);
 
66
static void LabEditDestroy(Widget arg_w);
 
67
static Boolean LabEditSetValues(Widget current_w, Widget request_w,
 
68
        Widget new_w, ArgList arg_list, Cardinal *n_args);
 
69
static void LabEditExpose(Widget arg_w, XEvent *event, Region arg_r);
 
70
 
 
71
 
 
72
/*
 
73
**      variables
 
74
*/
 
75
 
 
76
static XtResource resources[] =
 
77
{
 
78
        {
 
79
                XtNforeground,
 
80
                XtCForeground,
 
81
                XtRPixel,
 
82
                sizeof(Pixel),
 
83
                XtOffsetOf(LabEditRec, labEdit.foreground_pixel),
 
84
                XtRString,
 
85
                XtDefaultForeground
 
86
        },
 
87
        {
 
88
                XtNwallColor1,
 
89
                XtCWallColor,
 
90
                XtRPixel,
 
91
                sizeof(Pixel),
 
92
                XtOffsetOf(LabEditRec, labEdit.wall_colors[0]),
 
93
                XtRString,
 
94
                XtDefaultForeground
 
95
        },
 
96
        {
 
97
                XtNwallColor2,
 
98
                XtCWallColor,
 
99
                XtRPixel,
 
100
                sizeof(Pixel),
 
101
                XtOffsetOf(LabEditRec, labEdit.wall_colors[1]),
 
102
                XtRString,
 
103
                XtDefaultForeground
 
104
        },
 
105
        {
 
106
                XtNwallColor3,
 
107
                XtCWallColor,
 
108
                XtRPixel,
 
109
                sizeof(Pixel),
 
110
                XtOffsetOf(LabEditRec, labEdit.wall_colors[2]),
 
111
                XtRString,
 
112
                XtDefaultForeground
 
113
        },
 
114
        {
 
115
                XtNwallColor4,
 
116
                XtCWallColor,
 
117
                XtRPixel,
 
118
                sizeof(Pixel),
 
119
                XtOffsetOf(LabEditRec, labEdit.wall_colors[3]),
 
120
                XtRString,
 
121
                XtDefaultForeground
 
122
        },
 
123
        {
 
124
                XtNwallColor5,
 
125
                XtCWallColor,
 
126
                XtRPixel,
 
127
                sizeof(Pixel),
 
128
                XtOffsetOf(LabEditRec, labEdit.wall_colors[4]),
 
129
                XtRString,
 
130
                XtDefaultForeground
 
131
        },
 
132
        {
 
133
                XtNwallColor6,
 
134
                XtCWallColor,
 
135
                XtRPixel,
 
136
                sizeof(Pixel),
 
137
                XtOffsetOf(LabEditRec, labEdit.wall_colors[5]),
 
138
                XtRString,
 
139
                XtDefaultForeground
 
140
        },
 
141
        {
 
142
                XtNwallColor7,
 
143
                XtCWallColor,
 
144
                XtRPixel,
 
145
                sizeof(Pixel),
 
146
                XtOffsetOf(LabEditRec, labEdit.wall_colors[6]),
 
147
                XtRString,
 
148
                XtDefaultForeground
 
149
        },
 
150
        {
 
151
                XtNdoorColor1,
 
152
                XtCDoorColor,
 
153
                XtRPixel,
 
154
                sizeof(Pixel),
 
155
                XtOffsetOf(LabEditRec, labEdit.door_colors[0]),
 
156
                XtRString,
 
157
                XtDefaultForeground
 
158
        },
 
159
        {
 
160
                XtNdoorColor2,
 
161
                XtCDoorColor,
 
162
                XtRPixel,
 
163
                sizeof(Pixel),
 
164
                XtOffsetOf(LabEditRec, labEdit.door_colors[1]),
 
165
                XtRString,
 
166
                XtDefaultForeground
 
167
        },
 
168
        {
 
169
                XtNdoorColor3,
 
170
                XtCDoorColor,
 
171
                XtRPixel,
 
172
                sizeof(Pixel),
 
173
                XtOffsetOf(LabEditRec, labEdit.door_colors[2]),
 
174
                XtRString,
 
175
                XtDefaultForeground
 
176
        },
 
177
        {
 
178
                XtNdoorColor4,
 
179
                XtCDoorColor,
 
180
                XtRPixel,
 
181
                sizeof(Pixel),
 
182
                XtOffsetOf(LabEditRec, labEdit.door_colors[3]),
 
183
                XtRString,
 
184
                XtDefaultForeground
 
185
        },
 
186
        {
 
187
                XtNdoorColor5,
 
188
                XtCDoorColor,
 
189
                XtRPixel,
 
190
                sizeof(Pixel),
 
191
                XtOffsetOf(LabEditRec, labEdit.door_colors[4]),
 
192
                XtRString,
 
193
                XtDefaultForeground
 
194
        },
 
195
        {
 
196
                XtNdoorColor6,
 
197
                XtCDoorColor,
 
198
                XtRPixel,
 
199
                sizeof(Pixel),
 
200
                XtOffsetOf(LabEditRec, labEdit.door_colors[5]),
 
201
                XtRString,
 
202
                XtDefaultForeground
 
203
        },
 
204
        {
 
205
                XtNdoorColor7,
 
206
                XtCDoorColor,
 
207
                XtRPixel,
 
208
                sizeof(Pixel),
 
209
                XtOffsetOf(LabEditRec, labEdit.door_colors[6]),
 
210
                XtRString,
 
211
                XtDefaultForeground
 
212
        },
 
213
        {
 
214
                XtNdoorColor8,
 
215
                XtCDoorColor,
 
216
                XtRPixel,
 
217
                sizeof(Pixel),
 
218
                XtOffsetOf(LabEditRec, labEdit.door_colors[7]),
 
219
                XtRString,
 
220
                XtDefaultForeground
 
221
        },
 
222
        {
 
223
                XtNhCells,
 
224
                XtCHCells,
 
225
                XtRDimension,
 
226
                sizeof(Dimension),
 
227
                XtOffsetOf(LabEditRec, labEdit.h_cells),
 
228
                XtRImmediate,
 
229
                (XtPointer)16
 
230
        },
 
231
        {
 
232
                XtNvCells,
 
233
                XtCVCells,
 
234
                XtRDimension,
 
235
                sizeof(Dimension),
 
236
                XtOffsetOf(LabEditRec, labEdit.v_cells),
 
237
                XtRImmediate,
 
238
                (XtPointer)16
 
239
        }
 
240
};
 
241
 
 
242
static XtActionsRec actions[] =
 
243
{
 
244
        { "start_add_wall", LabEditStartAddWall },
 
245
        { "start_remove_wall", LabEditStartRemoveWall },
 
246
        { "extend_wall", LabEditExtendWall },
 
247
        { "finish_wall", LabEditFinishWall },
 
248
        { "abort_wall", LabEditAbortWall },
 
249
        { "toggle_door", LabEditToggleDoor }
 
250
};
 
251
 
 
252
static char translations[] =
 
253
        "Button1<BtnDown>: abort_wall() \n\
 
254
        Button2<BtnDown>:  abort_wall() \n\
 
255
        Button3<BtnDown>:  abort_wall() \n\
 
256
        <Btn1Down>:        start_add_wall() \n\
 
257
        <Btn2Down>:        toggle_door() \n\
 
258
        <Btn3Down>:        start_remove_wall() \n\
 
259
        <Btn1Motion>:      extend_wall() \n\
 
260
        <Btn3Motion>:      extend_wall() \n\
 
261
        <Btn1Up>:          finish_wall() \n\
 
262
        <Btn3Up>:          finish_wall()";
 
263
 
 
264
LabEditClassRec labEditClassRec =
 
265
{
 
266
        /* core_class */
 
267
        {
 
268
        /* superclass */                (WidgetClass)&coreClassRec,
 
269
        /* class_name */                "LabEdit",
 
270
        /* widget_size */               sizeof(LabEditRec),
 
271
        /* class_initialize */          NULL,
 
272
        /* class_part_initialize */     NULL,
 
273
        /* class_inited */              FALSE,
 
274
        /* initialize */                LabEditInit,
 
275
        /* initialize_hook */           NULL,
 
276
        /* realize */                   XtInheritRealize,
 
277
        /* actions */                   actions,
 
278
        /* num_actions */               XtNumber(actions),
 
279
        /* resources */                 resources,
 
280
        /* num_resources */             XtNumber(resources),
 
281
        /* xrm_class */                 NULLQUARK,
 
282
        /* compress_motion */           TRUE,
 
283
        /* compress_exposure */         XtExposeCompressMultiple,
 
284
        /* compress_enterleave */       TRUE,
 
285
        /* visible_interest */          FALSE,
 
286
        /* destroy */                   LabEditDestroy,
 
287
        /* resize */                    NULL, /***/
 
288
        /* expose */                    LabEditExpose,
 
289
        /* set_values */                LabEditSetValues,
 
290
        /* set_values_hook */           NULL,
 
291
        /* set_values_almost */         XtInheritSetValuesAlmost,
 
292
        /* get_values_hook */           NULL,
 
293
        /* accept_focus */              NULL, /***/
 
294
        /* version */                   XtVersion,
 
295
        /* callback_private */          NULL,
 
296
        /* tm_table */                  translations,
 
297
        /* query_geometry */            XtInheritQueryGeometry,
 
298
        /* display_accelerator */       XtInheritDisplayAccelerator,
 
299
        /* extension */                 NULL
 
300
        },
 
301
 
 
302
        /* labEdit_class */
 
303
        {
 
304
        /* [none] */                    0
 
305
        }
 
306
};
 
307
 
 
308
WidgetClass labEditWidgetClass = (WidgetClass)&labEditClassRec;
 
309
 
 
310
 
 
311
/*
 
312
**      local
 
313
*/
 
314
 
 
315
 
 
316
static int random_door_color(void)
 
317
{
 
318
        return zufall() % N_DOOR_COLORS + DOOR_COLOR1;
 
319
}
 
320
 
 
321
 
 
322
static void LabEditInit(Widget request_w, Widget new_w, ArgList arg_list,
 
323
        Cardinal *n_args)
 
324
{
 
325
        LabEditWidget w;
 
326
        XGCValues gc_set;
 
327
        int h, v, x, i;
 
328
 
 
329
        w = (LabEditWidget)new_w;
 
330
 
 
331
        w->labEdit.modified = 0;
 
332
 
 
333
        gc_set.foreground = w->labEdit.foreground_pixel;
 
334
        w->labEdit.foreground_gc = XtGetGC(new_w, GCForeground, &gc_set);
 
335
 
 
336
        for (i = 0; i < N_WALL_COLORS; i++)
 
337
        {
 
338
                gc_set.foreground = w->labEdit.wall_colors[i];
 
339
                w->labEdit.wall_gcs[i] = XtGetGC(new_w, GCForeground, &gc_set);
 
340
        }
 
341
 
 
342
        for (i = 0; i < N_DOOR_COLORS; i++)
 
343
        {
 
344
                gc_set.foreground = w->labEdit.door_colors[i];
 
345
                w->labEdit.door_gcs[i] = XtGetGC(new_w, GCForeground, &gc_set);
 
346
        }
 
347
 
 
348
        h = w->labEdit.h_cells;
 
349
        v = w->labEdit.v_cells;
 
350
 
 
351
        w->labEdit.walls = (void *)XtMalloc(h * sizeof *w->labEdit.walls);
 
352
        for (x = 0; x < h; x++)
 
353
                w->labEdit.walls[x] =
 
354
                        (void *)XtMalloc(v * sizeof **w->labEdit.walls);
 
355
 
 
356
        LabEditClear(new_w);
 
357
}
 
358
 
 
359
 
 
360
static void LabEditDestroy(Widget arg_w)
 
361
{
 
362
        LabEditWidget w;
 
363
        int h, x, i;
 
364
 
 
365
        w = (LabEditWidget)arg_w;
 
366
 
 
367
        XtReleaseGC(arg_w, w->labEdit.foreground_gc);
 
368
 
 
369
        for (i = 0; i < N_WALL_COLORS; i++)
 
370
                XtReleaseGC(arg_w, w->labEdit.wall_gcs[i]);
 
371
 
 
372
        for (i = 0; i < N_DOOR_COLORS; i++)
 
373
                XtReleaseGC(arg_w, w->labEdit.door_gcs[i]);
 
374
 
 
375
        h = w->labEdit.h_cells;
 
376
 
 
377
        for (x = 0; x < h; x++)
 
378
                XtFree((char *)w->labEdit.walls[x]);
 
379
        XtFree((char *)w->labEdit.walls);
 
380
}
 
381
 
 
382
 
 
383
static Boolean LabEditSetValues(Widget current_w, Widget request_w,
 
384
        Widget new_w, ArgList arg_list, Cardinal *n_args)
 
385
{
 
386
        LabEditWidget w, old_w;
 
387
        int h, v, x;
 
388
 
 
389
        old_w = (LabEditWidget)current_w;
 
390
        w = (LabEditWidget)new_w;
 
391
 
 
392
        if (w->labEdit.h_cells == old_w->labEdit.h_cells &&
 
393
                w->labEdit.v_cells == old_w->labEdit.v_cells)
 
394
                return False;
 
395
 
 
396
 
 
397
        /* destroy old lab data */
 
398
 
 
399
        h = old_w->labEdit.h_cells;
 
400
 
 
401
        for (x = 0; x < h; x++)
 
402
                XtFree((char *)w->labEdit.walls[x]);
 
403
        XtFree((char *)w->labEdit.walls);
 
404
 
 
405
 
 
406
        /* create again with new size */
 
407
 
 
408
        h = w->labEdit.h_cells;
 
409
        v = w->labEdit.v_cells;
 
410
 
 
411
        w->labEdit.walls = (void *)XtMalloc(h * sizeof *w->labEdit.walls);
 
412
        for (x = 0; x < h; x++)
 
413
                w->labEdit.walls[x] =
 
414
                        (void *)XtMalloc(v * sizeof **w->labEdit.walls);
 
415
 
 
416
        LabEditClear(new_w);
 
417
 
 
418
 
 
419
        return True;
 
420
}
 
421
 
 
422
 
 
423
static void draw_wall(LabEditWidget w, GC gc, int x1, int y1, int x2, int y2,
 
424
        int dir)
 
425
{
 
426
        static int dx[4] = { -1, 0, 1, 0 };
 
427
        static int dy[4] = { 0, 1, 0, -1 };
 
428
        XSegment s[WALL_WIDTH];
 
429
        int i;
 
430
 
 
431
        for (i = 0; i < WALL_WIDTH; i++)
 
432
        {
 
433
                s[i].x1 = x1 + i * (dy[dir] + dx[dir]) + (i ? 0 : dx[dir]);
 
434
                s[i].y1 = y1 + i * (-dx[dir] + dy[dir]) + (i ? 0 : dy[dir]);
 
435
                s[i].x2 = x2 + i * (dy[dir] - dx[dir]) - dx[dir];
 
436
                s[i].y2 = y2 + i * (-dx[dir] - dy[dir]) - dy[dir];
 
437
        }
 
438
 
 
439
        XDrawSegments(XtDisplay(w), XtWindow(w), gc, s, WALL_WIDTH);
 
440
}
 
441
 
 
442
 
 
443
static void draw_door(LabEditWidget w, GC gc, int x1, int y1, int x2, int y2,
 
444
        int dir)
 
445
{
 
446
        static int dx[4] = { -1, 0, 1, 0 };
 
447
        static int dy[4] = { 0, 1, 0, -1 };
 
448
        XSegment s[2 * WALL_WIDTH];
 
449
        int i;
 
450
 
 
451
        for (i = 0; i < WALL_WIDTH; i++)
 
452
        {
 
453
                s[i].x1 = x1 + i * dy[dir] + DOOR_CORNER_WIDTH * dx[dir];
 
454
                s[i].y1 = y1 - i * dx[dir] + DOOR_CORNER_WIDTH * dy[dir];
 
455
                s[i].x2 = x2 + i * dy[dir] - DOOR_CORNER_WIDTH * dx[dir];
 
456
                s[i].y2 = y2 - i * dx[dir] - DOOR_CORNER_WIDTH * dy[dir];
 
457
        }
 
458
 
 
459
        XDrawSegments(XtDisplay(w), XtWindow(w), gc, s, WALL_WIDTH);
 
460
 
 
461
        for (i = 0; i < WALL_WIDTH; i++)
 
462
        {
 
463
                s[i].x1 = x1 + i * (dy[dir] + dx[dir]) + (i ? 0 : dx[dir]);
 
464
                s[i].y1 = y1 + i * (-dx[dir] + dy[dir]) + (i ? 0 : dy[dir]);
 
465
                s[i].x2 = x1 + i * dy[dir] + (DOOR_CORNER_WIDTH - 1) * dx[dir];
 
466
                s[i].y2 = y1 - i * dx[dir] + (DOOR_CORNER_WIDTH - 1) * dy[dir];
 
467
 
 
468
                s[i + WALL_WIDTH].x1 = x2 + i * dy[dir] -
 
469
                        (DOOR_CORNER_WIDTH - 1) * dx[dir];
 
470
                s[i + WALL_WIDTH].y1 = y2 - i * dx[dir] -
 
471
                        (DOOR_CORNER_WIDTH - 1) * dy[dir];
 
472
                s[i + WALL_WIDTH].x2 = x2 + i * (dy[dir] - dx[dir]) - dx[dir];
 
473
                s[i + WALL_WIDTH].y2 = y2 + i * (-dx[dir] - dy[dir]) - dy[dir];
 
474
        }
 
475
 
 
476
        XDrawSegments(XtDisplay(w), XtWindow(w),
 
477
                w->labEdit.foreground_gc, s, 2 * WALL_WIDTH);
 
478
}
 
479
 
 
480
 
 
481
static void draw_wall_or_door(LabEditWidget w, int x1, int y1, int x2, int y2,
 
482
        int dir, int color)
 
483
{
 
484
        if (color >= 8)
 
485
                draw_door(w, w->labEdit.door_gcs[color - 8],
 
486
                        x1, y1, x2, y2, dir);
 
487
        else if (color > 0)
 
488
                draw_wall(w, w->labEdit.wall_gcs[color - 1],
 
489
                        x1, y1, x2, y2, dir);
 
490
}
 
491
 
 
492
 
 
493
static int calculate_wall_color(LabEditWidget w, int x, int y, int dir)
 
494
{
 
495
        int l, r;
 
496
 
 
497
        if (!w->labEdit.wall_pending ||
 
498
                !w->labEdit.wall_is_vert && dir != NORTH && dir != SOUTH ||
 
499
                w->labEdit.wall_is_vert && dir != WEST && dir != EAST ||
 
500
                dir == NORTH && y != w->labEdit.wall_y0 ||
 
501
                dir == SOUTH && y + 1 != w->labEdit.wall_y0 ||
 
502
                dir == WEST && x != w->labEdit.wall_x0 ||
 
503
                dir == EAST && x + 1 != w->labEdit.wall_x0)
 
504
                return w->labEdit.walls[x][y][dir];
 
505
 
 
506
        l = w->labEdit.wall_length;
 
507
        if (w->labEdit.wall_is_vert)
 
508
                r = y - w->labEdit.wall_y0;
 
509
        else
 
510
                r = x - w->labEdit.wall_x0;
 
511
 
 
512
        if (l < 0 && (r < l || r > 0) ||
 
513
                l >= 0 && (r > l || r < 0))
 
514
                return w->labEdit.walls[x][y][dir];
 
515
        else
 
516
                return w->labEdit.wall_color;
 
517
}
 
518
 
 
519
 
 
520
static void LabEditExpose(Widget arg_w, XEvent *event, Region arg_r)
 
521
{
 
522
        LabEditWidget w;
 
523
        int x, y, h, v, width, height;
 
524
        int x1, y1, x2, y2;
 
525
 
 
526
        w = (LabEditWidget)arg_w;
 
527
        if (!XtIsRealized(arg_w))
 
528
                return;
 
529
 
 
530
        h = w->labEdit.h_cells;
 
531
        v = w->labEdit.v_cells;
 
532
 
 
533
        width = w->core.width;
 
534
        height = w->core.height;
 
535
 
 
536
        for (x = 0; x < h; x++)
 
537
        {
 
538
                x1 = width * x / h;
 
539
                x2 = width * (x + 1) / h - 1;
 
540
 
 
541
                if (x1 >= event->xexpose.x + event->xexpose.width ||
 
542
                        x2 < event->xexpose.x)
 
543
                        continue;
 
544
 
 
545
                for (y = 0; y < v; y++)
 
546
                {
 
547
                        XPoint p[4];
 
548
 
 
549
                        y1 = height * y / v;
 
550
                        y2 = height * (y + 1) / v - 1;
 
551
 
 
552
                        if (y1 >= event->xexpose.y + event->xexpose.height ||
 
553
                                y2 < event->xexpose.y)
 
554
                                continue;
 
555
 
 
556
                        p[0].x = x1;
 
557
                        p[0].y = y1;
 
558
                        p[1].x = x2;
 
559
                        p[1].y = y1;
 
560
                        p[2].x = x1;
 
561
                        p[2].y = y2;
 
562
                        p[3].x = x2;
 
563
                        p[3].y = y2;
 
564
 
 
565
                        XDrawPoints(XtDisplay(w), XtWindow(w),
 
566
                                w->labEdit.foreground_gc,
 
567
                                p, 4, CoordModeOrigin);
 
568
 
 
569
                        draw_wall_or_door(w, x2, y1, x1, y1, NORTH,
 
570
                                calculate_wall_color(w, x, y, NORTH));
 
571
 
 
572
                        draw_wall_or_door(w, x1, y1, x1, y2, WEST,
 
573
                                calculate_wall_color(w, x, y, WEST));
 
574
 
 
575
                        draw_wall_or_door(w, x1, y2, x2, y2, SOUTH,
 
576
                                calculate_wall_color(w, x, y, SOUTH));
 
577
 
 
578
                        draw_wall_or_door(w, x2, y2, x2, y1, EAST,
 
579
                                calculate_wall_color(w, x, y, EAST));
 
580
                }
 
581
        }
 
582
}
 
583
 
 
584
 
 
585
static void schedule_blocks(LabEditWidget w, int x, int y, int n_h, int n_v)
 
586
{
 
587
        int h, v, width, height;
 
588
        int x1, y1, x2, y2;
 
589
 
 
590
        h = w->labEdit.h_cells;
 
591
        v = w->labEdit.v_cells;
 
592
 
 
593
        width = w->core.width;
 
594
        height = w->core.height;
 
595
 
 
596
        x1 = width * x / h;
 
597
        x2 = width * (x + n_h) / h;
 
598
        y1 = height * y / v;
 
599
        y2 = height * (y + n_v) / v;
 
600
 
 
601
        XClearArea(XtDisplay(w), XtWindow(w), x1, y1, x2 - x1, y2 - y1, True);
 
602
}
 
603
 
 
604
 
 
605
static void refresh_pending_wall(LabEditWidget w)
 
606
{
 
607
        int dx, dy;
 
608
        int x, y, l;
 
609
 
 
610
        if (!w->labEdit.wall_pending)
 
611
                return;
 
612
 
 
613
        x = w->labEdit.wall_x0;
 
614
        y = w->labEdit.wall_y0;
 
615
 
 
616
        if (w->labEdit.wall_is_vert)
 
617
        {
 
618
                dx = 0;
 
619
                dy = 1;
 
620
        }
 
621
        else
 
622
        {
 
623
                dx = 1;
 
624
                dy = 0;
 
625
        }
 
626
 
 
627
        l = w->labEdit.wall_length;
 
628
        if (l < 0)
 
629
        {
 
630
                x += dx * w->labEdit.wall_length;
 
631
                y += dy * w->labEdit.wall_length;
 
632
 
 
633
                l = -l;
 
634
        }
 
635
 
 
636
        if (w->labEdit.wall_is_vert)
 
637
                schedule_blocks(w, x - 1, y, 2, l + 1);
 
638
        else
 
639
                schedule_blocks(w, x, y - 1, l + 1, 2);
 
640
}
 
641
 
 
642
 
 
643
static int find_wall(LabEditWidget w, XEvent *event, int *x_p, int *y_p,
 
644
        int *is_vert_p)
 
645
{
 
646
        int h, v, width, height;
 
647
        int a, b;
 
648
 
 
649
        if (!XtIsRealized((Widget)w))
 
650
                return 0;
 
651
 
 
652
        h = w->labEdit.h_cells;
 
653
        v = w->labEdit.v_cells;
 
654
 
 
655
        width = w->core.width;
 
656
        height = w->core.height;
 
657
 
 
658
        if (event->xbutton.x < 0 || event->xbutton.x >= width ||
 
659
                event->xbutton.y < 0 || event->xbutton.y >= height)
 
660
                return 0;
 
661
 
 
662
        a = (event->xbutton.x * h * height +
 
663
                (height - 1 - event->xbutton.y) * v * width) / width / height;
 
664
        b = (event->xbutton.x * h * height +
 
665
                event->xbutton.y * v * width) / width / height;
 
666
 
 
667
        if (*is_vert_p = (a + b) % 2)
 
668
        {
 
669
                /* vertical */
 
670
 
 
671
                *x_p = (a + b + 1 - v) / 2;
 
672
                *y_p = (b - a + v - 1) / 2;
 
673
 
 
674
                if (*x_p > 0 && *x_p < h && *y_p >= 0 && *y_p < v)
 
675
                        return 1;
 
676
        }
 
677
        else
 
678
        {
 
679
                /* horizontal */
 
680
 
 
681
                *x_p = (a + b - v) / 2;
 
682
                *y_p = (b - a + v) / 2;
 
683
 
 
684
                if (*x_p >= 0 && *x_p < h && *y_p > 0 && *y_p < v)
 
685
                        return 1;
 
686
        }
 
687
 
 
688
        return 0;
 
689
}
 
690
 
 
691
 
 
692
static void change_wall(LabEditWidget w, XEvent *event)
 
693
{
 
694
        w->labEdit.wall_length = 0;
 
695
        w->labEdit.wall_pending = find_wall(w, event, &w->labEdit.wall_x0,
 
696
                &w->labEdit.wall_y0, &w->labEdit.wall_is_vert);
 
697
}
 
698
 
 
699
 
 
700
/*
 
701
**      global
 
702
*/
 
703
 
 
704
 
 
705
void LabEditSetWall(Widget arg_w, int x, int y, int dir, int value)
 
706
{
 
707
        LabEditWidget w;
 
708
 
 
709
        w = (LabEditWidget)arg_w;
 
710
 
 
711
        if (x < 0 || x >= w->labEdit.h_cells ||
 
712
                y < 0 || y >= w->labEdit.v_cells ||
 
713
                dir < 0 || dir > 4)
 
714
                return;
 
715
 
 
716
        w->labEdit.walls[x][y][dir] = value;
 
717
 
 
718
        if (XtIsRealized(arg_w))
 
719
                schedule_blocks(w, x, y, 1, 1);
 
720
}
 
721
 
 
722
 
 
723
int LabEditGetWall(Widget arg_w, int x, int y, int dir)
 
724
{
 
725
        LabEditWidget w;
 
726
 
 
727
        w = (LabEditWidget)arg_w;
 
728
 
 
729
        if (x < 0 || x >= w->labEdit.h_cells ||
 
730
                y < 0 || y >= w->labEdit.v_cells ||
 
731
                dir < 0 || dir > 4)
 
732
                return 0; /* shouldn't happen */
 
733
 
 
734
        return w->labEdit.walls[x][y][dir];
 
735
}
 
736
 
 
737
 
 
738
void LabEditStartAddWall(Widget arg_w, XEvent *event, String *params,
 
739
        Cardinal *n_params)
 
740
{
 
741
        LabEditWidget w;
 
742
 
 
743
        w = (LabEditWidget)arg_w;
 
744
 
 
745
        LabEditAbortWall(arg_w, event, params, n_params);
 
746
 
 
747
        w->labEdit.wall_color = DEFAULT_WALL;
 
748
        change_wall(w, event);
 
749
        refresh_pending_wall(w);
 
750
}
 
751
 
 
752
 
 
753
void LabEditStartRemoveWall(Widget arg_w, XEvent *event, String *params,
 
754
        Cardinal *n_params)
 
755
{
 
756
        LabEditWidget w;
 
757
 
 
758
        w = (LabEditWidget)arg_w;
 
759
 
 
760
        LabEditAbortWall(arg_w, event, params, n_params);
 
761
 
 
762
        w->labEdit.wall_color = 0;
 
763
        change_wall(w, event);
 
764
        refresh_pending_wall(w);
 
765
}
 
766
 
 
767
 
 
768
void LabEditExtendWall(Widget arg_w, XEvent *event, String *params,
 
769
        Cardinal *n_params)
 
770
{
 
771
        LabEditWidget w;
 
772
        int h, v, width, height, old_l, new_l;
 
773
        int bx, by;
 
774
 
 
775
        w = (LabEditWidget)arg_w;
 
776
 
 
777
        if (!XtIsRealized(arg_w))
 
778
                return;
 
779
 
 
780
        if (!w->labEdit.wall_pending)
 
781
                return;
 
782
 
 
783
        h = w->labEdit.h_cells;
 
784
        v = w->labEdit.v_cells;
 
785
 
 
786
        width = w->core.width;
 
787
        height = w->core.height;
 
788
 
 
789
        old_l = w->labEdit.wall_length;
 
790
 
 
791
        if (event->xbutton.x < 0 || event->xbutton.x >= width ||
 
792
                event->xbutton.y < 0 || event->xbutton.y >= height)
 
793
                return;
 
794
 
 
795
        bx = event->xbutton.x * h / width;
 
796
        by = event->xbutton.y * v / height;
 
797
 
 
798
        if (w->labEdit.wall_is_vert)
 
799
                new_l = by - w->labEdit.wall_y0;
 
800
        else
 
801
                new_l = bx - w->labEdit.wall_x0;
 
802
 
 
803
        if (new_l == old_l)
 
804
                return;
 
805
 
 
806
        if (old_l > 0 && new_l < old_l || old_l < 0 && new_l > old_l)
 
807
                refresh_pending_wall(w);
 
808
 
 
809
        w->labEdit.wall_length = new_l;
 
810
        refresh_pending_wall(w);
 
811
}
 
812
 
 
813
 
 
814
void LabEditFinishWall(Widget arg_w, XEvent *event, String *params,
 
815
        Cardinal *n_params)
 
816
{
 
817
        LabEditWidget w;
 
818
        int x, y, l, dx, dy;
 
819
        int is_vert, color;
 
820
 
 
821
        w = (LabEditWidget)arg_w;
 
822
 
 
823
        if (!XtIsRealized(arg_w))
 
824
                return;
 
825
 
 
826
        if (!w->labEdit.wall_pending)
 
827
                return;
 
828
 
 
829
        x = w->labEdit.wall_x0;
 
830
        y = w->labEdit.wall_y0;
 
831
        l = w->labEdit.wall_length;
 
832
        color = w->labEdit.wall_color;
 
833
 
 
834
        if (is_vert = w->labEdit.wall_is_vert)
 
835
        {
 
836
                dx = 0;
 
837
                dy = 1;
 
838
        }
 
839
        else
 
840
        {
 
841
                dx = 1;
 
842
                dy = 0;
 
843
        }
 
844
 
 
845
        if (l < 0)
 
846
        {
 
847
                dx = -dx;
 
848
                dy = -dy;
 
849
                l = -l;
 
850
        }
 
851
 
 
852
        for (l++; l--; x += dx, y += dy)
 
853
                if (is_vert)
 
854
                {
 
855
                        w->labEdit.walls[x][y][WEST] = color;
 
856
                        w->labEdit.walls[x - 1][y][EAST] = color;
 
857
                }
 
858
                else
 
859
                {
 
860
                        w->labEdit.walls[x][y][NORTH] = color;
 
861
                        w->labEdit.walls[x][y - 1][SOUTH] = color;
 
862
                }
 
863
 
 
864
        refresh_pending_wall(w);
 
865
        w->labEdit.wall_pending = 0;
 
866
        w->labEdit.modified = 1;
 
867
}
 
868
 
 
869
 
 
870
void LabEditAbortWall(Widget arg_w, XEvent *event, String *params,
 
871
        Cardinal *n_params)
 
872
{
 
873
        LabEditWidget w;
 
874
 
 
875
        w = (LabEditWidget)arg_w;
 
876
 
 
877
        refresh_pending_wall(w);
 
878
        w->labEdit.wall_pending = 0;
 
879
}
 
880
 
 
881
 
 
882
void LabEditToggleDoor(Widget arg_w, XEvent *event, String *params,
 
883
        Cardinal *n_params)
 
884
{
 
885
        LabEditWidget w;
 
886
        int x, y, is_vert;
 
887
        char *wall1, *wall2;
 
888
 
 
889
        w = (LabEditWidget)arg_w;
 
890
 
 
891
        if (!XtIsRealized(arg_w))
 
892
                return;
 
893
 
 
894
        LabEditAbortWall(arg_w, event, params, n_params);
 
895
 
 
896
        if (!find_wall(w, event, &x, &y, &is_vert))
 
897
                return;
 
898
 
 
899
        if (is_vert)
 
900
        {
 
901
                wall1 = &w->labEdit.walls[x - 1][y][EAST];
 
902
                wall2 = &w->labEdit.walls[x][y][WEST];
 
903
        }
 
904
        else
 
905
        {
 
906
                wall1 = &w->labEdit.walls[x][y - 1][SOUTH];
 
907
                wall2 = &w->labEdit.walls[x][y][NORTH];
 
908
        }
 
909
 
 
910
        if (IS_DOOR_COLOR(*wall1))
 
911
                if (IS_DOOR_COLOR(*wall2))
 
912
                {
 
913
                        *wall2 = DEFAULT_WALL;
 
914
                        schedule_blocks(w, x, y, 1, 1);
 
915
                        return;
 
916
                }
 
917
                else
 
918
                {
 
919
                        *wall2 = random_door_color();
 
920
                        *wall1 = DEFAULT_WALL;
 
921
                }
 
922
        else if (IS_DOOR_COLOR(*wall2))
 
923
                *wall1 = random_door_color();
 
924
        else
 
925
        {
 
926
                *wall1 = random_door_color();
 
927
                *wall2 = random_door_color();
 
928
        }
 
929
 
 
930
        if (is_vert)
 
931
                schedule_blocks(w, x - 1, y, 2, 1);
 
932
        else
 
933
                schedule_blocks(w, x, y - 1, 1, 2);
 
934
 
 
935
        w->labEdit.modified = 1;
 
936
}
 
937
 
 
938
 
 
939
void LabEditClear(Widget arg_w)
 
940
{
 
941
        LabEditWidget w;
 
942
        int h, v, x, y, i;
 
943
 
 
944
        w = (LabEditWidget)arg_w;
 
945
 
 
946
        w->labEdit.modified = 0;
 
947
 
 
948
        h = w->labEdit.h_cells;
 
949
        v = w->labEdit.v_cells;
 
950
 
 
951
        for (x = 0; x < h; x++)
 
952
        {
 
953
 
 
954
                for (y = 0; y < v; y++)
 
955
                        for (i = 0; i < 4; i++)
 
956
                                w->labEdit.walls[x][y][i] = 0;
 
957
 
 
958
                w->labEdit.walls[x][0][NORTH] = DEFAULT_WALL;
 
959
                w->labEdit.walls[x][v - 1][SOUTH] = DEFAULT_WALL;
 
960
        }
 
961
 
 
962
        for (y = 0; y < v; y++)
 
963
        {
 
964
                w->labEdit.walls[0][y][WEST] = DEFAULT_WALL;
 
965
                w->labEdit.walls[h - 1][y][EAST] = DEFAULT_WALL;
 
966
        }
 
967
 
 
968
        w->labEdit.wall_pending = 0;
 
969
 
 
970
        if (!XtIsRealized(arg_w))
 
971
                return;
 
972
 
 
973
        schedule_blocks(w, 0, 0, h, v);
 
974
}
 
975
 
 
976
 
 
977
void LabEditSetUnmodified(Widget arg_w)
 
978
{
 
979
        LabEditWidget w;
 
980
 
 
981
        w = (LabEditWidget)arg_w;
 
982
 
 
983
        w->labEdit.modified = 0;
 
984
}
 
985
 
 
986
 
 
987
int LabEditIsModified(Widget arg_w)
 
988
{
 
989
        LabEditWidget w;
 
990
 
 
991
        w = (LabEditWidget)arg_w;
 
992
 
 
993
        return w->labEdit.modified;
 
994
}