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

Last change on this file since 112 was 111, checked in by Sam Hocevar, 12 years ago
  • Simplified the window creation arguments. Got rid of a lot of macros and hid stuff in private namespaces.

Inspired by Win32 Abuse changelog for January 28, 2001:

  • Well, in the process of adding changes necessary to

handle recovery from alt-tabbing away from Abuse
(which is why I was updating jwindow::redraw()),
the entire windowing system is getting an overhaul.
It's gonna be sweet when I'm done, though.

  • jwindow::redraw() has been changed to a virtual

function requiring no parameters. This'll make
it much easier to implement special specific-
purpose windows.

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