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

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