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

Last change on this file since 481 was 481, checked in by Sam Hocevar, 11 years ago

Fuck the history, I'm renaming all .hpp files to .h for my own sanity.

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