]>
Commit | Line | Data |
---|---|---|
6a5fa4e0 MG |
1 | /* w_date.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 | short NewDate = 0; | |
66 | Tcl_HashTable DateCmds; | |
67 | int DateUpdateTime = 200; | |
68 | ||
69 | ||
70 | #define DEF_DATE_FONT "-Adobe-Helvetica-Bold-R-Normal-*-140-*" | |
71 | #define DEF_DATE_BG_COLOR "#b0b0b0" | |
72 | #define DEF_DATE_BG_MONO "#ffffff" | |
73 | #define DEF_DATE_BORDER_WIDTH "2" | |
74 | #define DEF_DATE_PADY "1" | |
75 | #define DEF_DATE_PADX "1" | |
76 | #define DEF_DATE_WIDTH "0" | |
77 | #define DEF_DATE_MONTHTAB "7" | |
78 | #define DEF_DATE_YEARTAB "13" | |
79 | ||
80 | Tk_ConfigSpec DateConfigSpecs[] = { | |
81 | {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL, | |
82 | DEF_DATE_FONT, Tk_Offset(SimDate, fontPtr), 0}, | |
83 | {TK_CONFIG_BORDER, "-background", "background", "Background", | |
84 | DEF_DATE_BG_COLOR, Tk_Offset(SimDate, border), | |
85 | TK_CONFIG_COLOR_ONLY}, | |
86 | {TK_CONFIG_BORDER, "-background", "background", "Background", | |
87 | DEF_DATE_BG_MONO, Tk_Offset(SimDate, border), | |
88 | TK_CONFIG_MONO_ONLY}, | |
89 | {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", | |
90 | DEF_DATE_BORDER_WIDTH, Tk_Offset(SimDate, borderWidth), 0}, | |
91 | {TK_CONFIG_PIXELS, "-padx", "padX", "Pad", | |
92 | DEF_DATE_PADX, Tk_Offset(SimDate, padX), 0}, | |
93 | {TK_CONFIG_PIXELS, "-pady", "padY", "Pad", | |
94 | DEF_DATE_PADY, Tk_Offset(SimDate, padY), 0}, | |
95 | {TK_CONFIG_INT, "-width", "width", "Width", | |
96 | DEF_DATE_WIDTH, Tk_Offset(SimDate, width), 0}, | |
97 | {TK_CONFIG_INT, "-monthtab", "monthtab", "MonthTab", | |
98 | DEF_DATE_MONTHTAB, Tk_Offset(SimDate, monthTab), 0}, | |
99 | {TK_CONFIG_INT, "-yeartab", "yeartab", "YearTab", | |
100 | DEF_DATE_YEARTAB, Tk_Offset(SimDate, yearTab), 0}, | |
101 | {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, | |
102 | (char *) NULL, 0, 0} | |
103 | }; | |
104 | ||
105 | ||
106 | XDisplay *FindXDisplay(); | |
107 | ||
108 | ||
109 | static void | |
110 | DisplaySimDate(ClientData clientData) | |
111 | { | |
112 | SimDate *date = (SimDate *) clientData; | |
113 | Tk_Window tkwin = date->tkwin; | |
114 | Pixmap pm = None; | |
115 | Drawable d; | |
116 | ||
117 | date->flags &= ~VIEW_REDRAW_PENDING; | |
118 | //fprintf(stderr, "DisplaySimDate cleared VIEW_REDRAW_PENDING\n"); | |
119 | ||
120 | assert(date->draw_date_token != 0); | |
121 | if (date->draw_date_token != 0) { | |
122 | // Tk_DeleteTimerHandler(date->draw_date_token); | |
123 | date->draw_date_token = 0; | |
124 | } | |
125 | ||
126 | if (date->visible && (tkwin != NULL) && Tk_IsMapped(tkwin)) { | |
127 | DoUpdateDate(date); | |
128 | } | |
129 | } | |
130 | ||
131 | ||
132 | void | |
133 | DestroySimDate(ClientData clientData) | |
134 | { | |
135 | SimDate *date = (SimDate *) clientData; | |
136 | ||
137 | DestroyDate(date); | |
138 | } | |
139 | ||
140 | ||
141 | EventuallyRedrawDate(SimDate *date) | |
142 | { | |
143 | if (!(date->flags & VIEW_REDRAW_PENDING)) { | |
144 | assert(date->draw_date_token == 0); | |
145 | if (date->draw_date_token == 0) { | |
146 | date->draw_date_token = | |
147 | Tk_CreateTimerHandler( | |
148 | DateUpdateTime, | |
149 | DisplaySimDate, | |
150 | (ClientData) date); | |
151 | date->flags |= VIEW_REDRAW_PENDING; | |
152 | //fprintf(stderr, "EventuallyRedrawDate set VIEW_REDRAW_PENDING\n"); | |
153 | } | |
154 | } | |
155 | } | |
156 | ||
157 | ||
158 | void | |
159 | SimDateEventProc(ClientData clientData, XEvent *eventPtr) | |
160 | { | |
161 | SimDate *date = (SimDate *) clientData; | |
162 | ||
163 | if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) { | |
164 | date->visible = 1; | |
165 | EventuallyRedrawDate(date); | |
166 | } else if (eventPtr->type == MapNotify) { | |
167 | date->visible = 1; | |
168 | } else if (eventPtr->type == UnmapNotify) { | |
169 | date->visible = 0; | |
170 | } else if (eventPtr->type == VisibilityNotify) { | |
171 | if (eventPtr->xvisibility.state == VisibilityFullyObscured) | |
172 | date->visible = 0; | |
173 | else | |
174 | date->visible = 1; | |
175 | } else if (eventPtr->type == ConfigureNotify) { | |
176 | DoResizeDate(date, | |
177 | eventPtr->xconfigure.width, | |
178 | eventPtr->xconfigure.height); | |
179 | EventuallyRedrawDate(date); | |
180 | } else if (eventPtr->type == DestroyNotify) { | |
181 | Tcl_DeleteCommand(date->interp, Tk_PathName(date->tkwin)); | |
182 | date->tkwin = NULL; | |
183 | if (date->flags & VIEW_REDRAW_PENDING) { | |
184 | assert(date->draw_date_token != 0); | |
185 | if (date->draw_date_token != 0) { | |
186 | Tk_DeleteTimerHandler(date->draw_date_token); | |
187 | date->draw_date_token = 0; | |
188 | } | |
189 | date->flags &= ~VIEW_REDRAW_PENDING; | |
190 | //fprintf(stderr, "SimDateEventProc cleared VIEW_REDRAW_PENDING\n"); | |
191 | } | |
192 | Tk_EventuallyFree((ClientData) date, DestroySimDate); | |
193 | } | |
194 | } | |
195 | ||
196 | ||
197 | static void | |
198 | ComputeDateGeometry(SimDate *date) | |
199 | { | |
200 | XCharStruct bbox; | |
201 | int dummy; | |
202 | unsigned int width, height; | |
203 | int charWidth; | |
204 | ||
205 | XTextExtents(date->fontPtr, "0", 1, | |
206 | &dummy, &dummy, &dummy, &bbox); | |
207 | charWidth = (bbox.lbearing + bbox.rbearing); | |
208 | ||
209 | if (date->width == 0) { | |
210 | char *maxString = "Date: MMM 1000000"; | |
211 | int maxStringLength = strlen(maxString); | |
212 | ||
213 | XTextExtents(date->fontPtr, maxString, maxStringLength, | |
214 | &dummy, &dummy, &dummy, &bbox); | |
215 | width = bbox.lbearing + bbox.rbearing; | |
216 | } else { | |
217 | width = date->width * charWidth; | |
218 | } | |
219 | ||
220 | height = date->fontPtr->ascent + date->fontPtr->descent; | |
221 | ||
222 | width += 2 * date->padX; | |
223 | height += 2 * date->padY; | |
224 | ||
225 | Tk_GeometryRequest( | |
226 | date->tkwin, | |
227 | (int) (width + (2 * date->borderWidth) + 2), | |
228 | (int) (height + (2 * date->borderWidth) + 2)); | |
229 | Tk_SetInternalBorder( | |
230 | date->tkwin, | |
231 | date->borderWidth); | |
232 | ||
233 | date->yearTabX = date->yearTab * charWidth; | |
234 | date->monthTabX = date->monthTab * charWidth; | |
235 | } | |
236 | ||
237 | ||
238 | int DateCmdconfigure(DATE_ARGS) | |
239 | { | |
240 | int result = TCL_OK; | |
241 | ||
242 | if (argc == 2) { | |
243 | result = Tk_ConfigureInfo(interp, date->tkwin, DateConfigSpecs, | |
244 | (char *) date, (char *) NULL, 0); | |
245 | } else if (argc == 3) { | |
246 | result = Tk_ConfigureInfo(interp, date->tkwin, DateConfigSpecs, | |
247 | (char *) date, argv[2], 0); | |
248 | } else { | |
249 | result = ConfigureSimDate(interp, date, argc-2, argv+2, | |
250 | TK_CONFIG_ARGV_ONLY); | |
251 | } | |
252 | return TCL_OK; | |
253 | } | |
254 | ||
255 | ||
256 | int DateCmdposition(DATE_ARGS) | |
257 | { | |
258 | int result = TCL_OK; | |
259 | ||
260 | if ((argc != 2) && (argc != 4)) { | |
261 | return TCL_ERROR; | |
262 | } | |
263 | if (argc == 4) { | |
264 | if ((Tcl_GetInt(interp, argv[2], &date->w_x) != TCL_OK) | |
265 | || (Tcl_GetInt(interp, argv[3], &date->w_y) != TCL_OK)) { | |
266 | return TCL_ERROR; | |
267 | } | |
268 | } | |
269 | sprintf(interp->result, "%d %d", date->w_x, date->w_y); | |
270 | return TCL_OK; | |
271 | } | |
272 | ||
273 | ||
274 | int DateCmdsize(DATE_ARGS) | |
275 | { | |
276 | if ((argc != 2) && (argc != 4)) { | |
277 | return TCL_ERROR; | |
278 | } | |
279 | if (argc == 4) { | |
280 | int w, h; | |
281 | ||
282 | if (Tcl_GetInt(interp, argv[2], &w) != TCL_OK) { | |
283 | return TCL_ERROR; | |
284 | } | |
285 | if (Tcl_GetInt(interp, argv[3], &h) != TCL_OK) { | |
286 | return TCL_ERROR; | |
287 | } | |
288 | date->w_width = w; | |
289 | date->w_height = h; | |
290 | } | |
291 | sprintf(interp->result, "%d %d", date->w_width, date->w_height); | |
292 | return TCL_OK; | |
293 | } | |
294 | ||
295 | ||
296 | int DateCmdVisible(DATE_ARGS) | |
297 | { | |
298 | int visible; | |
299 | ||
300 | if ((argc != 2) && (argc != 3)) { | |
301 | Tcl_AppendResult(interp, "wrong # args", (char *) NULL); | |
302 | return TCL_ERROR; | |
303 | } | |
304 | ||
305 | if (argc == 3) { | |
306 | if ((Tcl_GetInt(interp, argv[2], &visible) != TCL_OK) || | |
307 | (visible < 0) || (visible > 1)) { | |
308 | Tcl_AppendResult(interp, " bogus args", (char *) NULL); | |
309 | return TCL_ERROR; | |
310 | } | |
311 | ||
312 | date->visible = visible; | |
313 | } | |
314 | ||
315 | sprintf(interp->result, "%d", date->visible); | |
316 | ||
317 | return TCL_OK; | |
318 | } | |
319 | ||
320 | ||
321 | int DateCmdReset(DATE_ARGS) | |
322 | { | |
323 | int range; | |
324 | ||
325 | if (argc != 2) { | |
326 | Tcl_AppendResult(interp, "wrong # args", (char *) NULL); | |
327 | return TCL_ERROR; | |
328 | } | |
329 | ||
330 | date->reset = 1; | |
331 | ||
332 | // ComputeDateGeometry(date); // ??? | |
333 | ||
334 | EventuallyRedrawDate(date); | |
335 | ||
336 | return TCL_OK; | |
337 | } | |
338 | ||
339 | ||
340 | int DateCmdSet(DATE_ARGS) | |
341 | { | |
342 | int range; | |
343 | ||
344 | if (argc != 4) { | |
345 | Tcl_AppendResult(interp, "wrong # args", (char *) NULL); | |
346 | return TCL_ERROR; | |
347 | } | |
348 | ||
349 | if ((Tcl_GetInt(interp, argv[2], &date->month) != TCL_OK) || | |
350 | (date->month < 0) || | |
351 | (date->month >= 12)) { | |
352 | Tcl_AppendResult(interp, " bogus args", (char *) NULL); | |
353 | return TCL_ERROR; | |
354 | } | |
355 | ||
356 | if ((Tcl_GetInt(interp, argv[3], &date->year) != TCL_OK) || | |
357 | (date->year < 0)) { | |
358 | Tcl_AppendResult(interp, " bogus args", (char *) NULL); | |
359 | return TCL_ERROR; | |
360 | } | |
361 | ||
362 | // ComputeDateGeometry(date); // ??? | |
363 | ||
364 | EventuallyRedrawDate(date); | |
365 | ||
366 | return TCL_OK; | |
367 | } | |
368 | ||
369 | ||
370 | int | |
371 | DoDateCmd(CLIENT_ARGS) | |
372 | { | |
373 | SimDate *date = (SimDate *) clientData; | |
374 | Tcl_HashEntry *ent; | |
375 | int result = TCL_OK; | |
376 | int (*cmd)(); | |
377 | ||
378 | if (argc < 2) { | |
379 | return TCL_ERROR; | |
380 | } | |
381 | ||
382 | if (ent = Tcl_FindHashEntry(&DateCmds, argv[1])) { | |
383 | cmd = (int (*)())ent->clientData; | |
384 | Tk_Preserve((ClientData) date); | |
385 | result = cmd(date, interp, argc, argv); | |
386 | Tk_Release((ClientData) date); | |
387 | } else { | |
388 | Tcl_AppendResult(interp, "unknown command name: \"", | |
389 | argv[0], " ", argv[1], "\".", (char *) NULL); | |
390 | result = TCL_ERROR; | |
391 | } | |
392 | return result; | |
393 | } | |
394 | ||
395 | ||
396 | int | |
397 | DateViewCmd(CLIENT_ARGS) | |
398 | { | |
399 | SimDate *date; | |
400 | Tk_Window tkwin = (Tk_Window) clientData; | |
401 | ||
402 | if (argc < 2) { | |
403 | Tcl_AppendResult(interp, "wrong # args: should be \"", | |
404 | argv[0], " pathName ?options?\"", (char *) NULL); | |
405 | return TCL_ERROR; | |
406 | } | |
407 | ||
408 | tkwin = Tk_CreateWindowFromPath(interp, tkwin, | |
409 | argv[1], (char *) NULL); | |
410 | if (tkwin == NULL) { | |
411 | return TCL_ERROR; | |
412 | } | |
413 | ||
414 | date = (SimDate *)ckalloc(sizeof (SimDate)); | |
415 | ||
416 | date->tkwin = tkwin; | |
417 | date->interp = interp; | |
418 | date->flags = 0; | |
419 | date->reset = 1; | |
420 | date->month = 0; | |
421 | date->year = 0; | |
422 | date->lastmonth = 0; | |
423 | date->lastyear = 0; | |
424 | ||
425 | Tk_SetClass(date->tkwin, "DateView"); | |
426 | Tk_CreateEventHandler(date->tkwin, | |
427 | VisibilityChangeMask | | |
428 | ExposureMask | | |
429 | StructureNotifyMask, | |
430 | SimDateEventProc, (ClientData) date); | |
431 | Tcl_CreateCommand(interp, Tk_PathName(date->tkwin), | |
432 | DoDateCmd, (ClientData) date, (void (*)()) NULL); | |
433 | ||
434 | /* | |
435 | Tk_MakeWindowExist(date->tkwin); | |
436 | */ | |
437 | ||
438 | if (getenv("XSYNCHRONIZE") != NULL) { | |
439 | XSynchronize(Tk_Display(tkwin), 1); | |
440 | } | |
441 | ||
442 | InitNewDate(date); | |
443 | DoNewDate(date); | |
444 | ||
445 | if (ConfigureSimDate(interp, date, argc-2, argv+2, 0) != TCL_OK) { | |
446 | /* XXX: destroy date */ | |
447 | Tk_DestroyWindow(date->tkwin); | |
448 | return TCL_ERROR; | |
449 | } | |
450 | ||
451 | interp->result = Tk_PathName(date->tkwin); | |
452 | return TCL_OK; | |
453 | } | |
454 | ||
455 | ||
456 | int | |
457 | ConfigureSimDate(Tcl_Interp *interp, SimDate *date, | |
458 | int argc, char **argv, int flags) | |
459 | { | |
460 | if (Tk_ConfigureWidget(interp, date->tkwin, DateConfigSpecs, | |
461 | argc, argv, (char *) date, flags) != TCL_OK) { | |
462 | return TCL_ERROR; | |
463 | } | |
464 | ||
465 | Tk_SetBackgroundFromBorder(date->tkwin, date->border); | |
466 | ||
467 | ComputeDateGeometry(date); | |
468 | ||
469 | EventuallyRedrawDate(date); | |
470 | ||
471 | return TCL_OK; | |
472 | } | |
473 | ||
474 | ||
475 | date_command_init() | |
476 | { | |
477 | int new; | |
478 | ||
479 | Tcl_CreateCommand(tk_mainInterp, "dateview", DateViewCmd, | |
480 | (ClientData)MainWindow, (void (*)()) NULL); | |
481 | ||
482 | Tcl_InitHashTable(&DateCmds, TCL_STRING_KEYS); | |
483 | ||
484 | #define DATE_CMD(name) HASHED_CMD(Date, name) | |
485 | ||
486 | DATE_CMD(configure); | |
487 | DATE_CMD(position); | |
488 | DATE_CMD(size); | |
489 | DATE_CMD(Visible); | |
490 | DATE_CMD(Reset); | |
491 | DATE_CMD(Set); | |
492 | } | |
493 | ||
494 | ||
495 | InitNewDate(SimDate *date) | |
496 | { | |
497 | int d = 8; | |
498 | struct XDisplay *xd; | |
499 | ||
500 | date->next = NULL; | |
501 | ||
502 | /* This stuff was initialized in our caller (DateCmd) */ | |
503 | /* date->tkwin = NULL; */ | |
504 | /* date->interp = NULL; */ | |
505 | /* date->flags = 0; */ | |
506 | ||
507 | date->x = NULL; | |
508 | date->visible = 0; | |
509 | date->w_x = date->w_y = 0; | |
510 | date->w_width = date->w_height = 0; | |
511 | date->pixmap = None; | |
512 | date->pixels = NULL; | |
513 | date->fontPtr = NULL; | |
514 | date->border = NULL; | |
515 | date->borderWidth = 0; | |
516 | date->padX = 0; | |
517 | date->padY = 0; | |
518 | date->width = 0; | |
519 | date->monthTab = 0; | |
520 | date->monthTabX = 0; | |
521 | date->yearTab = 0; | |
522 | date->yearTabX = 0; | |
523 | date->draw_date_token = 0; | |
524 | date->reset = 1; | |
525 | date->year = 0; | |
526 | date->month = 0; | |
527 | date->lastyear = 0; | |
528 | date->lastmonth = 0; | |
529 | ||
530 | date->x = FindXDisplay(date->tkwin); | |
531 | IncRefDisplay(date->x); | |
532 | ||
533 | date->pixels = date->x->pixels; | |
534 | date->fontPtr = NULL; | |
535 | ||
536 | DoResizeDate(date, 16, 16); | |
537 | } | |
538 | ||
539 | ||
540 | DestroyDate(SimDate *date) | |
541 | { | |
542 | SimDate **gp; | |
543 | ||
544 | for (gp = &sim->date; | |
545 | (*gp) != NULL; | |
546 | gp = &((*gp)->next)) { | |
547 | if ((*gp) == date) { | |
548 | (*gp) = date->next; | |
549 | sim->dates--; | |
550 | break; | |
551 | } | |
552 | } | |
553 | ||
554 | if (date->pixmap != None) { | |
555 | XFreePixmap(date->x->dpy, date->pixmap); | |
556 | date->pixmap = None; | |
557 | } | |
558 | ||
559 | DecRefDisplay(date->x); | |
560 | ||
561 | ckfree((char *) date); | |
562 | } | |
563 | ||
564 | ||
565 | DoResizeDate(SimDate *date, int w, int h) | |
566 | { | |
567 | int resize = 0; | |
568 | ||
569 | date->w_width = w; date->w_height = h; | |
570 | ||
571 | if (date->pixmap != None) { | |
572 | XFreePixmap(date->x->dpy, date->pixmap); | |
573 | date->pixmap = None; | |
574 | } | |
575 | date->pixmap = XCreatePixmap(date->x->dpy, date->x->root, | |
576 | w, h, date->x->depth); | |
577 | if (date->pixmap == None) { | |
578 | fprintf(stderr, | |
579 | "Sorry, Micropolis can't create a pixmap on X display \"%s\".\n", | |
580 | date->x->display); | |
581 | sim_exit(1); // Just sets tkMustExit and ExitReturn | |
582 | return; | |
583 | } | |
584 | } | |
585 | ||
586 | ||
587 | DoNewDate(SimDate *date) | |
588 | { | |
589 | sim->dates++; date->next = sim->date; sim->date = date; | |
590 | ||
591 | NewDate = 1; | |
592 | } | |
593 | ||
594 | ||
595 | #define BORDER 1 | |
596 | ||
597 | DoUpdateDate(SimDate *date) | |
598 | { | |
599 | Display *dpy; | |
600 | GC gc; | |
601 | Pixmap pm; | |
602 | int *pix; | |
603 | int w, h, i, j, x, y; | |
604 | int tx, ty; | |
605 | float sx, sy; | |
606 | ||
607 | if (!date->visible) { | |
608 | return; | |
609 | } | |
610 | ||
611 | dpy = date->x->dpy; | |
612 | gc = date->x->gc; | |
613 | pm = date->pixmap; | |
614 | pix = date->pixels; | |
615 | ||
616 | w = date->w_width; | |
617 | h = date->w_height; | |
618 | ||
619 | XSetFont(date->x->dpy, date->x->gc, date->fontPtr->fid); | |
620 | ||
621 | #if 0 | |
622 | if (date->x->color) { | |
623 | XSetForeground(dpy, gc, pix[COLOR_LIGHTGRAY]); | |
624 | } else { | |
625 | XSetForeground(dpy, gc, pix[COLOR_WHITE]); | |
626 | } | |
627 | #else | |
628 | XSetForeground(dpy, gc, Tk_3DBorderColor(date->border)->pixel); | |
629 | #endif | |
630 | ||
631 | XFillRectangle(dpy, pm, gc, 0, 0, w, h); | |
632 | ||
633 | tx = BORDER; ty = BORDER; | |
634 | ||
635 | if ((w -= (2 * BORDER)) < 1) w = 1; | |
636 | if ((h -= (2 * BORDER)) < 1) h = 1; | |
637 | ||
638 | x = date->borderWidth + date->padX + 1; | |
639 | y = date->borderWidth + date->padY + date->fontPtr->ascent; | |
640 | ||
641 | if (date->reset) { | |
642 | date->reset = 0; | |
643 | date->lastyear = date->year; | |
644 | date->lastmonth = date->month; | |
645 | } | |
646 | ||
647 | { | |
648 | char *dateString = "Date:"; | |
649 | char yearString[256]; | |
650 | int month = date->month; | |
651 | int year = date->year; | |
652 | int lastmonth = date->lastmonth; | |
653 | int lastyear = date->lastyear; | |
654 | int yearsPassed; | |
655 | int monthsPassed; | |
656 | yearsPassed = | |
657 | (year - lastyear); | |
658 | if (yearsPassed < 0) yearsPassed = 1; | |
659 | if (yearsPassed > 9) yearsPassed = 9; | |
660 | monthsPassed = | |
661 | (month - lastmonth) + | |
662 | (12 * yearsPassed); | |
663 | ||
664 | if (monthsPassed > 11) monthsPassed = 11; | |
665 | if (monthsPassed == 1) monthsPassed = 0; | |
666 | if (monthsPassed) { | |
667 | int m = lastmonth; | |
668 | int i; | |
669 | ||
670 | XSetForeground(dpy, gc, pix[COLOR_DARKGRAY]); | |
671 | ||
672 | for (i = 0; i < monthsPassed; i++) { | |
673 | ||
674 | XDrawString(date->x->dpy, pm, date->x->gc, | |
675 | x + date->monthTabX, y, | |
676 | dateStr[m], | |
677 | strlen(dateStr[date->month])); | |
678 | ||
679 | m++; | |
680 | if (m == 12) m = 0; | |
681 | } | |
682 | ||
683 | if (year != lastyear) { | |
684 | int yy = lastyear; | |
685 | if ((year - yy) > 10) { | |
686 | yy = year - 10; | |
687 | } | |
688 | ||
689 | for (i = yy; i < year; i++) { | |
690 | sprintf( | |
691 | yearString, | |
692 | "%d", | |
693 | i); | |
694 | ||
695 | XDrawString(date->x->dpy, pm, date->x->gc, | |
696 | x + date->yearTabX, y, | |
697 | yearString, | |
698 | strlen(yearString)); | |
699 | } | |
700 | } | |
701 | ||
702 | EventuallyRedrawDate(date); | |
703 | } | |
704 | ||
705 | date->lastmonth = month; | |
706 | date->lastyear = year; | |
707 | ||
708 | XSetForeground(dpy, gc, pix[COLOR_BLACK]); | |
709 | ||
710 | XDrawString(date->x->dpy, pm, date->x->gc, | |
711 | x, y, | |
712 | dateString, | |
713 | strlen(dateString)); | |
714 | ||
715 | XDrawString(date->x->dpy, pm, date->x->gc, | |
716 | x + date->monthTabX, y, | |
717 | dateStr[date->month], | |
718 | strlen(dateStr[date->month])); | |
719 | ||
720 | sprintf( | |
721 | yearString, | |
722 | "%d", | |
723 | year); | |
724 | ||
725 | XDrawString(date->x->dpy, pm, date->x->gc, | |
726 | x + date->yearTabX, y, | |
727 | yearString, | |
728 | strlen(yearString)); | |
729 | } | |
730 | ||
731 | XCopyArea(date->x->dpy, date->pixmap, | |
732 | Tk_WindowId(date->tkwin), date->x->gc, | |
733 | 0, 0, date->w_width, date->w_height, 0, 0); | |
734 | } | |
735 | ||
736 |