source: abuse/trunk/src/dev.cpp @ 671

Last change on this file since 671 was 671, checked in by Sam Hocevar, 11 years ago

imlib: convert some Jwindow members to vec2i.

File size: 99.3 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com, by
8 *  Jonathan Clark, or by Sam Hocevar.
9 */
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <ctype.h>
16#include <string.h>
17
18#include "common.h"
19
20#include "dev.h"
21#include "input.h"
22#include "objects.h"
23#include "id.h"
24#include "lisp.h"
25#include "light.h"
26#include "devsel.h"
27#include "dprint.h"
28#include "property.h"
29#include "pmenu.h"
30#include "filesel.h"
31#include "tools.h"
32#include "game.h"
33#include "pcxread.h"
34#include "lisp_gc.h"
35#include "demo.h"
36#include "profile.h"
37#include "sbar.h"
38#include "compiled.h"
39#include "chat.h"
40
41#define make_above_tile(x) ((x)|0x4000)
42char backw_on=0,forew_on=0,show_menu_on=0,ledit_on=0,pmenu_on=0,omenu_on=0,commandw_on=0,tbw_on=0,
43     searchw_on=0,small_render_on=0,interpolate_draw=0,disable_autolight=0,fps_on=0,profile_on=0,
44     show_names=0,fg_reversed=0,
45     raise_all;
46
47char const *symbol_str(char const *name)
48{
49  LSymbol *sym = LSymbol::FindOrCreate(name);
50  if (sym->GetValue() && item_type(sym->GetValue())==L_STRING)
51    return lstring_value(sym->GetValue());
52
53
54  // maybe english.lsp was not loaded yet, let's try to do that
55  LSpace *sp = LSpace::Current;
56  LSpace::Current = &LSpace::Perm;
57
58  char prog[50];
59  char const *cs=prog;
60  strcpy(prog,"(setq section 'game_section)\n");
61  LObject::Compile(cs)->Eval();
62  strcpy(prog,"(load \"lisp/english.lsp\")\n");
63  cs=prog;
64  if (!LObject::Compile(cs)->Eval())
65  {
66    printf("unable to open file '%s'\n",lsf);
67    exit(0);
68  }
69  LSpace::Current=sp;
70
71
72  // check again to see if the symbol is there
73  sym = LSymbol::FindOrCreate(name);
74  if (sym->GetValue() && item_type(sym->GetValue())==L_STRING)
75    return lstring_value(sym->GetValue());
76
77
78  // check to see if there is a missing symbol definition
79  sym = LSymbol::FindOrCreate("missing_sym");
80  if (sym->GetValue() && item_type(sym->GetValue())==L_STRING)
81    return lstring_value(sym->GetValue());
82
83  // last resort, return english string
84  return "Missing language symbol!";
85}
86
87
88static game_object *copy_object=NULL;
89
90pmenu *dev_menu=NULL;
91Jwindow *mess_win=NULL,*warn_win=NULL;
92
93game_object *edit_object;
94dev_controll *dev_cont=NULL;
95image *small_render=NULL;
96
97vec2i dlast;
98int scale_mult,scale_div;
99int last_created_type=-1;
100char level_file[100]="levels/level00.spe";
101
102
103class cached_image : public visual_object
104{
105  int id;
106  public :
107  cached_image(int Id) { id=Id; }
108  virtual void draw(image *screen, int x, int y, Filter *f)
109  {
110    if (f)
111      f->PutImage(screen, cache.img(id), vec2i(x, y));
112    else
113      screen->PutImage(cache.img(id), vec2i(x, y));
114  }
115  virtual int width() { return cache.img(id)->Size().x; }
116  virtual int height() { return cache.img(id)->Size().y; }
117} ;
118
119
120#define DEV_MODES 3
121cached_image *dev_mode_pict[DEV_MODES];
122
123int dev_del,dev_move, dev_char_left,dev_char_right,dev_back,dev_front,dev_ok,dev_copy,dev_brain,
124    dev_lights,dev_objects,dev_ai,dev_mode_icon[DEV_MODES],
125    dev_forward,dev_backward;
126
127char const *dev_mode_icon_names[DEV_MODES] =
128{
129    "pixel_mode", "pick_mode", /* "fill_mode",
130    "line_mode","rect_mode","bar_mode", */ "area_select"
131};
132
133int dev_mode_ids[DEV_MODES]={ ID_DMODE_DRAW,ID_DMODE_PICK, ID_DMODE_AREA};
134
135int edit_mode=ID_DMODE_DRAW;
136
137
138dev_term *dev_console=NULL;
139int ldef_width=0,ldef_height=0,ldef_r1=1,ldef_r2=100;
140
141void make_screen_size(int w, int h);
142
143class amb_cont : public scroller
144{
145  public :
146  amb_cont(int X, int Y, ifield *Next) : scroller(X,Y,ID_NULL,100,wm->font()->Size().y+2,0,64,Next)
147  { if (player_list) sx=player_list->ambient; }
148  virtual void scroll_event(int newx, image *screen)
149  {
150    screen->Bar(m_pos, m_pos + vec2i(l - 1, h - 1), wm->dark_color());
151    char st[100];
152    sprintf(st,"%d",newx);
153    wm->font()->PutString(screen, m_pos + vec2i(30, 1), st, wm->bright_color());
154    if (player_list)
155      player_list->ambient=newx;
156    the_game->need_refresh();
157  }
158} ;
159
160
161int confirm_quit()
162{
163    Jwindow *quitw;
164    image *ok_image, *cancel_image;
165
166    ok_image = cache.img(cache.reg("art/frame.spe", "dev_ok",
167                                 SPEC_IMAGE, 1))->copy();
168    cancel_image = cache.img(cache.reg("art/frame.spe", "cancel",
169                                     SPEC_IMAGE, 1))->copy();
170
171    quitw = wm->CreateWindow(vec2i(xres / 2 + 40, yres / 2), vec2i(80, -1),
172              new button(10, wm->font()->Size().y + 4, ID_QUIT_OK, ok_image,
173              new button(38, wm->font()->Size().y + 4, ID_CANCEL, cancel_image,
174              new info_field(2, 2, ID_NULL, symbol_str("sure?"), NULL))),
175              symbol_str("quit_title"));
176
177    wm->grab_focus(quitw);
178    int fin = 0, quit = 0;
179
180    while(!fin)
181    {
182        wm->flush_screen();
183
184        Event ev;
185        wm->get_event(ev);
186        if(ev.type == EV_MESSAGE && ev.message.id == ID_QUIT_OK)
187            fin = quit = 1;
188        else if(ev.type == EV_MESSAGE && ev.message.id == ID_CANCEL)
189            fin = 1;
190        else if(ev.type == EV_KEY
191                 && toupper(ev.key) == toupper(*symbol_str("YES")))
192            fin = quit = 1;
193        else if(ev.type == EV_KEY
194                 && toupper(ev.key) == toupper(*symbol_str("NO")))
195            fin = 1;
196        if((ev.type == EV_KEY && ev.key == JK_ESC)
197           || ev.type == EV_CLOSE_WINDOW)
198            fin = 1;
199    }
200
201    delete ok_image;
202    delete cancel_image;
203
204    the_game->reset_keymap();
205
206    wm->close_window(quitw);
207    wm->flush_screen();
208    return quit;
209}
210
211static void show_object_number (game_object *who)
212{
213  int total=0,number=0;
214  game_object *c;
215  for (c=current_level->first_object(); c; c=c->next)
216  {
217    if (c->otype==who->otype)
218      total++;
219    if (c==who) number=total;
220  }
221  char msg[100];
222  sprintf(msg,"%s : %d of %d",object_names[who->otype],number,total);
223}
224
225void dev_controll::search_backward()
226{ ;
227}
228
229
230static void single_render()
231{
232  // enlarge clip area
233  the_game->first_view->cx2=the_game->first_view->cx1+
234                            (the_game->first_view->cx2-the_game->first_view->cx1+1)*2;
235  the_game->first_view->cy2=the_game->first_view->cy1+
236                            (the_game->first_view->cy2-the_game->first_view->cy1+1)*2;
237  delete small_render;
238  small_render=NULL;
239  small_render_on=0;
240}
241
242static void double_render()
243{
244  small_render_on=1;
245  // reduce clip area
246  the_game->first_view->cx2=the_game->first_view->cx1+
247                            (the_game->first_view->cx2-the_game->first_view->cx1+1)/2;
248  the_game->first_view->cy2=the_game->first_view->cy1+
249                            (the_game->first_view->cy2-the_game->first_view->cy1+1)/2;
250
251  small_render=new image(vec2i(the_game->first_view->cx2-the_game->first_view->cx1+1, the_game->first_view->cy2-the_game->first_view->cy1+1),NULL,2);
252}
253
254
255void dev_controll::search_forward()
256{
257  if (search_window) // if no window then we can't get the object name
258  {
259    char *name=search_window->read(ID_SEARCH_TEXT);
260    int type=-1;    // see if this type existss
261    int i;
262    for (i=0; i<total_objects; i++)
263      if (!strcmp(object_names[i],name))
264        type=i;
265    if (type==-1)
266    {
267      char msg[60];
268      sprintf(msg,"Object type '%s' does not existss!\n",name);
269      the_game->show_help(msg);
270      the_game->need_refresh();
271    } else
272    {
273      game_object *first,*find=NULL;
274      if (!search_object || search_object->otype!=type)
275        first=current_level->first_object();
276      else
277        first=search_object->next;
278      for (; !find && first; first=first->next)
279        if (first->otype==type)
280      find=first;
281      if (!find)
282      {
283    for (first=current_level->first_object(); first && !find; first=first->next)
284    {
285      if (first->otype==type)
286        find=first;
287    }
288      }
289      if (find)
290      {
291        search_object=find;
292    show_object_number(search_object);
293      }
294      else
295      {
296    the_game->show_help("No object matching name exists in level\n");
297
298      }
299    }
300  }
301}
302
303
304int32_t dev_controll::snap_x(int32_t x)
305{
306  if (wm->key_pressed(JK_CTRL_L) || wm->key_pressed(JK_CTRL_R))
307    return x-(x%the_game->ftile_width());
308  else if (wm->key_pressed(JK_ALT_L) || wm->key_pressed(JK_ALT_R))
309    return x-(x%the_game->ftile_width())+the_game->ftile_width()/2;
310  else return x;
311}
312
313int32_t dev_controll::snap_y(int32_t y)
314{
315  if (wm->key_pressed(JK_CTRL_L) || wm->key_pressed(JK_CTRL_R))
316    return y-(y%the_game->ftile_height())-1;
317  else if (wm->key_pressed(JK_ALT_L) || wm->key_pressed(JK_ALT_R))
318    return y-(y%the_game->ftile_height())+the_game->ftile_height()/2-1;
319  else return y;
320}
321
322void dev_controll::make_ambient()
323{
324    if(ambw)
325        return;
326
327    ambw = wm->CreateWindow(vec2i(prop->getd("ambient x", -1),
328                                  prop->getd("ambient y", -1)),
329                            vec2i(-1), new amb_cont(0, 0, NULL), "ambient");
330}
331
332void dev_term::execute(char *st)
333{
334  if (!strcmp(st,"?"))
335  {
336    put_string("unchop x y, size x y,\n"
337           "load, esave, name\n");
338  } else
339  {
340    Event ev;
341    dv->do_command(st,ev);
342  }
343}
344
345static void load_dev_icons()
346{
347  char const *artf="art/dev.spe";
348  dev_del=cache.reg(artf,"dev_del",SPEC_IMAGE,0);
349  dev_move=cache.reg(artf,"dev_move",SPEC_IMAGE,0);
350  dev_char_left=cache.reg(artf,"dev_char_left",SPEC_IMAGE,0);
351  dev_char_right=cache.reg(artf,"dev_char_right",SPEC_IMAGE,0);
352  dev_back=cache.reg(artf,"dev_back",SPEC_IMAGE,0);
353  dev_front=cache.reg(artf,"dev_front",SPEC_IMAGE,0);
354  dev_ok=cache.reg(artf,"dev_ok",SPEC_IMAGE,0);
355  dev_copy=cache.reg(artf,"dev_copy",SPEC_IMAGE,0);
356  dev_brain=cache.reg(artf,"brain",SPEC_IMAGE,0);
357  dev_lights=cache.reg(artf,"lights",SPEC_IMAGE,0);
358  dev_objects=cache.reg(artf,"objects",SPEC_IMAGE,0);
359  dev_ai=cache.reg(artf,"ai",SPEC_IMAGE,0);
360  dev_forward=cache.reg(artf,"forward",SPEC_IMAGE,0);
361  dev_backward=cache.reg(artf,"backward",SPEC_IMAGE,0);
362
363  for (int i=0; i<DEV_MODES; i++)
364    dev_mode_icon[i]=cache.reg(artf,dev_mode_icon_names[i],SPEC_IMAGE,0);
365
366}
367
368void scale_put(image *im, image *screen, int x, int y, short new_width, short new_height)
369{
370  unsigned char *sl1,*sl2;
371  int32_t xstep=(im->Size().x<<16)/new_width,
372       ystep=(im->Size().y<<16)/new_height,iy,ix,sx,ix_start,iy_start;
373  screen->AddDirty(vec2i(x, y), vec2i(x + new_width, y + new_height));
374
375  vec2i caa, cbb;
376  screen->GetClip(caa, cbb);
377  if (caa.x > cbb.x || caa.y > cbb.y || x>=cbb.x || y>=cbb.y || x+new_width<=caa.x || y+new_height<=caa.y) return ;
378  if (x<caa.x)
379  {
380    ix_start=(caa.x-x)*xstep;
381    new_width-=(caa.x-x);
382    x=caa.x;
383  } else ix_start=0;
384  if (x+new_width>cbb.x)
385    new_width-=x+new_width-cbb.x;
386  if (y<caa.y)
387  {
388    iy_start=(caa.y-y)*ystep;
389    new_height-=(caa.y-y);
390    y=caa.y;
391  } else iy_start=0;
392  if (y+new_height>cbb.y)
393    new_height-=y+new_height-cbb.y;
394
395  screen->Lock();
396  im->Lock();
397  for (iy=iy_start; new_height>0; new_height--,y++,iy+=ystep)
398  {
399    sl1=im->scan_line(iy>>16);
400    sl2=screen->scan_line(y)+x;
401    for (ix=ix_start,sx=0; sx<new_width; sx++,ix+=xstep,sl2++)
402      *sl2=sl1[ix>>16];
403  }
404  im->Unlock();
405  screen->Unlock();
406}
407
408
409void scale_put_trans(image *im, image *screen, int x, int y, short new_width, short new_height)
410{
411  unsigned char *sl1,*sl2;
412  int32_t xstep=(im->Size().x<<16)/new_width,
413       ystep=(im->Size().y<<16)/new_height,iy,ix,sx,ix_start,iy_start;
414  screen->AddDirty(vec2i(x, y), vec2i(x + new_width, y + new_height));
415
416  vec2i caa, cbb;
417  screen->GetClip(caa, cbb);
418  if (caa.x > cbb.x || caa.y > cbb.y || x >= cbb.x || y >= cbb.y || x+new_width<=caa.x || y+new_height<=caa.y) return ;
419  if (x<caa.x)
420  {
421    ix_start=(caa.x-x)*xstep;
422    new_width-=(caa.x-x);
423    x=caa.x;
424  } else ix_start=0;
425  if (x+new_width>cbb.x)
426    new_width-=x+new_width-cbb.x;
427  if (y<caa.y)
428  {
429    iy_start=(caa.y-y)*ystep;
430    new_height-=(caa.y-y);
431    y=caa.y;
432  } else iy_start=0;
433  if (y+new_height>cbb.y)
434    new_height-=y+new_height-cbb.y;
435
436  uint8_t d;
437  screen->Lock();
438  for (iy=iy_start; new_height>0; new_height--,y++,iy+=ystep)
439  {
440    sl1=im->scan_line(iy>>16);
441    sl2=screen->scan_line(y)+x;
442    for (ix=ix_start,sx=0; sx<new_width; sx++,ix+=xstep,sl2++)
443    {
444      d=sl1[ix>>16];
445      if (d)
446        *sl2=d;
447    }
448  }
449  screen->Unlock();
450}
451
452int dev_controll::need_plus_minus()
453{
454  if (state==DEV_MOVE_LIGHT) return 1; else return 0;
455}
456
457int dev_controll::need_arrows()
458{
459  if (state==DEV_MOVE_LIGHT) return 1; else return 0;
460}
461
462int dev_controll::repeat_key_mode()
463{
464  if (state==DEV_MOVE_LIGHT) return 1; else return 0;
465}
466
467int last_link_x=0,last_link_y=0;
468
469void dev_controll::dev_draw(view *v)
470{
471  int32_t x1,y1,x2,y2;
472  if (dev&EDIT_MODE)
473  {
474    int32_t vx=v->xoff(),vy=v->yoff();
475
476    if (dev&DRAW_LINKS)
477    {
478      for (light_source *f=first_light_source; f; f=f->next)
479      {
480    if (f->x-vx>=0 && f->x-vx<=(v->cx2-v->cx1+1) && f->y-vy>=0 && f->y-vy<=(v->cy2-v->cy1+1))
481    {
482      image *im = cache.img(light_buttons[f->type]);
483      main_screen->PutImage(im, vec2i(f->x - vx + v->cx1 - im->Size().x / 2,
484                                      f->y - vy + v->cy1 - im->Size().y / 2), 1);
485      main_screen->Rectangle(vec2i(f->x1 - vx + v->cx1, f->y1 - vy + v->cy1),
486                             vec2i(f->x2 - vx + v->cx1, f->y2 - vy + v->cy1),
487                             wm->medium_color());
488    }
489      }
490    }
491
492    if (link_object)
493    {
494      vec2i pos = the_game->GameToMouse(vec2i(link_object->x, link_object->y), v);
495      main_screen->Line(pos, dlast, yellow);
496    }
497
498    if (selected_light)
499    {
500      image *im = cache.img(light_buttons[0]);
501      vec2i pos = the_game->GameToMouse(vec2i(selected_light->x, selected_light->y), v);
502      main_screen->Rectangle(pos - im->Size() / 2, pos + im->Size() / 2,
503                             wm->bright_color());
504    }
505
506    game_object *o;
507    if (show_names)
508      for (o=current_level->first_object(); o; o=o->next)
509      {
510    vec2i pos = the_game->GameToMouse(vec2i(o->x, o->y), current_view);
511    char *nm=object_names[o->otype];
512    console_font->PutString(main_screen, pos + vec2i(- strlen(nm) * console_font->Size().x / 2, 2), nm);
513      }
514
515    if (dev&DRAW_LINKS)
516    {
517      // draw connections between objects
518      for (o=current_level->first_object(); o; o=o->next)
519      {
520    vec2i pos1 = the_game->GameToMouse(vec2i(o->x, o->y), current_view);
521
522    int i=0;
523    for (; i<o->total_objects(); i++)
524    {
525      game_object *other=o->get_object(i);
526      vec2i pos2 = the_game->GameToMouse(vec2i(other->x, other->y), current_view);
527      main_screen->Line(pos1, pos2, wm->bright_color());
528    }
529
530    for (i=0; i<o->total_lights(); i++)
531    {
532      light_source *l=o->get_light(i);
533      vec2i pos2 = the_game->GameToMouse(vec2i(l->x, l->y), current_view);
534      main_screen->Line(pos1, pos2, light_connection_color);
535    }
536
537      }
538    }
539
540    if (selected_object)
541    {
542      selected_object->picture_space(x1,y1,x2,y2);
543      vec2i pos1 = the_game->GameToMouse(vec2i(x1, y1), v);
544      vec2i pos2 = the_game->GameToMouse(vec2i(x2, y2), v);
545      main_screen->Rectangle(pos1, pos2, wm->bright_color());
546
547      pos1 = the_game->GameToMouse(vec2i(selected_object->x, selected_object->y), current_view);
548      for (int i=0; i<selected_object->total_objects(); i++)
549      {
550        game_object *other = selected_object->get_object(i);
551        pos2 = the_game->GameToMouse(vec2i(other->x, other->y), current_view);
552        main_screen->Line(pos1, pos2, light_connection_color);
553      }
554    }
555  }
556}
557
558static light_source *find_light(int32_t x, int32_t y)
559{
560  image *i=cache.img(light_buttons[0]);
561  int l=i->Size().x/2,h=i->Size().y/2;
562  for (light_source *f=first_light_source; f; f=f->next)
563  {
564    if (x>=f->x-l && x<=f->x+l && y>=f->y-h && y<=f->y+h)
565      return f;
566  }
567  return NULL;
568}
569
570
571void dev_controll::toggle_toolbar()
572{
573  if (tbw)
574  {
575    tbw_on=0;
576    prop->setd("toolbar x",tbw->m_pos.x);
577    prop->setd("toolbar y",tbw->m_pos.y);
578    wm->close_window(tbw);
579    tbw=NULL;
580  } else
581  {
582    tbw_on=1;
583    int setx=0;
584    for (int i=0; i<DEV_MODES; i++)
585    {
586      if (edit_mode==dev_mode_ids[i])
587        setx=i;
588      dev_mode_pict[i]=new cached_image(dev_mode_icon[i]);
589    }
590
591    tool_picker *tp=new tool_picker(0, 0,
592                         ID_NULL,
593                         5,(visual_object **)dev_mode_pict,dev_mode_ids,DEV_MODES,
594                        pal,pal,NULL);
595    tbw=wm->CreateWindow(vec2i(prop->getd("toolbar x", -1),
596                               prop->getd("toolbar y", -1)), vec2i(-1), tp);
597    tp->set_x(setx,tbw->m_surf);
598  }
599}
600
601void dev_controll::toggle_show_menu()
602{
603    if(show_menu)
604    {
605        show_menu_on = 0;
606        prop->setd("layer x", show_menu->m_pos.x);
607        prop->setd("layer y", show_menu->m_pos.y);
608        wm->close_window(show_menu);
609        show_menu = NULL;
610        return;
611    }
612
613    show_menu_on = 1;
614
615    button *lnb, *lb, *cb, *bb, *bdb, *fb;
616
617    lnb = new button(0, 100, SHOW_LINKS, symbol_str("l_links"), NULL);
618    if(dev & DRAW_LINKS)
619        lnb->push();
620    lb = new button(0, 80, SHOW_LIGHT, symbol_str("l_light"), lnb);
621    if(dev & DRAW_LIGHTS)
622        lb->push();
623    cb = new button(0, 60, SHOW_CHARACTERS, symbol_str("l_char"), lb);
624    if(dev & DRAW_PEOPLE_LAYER)
625        cb->push();
626    bb = new button(0, 40, SHOW_BACKGROUND, symbol_str("l_back"), cb);
627    if(dev & DRAW_BG_LAYER)
628        bb->push();
629    bdb = new button(0, 20, SHOW_FOREGROUND_BOUND, symbol_str("l_bound"), bb);
630    if(dev & DRAW_FG_BOUND_LAYER)
631        bdb->push();
632    fb = new button(0, 0, SHOW_FOREGROUND, symbol_str("l_fore"), bdb);
633    if(dev & DRAW_FG_LAYER)
634        fb->push();
635
636    show_menu = wm->CreateWindow(vec2i(prop->getd("layer x", -1),
637                                       prop->getd("layer y", -1)), vec2i(-1),
638                                 fb, symbol_str(symbol_str("SHOW?")));
639}
640
641char **listable_objs=NULL;
642int total_listable;
643
644void dev_controll::toggle_omenu()
645{
646    if(omenu)
647    {
648        omenu_on = 0;
649        prop->setd("objects x", omenu->m_pos.x);
650        prop->setd("objects y", omenu->m_pos.y);
651        wm->close_window(omenu);
652        omenu = NULL;
653        free(listable_objs);
654        listable_objs = NULL;
655        return;
656    }
657
658    omenu_on = 1;
659    total_listable = 0;
660
661    int i, c;
662
663    for(i = 0; i < total_objects; i++)
664        if(!figures[i]->get_cflag(CFLAG_UNLISTABLE))
665            total_listable++;
666    listable_objs = (char **)malloc(sizeof(char *) * total_listable);
667
668    for(i = 0, c = 0; i < total_objects; i++)
669        if(!figures[i]->get_cflag(CFLAG_UNLISTABLE))
670        {
671            listable_objs[c] = object_names[i];
672            c++;
673        }
674
675    omenu = wm->CreateWindow(vec2i(prop->getd("objects x", 0),
676                                   prop->getd("objects y", 0)), vec2i(-1),
677                             new pick_list(0, 0, DEV_CREATE,
678                                           yres / wm->font()->Size().y / 2,
679                                           listable_objs, total_listable, 0,
680                                           NULL, cache.img(window_texture)));
681}
682
683static int get_omenu_item(int x)
684{
685  for (int i=0; i<total_objects; i++)
686    if (listable_objs[x]==object_names[i])
687      return i;
688  return 0;
689}
690
691void dev_controll::toggle_pmenu()
692{
693    if(pmenu)
694    {
695        pmenu_on = 0;
696        prop->setd("pal x", pmenu->m_pos.x);
697        prop->setd("pal y", pmenu->m_pos.y);
698        wm->close_window(pmenu);
699        pmenu = NULL;
700        free(pwin_list);
701        return;
702    }
703
704    if(!total_pals)
705    {
706        the_game->show_help(symbol_str("no_pals"));
707        return;
708    }
709
710    pmenu_on = 1;
711
712    pwin_list = (char **)malloc(total_pals * sizeof(char *));
713    for(int i = 0; i < total_pals; i++)
714        pwin_list[i] = pal_wins[i]->name;
715
716    pmenu = wm->CreateWindow(vec2i(prop->getd("pal x", 0),
717                                   prop->getd("pal y", -1)), vec2i(-1),
718                             new pick_list(0, 0, DEV_PALETTE,
719                                           yres / wm->font()->Size().y / 2,
720                                           pwin_list, total_pals, 0, NULL,
721                                           cache.img(window_texture)));
722}
723
724
725void dev_controll::toggle_fgw()
726{
727    if(forew)
728    {
729        forew_on = 1;
730        prop->setd("fore x", forew->m_pos.x);
731        prop->setd("fore y", forew->m_pos.y);
732        wm->close_window(forew);
733        forew = NULL;
734        return;
735    }
736
737    /* FIXME: shouldn't this be 1? */
738    forew_on = 0;
739    int maxh = (yres - 25) / (the_game->ftile_height() / fg_scale);
740
741    /* FIXME: previous code had 1 instead of 0, investigate */
742    tile_picker *f_tp = new tile_picker(0, 0, DEV_FG_PICKER, SPEC_FORETILE,
743                                        fg_scale, maxh, fg_w, NULL);
744    f_tp->reverse();
745
746    forew = wm->CreateWindow(vec2i(prop->getd("fore x", -30),
747                                   prop->getd("fore y", 0)),
748                             vec2i(-1), f_tp,symbol_str("l_fg"));
749}
750
751void dev_controll::toggle_music_window()
752{
753/*  if (!music_window)
754  {
755    music_window=wm->CreateWindow(vec2i(-1, 30), vec2i(0, 0),
756             new pick_list(0,0,DEV_MUSIC_PICKLIST,10,song_list,total_songs,0,NULL));
757    wm->fnt->put_string(music_window->m_surf,0,1,"songs");
758  } else
759  {
760    wm->close_window(music_window);
761    music_window=NULL;
762  }*/
763}
764
765void dev_controll::toggle_bgw()
766{
767    if(backw)
768    {
769        backw_on = 1;
770        prop->setd("back x", backw->m_pos.x);
771        prop->setd("back y", backw->m_pos.y);
772        wm->close_window(backw);
773        backw = NULL;
774        return;
775    }
776
777    /* FIXME: shouldn't this be 1? */
778    backw_on = 0;
779    int maxh = (yres - 25) / (the_game->btile_height() / bg_scale);
780
781    /* FIXME: previous code had 1 instead of 0, investigate */
782    tile_picker *f_tp = new tile_picker(0, 0, DEV_BG_PICKER, SPEC_BACKTILE,
783                                        bg_scale, maxh, bg_w, NULL);
784    forew = wm->CreateWindow(vec2i(prop->getd("back x", -30),
785                                   prop->getd("back y", 0)),
786                             vec2i(-1), f_tp,symbol_str("l_bg"));
787}
788
789void dev_controll::toggle_search_window()
790{
791    if(search_window)
792    {
793        searchw_on = 1;
794        prop->setd("searchw x", search_window->m_pos.x);
795        prop->setd("searchw y", search_window->m_pos.y);
796        prop->set("search name", search_window->read(ID_SEARCH_TEXT));
797        wm->close_window(search_window);
798        search_window = NULL;
799        search_object = NULL;
800        return;
801    }
802
803    int bw = cache.img(dev_forward)->Size().x;
804    /* FIXME: previous code had 1,1 instead of 0,0 -- investigate */
805    search_window = wm->CreateWindow(vec2i(prop->getd("searchw x", -30),
806                                           prop->getd("searchw y", 0)),
807                                     vec2i(-1),
808        new text_field(0, 0, ID_SEARCH_TEXT, "object name>",
809                       "***************************",
810                       prop->get("search name", ""),
811        new button(bw, wm->font()->Size().y + 5, ID_SEARCH_BACKWARD,
812                   cache.img(dev_backward),
813        new button(bw * 3, wm->font()->Size().y + 5, ID_SEARCH_FOREWARD,
814                   cache.img(dev_forward), NULL))), "SEARCH");
815
816    /* FIXME: shouldn't this be 1? */
817    searchw_on = 0;
818}
819
820int open_owin=0,open_fwin=0,open_bwin=0,start_edit=0,start_nodelay=0,start_doubled=0,start_mem=0;
821
822
823int get_option(char const *name);
824
825
826void dev_init(int argc, char **argv)
827{
828  scale_mult=1;
829  scale_div=1;
830  dev=0;
831  int i;
832  prop=new property_manager;
833  prop->load("defaults.prp");
834
835  for (i=1; i<argc; i++)
836  {
837    if (!strcmp(argv[i],"-edit"))
838    {
839      dev|=EDIT_MODE;
840      start_edit=1;
841      start_running=1;
842      disable_autolight=1;
843      if (get_option("-2"))
844      {
845        printf("%s\n",symbol_str("no2"));
846        exit(0);
847      }
848    }
849    else if (!strcmp(argv[i],"-fwin"))
850      open_fwin=1;
851    else if (!strcmp(argv[i],"-show_mem"))
852      start_mem=1;
853    else if (!strcmp(argv[i],"-bwin"))
854      open_bwin=1;
855    else if (!strcmp(argv[i],"-owin"))
856      open_owin=1;
857    else if (!strcmp(argv[i],"-nodelay"))
858      start_nodelay=1;
859// AK : NOTE: Commented this out as it causes a conflict
860/*    else if (!strcmp(argv[i],"-scale"))
861    {
862      i++;
863      scale_mult=atoi(argv[i++]);
864      scale_div=atoi(argv[i]);
865    }*/
866    else if (!strcmp(argv[i],"-f"))
867    {
868      i++;
869      strncpy(level_file, argv[i], sizeof(level_file) - 1);
870      level_file[sizeof(level_file) - 1] = '\0';
871    } else if (!strcmp(argv[i],"-2"))
872      start_doubled=1;
873    else if (!strcmp(argv[i],"-demo"))
874      demo_start=1;
875
876  }
877
878  if (get_option("-no_autolight"))
879    disable_autolight=0;
880
881  if ((get_option("-size") || get_option("-vmode")) && !start_edit)
882  {
883    printf("%s\n",symbol_str("no_hirez"));
884    exit(0);
885  }
886
887  fg_reversed=prop->getd("fg_reversed",0);
888  mouse_scrolling=prop->getd("mouse_scrolling",0);
889  palettes_locked=prop->getd("palettes_locked",0);
890  view_shift_disabled=prop->getd("view_shift_disabled",0);
891  fps_on=prop->getd("fps_on",0);
892  show_names=prop->getd("show_names",0);
893  raise_all=prop->getd("raise_all",0);
894}
895
896static pmenu *make_menu(int x, int y);
897
898
899dev_controll::dev_controll()
900{
901  area_win=NULL;
902  current_area=NULL;
903  fg_w=bg_w=1;
904  commandw=NULL;
905  bg_scale=fg_scale=1;
906  pal_wins=NULL;
907  total_pals=0;
908  state=DEV_SELECT;
909  aiw=NULL;
910  edit_light=NULL;
911  selected_light=NULL;
912
913  tbw=NULL;
914  modew=NULL;
915  link_object=NULL;
916  selected_object=NULL;
917  edit_object=NULL;
918  ai_object=NULL;
919  search_object = NULL;
920  oedit=NULL;
921  forew=NULL;
922  backw=NULL;
923  omenu=NULL;
924  ledit=NULL;
925  pmenu=NULL;
926  lightw=NULL;
927  search_window=NULL;
928  show_menu=NULL;
929  music_window=NULL;
930  ambw=NULL;
931  load_dev_icons();
932
933  if (open_owin) toggle_omenu();
934  if (open_fwin) toggle_fgw();
935  if (open_bwin) toggle_bgw();
936  if (start_nodelay) the_game->toggle_delay();
937  yellow=pal->find_closest(255,255,0);
938  if (start_edit)
939  {
940    the_game->load_level(level_file);
941    the_game->draw();
942  }
943
944  dev_console=new dev_term(50,18,this);
945  if (start_edit)
946    dev_menu=make_menu(0,yres-wm->font()->Size().y-5);
947
948  if (get_option("-nolight"))
949    dev=dev^DRAW_LIGHTS;
950}
951
952
953void dev_controll::set_state(int new_state)
954{
955  if (start_doubled && new_state==RUN_STATE && !small_render)
956    double_render();
957}
958
959void dev_controll::load_stuff()
960{
961  if (dev & EDIT_MODE)
962  {
963    char prog[100];
964    char const *cs;
965    strcpy(prog,"(compile-file \"edit.lsp\")");
966    cs=prog;
967    LObject *p = LObject::Compile(cs);
968    l_user_stack.push(p);
969    p->Eval();
970    l_user_stack.pop(1);
971    for (int i=0; i<total_pals; i++)
972      pal_wins[i]->close_window();
973  }
974
975}
976
977void dev_controll::do_command(char const *command, Event &ev)
978{
979  char fword[50];
980  char const *st;
981  int l,h,x,y,i;
982  if (command[0]=='(')            // is this a lisp command?
983  {
984    LObject::Compile(command)->Eval();
985    return ;
986  }
987
988  sscanf(command,"%s",fword);
989  for (st=command; *st && *st!=' '; st++);
990  if (*st) st++;
991  if (!strcmp(fword,"active"))
992  {
993    if (current_level && current_level->first_active_object())
994    {
995      game_object *o=current_level->first_active_object();
996      while (o)
997      {
998    dprintf("%s %d %d %d %d\n",object_names[o->otype],o->x,o->y,
999        figures[o->otype]->rangex,
1000        figures[o->otype]->rangey
1001        );
1002    o=o->next_active;
1003      }
1004    }
1005  }
1006
1007  if (!strcmp(fword,"clear_weapons"))
1008  {
1009    view *f=NULL;
1010    for (f=player_list; f; f=f->next)
1011    {
1012      int i;
1013      for (i=0; i<total_weapons; i++)
1014    f->weapons[i]=-1;
1015
1016      if (total_weapons)
1017        f->weapons[0]=0;
1018    }
1019  }
1020
1021  if (!strcmp(fword,"reload"))
1022  {
1023    if (current_level && player_list && player_list->focus)
1024    {
1025      edit_object=selected_object=NULL;
1026      int32_t cx=player_list->focus->x,cy=player_list->focus->y;
1027
1028      // save the old weapon array
1029      int32_t *w=(int32_t *)malloc(total_weapons*sizeof(int32_t));
1030      memcpy(w,player_list->weapons,total_weapons*sizeof(int32_t));
1031
1032      char tmp[100];
1033      strcpy(tmp,current_level->name());
1034      the_game->load_level(tmp);
1035      current_level->unactivate_all();
1036
1037      if (main_screen)  // don't draw if graphics haven't been setup yet.
1038        the_game->draw();
1039      player_list->reset_player();
1040      player_list->focus->x=cx;
1041      player_list->focus->y=cy;
1042
1043      memcpy(player_list->weapons,w,total_weapons*sizeof(int32_t));
1044      free(w);
1045
1046      the_game->need_refresh();
1047    }
1048  }
1049
1050  if (!strcmp(fword,"unchop"))
1051  {
1052    vec2i tile = the_game->GetBgTile(dlast);
1053    if (tile.x>=0 && tile.y>=0)
1054    {
1055      if (sscanf(command,"%s%d%d",fword,&l,&h)==3)
1056      {
1057    dprintf("unchopped %dx%d to ",l,h);
1058    l=(l+the_game->btile_width()-1)/the_game->btile_width();
1059    h=(h+the_game->btile_height()-1)/the_game->btile_height();
1060    for (y=0,i=cur_bg; y<h; y++)
1061          for (x=0; x<l; x++)
1062            the_game->PutBg(tile + vec2i(x, y), i++);
1063    dprintf("%dx%d\n",l,h);
1064      } else dprintf(symbol_str("unchop1"));
1065
1066    }
1067  }
1068  if (!strcmp(fword,"center"))
1069  {
1070    view *v=the_game->first_view;
1071    for (; v; v=v->next)
1072    {
1073      v->pan_x=0;
1074      v->pan_y=0;
1075    }
1076    the_game->need_refresh();
1077  }
1078
1079  if (!strcmp(fword,"size"))
1080  {
1081    int l,w;
1082    if (sscanf(command,"%s%d%d",fword,&l,&w)==3)
1083    {
1084      current_level->set_size(l,w);
1085      dprintf("level is now %dx%d\n",l,w);
1086    } else dprintf(symbol_str("size1"));
1087
1088
1089  }
1090  if (!strcmp(fword,"name"))
1091  {
1092    while (*command && *command!=' ') command++;
1093    if (*command)
1094      current_level->set_name(command+1);
1095    dprintf(symbol_str("name_now"),current_level->name());
1096  }
1097  if (!strcmp(fword,"set_first_level"))
1098  {
1099    strcpy(level_file,st);
1100    dprintf("first level will be '%s'\n",level_file);
1101  }
1102
1103  if (!strcmp(fword,"load"))
1104  {
1105    if (!strcmp(st,"STARTING_LEVEL"))
1106      st=level_file;
1107
1108    dprintf("loading '%s'\n",st);
1109    the_game->load_level(st);
1110    current_level->unactivate_all();
1111
1112    the_game->need_refresh();
1113  }
1114
1115  if (!strcmp(fword,"mem"))
1116  {
1117    if (st[0])
1118      show_char_mem(st);
1119    else show_mem();
1120  }
1121
1122  if (!strcmp(fword,"esave"))
1123  {
1124    dprintf(symbol_str("esave"));
1125    save();
1126  }
1127
1128  if (!strcmp(fword,"delete"))
1129  {
1130    if (selected_object)
1131    {
1132      if (!(dev&EDIT_MODE) && current_level->is_attacker(selected_object))
1133        the_game->show_help(symbol_str("nd_player"));
1134      else
1135      {
1136    if (selected_object->controller())
1137      the_game->show_help(symbol_str("nd_player"));
1138    else
1139    {
1140      current_level->delete_object(selected_object);
1141      if (S_DELETE_SND>0) cache.sfx(S_DELETE_SND)->play(sfx_volume/2);
1142      selected_object=NULL;
1143    }
1144      }
1145    } else if (selected_light)
1146    {
1147      if (!edit_light)
1148      {
1149    if (current_level)
1150    {
1151          current_level->remove_light(selected_light);
1152      if (S_DELETE_SND>0) cache.sfx(S_DELETE_SND)->play(sfx_volume/2);
1153    }
1154    else
1155          delete_light(selected_light);
1156    selected_light=NULL;
1157      }
1158    } else the_game->show_help(symbol_str("d_nosel"));
1159    the_game->need_refresh();
1160  }
1161
1162  if (!strcmp(fword,"create"))
1163  {
1164    char oname[100];
1165    sscanf(command,"%s%s",fword,oname);       // read the type of object to create
1166    int x,t=-1;
1167    for (x=0; x<total_objects; x++)             // find the object type by name
1168       if (!strcmp(object_names[x],oname))
1169         t=x;
1170
1171    if (t>=0)                                 // did we find it?
1172    {
1173      vec2i pos = the_game->MouseToGame(dlast);
1174      edit_object=create(t, pos.x, pos.y);
1175      current_level->add_object(edit_object);
1176      the_game->need_refresh();
1177      last_created_type=t;
1178    } else
1179    {
1180      sprintf(fword,"No such object type : %s\n",oname);
1181      the_game->show_help(fword);
1182    }
1183  }
1184
1185  if (!strcmp(fword,"move"))
1186  {
1187    if (selected_object)
1188      edit_object=selected_object;
1189
1190    if (edit_object)
1191      state=DEV_MOVE_OBJECT;
1192    else the_game->show_help("No object selected");
1193
1194  }
1195  if (!strcmp(fword,"move_light"))
1196  {
1197    if (selected_light)
1198      edit_light=selected_light;
1199
1200    if (edit_light)
1201      state=DEV_MOVE_LIGHT;
1202    else the_game->show_help("No light selected");
1203
1204  }
1205
1206
1207  if (!strcmp(fword,"clear_auto"))
1208  {
1209    int32_t i,j;
1210    for (i=0; i<current_level->foreground_width(); i++)
1211      for (j=0; j<current_level->foreground_height(); j++)
1212        current_level->clear_fg(i,j);
1213  }
1214
1215  if (!strcmp(fword,"fg_select"))
1216  {
1217    vec2i tile = the_game->GetFgTile(dlast);
1218    if (tile.x >= 0 && tile.y >= 0 &&
1219        tile.x < current_level->foreground_width() &&
1220        tile.y < current_level->foreground_height())
1221    {
1222      cur_fg=current_level->GetFg(tile);
1223      if (forew)
1224    ((tile_picker *)forew->read(DEV_FG_PICKER))->recenter(forew->m_surf);
1225      the_game->need_refresh();
1226    }
1227  }
1228
1229  if (!strcmp(fword,"toggle_fg_raise"))
1230  {
1231    vec2i tile = the_game->GetFgTile(dlast);
1232    if (tile.x >= 0 && tile.y >= 0 &&
1233        tile.x < current_level->foreground_width() &&
1234        tile.y < current_level->foreground_height())
1235      current_level->fg_set_raised(tile.x, tile.y,!current_level->fg_raised(tile.x,tile.y));
1236  }
1237
1238  if (!strcmp(fword,"fg_add"))
1239  {
1240    int x;
1241    if (sscanf(st,"%d",&x))
1242    {
1243      cur_fg++;
1244      if (cur_fg<0) cur_fg=0;
1245      if (cur_fg>=nforetiles) cur_fg=nforetiles-1;
1246
1247      if (forew)
1248    ((tile_picker *)forew->read(DEV_FG_PICKER))->recenter(forew->m_surf);
1249    }
1250  }
1251
1252  if (!strcmp(fword,"restart"))
1253  {
1254    current_level->restart();
1255  }
1256  if (!strcmp(fword,"quit"))
1257  {
1258    the_game->end_session();
1259  }
1260
1261  if (!strcmp(fword,"to_front"))
1262  {
1263    game_object *which=selected_object;
1264    if (!selected_object) which=edit_object;
1265    if (which)
1266      current_level->to_front(which);
1267    else the_game->show_help(symbol_str("forward?"));
1268  }
1269
1270  if (!strcmp(fword,"to_back"))
1271  {
1272    game_object *which=selected_object;
1273    if (!selected_object) which=edit_object;
1274    if (which)
1275      current_level->to_back(which);
1276    else the_game->show_help(symbol_str("back?"));
1277  }
1278
1279  if (!strcmp(fword,"set_aitype"))
1280  {
1281    game_object *which=selected_object;
1282    if (!selected_object) which=edit_object;
1283    if (which)
1284    {
1285      int x;
1286      if (*st && sscanf(st,"%d",&x)!=EOF)
1287        which->change_aitype(x);
1288      else
1289      {
1290    switch (ev.key)
1291    {
1292      case '0' : which->change_aitype(0); break;
1293      case '1' : which->change_aitype(1); break;
1294      case '2' : which->change_aitype(2); break;
1295      case '3' : which->change_aitype(3); break;
1296      case '4' : which->change_aitype(4); break;
1297      case '5' : which->change_aitype(5); break;
1298      case '6' : which->change_aitype(6); break;
1299      case '7' : which->change_aitype(7); break;
1300      case '8' : which->change_aitype(8); break;
1301      case '9' : which->change_aitype(9); break;
1302      case ')' : which->change_aitype(10); break;
1303      case '!' : which->change_aitype(11); break;
1304      case '@' : which->change_aitype(12); break;
1305      case '#' : which->change_aitype(13); break;
1306      case '$' : which->change_aitype(14); break;
1307      case '%' : which->change_aitype(15); break;
1308      case '^' : which->change_aitype(16); break;
1309      case '&' : which->change_aitype(17); break;
1310      case '*' : which->change_aitype(18); break;
1311      case '(' : which->change_aitype(19); break;
1312    }
1313      }
1314      the_game->need_refresh();
1315    }
1316    else the_game->show_help(symbol_str("aitype"));
1317  }
1318}
1319
1320
1321void dev_controll::toggle_light_window()
1322{
1323    if(lightw)
1324    {
1325        prop->setd("light create x", lightw->m_pos.x);
1326        prop->setd("light create y", lightw->m_pos.y);
1327        prop->setd("light create w", atoi(lightw->read(DEV_LIGHTW)));
1328        prop->setd("light create h", atoi(lightw->read(DEV_LIGHTH)));
1329        prop->setd("light create r1", atoi(lightw->read(DEV_LIGHTR1)));
1330        prop->setd("light create r2", atoi(lightw->read(DEV_LIGHTR2)));
1331        wm->close_window(lightw);
1332        lightw = NULL;
1333        return;
1334    }
1335
1336    int bh = 16 + 6, bw = 20 + 6, th = wm->font()->Size().y + 4;
1337
1338    lightw = wm->CreateWindow(vec2i(prop->getd("light create x", 0),
1339                                    prop->getd("light create y", 0)), vec2i(-1),
1340        new button_box(0, 0, DEV_LIGHT_BUTTON_BOX, 1,
1341            new button(bw * 0, bh * 0, DEV_LIGHT0, cache.img(light_buttons[0]),
1342            new button(bw * 1, bh * 0, DEV_LIGHT1, cache.img(light_buttons[1]),
1343            new button(bw * 2, bh * 0, DEV_LIGHT2, cache.img(light_buttons[2]),
1344            new button(bw * 0, bh * 1, DEV_LIGHT3, cache.img(light_buttons[3]),
1345            new button(bw * 1, bh * 1, DEV_LIGHT4, cache.img(light_buttons[4]),
1346            new button(bw * 2, bh * 1, DEV_LIGHT5, cache.img(light_buttons[5]),
1347            new button(bw * 0, bh * 2, DEV_LIGHT6, cache.img(light_buttons[6]),
1348            new button(bw * 1, bh * 2, DEV_LIGHT7, cache.img(light_buttons[7]),
1349            new button(bw * 2, bh * 2, DEV_LIGHT8, cache.img(light_buttons[8]),
1350            new button(bw * 0, bh * 3, DEV_LIGHT9, cache.img(light_buttons[9]),
1351            new button(bw * 1, bh * 3, DEV_AMBIENT, cache.img(light_buttons[11]),
1352            NULL))))))))))),
1353        new text_field(0, bh * 4, DEV_LIGHTW, "W ", "******",
1354                       prop->getd("light create w", 0),
1355        new text_field(0, bh * 4 + th * 1, DEV_LIGHTH, "H ", "******",
1356                       prop->getd("light create h", 0),
1357        new text_field(0, bh * 4 + th * 2, DEV_LIGHTR1, "R1", "******",
1358                       prop->getd("light create r1", 1),
1359        new text_field(0, bh * 4 + th * 3, DEV_LIGHTR2, "R2", "******",
1360                       prop->getd("light create r2", 100), NULL))))),
1361        symbol_str("l_light"));
1362}
1363
1364void dev_controll::make_ai_window(game_object *o)
1365{
1366  ai_object=o;
1367  int th=wm->font()->Size().y+4,wl = 0, wh = 20;
1368  if (figures[o->otype]->total_fields)
1369  {
1370    int maxl=0;
1371    int i=0;
1372    for (; i<figures[o->otype]->total_fields; i++)
1373      if( strlen(figures[o->otype]->fields[i]->descript_name) > (unsigned)maxl )
1374        maxl=strlen(figures[o->otype]->fields[i]->descript_name);
1375
1376    int owh=wh;
1377    ifield *first=NULL,*last=NULL;
1378    for (i=0; i<figures[o->otype]->total_fields; i++)
1379    {
1380      char tmp[200];
1381      strcpy(tmp,figures[o->otype]->fields[i]->descript_name);
1382      for (int j=maxl-strlen(figures[o->otype]->fields[i]->descript_name); j; j--)
1383        strcat(tmp," ");
1384      int er;
1385      ifield *p=new text_field(wl,wh,ID_NULL,tmp,"######",
1386                   (double)o->get_var_by_name(figures[o->otype]->fields[i]->real_name,er),
1387                   NULL);
1388      if (last)
1389        last->next=p;
1390      else
1391        first=p;
1392      last=p;
1393      wh+=th;
1394    }
1395    aiw=wm->CreateWindow(vec2i(prop->getd("ai x",0), prop->getd("ai y",0)),
1396                         vec2i(-1),
1397       new button(wl,owh-20,DEV_AI_OK,cache.img(dev_ok),first),"ai");
1398
1399  }
1400  else
1401  {
1402    aiw=wm->CreateWindow(vec2i(prop->getd("ai x", 0), prop->getd("ai y", 0)),
1403                         vec2i(-1),
1404       new button(wl,wh-20,DEV_AI_OK,cache.img(dev_ok),
1405       new text_field(wl,wh+th*0, DEV_AI_XVEL,    symbol_str("ai_xvel"),"#####",(double)o->xvel(),
1406       new text_field(wl,wh+th*1, DEV_AI_YVEL,    symbol_str("ai_yvel"),"#####",(double)o->yvel(),
1407       new text_field(wl,wh+th*2, DEV_AI_XACEL,   symbol_str("ai_xacel"),"#####",(double)o->xacel(),
1408       new text_field(wl,wh+th*3, DEV_AI_YACEL,   symbol_str("ai_yacel"),"#####",(double)o->yacel(),
1409       new text_field(wl,wh+th*4, DEV_AI_STTIME,  symbol_str("ai_stime"),"####",(double)o->aistate_time(),
1410       new text_field(wl,wh+th*5, DEV_AI_GRAVITY, symbol_str("ai_gravity"),"####",(double)o->gravity(),
1411       new text_field(wl,wh+th*6, DEV_AI_HEALTH,  symbol_str("ai_health"),"####",(double)o->hp(),
1412       new text_field(wl,wh+th*7, DEV_AI_MORPHPR, symbol_str("ai_morph"),"####",(double)o->mp(),
1413       new text_field(wl,wh+th*8, DEV_AI_TYPE,    symbol_str("ai_type"),"####",(double)o->aitype(),
1414       new text_field(wl,wh+th*9,DEV_AI_STATE,    symbol_str("ai_state"),"####",(double)o->aistate(),
1415       new text_field(wl,wh+th*10,DEV_AI_FADE,    symbol_str("ai_fade"),"####",(double)o->fade_count(),
1416              NULL)))))))))))),"ai");
1417  }
1418
1419  wm->grab_focus(aiw);
1420}
1421
1422void dev_controll::notify_deleted_light(light_source *l)
1423{
1424  if (l==edit_light)
1425  {
1426    if (ledit)
1427    {
1428      prop->setd("ledit x",ledit->m_pos.x);
1429      prop->setd("ledit y",ledit->m_pos.y);
1430      wm->close_window(ledit); ledit=NULL;
1431    }
1432    edit_light=NULL;
1433  }
1434  if (l==selected_light)
1435    selected_light=NULL;
1436}
1437
1438void dev_controll::notify_deleted_object(game_object *o)
1439{
1440  if (o==edit_object)
1441  {
1442    state=DEV_SELECT;
1443    close_oedit_window();
1444  }
1445
1446  if (o==ai_object)
1447    close_ai_window();
1448  if (o==search_object)
1449  { if (search_window)
1450      toggle_search_window();
1451    search_object=NULL;
1452  }
1453  if (o==link_object)
1454    link_object=NULL;
1455  if (o==selected_object)
1456  {
1457    selected_object=NULL;
1458    state=DEV_SELECT;
1459  }
1460
1461}
1462
1463void dev_controll::close_ai_window()
1464{
1465  if (aiw)
1466  {
1467    game_object *o=ai_object;
1468    int32_t x;
1469    if (o)
1470    {
1471      if (figures[o->otype]->total_fields)
1472      {
1473    ifield *f=aiw->inm->get(DEV_AI_OK)->next;
1474    for (int i=0; i<figures[o->otype]->total_fields; i++)
1475    {
1476      x=atoi(f->read());
1477      char *v=figures[o->otype]->fields[i]->real_name;
1478      int er;
1479      if (o->get_var_by_name(v,er)!=x)
1480      o->set_var_by_name(v,x);
1481      f=f->next;
1482    }
1483      }
1484      else
1485      {
1486    x=atoi(aiw->read(DEV_AI_XVEL)); if (x!=o->xvel()) o->set_xvel(x);
1487    x=atoi(aiw->read(DEV_AI_YVEL)); if (x!=o->yvel()) o->set_yvel(x);
1488
1489    x=atoi(aiw->read(DEV_AI_XACEL)); if (x!=o->xacel()) o->set_xacel(x);
1490    x=atoi(aiw->read(DEV_AI_YACEL)); if (x!=o->yacel()) o->set_yacel(x);
1491
1492    x=atoi(aiw->read(DEV_AI_STTIME)); if (x!=o->aistate_time()) o->set_aistate_time(x);
1493    x=atoi(aiw->read(DEV_AI_GRAVITY)); if (x!=o->gravity()) o->set_gravity(x);
1494
1495    x=atoi(aiw->read(DEV_AI_HEALTH)); if (x!=o->hp()) o->set_hp(x);
1496    x=atoi(aiw->read(DEV_AI_MORPHPR)); if (x!=o->mp()) o->set_mp(x);
1497
1498    x=atoi(aiw->read(DEV_AI_TYPE)); if (x!=o->aitype()) o->set_aitype(x);
1499    x=atoi(aiw->read(DEV_AI_STATE)); if (x!=o->aistate()) o->set_aistate(x);
1500    x=atoi(aiw->read(DEV_AI_FADE)); if (x!=o->fade_count()) o->set_fade_count(x);
1501      }
1502    }
1503    prop->setd("ai x",aiw->m_pos.x);
1504    prop->setd("ai y",aiw->m_pos.y);
1505    wm->close_window(aiw);
1506    aiw=NULL;
1507    ai_object=NULL;
1508    the_game->need_refresh();
1509  }
1510}
1511
1512
1513void dev_controll::area_handle_input(Event &ev)
1514{
1515
1516  if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
1517  {
1518    vec2i pos = the_game->MouseToGame(last_demo_mpos);
1519    if (!current_level) return ;
1520    current_area=current_level->area_list=new area_controller(pos.x, pos.y,
1521                                  the_game->ftile_width(),
1522                                  the_game->ftile_height(),
1523                                  current_level->area_list);
1524    the_game->need_refresh();
1525    state=DEV_DRAG_AREA_BOTTOM;
1526  }
1527}
1528
1529void dev_controll::close_area_win(int read_values)
1530{
1531  if (area_win)
1532  {
1533    prop->setd("area_box x",area_win->m_pos.x);
1534    prop->setd("area_box y",area_win->m_pos.y);
1535
1536    if (current_area && read_values)
1537    {
1538      current_area->ambient=atoi(area_win->read(DEV_AREA_AMBIENT));
1539      current_area->ambient_speed=atoi(area_win->read(DEV_AREA_AMBIENT_SPEED));
1540      current_area->view_xoff=atoi(area_win->read(DEV_AREA_VIEW_XOFF));
1541      current_area->view_yoff=atoi(area_win->read(DEV_AREA_VIEW_YOFF));
1542      current_area->view_xoff_speed=atoi(area_win->read(DEV_AREA_VIEW_XOFF_SPEED));
1543      current_area->view_yoff_speed=atoi(area_win->read(DEV_AREA_VIEW_YOFF_SPEED));
1544    }
1545    wm->close_window(area_win);
1546    area_win=NULL;
1547  }
1548}
1549
1550void dev_controll::pick_handle_input(Event &ev)
1551{
1552  area_controller *find=NULL;
1553  int find_top=0;
1554  if (!current_level) return;
1555  if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
1556  {
1557    vec2i m = last_demo_mpos;
1558    view *v = the_game->GetView(m);
1559    for (area_controller *a=current_level->area_list; a; a=a->next)
1560    {
1561      vec2i pos1 = the_game->GameToMouse(vec2i(a->x, a->y), v);
1562      vec2i pos2 = the_game->GameToMouse(vec2i(a->x + a->w, a->y + a->h), v);
1563      if (abs(pos1.x - m.x) < 2 && abs(pos1.y - m.y) < 2)
1564      { find = a; find_top = 1; }
1565      else if (abs(pos2.x - m.x) < 2 && abs(pos2.y - m.y) < 2)
1566      { find = a; find_top = 0; }
1567    }
1568
1569    time_marker now;
1570    int dc=now.diff_time(&last_area_click)<0.5;
1571    last_area_click.get_time();
1572    if (find && current_area && dc)
1573    {
1574      if (area_win) close_area_win(0);
1575      int wl=0,wh=0,th=wm->font()->Size().y+12,bw=cache.img(dev_ok)->Size().x+10;
1576      area_win=wm->CreateWindow(vec2i(prop->getd("area_box x", 0),
1577                                      prop->getd("area_box y", 0)), vec2i(-1),
1578                  new button(wl+bw*0,wh-8,DEV_AREA_OK,cache.img(dev_ok),
1579                  new button(wl+bw*1,wh-8,DEV_AREA_DELETE,cache.img(dev_del),
1580
1581                  new text_field(wl,wh+th*1,DEV_AREA_AMBIENT,         symbol_str("a_ambient"),"******",current_area->ambient,
1582                              new text_field(wl,wh+th*2,DEV_AREA_AMBIENT_SPEED,   symbol_str("a_aspeed"),"******",current_area->ambient_speed,
1583                              new text_field(wl,wh+th*3,DEV_AREA_VIEW_XOFF,       symbol_str("a_view_xoff"),"******",current_area->view_xoff,
1584                              new text_field(wl,wh+th*4,DEV_AREA_VIEW_YOFF,       symbol_str("a_view_yoff"),"******",current_area->view_yoff,
1585                              new text_field(wl,wh+th*5,DEV_AREA_VIEW_XOFF_SPEED, symbol_str("a_view_xspd"),"******",current_area->view_xoff_speed,
1586                              new text_field(wl,wh+th*6,DEV_AREA_VIEW_YOFF_SPEED, symbol_str("a_view_yspd"),"******",current_area->view_yoff_speed,
1587                         NULL)))))))));
1588    } else if (find)
1589    {
1590      current_area=find;
1591      current_area->active=1;
1592      if (find_top)
1593      state=DEV_DRAG_AREA_TOP;
1594      else state=DEV_DRAG_AREA_BOTTOM;
1595      the_game->need_refresh();
1596    } else if (current_area)
1597    {
1598      current_area->active=0;
1599      current_area=NULL;
1600      the_game->need_refresh();
1601    }
1602  }
1603}
1604
1605void dev_controll::close_oedit_window()
1606{
1607  if (oedit)
1608  {
1609    prop->setd("oedit x",oedit->m_pos.x);
1610    prop->setd("oedit y",oedit->m_pos.y);
1611    wm->close_window(oedit);
1612    oedit=NULL;
1613    edit_object=NULL;
1614  }
1615}
1616
1617int screen_shot_on=1;
1618int sshot_fcount=-1;
1619
1620void dev_controll::handle_event(Event &ev)
1621{
1622  int32_t x,y;
1623  if (link_object && (dlast.x!=last_link_x || dlast.y!=last_link_y))
1624  {
1625    last_link_x=dlast.x;
1626    last_link_y=dlast.y;
1627    the_game->need_refresh();
1628  }
1629
1630  if (dev_menu && dev_menu->handle_event(ev,main_screen)) return ;
1631
1632  if (!current_level) return ;
1633
1634  for (x=0; x<total_pals; x++)
1635    pal_wins[x]->handle_event(ev);
1636  if (ev.type==EV_MOUSE_MOVE)
1637    dlast = last_demo_mpos;
1638  if (dev_console && dev_console->handle_event(ev))
1639    return;
1640
1641  if (ev.type==EV_KEY && ev.key==JK_F2)
1642    write_PCX(main_screen,pal,"scrnshot.pcx");
1643  else if (ev.type==EV_KEY && ev.key==JK_F3)
1644  {
1645    char name[100];
1646    sprintf(name,"shot%04d.pcx",screen_shot_on++);
1647    write_PCX(main_screen,pal,name);
1648  } else if (ev.type==EV_KEY && ev.key==JK_F5)
1649  {
1650    if (sshot_fcount!=-1)
1651    {
1652      sshot_fcount=-1;
1653      the_game->show_help(symbol_str("seqs_off"));
1654    }
1655    else
1656    {
1657      sshot_fcount=0;
1658      the_game->show_help(symbol_str("seqs_on"));
1659    }
1660  }
1661
1662  switch (state)
1663  {
1664    case DEV_MOUSE_RELEASE :
1665    {
1666      if (!ev.mouse_button)
1667        state=DEV_SELECT;
1668    } break;
1669
1670    case DEV_CREATE_OBJECT :
1671    {
1672      if (!ev.mouse_button)
1673        state=DEV_MOVE_OBJECT;
1674    } break;
1675
1676
1677    case DEV_MOVE_OBJECT :
1678    {
1679      if (!edit_object)
1680      { state=DEV_SELECT; }
1681      else
1682      {
1683    if (ev.type==EV_MOUSE_MOVE)
1684    {
1685      vec2i pos = the_game->MouseToGame(last_demo_mpos);
1686      edit_object->x = snap_x(pos.x);
1687      edit_object->y = snap_y(pos.y);
1688      the_game->need_refresh();
1689    }
1690    else if (ev.mouse_button==1 && ev.window==NULL)
1691    {
1692      state=DEV_MOUSE_RELEASE;
1693      selected_object=edit_object=NULL;
1694    }
1695    if (ev.window==NULL && ev.type==EV_KEY && ev.key=='d')
1696    {
1697      int32_t xv=0,yv=100;
1698      edit_object->try_move(edit_object->x,edit_object->y,xv,yv,1);
1699      edit_object->y+=yv;
1700      state=DEV_SELECT;
1701      selected_object=edit_object=NULL;
1702    }
1703      }
1704    } break;
1705
1706
1707    case DEV_MOVE_LIGHT :
1708    {
1709      if (edit_light)
1710      {
1711    if (ev.type==EV_MOUSE_MOVE)
1712    {
1713      vec2i pos = the_game->MouseToGame(last_demo_mpos);
1714      edit_light->x = snap_x(pos.x);
1715      edit_light->y = snap_y(pos.y);
1716
1717      edit_light->calc_range();
1718      the_game->need_refresh();
1719    } else if (ev.type==EV_KEY)
1720    {
1721      int rd=0;
1722      switch (ev.key)
1723      {
1724        case '+' :
1725        {
1726          if (edit_light->type==9)
1727          {
1728        if (edit_light->inner_radius<64)
1729        { edit_light->inner_radius++; rd=1; }
1730          } else { edit_light->outer_radius++; rd=1; }
1731        } break;
1732        case '-' :
1733        {
1734          if (edit_light->type==9)
1735          {
1736        if (edit_light->inner_radius>0)
1737        { edit_light->inner_radius--; rd=1; }
1738          } else if (edit_light->outer_radius>edit_light->inner_radius+1)
1739          { edit_light->outer_radius--; rd=1; }
1740        } break;
1741        case JK_RIGHT :
1742        {
1743          if (edit_light->type==9)
1744          { edit_light->xshift++; rd=1; }
1745          else if (edit_light->xshift>0)
1746          { edit_light->xshift--; rd=1; }
1747        } break;
1748        case JK_LEFT :
1749        {
1750          if (edit_light->type==9)
1751          {
1752        if (edit_light->xshift>1)
1753        { edit_light->xshift--; rd=1; }
1754          }
1755          else
1756          { edit_light->xshift++; rd=1; }
1757        } break;
1758        case JK_UP :
1759        {
1760          if (edit_light->type==9)
1761          { edit_light->yshift++; rd=1; }
1762          else if (edit_light->yshift>0)
1763          { edit_light->yshift--; rd=1; }
1764        } break;
1765        case JK_DOWN :
1766        {
1767          if (edit_light->type==9)
1768          {
1769        if (edit_light->yshift>1)
1770        { edit_light->yshift--; rd=1; }
1771          }
1772          else
1773          { edit_light->yshift++; rd=1; }
1774        } break;
1775
1776      }
1777      if (rd)
1778      {
1779        edit_light->calc_range();
1780        the_game->need_refresh();
1781      }
1782
1783    }
1784      }
1785
1786      if ((ev.mouse_button==1 && ev.window==NULL) || !edit_light)
1787        state=DEV_MOUSE_RELEASE;
1788    } break;
1789
1790
1791    case DEV_DRAG_AREA_BOTTOM :
1792    {
1793      if (current_area)
1794      {
1795    vec2i pos = the_game->MouseToGame(last_demo_mpos);
1796    if (pos.x>current_area->x && pos.y>current_area->y)
1797    {
1798      if (pos.x-current_area->x!=current_area->w || pos.y-current_area->y!=current_area->h)
1799      {
1800        the_game->need_refresh();
1801        current_area->w=pos.x-current_area->x;
1802        current_area->h=pos.y-current_area->y;
1803      }
1804    }
1805    if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button)
1806    {
1807      current_area->active=0;
1808      state=DEV_SELECT;
1809    }
1810      }
1811    } break;
1812
1813    case DEV_DRAG_AREA_TOP :
1814    {
1815      if (current_area)
1816      {
1817    vec2i pos = the_game->MouseToGame(last_demo_mpos);
1818    if (pos.x<current_area->x+current_area->w && pos.y<current_area->y+current_area->h)
1819    {
1820      if (pos.x!=current_area->x || pos.y!=current_area->y)
1821      {
1822        the_game->need_refresh();
1823        current_area->x=pos.x;
1824        current_area->y=pos.y;
1825      }
1826    }
1827    if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button)
1828    {
1829      current_area->active=0;
1830      state=DEV_SELECT;
1831    }
1832      }
1833    } break;
1834
1835    case DEV_SELECT :
1836    {
1837      if (dev&EDIT_MODE)
1838      {
1839    game_object *old=selected_object;
1840    selected_object=NULL;
1841    if (ev.window==NULL)
1842    {
1843      vec2i pos = the_game->MouseToGame(last_demo_mpos);
1844
1845      if (!(dev & MAP_MODE))
1846      {
1847        if (dev&DRAW_PEOPLE_LAYER)
1848              selected_object=current_level->find_object(pos.x, pos.y);
1849        light_source *old_light=selected_light;
1850        selected_light = selected_object ? NULL : find_light(pos.x, pos.y);
1851        if (selected_light!=old_light)
1852          the_game->need_refresh();
1853      } else { selected_light=NULL; }
1854
1855      if (edit_mode==ID_DMODE_DRAW)
1856      {
1857        // FIXME: there is a bug here, the two if conditionals are the same
1858        if (ev.mouse_button==1 && !selected_object && !selected_light)
1859        {
1860          vec2i tile = the_game->GetFgTile(last_demo_mpos);
1861          if (tile.x>=0 && tile.y>=0 && tile.x<current_level->foreground_width() &&
1862          tile.y<current_level->foreground_height())
1863          current_level->PutFg(tile, raise_all ? make_above_tile(cur_fg) : cur_fg);
1864          the_game->need_refresh();
1865        } else if (ev.mouse_button==1 && !selected_object && !selected_light)
1866        {
1867          vec2i tile = the_game->GetBgTile(last_demo_mpos);
1868          if (tile.x>=0 && tile.y>=0 && tile.x<current_level->background_width() &&
1869          tile.y<current_level->background_height())
1870          current_level->PutBg(tile, cur_fg);
1871          the_game->need_refresh();
1872        }
1873      } else if (edit_mode==ID_DMODE_AREA)
1874        area_handle_input(ev);
1875      else if (edit_mode==ID_DMODE_PICK)
1876        pick_handle_input(ev);
1877    }
1878
1879    if (old!=selected_object)
1880        the_game->need_refresh();
1881
1882
1883    if (ev.mouse_button)
1884    {
1885      if (selected_object)
1886      {
1887        if (edit_object && edit_object!=selected_object)
1888             edit_object->add_object(selected_object);
1889
1890        if (oedit)
1891          close_oedit_window();
1892
1893        int bw=20+6,bh=16+6;
1894
1895        oedit=wm->CreateWindow(vec2i(prop->getd("oedit x", 0),
1896                                     prop->getd("oedit y", 0)), vec2i(-1),
1897            new button_box(0,0,ID_NULL,1,
1898                new button(bw*0,0,DEV_OEDIT_OK,cache.img(dev_ok),
1899                new button(bw*1,0,DEV_OEDIT_MOVE,cache.img(dev_move),
1900                new button(bw*2,0,DEV_OEDIT_FRONT,cache.img(dev_front),
1901                new button(bw*3,0,DEV_OEDIT_BACK,cache.img(dev_back),
1902                new button(bw*4,0,DEV_OEDIT_COPY,cache.img(dev_copy),
1903                new button(bw*0,bh*1,DEV_OEDIT_DELETE,cache.img(dev_del),
1904                           NULL)))))),
1905            new button(bw*5,bh*0,DEV_OEDIT_AI,cache.img(dev_ai),
1906
1907            new button_box(bw*1,bh*1,DEV_OEDIT_CHAR_BOX,0,
1908                new button(bw*1,bh*1,DEV_OEDIT_LEFT,cache.img(dev_char_left),
1909                new button(bw*2,bh*1,DEV_OEDIT_RIGHT,cache.img(dev_char_right),NULL)),
1910                new button(bw*3,bh*1,DEV_OBJECTS_DELETE,cache.img(dev_objects),
1911                new button(bw*4,bh*1,DEV_LIGHTS_DELETE,cache.img(dev_lights),NULL))))),
1912            symbol_str("l_EDIT"));
1913
1914
1915        edit_object=selected_object;
1916      } else if (selected_light)
1917      {
1918        if (ledit)
1919        {
1920          prop->setd("ledit x",ledit->m_pos.x);
1921          prop->setd("ledit x",ledit->m_pos.y);
1922          wm->close_window(ledit);
1923        }
1924        int bw=20+6,bh=16+6,th=wm->font()->Size().y+4;
1925        edit_light=selected_light;
1926        if (edit_object)
1927        {
1928          edit_object->add_light(edit_light);
1929          edit_light->known=1;
1930        }
1931        ledit=wm->CreateWindow(vec2i(prop->getd("ledit x", 0),
1932                                     prop->getd("ledit y", 0)), vec2i(-1),
1933              new button_box(0,0,ID_NULL,1,
1934                   new button(bw*0,0,DEV_LEDIT_OK,cache.img(dev_ok),
1935               new button(bw*1,0,DEV_LEDIT_MOVE,cache.img(dev_move),
1936                  new button(bw*2,0,DEV_LEDIT_COPY,cache.img(dev_copy),
1937            new button(bw*3,0,DEV_LEDIT_DEL,cache.img(dev_del),NULL)))),
1938            new text_field(0,bh,DEV_LEDIT_W,      "W ","******",edit_light->xshift,
1939            new text_field(0,bh+th*1,DEV_LEDIT_H, "H ","******",edit_light->yshift,
1940          new text_field(0,bh+th*2,DEV_LEDIT_R1,"R1","******",(int)(edit_light->inner_radius),
1941         new text_field(0,bh+th*3,DEV_LEDIT_R2,"R2","******",(int)(edit_light->outer_radius),
1942                   NULL))))));
1943      }
1944      else if (ev.window==NULL)
1945      {
1946        if (dlast.x>=0 && dlast.y>=0 && edit_mode==ID_DMODE_DRAW)
1947        {
1948          if ((dev & DRAW_FG_LAYER) && ev.mouse_button==1)
1949          {
1950        vec2i tile = the_game->GetFgTile(last_demo_mpos);
1951        if (tile.x>=0 && tile.y>=0 && tile.x<current_level->foreground_width() &&
1952            tile.y<current_level->foreground_height())
1953        the_game->PutFg(tile, raise_all ? make_above_tile(cur_fg) : cur_fg);
1954          }
1955          if ((dev & DRAW_BG_LAYER) && ev.mouse_button==2)
1956          {
1957        vec2i tile = the_game->GetBgTile(last_demo_mpos);
1958        if (tile.x>=0 && tile.y>=0 && tile.x<current_level->background_width() &&
1959            tile.y<current_level->background_height())
1960        the_game->PutBg(tile, cur_bg);
1961          }
1962        }
1963      }
1964    }
1965      }
1966    }
1967    default:
1968      break;
1969  }
1970
1971  switch (ev.type)
1972  {
1973    case EV_MESSAGE :
1974    {
1975      switch (ev.message.id)
1976      {
1977    case ID_DMODE_DRAW :
1978    case ID_DMODE_PICK :
1979    case ID_DMODE_FILL :
1980    case ID_DMODE_LINE :
1981    case ID_DMODE_RECT :
1982    case ID_DMODE_BAR  :
1983    case ID_DMODE_AREA :
1984    {
1985      edit_mode=ev.message.id;
1986    } break;
1987/*    case ID_ENLARGE_RENDER :
1988    {
1989      if (!small_render)
1990        double_render();
1991      else
1992        single_render();
1993
1994      view_shift_disabled=!view_shift_disabled;
1995    } break; */
1996
1997    case ID_SEARCH :
1998    {
1999      toggle_search_window();
2000    } break;
2001    case ID_SEARCH_FOREWARD :
2002    { search_forward();
2003    } break;
2004    case ID_SEARCH_BACKWARD :
2005    { search_forward();
2006    } break;
2007    case ID_CANCEL :
2008    {
2009      if (mess_win)
2010      {
2011        wm->close_window(mess_win);
2012        mess_win=NULL;
2013      } break;
2014    } break;
2015    case ID_LEVEL_LOAD :
2016    {
2017      if (!mess_win)
2018      {
2019        mess_win=file_dialog(symbol_str("level_name"),current_level ? current_level->name() : "",
2020                 ID_LEVEL_LOAD_OK,symbol_str("ok_button"),ID_CANCEL,symbol_str("cancel_button"),
2021                 symbol_str("FILENAME"),ID_MESS_STR1);
2022        wm->grab_focus(mess_win);
2023      }
2024    } break;
2025    case ID_LEVEL_LOAD_OK :
2026    {
2027      char cmd[100];
2028      sprintf(cmd,"load %s",mess_win->read(ID_MESS_STR1));
2029      dev_cont->do_command(cmd,ev);
2030      wm->Push(new Event(ID_CANCEL,NULL));        // close window
2031    } break;
2032    case ID_GAME_SAVE :
2033    {
2034      current_level->save("savegame.spe",1);
2035      the_game->show_help(symbol_str("saved_game"));
2036      the_game->need_refresh();
2037    } break;
2038    case ID_LEVEL_SAVE :
2039    { if (current_level)
2040      {
2041        if (current_level->save(current_level->name(),0))
2042        {
2043          char msg[100];
2044          sprintf(msg,symbol_str("saved_level"),current_level->name());
2045          the_game->show_help(msg);
2046          the_game->need_refresh();
2047        }
2048      }
2049      else the_game->show_help("no current level, cannot save");
2050    } break;
2051    case ID_LEVEL_SAVEAS :
2052    {
2053      if (!mess_win)
2054      {
2055        mess_win=file_dialog(symbol_str("saveas_name"),current_level ? current_level->name() : "untitled.spe",
2056                   ID_LEVEL_SAVEAS_OK,symbol_str("ok_button"),
2057                 ID_CANCEL,symbol_str("cancel_button"),
2058                 symbol_str("FILENAME"),ID_MESS_STR1);
2059        wm->grab_focus(mess_win);
2060      }
2061    } break;
2062    case ID_LEVEL_SAVEAS_OK :
2063    {
2064      if (current_level)
2065      {
2066        current_level->set_name(mess_win->read(ID_MESS_STR1));
2067        wm->Push(new Event(ID_CANCEL,NULL));        // close window after save
2068        wm->Push(new Event(ID_LEVEL_SAVE,NULL));
2069      }
2070    } break;
2071    case ID_EDIT_SAVE :
2072    {
2073      do_command("esave",ev);
2074      the_game->show_help(symbol_str("edit_saved"));
2075    } break;
2076    case ID_CACHE_PROFILE :
2077    {
2078      if (current_level && !cache.prof_is_on())
2079      {
2080        cache.prof_init();
2081        the_game->show_help("Cache profiling is now on.");
2082      }
2083      else the_game->show_help("Cache profiling is already on!");
2084    } break;
2085
2086    case ID_CACHE_PROFILE_END :  // ask the user for a file name to save as
2087    {
2088      if (cache.prof_is_on())
2089      {
2090        cache.prof_uninit();
2091        the_game->show_help(symbol_str("prof_off"));
2092      } else the_game->show_help(symbol_str("prof"));
2093    } break;
2094
2095    case ID_LEVEL_NEW :
2096    {
2097      if (!mess_win)
2098      {
2099        mess_win=wm->CreateWindow(vec2i(xres / 2, yres / 2), vec2i(-1),
2100               new button(10,20,ID_LEVEL_NEW_OK,symbol_str("YES"),
2101                        new button(40,20,ID_CANCEL,symbol_str("NO"),
2102          new info_field(0,0,ID_NULL,symbol_str("sure?"),NULL))),symbol_str("New?"));
2103        wm->grab_focus(mess_win);
2104      }
2105    } break;
2106    case ID_LEVEL_NEW_OK :
2107    {
2108      wm->Push(new Event(ID_CANCEL,NULL));  // close_window
2109      if (current_level)
2110        delete current_level;
2111      current_level=new level(100,100,"untitled.spe");
2112    } break;
2113    case ID_LEVEL_RESIZE :
2114    {
2115      if (!mess_win)
2116      {
2117        int h=wm->font()->Size().y+8;
2118        mess_win=wm->CreateWindow(vec2i(xres / 2, yres / 2), vec2i(-1),
2119            new text_field(0,h*0,ID_MESS_STR1,symbol_str("width_"),"****",
2120                   current_level ? current_level->foreground_width() : 100,
2121            new text_field(0,h*1,ID_MESS_STR2,symbol_str("height_"),"****",
2122                   current_level ? current_level->foreground_height() : 100,
2123                   new button(10,h*4,ID_LEVEL_RESIZE_OK,symbol_str("ok_button"),
2124                   new button(40,h*4,ID_CANCEL,symbol_str("cancel_button"),NULL)))),symbol_str("_scroll"));
2125      }
2126    } break;
2127    case ID_LEVEL_RESIZE_OK :
2128    {
2129      if (current_level)
2130      {
2131        current_level->set_size(atoi(mess_win->read(ID_MESS_STR1)),
2132                    atoi(mess_win->read(ID_MESS_STR2)));
2133      } else the_game->show_help("Create a level first!");
2134      wm->Push(new Event(ID_CANCEL,NULL));  // close_window
2135    } break;
2136
2137    case ID_SUSPEND :
2138    {
2139      dev^=SUSPEND_MODE;
2140      if (dev&SUSPEND_MODE)
2141        the_game->show_help(symbol_str("suspend_on"));
2142      else
2143         the_game->show_help(symbol_str("suspend_off"));
2144    } break;
2145    case ID_PLAY_MODE :
2146    {
2147      dev^=EDIT_MODE;
2148    } break;
2149    case ID_QUIT :
2150    {
2151      if (confirm_quit())
2152        do_command("quit",ev);
2153    } ;
2154    case ID_TOGGLE_MAP :
2155    {
2156      if (dev&MAP_MODE) dev-=MAP_MODE;
2157      else dev|=MAP_MODE;
2158      the_game->need_refresh();
2159    } break;
2160    case ID_TOGGLE_LIGHT :
2161    {
2162      dev^=DRAW_LIGHTS;
2163      the_game->need_refresh();
2164    } break;
2165    case ID_RECORD_DEMO :
2166    {
2167      if (!mess_win)
2168      {
2169        int h=wm->font()->Size().y+8;
2170        mess_win=wm->CreateWindow(vec2i(xres / 2, yres / 2), vec2i(-1),
2171            new text_field(0,h*0,ID_RECORD_DEMO_FILENAME,
2172                   "demo filename","*******************",
2173                   "demo.dat",
2174                   new button(10,h*2,ID_RECORD_DEMO_OK,symbol_str("ok_button"),
2175                   new button(40,h*2,ID_CANCEL,symbol_str("cancel_button"),NULL))));
2176      }
2177    } break;
2178
2179        case ID_RECORD_DEMO_OK :
2180    {
2181      demo_man.set_state(demo_manager::RECORDING,mess_win->read(ID_RECORD_DEMO_FILENAME));
2182      wm->Push(new Event(ID_CANCEL,NULL));        // close window
2183    } break;
2184
2185    case ID_PLAY_DEMO :
2186    {
2187      if (!mess_win)
2188      {
2189        int h=wm->font()->Size().y+8;
2190        mess_win=wm->CreateWindow(vec2i(xres / 2, yres / 2), vec2i(-1),
2191            new text_field(0,h*0,ID_PLAY_DEMO_FILENAME,
2192                   "demo filename","*******************",
2193                   "demo.dat",
2194                   new button(10,h*2,ID_PLAY_DEMO_OK,symbol_str("ok_button"),
2195                   new button(40,h*2,ID_CANCEL,symbol_str("cancel_button"),NULL))));
2196      }
2197    } break;
2198
2199        case ID_PLAY_DEMO_OK :
2200    {
2201      demo_man.set_state(demo_manager::PLAYING,mess_win->read(ID_PLAY_DEMO_FILENAME));
2202      wm->close_window(mess_win);
2203      mess_win=NULL;
2204    } break;
2205
2206    case ID_SET_SCROLL :
2207    {
2208      if (!mess_win)
2209      {
2210        int h=wm->font()->Size().y+8;
2211        mess_win=wm->CreateWindow(vec2i(xres / 2, yres / 2), vec2i(-1),
2212            new text_field(0,h*0,ID_MESS_STR1,symbol_str("x_mul"),"****",bg_xmul,
2213            new text_field(0,h*1,ID_MESS_STR2,symbol_str("x_div"),"****",bg_xdiv,
2214            new text_field(0,h*2,ID_MESS_STR3,symbol_str("y_mul"),"****",bg_ymul,
2215            new text_field(0,h*3,ID_MESS_STR4,symbol_str("y_div"),"****",bg_ydiv,
2216                   new button(10,h*4,ID_SET_SCROLL_CHECK,symbol_str("ok_button"),
2217                   new button(40,h*4,ID_CANCEL,symbol_str("cancel_button"),NULL)))))),symbol_str("_scroll"));
2218      }
2219    } break;
2220    case ID_SET_SCROLL_CHECK :
2221    {
2222      int tbg_xmul=atoi(mess_win->read(ID_MESS_STR1));
2223      int tbg_xdiv=atoi(mess_win->read(ID_MESS_STR2));
2224      int tbg_ymul=atoi(mess_win->read(ID_MESS_STR3));
2225      int tbg_ydiv=atoi(mess_win->read(ID_MESS_STR4));
2226
2227      if ( (((float)tbg_xmul/(float)tbg_xdiv) < ((float)bg_xmul/(float)bg_xdiv)) ||
2228          (((float)tbg_ymul/(float)tbg_ydiv) < ((float)bg_ymul/(float)bg_ydiv)))
2229      {
2230        int h=wm->font()->Size().y+8;
2231
2232        warn_win=wm->CreateWindow(vec2i(xres / 2 - 40, yres / 2 - 40),
2233                                  vec2i(-1),
2234                  new info_field(0,0,ID_NULL,
2235                      symbol_str("back_loss"),
2236                      new button(10,h*4,ID_SET_SCROLL_OK,symbol_str("ok_button"),
2237                      new button(40,h*4,ID_WARN_CANCEL,symbol_str("cancel_button"),NULL))),
2238                    symbol_str("WARNING"));
2239        wm->grab_focus(warn_win);
2240      } else wm->Push(new Event(ID_SET_SCROLL_OK,NULL));
2241    } break;
2242    case ID_WARN_CANCEL :
2243    {
2244      wm->close_window(warn_win); warn_win=NULL;
2245      wm->Push(new Event(ID_CANCEL,NULL));
2246    } break;
2247    case ID_SET_SCROLL_OK :
2248    {
2249      if (warn_win) { wm->close_window(warn_win); warn_win=NULL; }
2250      bg_xmul=atoi(mess_win->read(ID_MESS_STR1));
2251      bg_xdiv=atoi(mess_win->read(ID_MESS_STR2));
2252      bg_ymul=atoi(mess_win->read(ID_MESS_STR3));
2253      bg_ydiv=atoi(mess_win->read(ID_MESS_STR4));
2254      wm->Push(new Event(ID_CANCEL,NULL));        // close window
2255    } break;
2256
2257    case ID_CENTER_PLAYER :
2258    {
2259       do_command("center",ev); break;
2260    } break;
2261
2262    case ID_INTERPOLATE_DRAW :
2263    {
2264      interpolate_draw=!interpolate_draw;
2265    } break;
2266
2267    case ID_DISABLE_AUTOLIGHT :
2268    {
2269      disable_autolight=!disable_autolight;
2270    } break;
2271
2272    case ID_ADD_PALETTE :
2273    {
2274      if (!mess_win)
2275      {
2276        int h=wm->font()->Size().y+8;
2277        mess_win=wm->CreateWindow(vec2i(xres / 2, yres / 2), vec2i(-1),
2278            new text_field(0,h*0,ID_MESS_STR1,symbol_str("ap_width"),"****",2,
2279            new text_field(0,h*1,ID_MESS_STR2,symbol_str("ap_height"),"****",2,
2280            new text_field(0,h*2,ID_MESS_STR3,symbol_str("ap_name"),"***********","pal",
2281                   new button(10,h*3,ID_ADD_PALETTE_OK,symbol_str("ok_button"),
2282                   new button(40,h*3,ID_CANCEL,symbol_str("cancel_button"),NULL))))),symbol_str("ap_pal"));
2283      }
2284    } break;
2285    case ID_ADD_PALETTE_OK :
2286    {
2287      char name[70];
2288      sprintf(name,"(add_palette \"%s\" %d %d)",mess_win->read(ID_MESS_STR3),
2289          atoi(mess_win->read(ID_MESS_STR1)),
2290          atoi(mess_win->read(ID_MESS_STR2)));
2291      char const *s=name;
2292      LObject::Compile(s)->Eval();
2293      wm->Push(new Event(ID_CANCEL,NULL));        // close window
2294    } break;
2295    case ID_TOGGLE_DELAY :
2296    {
2297      the_game->toggle_delay(); break;
2298    } break;
2299
2300    case ID_SMALL_MODE :
2301    {
2302      make_screen_size(311,160); break;
2303    } break;
2304    case ID_CLEAR_WEAPONS :
2305    {
2306      Event ev;
2307      do_command("clear_weapons",ev);
2308    } break;
2309    case ID_GOD_MODE :
2310    {
2311      for (view *v=player_list; v; v=v->next)
2312        v->god=!v->god;
2313    } break;
2314    case ID_MOUSE_SCROLL :
2315    {
2316      mouse_scrolling=!mouse_scrolling;
2317      prop->setd("mouse_scrolling",mouse_scrolling);
2318      if (mouse_scrolling)
2319        the_game->show_help(symbol_str("ms_on"));
2320      else
2321        the_game->show_help(symbol_str("ms_off"));
2322    } break;
2323
2324    case ID_LOCK_PALETTES :
2325    {
2326      palettes_locked=!palettes_locked;
2327      prop->setd("palettes_locked",palettes_locked);
2328      if (palettes_locked)
2329        the_game->show_help(symbol_str("pal_lock"));
2330      else the_game->show_help(symbol_str("pal_unlock"));
2331    } break;
2332
2333    case ID_DISABLE_VIEW_SHIFT :
2334    {
2335      view_shift_disabled=!view_shift_disabled;
2336      prop->setd("view_shift_disabled",view_shift_disabled);
2337      if (view_shift_disabled)
2338        the_game->show_help(symbol_str("vs_dis"));
2339      else the_game->show_help(symbol_str("vs_en"));
2340    } break;
2341
2342    case ID_WIN_FORE :
2343    {
2344      toggle_fgw();
2345    } break;
2346    case ID_WIN_BACK :
2347    {
2348      toggle_bgw();
2349    } break;
2350    case ID_WIN_OBJECTS :
2351    {
2352      toggle_omenu();
2353    } break;
2354    case ID_WIN_PALETTES :
2355    {
2356      toggle_pmenu();
2357    } break;
2358    case ID_WIN_LIGHTING :
2359    {
2360      toggle_light_window();
2361    } break;
2362    case ID_WIN_LAYERS :
2363    {
2364      toggle_show_menu();
2365    } break;
2366    case ID_WIN_CONSOLE :
2367    {
2368      if (dev_console) dev_console->toggle();
2369    } break;
2370    case ID_WIN_TOOLBAR :
2371    {
2372      toggle_toolbar();
2373    } break;
2374
2375    case DEV_AMBIENT :
2376    { if (!ambw) make_ambient(); } break;
2377    case DEV_AREA_OK :
2378    { close_area_win(1); } break;
2379    case DEV_AREA_DELETE :
2380    { close_area_win(0);
2381      if (current_area && current_level)
2382      {
2383        if (current_level->area_list==current_area)
2384          current_level->area_list=current_level->area_list->next;
2385        else
2386        {
2387          area_controller *a=current_level->area_list,*l=NULL;
2388          for (; a!=current_area && a; a=a->next) { l=a; }
2389          l->next=a->next;
2390          delete a;
2391        }
2392        current_area=NULL;
2393        the_game->need_refresh();
2394      }
2395    } break;
2396    case DEV_AI_OK :
2397      close_ai_window(); break;
2398    case DEV_OEDIT_AI :
2399      make_ai_window(edit_object); break;
2400    case DEV_OBJECTS_DELETE :
2401    {
2402      if (edit_object)
2403      {
2404        for (int i=0; i<edit_object->total_objects(); i++)
2405          edit_object->remove_object(edit_object->get_object(0));
2406        the_game->need_refresh();
2407      }
2408    } break;
2409
2410    case DEV_LIGHTS_DELETE :
2411    {
2412      if (edit_object)
2413      {
2414        for (int i=0; i<edit_object->total_lights(); i++)
2415          edit_object->remove_light(edit_object->get_light(0));
2416        the_game->need_refresh();
2417      }
2418    } break;
2419
2420    case DEV_LEDIT_DEL :
2421    {
2422      prop->setd("ledit x",ledit->m_pos.x);
2423      prop->setd("ledit y",ledit->m_pos.y);
2424      wm->close_window(ledit); ledit=NULL;
2425      if (current_level)
2426        current_level->remove_light(edit_light);
2427      else
2428        delete_light(edit_light);
2429      edit_light=NULL;
2430      the_game->need_refresh();
2431    } break;
2432    case DEV_LEDIT_OK :
2433    {
2434      edit_light->xshift=atoi(ledit->read(DEV_LEDIT_W));
2435      edit_light->yshift=atoi(ledit->read(DEV_LEDIT_H));
2436      edit_light->inner_radius=atoi(ledit->read(DEV_LEDIT_R1));
2437      edit_light->outer_radius=atoi(ledit->read(DEV_LEDIT_R2));
2438      if (edit_light->outer_radius<=edit_light->inner_radius)
2439      {
2440        edit_light->inner_radius=edit_light->outer_radius-1;
2441        if (edit_light->inner_radius<1)
2442        {
2443          edit_light->inner_radius=1;
2444          edit_light->outer_radius=2;
2445        }
2446      }
2447
2448      edit_light->calc_range();
2449      edit_light=NULL;
2450      prop->setd("ledit x",ledit->m_pos.x);
2451      prop->setd("ledit y",ledit->m_pos.y);
2452      wm->close_window(ledit); ledit=NULL;
2453      the_game->need_refresh();
2454    } break;
2455    case DEV_LEDIT_MOVE :
2456    {
2457      prop->setd("ledit x",ledit->m_pos.x);
2458      prop->setd("ledit y",ledit->m_pos.y);
2459      wm->close_window(ledit); ledit=NULL;
2460      state=DEV_MOVE_LIGHT;
2461    } break;
2462    case DEV_LEDIT_COPY :
2463    {
2464      edit_light=edit_light->copy();
2465      prop->setd("ledit x",ledit->m_pos.x);
2466      prop->setd("ledit y",ledit->m_pos.y);
2467      wm->close_window(ledit); ledit=NULL;
2468      state=DEV_MOVE_LIGHT;
2469    } break;
2470
2471
2472    case DEV_LIGHT0 :
2473    case DEV_LIGHT1 :
2474    case DEV_LIGHT2 :
2475    case DEV_LIGHT3 :
2476    case DEV_LIGHT4 :
2477    case DEV_LIGHT5 :
2478    case DEV_LIGHT6 :
2479    case DEV_LIGHT7 :
2480    case DEV_LIGHT8 :
2481    case DEV_LIGHT9 :
2482    {
2483      vec2i pos = the_game->MouseToGame(last_demo_mpos);
2484      edit_light = add_light_source(ev.message.id - DEV_LIGHT0,
2485                                    snap_x(pos.x), snap_y(pos.y),
2486                                    atoi(lightw->read(DEV_LIGHTR1)),
2487                                    atoi(lightw->read(DEV_LIGHTR2)),
2488                                    atoi(lightw->read(DEV_LIGHTW)),
2489                                    atoi(lightw->read(DEV_LIGHTH)));
2490      state=DEV_MOVE_LIGHT;
2491    } break;
2492    case ID_RAISE_ALL :
2493    {
2494      raise_all=!raise_all;
2495      prop->setd("raise_all",raise_all);
2496      if (raise_all)
2497        the_game->show_help(symbol_str("fg_r"));
2498      else
2499        the_game->show_help(symbol_str("fg_l"));
2500    } break;
2501    case DEV_OEDIT_COPY :
2502    {
2503      game_object *use=copy_object;
2504      if (!use) use=edit_object;
2505      if (use)
2506      {
2507        game_object *old=use;
2508        close_oedit_window();
2509        if (use->controller())
2510          the_game->show_help(symbol_str("no_clone"));
2511        else
2512        {
2513          edit_object=old->copy();
2514
2515          current_level->add_object(edit_object);
2516          the_game->need_refresh();
2517          state=DEV_MOVE_OBJECT;
2518
2519          close_oedit_window();
2520          copy_object=NULL;
2521        }
2522      }
2523    } break;
2524    case DEV_OEDIT_LEFT :
2525    {
2526      if (edit_object)
2527      {
2528        the_game->need_refresh();
2529        edit_object->direction=-1;
2530      }
2531    } break;
2532    case DEV_OEDIT_RIGHT :
2533    {
2534      if (edit_object)
2535      {
2536        the_game->need_refresh();
2537        edit_object->direction=1;
2538      }
2539    } break;
2540
2541
2542    case DEV_COMMAND_OK :
2543    {
2544      char cmd[100];
2545      strcpy(cmd,commandw->inm->get(DEV_COMMAND)->read());
2546      prop->setd("commandw x",commandw->m_pos.x);
2547      prop->setd("commandw y",commandw->m_pos.y);
2548      wm->close_window(commandw);
2549      commandw=NULL;
2550      do_command(cmd,ev);
2551    } break;
2552
2553    case ID_SHOW_FPS :
2554    { fps_on=!fps_on; } break;
2555    case ID_PROFILE :
2556    { profile_toggle();
2557      profile_on=!profile_on;
2558    } break;
2559
2560    case ID_TOGGLE_NAMES : { show_names=!show_names; } break;
2561    case DEV_QUIT : the_game->end_session(); break;
2562    case DEV_EDIT_FG : dev=1; break; //the_game->draw(); break;
2563    case DEV_EDIT_BG : dev=2; break; //the_game->draw(); break;
2564    case DEV_EDIT_FGBG : dev=3; break; //the_game->draw(); break;
2565    case DEV_PLAY : dev=0; break; //the_game->draw(); break;
2566    case SHOW_FOREGROUND :
2567    { dev=dev^DRAW_FG_LAYER; the_game->need_refresh(); } break;
2568    case SHOW_FOREGROUND_BOUND :
2569    { dev=dev^DRAW_FG_BOUND_LAYER; the_game->need_refresh(); } break;
2570    case SHOW_BACKGROUND :
2571    { dev=dev^DRAW_BG_LAYER; the_game->need_refresh(); } break;
2572    case SHOW_CHARACTERS :
2573    { dev=dev^DRAW_PEOPLE_LAYER; the_game->need_refresh(); } break;
2574    case SHOW_LIGHT :
2575    { dev=dev^DRAW_LIGHTS; the_game->need_refresh(); } break;
2576    case SHOW_LINKS :
2577    { dev=dev^DRAW_LINKS;  the_game->need_refresh(); } break;
2578
2579
2580    case DEV_CREATE :
2581    {
2582      int val=get_omenu_item(((pick_list *)ev.message.data)->get_selection());
2583      char cmd[100];
2584      sprintf(cmd,"create %s",object_names[val]);
2585      do_command(cmd,ev);
2586      state=DEV_CREATE_OBJECT;
2587      dev|=(EDIT_MODE | DRAW_PEOPLE_LAYER);
2588    }
2589    break;
2590
2591    case DEV_PALETTE :
2592    {
2593      int val=((pick_list *)ev.message.data)->get_selection();
2594      pal_wins[val]->open_window();
2595    } break;
2596
2597    case DEV_MUSIC_PICKLIST :
2598    {
2599/*        int *val=((int *)((pick_list *)ev.message.data)->read());
2600        if (current_song) delete current_song;
2601        current_song=new song(song_list[*val]);
2602        current_song->play();        */
2603    }
2604    break;
2605
2606    case DEV_OEDIT_OK :
2607    { close_oedit_window(); } break;
2608
2609    case DEV_OEDIT_DELETE :
2610    {
2611      selected_object=edit_object;
2612      do_command("delete",ev);
2613      close_oedit_window();
2614    }
2615    break;
2616
2617    case DEV_OEDIT_FRONT :
2618    {
2619      do_command("to_front",ev);
2620      close_oedit_window();
2621    }
2622    break;
2623
2624    case DEV_OEDIT_BACK :
2625    {
2626      do_command("to_back",ev);
2627      close_oedit_window();
2628    }
2629    break;
2630
2631    case DEV_OEDIT_MOVE :
2632    {
2633      game_object *o=edit_object;
2634      close_oedit_window();
2635      edit_object=o;
2636      do_command("move",ev);
2637    }
2638    break;
2639      }
2640    } break;
2641
2642
2643    case EV_CLOSE_WINDOW :
2644    {
2645      if (ev.window)
2646      {
2647    if (ev.window==commandw)
2648    {
2649      prop->setd("commandw x",commandw->m_pos.x);
2650      prop->setd("commandw y",commandw->m_pos.y);
2651      wm->close_window(commandw);
2652      commandw=NULL;
2653    } else if (ev.window==oedit)
2654      close_oedit_window();
2655    else if (ev.window==ambw)
2656    { wm->close_window(ambw); ambw=NULL; }
2657    else if (ev.window==backw) toggle_bgw();
2658    else if (ev.window==forew) toggle_fgw();
2659    else if (ev.window==lightw) toggle_light_window();
2660    else if (ev.window==show_menu) toggle_show_menu();
2661    else if (ev.window==pmenu) toggle_pmenu();
2662    else if (ev.window==tbw) toggle_toolbar();
2663    else if (ev.window==omenu) toggle_omenu();
2664    else if (ev.window==search_window) toggle_search_window();
2665    else if (profile_handle_event(ev))  profile_on=!profile_on;
2666    else if (chat->chat_event(ev)) chat->toggle();
2667
2668      }
2669    }
2670    break;
2671    case EV_KEYRELEASE :
2672    {
2673      if (ev.key==JK_CTRL_L)
2674      {
2675        if (!edit_object && link_object && selected_object && link_object!=selected_object)
2676    {
2677      link_object->add_object(selected_object);
2678      if (S_LINK_SND>0) cache.sfx(S_LINK_SND)->play(sfx_volume/2);
2679      the_game->need_refresh();
2680    }
2681
2682    link_object=NULL;
2683      }
2684    } break;
2685    case EV_KEY :
2686    {
2687      if (backw && ev.window==backw)
2688      { if (ev.key=='-' && bg_scale<the_game->btile_height()/2)
2689    { toggle_bgw();
2690      bg_scale++;
2691      toggle_bgw();
2692    } else if (ev.key=='+' && bg_scale>1)
2693    { toggle_bgw();
2694      bg_scale--;
2695      toggle_bgw();
2696    } else if (ev.key=='b') toggle_bgw();
2697    else if (ev.key=='B') { toggle_bgw(); bg_w++; if (bg_w>6) bg_w=1; toggle_bgw(); }
2698      }
2699      if (forew && ev.window==forew)
2700      { if (ev.key=='-' && fg_scale<the_game->ftile_height()/2)
2701    { toggle_fgw();
2702      fg_scale++;
2703      toggle_fgw();
2704    } else if (ev.key=='+' && fg_scale>1)
2705    { toggle_fgw();
2706      fg_scale--;
2707      toggle_fgw();
2708    } else if (ev.key=='i')
2709    {
2710      toggle_fgw();
2711      fg_reversed=!fg_reversed;
2712      prop->setd("fg_reversed",fg_reversed);
2713      toggle_fgw();
2714    } else if (ev.key=='f') toggle_fgw();
2715
2716    else if (ev.key=='F') { toggle_fgw(); fg_w++; if (fg_w>6) fg_w=1; toggle_fgw(); }
2717      }
2718      if (ev.window==NULL || ev.window==pmenu ||
2719      ev.window==forew || is_pal_win(ev.window))  // main window actions
2720      {
2721    switch (ev.key)
2722    {
2723      case JK_CTRL_L : if (!edit_object && !link_object) { link_object=selected_object; }
2724      case 'n' : current_level->next_focus(); break;
2725//      case '/' : if (dev_console) dev_console->toggle(); break;
2726      case 't' :
2727      {
2728        if (ev.window==NULL || ev.window==forew)
2729        {
2730          vec2i tile = the_game->GetFgTile(last_demo_mpos);
2731          fg_fill(cur_fg, tile.x, tile.y, NULL);
2732        }
2733      } break;
2734      case 'f' : toggle_fgw(); break;
2735      case 'M' : toggle_music_window(); break;
2736
2737      case 'b' : toggle_bgw(); break;
2738      case 'a' : toggle_toolbar(); break;
2739      case 'A' : { if (selected_object)
2740               {
2741             if (oedit) wm->Push(new Event(DEV_OEDIT_OK,NULL));
2742             make_ai_window(selected_object);
2743               }
2744             } break;
2745
2746      case 'o' : toggle_omenu(); break;
2747
2748      case '<' : do_command("to_back",ev); break;
2749
2750      case '>' : do_command("to_front",ev); break;
2751      case 'p' : toggle_pmenu(); break;
2752      case 'P' : profile_toggle(); break;
2753      case '.' :
2754      {
2755        if (last_created_type>=0)
2756        {
2757          int val=last_created_type;
2758          char cmd[100];
2759          sprintf(cmd,"create %s",object_names[val]);
2760          do_command(cmd,ev);
2761          state=DEV_CREATE_OBJECT;
2762          dev|=(EDIT_MODE | DRAW_PEOPLE_LAYER);
2763        }
2764      }
2765      break;
2766
2767
2768      case 'd' : { do_command("delete",ev);  the_game->need_refresh(); } break;
2769      case 'i' :
2770      {
2771        fg_reversed=!fg_reversed;
2772        prop->setd("fg_reversed",fg_reversed);
2773        if (forew)
2774        {
2775          toggle_fgw();
2776          toggle_fgw();
2777        }
2778      } break;
2779      case 'l' : toggle_light_window(); break;
2780      case '!' :
2781      case '@' :
2782      case '#' :
2783      case '$' :
2784      case '%' :
2785      case '^' :
2786      case '&' :
2787      case '*' :
2788      case '(' :
2789      case ')' :
2790
2791      case '0' :
2792      case '1' :
2793      case '2' :
2794      case '3' :
2795      case '4' :
2796      case '5' :
2797      case '6' :
2798      case '7' :
2799      case '8' :
2800      case '9' : do_command("set_aitype",ev); break;
2801      case 'c' : do_command("center",ev); break;
2802      case 'C' :
2803      if (selected_object && selected_object->controller()==NULL)
2804      { copy_object=selected_object;
2805            wm->Push(new Event(DEV_OEDIT_COPY,NULL)); } break;
2806
2807      case 'D' : the_game->toggle_delay(); break;
2808      case 'L' : toggle_show_menu(); break;
2809      case '`' : do_command("fg_select",ev); break;
2810      case 'r' : { do_command("toggle_fg_raise",ev); the_game->need_refresh(); }  break;
2811      case '[' : do_command("fg_add -1",ev); break;
2812      case ']' : do_command("fg_add 1",ev); break;
2813      case 'R' : do_command("reload",ev); break;
2814      case 'w' :
2815      {
2816        vec2i pos = the_game->MouseToGame(dlast);
2817        char msg[100]; sprintf(msg, symbol_str("mouse_at"), pos.x, pos.y);
2818        the_game->show_help(msg);
2819        the_game->need_refresh();
2820      } break;
2821      case 'k' :
2822      {
2823        if (selected_object && selected_object->total_objects())
2824          selected_object->remove_object(selected_object->get_object(0));
2825        the_game->need_refresh();
2826      } break;
2827      case 'K' :
2828      {
2829        if (selected_object && selected_object->total_objects())
2830          selected_object->remove_object(selected_object->get_object(selected_object->total_objects()-1));
2831        the_game->need_refresh();
2832      } break;
2833      case 'j' :
2834      {
2835        if (current_level && player_list && player_list->focus)
2836        {
2837          vec2i pos = the_game->MouseToGame(dlast);
2838          player_list->focus->x = pos.x;
2839          player_list->focus->y = pos.y;
2840          do_command("center",ev);
2841          the_game->need_refresh();
2842        }
2843      } break;
2844      case 'z' : do_command("clear_weapons",ev); break;
2845      case 'Z' : if (dev&EDIT_MODE)
2846      { view *v = the_game->GetView(last_demo_mpos);
2847        if (v)
2848        {
2849          v->god=!v->god;
2850          sbar.redraw(main_screen);
2851        }
2852      } break;
2853      case ' ' :
2854      {
2855        if (dev & EDIT_MODE)
2856        {
2857          if (selected_object)
2858          {
2859        if (oedit)
2860          close_oedit_window();
2861        edit_object=selected_object;
2862        do_command("move",ev);
2863          } else if (selected_light)
2864          {
2865        if (ledit)
2866        {
2867          wm->close_window(ledit);
2868          ledit=NULL;
2869        }
2870        edit_light=selected_light;
2871        do_command("move_light",ev);
2872          }
2873
2874        } break;
2875      }
2876      case 'x' :
2877      {
2878        if (selected_object)
2879        { if (selected_object->direction>0)
2880          selected_object->direction=-1;
2881        else selected_object->direction=1;
2882        }
2883      } break;
2884
2885    }
2886      }
2887    }
2888  }
2889
2890
2891}
2892
2893
2894void dev_controll::add_palette(void *args)
2895{
2896  total_pals++;
2897  pal_wins=(pal_win **)realloc(pal_wins,sizeof(pal_win *)*total_pals);
2898  pal_wins[total_pals-1]=new pal_win(args);
2899}
2900
2901
2902pal_win::pal_win(void *args)
2903{
2904  int i=0;
2905  Cell *ao=(Cell *)args;
2906
2907  name = strdup(lstring_value(CAR(args)));
2908  ao=CDR(ao);
2909  scale=w=h=1;
2910  x=y=0;
2911
2912  if (!NILP(ao))
2913  {
2914    w=lnumber_value(CAR(ao)); ao=CDR(ao);
2915    if (!NILP(ao))
2916    {
2917      h=lnumber_value(CAR(ao)); ao=CDR(ao);
2918      if (!NILP(ao))
2919      {
2920    x=lnumber_value(CAR(ao)); ao=CDR(ao);
2921    if (!NILP(ao))
2922    {
2923      y=lnumber_value(CAR(ao)); ao=CDR(ao);
2924      if (!NILP(ao))
2925        scale=lnumber_value(CAR(ao)); ao=CDR(ao);
2926    }
2927      }
2928    }
2929  }
2930
2931  if (w<=0) w=0;
2932  if (h<=0) h=0;
2933
2934  pat=(unsigned short *)malloc(w*h*sizeof(unsigned short));
2935  memset(pat,0,sizeof(unsigned short)*w*h);   // set the palette to black if no parameters are given
2936  while (!NILP(ao))   // loop until we run out of parameters
2937  {
2938    if (i>w*h)
2939    {
2940      lbreak("to many parameters to add_palette ");
2941      exit(0);
2942    }
2943    pat[i]=lnumber_value(CAR(ao));
2944    // make sure the tile that they suggested exists
2945    if (pat[i]<=0 || pat[i]>nforetiles || foretiles[pat[i]]<0)
2946      pat[i]=0;
2947    ao=CDR(ao);
2948    i++;
2949  }
2950  last_selected=-1;
2951  me=NULL;
2952  open_window();
2953}
2954
2955void pal_win::open_window()
2956{
2957  if (me) close_window();
2958  me=wm->CreateWindow(vec2i(x, y), vec2i(w * f_wid / scale,
2959                                         h * f_hi / scale), NULL, name);
2960  draw();
2961}
2962
2963void pal_win::close_window()
2964{
2965  if (me)       // dont' close the window if the window is already closed
2966  {
2967    x=me->m_pos.x;    //  save the old poisition of the window so that when we  open it
2968                //  it will be in the same spot
2969    y=me->m_pos.y;
2970    wm->close_window(me);
2971    me=NULL;
2972
2973  }
2974}
2975
2976void pal_win::draw()
2977{
2978  int i,d=cur_fg;
2979  if (me)
2980  {
2981    me->clear();
2982    image *im=new image(vec2i(the_game->ftile_width(),the_game->ftile_height()));
2983    int th=the_game->ftile_height()/scale,tw=the_game->ftile_width()/scale;
2984
2985    for (i=0; i<w*h; i++)
2986    {
2987      im->clear();
2988      the_game->get_fg(pat[i])->im->PutImage(im, vec2i(0,0));
2989      scale_put(im,me->m_surf,me->x1()+(i%w)*tw,
2990        me->y1()+(i/w)*th,tw,th);
2991      if (d==pat[i])
2992      {
2993    me->m_surf->Rectangle(vec2i(me->x1() + (i % w) * tw,
2994                                me->y1() + (i / w) * th),
2995                          vec2i(me->x1() + (i % w) * tw + tw - 1,
2996                                me->y1() + (i / w) * th + th - 1),
2997                          wm->bright_color());
2998      }
2999    }
3000    delete im;
3001    last_selected=d;
3002  }
3003}
3004
3005void pal_win::handle_event(Event &ev)
3006{
3007  int d=cur_fg;
3008
3009  if (d!=last_selected)  // if so see if we need to hilight any of our tiles.
3010  {
3011    int i,dr=0;
3012    for (i=0; i<w*h; i++)
3013    {
3014      if (pat[i]==d || pat[i]==last_selected)
3015        dr=1;
3016    }
3017    if (dr) draw();
3018    last_selected=d;
3019  }
3020
3021  if (ev.window && ev.window==me)
3022  {
3023    switch (ev.type)
3024    {
3025      case EV_MOUSE_BUTTON :
3026      {
3027        if (ev.mouse_button==1)
3028    {
3029      int selx=(last_demo_mpos.x-me->m_pos.x-me->x1())/(the_game->ftile_width()/scale),
3030          sely=(last_demo_mpos.y-me->m_pos.y-me->y1())/(the_game->ftile_height()/scale);
3031      if (selx>=0 && sely>=0 && selx<w && sely<h)
3032      {
3033        cur_fg=pat[selx+sely*w];
3034        if (dev_cont->forew)
3035          ((tile_picker *)dev_cont->forew->
3036           read(DEV_FG_PICKER))->recenter(dev_cont->forew->m_surf);
3037      }
3038    } else if (ev.mouse_button==2)
3039    {
3040      if (palettes_locked)
3041        the_game->show_help(symbol_str("pal_lock"));
3042      else
3043      {
3044        int selx=(last_demo_mpos.x-me->m_pos.x-me->x1())/(the_game->ftile_width()/scale),
3045            sely=(last_demo_mpos.y-me->m_pos.y-me->y1())/(the_game->ftile_height()/scale);
3046        if (selx>=0 && sely>=0 && selx<w && sely<h)
3047        {
3048          pat[selx+sely*w]=cur_fg;
3049          draw();
3050        }
3051      }
3052    }
3053      } break;
3054
3055      case EV_KEY :
3056      {
3057        switch (ev.key)
3058    {
3059      case '+' :
3060      { if (scale>1)
3061        {
3062          close_window();
3063          scale--;
3064          open_window();
3065        }
3066      } break;
3067      case '-' :
3068      { if (scale<the_game->ftile_height()/2)
3069        {
3070          close_window();
3071          scale++;
3072          open_window();
3073        }
3074      } break;
3075      case JK_LEFT :
3076      {
3077        if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3078        else if (w>1) resize(-1,0);
3079      } break;
3080      case JK_RIGHT :
3081      {
3082        if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3083        else
3084          resize(1,0);
3085      } break;
3086      case JK_UP :
3087      {
3088        if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
3089        else if (h>1) resize(0,-1);
3090      } break;
3091      case JK_DOWN :
3092      {
3093        if (palettes_locked)
3094          the_game->show_help(symbol_str("pal_lock"));
3095        else
3096          resize(0,1);
3097      } break;
3098      case JK_ESC : close_window();     break;
3099      case ' ' :
3100      {
3101        int32_t xx, yy;
3102        vec2i tile = the_game->GetFgTile(me->m_pos);
3103
3104        for (xx=tile.x; xx<tile.x+w; xx++)
3105        {
3106          for (yy=tile.y; yy<tile.y+h; yy++)
3107          {
3108        if (xx>=0 && yy>=0 && xx<current_level->foreground_width() &&
3109            yy<current_level->foreground_height())
3110          the_game->PutFg(vec2i(xx, yy), raise_all ? make_above_tile(pat[xx-tile.x+(yy-tile.y)*w]) : pat[xx-tile.x+(yy-tile.y)*w] );
3111          }
3112        }
3113      } break;
3114      case 't' :
3115      {
3116        vec2i tile = the_game->GetFgTile(me->m_pos);
3117        dev_cont->fg_fill(-1, tile.x, tile.y, this);
3118      } break;
3119
3120    }
3121      } break;
3122
3123      case EV_CLOSE_WINDOW : close_window(); break;
3124    }
3125  }
3126
3127
3128}
3129
3130
3131void pal_win::resize(int xa, int ya)
3132{
3133  int i,j;
3134  unsigned short *npat;
3135  if (w+xa<1 || y+ya<1) return ;
3136
3137  npat=(unsigned short *)malloc(sizeof(unsigned short)*(w+xa)*(h+ya));
3138  memset(npat,0,sizeof(unsigned short)*(w+xa)*(h+ya));
3139  for (i=0; i<(w+xa); i++)
3140    for (j=0; j<(h+ya); j++)
3141      if (i+j*w<w*h)
3142        npat[i+j*(w+xa)]=pat[i+j*w];
3143  free(pat);
3144  w+=xa;
3145  h+=ya;
3146  pat=npat;
3147  last_selected=-1;
3148  close_window();
3149  open_window();
3150}
3151
3152
3153void pal_win::save(FILE *fp)
3154{
3155  if (me)
3156  {
3157    x=me->m_pos.x;
3158    y=me->m_pos.y;
3159  }
3160
3161  fprintf(fp,"(add_palette \"%s\" %ld %ld %ld %ld %ld ",name,(long)w,(long)h,(long)x,(long)y,(long)scale);
3162  int i;
3163  for (i=0; i<w*h; i++)
3164    fprintf(fp,"%d ",pat[i]&0x7fff);
3165  fprintf(fp,")\n");
3166
3167}
3168
3169void dev_controll::save()
3170{
3171  FILE *fp=open_FILE("edit.lsp","w");
3172  if (!fp)
3173    the_game->show_help(symbol_str("no_edit.lsp"));
3174  else
3175  {
3176    fprintf(fp,"(set_zoom %d)\n",the_game->zoom);
3177
3178    int i;
3179    for (i=0; i<total_pals; i++)
3180    {
3181      pal_wins[i]->save(fp);
3182    }
3183    fprintf(fp,"\n");
3184    fclose(fp);
3185  }
3186
3187}
3188
3189int dev_controll::is_pal_win(Jwindow *win)
3190{
3191  int i;
3192  for (i=0; i<total_pals; i++)
3193    if (win==pal_wins[i]->me) return 1;
3194  return 0;
3195}
3196
3197
3198class fill_rec
3199{
3200public :
3201  short x,y;
3202  fill_rec *last;
3203  fill_rec(short X, short Y, fill_rec *Last)
3204  { x=X; y=Y; last=Last; }
3205} ;
3206
3207static int get_color(int color, int x, int y, pal_win *p)
3208{
3209  if (p)
3210  {
3211    while (x<0) x+=p->width();
3212    while (y<0) y+=p->height();
3213    return p->get_pat(x%p->width(),y%p->height());
3214  }
3215  else return color;
3216}
3217
3218void dev_controll::fg_fill(int color, int x, int y, pal_win *p)
3219{
3220  unsigned short *sl,*above,*below;
3221  fill_rec *recs=NULL,*r;
3222  unsigned short fcolor;
3223  sl=current_level->get_fgline(y);
3224  fcolor=fgvalue(sl[x]);
3225  int startx=x,starty=y;
3226  if (fcolor==color) return ;
3227  do
3228  {
3229    if (recs)
3230    { r=recs;
3231      recs=recs->last;
3232      x=r->x; y=r->y;
3233      delete r;
3234    }
3235    sl=current_level->get_fgline(y);
3236    if (fgvalue(sl[x])==fcolor)
3237    {
3238      while (x>0 && fgvalue(sl[x])==fcolor) x--;
3239      if (fgvalue(sl[x])!=fgvalue(fcolor) && x<current_level->foreground_width()-1) x++;
3240      if (y>0)
3241      {
3242        above=current_level->get_fgline(y-1);
3243        if (fgvalue(above[x])==fcolor)
3244        { r=new fill_rec(x,y-1,recs);
3245          recs=r;
3246        }
3247      }
3248      if (y<current_level->foreground_height()-1)
3249      {
3250        above=current_level->get_fgline(y+1);
3251        if (above[x]==fcolor)
3252        { r=new fill_rec(x,y+1,recs);
3253          recs=r;
3254        }
3255      }
3256
3257
3258
3259      do
3260      {
3261        sl[x]=get_color(color,x-startx,y-starty,p);
3262        if (y>0)
3263        { above=current_level->get_fgline(y-1);
3264          if (x>0 && fgvalue(above[x-1])!=fgvalue(fcolor) && fgvalue(above[x])==fgvalue(fcolor))
3265          { r=new fill_rec(x,y-1,recs);
3266            recs=r;
3267          }
3268        }
3269        if (y<current_level->foreground_height()-1)
3270        { below=current_level->get_fgline(y+1);
3271          if (x>0 && fgvalue(below[x-1])!=fgvalue(fcolor) && fgvalue(below[x])==fgvalue(fcolor))
3272          { r=new fill_rec(x,y+1,recs);
3273            recs=r;
3274          }
3275        }
3276        x++;
3277      } while (fgvalue(sl[x])==fgvalue(fcolor) && x<current_level->foreground_width());
3278      x--;
3279      if (y>0)
3280      {
3281        above=current_level->get_fgline(y-1);
3282        if (fgvalue(above[x])==fgvalue(fcolor))
3283        { r=new fill_rec(x,y-1,recs);
3284          recs=r;
3285        }
3286      }
3287      if (y<current_level->foreground_height()-1)
3288      {
3289        above=current_level->get_fgline(y+1);
3290        if (fgvalue(above[x])==fgvalue(fcolor))
3291        { r=new fill_rec(x,y+1,recs);
3292          recs=r;
3293        }
3294      }
3295    }
3296  } while (recs);
3297  the_game->need_refresh();
3298}
3299
3300static int get_char_mem(int type, int print)
3301{
3302  int t=0;
3303  for (int j=0; j<MAX_STATE; j++)
3304  {
3305    if (figures[type]->has_sequence((character_state)j))
3306    {
3307      int s=figures[type]->get_sequence((character_state)j)->MemUsage();
3308      if (print)
3309        dprintf("(%s=%d)",state_names[j],s);
3310      t+=s;
3311    }
3312  }
3313  if (print)
3314    dprintf("\ntotal=%d\n",t);
3315  return t;
3316}
3317
3318void dev_controll::show_char_mem(char const *name)
3319{
3320  int find=-1;
3321  for (int i=0; i<total_objects; i++)
3322  {
3323    if (!strcmp(name,object_names[i]))
3324      find=i;
3325  }
3326  if (find<0)
3327    dprintf("No character '%s' defined\n",name);
3328  else
3329    get_char_mem(find,1);
3330
3331}
3332
3333void dev_controll::show_mem()
3334{
3335  int t=0,s=0;
3336  int i=0;
3337  for (; i<nforetiles; i++)
3338  {
3339    if (foretiles[i]>=0)
3340    {
3341      if (cache.loaded(foretiles[i]))
3342      {
3343    t++;
3344    s+=cache.foret(foretiles[i])->size();
3345      }
3346    }
3347  }
3348  dprintf("%d loaded foretiles=%d bytes\n",t,s);
3349
3350  t=0; s=0;
3351  for (i=0; i<nbacktiles; i++)
3352  {
3353    if (backtiles[i]>=0)
3354    {
3355      if (cache.loaded(foretiles[i]))
3356      {
3357    t++;
3358    s+=cache.backt(backtiles[i])->size();
3359      }
3360    }
3361  }
3362  dprintf("%d loaded backtiles=%d bytes\n",t,s);
3363
3364  t=0; s=0;
3365  for (i=0; i<total_objects; i++)
3366  {
3367    t++;
3368    s+=get_char_mem(i,0);
3369  }
3370  dprintf("%d character=%d bytes\n",t,s);
3371
3372}
3373
3374
3375
3376void dev_cleanup()
3377{
3378  if (start_edit)
3379    prop->save("defaults.prp");
3380  delete prop;
3381  if (listable_objs)
3382  {
3383    free(listable_objs);
3384    listable_objs=NULL;
3385  }
3386  crc_manager.clean_up();
3387
3388}
3389
3390
3391
3392struct pmi
3393{
3394  char const *name;
3395  int id;
3396  char const *on_off;
3397  int key;
3398} ;
3399
3400
3401static pmi filemenu[]={
3402          { "menu1_load",         ID_LEVEL_LOAD,NULL,-1},
3403      { NULL,0,NULL,-1},
3404      { "menu1_save",     ID_LEVEL_SAVE,NULL,-1},
3405      { "menu1_saveas",      ID_LEVEL_SAVEAS,NULL,-1},
3406      { "menu1_savegame",          ID_GAME_SAVE,NULL,-1},
3407      { "menu1_new",          ID_LEVEL_NEW,NULL,-1},
3408      { "menu1_resize",         ID_LEVEL_RESIZE,NULL,-1},
3409      { NULL,0,NULL,-1},
3410      { "menu1_suspend",ID_SUSPEND,NULL,-1},
3411      { "menu1_toggle",ID_PLAY_MODE,NULL,-1},
3412      { NULL,0,NULL,-1},
3413      { "menu1_savepal",ID_EDIT_SAVE,NULL,-1},
3414//      { "menu1_startc",ID_CACHE_PROFILE,NULL,-1},
3415//      { "menu1_endc",ID_CACHE_PROFILE_END,NULL,-1},
3416      { NULL,0,NULL,-1},
3417      { "menu1_quit",      ID_QUIT,NULL,-1},
3418      { NULL,-1,NULL,-1}
3419    };
3420
3421
3422static pmi editmenu[]={
3423  { "menu2_light",               ID_TOGGLE_LIGHT,NULL,-1},
3424  { "menu2_scroll",            ID_SET_SCROLL,NULL,-1},
3425  { "menu2_center",       ID_CENTER_PLAYER,NULL,-1},
3426  { "menu2_addpal",                ID_ADD_PALETTE,NULL,-1},
3427  { "menu2_delay",          ID_TOGGLE_DELAY,NULL,-1},
3428
3429  { "menu2_god",                   ID_GOD_MODE,NULL,-1},
3430  { "menu2_clear",          ID_CLEAR_WEAPONS,NULL,-1},
3431  { "menu2_mscroll",               ID_MOUSE_SCROLL,&mouse_scrolling,-1},
3432  { "menu2_lock",       ID_LOCK_PALETTES,&palettes_locked,-1},
3433  { "menu2_raise",       ID_RAISE_ALL,&raise_all,-1},
3434  { "menu2_names",        ID_TOGGLE_NAMES,&show_names,-1},
3435
3436  { NULL,0,NULL,-1},
3437  { "menu2_map",      ID_TOGGLE_MAP,NULL,-1},
3438//  { "Shrink to 320x200 (F10)",    ID_SMALL_MODE,NULL,-1},
3439  { "menu2_view",        ID_DISABLE_VIEW_SHIFT,&view_shift_disabled,-1},
3440//  { "Ultra Smooth draw (U)",      ID_INTERPOLATE_DRAW,  &interpolate_draw,'U'},
3441  { "menu2_alight",      ID_DISABLE_AUTOLIGHT, &disable_autolight,'A'},
3442  { "menu2_fps",         ID_SHOW_FPS,          &fps_on,-1},
3443//  { NULL,0,NULL,-1},
3444//  { "Record demo",                ID_RECORD_DEMO,NULL,-1},
3445//  { "Play demo",                  ID_PLAY_DEMO,NULL,-1},
3446  { NULL,-1,NULL,-1}
3447};
3448
3449
3450
3451// Window Menus
3452static pmi winmenu[]={
3453          { "menu3_fore",    ID_WIN_FORE,    &forew_on,-1},
3454          { "menu3_back",    ID_WIN_BACK,    &backw_on,-1},
3455          { "menu3_layers",    ID_WIN_LAYERS,  &show_menu_on,-1},
3456      { "menu3_light",    ID_WIN_LIGHTING,&ledit_on,-1},
3457      { "menu3_pal",    ID_WIN_PALETTES,&pmenu_on,-1},
3458      { "menu3_objs",    ID_WIN_OBJECTS, &omenu_on,-1},
3459//      { "menu3_console",    ID_WIN_CONSOLE, &commandw_on,-1},
3460      { "menu3_toolbar",    ID_WIN_TOOLBAR, &tbw_on,-1},
3461//      { "Search      (s)",    ID_SEARCH,      &searchw_on,-1},
3462      { "menu3_prof",    ID_PROFILE,     &profile_on,-1},
3463      { "menu3_save",     ID_SAVE_WINDOWS,NULL,-1},
3464      { NULL,-1,NULL,-1}
3465    };
3466
3467
3468
3469/*
3470static pmi filemenu[]={
3471          { "Load Level",         ID_LEVEL_LOAD,NULL,-1},
3472      { NULL,0,NULL,-1},
3473      { "Save Level (S)",     ID_LEVEL_SAVE,NULL,-1},
3474      { "Save level as",      ID_LEVEL_SAVEAS,NULL,-1},
3475      { "Save game",          ID_GAME_SAVE,NULL,-1},
3476      { "New level",          ID_LEVEL_NEW,NULL,-1},
3477      { "Resize map",         ID_LEVEL_RESIZE,NULL,-1},
3478      { NULL,0,NULL,-1},
3479      { "Suspend non-players",ID_SUSPEND,NULL,-1},
3480      { "Play mode toggle (TAB)",ID_PLAY_MODE,NULL,-1},
3481      { NULL,0,NULL,-1},
3482      { "Save Palettes         ",ID_EDIT_SAVE,NULL,-1},
3483      { "Start cache profile   ",ID_CACHE_PROFILE,NULL,-1},
3484      { "End cache profile     ",ID_CACHE_PROFILE_END,NULL,-1},
3485      { NULL,0,NULL,-1},
3486      { "Quit      (Q)",      ID_QUIT,NULL,-1},
3487      { NULL,-1,NULL,-1}
3488    };
3489
3490
3491static pmi editmenu[]={
3492  { "Toggle light",               ID_TOGGLE_LIGHT,NULL,-1},
3493  { "Set scroll rate",            ID_SET_SCROLL,NULL,-1},
3494  { "Center on player   (c)",       ID_CENTER_PLAYER,NULL,-1},
3495  { "Add palette",                ID_ADD_PALETTE,NULL,-1},
3496  { "Toggle Delays      (D)",          ID_TOGGLE_DELAY,NULL,-1},
3497
3498  { "God mode",                   ID_GOD_MODE,NULL,-1},
3499  { "Clear weapons (z)",          ID_CLEAR_WEAPONS,NULL,-1},
3500  { "Mouse scroll",               ID_MOUSE_SCROLL,&mouse_scrolling,-1},
3501  { "Lock palette windows",       ID_LOCK_PALETTES,&palettes_locked,-1},
3502  { "Raise all foreground",       ID_RAISE_ALL,&raise_all,-1},
3503  { "Toggle object names",        ID_TOGGLE_NAMES,&show_names,-1},
3504
3505  { NULL,0,NULL,-1},
3506  { "Toggle map        (m)",      ID_TOGGLE_MAP,NULL,-1},
3507//  { "Shrink to 320x200 (F10)",    ID_SMALL_MODE,NULL,-1},
3508  { "Disable view shifts",        ID_DISABLE_VIEW_SHIFT,&view_shift_disabled,-1},
3509//  { "Ultra Smooth draw (U)",      ID_INTERPOLATE_DRAW,  &interpolate_draw,'U'},
3510  { "Disable Autolight (A)",      ID_DISABLE_AUTOLIGHT, &disable_autolight,'A'},
3511  { "Show FPS/Obj count",         ID_SHOW_FPS,          &fps_on,-1},
3512//  { NULL,0,NULL,-1},
3513//  { "Record demo",                ID_RECORD_DEMO,NULL,-1},
3514//  { "Play demo",                  ID_PLAY_DEMO,NULL,-1},
3515  { NULL,-1,NULL,-1}
3516};
3517
3518
3519
3520// Window Menus
3521static pmi winmenu[]={
3522          { "Foreground  (f)",    ID_WIN_FORE,    &forew_on,-1},
3523          { "Background  (b)",    ID_WIN_BACK,    &backw_on,-1},
3524          { "Draw layers (L)",    ID_WIN_LAYERS,  &show_menu_on,-1},
3525      { "Lighting    (l)",    ID_WIN_LIGHTING,&ledit_on,-1},
3526      { "Palettes    (p)",    ID_WIN_PALETTES,&pmenu_on,-1},
3527      { "Objects     (o)",    ID_WIN_OBJECTS, &omenu_on,-1},
3528      { "Console     (/)",    ID_WIN_CONSOLE, &commandw_on,-1},
3529      { "Tool Bar    (a)",    ID_WIN_TOOLBAR, &tbw_on,-1},
3530//      { "Search      (s)",    ID_SEARCH,      &searchw_on,-1},
3531      { "Profile     (P)",    ID_PROFILE,     &profile_on,-1},
3532      { "Save positions",     ID_SAVE_WINDOWS,NULL,-1},
3533      { NULL,-1,NULL,-1}
3534    };
3535
3536*/
3537
3538static pmenu_item *i_recurse(pmi *first)
3539{
3540  if (first->id==-1)
3541    return NULL;
3542  else
3543    return new pmenu_item(first->id,first->name ? symbol_str(first->name) : 0,first->on_off,first->key,i_recurse(first+1));
3544}
3545
3546static pmenu *make_menu(int x, int y)
3547{
3548  return new pmenu(x,y,
3549         new pmenu_item(symbol_str("file_top"),new psub_menu(i_recurse(filemenu),NULL),
3550     new pmenu_item(symbol_str("edit_top"),new psub_menu(i_recurse(editmenu),NULL),
3551     new pmenu_item(symbol_str("window_top"),new psub_menu(i_recurse(winmenu),NULL),NULL))),main_screen);
3552}
3553
3554
3555
3556void toggle_edit_mode()
3557{
3558  dev=dev^EDIT_MODE;
3559  if (dev&EDIT_MODE)
3560  {
3561    wm->SetMouseShape(cache.img(c_normal)->copy(), vec2i(1, 1));
3562    pal->load();
3563  }
3564  else
3565  {
3566    if (dev&MAP_MODE) dev-=MAP_MODE;                        // no map mode while playing!
3567    wm->SetMouseShape(cache.img(c_target)->copy(), vec2i(8, 8));
3568  }
3569  if ((dev&EDIT_MODE) && !dev_menu)
3570  {
3571    dev_menu=make_menu(0,yres-wm->font()->Size().y-5);
3572  }
3573  else if (!(dev&EDIT_MODE) && dev_menu)
3574  {
3575    delete dev_menu;
3576    dev_menu=NULL;
3577  }
3578}
3579
3580
3581int dev_controll::ok_to_scroll()
3582{
3583  if (state==DEV_MOVE_LIGHT || state==DEV_MOVE_OBJECT || mouse_scrolling) return 1;
3584  else return 0;
3585}
3586
3587dev_controll::~dev_controll()
3588{
3589  for (int i=0; i<total_pals; i++)
3590    delete pal_wins[i];
3591  if (total_pals)
3592    free(pal_wins);
3593}
3594
3595
3596
3597pal_win::~pal_win()
3598{
3599  free(pat);
3600  free(name);
3601}
Note: See TracBrowser for help on using the repository browser.