]> git.zerfleddert.de Git - micropolis/blob - src/sim/w_cam.c
correctly resize editor window to be in sync with the mini map
[micropolis] / src / sim / w_cam.c
1 /* w_cam.c
2 *
3 * Micropolis, Unix Version. This game was released for the Unix platform
4 * in or about 1990 and has been modified for inclusion in the One Laptop
5 * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If
6 * you need assistance with this program, you may contact:
7 * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org.
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details. You should have received a
18 * copy of the GNU General Public License along with this program. If
19 * not, see <http://www.gnu.org/licenses/>.
20 *
21 * ADDITIONAL TERMS per GNU GPL Section 7
22 *
23 * No trademark or publicity rights are granted. This license does NOT
24 * give you any right, title or interest in the trademark SimCity or any
25 * other Electronic Arts trademark. You may not distribute any
26 * modification of this program using the trademark SimCity or claim any
27 * affliation or association with Electronic Arts Inc. or its employees.
28 *
29 * Any propagation or conveyance of this program must include this
30 * copyright notice and these terms.
31 *
32 * If you convey this program (or any modifications of it) and assume
33 * contractual liability for the program to recipients of it, you agree
34 * to indemnify Electronic Arts for any liability that those contractual
35 * assumptions impose on Electronic Arts.
36 *
37 * You may not misrepresent the origins of this program; modified
38 * versions of the program must be marked as such and not identified as
39 * the original program.
40 *
41 * This disclaimer supplements the one included in the General Public
42 * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
43 * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
44 * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
45 * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
46 * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
47 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
48 * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
49 * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
50 * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
51 * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
52 * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
53 * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
54 * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
55 * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
56 * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
57 * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
58 * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
59 * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
60 * NOT APPLY TO YOU.
61 */
62 #include "sim.h"
63
64
65 #ifdef CAM
66
67
68 Tk_ConfigSpec SimCamConfigSpecs[] = {
69 {TK_CONFIG_PIXELS, "-width", "width", "Width",
70 0, Tk_Offset(SimCam, w_width), 0},
71 {TK_CONFIG_PIXELS, "-height", "height", "Height",
72 0, Tk_Offset(SimCam, w_height), 0},
73 {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
74 (char *) NULL, 0, 0}
75 };
76
77
78 Tk_ConfigSpec CamConfigSpecs[] = {
79 {TK_CONFIG_PIXELS, "-wrap", "wrap", "Wrap",
80 0, Tk_Offset(Cam, wrap), 0},
81 {TK_CONFIG_PIXELS, "-steps", "steps", "Steps",
82 0, Tk_Offset(Cam, steps), 0},
83 {TK_CONFIG_PIXELS, "-frob", "frob", "Frob",
84 0, Tk_Offset(Cam, frob), 0},
85 {TK_CONFIG_PIXELS, "-x", "x", "X",
86 0, Tk_Offset(Cam, x), 0},
87 {TK_CONFIG_PIXELS, "-y", "y", "Y",
88 0, Tk_Offset(Cam, y), 0},
89 {TK_CONFIG_PIXELS, "-width", "width", "Width",
90 0, Tk_Offset(Cam, width), 0},
91 {TK_CONFIG_PIXELS, "-height", "height", "Height",
92 0, Tk_Offset(Cam, height), 0},
93 {TK_CONFIG_PIXELS, "-dx", "dx", "Dx",
94 0, Tk_Offset(Cam, dx), 0},
95 {TK_CONFIG_PIXELS, "-dy", "dy", "Dy",
96 0, Tk_Offset(Cam, dy), 0},
97 {TK_CONFIG_PIXELS, "-gx", "gx", "Gx",
98 0, Tk_Offset(Cam, gx), 0},
99 {TK_CONFIG_PIXELS, "-gy", "gy", "Gy",
100 0, Tk_Offset(Cam, gy), 0},
101 {TK_CONFIG_PIXELS, "-dragging", "dragging", "Dragging",
102 0, Tk_Offset(Cam, dragging), 0},
103 {TK_CONFIG_PIXELS, "-setx", "setx", "SetX",
104 "-1", Tk_Offset(Cam, set_x), 0},
105 {TK_CONFIG_PIXELS, "-sety", "sety", "SetY",
106 "-1", Tk_Offset(Cam, set_y), 0},
107 {TK_CONFIG_PIXELS, "-setwidth", "setwidth", "SetWidth",
108 "-1", Tk_Offset(Cam, set_width), 0},
109 {TK_CONFIG_PIXELS, "-setheight", "setheight", "SetHeight",
110 "-1", Tk_Offset(Cam, set_height), 0},
111 {TK_CONFIG_PIXELS, "-setx0", "setx0", "SetX0",
112 "-1", Tk_Offset(Cam, set_x0), 0},
113 {TK_CONFIG_PIXELS, "-sety0", "sety0", "SetY0",
114 "-1", Tk_Offset(Cam, set_y0), 0},
115 {TK_CONFIG_PIXELS, "-setx1", "setx1", "SetX1",
116 "-1", Tk_Offset(Cam, set_x1), 0},
117 {TK_CONFIG_PIXELS, "-sety1", "sety1", "SetY1",
118 "-1", Tk_Offset(Cam, set_y1), 0},
119 {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
120 (char *) NULL, 0, 0}
121 };
122
123
124 Tcl_HashTable CamCmds;
125
126 int next_cam_id = 1;
127
128
129 static void
130 DisplaySimCam(ClientData clientData)
131 {
132 SimCam *scam = (SimCam *) clientData;
133 Tk_Window tkwin = scam->tkwin;
134 Pixmap pm = None;
135 Drawable d;
136
137 scam->flags &= ~VIEW_REDRAW_PENDING;
138 if (scam->visible && (tkwin != NULL) && Tk_IsMapped(tkwin)) {
139 DoUpdateCam(scam);
140 }
141 }
142
143
144 void
145 DestroyCam(SimCam *scam, Cam *cam)
146 {
147 Cam **cp;
148
149 for (cp = &scam->cam_list;
150 (*cp) != NULL;
151 cp = &((*cp)->next)) {
152 if ((*cp) == cam) {
153 (*cp) = cam->next;
154 scam->cam_count--;
155 if (cam->front != NULL) {
156 ckfree(cam->front);
157 }
158 if (cam->back != NULL) {
159 if (cam->back->mem != NULL) {
160 ckfree(cam->back->mem);
161 }
162 ckfree(cam->back);
163 }
164 if (cam->rule != NULL) {
165 ckfree(cam->rule);
166 }
167 if (cam->name != NULL) {
168 ckfree(cam->name);
169 }
170 ckfree(cam);
171 break;
172 }
173 }
174 }
175
176
177 void
178 DestroyScam(ClientData cdata)
179 {
180 SimCam *scam = (SimCam *)cdata;
181 SimCam **cp;
182
183 CancelRedrawView(scam);
184
185 while (scam->cam_list) {
186 DestroyCam(scam, scam->cam_list);
187 }
188
189 for (cp = &sim->scam;
190 (*cp) != NULL;
191 cp = &((*cp)->next)) {
192 if ((*cp) == scam) {
193 (*cp) = scam->next;
194 sim->scams--;
195 break;
196 }
197 }
198
199 if (scam->shminfo != NULL) {
200 XShmDetach(scam->x->dpy, scam->shminfo);
201 shmdt(scam->shminfo->shmaddr);
202 shmctl(scam->shminfo->shmid, IPC_RMID, 0);
203 ckfree(scam->shminfo);
204 scam->shminfo = NULL;
205 if (scam->image) {
206 scam->image->data = NULL;
207 scam->data = NULL;
208 XDestroyImage(scam->image);
209 scam->image = NULL;
210 }
211 } else {
212 if (scam->image) {
213 if (scam->image->data) {
214 ckfree(scam->image->data);
215 scam->image->data = NULL;
216 }
217 scam->data = NULL;
218 XDestroyImage(scam->image);
219 scam->image = NULL;
220 }
221 }
222
223 DecRefDisplay(scam->x);
224
225 ckfree((char *) scam);
226 }
227
228
229 void
230 CamEventProc(ClientData clientData, XEvent *eventPtr)
231 {
232 SimCam *scam = (SimCam *) clientData;
233
234 if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
235 scam->visible = 1;
236 EventuallyRedrawCam(scam);
237 } else if (eventPtr->type == MapNotify) {
238 scam->visible = 1;
239 } else if (eventPtr->type == UnmapNotify) {
240 scam->visible = 0;
241 } else if (eventPtr->type == VisibilityNotify) {
242 if (eventPtr->xvisibility.state == VisibilityFullyObscured)
243 scam->visible = 0;
244 else
245 scam->visible = 1;
246 } else if (eventPtr->type == ConfigureNotify) {
247 DoResizeCam(scam,
248 eventPtr->xconfigure.width,
249 eventPtr->xconfigure.height);
250 EventuallyRedrawCam(scam);
251 } else if (eventPtr->type == DestroyNotify) {
252 Tcl_DeleteCommand(scam->interp, Tk_PathName(scam->tkwin));
253 scam->tkwin = NULL;
254 if (scam->flags & VIEW_REDRAW_PENDING) {
255 Tk_CancelIdleCall(DisplaySimCam, (ClientData) scam);
256 }
257 Tk_EventuallyFree((ClientData) scam, DestroyScam);
258 }
259 }
260
261
262 int
263 DoCamCmd(CLIENT_ARGS)
264 {
265 SimCam *scam = (SimCam *) clientData;
266 Tcl_HashEntry *ent;
267 int result = TCL_OK;
268 int (*cmd)();
269
270 if (argc < 2) {
271 return TCL_ERROR;
272 }
273
274 if (ent = Tcl_FindHashEntry(&CamCmds, argv[1])) {
275 cmd = (int (*)())ent->clientData;
276 Tk_Preserve((ClientData) scam);
277 result = cmd(scam, interp, argc, argv);
278 Tk_Release((ClientData) scam);
279 } else {
280 Tcl_AppendResult(interp, "unknown command name: \"",
281 argv[0], " ", argv[1], "\".", (char *) NULL);
282 result = TCL_ERROR;
283 }
284 return result;
285 }
286
287
288 int
289 CamCmd(CLIENT_ARGS)
290 {
291 Tk_Window tkwin = (Tk_Window) clientData;
292 SimCam *scam;
293
294 if (argc < 2) {
295 Tcl_AppendResult(interp, "wrong # args: should be \"",
296 argv[0], " pathName ?options?\"", (char *) NULL);
297 return TCL_ERROR;
298 }
299
300 tkwin = Tk_CreateWindowFromPath(interp, tkwin,
301 argv[1], (char *) NULL);
302 if (tkwin == NULL) {
303 return TCL_ERROR;
304 }
305
306 scam = (SimCam *)ckalloc(sizeof (SimCam));
307
308 scam->w_x = 0;
309 scam->w_y = 0;
310 scam->w_width = 0;
311 scam->w_height = 0;
312 scam->visible = 0;
313 scam->invalid = 1;
314 scam->skips = 0;
315 scam->skip = 0;
316 scam->tkwin = tkwin;
317 scam->interp = interp;
318 scam->flags = 0;
319 scam->x = NULL;
320 scam->image = NULL;
321 scam->shminfo = NULL;
322 scam->line_bytes = 0;
323 scam->data = NULL;
324 scam->cam_count = 0;
325 scam->cam_list = NULL;
326
327 Tk_SetClass(scam->tkwin, "Cam");
328
329 Tk_CreateEventHandler(scam->tkwin,
330 VisibilityChangeMask |
331 ExposureMask |
332 StructureNotifyMask |
333 EnterWindowMask |
334 LeaveWindowMask |
335 PointerMotionMask,
336 CamEventProc, (ClientData) scam);
337 Tcl_CreateCommand(interp, Tk_PathName(scam->tkwin),
338 DoCamCmd, (ClientData) scam, (void (*)()) NULL);
339
340 Tk_MakeWindowExist(scam->tkwin);
341
342 if (getenv("XSYNCHRONIZE") != NULL) {
343 XSynchronize(Tk_Display(tkwin), 1);
344 }
345
346 InitNewCam(scam);
347 DoNewCam(scam);
348
349 if (ConfigureCam(interp, scam, argc-2, argv+2, 0) != TCL_OK) {
350 /* XXX: destroy scam */
351 Tk_DestroyWindow(scam->tkwin);
352 return TCL_ERROR;
353 }
354
355 scam->invalid = 1;
356
357 interp->result = Tk_PathName(scam->tkwin);
358 return TCL_OK;
359 }
360
361
362 int
363 ConfigureCam(Tcl_Interp *interp, SimCam *scam,
364 int argc, char **argv, int flags)
365 {
366 if (Tk_ConfigureWidget(interp, scam->tkwin, SimCamConfigSpecs,
367 argc, argv, (char *) scam, flags) != TCL_OK) {
368 return TCL_ERROR;
369 }
370
371 if (scam->w_width || scam->w_height) {
372 Tk_GeometryRequest(scam->tkwin, scam->w_width, scam->w_height);
373 }
374
375 EventuallyRedrawCam(scam);
376
377 return TCL_OK;
378 }
379
380
381 EventuallyRedrawCam(SimCam *scam)
382 {
383 if (!(scam->flags & VIEW_REDRAW_PENDING)) {
384 Tk_DoWhenIdle(DisplaySimCam, (ClientData) scam);
385 scam->flags |= VIEW_REDRAW_PENDING;
386 }
387 }
388
389
390 CamCmdconfigure(CAM_ARGS)
391 {
392 int result = TCL_OK;
393
394 if (argc == 2) {
395 result = Tk_ConfigureInfo(interp, scam->tkwin, SimCamConfigSpecs,
396 (char *) scam, (char *) NULL, 0);
397 } else if (argc == 3) {
398 result = Tk_ConfigureInfo(interp, scam->tkwin, SimCamConfigSpecs,
399 (char *) scam, argv[2], 0);
400 } else {
401 result = ConfigureCam(interp, scam, argc-2, argv+2,
402 TK_CONFIG_ARGV_ONLY);
403 }
404 return result;
405 }
406
407
408 CamCmdposition(CAM_ARGS)
409 {
410 if ((argc != 2) && (argc != 4)) {
411 return TCL_ERROR;
412 }
413 if (argc == 4) {
414 int x, y;
415
416 if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
417 || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
418 return TCL_ERROR;
419 }
420 scam->w_x = x;
421 scam->w_y = y;
422 }
423 sprintf(interp->result, "%d %d", scam->w_x, scam->w_y);
424 return TCL_OK;
425 }
426
427
428 CamCmdsize(CAM_ARGS)
429 {
430 if ((argc != 2) && (argc != 4)) {
431 return TCL_ERROR;
432 }
433 if (argc == 4) {
434 int w, h;
435
436 if (Tcl_GetInt(interp, argv[2], &w) != TCL_OK) {
437 return TCL_ERROR;
438 }
439 if (Tcl_GetInt(interp, argv[3], &h) != TCL_OK) {
440 return TCL_ERROR;
441 }
442 scam->w_width = w;
443 scam->w_height = h;
444 }
445 sprintf(interp->result, "%d %d", scam->w_width, scam->w_height);
446 return TCL_OK;
447 }
448
449
450 CamCmdVisible(CAM_ARGS)
451 {
452 int visible;
453
454 if ((argc != 2) && (argc != 3)) {
455 return TCL_ERROR;
456 }
457
458 if (argc == 3) {
459 if ((Tcl_GetInt(interp, argv[2], &visible) != TCL_OK) ||
460 (visible < 0) || (visible > 1)) {
461 return TCL_ERROR;
462 }
463
464 visible = visible && Tk_IsMapped(scam->tkwin);
465 scam->visible = visible;
466 }
467
468 sprintf(interp->result, "%d", scam->visible);
469 return TCL_OK;
470 }
471
472
473 CamCmdStoreColor(CAM_ARGS)
474 {
475 int index, r, g, b, err;
476 XColor color;
477
478 if (argc != 6) {
479 return TCL_ERROR;
480 }
481
482 if ((Tcl_GetInt(interp, argv[2], &index) != TCL_OK) ||
483 (Tcl_GetInt(interp, argv[2], &r) != TCL_OK) ||
484 (Tcl_GetInt(interp, argv[2], &g) != TCL_OK) ||
485 (Tcl_GetInt(interp, argv[2], &b) != TCL_OK)) {
486 return TCL_ERROR;
487 }
488
489 color.pixel = index;
490 color.red = r;
491 color.green = g;
492 color.blue = b;
493 color.flags = DoRed | DoGreen | DoBlue;
494 err = XStoreColor(scam->x->dpy, scam->x->colormap, &color);
495
496 sprintf(interp->result, "%d", err);
497 return TCL_OK;
498 }
499
500
501 CamCmdNewCam(CAM_ARGS)
502 {
503 Cam *cam;
504 char *name;
505 char *rule_name = NULL;
506 int rule_number = 0;
507 int x, y, w, h;
508
509 if (argc < 8) {
510 return TCL_ERROR;
511 }
512
513 name = argv[2];
514
515 if ((Tcl_GetInt(interp, argv[3], &rule_number) != TCL_OK) ||
516 (rule_number == 0)) {
517 rule_name = argv[3];
518 }
519
520 if ((Tcl_GetInt(interp, argv[4], &x) != TCL_OK) ||
521 (Tcl_GetInt(interp, argv[5], &y) != TCL_OK) ||
522 (Tcl_GetInt(interp, argv[6], &w) != TCL_OK) ||
523 (Tcl_GetInt(interp, argv[7], &h) != TCL_OK)) {
524 return TCL_ERROR;
525 }
526
527 cam = (Cam *)find_cam_by_name(scam, name);
528
529 if (cam != NULL) {
530 DestroyCam(scam, cam);
531 }
532
533 cam = (Cam *)new_cam(scam, x, y, w, h, 0, 0, NULL);
534 cam->name = (char *)malloc(strlen(name) + 1);
535 strcpy(cam->name, name);
536
537 if (rule_name != NULL) {
538 cam_load_rule(cam, rule_name);
539 } else {
540 cam_set_neighborhood(cam, rule_number);
541 }
542
543 return Tk_ConfigureWidget(interp, scam->tkwin, CamConfigSpecs,
544 argc - 8, argv + 8, (char *) cam, 0);
545 }
546
547
548 CamCmdDeleteCam(CAM_ARGS)
549 {
550 Cam *cam;
551 char *name;
552
553 if (argc != 3) {
554 return TCL_ERROR;
555 }
556
557 name = argv[2];
558
559 cam = (Cam *)find_cam_by_name(scam, name);
560
561 if (cam != NULL) {
562 DestroyCam(scam, cam);
563 }
564
565 return TCL_OK;
566 }
567
568
569 CamCmdRandomizeCam(CAM_ARGS)
570 {
571 Cam *cam;
572 char *name;
573
574 if (argc != 3) {
575 return TCL_ERROR;
576 }
577
578 name = argv[2];
579
580 cam = (Cam *)find_cam_by_name(scam, name);
581
582 if (cam != NULL) {
583 cam_randomize(cam);
584 }
585
586 return TCL_OK;
587 }
588
589
590 CamCmdConfigCam(CAM_ARGS)
591 {
592 Cam *cam;
593 int result = TCL_OK;
594
595 if (argc < 3) {
596 return TCL_ERROR;
597 }
598
599 cam = (Cam *)find_cam_by_name(scam, argv[2]);
600
601 if (cam == NULL) {
602 return TCL_ERROR;
603 }
604
605 if (argc == 3) {
606 result = Tk_ConfigureInfo(interp, scam->tkwin, CamConfigSpecs,
607 (char *) cam, (char *) NULL, 0);
608 } else if (argc == 4) {
609 result = Tk_ConfigureInfo(interp, scam->tkwin, CamConfigSpecs,
610 (char *) cam, argv[3], 0);
611 } else {
612 result = Tk_ConfigureWidget(interp, scam->tkwin, CamConfigSpecs,
613 argc - 3, argv + 3, (char *) cam, 0);
614 }
615
616 return result;
617 }
618
619
620 CamCmdFindCam(CAM_ARGS)
621 {
622 Cam *cam;
623 int x, y;
624
625 if (argc != 4) {
626 return TCL_ERROR;
627 }
628
629 if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
630 (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
631 return TCL_ERROR;
632 }
633
634 cam = (Cam *)find_cam(scam, x, y);
635 sprintf(interp->result, "%s", (cam == NULL) ? "" : cam->name);
636
637 return TCL_OK;
638 }
639
640
641 CamCmdFindSomeCam(CAM_ARGS)
642 {
643 Cam *cam;
644 int x, y;
645
646 if (argc != 4) {
647 return TCL_ERROR;
648 }
649
650 if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
651 (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
652 return TCL_ERROR;
653 }
654
655 cam = (Cam *)find_cam(scam, x, y);
656 if (cam == NULL) {
657 cam = scam->cam_list;
658 }
659
660 sprintf(interp->result, "%s", (cam == NULL) ? "" : cam->name);
661
662 return TCL_OK;
663 }
664
665 /*************************************************************************/
666
667 InitNewCam(SimCam *scam)
668 {
669 scam->x = (XDisplay *)FindXDisplay(scam->tkwin);
670 IncRefDisplay(scam->x);
671
672 DoResizeCam(scam, 512, 512);
673
674 init_scam(scam);
675 }
676
677
678 DoResizeCam(SimCam *scam, int w, int h)
679 {
680 Cam *cam;
681
682 for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
683 if (cam->front->width > w) w = cam->front->width;
684 if (cam->front->height > h) h = cam->front->height;
685 }
686
687 scam->w_width = w;
688 scam->w_height = h;
689
690 if (scam->shminfo != NULL) {
691 XShmDetach(scam->x->dpy, scam->shminfo);
692 shmdt(scam->shminfo->shmaddr);
693 shmctl(scam->shminfo->shmid, IPC_RMID, 0);
694 ckfree(scam->shminfo);
695 scam->shminfo = NULL;
696 if (scam->image) {
697 scam->image->data = NULL;
698 scam->data = NULL;
699 XDestroyImage(scam->image);
700 scam->image = NULL;
701 }
702 } else {
703 if (scam->image) {
704 if (scam->image->data) {
705 ckfree(scam->image->data);
706 scam->image->data = NULL;
707 }
708 scam->data = NULL;
709 XDestroyImage(scam->image);
710 scam->image = NULL;
711 }
712 }
713
714 if (scam->x->shared) {
715 scam->shminfo = (XShmSegmentInfo *)ckalloc(sizeof (XShmSegmentInfo));
716
717 scam->image =
718 XShmCreateImage(scam->x->dpy, scam->x->visual, scam->x->depth,
719 scam->x->color ? ZPixmap : XYBitmap,
720 NULL, scam->shminfo,
721 scam->w_width, scam->w_height);
722
723 scam->line_bytes = scam->image->bytes_per_line;
724 scam->shminfo->readOnly = False;
725 scam->shminfo->shmid = shmget(IPC_PRIVATE,
726 (scam->line_bytes *
727 scam->w_height),
728 (IPC_CREAT | 0777));
729 if (scam->shminfo->shmid < 0) {
730 perror("shmget");
731 fprintf(stderr,
732 "Drat, Micropolis can't share memory with X display \"%s\".\n",
733 scam->x->display);
734 goto FALL_BACK;
735 }
736
737 scam->data = (unsigned char *)shmat(scam->shminfo->shmid, 0, 0);
738 scam->image->data = (char *)scam->data;
739 if ((int)scam->data == -1) {
740 perror("shmat");
741 fprintf(stderr,
742 "Drat, Micropolis can't find any memory to share with display \"%s\".\n",
743 scam->x->display);
744 goto FALL_BACK;
745 }
746
747 scam->shminfo->shmaddr = (char *)scam->data;
748 scam->shminfo->readOnly = False;
749
750
751 { int (*old)();
752 int CatchXError();
753
754 GotXError = 0;
755 old = XSetErrorHandler(CatchXError);
756
757 if (XShmAttach(scam->x->dpy, scam->shminfo) == 0) {
758 fprintf(stderr,
759 "Drat, the X display \"%s\" can't access Micropolis's shared memory.\n",
760 scam->x->display);
761 GotXError = 1;
762 }
763
764 XSync(scam->x->dpy, False);
765
766 XSetErrorHandler(old);
767
768 if (GotXError) {
769 goto FALL_BACK;
770 }
771 }
772 } else {
773 goto SPRING_FORWARD;
774 FALL_BACK:
775 fprintf(stderr,
776 "Falling back to the X network protocol on display \"%s\"...\n",
777 scam->x->display);
778 SPRING_FORWARD:
779 scam->x->shared = 0;
780 if (scam->shminfo) {
781 if (scam->shminfo->shmid >= 0) {
782 if (scam->shminfo->shmaddr) {
783 shmdt(scam->shminfo->shmaddr);
784 }
785 shmctl(scam->shminfo->shmid, IPC_RMID, 0);
786 }
787 ckfree((char *)scam->shminfo);
788 scam->shminfo = NULL;
789 }
790 if (scam->image) {
791 scam->image->data = NULL;
792 XDestroyImage(scam->image);
793 scam->image = NULL;
794 }
795 scam->data = NULL;
796 scam->line_bytes = scam->w_width;
797 scam->data = (Byte *)ckalloc(scam->line_bytes * scam->w_height);
798 scam->image =
799 XCreateImage(scam->x->dpy, scam->x->visual,
800 scam->x->depth,
801 scam->x->color ? ZPixmap : XYBitmap,
802 0, (char *)scam->data,
803 scam->w_width, scam->w_height,
804 8, scam->line_bytes); /* XXX: handle other depths */
805 }
806
807 for (cam = scam->cam_list; cam != NULL; cam = cam->next) {
808 if (cam->x + cam->front->width > scam->w_width) {
809 cam->x = scam->w_width - cam->front->width;
810 }
811 if (cam->y + cam->front->height > scam->w_height) {
812 cam->y = scam->w_height - cam->front->height;
813 }
814 cam->front->line_bytes = scam->line_bytes;
815 cam->front->mem = /* XXX: handle other depths */
816 (Byte *)scam->data + cam->x + (scam->line_bytes * cam->y);
817 }
818 }
819
820
821 DoNewCam(SimCam *scam)
822 {
823 sim->scams++; scam->next = sim->scam; sim->scam = scam;
824 scam->invalid = 1;
825 }
826
827
828 DoUpdateCam(SimCam *scam)
829 {
830 if (!scam->visible) {
831 return;
832 }
833
834 if (scam->invalid) {
835 scam->invalid = 0;
836 }
837
838 if (scam->x->shared) {
839 XShmPutImage(scam->x->dpy, Tk_WindowId(scam->tkwin), scam->x->gc,
840 scam->image, 0, 0,
841 0, 0, scam->w_width, scam->w_height,
842 False);
843 } else {
844 XPutImage(scam->x->dpy, Tk_WindowId(scam->tkwin), scam->x->gc,
845 scam->image, 0, 0,
846 0, 0, scam->w_width, scam->w_height);
847 }
848 }
849
850
851 cam_command_init()
852 {
853 int new;
854 extern int TileCamCmd(CLIENT_ARGS);
855
856 Tcl_CreateCommand(tk_mainInterp, "camview", CamCmd,
857 (ClientData)MainWindow, (void (*)()) NULL);
858
859 Tcl_InitHashTable(&CamCmds, TCL_STRING_KEYS);
860
861 #define CAM_CMD(name) HASHED_CMD(Cam, name)
862
863 CAM_CMD(configure);
864 CAM_CMD(position);
865 CAM_CMD(size);
866 CAM_CMD(Visible);
867 CAM_CMD(StoreColor);
868 CAM_CMD(NewCam);
869 CAM_CMD(DeleteCam);
870 CAM_CMD(RandomizeCam);
871 CAM_CMD(ConfigCam);
872 CAM_CMD(FindCam);
873 CAM_CMD(FindSomeCam);
874 }
875
876
877 #endif /* CAM */
Impressum, Datenschutz