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

# User Rev Content
1 root 1.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     }