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

Last change on this file since 115 was 115, checked in by Sam Hocevar, 11 years ago
  • Add lock() and unlock() methods to jimage objects. They're no-ops, but the Win32/DirectX version uses them all over the place because it uses DirectDraw? surfaces. One day we may wish to merge Abuse Win32's video output, or to use the SDL blending functions. You never know.
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.