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

Last change on this file since 496 was 496, checked in by Sam Hocevar, 7 years ago

lisp: implement LObject::Eval.

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