ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/crossedit/CrEdit.c
Revision: 1.1
Committed: Fri Feb 3 07:11:43 2006 UTC (18 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
Branch point for: UPSTREAM
Log Message:
Initial revision

File Contents

# User Rev Content
1 root 1.1 /*
2     * static char *rcsid_map_c =
3     * "$Id: CrEdit.c,v 1.8 2005/08/30 22:15:25 akirschbaum Exp $";
4     */
5    
6     /*
7     CrossFire, A Multiplayer game for X-windows
8    
9     Copyright (C) 2001 Mark Wedel & Crossfire Development Team
10     Copyright (C) 1992 Frank Tore Johansen
11    
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16    
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20     GNU General Public License for more details.
21    
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25    
26     The authors can be reached via e-mail at crossfire-devel@real-time.com
27     */
28    
29     #include "Defines.h"
30     #include "Ansi.h"
31     #include "Xaw.h"
32     #include <X11/IntrinsicP.h>
33     #include <X11/StringDefs.h>
34    
35     #include "global.h"
36     #include "debug.h"
37    
38     #include "Cnv.h"
39     #include "CrEditP.h"
40     #include "CrUtil.h"
41    
42     extern Pixmap *pixmaps; /* list of pixmaps */
43    
44     /**********************************************************************
45     * resources
46     **********************************************************************/
47    
48     static XtResource resources[] = {
49     #define Offset(field) XtOffsetOf(CrEditRec, crEdit.field)
50     {
51     XtNinsertCallback,
52     XtCInsertCallback,
53     XtRCallback,
54     sizeof(XtCallbackList),
55     Offset(insertCallbacks),
56     XtRCallback,
57     NULL
58     },{
59     XtNselectCallback,
60     XtCSelectCallback,
61     XtRCallback,
62     sizeof(XtCallbackList),
63     Offset(selectCallbacks),
64     XtRCallback,
65     NULL
66     },{
67     XtNpropsCallback,
68     XtCPropsCallback,
69     XtRCallback,
70     sizeof(XtCallbackList),
71     Offset(propsCallbacks),
72     XtRCallback,
73     NULL
74     },{
75     XtNdeleteCallback,
76     XtCDeleteCallback,
77     XtRCallback,
78     sizeof(XtCallbackList),
79     Offset(deleteCallbacks),
80     XtRCallback,
81     NULL
82     },{
83     XtNalignCallback,
84     XtCAlignCallback,
85     XtRCallback,
86     sizeof(XtCallbackList),
87     Offset(alignCallbacks),
88     XtRCallback,
89     NULL
90     },{
91     XtNfeedCallback,
92     XtCFeedCallback,
93     XtRCallback,
94     sizeof(XtCallbackList),
95     Offset(feedCallbacks),
96     XtRCallback,
97     NULL
98     },{
99     XtNmap,
100     XtCMap,
101     XtRPointer,
102     sizeof(XtPointer),
103     Offset(map),
104     XtRPointer,
105     NULL
106     },{
107     XtNstacking,
108     XtCStacking,
109     XtRInt,
110     sizeof(int),
111     Offset(stacking),
112     XtRImmediate,
113     (XtPointer)0
114     },{
115     XtNshow_weak_walls,
116     XtCShow_weak_walls,
117     XtRInt,
118     sizeof(int),
119     Offset(show_weak_walls),
120     XtRImmediate,
121     (XtPointer)0
122     },{
123     XtNselectArea,
124     XtCSelectArea,
125     XtRBoolean,
126     sizeof(Boolean),
127     Offset(selectArea),
128     XtRBoolean,
129     (XtPointer)NULL,
130     }
131     #undef offset
132     };
133    
134     /**********************************************************************
135     * declarations
136     **********************************************************************/
137    
138     static void UpdatePosition (Widget w, int x, int y,Boolean inv);
139     static void ClassInitialize();
140     static void Initialize(Widget req,Widget new,Arg args[],Cardinal *num);
141     static void Destroy(Widget w);
142     static void Resize(Widget w);
143     static void Redisplay(Widget w,XEvent *event,Region region);
144     static Boolean SetValues(Widget cur,Widget req,Widget new,
145     Arg args[],Cardinal *num);
146    
147     #define EmptyObject "editor_archetype"
148    
149     /**********************************************************************
150     * actions & translations
151     **********************************************************************/
152    
153     static void InsertAc ( Widget w, XEvent * event,
154     String * argv, Cardinal * argc );
155     static void DeleteAc ( Widget w, XEvent * event,
156     String * argv, Cardinal * argc );
157     static void PropsAc ( Widget w, XEvent * event,
158     String * argv, Cardinal * argc );
159     static void MoveAc ( Widget w, XEvent * e,
160     String * argv, Cardinal * argc );
161     static void ResizeAc ( Widget w, XEvent * e,
162     String * argv, Cardinal * argc );
163     static void ScrollAc ( Widget w, XEvent * e,
164     String * argv, Cardinal * argc );
165     static void SelectBeginAc ( Widget w, XEvent * e,
166     String * argv, Cardinal * argc );
167     static void SelectExpandAc ( Widget w, XEvent * e,
168     String * argv, Cardinal * argc );
169     static void SelectEndAc ( Widget w, XEvent * e,
170     String * argv, Cardinal * argc );
171     static void FeedAc ( Widget w, XEvent * e,
172     String * argv, Cardinal * argc );
173    
174     XtActionsRec actions[] = {
175     {"Insert", InsertAc},
176     {"SelectBegin", SelectBeginAc},
177     {"SelectExpand", SelectExpandAc},
178     {"SelectEnd", SelectEndAc},
179     {"Props", PropsAc},
180     {"Delete", DeleteAc},
181     {"Feed", FeedAc},
182     {"Move", MoveAc},
183     {"Resize", ResizeAc},
184     {"Scroll", ScrollAc},
185     };
186    
187     static char translations[] = "\
188     <Btn1Up>: Insert(archetype) \n\
189     <Btn1Motion>: Insert(archetype) \n\
190     Ctrl<Btn2Up>: Feed(coordinate) \n\
191     Ctrl<Btn2Motion>: Feed(coordinate) \n\
192     Shift<Btn2Up>: Props() \n\
193     None<Btn2Down>: SelectBegin() \n\
194     None<Btn2Motion>: SelectExpand() \n\
195     None<Btn2Up>: SelectEnd() \n\
196     <Btn3Down>: Delete(archetype) \n\
197     <Btn3Motion>: Delete(archetype) \n\
198     Ctrl<Key>Right: Resize(right) \n\
199     Ctrl<Key>Left: Resize(left) \n\
200     Ctrl<Key>Down: Resize(down) \n\
201     Ctrl<Key>Up: Resize(up) \n\
202     Shift<Key>Right: Scroll(right) \n\
203     Shift<Key>Left: Scroll(left) \n\
204     Shift<Key>Down: Scroll(down) \n\
205     Shift<Key>Up: Scroll(up) \n\
206     <Key>Right: Move(right) \n\
207     <Key>Left: Move(left) \n\
208     <Key>Down: Move(down) \n\
209     <Key>Up: Move(up) \n\
210     ";
211    
212     /**********************************************************************
213     * class record
214     **********************************************************************/
215    
216     CrEditClassRec crEditClassRec = {
217     { /* core fields */
218     /* superclass */ (WidgetClass)&widgetClassRec,
219     /* class_name */ "CrEdit",
220     /* widget_size */ sizeof(CrEditRec),
221     /* class_initialize */ ClassInitialize,
222     /* class_part_initialize */ NULL,
223     /* class_inited */ FALSE,
224     /* initialize */ Initialize,
225     /* initialize_hook */ NULL,
226     /* realize */ XtInheritRealize,
227     /* actions */ actions,
228     /* num_actions */ XtNumber(actions),
229     /* resources */ resources,
230     /* num_resources */ XtNumber(resources),
231     /* xrm_class */ NULLQUARK,
232     /* compress_motion */ TRUE,
233     /* compress_exposure */ TRUE,
234     /* compress_enterleave */ TRUE,
235     /* visible_interest */ FALSE,
236     /* destroy */ Destroy,
237     /* resize */ Resize,
238     /* expose */ Redisplay,
239     /* set_values */ SetValues,
240     /* set_values_hook */ NULL,
241     /* set_values_almost */ XtInheritSetValuesAlmost,
242     /* get_values_hook */ NULL,
243     /* accept_focus */ NULL,
244     /* version */ XtVersion,
245     /* callback_private */ NULL,
246     /* tm_table */ translations,
247     /* query_geometry */ XtInheritQueryGeometry,
248     /* display_accelerator */ XtInheritDisplayAccelerator,
249     /* extension */ NULL
250     },
251     { /* crEdit fields */
252     /* empty */ 0
253     }
254     };
255    
256     WidgetClass crEditWidgetClass = (WidgetClass)&crEditClassRec;
257    
258     /**********************************************************************
259     * inner functions
260     **********************************************************************/
261    
262     /*
263     *
264     */
265     static void SegToRec(XSegment *seg,XRectangle *rec)
266     {
267     /*** calculate rectangle ***/
268     rec->x = seg->x1 < seg->x2 ? seg->x1 : seg->x2;
269     rec->y = seg->y1 < seg->y2 ? seg->y1 : seg->y2;
270     rec->width = abs(seg->x1 - seg->x2) + 1;
271     rec->height = abs(seg->y1 - seg->y2) + 1;
272     }
273    
274     static void SetSize(Widget w)
275     {
276     CrEditWidget self = (CrEditWidget)w;
277     XtWidgetGeometry request,reply;
278     /*Dimension width,height,rWidth,rHeight;*/
279    
280     /*** determine size to ask for ***/
281     if(self->crEdit.map) {
282     request.width = MAP_WIDTH(self->crEdit.map) * self->crEdit.fontSize;
283     request.height = MAP_HEIGHT(self->crEdit.map) * self->crEdit.fontSize;
284     } else {
285     request.width = self->crEdit.fontSize;
286     request.height = self->crEdit.fontSize;
287     }
288     request.x = request.y = 0;
289     request.request_mode = CWWidth | CWHeight;
290    
291     /*** ask it ***/
292     switch(XtMakeGeometryRequest(w,&request,&reply)) {
293     case XtGeometryYes:
294     break;
295     case XtGeometryNo:
296     debug1 ("%s: May not change my geometry\n",XtName(w));
297     break;
298     case XtGeometryAlmost:
299     XtMakeGeometryRequest(w,&reply,&reply);
300     break;
301     default:
302     CnvDie(w,"Unknown geometry request return");
303     break;
304     };
305     /*
306     XSendEvent(XtDisplay(w),XtWindow(w),False,ResizeRequest,NULL);
307     */
308     debug3("%s: setting widget size to %dx%d\n",XtName(w),self->core.width,
309     self->core.height);
310     }
311    
312     /**********************************************************************
313     **********************************************************************/
314    
315    
316     static void AnimateCursor (Widget w, int x, int y) {
317     /* Currently, this was only supported with bitmap mode.
318     * I'm sure soething clever could be done in other modes.
319     */
320    
321     }
322    
323    
324    
325     /**********************************************************************
326     * drawing functions
327     * hierarchy:
328     * DrawRectangle DrawBorder
329     * UpdatePosition
330     * DrawObject
331     **********************************************************************/
332    
333     /*
334     * inv : draw inverse colored object if True
335     */
336    
337    
338     /*
339     * member: update object stack at point in map
340     * x,y : point
341     * inv : draw inverse
342     */
343     static void UpdatePosition (Widget w, int x, int y,Boolean inv)
344     {
345     CrEditWidget self = (CrEditWidget)w;
346     object *op;
347     int i;
348    
349     if(out_of_map(self->crEdit.map,x,y)) return;
350    
351     if (self->crEdit.stacking) {
352     /* stacking mode */
353     float xb, yb;
354     XClearArea (XtDisplay(w), XtWindow(w),
355     x * self->crEdit.fontSize,
356     y * self->crEdit.fontSize,
357     self->crEdit.fontSize,
358     self->crEdit.fontSize, False);
359     for (i = 0, op = get_map_ob (self->crEdit.map, x, y);
360     op;
361     i++, op = op->above);
362     if (i > 0) {
363     int diff = self->crEdit.fontSize - FontSize;
364     int depth = diff / STACK_MIN + 1;
365     float dist = 0;
366    
367     if (depth < 1)
368     depth = 1;
369     for (op = get_map_ob (self->crEdit.map, x, y); i > depth; i--)
370     op = op->above;
371    
372     i--;
373     if (i) {
374     dist = (diff - 1) / (float)i;
375     if (dist > STACK_MAX)
376     dist = STACK_MAX;
377     }
378    
379     xb = diff + x * self->crEdit.fontSize - 1;
380     yb = diff + y * self->crEdit.fontSize - 1;
381    
382     while (op) {
383     if (QUERY_FLAG(op, FLAG_TEAR_DOWN) && self->crEdit.show_weak_walls) {
384     New_Face * f;
385     f = &new_faces[GET_ANIMATION(op,NUM_ANIMATIONS(op)/2)];
386     DrawFacePart(w, self->crEdit.gc, f, xb, yb, 0, 0);
387     } else {
388     DrawPartObject(w, self->crEdit.gc, op, xb, yb);
389     }
390    
391     if (HAS_COLOUR(w)) {
392     XSetForeground(XtDisplay(w), self->crEdit.gc,
393     BlackPixelOfScreen(XtScreen(w)));
394     }
395     XDrawRectangle (XtDisplay(w),
396     XtWindow(w), self->crEdit.gc,
397     (int) xb, (int) yb, FontSize -1, FontSize -1);
398     xb -= dist;
399     yb -= dist;
400     op = op->above;
401     }
402     }
403     } else { /* Normal map drawing routine */
404     New_Face *f;
405    
406     if (GET_MAP_FLAGS(self->crEdit.map, x, y) & P_NEED_UPDATE) {
407     update_position(self->crEdit.map, x, y);
408     }
409    
410     if (displaymode==Dm_Png) {
411     op = GET_MAP_FACE_OBJ(self->crEdit.map, x, y, 2);
412     if (op != NULL)
413     DrawPartObject(w, self->crEdit.gc, op,
414     x * self->crEdit.fontSize,
415     y * self->crEdit.fontSize);
416     op = GET_MAP_FACE_OBJ(self->crEdit.map, x, y, 1);
417     if (op != NULL && op->face->number != blank_face->number)
418     DrawPartObject(w, self->crEdit.gc, op,
419     x * self->crEdit.fontSize,
420     y * self->crEdit.fontSize);
421     op = GET_MAP_FACE_OBJ(self->crEdit.map, x, y, 0);
422     if (op != NULL && op->face->number != blank_face->number)
423     DrawPartObject(w, self->crEdit.gc, op,
424     x * self->crEdit.fontSize,
425     y * self->crEdit.fontSize);
426     }
427     op=get_map_ob(self->crEdit.map, x, y);
428     while (op && op->above) op=op->above;
429     if (op == NULL) {
430     ; /* Paint nothing */
431     } else if (QUERY_FLAG(op, FLAG_TEAR_DOWN) && self->crEdit.show_weak_walls) {
432     f = &new_faces[GET_ANIMATION(op, NUM_ANIMATIONS(op)/2)];
433    
434     if (displaymode == Dm_Png || f->number != blank_face->number)
435     DrawFacePart (w, self->crEdit.gc, f,
436     x * self->crEdit.fontSize,
437     y * self->crEdit.fontSize,
438     0, 0);
439     } else {
440     if (displaymode == Dm_Png || op->face->number != blank_face->number)
441     DrawPartObject (w, self->crEdit.gc, op,
442     x * self->crEdit.fontSize,
443     y * self->crEdit.fontSize);
444     }
445     }
446     return;
447     }
448    
449     /*
450     * member: draw filled rectangle
451     * rec : rectangle
452     * inv : True = inverse
453     */
454     static void DrawRectangle(Widget w,XRectangle area,Boolean inv)
455     {
456     CrEditWidget self = (CrEditWidget)w;
457     int i, j;
458    
459     if (!self->crEdit.map) return;
460     for (j = area.x;
461     j < area.x + area.width && j < MAP_WIDTH(self->crEdit.map);
462     j++) {
463     for (i = area.y;
464     i < area.y + area.height && i < MAP_HEIGHT(self->crEdit.map);
465     i++) {
466     UpdatePosition (w,j,i,inv);
467     }
468     }
469     }
470    
471     /*
472     * member: draw open square
473     * seg : start and end points of square
474     * inv : border of square are inversed
475     */
476     static void DrawBorder(Widget w,XSegment seg,Boolean inv)
477     {
478     CrEditWidget self = (CrEditWidget)w;
479     int i,x1,x2,y1,y2;
480    
481     if (!self->crEdit.map) return;
482     x1 = seg.x1 < seg.x2 ? seg.x1 : seg.x2;
483     y1 = seg.y1 < seg.y2 ? seg.y1 : seg.y2;
484     x2 = abs(seg.x1 - seg.x2) + x1;
485     y2 = abs(seg.y1 - seg.y2) + y1;
486    
487     if(x1 > MAP_WIDTH(self->crEdit.map) ||
488     x2 > MAP_WIDTH(self->crEdit.map) ||
489     y1 > MAP_HEIGHT(self->crEdit.map) ||
490     y2 > MAP_HEIGHT(self->crEdit.map)) return;
491    
492     if (inv) {
493     XDrawRectangle (XtDisplay(w), XtWindow(w),
494     DefaultGC(XtDisplay(w), XScreenNumberOfScreen(XtScreen(w))),
495     x1 * self->crEdit.fontSize,
496     y1 * self->crEdit.fontSize,
497     (x2 - x1 + 1) * self->crEdit.fontSize - 1,
498     (y2 - y1 + 1) * self->crEdit.fontSize - 1);
499     XDrawRectangle (XtDisplay(w), XtWindow(w),
500     DefaultGC(XtDisplay(w), XScreenNumberOfScreen(XtScreen(w))),
501     x1 * self->crEdit.fontSize + 1,
502     y1 * self->crEdit.fontSize + 1,
503     (x2 - x1 + 1) * self->crEdit.fontSize - 3,
504     (y2 - y1 + 1) * self->crEdit.fontSize - 3);
505     } else {
506    
507     for(i=x1;
508     i <= x2;
509     i++) {
510     UpdatePosition(w,i,seg.y1,inv);
511     if (y1 != y2)
512     UpdatePosition(w,i,seg.y2,inv);
513     }
514     for(i=y1 + 1;
515     i <= (y2 - 1);
516     i++) {
517     UpdatePosition(w,seg.x1,i,inv);
518     if (x1 != x2)
519     UpdatePosition(w,seg.x2,i,inv);
520     }
521     }
522     }
523    
524     /*
525     * member:
526     * x,y :
527     * return:
528     */
529     static int CalcIndex (Widget w, int x, int y) {
530     CrEditWidget self = (CrEditWidget)w;
531     object *op;
532     int i, j = 0;
533     int xp, yp;
534     float xb, yb;
535    
536     xp = x / self->crEdit.fontSize;
537     yp = y / self->crEdit.fontSize;
538    
539     if (out_of_map (self->crEdit.map, xp, yp))
540     return 0;
541    
542     for (i = 0, op = get_map_ob (self->crEdit.map, xp, yp);
543     op;
544     i++, op = op->above);
545    
546     if (i > 0) {
547     int diff = self->crEdit.fontSize - FontSize;
548     int depth = diff / STACK_MIN;
549     float dist = 0;
550    
551     if (depth == 0)
552     depth = 1;
553     if (i > depth)
554     i = depth;
555    
556     i--;
557     if (i) {
558     dist = (diff - 1) / (float)i;
559     if (dist > STACK_MAX)
560     dist = STACK_MAX;
561     }
562    
563     xb = self->crEdit.fontSize - i * dist;
564     yb = self->crEdit.fontSize - i * dist;
565    
566     x %= self->crEdit.fontSize;
567     y %= self->crEdit.fontSize;
568    
569     debug4 ("%dx%d %d %f\n", x, y, i, dist);
570     for (j = 0; j <= i; j++) {
571     if (x < xb && y < yb)
572     break;
573     xb += dist;
574     yb += dist;
575     }
576     }
577     return (j);
578     }
579    
580     /*
581     * no borders drawing set
582     */
583     static void BorderOff(Widget w)
584     {
585     CrEditWidget self = (CrEditWidget)w;
586     self->crEdit.seg.x1 = 0;
587     self->crEdit.seg.y1 = 0;
588     self->crEdit.seg.x2 = 10000;
589     self->crEdit.seg.y2 = 10000;
590     }
591    
592     /**********************************************************************
593     * actions
594     **********************************************************************/
595    
596     /*
597     * action: insert object to map
598     */
599     static void InsertAc (Widget w, XEvent * event,
600     String * argv, Cardinal * argc)
601     {
602     CrEditWidget self = (CrEditWidget)w;
603     int x, y;
604     static int oldx, oldy;
605     struct CrEditCall call;
606    
607     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
608     x = event->xbutton.x / self->crEdit.fontSize;
609     y = event->xbutton.y / self->crEdit.fontSize;
610    
611     if(XtHasCallbacks(w,XtNinsertCallback) == XtCallbackHasNone) return;
612     /*** fill the call strcture ***/
613     call.rect.x = x;
614     call.rect.y = y;
615     call.rect.width = 0;
616     call.rect.height = 0;
617     call.map = self->crEdit.map;
618     call.z = self->crEdit.stacking ?
619     CalcIndex (w,event->xbutton.x,event->xbutton.y) : 0;
620    
621     if (!(event->type == MotionNotify && x == oldx && y == oldy)) {
622     XtCallCallbackList(w,self->crEdit.insertCallbacks,(XtPointer)&call);
623     }
624     oldx = x;
625     oldy = y;
626     }
627    
628     /*
629     * action: set begin of selection
630     */
631     static void SelectBeginAc(Widget w, XEvent * event,
632     String * argv, Cardinal * argc)
633     {
634     CrEditWidget self = (CrEditWidget)w;
635     int x,y;
636    
637     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
638     if(!self->crEdit.selectArea) return;
639     DrawBorder(w,self->crEdit.seg,False);
640    
641     x = event->xbutton.x / self->crEdit.fontSize;
642     y = event->xbutton.y / self->crEdit.fontSize;
643    
644     debug2("SelectBeginAc() %dx%d\n",x,y);
645    
646     if(out_of_map(self->crEdit.map,x,y)) return;
647    
648     self->crEdit.seg.x1 = self->crEdit.seg.x2 = x;
649     self->crEdit.seg.y1 = self->crEdit.seg.y2 = y;
650     DrawBorder(w,self->crEdit.seg,True);
651     }
652    
653     /*
654     * action: expand selection
655     */
656     static void SelectExpandAc(Widget w, XEvent * event,
657     String * argv, Cardinal * argc)
658     {
659     CrEditWidget self = (CrEditWidget)w;
660     int x,y;
661     static int oldx, oldy;
662    
663     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
664     if(!self->crEdit.selectArea) return;
665    
666     x = event->xbutton.x / self->crEdit.fontSize;
667     y = event->xbutton.y / self->crEdit.fontSize;
668    
669     if (x >= MAP_WIDTH(self->crEdit.map) )
670     x = MAP_WIDTH(self->crEdit.map) - 1;
671     if (x < 0)
672     x = 0;
673    
674     if (y >= MAP_HEIGHT(self->crEdit.map) )
675     y = MAP_HEIGHT(self->crEdit.map) - 1;
676     if (y < 0)
677     y = 0;
678    
679     if (!(event->type == MotionNotify && x == oldx && y == oldy)) {
680     DrawBorder(w,self->crEdit.seg,False);
681     self->crEdit.seg.x2 = x;
682     self->crEdit.seg.y2 = y;
683     DrawBorder(w,self->crEdit.seg,True);
684     }
685     oldx = x;
686     oldy = y;
687     }
688    
689     /*
690     * action: get end of selection
691     */
692     static void SelectEndAc(Widget w, XEvent * event,
693     String * argv, Cardinal * argc)
694     {
695     CrEditWidget self = (CrEditWidget)w;
696     int x,y;
697     struct CrEditCall call;
698    
699     x = event->xbutton.x / self->crEdit.fontSize;
700     y = event->xbutton.y / self->crEdit.fontSize;
701    
702     debug2("SelectEndAc() %dx%d\n",x,y);
703    
704     if (x >= MAP_WIDTH(self->crEdit.map) )
705     x = MAP_WIDTH(self->crEdit.map) - 1;
706     if (x < 0)
707     x = 0;
708    
709     if (y >= MAP_HEIGHT(self->crEdit.map) )
710     y = MAP_HEIGHT(self->crEdit.map) - 1;
711     if (y < 0)
712     y = 0;
713    
714     /*** fill the call strcture ***/
715     if(self->crEdit.selectArea) {
716     SegToRec(&self->crEdit.seg,&call.rect);
717     } else {
718     call.rect.x = x;
719     call.rect.y = y;
720     call.rect.width = 0;
721     call.rect.height = 0;
722     }
723     call.map = self->crEdit.map;
724     call.z = 0;
725    
726     XtCallCallbackList(w,self->crEdit.selectCallbacks,(XtPointer)&call);
727     }
728    
729     /*
730     * action:
731     */
732     static void PropsAc(Widget w, XEvent * event,
733     String * argv, Cardinal * argc)
734     {
735     CrEditWidget self = (CrEditWidget)w;
736     int x, y;
737     struct CrEditCall call;
738    
739     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
740     x = event->xbutton.x / self->crEdit.fontSize;
741     y = event->xbutton.y / self->crEdit.fontSize;
742    
743     /*** fill the call strcture ***/
744     call.rect.x = x;
745     call.rect.y = y;
746     call.rect.width = 0;
747     call.rect.height = 0;
748     call.map = self->crEdit.map;
749     call.z = self->crEdit.stacking ? CalcIndex
750     (w,event->xbutton.x, event->xbutton.y) : 0;
751    
752     XtCallCallbackList(w,self->crEdit.propsCallbacks,(XtPointer)&call);
753     }
754    
755     /*
756     * action: delete object from map
757     */
758     static void DeleteAc(Widget w, XEvent * event,
759     String * argv, Cardinal * argc)
760     {
761     CrEditWidget self = (CrEditWidget)w;
762     int x, y;
763     static int oldx, oldy;
764     struct CrEditCall call;
765    
766     AnimateCursor (w, event->xbutton.x, event->xbutton.y);
767     x = event->xbutton.x / self->crEdit.fontSize;
768     y = event->xbutton.y / self->crEdit.fontSize;
769    
770     if (!(event->type == MotionNotify && x == oldx && y == oldy)) {
771     /*** fill the call strcture ***/
772     call.rect.x = x;
773     call.rect.y = y;
774     call.rect.width = 0;
775     call.rect.height = 0;
776     call.map = self->crEdit.map;
777     call.z = self->crEdit.stacking ? CalcIndex
778     (w,event->xbutton.x, event->xbutton.y) : 0;
779    
780     XtCallCallbackList(w,self->crEdit.deleteCallbacks,(XtPointer)&call);
781     UpdatePosition(w,x,y,False);
782     }
783     oldx = x;
784     oldy = y;
785     }
786    
787     /*
788     * action: feed point
789     */
790     static void FeedAc (Widget w, XEvent * event, String * argv, Cardinal * argc)
791     {
792     CrEditWidget self = (CrEditWidget)w;
793     int x, y;
794     static int oldx, oldy;
795     struct CrEditCall call;
796    
797     x = event->xbutton.x / self->crEdit.fontSize;
798     y = event->xbutton.y / self->crEdit.fontSize;
799    
800     if (!(event->type == MotionNotify && x == oldx && y == oldy)) {
801     /*** fill the call strcture ***/
802     call.rect.x = x;
803     call.rect.y = y;
804     call.rect.width = 0;
805     call.rect.height = 0;
806     call.map = self->crEdit.map;
807     call.z = self->crEdit.stacking ? CalcIndex
808     (w,event->xbutton.x, event->xbutton.y) : 0;
809    
810     XtCallCallbackList(w,self->crEdit.feedCallbacks,(XtPointer)&call);
811     }
812    
813     oldx = x;
814     oldy = y;
815     }
816    
817     /*
818     * action: resize to directions
819     */
820     static void ResizeAc (Widget w, XEvent * e, String * argv, Cardinal * argc)
821     {
822     CrEditWidget self = (CrEditWidget)w;
823     struct CrEditCall call;
824     char buf[BUFSIZ];
825    
826     call.map = self->crEdit.map;
827     call.rect.x = 0;
828     call.rect.y = 0;
829     call.rect.width = MAP_WIDTH(self->crEdit.map);
830     call.rect.height = MAP_HEIGHT(self->crEdit.map);
831     call.z = 0;
832     if (argv) {
833     if (!strcmp (argv[0], "right")) {
834     call.rect.width++;
835     } else if (!strcmp (argv[0], "left")) {
836     call.rect.width--;
837     } else if (!strcmp (argv[0], "down")) {
838     call.rect.height++;
839     } else if (!strcmp (argv[0], "up")) {
840     call.rect.height--;
841     } else {
842     sprintf(buf,"bad argument %s",argv[0]);
843     CnvWarn(w,buf);
844     }
845     }
846     XtCallCallbackList(w,self->crEdit.alignCallbacks,(XtPointer)&call);
847     }
848    
849     /*
850     * action: scroll around to directions
851     */
852     static void ScrollAc (Widget w, XEvent * e, String * argv, Cardinal * argc)
853     {
854     CrEditWidget self = (CrEditWidget)w;
855     struct CrEditCall call;
856     char buf[BUFSIZ];
857    
858     call.map = self->crEdit.map;
859     call.rect.x = 0;
860     call.rect.y = 0;
861     call.rect.width = MAP_WIDTH(self->crEdit.map);
862     call.rect.height = MAP_HEIGHT(self->crEdit.map);
863     call.z = 0;
864    
865     /*
866     debug4("CrEdit::ScrollAc() by %dx%d+%d+%d",call->rect.width,
867     call->rect.height,call->rect.x,call->rect.y); */
868    
869     if (argv) {
870     if (!strcmp (argv[0], "right")) {
871     call.rect.x++;
872     } else if (!strcmp (argv[0], "left")) {
873     call.rect.x--;
874     } else if (!strcmp (argv[0], "down")) {
875     call.rect.y++;
876     } else if (!strcmp (argv[0], "up")) {
877     call.rect.y--;
878     } else {
879     sprintf(buf,"bad argument %s",argv[0]);
880     CnvWarn(w,buf);
881     }
882     XtCallCallbackList(w,self->crEdit.alignCallbacks,(XtPointer)&call);
883     }
884     }
885    
886     /*
887     * action: move clipped window in viewport
888     */
889     static void MoveAc (Widget w, XEvent * e, String * argv, Cardinal * argc)
890     {
891     /* CrEditWidget self = (CrEditWidget)w; */
892     Widget horizontal, vertical;
893    
894     if (argv) {
895     horizontal = XtNameToWidget (XtParent (w), "horizontal");
896     vertical = XtNameToWidget (XtParent (w), "vertical");
897    
898     if (!strcmp (argv[0], "right")) {
899     String argv[1];
900     argv[0] = XtNewString ("Forward");
901     XtCallActionProc (horizontal, "StartScroll", e, argv, 1);
902     XtFree (argv[0]);
903     argv[0] = XtNewString ("Proportional");
904     XtCallActionProc (horizontal, "NotifyScroll", e, argv, 1);
905     XtFree (argv[0]);
906     XtCallActionProc (horizontal, "EndScroll", e, NULL, 0);
907     } else if (!strcmp (argv[0], "left")) {
908     String argv[1];
909     argv[0] = XtNewString ("Backward");
910     XtCallActionProc (horizontal, "StartScroll", e, argv, 1);
911     XtFree (argv[0]);
912     argv[0] = XtNewString ("Proportional");
913     XtCallActionProc (horizontal, "NotifyScroll", e, argv, 1);
914     XtFree (argv[0]);
915     XtCallActionProc (horizontal, "EndScroll", e, NULL, 0);
916     } else if (!strcmp (argv[0], "down")) {
917     String argv[1];
918     argv[0] = XtNewString ("Forward");
919     XtCallActionProc (vertical, "StartScroll", e, argv, 1);
920     XtFree (argv[0]);
921     argv[0] = XtNewString ("Proportional");
922     XtCallActionProc (vertical, "NotifyScroll", e, argv, 1);
923     XtFree (argv[0]);
924     XtCallActionProc (vertical, "EndScroll", e, NULL, 0);
925     } else if (!strcmp (argv[0], "up")) {
926     String argv[1];
927     argv[0] = XtNewString ("Backward");
928     XtCallActionProc (vertical, "StartScroll", e, argv, 1);
929     XtFree (argv[0]);
930     argv[0] = XtNewString ("Proportional");
931     XtCallActionProc (vertical, "NotifyScroll", e, argv, 1);
932     XtFree (argv[0]);
933     XtCallActionProc (vertical, "EndScroll", e, NULL, 0);
934     }
935     }
936     }
937    
938     /**********************************************************************
939     * members
940     **********************************************************************/
941    
942     static void ClassInitialize()
943     {
944     debug0("CrEdit-ClassInitialize()\n");
945    
946     }
947    
948     static void Initialize(Widget req,Widget new,Arg args[],Cardinal *num)
949     {
950     CrEditWidget self = (CrEditWidget)new;
951    
952     debug1("CrEdit-%s-Initialize()\n",XtName(new));
953    
954     /*** allocate gc ***/
955     self->crEdit.gc = GCCreate (new);
956     self->crEdit.fontSize = FontSize;
957     SetSize(new);
958     BorderOff(new);
959     }
960    
961     static void Destroy(Widget w)
962     {
963     CrEditWidget self = (CrEditWidget)w;
964     debug1("CrEdit-%s-Destroy()\n",XtName(w));
965     XtReleaseGC(w,self->crEdit.gc);
966     }
967    
968     static void Resize(Widget w)
969     {
970     /* CrEditWidget self = (CrEditWidget)w; */
971     debug1("CrEdit-%s-Resize()\n",XtName(w));
972     SetSize(w);
973     }
974    
975     static void Redisplay(Widget w,XEvent *event,Region region)
976     {
977     CrEditWidget self = (CrEditWidget)w;
978     XRectangle rect, new;
979    
980     if(!region) return;
981     XClipBox(region,&rect);
982     new.x = rect.x / self->crEdit.fontSize;
983     new.y = rect.y / self->crEdit.fontSize;
984     new.width = (rect.x + rect.width) / self->crEdit.fontSize - new.x + 1;
985     new.height = (rect.y + rect.height) / self->crEdit.fontSize - new.y + 1;
986    
987     debug5("CrEdit-%s-Expose() %dx%d+%d+%d\n",XtName(w),
988     new.width, new.height, new.x, new.y);
989    
990     DrawRectangle(w,new,False);
991     if (self->crEdit.selectArea)
992     DrawBorder(w, self->crEdit.seg, True);
993     }
994    
995     static Boolean SetValues(Widget cur,Widget req,Widget new,
996     Arg args[],Cardinal *num)
997     {
998     Boolean redpy = False;
999    
1000     CrEditWidget self = (CrEditWidget)new;
1001     CrEditWidget old = (CrEditWidget)cur;
1002     debug1("CrEdit-%s-SetValues()\n",XtName(new));
1003    
1004     /*** stacking change ***/
1005     if(self->crEdit.stacking != old->crEdit.stacking) {
1006     self->crEdit.fontSize = FontSize + self->crEdit.stacking;
1007     SetSize(new);
1008     redpy = True;
1009     }
1010     /*** map change ***/
1011     if(self->crEdit.map != old->crEdit.map) {
1012     SetSize(new);
1013     redpy = True;
1014     }
1015     /*** weak wall change ***/
1016     if(self->crEdit.show_weak_walls != old->crEdit.show_weak_walls) {
1017     SetSize(new);
1018     redpy = True;
1019     }
1020     return redpy; /* redisplay */
1021     }
1022    
1023     /**********************************************************************
1024     * public
1025     **********************************************************************/
1026    
1027     /*
1028     * member: draw rectangle part of w
1029     * rect : rectangle, width = height = 10000 to draw all
1030     */
1031     void CrEditRefresh(Widget w,XRectangle rect)
1032     {
1033     CrEditWidget self = (CrEditWidget)w;
1034     if(!w) return;
1035    
1036    
1037     debug4("CrEditRefresh() %dx%d+%d+%d\n",
1038     rect.width,
1039     rect.height,
1040     rect.x,
1041     rect.y
1042     );
1043     /* for all */
1044     if(rect.width == 10000 && rect.height == 10000) {
1045     XClearWindow(XtDisplay(w),XtWindow(w));
1046     SetSize(w); /* for partially fix to sizing probem */
1047     }
1048     DrawRectangle(w,rect,False);
1049    
1050     if (self->crEdit.selectArea)
1051     DrawBorder(w, self->crEdit.seg, True);
1052     }
1053    
1054     /*
1055     * atc: True: selection-border drawing active, other no draw
1056     */
1057     void CrEditBorderOff(Widget w)
1058     {
1059     CrEditWidget self = (CrEditWidget)w;
1060    
1061     debug1("%s-CrEditBorderOff()\n",XtName(w));
1062     DrawBorder(w,self->crEdit.seg,False);
1063     BorderOff(w);
1064     }
1065    
1066     /*
1067     * member:
1068     * rect :
1069     */
1070     void CrEditSelect(Widget w,XRectangle rect)
1071     {
1072     CrEditWidget self = (CrEditWidget)w;
1073     if(!w) return;
1074    
1075    
1076     debug4("CrEditRefresh() %dx%d+%d+%d\n",
1077     rect.width,
1078     rect.height,
1079     rect.x,
1080     rect.y
1081     );
1082     /* for all */
1083     if(rect.width == 10000 && rect.height == 10000) {
1084     XClearWindow(XtDisplay(w),XtWindow(w));
1085     SetSize(w); /* for partially fix to sizing probem */
1086     }
1087    
1088     if (self->crEdit.selectArea) {
1089     DrawBorder(w, self->crEdit.seg, False);
1090     self->crEdit.seg.x1 = rect.x;
1091     self->crEdit.seg.y1 = rect.y;
1092     self->crEdit.seg.x2 = rect.x + rect.width;
1093     self->crEdit.seg.y2 = rect.y + rect.height;
1094     DrawBorder(w, self->crEdit.seg, True);
1095     }
1096     }
1097    
1098     /*** end of CrEdit.c ***/