ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/crossedit/Attr.c
Revision: 1.1.1.1 (vendor branch)
Committed: Fri Feb 3 07:11:42 2006 UTC (18 years, 3 months ago) by root
Content type: text/plain
Branch: UPSTREAM
CVS Tags: UPSTREAM_2006_03_15, UPSTREAM_2006_02_22, UPSTREAM_2006_02_03
Changes since 1.1: +0 -0 lines
Log Message:
initial import

File Contents

# User Rev Content
1 root 1.1 /*
2     Copyright (C) 1993 Jarkko Sonninen & Petri Heinila
3    
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8    
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     GNU General Public License for more details.
13    
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17    
18     The authors can be reached via e-mail to Jarkko.Sonninen@lut.fi
19     or Petri.Heinila@lut.fi .
20     */
21    
22    
23    
24     #include "Posix.h"
25     #include "Attr.h"
26     #include "X11.h"
27     #include "CrList.h"
28     #include "CrFace.h"
29     #include "CrEdit.h"
30     #include "Cnv.h"
31     #include "Edit.h"
32     #include "App.h"
33     #include "loader.h"
34     #include "debug.h"
35    
36     static void AttrReset(Attr self);
37    
38     /* variables, combination bit */
39     #define T_Path (1<<I_Path)
40     #define T_X (1<<I_X)
41     #define T_Y (1<<I_Y)
42     #define T_Weight (1<<I_Weight)
43     #define T_Connect (1<<I_Connect)
44     #define T_Hp (1<<I_Hp)
45     #define T_Trigger (1<<I_Trigger)
46     #define T_Sacrifice (1<<I_Sacrifice)
47     #define T_Count (1<<I_Count)
48     #define T_Lockcode (1<<I_Lockcode) /* slaying - field */
49     #define T_Direction (1<<I_Direction)
50     #define T_Rotation (1<<I_Rotation)
51     #define T_NoPick (1<<I_NoPick)
52     #define T_Unique (1<<I_Unique)
53     #define T_WeightL (1<<I_WeightL)
54     #define T_Brand (1<<I_Brand)
55     #define T_Maker (1<<I_Maker)
56    
57     /*** types ar Combinations ***/
58     #define T_Exit (T_Path | T_X | T_Y )
59     #define T_Trapdoor (T_Weight | T_X | T_Y )
60     #define T_Connected (T_Connect )
61     #define T_Pit (T_Connect | T_X | T_Y )
62     #define T_Monster (T_Hp )
63     #define T_Pedestal (T_Connected | T_Trigger )
64     #define T_Altar (T_Connected | T_Sacrifice | T_Count )
65     #define T_Button (T_Weight | T_Connected)
66     #define T_Director (T_Connected | T_Direction | T_Rotation)
67     #define T_Lockdoor (T_Lockcode)
68     #define T_Key (T_Lockcode | T_Unique)
69     #define T_Container (T_Lockcode | T_WeightL | T_Brand | T_Unique | T_NoPick)
70     #define T_Sign 0
71     #define T_Map (T_X | T_Y | T_Path)
72    
73     #define T_Default 0
74    
75     /*
76     * transfer type from game to editor, return negative on error
77     *
78     * Basically, for certain things, we want to have default values set up.
79     */
80     int GetType (object *tmp)
81     {
82     if (!tmp)
83     return (-1);
84    
85     if (tmp->head)
86     tmp = tmp->head;
87    
88     switch (tmp->type) {
89     case TELEPORTER:
90     return T_Connected|T_Exit;
91     case PLAYER_CHANGER:
92     case EXIT:
93     return T_Exit;
94     case TRAPDOOR:
95     return T_Trapdoor;
96     case HOLE:
97     return T_Pit;
98     case BUTTON:
99     case TRIGGER_BUTTON:
100     return T_Button;
101     case CREATOR:
102     return T_Connected|T_Maker;
103     case CONVERTER:
104     return T_Maker|T_Lockcode;
105     case GATE:
106     case CF_HANDLE:
107     case TIMED_GATE:
108     case MAGIC_EAR:
109     case TRIGGER:
110     return T_Connected;
111     case CHECK_INV:
112     return T_Connected | T_Lockcode;
113     case ALTAR:
114     case TRIGGER_ALTAR:
115     return T_Altar;
116     case PEDESTAL:
117     case TRIGGER_PEDESTAL:
118     return T_Pedestal;
119     case BOOK:
120     case SIGN:
121     return T_Sign;
122     case MARKER:
123     case LOCKED_DOOR:
124     return T_Lockdoor;
125     case SPECIAL_KEY:
126     return T_Key;
127     case MAP: /* shouldn't happen ... */
128     return T_Map;
129     case DIRECTOR:
130     case FIREWALL:
131     return (NUM_ANIMATIONS(tmp) > 0)
132     ? T_Director : T_Connected;
133     case CONTAINER:
134     return T_Container;
135     default:
136     if (QUERY_FLAG(tmp, FLAG_MONSTER))
137     return T_Monster;
138     else
139     return T_Default;
140     }
141     /* return -1; */
142     }
143    
144     /**********************************************************************
145     *Section: get value from object for displying
146     *Commentary:
147     * Remeber, the strings from obejct may be NULL's
148     **********************************************************************/
149    
150     static void getX (object *ob, char *str, XtPointer c) {
151     sprintf(str,"%d",EXIT_X(ob));
152     }
153    
154     static void getY (object *ob, char *str, XtPointer c) {
155     sprintf(str,"%d",EXIT_Y(ob));
156     }
157    
158     static void getPath (object *ob, char *str, XtPointer c) {
159     strcpy (str, EXIT_PATH(ob) ? EXIT_PATH(ob) : "");
160     }
161    
162     static void getWeight (object *ob, char *str, XtPointer c) {
163     sprintf(str,"%d",ob->weight);
164     }
165    
166     /*** connected ***/
167     static void getConnect (object *ob, char *str, XtPointer c) {
168     sprintf(str,"%d",get_button_value(ob));
169     }
170    
171     static void getHp (object *ob, char *str, XtPointer c) {
172     sprintf(str,"%d",ob->stats.hp);
173     }
174    
175     #define NotUsed "(not-used)"
176    
177     static void getTrigger (object *ob, char *str, XtPointer c) {
178     if(!ob->slaying || !*ob->slaying)
179     sprintf(str,NotUsed);
180     else
181     strcpy (str, ob->slaying);
182     }
183    
184     /*** sacrifice ***/
185     static void getSacrifice (object *ob, char *str, XtPointer c) {
186     if(!ob->slaying || !*ob->slaying) {
187     if(!ob->arch->clone.slaying)
188     LOG(llevError,"missing sacrifice for altar\n");
189     strcpy (str, ob->arch->clone.slaying);
190     } else
191     strcpy (str, ob->slaying);
192     }
193    
194     static void getCount (object *ob, char *str, XtPointer c) {
195     sprintf(str,"%d",ob->stats.food);
196     }
197    
198     /*** lockcode ***/
199     static void getLockcode (object *ob, char *str, XtPointer c) {
200     if(!ob->slaying || !*ob->slaying) {
201     sprintf(str,NotUsed);
202     } else
203     strcpy (str, ob->slaying);
204     }
205    
206     /*** direction ***/
207     static void getDirection (object *ob, char *str, XtPointer c) {
208     sprintf(str,"%d",ob->stats.maxsp);
209     }
210    
211     /*** rotation ***/
212     static void getRotation (object *ob, char *str, XtPointer c) {
213     sprintf(str,"%d",ob->stats.sp);
214     }
215    
216     /*** unique ***/
217     static void getUnique (object *ob, char *str, XtPointer c) {
218     *str = QUERY_FLAG(ob, FLAG_UNIQUE) ? ~0 : 0;
219     }
220    
221     /*** no pick ***/
222     static void getNoPick (object *ob, char *str, XtPointer c) {
223     *str = QUERY_FLAG(ob, FLAG_NO_PICK) ? ~0 : 0;
224     }
225    
226     /*** weight limit ***/
227     static void getWeightL (object *ob, char *str, XtPointer c) {
228     sprintf(str,"%d",ob->weight_limit);
229     }
230    
231     /*** brand ***/
232     static void getBrand (object *ob, char *str, XtPointer c) {
233     if(!ob->race || !*ob->race)
234     sprintf(str,NotUsed);
235     else
236     sprintf(str,"%s",ob->race);
237     }
238    
239     /*** brand ***/
240     static void getMakes (object *ob, char *str, XtPointer c) {
241     if(!ob->other_arch)
242     sprintf(str,NotUsed);
243     else
244     sprintf(str,"%s",ob->other_arch->name);
245     }
246    
247     /*
248     * putValue functions
249     *
250     */
251    
252     /*** coord ***/
253     static void putX (object *ob, char *str, XtPointer c) {
254     EXIT_X(ob) = atoi(str);
255     }
256    
257     static void putY (object *ob, char *str, XtPointer c) {
258     EXIT_Y(ob) = atoi(str);
259     }
260    
261     /*** path ***/
262     static void putPath (object *ob, char *str, XtPointer c) {
263     if(EXIT_PATH(ob)) free_string(EXIT_PATH(ob));
264     EXIT_PATH(ob) = NULL;
265     if(strlen(str)) EXIT_PATH(ob) = add_string(str);
266     }
267    
268     /*** sacrifice ***/
269     static void putSacrifice (object *ob, char *str, XtPointer c) {
270     if(ob->slaying) free_string(ob->slaying);
271     ob->slaying = add_string(str);
272     }
273    
274     /*** trigger ***/
275     static void putTrigger (object *ob, char *str, XtPointer c) {
276     if(!strcmp(str,NotUsed))
277     ob->slaying = NULL;
278     else {
279     if(ob->slaying) free_string(ob->slaying);
280     ob->slaying = add_string(str);
281     }
282     }
283    
284     /*** weight ***/
285     static void putWeight (object *ob, char *str, XtPointer c) {
286     ob->weight = atoi(str);
287     }
288    
289     /*** connect ***/
290     static void putConnect (object *ob, char *str, XtPointer c) {
291     if (QUERY_FLAG(ob, FLAG_IS_LINKED))
292     remove_button_link(ob);
293     add_button_link(ob, ob->map, atoi(str));
294     }
295    
296     /*** hp ***/
297     static void putHp (object *ob, char *str, XtPointer c) {
298     ob->stats.hp = atoi(str);
299     }
300    
301     /*** count ***/
302     static void putCount (object *ob, char *str, XtPointer c) {
303     ob->stats.food = atoi(str);
304     }
305    
306     /*** lockcode ***/
307     static void putLockcode (object *ob, char *str, XtPointer c) {
308     if(!strcmp(str,NotUsed))
309     ob->slaying = NULL;
310     else {
311     if(ob->slaying) free_string(ob->slaying);
312     ob->slaying = add_string(str);
313     }
314     }
315    
316     /*** direction ***/
317     static void putDirection (object *ob, char *str, XtPointer c) {
318     ob->stats.maxsp = atoi(str);
319     animate_object (ob, ob->direction);
320     }
321    
322     /*** rotation ***/
323     static void putRotation (object *ob, char *str, XtPointer c) {
324     ob->stats.sp = atoi(str);
325     animate_object (ob, ob->direction);
326     }
327    
328     /*** unique ***/
329     static void putUnique (object *ob, char *str, XtPointer c) {
330     *str ? SET_FLAG(ob, FLAG_UNIQUE) : CLEAR_FLAG(ob, FLAG_UNIQUE);
331     }
332    
333     /*** no pick ***/
334     static void putNoPick (object *ob, char *str, XtPointer c) {
335     *str ? SET_FLAG(ob, FLAG_NO_PICK) : CLEAR_FLAG(ob, FLAG_NO_PICK);
336     }
337    
338     /*** weight limit ***/
339     static void putWeightL (object *ob, char *str, XtPointer c) {
340     debug0("NO putWeightL\n");
341     }
342    
343     /*** brand ***/
344     static void putBrand (object *ob, char *str, XtPointer c) {
345     if(!strcmp(str,NotUsed))
346     ob->race = NULL;
347     else {
348     if(ob->race) free_string(ob->race);
349     ob->race = add_string(str);
350     }
351     }
352    
353     static void putMakes (object *ob, char *str, XtPointer c) {
354     if(!strcmp(str,NotUsed))
355     ob->other_arch = NULL;
356     else {
357     ob->other_arch = find_archetype(str);
358     }
359     }
360    
361    
362     /**********************************************************************
363     * tags
364     **********************************************************************/
365    
366     AttrDef AttrDescription[] = {
367     {"Path", TypeString, getPath, putPath},
368     {"X", TypeString, getX, putX},
369     {"Y", TypeString, getY, putY},
370     {"Weight", TypeString, getWeight, putWeight},
371     {"Connect", TypeString, getConnect, putConnect},
372     {"Hp", TypeString, getHp, putHp},
373     {"Trigger", TypeString, getTrigger, putTrigger},
374     {"Sacrifice", TypeString, getSacrifice, putSacrifice},
375     {"Count", TypeString, getCount, putCount},
376     {"Lockcode", TypeString, getLockcode, putLockcode},
377     {"Direction", TypeString, getDirection, putDirection},
378     {"Rotation", TypeString, getRotation, putRotation},
379     {"No Pick", TypeToggle, getNoPick, putNoPick},
380     {"Unique", TypeToggle, getUnique, putUnique},
381     {"WeightL", TypeString, getWeightL, putWeightL},
382     {"Brand", TypeString, getBrand, putBrand},
383     {"Makes", TypeString, getMakes, putMakes}, /* other_arch */
384     {NULL, 0, 0, NULL}
385     };
386    
387     char *allowed_variables[] = {
388    
389     "name", "race", "slaying", "other_arch", "last_heal", "last_sp",
390     "last_eat", "speed", "speed_left", "slow_move", "face", "Str", "Dex",
391     "Con", "Wis", "Cha", "Int", "Pow", "hp", "maxhp", "sp", "maxsp", "exp",
392     "food", "dam", "wc", "ac", "nrof", "level", "direction", "type",
393     "material", "value", "weight", "carrying", "immune", "protected",
394     "attacktype", "vulnerable", "path_attuned", "path_repelled",
395     "path_denied", "invisible", "magic", "state", "alive", "applied",
396     "unpaid", "need_an", "need_ie", "no_pick", "no_pass", "walk_on",
397     "walk_off", "fly_on", "fly_off", "flying", "monster",
398     "neutral", "no_attack", "no_damage", "friendly",
399     "generator", "is_thrown", "auto_apply", "treasure", "apply_once",
400     "see_invisible", "can_roll", "is_turning", "is_turnable", "is_used_up",
401     "identified", "reflecting", "changing", "splitting", "hitback",
402     "startequip", "blocksview", "undead", "scared", "unaggressive",
403     "reflect_missile", "reflect_spell", "no_magic", "wiz", "was_wiz",
404     "tear_down", "luck", "run_away", "pass_thru", "can_pass_thru",
405     "pick_up", "anim_speed", "container", "no_drop", "no_pretext",
406     "will_apply", "random_movement", "can_apply", "can_cast_spell",
407     "can_use_scroll", "can_use_wand", "can_use_bow", "can_use_armour",
408     "can_use_weapon", "can_use_ring", "has_ready_wand", "has_ready_bow",
409     "xrays", "is_floor", "lifesave", "no_strength", "sleep", "stand_still",
410     "random_move", "only_attack", "armour", "attack_movement", "move_state",
411     "confused", "stealth", "connected", "cursed", "damned", "see_anywhere",
412     "known_magical", "known_cursed", "can_use_skill", "been_applied",
413     "title", "has_ready_rod", "can_use_rod", "has_ready_horn",
414     "can_use_horn", "expmul", "unique", "make_invisible", "is_wooded",
415     "is_hilly", "has_ready_skill", "has_ready_weapon", "no_skill_ident",
416     "glow_radius", "is_blind", "can_see_in_dark", "is_cauldron",
417     "randomitems", "is_dust", "no_steal", "one_hit","berserk",
418     "sub_type", "sub_type2","casting_speed", "elevation",
419     "save_on_overlay",
420     /* GROS - These are hooks for script events */
421     "script_load","script_apply","script_say","script_trigger", "script_time",
422     "script_attack","script_drop", "script_throw", "script_stop", "script_death", "current_weapon_script",
423     "start_script_load", "start_script_apply","start_script_say","start_script_trigger","start_script_time",
424     "start_script_attack","start_script_drop","start_script_throw","start_script_stop", "start_script_death",
425     "end_script_load", "end_script_apply","end_script_say","end_script_trigger","end_script_time",
426     "end_script_attack","end_script_drop","end_script_throw","end_script_stop", "end_script_death",
427    
428     #ifdef NPC_PROG
429     "npc_status", "npc_program",
430     #endif
431    
432     /* Resistances */ "resist_physical", "resist_magic", "resist_fire",
433     "resist_electricity", "resist_cold", "resist_confusion", "resist_acid",
434     "resist_drain", "resist_weaponmagic", "resist_ghosthit", "resist_poison",
435     "resist_slow", "resist_paralyze", "resist_turn_undead", "resist_fear",
436     "resist_cancellation", "resist_deplete", "resist_death", "resist_chaos",
437     "resist_counterspell", "resist_godpower", "resist_holyword",
438     "resist_blind", "elevation"
439    
440     };
441    
442     #define ALLOWED_VARIABLES (sizeof(allowed_variables) / sizeof (char *))
443    
444     /**********************************************************************
445     * widgets
446     **********************************************************************/
447    
448     /*
449     * member: create tag widgets
450     * parent: parent container
451     */
452     static void AttrTagsCreate(Attr self,Widget parent)
453     {
454     int i;
455     self->attrnumber = 0;
456     while (self->desc[self->attrnumber].label)
457     self->attrnumber++;
458    
459     self->tags = (AttrTags*)XtCalloc(self->attrnumber,sizeof(AttrTags));
460     for(i=0; i < self->attrnumber; i++) {
461     if (self->desc[i].type == TypeString) {
462     self->tags[i].cont = XtVaCreateWidget
463     ("box",boxWidgetClass,parent,
464     XtNorientation,XtorientHorizontal,
465     NULL);
466     XtVaCreateManagedWidget
467     ("label",labelWidgetClass,self->tags[i].cont,
468     XtNlabel,self->desc[i].label,
469     NULL);
470     self->tags[i].value = XtVaCreateManagedWidget
471     ("value",asciiTextWidgetClass,self->tags[i].cont,
472     XtNtype,XawAsciiString,
473     XtNeditType,XawtextEdit,
474     NULL);
475     }
476     }
477     for(i=0; i < self->attrnumber; i++) {
478     if (self->desc[i].type == TypeToggle) {
479     self->tags[i].cont = XtVaCreateWidget
480     ("box",boxWidgetClass,parent,
481     XtNorientation,XtorientHorizontal,
482     NULL);
483    
484     self->tags[i].value = XtVaCreateManagedWidget
485     ("toggle",toggleWidgetClass, self->tags[i].cont,
486     XtNlabel,self->desc[i].label,
487     NULL);
488     }
489     }
490     }
491    
492    
493     /*
494     * callback: receive ok
495     */
496     static void AttrOkCb(Widget w,XtPointer client,XtPointer call)
497     {
498     Attr self = (Attr)client;
499    
500     AttrApply(self);
501     AttrDestroy (self);
502     }
503    
504     /*
505     * receive apply
506     */
507     static void AttrApplyCb(Widget w,XtPointer client,XtPointer call)
508     {
509     Attr self = (Attr)client;
510     AttrApply(self);
511     }
512    
513     /*
514     * receive cancel
515     */
516     static void AttrCancelCb(Widget w,XtPointer client,XtPointer call)
517     {
518     Attr self = (Attr)client;
519    
520     AttrDestroy(self);
521     }
522    
523     /*
524     * receive dump
525     */
526     static void AttrDumpCb(Widget w,XtPointer client,XtPointer call)
527     {
528     Attr self = (Attr)client;
529    
530     dump_object(self->op);
531     CnvBrowseShowString(self->dump,errmsg);
532     }
533    
534     /**********************************************************************
535     * widget-message
536     **********************************************************************/
537    
538    
539     static CrListNode AttrInventoryNext(XtPointer client,XtPointer call)
540     {
541     Attr self = (Attr)client;
542     CrListNode retNode = (CrListNode)call;
543     static struct _CrListNode node;
544     object *op = NULL;
545    
546     if (!self->op)
547     return (CrListNode)NULL;
548    
549     if(retNode) { /* next */
550     op = ((object *)retNode->ptr)->below;
551     } else { /* begin */
552     op = self->op->inv;
553     }
554    
555     if(op) {
556     node.face = op->face;
557     node.name = op->name;
558     node.ptr = (XtPointer)op;
559     return &node;
560     }
561     return (CrListNode)NULL;
562     }
563    
564     /*
565     * callback: insert object
566     */
567     static void InsertCb(Widget w,XtPointer client,XtPointer call)
568     {
569     Attr self = (Attr)client;
570     /* CrListCall ret = (CrListCall)call; */
571     object *obj;
572    
573     if((obj = AppItemGetObject(self->app)) && AttrGetObject(self)) {
574     debug1("Attr-InsertCb() %s\n",obj->name);
575     (void) insert_ob_in_ob(object_create_clone(obj),AttrGetObject(self));
576     }
577     }
578    
579     /*
580     * create recursively attributes from inventory
581     */
582     static void AttrInventorySelectCb(Widget w,XtPointer client,XtPointer call)
583     {
584     Attr self = (Attr)client;
585     CrListCall p = (CrListCall)call;
586     object *ob = (object *)p->node;
587    
588     if (self->attr) {
589     AttrDestroy (self->attr);
590     }
591    
592     self->attr = AttrCreate("attr",self->app, ob,
593     AttrDescription, GetType(ob), self->client);
594     }
595    
596     /*
597     * callback: delete object from look window
598     */
599     static void DeleteCb(Widget w,XtPointer client,XtPointer call)
600     {
601     Attr self = (Attr)client;
602     CrListCall ret = (CrListCall)call;
603     object *obj = ret->node;
604    
605     debug1("Attr-DeleteCb() %s\n",obj->name);
606     if (self->attr && self->attr->op == obj)
607     AttrDestroy (self->attr);
608     remove_ob(obj);
609     free_object(obj);
610     }
611    
612     /**********************************************************************
613     * widget - variables
614     **********************************************************************/
615    
616     /*
617     *
618     */
619     static void AttrVarSelectCb(Widget w,XtPointer client,XtPointer call)
620     {
621     Attr self = (Attr)client;
622     XawListReturnStruct *ret = (XawListReturnStruct*)call;
623     XtVaSetValues(self->iw.var,
624     XtNstring,ret->string,
625     NULL);
626     XtPopdown(self->vars.shell);
627     }
628    
629     /*
630     *
631     */
632     static void AttrVarCancelCb(Widget w,XtPointer client,XtPointer call)
633     {
634     Attr self = (Attr)client;
635     XtPopdown(self->vars.shell);
636     }
637    
638     /*
639     * compare funtion for sorting in PathListGet()
640     */
641     static int StrCmp (const void **s1, const void **s2)
642     {
643     return strcmp (*s1, *s2);
644     }
645    
646     /*
647     * create widget layout for selectin variable from list
648     */
649     static void AttrVarLayout(Attr self,Widget parent)
650     {
651     Widget form,cancel,view;
652    
653     self->vars.shell = XtVaCreatePopupShell
654     ("vars",transientShellWidgetClass,parent,
655     NULL);
656     form = XtVaCreateManagedWidget
657     ("form",formWidgetClass,self->vars.shell,
658     NULL);
659     view = XtVaCreateManagedWidget
660     ("view",viewportWidgetClass,form,
661     NULL);
662     self->vars.list = XtVaCreateManagedWidget
663     ("list",listWidgetClass,view,
664     NULL);
665     XtAddCallback(self->vars.list,XtNcallback,AttrVarSelectCb,(XtPointer)self);
666     /*** sort varibales ***/
667    
668     qsort(allowed_variables, ALLOWED_VARIABLES,
669     sizeof(char *),(int (*)())StrCmp);
670    
671     XawListChange(self->vars.list,allowed_variables,
672     ALLOWED_VARIABLES, 0, True);
673     cancel = XtVaCreateManagedWidget
674     ("cancel",commandWidgetClass,form,
675     XtNfromVert,view,
676     NULL);
677     XtAddCallback(cancel,XtNcallback,AttrVarCancelCb,(XtPointer)self);
678     CnvCenterWidget(self->vars.shell);
679     }
680    
681     /*
682     *
683     */
684     static void AttrVarGetCb(Widget w,XtPointer client,XtPointer call)
685     {
686     Attr self = (Attr)client;
687     XtPopup(self->vars.shell,XtGrabExclusive);
688     }
689    
690     /**********************************************************************
691     * members
692     **********************************************************************/
693    
694     void AppLayout(Attr self,Widget parent, char *name)
695     {
696     Widget form,view1,pane;
697     Widget ok,apply,cancel;
698     Widget view;
699    
700     self->shell = XtVaCreatePopupShell
701     (name, topLevelShellWidgetClass, parent, NULL);
702     form = XtVaCreateManagedWidget("form",formWidgetClass,self->shell,NULL);
703    
704     self->iw.name = XtVaCreateManagedWidget
705     ("name",asciiTextWidgetClass,form,
706     XtNtype,XawAsciiString,
707     XtNeditType,XawtextEdit,
708     XtNresize,False,
709     XtNadjust,False,
710     NULL);
711    
712     self->iw.face = XtVaCreateManagedWidget
713     ("face",crFaceWidgetClass,form,
714     XtNfromVert,self->iw.name,
715     XtNresize,True,
716     XtNadjust,False,
717     XtNobject,self->op,
718     NULL);
719    
720     /*** dump ***/
721     self->iw.exact = XtVaCreateManagedWidget
722     ("exact",commandWidgetClass,form,
723     XtNfromVert,self->iw.face,
724     XtNresize,True,
725     XtNadjust,False,
726     NULL);
727     XtAddCallback(self->iw.exact,XtNcallback,AttrDumpCb,(XtPointer)self);
728    
729     /*** inventory ***/
730     view = XtVaCreateManagedWidget
731     ("inventory",viewportWidgetClass,form,
732     XtNfromVert,self->iw.name,
733     XtNfromHoriz,self->iw.face,
734     NULL);
735    
736     self->iw.inv = XtVaCreateManagedWidget
737     ("list",crListWidgetClass,view,
738     XtNpackage, self,
739     XtNnext, AttrInventoryNext,
740     NULL);
741     XtAddCallback(self->iw.inv,XtNselectCallback,AttrInventorySelectCb,
742     (XtPointer)self);
743     XtAddCallback(self->iw.inv,XtNinsertCallback,InsertCb,
744     (XtPointer)self);
745     XtAddCallback(self->iw.inv,XtNdeleteCallback,DeleteCb,
746     (XtPointer)self);
747    
748     /*** multi ***/
749     view1 = XtVaCreateManagedWidget
750     ("view",viewportWidgetClass,form,
751     /*XtNallowVert,True,*/
752     XtNforceBars,True,
753     XtNfromVert,self->iw.exact,
754     NULL);
755     pane = XtVaCreateManagedWidget
756     ("pane",boxWidgetClass,view1,
757     XtNorientation,XtorientVertical,
758     NULL);
759    
760     /*** variable setting ***/
761     AttrVarLayout(self,parent);
762    
763     self->iw.msg = XtVaCreateManagedWidget
764     ("msg",asciiTextWidgetClass,form,
765     XtNtype,XawAsciiString,
766     XtNeditType,XawtextEdit,
767     XtNfromHoriz,NULL,
768     XtNfromVert,view1,
769     NULL);
770    
771    
772     self->iw.vars = XtVaCreateManagedWidget
773     ("vars",commandWidgetClass,form,
774     XtNfromVert,self->iw.msg,
775     NULL);
776     XtAddCallback(self->iw.vars,XtNcallback,AttrVarGetCb,(XtPointer)self);
777     self->iw.var = XtVaCreateManagedWidget
778     ("var",asciiTextWidgetClass,form,
779     XtNfromHoriz,self->iw.vars,
780     XtNfromVert,self->iw.msg,
781     XtNtype,XawAsciiString,
782     XtNeditType,XawtextEdit,
783     NULL);
784    
785     /*** reponses ***/
786     ok = XtVaCreateManagedWidget
787     ("ok",commandWidgetClass,form,
788     XtNfromVert,self->iw.vars,
789     NULL);
790     XtAddCallback(ok,XtNcallback,AttrOkCb,(XtPointer)self);
791     apply = XtVaCreateManagedWidget
792     ("apply",commandWidgetClass,form,
793     XtNfromVert,self->iw.vars,
794     XtNfromHoriz,ok,
795     NULL);
796     XtAddCallback(apply,XtNcallback,AttrApplyCb,(XtPointer)self);
797     cancel = XtVaCreateManagedWidget
798     ("cancel",commandWidgetClass,form,
799     XtNfromVert,self->iw.vars,
800     XtNfromHoriz,apply,
801     NULL);
802     XtAddCallback(cancel,XtNcallback,AttrCancelCb,(XtPointer)self);
803    
804     AttrTagsCreate(self,pane);
805     }
806    
807     /*
808     * - create object attribute editor from given object
809     * - change values in future of given object
810     * - struct Attr don't have to be initialized, but have to be
811     * allocated anyway.
812     * - create widgets & popup window
813     */
814     Attr AttrCreate(char *name, App app, object *ob,
815     AttrDef *desc, unsigned long flags, Edit edit)
816     {
817     Attr self = (Attr) XtMalloc (sizeof(struct _Attr));
818    
819     if (ob->head)
820     ob = ob->head;
821     self->op = ob;
822     self->app = app;
823     self->client = edit;
824     self->attr = NULL;
825    
826     self->desc = desc;
827     AppLayout (self, self->app->shell, name);
828     AttrChange(self,self->op, flags, self->client);
829    
830     self->dump = CnvBrowseCreate("dump", self->app->shell, NULL);
831     XtPopup(self->shell,XtGrabNone);
832     self->isup = True;
833     return self;
834     }
835    
836     /*
837     * change object to another
838     */
839     void AttrChange(Attr self,object *ob, unsigned long flags, Edit edit)
840     {
841     char buf[BUFSIZ];
842     int i, mask = 1;
843    
844     if (!self)
845     return;
846    
847     if (self->attr)
848     AttrDestroy (self->attr);
849    
850     if (ob && ob->head)
851     ob = ob->head;
852     self->op = ob;
853    
854     if(!ob) {
855     AttrReset(self);
856     XtVaSetValues(self->shell,
857     XtNtitle,"",
858     NULL);
859     return;
860     }
861    
862     self->flags = flags;
863    
864     /*** name ***/
865     XtVaSetValues(self->iw.name,
866     XtNstring,self->op->name,
867     NULL);
868    
869     /*** object ***/
870     XtVaSetValues(self->iw.face,
871     XtNobject,self->op,
872     NULL);
873    
874     /*** message ***/
875     XtVaSetValues(self->iw.msg,
876     XtNstring,self->op->msg,
877     NULL);
878    
879     /*** inventory ***/
880     XtVaSetValues(self->iw.inv,
881     XtNpackage,self,
882     NULL);
883    
884     /* get attribute value */
885     for (i = 0; self->desc[i].label; i++, mask <<= 1)
886     if(self->flags & mask) {
887     self->desc[i].getValue (ob, buf, (XtPointer) self->client);
888     if (self->desc[i].type == TypeString) {
889     XtVaSetValues(self->tags[i].value,
890     XtNstring, buf,
891     NULL);
892     } else if (self->desc[i].type == TypeToggle) {
893     XtVaSetValues(self->tags[i].value,
894     XtNstate, *buf ? TRUE : FALSE,
895     NULL);
896     }
897     }
898    
899     /*** update ***/
900     for(i=0; self->desc[i].label; i++) {
901     XtUnmanageChild(self->tags[i].cont);
902     }
903     for(i=0; self->desc[i].label; i++) {
904     if(self->flags & (1 << i)) {
905     XtManageChild(self->tags[i].cont);
906     }
907     }
908     sprintf(buf,"Attr: %s",self->op->name);
909     XtVaSetValues(self->shell,
910     XtNtitle,buf,
911     XtNiconName,buf,
912     NULL);
913     self->modified = False;
914     }
915    
916     static void AttrReset(Attr self)
917     {
918     int i;
919     debug0("Attr-Reset()\n");
920     /*** name ***/
921     XtVaSetValues(self->iw.name,
922     XtNstring,NULL,
923     NULL);
924     /*** object ***/
925     XtVaSetValues(self->iw.face,
926     XtNobject,NULL,
927     NULL);
928     /*** message ***/
929     XtVaSetValues(self->iw.msg,
930     XtNstring,NULL,
931     NULL);
932     /*** inventory ***/
933     XtVaSetValues(self->iw.inv,
934     XtNpackage,self,
935     NULL);
936    
937     for(i=0; self->desc[i].label; i++) {
938     XtUnmanageChild(self->tags[i].cont);
939     }
940     }
941    
942     /*
943     * popdown window & destroy widgets
944     */
945     void AttrDestroy(Attr self)
946     {
947     Attr tmp2;
948    
949     if (self->attr)
950     AttrDestroy (self->attr);
951     XtDestroyWidget(self->shell);
952     XtFree((char*)self->tags);
953     self->isup = False;
954     CnvBrowseDestroy(self->dump);
955    
956     /*
957     * dirty part:
958     * here we find out to what part this window belongs to.
959     * it may be:
960     * - Attr of Look in App
961     * - Attr of other Attr (inventory)
962     */
963    
964     if (self == self->app->attr)
965     self->app->attr = NULL;
966     else {
967     for (tmp2 = self->app->attr; tmp2; tmp2 = tmp2->attr)
968     if (self == tmp2->attr) {
969     tmp2->attr = NULL;
970     break;
971     }
972     #ifdef DEBUG
973     if (!tmp2)
974     debug0 ("Cannot find origin of Attr!!\n");
975     #endif
976     }
977     XtFree((char*)self);
978     }
979    
980     /*
981     * member: store information from edited widget structure
982     * to object structure
983     */
984     void AttrApply(Attr self)
985     {
986     String str,var;
987     object *ob;
988     char buf[BUFSIZ];
989     int len, mask,set_all=1;
990     size_t i;
991    
992     /* check out, that object exist */
993     if(!self->op) {
994     return;
995     }
996    
997     for(ob = self->op; ob && set_all; ob = ob->more) {
998     /*** variable ***/
999     XtVaGetValues(self->iw.var,
1000     XtNstring,&var,
1001     NULL);
1002     if(var && *var) {
1003     debug1("AttrApply(), %s\n",var);
1004    
1005     /* This is a pretty gross hack, but somewhat necessary. Otherwise,
1006     * all pieces of a multisquare monster will get the treasure, which
1007     * is really not what we want.
1008     */
1009     if (!strncmp(var, "randomitems", 11)) set_all=0;
1010     for (i = 0; i < ALLOWED_VARIABLES; i++)
1011     if (!strncmp (allowed_variables[i], var,
1012     strlen(allowed_variables[i]))) {
1013     if (set_variable(ob,var) == -1) {
1014     sprintf(buf,"%s: no such variable",var);
1015     CnvNotify(buf,"Continue",NULL);
1016     }
1017     break;
1018     }
1019     if (i >= ALLOWED_VARIABLES) {
1020     sprintf(buf,"%s: cannot set variable",var);
1021     CnvNotify(buf,"Continue",NULL);
1022     }
1023     }
1024     /*** name ***/
1025     XtVaGetValues(self->iw.name,
1026     XtNstring,&str,
1027     NULL);
1028     if(ob->name) free_string(ob->name);
1029     ob->name = add_string(str);
1030    
1031     /*** message ***/
1032     XtVaGetValues(self->iw.msg,
1033     XtNstring,&str,
1034     NULL);
1035    
1036     if(self->op->msg) free_string(self->op->msg);
1037     if((len = strlen(str))) {
1038     if(str[len-1] != '\n') str[len-1] = '\n'; /*** kludge ***/
1039     self->op->msg = add_string(str);
1040     } else {
1041     self->op->msg = NULL;
1042     }
1043    
1044     /* set individual attribute value */
1045     for (i = 0, mask = 1; self->desc[i].label; i++, mask <<= 1) {
1046     if(self->flags & mask) {
1047     if (self->desc[i].type == TypeString) {
1048     XtVaGetValues(self->tags[i].value, XtNstring, &str, NULL);
1049     self->desc[i].putValue (ob, str, (XtPointer)self->client);
1050     } else if (self->desc[i].type == TypeToggle) {
1051     Boolean tmp;
1052     XtVaGetValues(self->tags[i].value, XtNstate, &tmp, NULL);
1053     *str = tmp ? ~0 : 0;
1054     self->desc[i].putValue (ob, str, (XtPointer)self->client);
1055     }
1056     }
1057     }
1058     } /* for all parts of the object */
1059    
1060     /*** clear variables ***/
1061     XtVaSetValues(self->iw.var,XtNstring,NULL,NULL);
1062    
1063     /*** update ***/
1064     AppUpdate (self->app);
1065    
1066     self->modified = True;
1067     /*self->client->modified = True;*/
1068     EditModified(self->client);
1069     }
1070    
1071    
1072     /*** end of Attr.c ***/