ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/crossedit/MapAttr.c
Revision: 1.2
Committed: Sun Aug 13 17:16:01 2006 UTC (17 years, 9 months ago) by elmex
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
Log Message:
Made server compile with C++.
Removed cfanim plugin and crossedit.
C++ here we come.

File Contents

# Content
1 /*
2 * CrossEdit - game world editor
3 * Copyright (C) 2005 Mark Wedel & Crossfire Development Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * The authors can be reached via e-mail at crossfire-devel@real-time.com
20 */
21
22 #include <assert.h>
23
24 #include "MapAttr.h"
25 #include "CrFace.h" /* XtNadjust */
26 #include "debug.h" /* debug0, etc */
27
28 /*
29 * getValue functions
30 */
31
32 /* Buffer size is defined in MapAttrChange(). */
33 #define CPY_INT(x) snprintf(str, BUFSIZ, "%d", (x));
34 #define CPY_STR(x) snprintf(str, BUFSIZ, "%s", (x));
35
36 static void getEnterX(mapstruct *map, char *str) {
37 CPY_INT(MAP_ENTER_X(map));
38 }
39
40 static void getEnterY(mapstruct *map, char *str) {
41 CPY_INT(MAP_ENTER_Y(map));
42 }
43
44 static void getWidth(mapstruct *map, char *str) {
45 CPY_INT(MAP_WIDTH(map));
46 }
47
48 static void getHeight(mapstruct *map, char *str) {
49 CPY_INT(MAP_HEIGHT(map));
50 }
51
52 static void getTileMapn(mapstruct *map, char *str, int n) {
53 if (map->tile_path[n] == NULL) {
54 str[0] = '\0';
55 } else {
56 CPY_STR(map->tile_path[n]);
57 }
58 }
59
60 static void getTileMap0(mapstruct *map, char *str) {
61 getTileMapn(map, str, 0);
62 }
63
64 static void getTileMap1(mapstruct *map, char *str) {
65 getTileMapn(map, str, 1);
66 }
67
68 static void getTileMap2(mapstruct *map, char *str) {
69 getTileMapn(map, str, 2);
70 }
71
72 static void getTileMap3(mapstruct *map, char *str) {
73 getTileMapn(map, str, 3);
74 }
75
76 static void getTimeout(mapstruct *map, char *str) {
77 CPY_INT(MAP_TIMEOUT(map));
78 }
79
80 static void getReset(mapstruct *map, char *str) {
81 CPY_INT(MAP_RESET_TIMEOUT(map));
82 }
83
84 static void getDarkness(mapstruct *map, char *str) {
85 CPY_INT(MAP_DARKNESS(map));
86 }
87
88 static void getDifficulty(mapstruct *map, char *str) {
89 CPY_INT(MAP_DIFFICULTY(map));
90 }
91
92 static void getNoReset(mapstruct *map, char *str) {
93 *str = map->fixed_resettime;
94 }
95
96 static void getOutdoor(mapstruct *map, char *str) {
97 *str = MAP_OUTDOORS(map);
98 }
99
100 static void getRegion(mapstruct *map, char *str) {
101 CPY_STR(get_name_of_region_for_map(map));
102 }
103
104 static void getNoSmooth(mapstruct *map, char *str) {
105 *str = MAP_NOSMOOTH(map);
106 }
107
108 #undef CPY_STR
109 #undef CPY_INT
110
111 /*
112 * putValue functions
113 */
114
115 static void putEnterX(mapstruct *map, const char *str) {
116 MAP_ENTER_X(map) = atoi(str);
117 }
118
119 static void putEnterY(mapstruct *map, const char *str) {
120 MAP_ENTER_Y(map) = atoi(str);
121 }
122
123 static void putTileMapn(mapstruct *map, const char *str, int n) {
124 if (map->tile_path[n] != NULL) {
125 free(map->tile_path[n]);
126 map->tile_path[n] = NULL;
127 }
128 if (str != NULL && strcmp(str, "") != 0) {
129 map->tile_path[n] = strdup_local(str);
130 }
131 }
132
133 static void putTileMap0(mapstruct *map, const char *str) {
134 putTileMapn(map, str, 0);
135 }
136
137 static void putTileMap1(mapstruct *map, const char *str) {
138 putTileMapn(map, str, 1);
139 }
140
141 static void putTileMap2(mapstruct *map, const char *str) {
142 putTileMapn(map, str, 2);
143 }
144
145 static void putTileMap3(mapstruct *map, const char *str) {
146 putTileMapn(map, str, 3);
147 }
148
149 /* Rather than resize the map twice, record the new size here,
150 and apply it once (see MapAttrApply()). */
151 static int new_width, new_height;
152
153 static void putWidth(mapstruct *map, const char *str) {
154 new_width = atoi(str);
155 }
156 static void putHeight(mapstruct *map, const char *str) {
157 new_height = atoi(str);
158 }
159
160 static void putTimeout(mapstruct *map, const char *str) {
161 MAP_TIMEOUT(map) = atoi(str);
162 }
163
164 static void putReset(mapstruct *map, const char *str) {
165 MAP_RESET_TIMEOUT(map) = atoi(str);
166 }
167
168 static void putDarkness(mapstruct *map, const char *str) {
169 MAP_DARKNESS(map) = atoi(str);
170 }
171
172 static void putDifficulty(mapstruct *map, const char *str) {
173 MAP_DIFFICULTY(map) = atoi(str);
174 }
175
176 static void putOutdoor(mapstruct *map, const char *str) {
177 if (*str)
178 MAP_OUTDOORS(map) = 1;
179 else
180 MAP_OUTDOORS(map) = 0;
181 }
182
183 static void putRegion (mapstruct *map, const char *str) {
184 map->region = get_region_by_name(str);
185 }
186
187 static void putNoSmooth(mapstruct *map, const char *str) {
188 if (*str)
189 MAP_NOSMOOTH(map) = 1;
190 else
191 MAP_NOSMOOTH(map) = 0;
192 }
193
194 static void putNoReset(mapstruct *map, const char *str) {
195 if (*str)
196 map->fixed_resettime = 1;
197 else
198 map->fixed_resettime = 0;
199 }
200
201
202
203 /**********************************************************************
204 * tags
205 **********************************************************************/
206
207 static const MapAttrDef MapDescription[] = {
208 {"Start X", MATypeString, getEnterX, putEnterX},
209 {"Start Y", MATypeString, getEnterY, putEnterY},
210 {"Width", MATypeString, getWidth, putWidth},
211 {"Height", MATypeString, getHeight, putHeight},
212
213 {"Swap Time", MATypeString, getTimeout, putTimeout},
214 {"Reset Timeout", MATypeString, getReset, putReset},
215
216 {"Difficulty", MATypeString, getDifficulty, putDifficulty},
217 {"Darkness", MATypeString, getDarkness, putDarkness},
218 {"Region", MATypeString, getRegion, putRegion},
219
220 {"East Map", MATypeString, getTileMap1, putTileMap1},
221 {"West Map", MATypeString, getTileMap3, putTileMap3},
222 {"North Map", MATypeString, getTileMap0, putTileMap0},
223 {"South Map", MATypeString, getTileMap2, putTileMap2},
224
225 {"Outdoor", MATypeToggle, getOutdoor, putOutdoor},
226 {"No Smoothing", MATypeToggle, getNoSmooth, putNoSmooth},
227 {"FixedReset", MATypeToggle, getNoReset, putNoReset},
228 };
229
230 static const int NUM_ATTRS = sizeof(MapDescription)/sizeof(MapAttrDef);
231
232
233 /* Build the widgets for the above list of attributes. */
234 static void MapAttrTagsCreate(MapAttr self, Widget parent)
235 {
236 Widget cont;
237 int i;
238
239 self->tags = (Widget *)XtCalloc(NUM_ATTRS, sizeof(Widget));
240
241 /* First, those that use a textbox, */
242 for (i = 0; i < NUM_ATTRS; i++) {
243 if (MapDescription[i].type == MATypeString) {
244
245 /* A layout composite widget to keep the
246 label to the left of the entry box. */
247 cont = XtVaCreateManagedWidget
248 ("box", boxWidgetClass, parent,
249 XtNorientation, XtorientHorizontal,
250 NULL);
251 XtVaCreateManagedWidget
252 ("label", labelWidgetClass, cont,
253 XtNlabel, MapDescription[i].label,
254 NULL);
255 self->tags[i] = XtVaCreateManagedWidget
256 ("value", asciiTextWidgetClass, cont,
257 XtNtype, XawAsciiString,
258 XtNeditType, XawtextEdit,
259 NULL);
260 }
261 }
262
263 /* Then those that toggle. */
264 for (i = 0; i < NUM_ATTRS; i++) {
265 if (MapDescription[i].type == MATypeToggle) {
266
267 /* Also, Crossedit.ad puts a few pixels' spacing
268 around each list entry by putting a width
269 on the *box's* border. */
270 cont = XtVaCreateManagedWidget
271 ("box", boxWidgetClass, parent,
272 XtNorientation, XtorientHorizontal,
273 NULL);
274
275 self->tags[i] = XtVaCreateManagedWidget
276 ("toggle", toggleWidgetClass, cont,
277 XtNlabel, MapDescription[i].label,
278 NULL);
279 }
280 }
281 }
282
283 /**
284 * Write the values from our widgets into self->map. Sort of the reverse of
285 * MapAttrChange().
286 */
287 static void MapAttrApply(MapAttr self)
288 {
289 String str;
290 int len;
291 int i;
292
293 if (self->map == NULL) {
294 return;
295 }
296
297 /*** name ***/
298 XtVaGetValues(self->iw.name,
299 XtNstring, &str,
300 NULL);
301 free(self->map->name);
302 self->map->name = strdup_local(str);
303
304 /*** message ***/
305 XtVaGetValues(self->iw.msg,
306 XtNstring, &str,
307 NULL);
308
309 free(self->map->msg);
310 len = strlen(str);
311 if (len > 0) {
312 if (str[len-1] == '\n') {
313 self->map->msg = strdup_local(str);
314 } else {
315 char *newmsg;
316
317 /* The msg doesn't end with a newline. Append one, otherwise
318 the headers can't be read properly. */
319
320 newmsg = malloc(len+2);
321 memcpy(newmsg, str, len);
322 newmsg[len] = '\n';
323 newmsg[len+1] = '\0';
324
325 self->map->msg = newmsg;
326 }
327 } else {
328 self->map->msg = NULL;
329 }
330
331 /* For each attribute, extract the state of the input widget,
332 and write it to the map. */
333 for (i = 0; i < NUM_ATTRS; i++) {
334 const MapAttrDef *which = &MapDescription[i];
335 if (which->type == MATypeString) {
336 XtVaGetValues(self->tags[i], XtNstring, &str, NULL);
337 which->putValue(self->map, str);
338 } else if (which->type == MATypeToggle) {
339 Boolean tmp;
340 XtVaGetValues(self->tags[i], XtNstate, &tmp, NULL);
341 *str = tmp ? ~0 : 0;
342 which->putValue(self->map, str);
343 }
344 }
345
346 /* The entries for the width and height store in new_width and new_height,
347 so we only resize once. */
348 if (new_width != MAP_WIDTH(self->map) ||
349 new_height != MAP_HEIGHT(self->map)) {
350 EditResizeScroll(self->client, new_width, new_height, 0, 0);
351 } else {
352 EditUpdate(self->client);
353 }
354
355 /*** update ***/
356 AppUpdate(self->app);
357
358 /* "Dirty" the map. */
359 EditModified(self->client);
360 }
361
362 /*
363 * callback: receive ok
364 */
365 static void OkCb(Widget w, XtPointer client, XtPointer call)
366 {
367 MapAttr self = (MapAttr)client;
368
369 MapAttrApply(self);
370 MapAttrDestroy(self);
371 }
372
373 /*
374 * callback: receive apply
375 */
376 static void ApplyCb(Widget w, XtPointer client, XtPointer call)
377 {
378 MapAttr self = (MapAttr)client;
379
380 MapAttrApply(self);
381 }
382
383 /*
384 * callback: receive cancel
385 */
386 static void CancelCb(Widget w, XtPointer client, XtPointer call) {
387 MapAttr self = (MapAttr)client;
388
389 MapAttrDestroy(self);
390 }
391
392 static void MapAttrLayout(MapAttr self, Widget parent) {
393 Widget form, view1, pane, ok, apply, cancel;
394
395 /* This widget gets decorated by the window manager.
396 ('Shell' is possibly the Intrinsics name for such widgets.) */
397 self->shell = XtVaCreatePopupShell
398 ("mapattr", topLevelShellWidgetClass, parent, NULL);
399
400 /* A "composite" widget, for laying out the other widgets. */
401 form = XtVaCreateManagedWidget("form", formWidgetClass, self->shell, NULL);
402
403 /* One line for the name,
404 (the dimensions of widgets are given in Crossedit.ad. */
405 self->iw.name = XtVaCreateManagedWidget
406 ("name", asciiTextWidgetClass, form,
407 XtNtype, XawAsciiString,
408 XtNeditType, XawtextEdit,
409 XtNresize, False,
410 NULL);
411
412 /* Below the name, several lines for the msg; */
413 self->iw.msg = XtVaCreateManagedWidget
414 ("msg", asciiTextWidgetClass, form,
415 XtNtype, XawAsciiString,
416 XtNeditType, XawtextEdit,
417 XtNfromVert, self->iw.name,
418 NULL);
419
420 /* Below the message window,
421 a widget that doesn't display all of its one child;
422 instead, it displays scrollbars. */
423 view1 = XtVaCreateManagedWidget
424 ("view", viewportWidgetClass, form,
425 /*XtNallowVert, True,*/
426 XtNforceBars, True,
427 XtNfromVert, self->iw.msg,
428 NULL);
429
430 /* Inside view1, a widget that packs its many children
431 as tightly as possible. We've told this one to be tall
432 and narrow, so we have a vertically scrolling list, with
433 the attribute widgets stacked on top of one-another. */
434 pane = XtVaCreateManagedWidget
435 ("pane", boxWidgetClass, view1,
436 XtNorientation, XtorientVertical,
437 NULL);
438
439 /* Below the attribute pane, view1, three button-type
440 widgets. */
441 ok = XtVaCreateManagedWidget
442 ("ok", commandWidgetClass, form,
443 XtNfromVert, view1,
444 NULL);
445 XtAddCallback(ok, XtNcallback, OkCb, (XtPointer)self);
446 apply = XtVaCreateManagedWidget
447 ("apply", commandWidgetClass, form,
448 XtNfromVert, view1,
449 XtNfromHoriz, ok,
450 NULL);
451 XtAddCallback(apply, XtNcallback, ApplyCb, (XtPointer)self);
452 cancel = XtVaCreateManagedWidget
453 ("cancel", commandWidgetClass, form,
454 XtNfromVert, view1,
455 XtNfromHoriz, apply,
456 NULL);
457 XtAddCallback(cancel, XtNcallback, CancelCb, (XtPointer)self);
458
459 /* Add the individual attribute widgets to
460 their pane. */
461 MapAttrTagsCreate(self, pane);
462 }
463
464 /* Destroy the widget tree and free the internal data (not the map!). */
465 void MapAttrDestroy(MapAttr self)
466 {
467 XtDestroyWidget(self->shell);
468 XtFree((char*)self->tags);
469
470 /* Clear the one pointer to self. */
471 assert(self->client->mapattr == self);
472 self->client->mapattr = NULL;
473
474 XtFree((char*)self);
475 }
476
477 /* Set self's widgets to reflect the state of the given map.
478 The new map is the one subsequent changes will be written to
479 (with MapAttrApply()).
480
481 This is sort of MapAttrApply()'s reverse. */
482 void MapAttrChange(MapAttr self, mapstruct * map) {
483 int i;
484 char buf[BUFSIZ];
485
486 self->map = map;
487
488 /* Give the name and msg boxes their new values. */
489 XtVaSetValues(self->iw.name, XtNstring, self->map->name, NULL);
490 XtVaSetValues(self->iw.msg, XtNstring, self->map->msg, NULL);
491
492 /* For each attribute, */
493 for (i = 0; i < NUM_ATTRS; i++) {
494 /* fetch the value from the map,
495 and give it to the matching widget. */
496
497 const MapAttrDef *which = &MapDescription[i];
498 which->getValue(map, buf);
499 if (which->type == MATypeString) {
500 XtVaSetValues(self->tags[i],
501 XtNstring, buf,
502 NULL);
503
504 /* Put the cursor at the end of the line. */
505 XtVaSetValues(self->tags[i],
506 XtNinsertPosition, strlen(buf),
507 NULL);
508 } else if (which->type == MATypeToggle) {
509 XtVaSetValues(self->tags[i],
510 XtNstate, *buf ? TRUE : FALSE,
511 NULL);
512 }
513 }
514
515 snprintf(buf, sizeof(buf), "Map: %s", self->map->name);
516 XtVaSetValues(self->shell,
517 XtNtitle, buf,
518 XtNiconName, buf,
519 NULL);
520 }
521
522 MapAttr MapAttrCreate(mapstruct * map, App app, Edit client)
523 {
524 MapAttr self = (MapAttr)XtMalloc(sizeof(struct _MapAttr));
525 self->map = map;
526 self->app = client->app;
527 self->client = client;
528
529 /* Build the widgets, */
530 MapAttrLayout(self, self->app->shell);
531
532 /* fill them with data, */
533 MapAttrChange(self, map);
534
535 /* and display the window. */
536 XtPopup(self->shell, XtGrabNone);
537
538 return self;
539 }