|
|
1.1 root 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 [email protected].
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.