1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
23 /* positions in the level editor */
24 #define ED_WIN_MB_LEFT_XPOS 7
25 #define ED_WIN_MB_LEFT_YPOS 6
26 #define ED_WIN_LEVELNR_XPOS 77
27 #define ED_WIN_LEVELNR_YPOS 7
28 #define ED_WIN_MB_MIDDLE_XPOS 7
29 #define ED_WIN_MB_MIDDLE_YPOS 258
30 #define ED_WIN_MB_RIGHT_XPOS 77
31 #define ED_WIN_MB_RIGHT_YPOS 258
33 /* other constants for the editor */
34 #define ED_SCROLL_NO 0
35 #define ED_SCROLL_LEFT 1
36 #define ED_SCROLL_RIGHT 2
37 #define ED_SCROLL_UP 4
38 #define ED_SCROLL_DOWN 8
40 /* screens in the level editor */
41 #define ED_MODE_DRAWING 0
42 #define ED_MODE_INFO 1
43 #define ED_MODE_PROPERTIES 2
45 /* how many steps can be cancelled */
46 #define NUM_UNDO_STEPS (10 + 1)
48 /* values for random placement */
49 #define RANDOM_USE_PERCENTAGE 0
50 #define RANDOM_USE_NUM_OBJECTS 1
52 /* values for elements with content */
53 #define MAX_ELEMCONT 8
55 /* values for the control window */
56 #define ED_CTRL_BUTTONS_GFX_YPOS 236
57 #define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142
59 #define ED_CTRL1_BUTTONS_HORIZ 4
60 #define ED_CTRL1_BUTTONS_VERT 4
61 #define ED_CTRL1_BUTTON_XSIZE 22
62 #define ED_CTRL1_BUTTON_YSIZE 22
63 #define ED_CTRL1_BUTTONS_XPOS 6
64 #define ED_CTRL1_BUTTONS_YPOS 6
65 #define ED_CTRL2_BUTTONS_HORIZ 3
66 #define ED_CTRL2_BUTTONS_VERT 2
67 #define ED_CTRL2_BUTTON_XSIZE 30
68 #define ED_CTRL2_BUTTON_YSIZE 20
69 #define ED_CTRL2_BUTTONS_XPOS 5
70 #define ED_CTRL2_BUTTONS_YPOS 100
71 #define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
72 #define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
73 #define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
75 /* values for properties window */
76 #define ED_PROPERTIES_XPOS (TILEX - MINI_TILEX/2)
78 /* values for counter gadgets */
79 #define ED_COUNT_VALUE_XOFFSET 5
80 #define ED_COUNT_VALUE_YOFFSET 3
81 #define ED_COUNT_SCORE_XPOS ED_PROPERTIES_XPOS
82 #define ED_COUNT_SCORE_YPOS (14 * MINI_TILEY)
83 #define ED_COUNT_ELEMCONT_XPOS ED_PROPERTIES_XPOS
84 #define ED_COUNT_ELEMCONT_YPOS (17 * MINI_TILEY)
86 /* values for element content drawing areas */
87 #define ED_AREA_ELEMCONT_XPOS (TILEX)
88 #define ED_AREA_ELEMCONT_YPOS (10 * TILEY)
90 /* values for scrolling gadgets */
91 #define ED_SCROLLBUTTON_XPOS 24
92 #define ED_SCROLLBUTTON_YPOS 0
93 #define ED_SCROLLBAR_XPOS 24
94 #define ED_SCROLLBAR_YPOS 64
96 #define ED_SCROLLBUTTON_XSIZE 16
97 #define ED_SCROLLBUTTON_YSIZE 16
99 #define ED_SCROLL_UP_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE)
100 #define ED_SCROLL_UP_YPOS (0)
101 #define ED_SCROLL_DOWN_XPOS ED_SCROLL_UP_XPOS
102 #define ED_SCROLL_DOWN_YPOS (SYSIZE - 3 * ED_SCROLLBUTTON_YSIZE)
103 #define ED_SCROLL_LEFT_XPOS (0)
104 #define ED_SCROLL_LEFT_YPOS (SYSIZE - 2 * ED_SCROLLBUTTON_YSIZE)
105 #define ED_SCROLL_RIGHT_XPOS (SXSIZE - 2 * ED_SCROLLBUTTON_XSIZE)
106 #define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS
107 #define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS
108 #define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + ED_SCROLLBUTTON_YSIZE)
109 #define ED_SCROLL_VERTICAL_XSIZE ED_SCROLLBUTTON_XSIZE
110 #define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE)
111 #define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + ED_SCROLLBUTTON_XSIZE)
112 #define ED_SCROLL_HORIZONTAL_YPOS ED_SCROLL_LEFT_YPOS
113 #define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - 3 * ED_SCROLLBUTTON_XSIZE)
114 #define ED_SCROLL_HORIZONTAL_YSIZE ED_SCROLLBUTTON_YSIZE
116 /* control button identifiers */
117 #define ED_CTRL_ID_SINGLE_ITEMS 0
118 #define ED_CTRL_ID_CONNECTED_ITEMS 1
119 #define ED_CTRL_ID_LINE 2
120 #define ED_CTRL_ID_TEXT 3
121 #define ED_CTRL_ID_RECTANGLE 4
122 #define ED_CTRL_ID_FILLED_BOX 5
123 #define ED_CTRL_ID_WRAP_UP 6
124 #define ED_CTRL_ID_PROPERTIES 7
125 #define ED_CTRL_ID_FLOOD_FILL 8
126 #define ED_CTRL_ID_WRAP_LEFT 9
127 #define ED_CTRL_ID_UNUSED1 10
128 #define ED_CTRL_ID_WRAP_RIGHT 11
129 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
130 #define ED_CTRL_ID_BRUSH 13
131 #define ED_CTRL_ID_WRAP_DOWN 14
132 #define ED_CTRL_ID_PICK_ELEMENT 15
133 #define ED_CTRL_ID_UNDO 16
134 #define ED_CTRL_ID_INFO 17
135 #define ED_CTRL_ID_SAVE 18
136 #define ED_CTRL_ID_CLEAR 19
137 #define ED_CTRL_ID_TEST 20
138 #define ED_CTRL_ID_EXIT 21
140 /* counter button identifiers */
141 #define ED_CTRL_ID_SCORE_DOWN 22
142 #define ED_CTRL_ID_SCORE_UP 23
143 #define ED_CTRL_ID_ELEMCONT_DOWN 24
144 #define ED_CTRL_ID_ELEMCONT_UP 25
146 /* drawing area identifiers */
147 #define ED_CTRL_ID_DRAWING_LEVEL 26
148 #define ED_CTRL_ID_ELEMCONT_0 27
149 #define ED_CTRL_ID_ELEMCONT_7 34
150 #define ED_CTRL_ID_AMOEBA_CONTENT 35
152 /* text input identifiers */
153 #define ED_CTRL_ID_LEVEL_NAME 36
155 /* gadgets for scrolling of drawing area */
156 #define ED_CTRL_ID_SCROLL_UP 37
157 #define ED_CTRL_ID_SCROLL_DOWN 38
158 #define ED_CTRL_ID_SCROLL_LEFT 39
159 #define ED_CTRL_ID_SCROLL_RIGHT 40
160 #define ED_CTRL_ID_SCROLL_VERTICAL 41
161 #define ED_CTRL_ID_SCROLL_HORIZONTAL 42
163 #define ED_NUM_GADGETS 43
165 /* values for counter gadgets */
166 #define ED_COUNTER_SCORE 0
167 #define ED_COUNTER_ELEMCONT 1
169 #define ED_NUM_COUNTERBUTTONS 2
170 #define ED_NUM_SCROLLBUTTONS 4
171 #define ED_NUM_SCROLLBARS 2
173 /* values for CopyLevelToUndoBuffer() */
174 #define UNDO_IMMEDIATE 0
175 #define UNDO_ACCUMULATE 1
177 static char *control_infotext[ED_NUM_CTRL_BUTTONS] =
180 "draw connected items",
182 "enter text elements",
183 "draw outline rectangles",
185 "wrap (rotate) level up",
186 "properties of drawing element",
188 "wrap (rotate) level left",
190 "wrap (rotate) level right",
191 "random element placement",
193 "wrap (rotate) level down",
194 "pick drawing element from editing area",
195 "undo last operation",
207 } counterbutton_info[ED_NUM_COUNTERBUTTONS] =
209 { ED_COUNT_SCORE_XPOS, ED_COUNT_SCORE_YPOS, ED_CTRL_ID_SCORE_DOWN },
210 { ED_COUNT_ELEMCONT_XPOS, ED_COUNT_ELEMCONT_YPOS, ED_CTRL_ID_ELEMCONT_DOWN }
219 } scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
222 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE,
223 ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP,
224 "scroll level editing area up"
227 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE,
228 ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN,
229 "scroll level editing area down"
232 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE,
233 ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT,
234 "scroll level editing area left"
237 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE,
238 ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT,
239 "scroll level editing area right"
251 } scrollbar_info[ED_NUM_SCROLLBARS] =
254 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
255 ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS,
256 ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE,
257 GD_TYPE_SCROLLBAR_VERTICAL,
258 ED_CTRL_ID_SCROLL_VERTICAL,
259 "scroll level editing area vertically"
262 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
263 ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS,
264 ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE,
265 GD_TYPE_SCROLLBAR_HORIZONTAL,
266 ED_CTRL_ID_SCROLL_HORIZONTAL,
267 "scroll level editing area horizontally"
272 /* forward declaration for internal use */
273 static void DrawDrawingWindow();
274 static void DrawPropertiesWindow();
275 static void CopyLevelToUndoBuffer(int);
276 static void HandleControlButtons(struct GadgetInfo *);
277 static void HandleCounterButtons(struct GadgetInfo *);
278 static void HandleDrawingAreas(struct GadgetInfo *);
279 static void HandleDrawingAreaInfo(struct GadgetInfo *);
280 static void HandleTextInputGadgets(struct GadgetInfo *);
282 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
283 static boolean level_editor_gadgets_created = FALSE;
285 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
286 static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
287 static int properties_element = 0;
289 static short ElementContent[MAX_ELEMCONT][3][3];
290 static short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
291 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
292 static int undo_buffer_position = 0;
293 static int undo_buffer_steps = 0;
295 static int random_placement_percentage = 10;
296 static int random_placement_num_objects = 10;
298 static int random_placement_method = RANDOM_USE_PERCENTAGE;
300 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
303 /* pointer to score value */
304 static int *gadget_score_value;
305 static int *gadget_areas_value;
307 static int level_xpos,level_ypos;
308 static int edit_mode;
309 static boolean name_typing;
310 static int new_element1 = EL_MAUERWERK;
311 static int new_element2 = EL_LEERRAUM;
312 static int new_element3 = EL_ERDREICH;
314 int element_shift = 0;
316 int editor_element[] =
318 EL_CHAR_A + ('B' - 'A'),
319 EL_CHAR_A + ('O' - 'A'),
320 EL_CHAR_A + ('U' - 'A'),
321 EL_CHAR_A + ('L' - 'A'),
324 EL_CHAR_A + ('D' - 'A'),
325 EL_CHAR_A + ('E' - 'A'),
326 EL_CHAR_A + ('R' - 'A'),
328 EL_CHAR_A + ('D' - 'A'),
329 EL_CHAR_A + ('A' - 'A'),
330 EL_CHAR_A + ('S' - 'A'),
331 EL_CHAR_A + ('H' - 'A'),
358 EL_CHAR_A + ('E' - 'A'),
359 EL_CHAR_A + ('M' - 'A'),
360 EL_CHAR_A + ('E' - 'A'),
363 EL_CHAR_A + ('R' - 'A'),
364 EL_CHAR_A + ('A' - 'A'),
365 EL_CHAR_A + ('L' - 'A'),
366 EL_CHAR_A + ('D' - 'A'),
368 EL_CHAR_A + ('M' - 'A'),
369 EL_CHAR_A + ('I' - 'A'),
370 EL_CHAR_A + ('N' - 'A'),
371 EL_CHAR_A + ('E' - 'A'),
448 EL_CHAR_A + ('M' - 'A'),
449 EL_CHAR_A + ('O' - 'A'),
450 EL_CHAR_A + ('R' - 'A'),
451 EL_CHAR_A + ('E' - 'A'),
503 EL_CHAR_A + ('S' - 'A'),
504 EL_CHAR_A + ('O' - 'A'),
505 EL_CHAR_A + ('K' - 'A'),
506 EL_CHAR_A + ('O' - 'A'),
509 EL_CHAR_A + ('B' - 'A'),
510 EL_CHAR_A + ('A' - 'A'),
511 EL_CHAR_A + ('N' - 'A'),
514 EL_SOKOBAN_FELD_LEER,
515 EL_SOKOBAN_FELD_VOLL,
584 EL_CHAR_A + ('D' - 'A'),
585 EL_CHAR_A + ('Y' - 'A'),
586 EL_CHAR_A + ('N' - 'A'),
587 EL_CHAR_A + ('A' - 'A'),
589 EL_CHAR_A + ('B' - 'A'),
590 EL_CHAR_A + ('L' - 'A'),
591 EL_CHAR_A + ('A' - 'A'),
592 EL_CHAR_A + ('S' - 'A'),
595 EL_CHAR_A + ('T' - 'A'),
596 EL_CHAR_A + ('E' - 'A'),
597 EL_CHAR_A + ('R' - 'A'),
680 int elements_in_list = sizeof(editor_element)/sizeof(int);
682 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
685 int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
686 int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0);
688 XCopyArea(display, drawto, drawto, gc,
689 SX + (dx == -1 ? MINI_TILEX : 0),
690 SY + (dy == -1 ? MINI_TILEY : 0),
691 (ED_FIELDX * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
692 (ED_FIELDY * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
693 SX + (dx == +1 ? MINI_TILEX : 0),
694 SY + (dy == +1 ? MINI_TILEY : 0));
697 x = (dx == 1 ? 0 : ED_FIELDX - 1);
698 for(y=0; y<ED_FIELDY; y++)
699 DrawMiniElementOrWall(x, y, from_x, from_y);
703 y = (dy == 1 ? 0 : ED_FIELDY - 1);
704 for(x=0; x<ED_FIELDX; x++)
705 DrawMiniElementOrWall(x, y, from_x, from_y);
708 redraw_mask |= REDRAW_FIELD;
712 void InitLevelEditorGadgets()
716 for (i=0; i<ED_NUM_GADGETS; i++)
717 level_editor_gadget[i] = NULL;
720 static void CreateControlButtons()
722 Pixmap gd_pixmap = pix[PIX_DOOR];
723 struct GadgetInfo *gi;
724 unsigned long event_mask;
727 /* create toolbox buttons */
728 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
732 int gd_xoffset, gd_yoffset;
733 int gd_x1, gd_x2, gd_y1, gd_y2;
736 boolean radio_button_pressed;
738 if (id == ED_CTRL_ID_SINGLE_ITEMS ||
739 id == ED_CTRL_ID_CONNECTED_ITEMS ||
740 id == ED_CTRL_ID_LINE ||
741 id == ED_CTRL_ID_TEXT ||
742 id == ED_CTRL_ID_RECTANGLE ||
743 id == ED_CTRL_ID_FILLED_BOX ||
744 id == ED_CTRL_ID_FLOOD_FILL ||
745 id == ED_CTRL_ID_BRUSH ||
746 id == ED_CTRL_ID_PICK_ELEMENT)
748 button_type = GD_TYPE_RADIO_BUTTON;
750 radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
751 event_mask = GD_EVENT_PRESSED;
755 button_type = GD_TYPE_NORMAL_BUTTON;
757 radio_button_pressed = FALSE;
759 if (id == ED_CTRL_ID_WRAP_LEFT ||
760 id == ED_CTRL_ID_WRAP_RIGHT ||
761 id == ED_CTRL_ID_WRAP_UP ||
762 id == ED_CTRL_ID_WRAP_DOWN)
763 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
765 event_mask = GD_EVENT_RELEASED;
768 if (id < ED_NUM_CTRL1_BUTTONS)
770 int x = i % ED_CTRL1_BUTTONS_HORIZ;
771 int y = i / ED_CTRL1_BUTTONS_HORIZ;
773 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
774 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
775 width = ED_CTRL1_BUTTON_XSIZE;
776 height = ED_CTRL1_BUTTON_YSIZE;
780 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
781 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
783 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
784 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
785 width = ED_CTRL2_BUTTON_XSIZE;
786 height = ED_CTRL2_BUTTON_YSIZE;
789 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
790 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
791 gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
792 gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
794 gi = CreateGadget(GDI_CUSTOM_ID, id,
795 GDI_DESCRIPTION_TEXT, control_infotext[i],
796 GDI_X, EX + gd_xoffset,
797 GDI_Y, EY + gd_yoffset,
800 GDI_TYPE, button_type,
801 GDI_STATE, GD_BUTTON_UNPRESSED,
802 GDI_RADIO_NR, radio_button_nr,
803 GDI_RADIO_PRESSED, radio_button_pressed,
804 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
805 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
806 GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
807 GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
808 GDI_EVENT_MASK, event_mask,
809 GDI_CALLBACK_ACTION, HandleControlButtons,
813 Error(ERR_EXIT, "cannot create gadget");
815 level_editor_gadget[id] = gi;
818 /* create buttons for scrolling of drawing area */
819 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
821 int id = scrollbutton_info[i].gadget_id;
822 int gd_x1, gd_x2, gd_y;
824 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
826 gd_y = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos;
827 gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos;
828 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
830 gi = CreateGadget(GDI_CUSTOM_ID, id,
831 GDI_DESCRIPTION_TEXT, scrollbutton_info[i].text,
832 GDI_X, SX + scrollbutton_info[i].x,
833 GDI_Y, SY + scrollbutton_info[i].y,
834 GDI_WIDTH, ED_SCROLLBUTTON_XSIZE,
835 GDI_HEIGHT, ED_SCROLLBUTTON_YSIZE,
836 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
837 GDI_STATE, GD_BUTTON_UNPRESSED,
838 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
839 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
840 GDI_EVENT_MASK, event_mask,
841 GDI_CALLBACK_ACTION, HandleControlButtons,
845 Error(ERR_EXIT, "cannot create gadget");
847 level_editor_gadget[id] = gi;
851 static void CreateCounterButtons()
855 for (i=0; i<ED_NUM_COUNTERBUTTONS; i++)
859 Pixmap gd_pixmap = pix[PIX_DOOR];
860 struct GadgetInfo *gi;
861 int id = counterbutton_info[i].gadget_id + j;
863 int gd_x1, gd_x2, gd_y;
864 unsigned long event_mask;
866 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
868 gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
869 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
870 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
871 gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
873 gi = CreateGadget(GDI_CUSTOM_ID, id,
874 GDI_X, SX + counterbutton_info[i].x + gd_xoffset,
875 GDI_Y, SY + counterbutton_info[i].y,
876 GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
877 GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
878 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
879 GDI_STATE, GD_BUTTON_UNPRESSED,
880 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
881 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
882 GDI_EVENT_MASK, event_mask,
883 GDI_CALLBACK_ACTION, HandleCounterButtons,
887 Error(ERR_EXIT, "cannot create gadget");
889 level_editor_gadget[id] = gi;
894 static void CreateDrawingAreas()
896 struct GadgetInfo *gi;
897 unsigned long event_mask;
902 GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
903 GD_EVENT_OFF_BORDERS;
905 /* one for the level drawing area ... */
906 id = ED_CTRL_ID_DRAWING_LEVEL;
907 gi = CreateGadget(GDI_CUSTOM_ID, id,
910 GDI_TYPE, GD_TYPE_DRAWING_AREA,
911 GDI_AREA_SIZE, ED_FIELDX, ED_FIELDY,
912 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
913 GDI_EVENT_MASK, event_mask,
914 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
915 GDI_CALLBACK_ACTION, HandleDrawingAreas,
919 Error(ERR_EXIT, "cannot create gadget");
921 level_editor_gadget[id] = gi;
923 /* ... up to eight areas for element content ... */
924 for (i=0; i<MAX_ELEMCONT; i++)
926 int gx = SX + ED_AREA_ELEMCONT_XPOS + 5 * (i % 4) * MINI_TILEX;
927 int gy = SX + ED_AREA_ELEMCONT_YPOS + 6 * (i / 4) * MINI_TILEY;
929 id = ED_CTRL_ID_ELEMCONT_0 + i;
930 gi = CreateGadget(GDI_CUSTOM_ID, id,
933 GDI_WIDTH, 3 * MINI_TILEX,
934 GDI_HEIGHT, 3 * MINI_TILEY,
935 GDI_TYPE, GD_TYPE_DRAWING_AREA,
936 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
937 GDI_EVENT_MASK, event_mask,
938 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
939 GDI_CALLBACK_ACTION, HandleDrawingAreas,
943 Error(ERR_EXIT, "cannot create gadget");
945 level_editor_gadget[id] = gi;
948 /* ... and one for the amoeba content */
949 id = ED_CTRL_ID_AMOEBA_CONTENT;
950 gi = CreateGadget(GDI_CUSTOM_ID, id,
951 GDI_X, SX + ED_AREA_ELEMCONT_XPOS,
952 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS,
953 GDI_WIDTH, MINI_TILEX,
954 GDI_HEIGHT, MINI_TILEY,
955 GDI_TYPE, GD_TYPE_DRAWING_AREA,
956 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
957 GDI_EVENT_MASK, event_mask,
958 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
959 GDI_CALLBACK_ACTION, HandleDrawingAreas,
963 Error(ERR_EXIT, "cannot create gadget");
965 level_editor_gadget[id] = gi;
968 static void CreateTextInputGadgets()
970 Pixmap gd_pixmap = pix[PIX_DOOR];
972 struct GadgetInfo *gi;
973 unsigned long event_mask;
976 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
977 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
978 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
980 /* text input gadget for the level name */
981 id = ED_CTRL_ID_LEVEL_NAME;
982 gi = CreateGadget(GDI_CUSTOM_ID, id,
983 GDI_X, SX + ED_COUNT_ELEMCONT_XPOS,
984 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS + 3 * TILEX,
985 GDI_TYPE, GD_TYPE_TEXTINPUT,
986 GDI_TEXT_VALUE, level.name,
988 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
989 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
990 GDI_DESIGN_BORDER, 3,
991 GDI_EVENT_MASK, event_mask,
992 GDI_CALLBACK_ACTION, HandleTextInputGadgets,
996 Error(ERR_EXIT, "cannot create gadget");
998 level_editor_gadget[id] = gi;
1001 static void CreateScrollbarGadgets()
1005 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1007 int id = scrollbar_info[i].gadget_id;
1008 Pixmap gd_pixmap = pix[PIX_DOOR];
1009 int gd_x1, gd_x2, gd_y1, gd_y2;
1010 struct GadgetInfo *gi;
1011 int items_max, items_visible, item_position;
1012 unsigned long event_mask;
1014 if (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL)
1016 items_max = lev_fieldx + 2;
1017 items_visible = ED_FIELDX;
1022 items_max = lev_fieldy + 2;
1023 items_visible = ED_FIELDY;
1027 event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
1029 gd_x1 = DOOR_GFX_PAGEX8 + scrollbar_info[i].xpos;
1030 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
1031 gd_y1 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1032 gd_y2 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1034 gi = CreateGadget(GDI_CUSTOM_ID, id,
1035 GDI_DESCRIPTION_TEXT, scrollbar_info[i].text,
1036 GDI_X, SX + scrollbar_info[i].x,
1037 GDI_Y, SY + scrollbar_info[i].y,
1038 GDI_WIDTH, scrollbar_info[i].width,
1039 GDI_HEIGHT, scrollbar_info[i].height,
1040 GDI_TYPE, scrollbar_info[i].type,
1041 GDI_SCROLLBAR_ITEMS_MAX, items_max,
1042 GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
1043 GDI_SCROLLBAR_ITEM_POSITION, item_position,
1044 GDI_STATE, GD_BUTTON_UNPRESSED,
1045 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
1046 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
1047 GDI_DESIGN_BORDER, 3,
1048 GDI_EVENT_MASK, event_mask,
1049 GDI_CALLBACK_ACTION, HandleControlButtons,
1053 Error(ERR_EXIT, "cannot create gadget");
1055 level_editor_gadget[id] = gi;
1059 static void CreateLevelEditorGadgets()
1061 if (level_editor_gadgets_created)
1064 CreateControlButtons();
1065 CreateCounterButtons();
1066 CreateDrawingAreas();
1067 CreateTextInputGadgets();
1068 CreateScrollbarGadgets();
1070 level_editor_gadgets_created = TRUE;
1073 static void MapControlButtons()
1077 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1078 MapGadget(level_editor_gadget[i]);
1081 static void MapCounterButtons(int id)
1086 MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id + i]);
1089 static void MapDrawingArea(int id)
1091 MapGadget(level_editor_gadget[id]);
1094 static void MapTextInputGadget(int id)
1096 MapGadget(level_editor_gadget[id]);
1099 static void MapMainDrawingArea()
1103 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
1104 MapGadget(level_editor_gadget[scrollbutton_info[i].gadget_id]);
1106 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1107 MapGadget(level_editor_gadget[scrollbar_info[i].gadget_id]);
1109 MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL);
1112 static void UnmapDrawingArea(int id)
1114 UnmapGadget(level_editor_gadget[id]);
1117 void UnmapLevelEditorWindowGadgets()
1121 for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
1122 UnmapGadget(level_editor_gadget[i]);
1125 void UnmapLevelEditorGadgets()
1129 for (i=0; i<ED_NUM_GADGETS; i++)
1130 UnmapGadget(level_editor_gadget[i]);
1135 int i, x, y, graphic;
1139 edit_mode = ED_MODE_DRAWING;
1140 name_typing = FALSE;
1142 CloseDoor(DOOR_CLOSE_ALL);
1144 OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
1146 if (level_editor_test_game)
1148 for(x=0; x<lev_fieldx; x++)
1149 for(y=0; y<lev_fieldy; y++)
1150 Feld[x][y] = Ur[x][y];
1152 for(x=0; x<lev_fieldx; x++)
1153 for(y=0; y<lev_fieldy; y++)
1154 Ur[x][y] = FieldBackup[x][y];
1156 level_editor_test_game = FALSE;
1160 undo_buffer_position = -1;
1161 undo_buffer_steps = -1;
1162 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
1166 DrawMiniLevel(level_xpos, level_ypos);
1170 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1171 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
1173 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1174 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1175 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
1176 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
1177 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
1178 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
1179 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
1181 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1183 if (i < elements_in_list)
1184 graphic = el2gfx(editor_element[i + element_shift]);
1186 graphic = GFX_LEERRAUM;
1188 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1189 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
1190 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
1191 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
1192 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
1196 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1197 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
1198 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
1199 el2gfx(new_element1));
1200 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1201 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
1202 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
1203 el2gfx(new_element2));
1204 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1205 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
1206 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
1207 el2gfx(new_element3));
1208 DrawTextExt(pix[PIX_DB_DOOR],gc,
1209 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
1210 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1211 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
1212 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1213 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
1214 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1216 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
1217 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1218 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1219 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
1220 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1222 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
1223 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1225 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1226 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1228 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1230 /* draw bigger door */
1231 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1236 /* draw new control window */
1237 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1238 DOOR_GFX_PAGEX8, 236,
1242 redraw_mask |= REDRAW_ALL;
1244 OpenDoor(DOOR_OPEN_1);
1246 if (!level_editor_gadgets_created)
1247 CreateLevelEditorGadgets();
1249 MapControlButtons();
1252 MapMainDrawingArea();
1255 DrawDrawingWindow();
1259 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
1263 void DrawControlWindow()
1268 UnmapLevelEditorWindowGadgets();
1270 /* Inhalt der Mampfer */
1271 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
1272 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
1273 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
1275 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
1276 XFillRectangle(display,drawto,gc,
1277 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
1278 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
1279 3*MINI_TILEX+2,3*MINI_TILEY+2);
1281 XCopyArea(display,drawto,drawto,gc,
1282 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
1283 4*5*MINI_TILEX,5*MINI_TILEY,
1284 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
1287 for(y=0;y<3;y++) for(x=0;x<3;x++)
1288 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
1290 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
1291 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
1292 int2str(i+1,1),FS_SMALL,FC_YELLOW);
1295 /* Inhalt der Amöbe */
1296 for(y=0;y<2;y++) for(x=0;x<2;x++)
1298 DrawMiniElement(29+x,26+y,EL_ERDREICH);
1299 XFillRectangle(display,drawto,gc,
1300 SX+29*MINI_TILEX+MINI_TILEX/2-1,
1301 SY+26*MINI_TILEY+MINI_TILEY/2-1,
1302 MINI_TILEX+2,MINI_TILEY+2);
1304 XCopyArea(display,drawto,drawto,gc,
1305 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
1306 3*MINI_TILEX,3*MINI_TILEY,
1307 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
1308 DrawMiniElement(29,26,level.amoebe_inhalt);
1310 for(i=0;i<11+3+2;i++)
1312 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1313 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1314 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1315 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1316 ED_COUNT_GADGET_XPOS,
1317 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
1320 DrawText(ED_COUNT_VALUE_XPOS,
1321 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
1322 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
1324 DrawText(ED_COUNT_VALUE_XPOS,
1325 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1326 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1328 DrawText(ED_COUNT_VALUE_XPOS,
1329 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1330 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1332 DrawText(ED_COUNT_VALUE_XPOS,
1333 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1334 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1336 DrawText(ED_COUNT_VALUE_XPOS,
1337 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1338 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1340 DrawText(ED_COUNT_VALUE_XPOS,
1341 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1342 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1345 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
1346 "Score for Emerald",FS_SMALL,FC_YELLOW);
1347 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
1348 "Score for Diamond",FS_SMALL,FC_YELLOW);
1349 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
1350 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
1351 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
1352 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
1353 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
1354 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
1355 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
1356 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
1357 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
1358 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
1359 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
1360 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
1361 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
1362 "Score for dynamite",FS_SMALL,FC_YELLOW);
1363 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
1364 "Score for key",FS_SMALL,FC_YELLOW);
1365 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
1366 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
1367 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
1368 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
1369 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
1370 "Time for magic wall",FS_SMALL,FC_YELLOW);
1371 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
1372 "Time for wheel",FS_SMALL,FC_YELLOW);
1373 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
1374 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
1375 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
1376 "Time available for this level",FS_SMALL,FC_YELLOW);
1378 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1379 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
1380 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1381 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
1382 ED_COUNT_GADGET_XPOS,
1383 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1385 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1386 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
1387 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1388 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
1389 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
1390 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1391 DrawText(ED_COUNT_GADGET_XPOS+5,
1392 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1393 level.name,FS_SMALL,FC_YELLOW);
1394 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
1395 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1396 "Title",FS_SMALL,FC_YELLOW);
1398 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
1399 "Playfield size:",FS_SMALL,FC_YELLOW);
1400 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1401 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1402 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1403 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1404 ED_SIZE_GADGET_XPOS,
1405 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
1406 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1407 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1408 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1409 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1410 ED_SIZE_GADGET_XPOS,
1411 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
1412 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
1413 "Width",FS_SMALL,FC_YELLOW);
1414 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
1415 "Height",FS_SMALL,FC_YELLOW);
1416 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1417 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1418 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1419 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1422 void AdjustLevelScrollPosition()
1424 if (level_xpos < -1)
1426 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
1427 level_xpos = lev_fieldx - ED_FIELDX + 1;
1428 if (lev_fieldx < ED_FIELDX - 2)
1431 if (level_ypos < -1)
1433 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
1434 level_ypos = lev_fieldy - ED_FIELDY + 1;
1435 if (lev_fieldy < ED_FIELDY - 2)
1439 void AdjustEditorScrollbar(int id)
1441 struct GadgetInfo *gi = level_editor_gadget[id];
1442 struct GadgetScrollbar *gs = &gi->scrollbar;
1443 int items_max, items_visible, item_position = gs->item_position;
1445 if (id == ED_CTRL_ID_SCROLL_HORIZONTAL)
1447 items_max = lev_fieldx + 2;
1448 items_visible = ED_FIELDX;
1452 items_max = lev_fieldy + 2;
1453 items_visible = ED_FIELDY;
1456 if (item_position > items_max - items_visible)
1457 item_position = items_max - items_visible;
1459 AdjustScrollbar(gi, items_max, item_position);
1462 static void PickDrawingElement(int button, int element)
1464 if (button < 1 || button > 3)
1469 new_element1 = element;
1470 DrawMiniGraphicExt(drawto, gc,
1471 DX + ED_WIN_MB_LEFT_XPOS,
1472 DY + ED_WIN_MB_LEFT_YPOS,
1473 el2gfx(new_element1));
1475 else if (button == 2)
1477 new_element2 = element;
1478 DrawMiniGraphicExt(drawto, gc,
1479 DX + ED_WIN_MB_MIDDLE_XPOS,
1480 DY + ED_WIN_MB_MIDDLE_YPOS,
1481 el2gfx(new_element2));
1485 new_element3 = element;
1486 DrawMiniGraphicExt(drawto, gc,
1487 DX + ED_WIN_MB_RIGHT_XPOS,
1488 DY + ED_WIN_MB_RIGHT_YPOS,
1489 el2gfx(new_element3));
1492 redraw_mask |= REDRAW_DOOR_1;
1495 void LevelEd(int mx, int my, int button)
1497 static int last_button = 0;
1498 static int in_field_pressed = FALSE;
1499 static boolean use_floodfill = FALSE;
1503 int x = (mx-SX)/MINI_TILEX;
1504 int y = (my-SY)/MINI_TILEY;
1508 HandlePressedControlButtons();
1509 HandleDrawingFunctions(mx, my, button);
1512 if (use_floodfill) /********** FLOOD FILL **********/
1520 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1525 if (x>lev_fieldx || y>lev_fieldy ||
1526 (x==0 && level_xpos<0) ||
1527 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1528 (y==0 && level_ypos<0) ||
1529 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY))
1532 from_x = x+level_xpos;
1533 from_y = y+level_ypos;
1534 fill_element = (button==1 ? new_element1 :
1535 button==2 ? new_element2 :
1536 button==3 ? new_element3 : 0);
1538 FloodFill(from_x,from_y,fill_element);
1539 DrawMiniLevel(level_xpos,level_ypos);
1542 use_floodfill = FALSE;
1543 CloseDoor(DOOR_CLOSE_1);
1544 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1553 else /********** EDIT/CTRL-FENSTER **********/
1555 static unsigned long choice_delay = 0;
1556 int choice = CheckElemButtons(mx,my,button);
1557 int elem_pos = choice-ED_BUTTON_ELEM;
1559 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1560 (choice == ED_BUTTON_EDOWN &&
1561 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1562 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1564 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1568 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1570 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1572 step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1573 element_shift += step;
1576 if (element_shift<0)
1578 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1579 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1580 if (element_shift % MAX_ELEM_X)
1581 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1583 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1584 DrawElemButton(i+2,ED_BUTTON_RELEASED);
1586 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1590 if (elem_pos+element_shift < elements_in_list)
1591 new_element = editor_element[elem_pos+element_shift];
1593 new_element = EL_LEERRAUM;
1595 PickDrawingElement(last_button, new_element);
1597 if (!HAS_CONTENT(properties_element))
1599 properties_element = new_element;
1600 if (edit_mode == ED_MODE_PROPERTIES)
1601 DrawPropertiesWindow();
1605 if (edit_mode == ED_MODE_DRAWING) /********** EDIT-FENSTER **********/
1612 switch(CheckEditButtons(mx,my,button))
1614 case ED_BUTTON_CTRL:
1615 CloseDoor(DOOR_CLOSE_2);
1616 DrawControlWindow();
1617 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1618 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1620 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1621 OpenDoor(DOOR_OPEN_2);
1622 edit_mode = ED_MODE_INFO;
1624 case ED_BUTTON_FILL:
1625 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1626 use_floodfill = TRUE;
1629 case ED_BUTTON_LEFT:
1632 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1634 if (lev_fieldx<ED_FIELDX-2)
1637 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1641 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1643 DrawMiniLevel(level_xpos,level_ypos);
1646 case ED_BUTTON_RIGHT:
1647 if (level_xpos<=lev_fieldx-ED_FIELDX)
1649 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1651 if (lev_fieldx<ED_FIELDX-2)
1654 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1655 if (level_xpos>lev_fieldx-ED_FIELDX+1)
1656 level_xpos = lev_fieldx-ED_FIELDX+1;
1658 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1660 DrawMiniLevel(level_xpos,level_ypos);
1666 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1668 if (lev_fieldy<ED_FIELDY-2)
1671 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1675 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1677 DrawMiniLevel(level_xpos,level_ypos);
1680 case ED_BUTTON_DOWN:
1681 if (level_ypos<=lev_fieldy-ED_FIELDY)
1683 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1685 if (lev_fieldy<ED_FIELDY-2)
1688 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1689 if (level_ypos>lev_fieldy-ED_FIELDY+1)
1690 level_ypos = lev_fieldy-ED_FIELDY+1;
1692 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1694 DrawMiniLevel(level_xpos,level_ypos);
1707 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1711 if (button && !motion_status)
1712 in_field_pressed = TRUE;
1714 if (!button || !in_field_pressed || button<1 || button>3 ||
1715 (y==0 && level_ypos<0) ||
1716 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY) ||
1717 (x==0 && level_xpos<0) ||
1718 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1719 x>lev_fieldx || y>lev_fieldy)
1722 new_element = (button==1 ? new_element1 :
1723 button==2 ? new_element2 :
1724 button==3 ? new_element3 : 0);
1726 if (new_element != Feld[x+level_xpos][y+level_ypos])
1728 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1732 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1734 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1736 Feld[x][y] = EL_LEERRAUM;
1737 if (x-level_xpos>=0 && x-level_xpos<ED_FIELDX &&
1738 y-level_ypos>=0 && y-level_ypos<ED_FIELDY)
1739 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1744 Feld[x+level_xpos][y+level_ypos] = new_element;
1745 DrawMiniElement(x,y,new_element);
1748 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1749 in_field_pressed = FALSE;
1756 else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
1758 int choice = CheckCountButtons(mx,my,button);
1759 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1761 if (choice >= 0 && choice < 36 &&
1762 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1771 level.score[choice] += step;
1772 if (level.score[choice]<0)
1773 level.score[choice] = 0;
1774 else if (level.score[choice]>255)
1775 level.score[choice] = 255;
1777 else if (choice==11)
1779 level.tempo_amoebe += step;
1780 if (level.tempo_amoebe<0)
1781 level.tempo_amoebe = 0;
1782 else if (level.tempo_amoebe>255)
1783 level.tempo_amoebe = 255;
1785 else if (choice==12)
1787 level.dauer_sieb += step;
1788 if (level.dauer_sieb<0)
1789 level.dauer_sieb = 0;
1790 else if (level.dauer_sieb>255)
1791 level.dauer_sieb = 255;
1793 else if (choice==13)
1795 level.dauer_ablenk += step;
1796 if (level.dauer_ablenk<0)
1797 level.dauer_ablenk = 0;
1798 else if (level.dauer_ablenk>255)
1799 level.dauer_ablenk = 255;
1801 else if (choice==14)
1803 level.edelsteine += step;
1804 if (level.edelsteine<0)
1805 level.edelsteine = 0;
1806 else if (level.edelsteine>999)
1807 level.edelsteine = 999;
1809 else if (choice==15)
1814 else if (level.time>999)
1817 else if (choice==16)
1820 if (lev_fieldx<MIN_LEV_FIELDX)
1821 lev_fieldx = MIN_LEV_FIELDX;
1822 else if (lev_fieldx>MAX_LEV_FIELDX)
1823 lev_fieldx = MAX_LEV_FIELDX;
1824 level.fieldx = lev_fieldx;
1826 else if (choice==17)
1829 if (lev_fieldy<MIN_LEV_FIELDY)
1830 lev_fieldy = MIN_LEV_FIELDY;
1831 else if (lev_fieldy>MAX_LEV_FIELDY)
1832 lev_fieldy = MAX_LEV_FIELDY;
1833 level.fieldy = lev_fieldy;
1837 DrawText(ED_COUNT_VALUE_XPOS,
1838 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1839 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1840 else if (choice==11)
1841 DrawText(ED_COUNT_VALUE_XPOS,
1842 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1843 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1844 else if (choice==12)
1845 DrawText(ED_COUNT_VALUE_XPOS,
1846 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1847 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1848 else if (choice==13)
1849 DrawText(ED_COUNT_VALUE_XPOS,
1850 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1851 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1852 else if (choice==14)
1853 DrawText(ED_COUNT_VALUE_XPOS,
1854 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1855 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1856 else if (choice==15)
1857 DrawText(ED_COUNT_VALUE_XPOS,
1858 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1859 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1860 else if (choice==16)
1861 DrawText(ED_SIZE_VALUE_XPOS,
1862 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1863 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1864 else if (choice==17)
1865 DrawText(ED_SIZE_VALUE_XPOS,
1866 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1867 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1869 redraw_mask &= ~REDRAW_FIELD;
1871 XCopyArea(display,drawto,window,gc,
1872 ED_COUNT_VALUE_XPOS,
1873 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1874 3*FONT2_XSIZE,FONT2_YSIZE,
1875 ED_COUNT_VALUE_XPOS,
1876 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1878 XCopyArea(display,drawto,window,gc,
1880 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1881 3*FONT2_XSIZE,FONT2_YSIZE,
1883 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1891 switch(CheckCtrlButtons(mx,my,button))
1893 case ED_BUTTON_EDIT:
1894 CloseDoor(DOOR_CLOSE_2);
1895 AdjustLevelScrollPosition();
1896 DrawMiniLevel(level_xpos,level_ypos);
1897 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1898 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1900 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1901 OpenDoor(DOOR_OPEN_2);
1902 edit_mode = ED_MODE_DRAWING;
1904 case ED_BUTTON_CLEAR:
1905 if (Request("Are you sure to clear this level ?",REQ_ASK))
1907 for(x=0;x<MAX_LEV_FIELDX;x++)
1908 for(y=0;y<MAX_LEV_FIELDY;y++)
1909 Feld[x][y] = EL_ERDREICH;
1910 DrawMiniLevel(level_xpos,level_ypos);
1913 case ED_BUTTON_UNDO:
1914 if (leveldir[leveldir_nr].readonly ||
1915 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1917 CloseDoor(DOOR_CLOSE_ALL);
1918 game_status=MAINMENU;
1923 CloseDoor(DOOR_CLOSE_1);
1924 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1927 case ED_BUTTON_EXIT:
1929 int figur_vorhanden = FALSE;
1931 if (leveldir[leveldir_nr].readonly)
1933 Request("This level is read only !",REQ_CONFIRM);
1937 for(y=0;y<lev_fieldy;y++)
1938 for(x=0;x<lev_fieldx;x++)
1939 if (Feld[x][y] == EL_SPIELFIGUR ||
1940 Feld[x][y] == EL_SPIELER1 ||
1941 Feld[x][y] == EL_SP_MURPHY)
1942 figur_vorhanden = TRUE;
1944 if (!figur_vorhanden)
1945 Request("No Level without Gregor Mc Duffin please !",
1949 if (Request("Save this level and kill the old ?",
1950 REQ_ASK | REQ_STAY_OPEN))
1952 for(x=0;x<lev_fieldx;x++)
1953 for(y=0;y<lev_fieldy;y++)
1954 Ur[x][y]=Feld[x][y];
1955 SaveLevel(level_nr);
1957 CloseDoor(DOOR_CLOSE_ALL);
1958 game_status=MAINMENU;
1971 if (mx>=ED_COUNT_GADGET_XPOS &&
1972 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1973 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1974 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1979 DrawText(ED_COUNT_GADGET_XPOS+5,
1980 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1981 level.name,FS_SMALL,FC_GREEN);
1982 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1983 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1984 "<",FS_SMALL,FC_RED);
1991 name_typing = FALSE;
1992 DrawText(ED_COUNT_GADGET_XPOS+5,
1993 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1994 level.name,FS_SMALL,FC_YELLOW);
1995 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1996 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1997 " ",FS_SMALL,FC_RED);
2001 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
2002 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
2006 if (!button || button<1 || button>3)
2009 new_element = (button==1 ? new_element1 :
2010 button==2 ? new_element2 :
2011 button==3 ? new_element3 : 0);
2013 if (new_element != level.amoebe_inhalt)
2015 level.amoebe_inhalt = new_element;
2016 DrawMiniElement(29,26,new_element);
2020 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
2021 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
2023 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
2024 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
2029 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
2031 if (button && !motion_status)
2032 in_field_pressed = TRUE;
2034 if (!button || !in_field_pressed || button<1 || button>3)
2037 new_element = (button==1 ? new_element1 :
2038 button==2 ? new_element2 :
2039 button==3 ? new_element3 : 0);
2041 if (new_element != level.mampfer_inhalt[i][x][y])
2043 level.mampfer_inhalt[i][x][y] = new_element;
2044 DrawMiniElement(1+5*i+x,2+y,new_element);
2047 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
2048 in_field_pressed = FALSE;
2050 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
2051 in_field_pressed = FALSE;
2055 last_button = button;
2060 void LevelNameTyping(KeySym key)
2062 unsigned char ascii = 0;
2063 int len = strlen(level.name);
2068 if (key>=XK_A && key<=XK_Z)
2069 ascii = 'A'+(char)(key-XK_A);
2070 else if (key>=XK_a && key<=XK_z)
2071 ascii = 'a'+(char)(key-XK_a);
2072 else if (key>=XK_0 && key<=XK_9)
2073 ascii = '0'+(char)(key-XK_0);
2075 else if (key>=XK_space && key<=XK_at)
2076 ascii = ' '+(char)(key-XK_space);
2077 else if (key==XK_Adiaeresis)
2079 else if (key==XK_Odiaeresis)
2081 else if (key==XK_Udiaeresis)
2083 else if (key==XK_adiaeresis)
2085 else if (key==XK_odiaeresis)
2087 else if (key==XK_udiaeresis)
2089 else if (key==XK_underscore)
2093 if (ascii && len<MAX_LEVNAMLEN-2)
2095 level.name[len] = ascii;
2096 level.name[len+1] = 0;
2099 DrawTextExt(drawto,gc,
2100 ED_COUNT_GADGET_XPOS+5,
2101 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2102 level.name,FS_SMALL,FC_GREEN);
2103 DrawTextExt(window,gc,
2104 ED_COUNT_GADGET_XPOS+5,
2105 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2106 level.name,FS_SMALL,FC_GREEN);
2107 DrawTextExt(drawto,gc,
2108 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2109 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2110 "<",FS_SMALL,FC_RED);
2111 DrawTextExt(window,gc,
2112 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2113 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2114 "<",FS_SMALL,FC_RED);
2116 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
2118 level.name[len-1] = 0;
2121 DrawTextExt(drawto,gc,
2122 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2123 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2124 "< ",FS_SMALL,FC_GREEN);
2125 DrawTextExt(window,gc,
2126 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2127 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2128 "< ",FS_SMALL,FC_GREEN);
2130 else if (key==XK_Return)
2132 DrawTextExt(drawto,gc,
2133 ED_COUNT_GADGET_XPOS+5,
2134 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2135 level.name,FS_SMALL,FC_YELLOW);
2136 DrawTextExt(window,gc,
2137 ED_COUNT_GADGET_XPOS+5,
2138 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2139 level.name,FS_SMALL,FC_YELLOW);
2140 DrawTextExt(drawto,gc,
2141 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2142 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2143 " ",FS_SMALL,FC_YELLOW);
2144 DrawTextExt(window,gc,
2145 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2146 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2147 " ",FS_SMALL,FC_YELLOW);
2149 name_typing = FALSE;
2153 static void DrawCounterValueField(int counter_id, int value)
2155 int x = SX + counterbutton_info[counter_id].x + ED_WIN_COUNT_XPOS;
2156 int y = SY + counterbutton_info[counter_id].y;
2158 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2159 DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
2160 DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
2161 ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
2164 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2165 int2str(value, 3), FS_SMALL, FC_YELLOW);
2168 static void DrawDrawingWindow()
2171 UnmapLevelEditorWindowGadgets();
2172 AdjustLevelScrollPosition();
2173 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_HORIZONTAL);
2174 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_VERTICAL);
2175 DrawMiniLevel(level_xpos, level_ypos);
2176 MapMainDrawingArea();
2179 static void DrawElementContentAreas()
2181 int *num_areas = &MampferMax;
2182 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2183 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2184 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2185 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2188 for (i=0; i<MAX_ELEMCONT; i++)
2191 ElementContent[i][x][y] = level.mampfer_inhalt[i][x][y];
2193 for (i=0; i<MAX_ELEMCONT; i++)
2194 UnmapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2196 /* display counter to choose number of element content areas */
2197 gadget_areas_value = num_areas;
2198 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
2199 x = counterbutton_info[ED_COUNTER_ELEMCONT].x + DXSIZE;
2200 y = counterbutton_info[ED_COUNTER_ELEMCONT].y;
2201 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2202 FC_YELLOW, "number of content areas");
2203 MapCounterButtons(ED_COUNTER_ELEMCONT);
2205 /* delete content areas in case of reducing number of them */
2206 XFillRectangle(display, backbuffer, gc,
2207 SX, area_sy - MINI_TILEX,
2208 SXSIZE, 12 * MINI_TILEY);
2210 /* draw some decorative border for the objects */
2211 for (i=0; i<*num_areas; i++)
2215 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2218 XFillRectangle(display, drawto, gc,
2219 area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
2220 area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
2221 3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
2224 /* copy border to the right location */
2225 XCopyArea(display, drawto, drawto, gc,
2226 area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 12 * MINI_TILEY,
2227 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2229 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
2230 "Content", FS_SMALL, FC_YELLOW);
2231 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
2232 "when", FS_SMALL, FC_YELLOW);
2233 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
2234 "smashed", FS_SMALL, FC_YELLOW);
2236 for (i=0; i<*num_areas; i++)
2240 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2241 ElementContent[i][x][y]);
2243 DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
2244 area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
2245 FC_YELLOW, "%d", i + 1);
2248 for (i=0; i<*num_areas; i++)
2249 MapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2252 static void DrawAmoebaContentArea()
2254 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2255 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2256 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2257 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2260 ElementContent[0][0][0] = level.amoebe_inhalt;
2262 /* draw decorative border for the object */
2265 DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
2267 XFillRectangle(display, drawto, gc,
2268 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
2269 MINI_TILEX + 2, MINI_TILEY + 2);
2271 /* copy border to the right location */
2272 XCopyArea(display, drawto, drawto, gc,
2273 area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
2274 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2276 DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
2277 FS_SMALL, FC_YELLOW);
2279 DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
2281 MapDrawingArea(ED_CTRL_ID_AMOEBA_CONTENT);
2284 #define TEXT_COLLECTING "Score for collecting"
2285 #define TEXT_SMASHING "Score for smashing"
2286 #define TEXT_CRACKING "Score for cracking"
2287 #define TEXT_SPEED "Speed of amoeba growth"
2288 #define TEXT_DURATION "Duration when activated"
2290 static void DrawPropertiesWindow()
2293 int num_elements_in_level;
2299 } elements_with_counter[] =
2301 { EL_EDELSTEIN, &level.score[0], TEXT_COLLECTING },
2302 { EL_EDELSTEIN_BD, &level.score[0], TEXT_COLLECTING },
2303 { EL_EDELSTEIN_GELB,&level.score[0], TEXT_COLLECTING },
2304 { EL_EDELSTEIN_ROT, &level.score[0], TEXT_COLLECTING },
2305 { EL_EDELSTEIN_LILA,&level.score[0], TEXT_COLLECTING },
2306 { EL_DIAMANT, &level.score[1], TEXT_COLLECTING },
2307 { EL_KAEFER_R, &level.score[2], TEXT_SMASHING },
2308 { EL_KAEFER_O, &level.score[2], TEXT_SMASHING },
2309 { EL_KAEFER_L, &level.score[2], TEXT_SMASHING },
2310 { EL_KAEFER_U, &level.score[2], TEXT_SMASHING },
2311 { EL_BUTTERFLY_R, &level.score[2], TEXT_SMASHING },
2312 { EL_BUTTERFLY_O, &level.score[2], TEXT_SMASHING },
2313 { EL_BUTTERFLY_L, &level.score[2], TEXT_SMASHING },
2314 { EL_BUTTERFLY_U, &level.score[2], TEXT_SMASHING },
2315 { EL_FLIEGER_R, &level.score[3], TEXT_SMASHING },
2316 { EL_FLIEGER_O, &level.score[3], TEXT_SMASHING },
2317 { EL_FLIEGER_L, &level.score[3], TEXT_SMASHING },
2318 { EL_FLIEGER_U, &level.score[3], TEXT_SMASHING },
2319 { EL_FIREFLY_R, &level.score[3], TEXT_SMASHING },
2320 { EL_FIREFLY_O, &level.score[3], TEXT_SMASHING },
2321 { EL_FIREFLY_L, &level.score[3], TEXT_SMASHING },
2322 { EL_FIREFLY_U, &level.score[3], TEXT_SMASHING },
2323 { EL_MAMPFER, &level.score[4], TEXT_SMASHING },
2324 { EL_MAMPFER2, &level.score[4], TEXT_SMASHING },
2325 { EL_ROBOT, &level.score[5], TEXT_SMASHING },
2326 { EL_PACMAN_R, &level.score[6], TEXT_SMASHING },
2327 { EL_PACMAN_O, &level.score[6], TEXT_SMASHING },
2328 { EL_PACMAN_L, &level.score[6], TEXT_SMASHING },
2329 { EL_PACMAN_U, &level.score[6], TEXT_SMASHING },
2330 { EL_KOKOSNUSS, &level.score[7], TEXT_CRACKING },
2331 { EL_DYNAMIT_AUS, &level.score[8], TEXT_COLLECTING },
2332 { EL_SCHLUESSEL1, &level.score[9], TEXT_COLLECTING },
2333 { EL_SCHLUESSEL2, &level.score[9], TEXT_COLLECTING },
2334 { EL_SCHLUESSEL3, &level.score[9], TEXT_COLLECTING },
2335 { EL_SCHLUESSEL4, &level.score[9], TEXT_COLLECTING },
2336 { EL_AMOEBE_NASS, &level.tempo_amoebe, TEXT_SPEED },
2337 { EL_AMOEBE_NORM, &level.tempo_amoebe, TEXT_SPEED },
2338 { EL_AMOEBE_VOLL, &level.tempo_amoebe, TEXT_SPEED },
2339 { EL_AMOEBE_BD, &level.tempo_amoebe, TEXT_SPEED },
2340 { EL_SIEB_INAKTIV, &level.dauer_sieb, TEXT_DURATION },
2341 { EL_ABLENK_AUS, &level.dauer_ablenk, TEXT_DURATION },
2346 UnmapLevelEditorWindowGadgets();
2348 /* draw some decorative border for the object */
2351 DrawMiniElement(2 + x , 2 + y, EL_ERDREICH);
2353 XFillRectangle(display, drawto, gc,
2354 SX + TILEX + MINI_TILEX/2 - 1,
2355 SY + TILEY + MINI_TILEY/2 - 1,
2356 TILEX + 2, TILEY + 2);
2358 /* copy border to the right location */
2359 XCopyArea(display, drawto, drawto, gc,
2360 SX + TILEX, SY + TILEY,
2361 2 * TILEX, 2 * TILEY,
2362 SX + TILEX - MINI_TILEX/2, SY + TILEY - MINI_TILEY/2);
2364 DrawGraphic(1, 1, el2gfx(properties_element));
2365 DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
2366 FS_SMALL, FC_YELLOW);
2368 num_elements_in_level = 0;
2369 for (y=0; y<lev_fieldy; y++)
2370 for (x=0; x<lev_fieldx; x++)
2371 if (Feld[x][y] == properties_element)
2372 num_elements_in_level++;
2374 DrawTextF(ED_PROPERTIES_XPOS, 5*TILEY, FC_YELLOW, "%d x contained in level",
2375 num_elements_in_level);
2377 /* check if there are elements where a score can be chosen for */
2378 for (i=0; elements_with_counter[i].element != -1; i++)
2380 if (elements_with_counter[i].element == properties_element)
2382 int x = counterbutton_info[ED_COUNTER_SCORE].x + DXSIZE;
2383 int y = counterbutton_info[ED_COUNTER_SCORE].y;
2385 gadget_score_value = elements_with_counter[i].counter_value;
2386 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2387 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2388 FC_YELLOW, elements_with_counter[i].text);
2389 MapCounterButtons(ED_COUNTER_SCORE);
2394 if (HAS_CONTENT(properties_element))
2396 if (IS_AMOEBOID(properties_element))
2397 DrawAmoebaContentArea();
2399 DrawElementContentAreas();
2402 /* TEST ONLY: level name text input gadget */
2403 MapTextInputGadget(ED_CTRL_ID_LEVEL_NAME);
2406 static void swap_numbers(int *i1, int *i2)
2414 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
2426 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
2428 int lx = sx + level_xpos;
2429 int ly = sy + level_ypos;
2431 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
2434 Feld[lx][ly] = element;
2437 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
2438 int element, boolean change_level)
2440 if (from_y == to_y) /* horizontal line */
2446 swap_numbers(&from_x, &to_x);
2448 for (x=from_x; x<=to_x; x++)
2449 DrawLineElement(x, y, element, change_level);
2451 else if (from_x == to_x) /* vertical line */
2457 swap_numbers(&from_y, &to_y);
2459 for (y=from_y; y<=to_y; y++)
2460 DrawLineElement(x, y, element, change_level);
2462 else /* diagonal line */
2464 int len_x = ABS(to_x - from_x);
2465 int len_y = ABS(to_y - from_y);
2468 if (len_y < len_x) /* a < 1 */
2470 float a = (float)len_y / (float)len_x;
2473 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2475 for (x=0; x<=len_x; x++)
2477 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
2479 DrawLineElement(from_x + x, from_y + y, element, change_level);
2484 float a = (float)len_x / (float)len_y;
2487 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2489 for (y=0; y<=len_y; y++)
2491 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
2493 DrawLineElement(from_x + x, from_y + y, element, change_level);
2499 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
2500 int element, boolean change_level)
2502 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
2503 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
2504 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
2505 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
2508 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
2509 int element, boolean change_level)
2514 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2516 for (y=from_y; y<=to_y; y++)
2517 DrawLine(from_x, y, to_x, y, element, change_level);
2520 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
2522 int from_sx, from_sy;
2526 swap_numbers(&from_x, &to_x);
2529 swap_numbers(&from_y, &to_y);
2531 from_sx = SX + from_x * MINI_TILEX;
2532 from_sy = SY + from_y * MINI_TILEY;
2533 to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
2534 to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
2536 XSetForeground(display, gc, WhitePixel(display, screen));
2538 XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
2539 XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
2540 XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
2541 XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
2543 XSetForeground(display, gc, BlackPixel(display, screen));
2545 if (from_x == to_x && from_y == to_y)
2546 MarkTileDirty(from_x/2, from_y/2);
2548 redraw_mask |= REDRAW_FIELD;
2551 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
2552 int element, boolean change_level)
2554 if (element == -1 || change_level)
2555 DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
2557 DrawAreaBorder(from_x, from_y, to_x, to_y);
2560 static void SetTextCursor(int unused_sx, int unused_sy, int sx, int sy,
2561 int element, boolean change_level)
2563 int lx = sx + level_xpos;
2564 int ly = sy + level_ypos;
2567 DrawMiniElement(sx, sy, Feld[lx][ly]);
2569 DrawAreaBorder(sx, sy, sx, sy);
2572 /* values for CopyBrushExt() */
2573 #define CB_AREA_TO_BRUSH 0
2574 #define CB_BRUSH_TO_LEVEL 1
2576 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int mode)
2578 static short brush_buffer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
2579 static int brush_from_x, brush_from_y;
2580 static int brush_to_x, brush_to_y;
2584 swap_numbers(&from_x, &to_x);
2587 swap_numbers(&from_y, &to_y);
2589 if (mode == CB_AREA_TO_BRUSH)
2591 for (y=from_y; y<=to_y; y++)
2592 for (x=from_x; x<=to_x; x++)
2593 brush_buffer[x][y] = Feld[x][y];
2595 brush_from_x = from_x;
2596 brush_from_y = from_y;
2602 for (y=brush_from_y; y<=brush_to_y; y++)
2603 for (x=brush_from_x; x<=brush_to_x; x++)
2604 Feld[x][y] = brush_buffer[x][y];
2605 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2609 static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y)
2611 CopyBrushExt(from_x, from_y, to_x, to_y, CB_AREA_TO_BRUSH);
2615 static void CopyBrushToLevel()
2617 CopyBrushExt(0, 0, 0, 0, CB_BRUSH_TO_LEVEL);
2621 static void FloodFill(int from_x, int from_y, int fill_element)
2625 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
2626 static int safety = 0;
2628 /* check if starting field still has the desired content */
2629 if (Feld[from_x][from_y] == fill_element)
2634 if (safety > lev_fieldx*lev_fieldy)
2635 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
2637 old_element = Feld[from_x][from_y];
2638 Feld[from_x][from_y] = fill_element;
2642 x = from_x + check[i][0];
2643 y = from_y + check[i][1];
2645 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
2646 FloodFill(x, y, fill_element);
2652 /* values for DrawLevelText() modes */
2654 #define TEXT_SETCURSOR 1
2655 #define TEXT_WRITECHAR 2
2656 #define TEXT_BACKSPACE 3
2657 #define TEXT_NEWLINE 4
2660 static void DrawLevelText(int sx, int sy, char letter, int mode)
2662 static short delete_buffer[MAX_LEV_FIELDX];
2663 static int start_sx, start_sy;
2664 static int last_sx, last_sy;
2665 static boolean typing = FALSE;
2666 int letter_element = EL_CHAR_ASCII0 + letter;
2669 /* map lower case letters to upper case and convert special characters */
2670 if (letter >= 'a' && letter <= 'z')
2671 letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
2672 else if (letter == 'ä' || letter == 'Ä')
2673 letter_element = EL_CHAR_AE;
2674 else if (letter == 'ö' || letter == 'Ö')
2675 letter_element = EL_CHAR_OE;
2676 else if (letter == 'ü' || letter == 'Ü')
2677 letter_element = EL_CHAR_UE;
2678 else if (letter == '^')
2679 letter_element = EL_CHAR_COPY;
2681 letter_element = EL_CHAR_ASCII0 + letter;
2683 if (mode != TEXT_INIT)
2688 if (mode != TEXT_SETCURSOR)
2694 lx = last_sx + level_xpos;
2695 ly = last_sy + level_ypos;
2702 DrawLevelText(0, 0, 0, TEXT_END);
2705 start_sx = last_sx = sx;
2706 start_sy = last_sy = sy;
2707 DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
2710 case TEXT_SETCURSOR:
2711 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
2712 DrawAreaBorder(sx, sy, sx, sy);
2717 case TEXT_WRITECHAR:
2718 if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
2720 delete_buffer[sx - start_sx] = Feld[lx][ly];
2721 Feld[lx][ly] = letter_element;
2723 if (sx + 1 < ED_FIELDX && lx + 1 < lev_fieldx)
2724 DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
2725 else if (sy + 1 < ED_FIELDY && ly + 1 < lev_fieldy)
2726 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2728 DrawLevelText(0, 0, 0, TEXT_END);
2732 case TEXT_BACKSPACE:
2735 Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
2736 DrawMiniElement(sx - 1, sy, new_element3);
2737 DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
2742 if (sy + 1 < ED_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
2743 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2745 DrawLevelText(0, 0, 0, TEXT_END);
2749 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2750 DrawMiniElement(sx, sy, Feld[lx][ly]);
2759 static void CopyLevelToUndoBuffer(int mode)
2761 static boolean accumulated_undo = FALSE;
2762 boolean new_undo_buffer_position = TRUE;
2767 case UNDO_IMMEDIATE:
2768 accumulated_undo = FALSE;
2771 case UNDO_ACCUMULATE:
2772 if (accumulated_undo)
2773 new_undo_buffer_position = FALSE;
2774 accumulated_undo = TRUE;
2781 if (new_undo_buffer_position)
2783 /* new position in undo buffer ring */
2784 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
2786 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
2787 undo_buffer_steps++;
2790 for(x=0; x<lev_fieldx; x++)
2791 for(y=0; y<lev_fieldy; y++)
2792 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
2795 printf("level saved to undo buffer\n");
2800 static void RandomPlacement(int button)
2805 new_element = (button == 1 ? new_element1 :
2806 button == 2 ? new_element2 :
2807 button == 3 ? new_element3 : 0);
2809 if (random_placement_method == RANDOM_USE_PERCENTAGE)
2811 for(x=0; x<lev_fieldx; x++)
2812 for(y=0; y<lev_fieldy; y++)
2813 if (RND(100) < random_placement_percentage)
2814 Feld[x][y] = new_element;
2818 int elements_left = random_placement_num_objects;
2820 while (elements_left > 0)
2822 x = RND(lev_fieldx);
2823 y = RND(lev_fieldy);
2825 if (Feld[x][y] != new_element)
2827 Feld[x][y] = new_element;
2833 DrawMiniLevel(level_xpos, level_ypos);
2834 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2837 void WrapLevel(int dx, int dy)
2839 int wrap_dx = lev_fieldx - dx;
2840 int wrap_dy = lev_fieldy - dy;
2843 for(x=0; x<lev_fieldx; x++)
2844 for(y=0; y<lev_fieldy; y++)
2845 FieldBackup[x][y] = Feld[x][y];
2847 for(x=0; x<lev_fieldx; x++)
2848 for(y=0; y<lev_fieldy; y++)
2850 FieldBackup[(x + wrap_dx) % lev_fieldx][(y + wrap_dy) % lev_fieldy];
2852 DrawMiniLevel(level_xpos, level_ypos);
2853 CopyLevelToUndoBuffer(UNDO_ACCUMULATE);
2856 static void HandleDrawingAreas(struct GadgetInfo *gi)
2858 static boolean started_inside_drawing_area = FALSE;
2859 static boolean draw_with_brush = FALSE;
2860 int id = gi->custom_id;
2861 boolean inside_drawing_area = !gi->event.off_borders;
2862 boolean button_press_event;
2863 boolean button_release_event;
2864 boolean draw_level = (id == ED_CTRL_ID_DRAWING_LEVEL);
2866 int button = gi->event.button;
2867 int sx = gi->event.x, sy = gi->event.y;
2868 int min_sx = 0, min_sy = 0;
2869 int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1;
2871 int min_lx = 0, min_ly = 0;
2872 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
2876 if (edit_mode != ED_MODE_DRAWING)
2880 button_press_event = (gi->event.type == GD_EVENT_PRESSED);
2881 button_release_event = (gi->event.type == GD_EVENT_RELEASED);
2883 /* make sure to stay inside drawing area boundaries */
2884 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
2885 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
2889 /* get positions inside level field */
2890 lx = sx + level_xpos;
2891 ly = sy + level_ypos;
2893 /* make sure to stay inside level field boundaries */
2894 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
2895 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
2897 /* correct drawing area positions accordingly */
2898 sx = lx - level_xpos;
2899 sy = ly - level_ypos;
2902 if (button_press_event)
2903 started_inside_drawing_area = inside_drawing_area;
2905 if (!started_inside_drawing_area)
2908 if (!button && !button_release_event)
2911 new_element = (button == 1 ? new_element1 :
2912 button == 2 ? new_element2 :
2913 button == 3 ? new_element3 : 0);
2915 if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS)
2918 switch (drawing_function)
2920 case ED_CTRL_ID_SINGLE_ITEMS:
2923 if (button_release_event)
2924 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2929 if (new_element != Feld[lx][ly])
2931 if (new_element == EL_SPIELFIGUR)
2933 /* remove player at old position */
2934 for(y=0; y<lev_fieldy; y++)
2936 for(x=0; x<lev_fieldx; x++)
2938 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
2940 Feld[x][y] = EL_LEERRAUM;
2941 if (x - level_xpos >= 0 && x - level_xpos < ED_FIELDX &&
2942 y - level_ypos >= 0 && y - level_ypos < ED_FIELDY)
2943 DrawMiniElement(x - level_xpos, y - level_ypos,
2950 Feld[lx][ly] = new_element;
2951 DrawMiniElement(sx, sy, new_element);
2956 DrawMiniGraphicExt(drawto, gc,
2957 gi->x + sx * MINI_TILEX,
2958 gi->y + sy * MINI_TILEY,
2959 el2gfx(new_element));
2960 DrawMiniGraphicExt(window, gc,
2961 gi->x + sx * MINI_TILEX,
2962 gi->y + sy * MINI_TILEY,
2963 el2gfx(new_element));
2965 if (id == ED_CTRL_ID_AMOEBA_CONTENT)
2966 level.amoebe_inhalt = new_element;
2967 else if (id >= ED_CTRL_ID_ELEMCONT_0 && id <= ED_CTRL_ID_ELEMCONT_7)
2968 level.mampfer_inhalt[id - ED_CTRL_ID_ELEMCONT_0][sx][sy] =
2973 case ED_CTRL_ID_CONNECTED_ITEMS:
2975 static int last_sx = -1;
2976 static int last_sy = -1;
2978 if (button_release_event)
2979 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2983 if (!button_press_event)
2984 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
2992 case ED_CTRL_ID_LINE:
2993 case ED_CTRL_ID_RECTANGLE:
2994 case ED_CTRL_ID_FILLED_BOX:
2995 case ED_CTRL_ID_BRUSH:
2996 case ED_CTRL_ID_TEXT:
2998 static int last_sx = -1;
2999 static int last_sy = -1;
3000 static int start_sx = -1;
3001 static int start_sy = -1;
3002 void (*draw_func)(int, int, int, int, int, boolean);
3004 if (drawing_function == ED_CTRL_ID_LINE)
3005 draw_func = DrawLine;
3006 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
3007 draw_func = DrawRectangle;
3008 else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
3009 draw_func = DrawFilledBox;
3010 else if (drawing_function == ED_CTRL_ID_BRUSH)
3011 draw_func = SelectArea;
3012 else /* (drawing_function == ED_CTRL_ID_TEXT) */
3013 draw_func = SetTextCursor;
3015 if (button_press_event)
3017 draw_func(sx, sy, sx, sy, new_element, FALSE);
3018 start_sx = last_sx = sx;
3019 start_sy = last_sy = sy;
3021 if (drawing_function == ED_CTRL_ID_TEXT)
3022 DrawLevelText(0, 0, 0, TEXT_END);
3024 else if (button_release_event)
3026 draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
3027 if (drawing_function == ED_CTRL_ID_BRUSH)
3029 CopyAreaToBrush(start_sx, start_sy, sx, sy);
3030 draw_with_brush = TRUE;
3032 else if (drawing_function == ED_CTRL_ID_TEXT)
3033 DrawLevelText(sx, sy, 0, TEXT_INIT);
3035 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3037 else if (last_sx != sx || last_sy != sy)
3039 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
3040 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
3050 case ED_CTRL_ID_TEXT:
3052 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
3053 DrawAreaBorder(sx, sy, sx, sy);
3058 if (button_press_event)
3059 DrawLevelText(sx, sy, 0, TEXT_INIT);
3065 case ED_CTRL_ID_FLOOD_FILL:
3066 if (button_press_event && Feld[lx][ly] != new_element)
3068 FloodFill(lx, ly, new_element);
3069 DrawMiniLevel(level_xpos, level_ypos);
3070 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3074 case ED_CTRL_ID_PICK_ELEMENT:
3075 if (button_press_event)
3076 PickDrawingElement(button, Feld[lx][ly]);
3077 if (button_release_event)
3078 ClickOnGadget(level_editor_gadget[last_drawing_function]);
3086 static void HandleCounterButtons(struct GadgetInfo *gi)
3088 int id = gi->custom_id;
3089 int button = gi->event.button;
3090 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3094 case ED_CTRL_ID_SCORE_DOWN:
3095 case ED_CTRL_ID_SCORE_UP:
3096 *gadget_score_value += (id == ED_CTRL_ID_SCORE_DOWN ? -step : step);
3097 if (*gadget_score_value < 0)
3098 *gadget_score_value = 0;
3099 else if (*gadget_score_value > 255)
3100 *gadget_score_value = 255;
3102 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
3105 case ED_CTRL_ID_ELEMCONT_DOWN:
3106 case ED_CTRL_ID_ELEMCONT_UP:
3107 *gadget_areas_value += (id == ED_CTRL_ID_ELEMCONT_DOWN ? -step : step);
3108 if (*gadget_areas_value < 1)
3109 *gadget_areas_value = 1;
3110 else if (*gadget_areas_value > MAX_ELEMCONT)
3111 *gadget_areas_value = MAX_ELEMCONT;
3113 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
3114 DrawElementContentAreas();
3122 static void HandleControlButtons(struct GadgetInfo *gi)
3124 int id = gi->custom_id;
3125 int button = gi->event.button;
3126 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3128 int player_present = FALSE;
3129 int level_changed = FALSE;
3132 new_element = (button == 1 ? new_element1 :
3133 button == 2 ? new_element2 :
3134 button == 3 ? new_element3 : 0);
3136 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3137 DrawLevelText(0, 0, 0, TEXT_END);
3139 if (id < ED_NUM_CTRL1_BUTTONS && id != ED_CTRL_ID_PROPERTIES &&
3140 edit_mode != ED_MODE_DRAWING)
3142 DrawDrawingWindow();
3143 edit_mode = ED_MODE_DRAWING;
3148 case ED_CTRL_ID_SCROLL_LEFT:
3149 if (level_xpos >= 0)
3151 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3152 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3153 struct GadgetScrollbar *gs = &gi->scrollbar;
3155 if (lev_fieldx < ED_FIELDX - 2)
3159 if (level_xpos < -1)
3162 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
3164 DrawMiniLevel(level_xpos, level_ypos);
3166 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3170 case ED_CTRL_ID_SCROLL_RIGHT:
3171 if (level_xpos <= lev_fieldx - ED_FIELDX)
3173 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3174 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3175 struct GadgetScrollbar *gs = &gi->scrollbar;
3177 if (lev_fieldx < ED_FIELDX - 2)
3181 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
3182 level_xpos = lev_fieldx - ED_FIELDX + 1;
3184 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
3186 DrawMiniLevel(level_xpos, level_ypos);
3188 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3192 case ED_CTRL_ID_SCROLL_UP:
3193 if (level_ypos >= 0)
3195 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3196 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3197 struct GadgetScrollbar *gs = &gi->scrollbar;
3199 if (lev_fieldy < ED_FIELDY - 2)
3203 if (level_ypos < -1)
3206 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
3208 DrawMiniLevel(level_xpos, level_ypos);
3210 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3214 case ED_CTRL_ID_SCROLL_DOWN:
3215 if (level_ypos <= lev_fieldy - ED_FIELDY)
3217 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3218 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3219 struct GadgetScrollbar *gs = &gi->scrollbar;
3221 if (lev_fieldy < ED_FIELDY - 2)
3225 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
3226 level_ypos = lev_fieldy - ED_FIELDY + 1;
3228 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
3230 DrawMiniLevel(level_xpos, level_ypos);
3232 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3236 case ED_CTRL_ID_SCROLL_HORIZONTAL:
3237 level_xpos = gi->event.item_position - 1;
3238 DrawMiniLevel(level_xpos, level_ypos);
3241 case ED_CTRL_ID_SCROLL_VERTICAL:
3242 level_ypos = gi->event.item_position - 1;
3243 DrawMiniLevel(level_xpos, level_ypos);
3246 case ED_CTRL_ID_WRAP_LEFT:
3247 WrapLevel(-step, 0);
3250 case ED_CTRL_ID_WRAP_RIGHT:
3254 case ED_CTRL_ID_WRAP_UP:
3255 WrapLevel(0, -step);
3258 case ED_CTRL_ID_WRAP_DOWN:
3262 case ED_CTRL_ID_SINGLE_ITEMS:
3263 case ED_CTRL_ID_CONNECTED_ITEMS:
3264 case ED_CTRL_ID_LINE:
3265 case ED_CTRL_ID_TEXT:
3266 case ED_CTRL_ID_RECTANGLE:
3267 case ED_CTRL_ID_FILLED_BOX:
3268 case ED_CTRL_ID_FLOOD_FILL:
3269 case ED_CTRL_ID_BRUSH:
3270 case ED_CTRL_ID_PICK_ELEMENT:
3271 last_drawing_function = drawing_function;
3272 drawing_function = id;
3275 case ED_CTRL_ID_RANDOM_PLACEMENT:
3276 RandomPlacement(button);
3279 case ED_CTRL_ID_PROPERTIES:
3280 if (edit_mode != ED_MODE_PROPERTIES)
3282 properties_element = new_element;
3283 DrawPropertiesWindow();
3284 edit_mode = ED_MODE_PROPERTIES;
3288 DrawDrawingWindow();
3289 edit_mode = ED_MODE_DRAWING;
3293 case ED_CTRL_ID_UNDO:
3294 if (undo_buffer_steps == 0)
3296 Request("Undo buffer empty !", REQ_CONFIRM);
3300 undo_buffer_position =
3301 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
3302 undo_buffer_steps--;
3304 for(x=0; x<lev_fieldx; x++)
3305 for(y=0; y<lev_fieldy; y++)
3306 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
3307 DrawMiniLevel(level_xpos,level_ypos);
3310 case ED_CTRL_ID_INFO:
3311 if (edit_mode != ED_MODE_INFO)
3313 DrawControlWindow();
3314 edit_mode = ED_MODE_INFO;
3318 DrawDrawingWindow();
3319 edit_mode = ED_MODE_DRAWING;
3323 case ED_CTRL_ID_CLEAR:
3324 for(x=0; x<MAX_LEV_FIELDX; x++)
3325 for(y=0; y<MAX_LEV_FIELDY; y++)
3326 Feld[x][y] = new_element3;
3327 CopyLevelToUndoBuffer(ED_CTRL_ID_CLEAR);
3329 DrawMiniLevel(level_xpos, level_ypos);
3332 case ED_CTRL_ID_SAVE:
3333 if (leveldir[leveldir_nr].readonly)
3335 Request("This level is read only !", REQ_CONFIRM);
3339 for(y=0; y<lev_fieldy; y++)
3340 for(x=0; x<lev_fieldx; x++)
3341 if (Feld[x][y] != Ur[x][y])
3342 level_changed = TRUE;
3344 if (0 && !level_changed)
3346 Request("Level has not changed !", REQ_CONFIRM);
3350 for(y=0; y<lev_fieldy; y++)
3351 for(x=0; x<lev_fieldx; x++)
3352 if (Feld[x][y] == EL_SPIELFIGUR ||
3353 Feld[x][y] == EL_SPIELER1 ||
3354 Feld[x][y] == EL_SP_MURPHY)
3355 player_present = TRUE;
3357 if (!player_present)
3358 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3361 if (Request("Save this level and kill the old ?", REQ_ASK))
3363 for(x=0; x<lev_fieldx; x++)
3364 for(y=0; y<lev_fieldy; y++)
3365 Ur[x][y] = Feld[x][y];
3366 SaveLevel(level_nr);
3371 case ED_CTRL_ID_TEST:
3372 for(y=0; y<lev_fieldy; y++)
3373 for(x=0; x<lev_fieldx; x++)
3374 if (Feld[x][y] == EL_SPIELFIGUR ||
3375 Feld[x][y] == EL_SPIELER1 ||
3376 Feld[x][y] == EL_SP_MURPHY)
3377 player_present = TRUE;
3379 if (!player_present)
3380 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3383 for(x=0; x<lev_fieldx; x++)
3384 for(y=0; y<lev_fieldy; y++)
3385 FieldBackup[x][y] = Ur[x][y];
3387 for(x=0; x<lev_fieldx; x++)
3388 for(y=0; y<lev_fieldy; y++)
3389 Ur[x][y] = Feld[x][y];
3391 UnmapLevelEditorGadgets();
3393 /* draw smaller door */
3394 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3395 DOOR_GFX_PAGEX7, 64,
3398 redraw_mask |= REDRAW_ALL;
3400 CloseDoor(DOOR_CLOSE_ALL);
3402 DrawCompleteVideoDisplay();
3404 if (setup.autorecord)
3405 TapeStartRecording();
3407 level_editor_test_game = TRUE;
3408 game_status = PLAYING;
3414 case ED_CTRL_ID_EXIT:
3415 for(y=0; y<lev_fieldy; y++)
3416 for(x=0; x<lev_fieldx; x++)
3417 if (Feld[x][y] != Ur[x][y])
3418 level_changed = TRUE;
3420 if (!level_changed ||
3421 Request("Level has changed! Exit without saving ?",
3422 REQ_ASK | REQ_STAY_OPEN))
3424 CloseDoor(DOOR_CLOSE_1);
3427 CloseDoor(DOOR_CLOSE_ALL);
3430 /* draw smaller door */
3431 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3432 DOOR_GFX_PAGEX7, 64,
3435 redraw_mask |= REDRAW_ALL;
3437 game_status = MAINMENU;
3442 CloseDoor(DOOR_CLOSE_1);
3443 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
3444 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3445 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3446 OpenDoor(DOOR_OPEN_1);
3452 if (gi->event.type == GD_EVENT_PRESSED)
3453 printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
3454 else if (gi->event.type == GD_EVENT_RELEASED)
3455 printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
3456 else if (gi->event.type == GD_EVENT_MOVING)
3457 printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
3459 printf("default: HandleControlButtons: ?\n");
3465 void HandleLevelEditorKeyInput(KeySym key)
3467 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3469 char letter = getCharFromKeySym(key);
3472 DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
3473 else if (key == XK_Delete || key == XK_BackSpace)
3474 DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
3475 else if (key == XK_Return)
3476 DrawLevelText(0, 0, 0, TEXT_NEWLINE);
3480 static void HandleTextInputGadgets(struct GadgetInfo *gi)
3482 int id = gi->custom_id;
3486 case ED_CTRL_ID_LEVEL_NAME:
3487 strcpy(level.name, gi->text_value);
3495 /* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
3496 #define INFOTEXT_XPOS SX
3497 #define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2)
3498 #define INFOTEXT_XSIZE SXSIZE
3499 #define INFOTEXT_YSIZE MINI_TILEX
3500 #define MAX_INFOTEXT_LEN (SXSIZE / FONT2_XSIZE)
3502 void ClearEditorGadgetInfoText()
3504 XFillRectangle(display, drawto, gc,
3505 INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
3506 redraw_mask |= REDRAW_FIELD;
3509 void HandleEditorGadgetInfoText(void *ptr)
3511 struct GadgetInfo *gi = (struct GadgetInfo *)ptr;
3512 char infotext[MAX_INFOTEXT_LEN + 1];
3514 ClearEditorGadgetInfoText();
3516 if (gi == NULL || gi->description_text == NULL)
3519 strncpy(infotext, gi->description_text, MAX_INFOTEXT_LEN);
3520 infotext[MAX_INFOTEXT_LEN] = '\0';
3522 DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, FS_SMALL, FC_YELLOW);
3525 static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
3527 int id = gi->custom_id;
3528 int sx = gi->event.x;
3529 int sy = gi->event.y;
3530 int lx = sx + level_xpos;
3531 int ly = sy + level_ypos;
3533 ClearEditorGadgetInfoText();
3535 if (id == ED_CTRL_ID_DRAWING_LEVEL)
3537 if (IN_LEV_FIELD(lx, ly))
3538 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3539 "Level: %d, %d (Screen: %d, %d)", lx, ly, sx, sy);
3541 else if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3542 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3545 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3546 "Cruncher %d content: %d, %d", id - ED_CTRL_ID_ELEMCONT_0 + 1,