1 /* Tower Toppler - Nebulus
2  * Copyright (C) 2000-2012  Andreas R�ver
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18 
19 #include "leveledit.h"
20 
21 #include "decl.h"
22 #include "level.h"
23 #include "screen.h"
24 #include "keyb.h"
25 #include "game.h"
26 #include "sound.h"
27 #include "robots.h"
28 #include "snowball.h"
29 #include "menu.h"
30 #include "txtsys.h"
31 #include "configuration.h"
32 
33 #include <stdlib.h>
34 #include <string.h>
35 
36 /* Editor key actions.
37  If you add here, change _ed_key_actions[] in leveledit.cc */
38 
39 typedef enum {
40   EDACT_QUIT,
41   EDACT_MOVEUP,
42   EDACT_MOVEDOWN,
43   EDACT_MOVELEFT,
44   EDACT_MOVERIGHT,
45   EDACT_INSROW,
46   EDACT_DELROW,
47   EDACT_ROT180,
48   EDACT_PUTSPACE,
49   EDACT_PUTSTEP,
50   EDACT_PUTVANISHER,
51   EDACT_PUTSLIDERLEFT,
52   EDACT_PUTSLIDERRIGHT,
53   EDACT_PUTDOOR,
54   EDACT_PUTGOAL,
55   EDACT_CHECKTOWER,
56   EDACT_PUTROBOT1,
57   EDACT_PUTROBOT2,
58   EDACT_PUTROBOT3,
59   EDACT_PUTROBOT4,
60   EDACT_PUTROBOT5,
61   EDACT_PUTROBOT6,
62   EDACT_PUTROBOT7,
63   EDACT_PUTLIFT,
64   EDACT_PUTLIFTMID,
65   EDACT_PUTLIFTTOP,
66   EDACT_PUTSTICK,
67   EDACT_PUTBOX,
68   EDACT_LOADTOWER,
69   EDACT_SAVETOWER,
70   EDACT_TESTTOWER,
71   EDACT_SETTOWERCOLOR,
72   EDACT_INCTIME,
73   EDACT_DECTIME,
74   EDACT_CREATEMISSION,
75   EDACT_MOVEPAGEUP,
76   EDACT_MOVEPAGEDOWN,
77   EDACT_GOTOSTART,
78   EDACT_SHOWKEYHELP,
79   EDACT_NAMETOWER,
80   EDACT_SETTIME,
81   EDACT_REC_DEMO,
82   EDACT_PLAY_DEMO,
83   EDACT_ADJHEIGHT,
84   EDACT_GOTOEND,
85   EDACT_CUTROW,
86   EDACT_PASTEROW,
87   EDACT_TOGGLEROBOT,
88 
89   NUMEDITORACTIONS
90 } key_actions;
91 
92 struct _ed_key {
93    key_actions action;
94    SDLKey key;
95    char   character;
96    Uint16 mod; /* KMOD_NONE|KMOD_SHIFT|KMOD_CTRL|KMOD_ALT */
97 };
98 
99 #define TOWERPAGESIZE 5 /* pageup/pagedown moving */
100 #define TOWERSTARTHEI 4 /* tower starting height */
101 
102 const char *_ed_key_actions[NUMEDITORACTIONS] = {
103    N_("Quit"),          N_("Move up"),        N_("Move down"),       N_("Move left"),
104    N_("Move right"),    N_("Insert row"),     N_("Delete row"),      N_("Rotate 180"),
105    N_("Put space"),     N_("Put step"),       N_("Put vanisher"),    N_("Put slider left"),
106    N_("Put slider right"),
107    N_("Put door"),      N_("Put goal"),       N_("Check tower"),     N_("Put rolling ball"),
108    N_("Put jumping ball moving"),   N_("Put jumping ball"),    N_("Put robot up down"),     N_("Put robot up down fast"),
109    N_("Put robot left right"),   N_("Put robot left right fast"),    N_("Put lift"),        N_("Lift middle stop"),
110    N_("Lift top stop"), N_("Put pillar"),     N_("Put box"),         N_("Load tower"),
111    N_("Save tower"),    N_("Test tower"),     N_("Set tower color"), N_("Increase time"),
112    N_("Decrease time"), N_("Create mission"), N_("Move page up"),    N_("Move page down"),
113    N_("Go to start"),   N_("Show this help"), N_("Name the tower"),  N_("Set tower time"),
114    N_("Record demo"),   N_("Play demo"),      N_("Adjust tower height"), N_("Go to end"),
115    N_("Cut row"),       N_("Paste row"),      N_("Change robot type")
116 };
117 
118 const struct _ed_key _ed_keys[] = {
119    {EDACT_QUIT,          SDLK_ESCAPE},
120    {EDACT_SHOWKEYHELP,   SDLK_F1},
121    {EDACT_SHOWKEYHELP,   SDLK_h,     'h'},
122    {EDACT_MOVEUP,        SDLK_UP},
123    {EDACT_MOVEDOWN,      SDLK_DOWN},
124    {EDACT_MOVELEFT,      SDLK_LEFT},
125    {EDACT_MOVERIGHT,     SDLK_RIGHT},
126    {EDACT_MOVEPAGEUP,    SDLK_PAGEUP},
127    {EDACT_MOVEPAGEDOWN,  SDLK_PAGEDOWN},
128    {EDACT_GOTOSTART,     SDLK_HOME},
129    {EDACT_GOTOEND,       SDLK_END},
130    {EDACT_ROT180,        SDLK_y,     'y'},
131    {EDACT_INSROW,        SDLK_INSERT},
132    {EDACT_DELROW,        SDLK_DELETE},
133    {EDACT_CUTROW,        SDLK_MINUS, '-'},
134    {EDACT_PASTEROW,      SDLK_PLUS,  '+'},
135    {EDACT_PUTSPACE,      SDLK_SPACE, ' '},
136    {EDACT_PUTSTEP,       SDLK_w,     'w'},
137    {EDACT_PUTVANISHER,   SDLK_s,     's'},
138    {EDACT_PUTSLIDERLEFT, SDLK_x,     'x'},
139    {EDACT_PUTSLIDERRIGHT,SDLK_x,     'X', KMOD_SHIFT},
140    {EDACT_PUTDOOR,       SDLK_i,     'i'},
141    {EDACT_PUTGOAL,       SDLK_k,     'k'},
142    {EDACT_PUTROBOT1,     SDLK_1,     '1'},
143    {EDACT_PUTROBOT2,     SDLK_2,     '2'},
144    {EDACT_PUTROBOT3,     SDLK_3,     '3'},
145    {EDACT_PUTROBOT4,     SDLK_4,     '4'},
146    {EDACT_PUTROBOT5,     SDLK_5,     '5'},
147    {EDACT_PUTROBOT6,     SDLK_6,     '6'},
148    {EDACT_PUTROBOT7,     SDLK_7,     '7'},
149    {EDACT_TOGGLEROBOT,   SDLK_8,     '8'},
150    {EDACT_PUTLIFT,       SDLK_c,     'c'},
151    {EDACT_PUTLIFTMID,    SDLK_d,     'd'},
152    {EDACT_PUTLIFTTOP,    SDLK_e,     'e'},
153    {EDACT_PUTSTICK,      SDLK_q,     'q'},
154    {EDACT_PUTBOX,        SDLK_a,     'a'},
155    {EDACT_CHECKTOWER,    SDLK_z,     'z'},
156    {EDACT_LOADTOWER,     SDLK_l,     'l'},
157    {EDACT_SAVETOWER,     SDLK_o,     'o'},
158    {EDACT_TESTTOWER,     SDLK_p,     'p'},
159    {EDACT_SETTOWERCOLOR, SDLK_v,     'v'},
160    {EDACT_SETTIME,       SDLK_b,     'b'},
161    {EDACT_INCTIME,       SDLK_n,     'n'},
162    {EDACT_DECTIME,       SDLK_n,     'N', KMOD_SHIFT},
163    {EDACT_CREATEMISSION, SDLK_m,     'm'},
164    {EDACT_NAMETOWER,     SDLK_t,     't'},
165    {EDACT_REC_DEMO,      SDLK_F10},
166    {EDACT_PLAY_DEMO,     SDLK_F11},
167    {EDACT_ADJHEIGHT,     SDLK_F8}
168 };
169 
170 static int bg_row;
171 static int bg_col;
172 static char *bg_text = NULL;
173 static bool bg_darken = false;
174 
175 /* men_yn() background drawing callback proc */
editor_background_proc(void)176 static void editor_background_proc(void) {
177    scr_drawedit(bg_row * 4, bg_col * 8, false);
178    if (bg_darken) scr_darkenscreen();
179    if (bg_text) scr_writetext_center(5, bg_text);
180 }
181 
editor_background_menu_proc(_menusystem * ms)182 static const char *editor_background_menu_proc(_menusystem *ms) {
183     editor_background_proc();
184     return 0;
185 }
186 
really_quit(int row,int col)187 static bool really_quit(int row, int col) {
188   bg_darken = true;
189   if (men_yn(_("Tower changed, really quit"), false)) {
190     return true;
191   } else {
192     return false;
193   }
194   bg_darken = false;
195 }
196 
really_load(int row,int col)197 static bool really_load(int row, int col) {
198   bg_darken = true;
199   if (men_yn(_("Tower changed, really load"), false)) {
200     return true;
201   } else {
202     return false;
203   }
204   bg_darken = false;
205 }
206 
edit_towercolor(int row,int col)207 static bool edit_towercolor(int row, int col) {
208 
209   int activecol = 0, abg_r = 10, abg_g = 50, abg_b = 120;
210   bool ende = false, oldpal = false;
211   char cbuf[32];
212   int tmpcol, z, tmp;
213   int oldc[3], newc[3], curc[3];
214   SDLKey c;
215 
216   const char *colorname[] = {_("Red"), _("Green"), _("Blue")};
217 
218   curc[0] = newc[0] = oldc[0] = lev_towercol_red();
219   curc[1] = newc[1] = oldc[1] = lev_towercol_green();
220   curc[2] = newc[2] = oldc[2] = lev_towercol_blue();
221   bg_darken = false;
222   do {
223 
224     scr_drawedit(row * 4, col * 8, false);
225     scr_writetext_center(22, _("Tower Color"));
226 
227     for (tmp = 0 ; tmp < 3; tmp++) {
228       scr_color_ramp(&abg_r, &abg_g, &abg_b);
229       tmpcol = newc[tmp];
230       z = ((SCREENHEI * 2) / 3) + tmp * (FONTHEI + 2);
231 
232       if (tmp == activecol) {
233         scr_putbar((SCREENWID / 2) - (128 + 8), z, 8, FONTHEI, abg_r, abg_g, abg_b, 255);
234         scr_putbar((SCREENWID / 2) + 128 - 1, z, 8, FONTHEI, abg_r, abg_g, abg_b, 255);
235       } else {
236         scr_putbar((SCREENWID / 2) - (128 + 8), z, 8, FONTHEI, 66, 66, 66, 255);
237         scr_putbar((SCREENWID / 2) + 128 - 1, z, 8, FONTHEI, 66, 66, 66, 255);
238       }
239       scr_putbar((SCREENWID / 2) - 128 + tmpcol, z, 255 - tmpcol, FONTHEI, 0,0,0, 255);
240       switch (tmp) {
241       default:
242       case 0: scr_putbar((SCREENWID / 2) - 128, z, tmpcol, FONTHEI, tmpcol / 3 + 64, 0, 0, 255); break;
243       case 1: scr_putbar((SCREENWID / 2) - 128, z, tmpcol, FONTHEI, 0, tmpcol / 3 + 64, 0, 255); break;
244       case 2: scr_putbar((SCREENWID / 2) - 128, z, tmpcol, FONTHEI, 0, 0, tmpcol / 3 + 64, 255); break;
245       }
246       cbuf[0] = '\0';
247       snprintf(cbuf, 32, "%5s  %.3d", colorname[tmp], tmpcol);
248       scr_writetext_center(z, cbuf);
249     }
250 
251     scr_swap();
252     dcl_wait();
253 
254     c = key_sdlkey();
255 
256     switch (c) {
257     case SDLK_UP: if (activecol > 0) activecol--; break;
258     case SDLK_DOWN: if (activecol < 2) activecol++; break;
259     case SDLK_LEFT: if (newc[activecol] > 0)   newc[activecol]--; break;
260     case SDLK_RIGHT: if (newc[activecol] < 255) newc[activecol]++; break;
261     case SDLK_PAGEDOWN: if (newc[activecol] > 10)  newc[activecol] = newc[activecol] - 10;
262                                               else newc[activecol] = 0;  break;
263     case SDLK_PAGEUP: if (newc[activecol] < 245)  newc[activecol] = newc[activecol] + 10;
264                                              else newc[activecol] = 255; break;
265     case SDLK_0: case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4:
266     case SDLK_5: case SDLK_6: case SDLK_7: case SDLK_8:
267     case SDLK_9: newc[activecol] = (int) ((c - '0') * 256) / 10; break;
268     case SDLK_PERIOD: for (tmp = 0; tmp < 3; tmp++) newc[tmp] = rand() % 256; break;
269     case SDLK_r: activecol = 0; break;
270     case SDLK_g: activecol = 1; break;
271     case SDLK_b: activecol = 2; break;
272     case SDLK_ESCAPE: ende = true; oldpal = true; break;
273     case SDLK_SPACE:
274     case SDLK_RETURN: ende = true;
275     default: break;
276     }
277 
278     if ((newc[0] != curc[0]) || (newc[1] != curc[1]) ||
279         (newc[2] != curc[2]) || oldpal) {
280       if (oldpal)
281         lev_set_towercol(oldc[0],oldc[1],oldc[2]);
282       else
283         lev_set_towercol(newc[0],newc[1],newc[2]);
284 
285       scr_settowercolor(lev_towercol_red(),
286                         lev_towercol_green(),
287                         lev_towercol_blue());
288 
289       curc[0] = newc[0];
290       curc[1] = newc[1];
291       curc[2] = newc[2];
292     }
293 
294   } while (!ende);
295 
296   return (!oldpal && ((curc[0] != oldc[0]) || (curc[1] != oldc[1]) || (curc[2] != oldc[2])));
297 }
298 
edit_checktower(int & row,int & col)299 static void edit_checktower(int &row, int &col) {
300   int r, c, pr;
301   r = row;
302   c = -col;
303 
304   static char *problemstr[NUM_TPROBLEMS] = {
305     _("No problems found"),
306     _("No starting step"),
307     _("Start is blocked"),
308     _("Unknown block"),
309     _("No elevator stop"),
310     _("Elevator is blocked"),
311     _("No opposing doorway"),
312     _("Broken doorway"),
313     _("No exit"),
314     _("Exit is unreachable"),
315     _("Not enough time"),
316     _("Tower is too short"),
317     _("Tower has no name")
318   };
319 
320   pr = lev_is_consistent(r, c);
321   if ((r >= lev_towerrows()) && (lev_towerrows() > 0)) r = lev_towerrows() - 1;
322   bg_row = r;
323   bg_col = -c;
324 
325   bg_text = _("Tower check:");
326   bg_darken = true;
327   men_info(problemstr[pr % NUM_TPROBLEMS], 50, 2);
328   bg_darken = false;
329   row = bg_row;
330   col = bg_col;
331   bg_text = NULL;
332 }
333 
keymod2str(Uint16 kmod)334 char *keymod2str(Uint16 kmod) {
335     static char buf[256];
336     buf[0] = '\0';
337     if (kmod != KMOD_NONE) {
338         if ((kmod & KMOD_LSHIFT) ||
339             (kmod & KMOD_RSHIFT)) snprintf(buf, 256, "shift+");
340         if ((kmod & KMOD_LCTRL) ||
341             (kmod & KMOD_RCTRL)) snprintf(&buf[strlen(buf)], 256-strlen(buf), "ctrl+");
342         if ((kmod & KMOD_LALT) ||
343             (kmod & KMOD_RALT)) snprintf(&buf[strlen(buf)], 256-strlen(buf), "alt+");
344     }
345     return buf;
346 }
347 
createMission(void)348 static void createMission(void) {
349 
350   scr_drawedit(0, 0, false);
351   scr_writetext_center(30, _("Mission creation"));
352   scr_writetext_center(80, _("enter mission name"));
353   scr_writetext_center(110, _("empty to abort"));
354 
355   set_men_bgproc(NULL);
356 
357   char missionname[25];
358   missionname[0] = 0;
359   while (!men_input(missionname, 15)) ;
360 
361   if (!missionname[0])
362     return;
363 
364   if (!lev_mission_new(missionname)) {
365 
366     scr_drawedit(0, 0, false);
367     scr_writetext_center(30, _("Mission creation"));
368 
369     scr_writetext_center(80, _("could not create file"));
370     scr_writetext_center(110, _("aborting"));
371 
372     scr_swap();
373 
374     int inp;
375 
376     do {
377       inp = key_chartyped();
378     } while (!inp);
379 
380     return;
381   }
382 
383   int currenttower = 1;
384   char towername[30];
385 
386   while (true) {
387 
388     scr_drawedit(0, 0, false);
389     scr_writetext_center(30, _("Mission creation"));
390     scr_writetext_center(80, _("enter name of"));
391 
392     char s[30];
393     snprintf(s, 30, _("tower no %i"), currenttower);
394     scr_writetext_center(110, s);
395 
396     towername[0] = 0;
397     while (!men_input(towername, 25)) ;
398 
399     if (!towername[0]) break;
400 
401     lev_mission_addtower(towername);
402 
403     currenttower++;
404   }
405 
406   lev_mission_finish();
407 
408   lev_findmissions();
409 }
410 
le_showkeyhelp(int row,int col)411 static void le_showkeyhelp(int row, int col) {
412   int k;
413   int maxkeylen = 0;
414   textsystem *ts = new textsystem(_("Editor Key Help"), editor_background_menu_proc);
415   char tabbuf1[6], tabbuf2[6];
416 
417   if (!ts) return;
418 
419   for (k = 0; k < SIZE(_ed_keys); k++) {
420       char knam[256];
421       snprintf(knam, 256, "%s%s", keymod2str(_ed_keys[k].mod), SDL_GetKeyName(_ed_keys[k].key));
422       int l = scr_textlength(knam);
423 
424       if (l > maxkeylen) maxkeylen = l;
425   }
426 
427   snprintf(tabbuf1, 6, "%3i", maxkeylen + FONTWID);
428   if (tabbuf1[0] < '0') tabbuf1[0] = '0';
429   if (tabbuf1[1] < '0') tabbuf1[1] = '0';
430   if (tabbuf1[2] < '0') tabbuf1[2] = '0';
431 
432   for (k = 0; k < SIZE(_ed_keys); k++) {
433       char buf[256];
434       char tmpb[256];
435       char knam[256];
436 
437       snprintf(knam, 256, "%s%s", keymod2str(_ed_keys[k].mod), SDL_GetKeyName(_ed_keys[k].key));
438 
439       snprintf(tabbuf2, 6, "%3i", maxkeylen - scr_textlength(knam));
440       if (tabbuf2[0] < '0') tabbuf2[0] = '0';
441       if (tabbuf2[1] < '0') tabbuf2[1] = '0';
442       if (tabbuf2[2] < '0') tabbuf2[2] = '0';
443 
444       snprintf(tmpb, 256, "~T%s%%s~T%s%%s", tabbuf2, tabbuf1);
445       snprintf(buf, 256, tmpb, knam, _(_ed_key_actions[_ed_keys[k].action]));
446 
447       ts->addline(buf);
448   }
449   bg_darken = true;
450   ts->run();
451   bg_darken = false;
452   delete ts;
453 }
454 
455 static int clipboard_rows = 0;
456 static Uint8 clipboard_tower[256][16];
457 static bool cursor_moved = false;
458 
le_tower_cut(int row,int col)459 void le_tower_cut(int row, int col) {
460     if (cursor_moved) clipboard_rows = 0;
461 
462     if (clipboard_rows < 255) {
463         for (int i = 0; i < 16; i++)
464             clipboard_tower[clipboard_rows][i] = lev_tower(row, (col+i) % 16);
465         lev_deleterow(row);
466         clipboard_rows++;
467     }
468 
469     cursor_moved = false;
470 }
471 
le_tower_paste(int row,int col)472 void le_tower_paste(int row, int col) {
473     if (clipboard_rows > 0) {
474         for (int z = 0; z < clipboard_rows; z++) {
475             lev_insertrow(row);
476             for (int i = 0; i < 16; i++) {
477                 lev_set_tower(row, (col+i) % 16, clipboard_tower[clipboard_rows - (z + 1)][i]);
478             }
479         }
480     } else lev_insertrow(row);
481 
482     cursor_moved = false;
483 }
484 
le_edit(void)485 void le_edit(void) {
486 
487   bool ende = false;
488   bool changed = false;
489   SDLKey inp = SDLK_UNKNOWN;
490   char inp_char;
491   Uint16 keymod;
492   int row = 0, col = 0;
493   int tstep = 0;
494   int blink_r = 70, blink_g = 40, blink_b = 10;
495   char status[80];
496   int towerstarthei;
497   int pagesize;
498 
499   if (config.editor_towerstarthei() < 0)
500       towerstarthei = TOWERSTARTHEI + (rand() % abs(config.editor_towerstarthei()));
501   else towerstarthei = TOWERSTARTHEI + config.editor_towerstarthei();
502 
503   lev_new(towerstarthei % 256);
504 
505   if (config.editor_towerpagesize() < 1) {
506     config.editor_towerpagesize(TOWERPAGESIZE);
507     pagesize = TOWERPAGESIZE;
508   } else pagesize = config.editor_towerpagesize();
509 
510   set_men_bgproc(editor_background_proc);
511 
512   lev_set_towertime(100 + (rand() % 10) * 50);
513 
514   lev_set_towercol(rand() % 256,rand() % 256,rand() % 256);
515   scr_settowercolor(lev_towercol_red(),
516                     lev_towercol_green(),
517                     lev_towercol_blue());
518 
519   lev_set_towername("");
520   lev_set_towerdemo(0, NULL);
521 
522   while (!ende) {
523 
524     bg_row = row;
525     bg_col = col;
526     bg_darken = false;
527 
528     scr_drawedit(row * 4, col * 8, true);
529 
530     status[0] = '\0';
531     snprintf(status, 80, "%c~t050X%d~t150Y%d~t250%s:%d",
532              changed ? '*' : ' ', -col & 0xf, row, _("cut#"), clipboard_rows);
533 
534     scr_putbar(SCREENWID-8, SCREENHEI-lev_towerrows(), 8, lev_towerrows(),
535                lev_towercol_red(), lev_towercol_green(), lev_towercol_blue(), 255);
536     scr_putbar(SCREENWID-8, SCREENHEI-row-1, 8, 1, blink_r, blink_g, blink_b, 128);
537 
538     scr_color_ramp(&blink_r, &blink_g, &blink_b);
539 
540     scr_writeformattext(0, SCREENHEI-FONTHEI, status);
541 
542     scr_swap();
543     dcl_wait();
544 
545     inp_char = key_chartyped();
546     inp = key_sdlkey();
547     keymod = (SDL_GetModState() & ~(KMOD_NUM|KMOD_CAPS|KMOD_MODE));
548     if (keymod & KMOD_SHIFT) keymod |= KMOD_SHIFT;
549     if (keymod & KMOD_CTRL) keymod |= KMOD_CTRL;
550     if (keymod & KMOD_ALT) keymod |= KMOD_ALT;
551     if (keymod & KMOD_META) keymod |= KMOD_META;
552 
553 
554     int k, action = -1;
555 
556     if (inp_char != 0)
557       for (k = 0; k < SIZE(_ed_keys); k++)
558         if (_ed_keys[k].character == inp_char) {
559           action = _ed_keys[k].action;
560           break;
561         }
562 
563     if ((inp != SDLK_UNKNOWN) && (action == -1))
564       for (k = 0; k < SIZE(_ed_keys); k++)
565         if (_ed_keys[k].key == inp && _ed_keys[k].mod == keymod) {
566           action = _ed_keys[k].action;
567           break;
568         }
569 
570     if ((action != -1) || (inp_char != 0) || (inp != SDLK_UNKNOWN))
571       debugprintf(3, _("key: %s, char: %c, action: %i\n"), SDL_GetKeyName(inp), inp_char, action);
572 
573     if (action != -1) {
574 
575       switch (action) {
576       case EDACT_QUIT:
577         if (changed) ende = really_quit(row, col);
578         else ende = true;
579         break;
580       case EDACT_MOVEUP:
581         if (row + 1 < lev_towerrows()) {
582             row++;
583             cursor_moved = true;
584         }
585         break;
586       case EDACT_MOVEDOWN:
587         if (row > 0) {
588             row--;
589             cursor_moved = true;
590         }
591         break;
592       case EDACT_MOVELEFT:
593         col++;
594         cursor_moved = true;
595         break;
596       case EDACT_MOVERIGHT:
597         col--;
598         cursor_moved = true;
599         break;
600       case EDACT_ROT180:
601         col += 8;
602         cursor_moved = true;
603         break;
604       case EDACT_INSROW:
605         lev_insertrow(row);
606         changed = true;
607         break;
608       case EDACT_DELROW:
609         lev_deleterow(row);
610         changed = true;
611         break;
612       case EDACT_PASTEROW:
613         le_tower_paste(row, -col & 0xf);
614         changed = true;
615         break;
616       case EDACT_CUTROW:
617         le_tower_cut(row, -col & 0xf);
618         changed = true;
619         break;
620       case EDACT_PUTSPACE:
621         lev_putspace(row, -col & 0xf);
622         changed = true;
623         break;
624       case EDACT_PUTSTEP:
625         lev_putstep(row, -col & 0xf);
626         changed = true;
627         break;
628       case EDACT_PUTVANISHER:
629         lev_putvanishingstep(row, -col & 0xf);
630         changed = true;
631         break;
632       case EDACT_PUTSLIDERLEFT:
633         lev_putslidingstep_left(row, -col & 0xf);
634         changed = true;
635         break;
636       case EDACT_PUTSLIDERRIGHT:
637         lev_putslidingstep_right(row, -col & 0xf);
638         changed = true;
639         break;
640       case EDACT_PUTDOOR:
641         lev_putdoor(row, -col & 0xf);
642         changed = true;
643         break;
644       case EDACT_PUTGOAL:
645         lev_puttarget(row, -col & 0xf);
646         changed = true;
647         break;
648       case EDACT_CHECKTOWER:
649         edit_checktower(row, col);
650         break;
651       case EDACT_PUTROBOT1:
652         lev_putrobot1(row, -col & 0xf);
653         changed = true;
654         break;
655       case EDACT_PUTROBOT2:
656         lev_putrobot2(row, -col & 0xf);
657         changed = true;
658         break;
659       case EDACT_PUTROBOT3:
660         lev_putrobot3(row, -col & 0xf);
661         changed = true;
662         break;
663       case EDACT_PUTROBOT4:
664         lev_putrobot4(row, -col & 0xf);
665         changed = true;
666         break;
667       case EDACT_PUTROBOT5:
668         lev_putrobot5(row, -col & 0xf);
669         changed = true;
670         break;
671       case EDACT_PUTROBOT6:
672         lev_putrobot6(row, -col & 0xf);
673         changed = true;
674         break;
675       case EDACT_PUTROBOT7:
676         lev_putrobot7(row, -col & 0xf);
677         changed = true;
678         break;
679       case EDACT_PUTLIFTTOP:
680         lev_puttopstation(row, -col & 0xf);
681         changed = true;
682         break;
683       case EDACT_PUTLIFTMID:
684         lev_putmiddlestation(row, -col & 0xf);
685         changed = true;
686         break;
687       case EDACT_PUTLIFT:
688         lev_putelevator(row, -col & 0xf);
689         changed = true;
690         break;
691       case EDACT_PUTSTICK:
692         lev_putstick(row, -col & 0xf);
693         changed = true;
694         break;
695       case EDACT_PUTBOX:
696         lev_putbox(row, -col & 0xf);
697         changed = true;
698         break;
699       case EDACT_LOADTOWER:
700         if (changed)
701           if (!really_load(row, col))
702             break;
703         bg_text = _("Load tower:");
704         bg_darken = true;
705         key_wait_for_none(editor_background_proc);
706         {
707           char name[TOWERNAMELEN+1];
708           strncpy(name, config.editor_towername(), TOWERNAMELEN);
709           name[TOWERNAMELEN] = 0;
710           while (!men_input(name, TOWERNAMELEN)) ;
711           config.editor_towername(name);
712         }
713         bg_text = NULL;
714         if ((strlen(config.editor_towername()) > 0) &&
715             lev_loadtower(config.editor_towername())) {
716             scr_settowercolor(lev_towercol_red(),
717                                lev_towercol_green(),
718                                lev_towercol_blue());
719             changed = false;
720         }
721         if (row >= lev_towerrows()) row = lev_towerrows()-1;
722         break;
723       case EDACT_SAVETOWER:
724         bg_text = _("Save tower:");
725         bg_darken = true;
726         key_wait_for_none(editor_background_proc);
727         {
728           char name[TOWERNAMELEN+1];
729           strncpy(name, config.editor_towername(), TOWERNAMELEN);
730           name[TOWERNAMELEN] = 0;
731           while (!men_input(name, TOWERNAMELEN)) ;
732           config.editor_towername(name);
733         }
734         bg_text = NULL;
735         lev_savetower(config.editor_towername());
736         changed = false;
737         break;
738 
739       case EDACT_REC_DEMO:
740         {
741             Uint8 dummy1;
742             Uint16 dummy2;
743             unsigned char *p;
744             int demolen = -1;
745             Uint16 *demobuf = NULL;
746             int speed = dcl_update_speed(config.game_speed());
747             lev_set_towerdemo(0, NULL);
748             lev_save(p);
749             gam_newgame();
750             rob_initialize();
751             snb_init();
752             ttsounds::instance()->startsound(SND_WATER);
753             gam_towergame(dummy1, dummy2, demolen, &demobuf);
754             ttsounds::instance()->stopsound(SND_WATER);
755             lev_restore(p);
756             lev_set_towerdemo(demolen, demobuf);
757             key_readkey();
758             set_men_bgproc(editor_background_proc);
759             dcl_update_speed(speed);
760         }
761         break;
762       case EDACT_PLAY_DEMO:
763         {
764             int demolen = 0;
765             Uint16 *demobuf = NULL;
766             lev_get_towerdemo(demolen, demobuf);
767             if (demolen > 0) {
768                 Uint8 dummy1;
769                 Uint16 dummy2;
770                 unsigned char *p;
771                 int speed = dcl_update_speed(config.game_speed());
772                 lev_save(p);
773                 gam_newgame();
774                 rob_initialize();
775                 snb_init();
776                 ttsounds::instance()->startsound(SND_WATER);
777                 gam_towergame(dummy1, dummy2, demolen, &demobuf);
778                 ttsounds::instance()->stopsound(SND_WATER);
779                 lev_restore(p);
780                 key_readkey();
781                 set_men_bgproc(editor_background_proc);
782                 dcl_update_speed(speed);
783             } else {
784                 bg_darken = true;
785                 men_info(_("No recorded demo"), 150, 2);
786             }
787         }
788         break;
789       case EDACT_TESTTOWER:
790         {
791           Uint8 dummy1;
792           Uint16 dummy2;
793           int dummy3 = -2;
794           int speed = dcl_update_speed(config.game_speed());
795           Uint16 *dummybuf = NULL;
796           unsigned char *p;
797           lev_save(p);
798           gam_newgame();
799           rob_initialize();
800           snb_init();
801           ttsounds::instance()->startsound(SND_WATER);
802           gam_towergame(dummy1, dummy2, dummy3, &dummybuf);
803           ttsounds::instance()->stopsound(SND_WATER);
804           lev_restore(p);
805           key_readkey();
806           set_men_bgproc(editor_background_proc);
807           dcl_update_speed(speed);
808         }
809         break;
810       case EDACT_SETTOWERCOLOR:
811         changed |= edit_towercolor(row, col);
812         break;
813       case EDACT_INCTIME:
814         if (tstep <= 0) tstep = 1;
815         lev_set_towertime(lev_towertime() + tstep);
816         if (tstep < 10) tstep++;
817         changed = true;
818         break;
819       case EDACT_DECTIME:
820         if (tstep >= 0) tstep = -1;
821         lev_set_towertime(lev_towertime() + tstep);
822         if (tstep > -10) tstep--;
823         changed = true;
824         break;
825       case EDACT_SETTIME:
826         {
827           char buf[64];
828 
829           snprintf(buf, 64, "%d", lev_towertime());
830 
831           bg_text = _("Enter tower time:");
832           bg_darken = true;
833           key_wait_for_none(editor_background_proc);
834           while (!men_input((char *)buf, 15, -1, -1, "0123456789")) ;
835           bg_text = NULL;
836 
837           lev_set_towertime(atoi(buf));
838         }
839         break;
840       case EDACT_ADJHEIGHT:
841         {
842             char buf[64];
843             int i;
844 
845             snprintf(buf, 64, "0");
846 
847             bg_text = _("Adjust tower height:");
848             bg_darken = true;
849             key_wait_for_none(editor_background_proc);
850             while (!men_input((char *)buf, 15, -1, -1, "-+0123456789")) ;
851             bg_text = NULL;
852 
853             i = atoi(buf);
854             if ((i > 0) && (buf[0] == '+')) {
855                 while (i-- > 0) lev_insertrow(row);
856             } else
857             if (i < 0) {
858                 i = abs(i);
859                 while (i-- > 0) lev_deleterow(row);
860             } else
861             if (i>0) {
862                if (i < lev_towerrows()) {
863                     while ((i > 0) && (i < lev_towerrows())) {
864                         lev_deleterow(row);
865                         if ((row > 0) && (row >= lev_towerrows())) row--;
866                     }
867                 } else {
868                     while ((i < 255) && (i > lev_towerrows())) {
869                         lev_insertrow(row);
870                     }
871                 }
872             }
873         }
874         break;
875       case EDACT_CREATEMISSION:
876         createMission();
877         break;
878       case EDACT_MOVEPAGEUP:
879         if (row + pagesize < lev_towerrows())
880           row += pagesize;
881         else
882           row = lev_towerrows() - 1;
883         break;
884       case EDACT_MOVEPAGEDOWN:
885         if (row > pagesize)
886           row -= pagesize;
887         else
888           row = 0;
889         break;
890       case EDACT_GOTOSTART:
891         col = 0;
892         row = 1;
893         break;
894       case EDACT_GOTOEND:
895         {
896             int trow = row;
897             int tcol = col;
898             int coladj = 0;
899             int rowadj = 0;
900             bool ende = false;
901             bool skip = lev_is_targetdoor(trow, -tcol & 0xf);
902 
903             do {
904                 tcol++;
905                 coladj++;
906 
907                 if (coladj >= 16) {
908                     tcol = col;
909                     trow = (trow + 1) % lev_towerrows();
910                     coladj = 0;
911                     rowadj++;
912                 }
913 
914                 if (rowadj >= lev_towerrows()) ende = true;
915                 else if (!skip && lev_is_targetdoor(trow, -tcol & 0xf) &&
916                          lev_is_door_upperend(trow, -tcol & 0xf)) ende = true;
917                 skip = false;
918             } while (!ende);
919 
920             if (rowadj < lev_towerrows()) {
921                 row = trow;
922                 col = tcol;
923             }
924         }
925         break;
926       case EDACT_NAMETOWER:
927         bg_text = _("Name the tower:");
928         bg_darken = true;
929         key_wait_for_none(editor_background_proc);
930         while (!men_input(lev_towername(), TOWERNAMELEN)) ;
931         bg_text = NULL;
932         changed = true;
933         break;
934       case EDACT_SHOWKEYHELP:
935         le_showkeyhelp(row, col);
936         break;
937       case EDACT_TOGGLEROBOT:
938         lev_set_robotnr((lev_robotnr() + 1) % scr_numrobots());
939         break;
940       default: break;
941       }
942     }
943   }
944 }
945