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

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