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

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