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

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