home *** CD-ROM | disk | FTP | other *** search
/ Toolkit for DOOM / DOOMTOOL.ISO / editors / dme301.zip / SOURCE.ZIP / THINGS.C < prev    next >
C/C++ Source or Header  |  1994-08-11  |  19KB  |  913 lines

  1. /*
  2.     This is a DMapEdit source code module.  Though it is copyrighted, you
  3.     may modify it and use it for your own personal use, meaning that new
  4.     modified code and anything derived from it (such as exe files) doesn't
  5.     get distributed to anyone, unless you get my permission first.  Code
  6.     from this file, or code based on ideas from this file may be used with
  7.     other programs, provided that you give credit for it in the source code,
  8.     documentation, and 'about' windows or screens, if one exists, for the
  9.     programs using it.  Giving credit means something like this:
  10.  
  11.     Code from DMapEdit was used in this program
  12.  
  13.                               or
  14.  
  15.     Some code for this program was based on ideas presented in DMapEdit
  16.  
  17.     Whatever.  Just be sure to mention "DMapEdit" in such a way that it's
  18.     self-evident how it was useful to the new program, and be sure to have
  19.     "DMapEdit is a trademark of Jason Hoffoss" in the docs.  That's all..
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <math.h>
  25. #include <string.h>
  26. #include <graphics.h>
  27. #include <conio.h>
  28. #include "dme.h"
  29. #include "dme2.h"
  30.  
  31. void mark_thing(int num);
  32. void update_button(int num);
  33.  
  34. extern int old_mark_color;
  35. extern int thing_rad[96]; /* thing's radius */
  36.  
  37. int cur_box_color=0; /* color of selection box */
  38. int default_type=2007; /* default type of added things */
  39. int default_angle=0; /* default angle of added things */
  40. int default_flags=7; /* default flags of added things */
  41. uint tshape;
  42.  
  43. int thing_edit(void)
  44. {
  45.     char name[41], msg[81], msg2[81], flags[9];
  46.     int i, z, cur_thing=-1, new_thing, dx, dy;
  47.     int dis, dis_min, shape_no, num, type;
  48.  
  49.     mark_mask = 4;
  50.     mouse_on();
  51.     sync_time();
  52.     while (1)
  53.     {
  54.         mouse_check();
  55.         dis_min = 15;
  56.         new_thing = -1;
  57.         for (i=0; i<lthing_count; i++)
  58.         {
  59.             dx = mousex - lthingx[i];
  60.             dy = mousey - lthingy[i];
  61.             if ((dis = abs(dx) + abs(dy)) < dis_min)
  62.             {
  63.                 dis_min = dis;
  64.                 new_thing = i;
  65.             }
  66.         }
  67.  
  68.         if (new_thing != cur_thing)
  69.         {
  70.             if (cur_thing != -1)
  71.             {
  72.                 setcolor(cur_box_color);
  73.                 cur_box_color = 0;
  74.                 box_local_thing(cur_thing);
  75.             }
  76.  
  77.             if (new_thing != -1)
  78.             {
  79.                 strcpy(name, "???");
  80.                 num = lthing_num[new_thing];
  81.                 type = things[num].type;
  82.                 for (i=0; i<thing_max; i++)
  83.                 {
  84.                     if (thing_types[i] == type)
  85.                     {
  86.                         _fstrcpy(name, thing_names[i]);
  87.                         break;
  88.                     }
  89.                 }
  90.                 strcpy(flags, "....");
  91.                 if (things[num].flags & 1)
  92.                 {
  93.                     flags[0] = '1';
  94.                     flags[1] = '2';
  95.                 }
  96.                 if (things[num].flags & 2)
  97.                     flags[2] = '3';
  98.                 if (things[num].flags & 4)
  99.                     flags[3] = '4';
  100.                 if (testmode)
  101.                 {
  102.                     strcat(flags, ".....");
  103.                     if (things[num].flags & 0x8)
  104.                         flags[4] = 'd';
  105.                     if (things[num].flags & 0x10)
  106.                         flags[5] = 'D';
  107.                     if (things[num].flags & 0x20)
  108.                         flags[6] = '?';
  109.                     if (things[num].flags & 0x40)
  110.                         flags[7] = '?';
  111.                     if (things[num].flags & 0x80)
  112.                         flags[8] = '?';
  113.                 }
  114.                 sprintf(msg, "Item #%d: Type=%d (%s)", num, type, name);
  115.                 if (things[num].flags & 0x8)
  116.                     strcat(msg, " Deaf");
  117.                 sprintf(msg2, "Angle: %d degrees, Skill levels: %s",
  118.                     things[num].angle, flags);
  119.                 if (things[num].flags & 0x10)
  120.                     strcat(msg2, ", Deathmatch mode thing");
  121.                 toptext2(msg, msg2);
  122.             } else toptext2("", "");
  123.             cur_thing = new_thing;
  124.         }
  125.  
  126.         if (wait(8))
  127.         {
  128.             if (cur_thing != -1)
  129.             {
  130.                 z = lthing_num[cur_thing];
  131.                 for (i=0; i<*mthings; i++)
  132.                     if (mthings[i+2] == z)
  133.                     {
  134.                         z = -9;
  135.                         break;
  136.                     }
  137.             }
  138.  
  139.             if (*mthings)
  140.             {
  141.                 plot_marked(-1);
  142.                 if (cur_thing != -1)
  143.                     color_num--;
  144.             }
  145.  
  146.             if (cur_thing != -1)
  147.             {
  148.                 if (z == -9)
  149.                     i = rand_color() ^ old_mark_color;
  150.                 else
  151.                     i = rand_color();
  152.                 setcolor(i ^ cur_box_color);
  153.                 cur_box_color = i;
  154.                 box_local_thing(cur_thing);
  155.             }
  156.       }
  157.  
  158.         if (button_status & 1)
  159.         {
  160.             if (*mthings)
  161.             {
  162.                 if (cur_thing != -1)
  163.                 {
  164.                     setcolor(cur_box_color);
  165.                     box_local_thing(cur_thing);
  166.                     cur_box_color = 0;
  167.                 }
  168.                 edit_mode = 1;
  169.                 return 0;
  170.             }
  171.  
  172.             if (cur_thing != -1)
  173.             {
  174.                 edit_mode = 1;
  175.                 cur_drag = cur_thing;
  176.                 return 0;
  177.             }
  178.  
  179.             if (t_size == t_max)
  180.             {
  181.                 void far *ptr;
  182.  
  183.                 if (t_max)
  184.                     ptr = resize_farmem(things, (t_max+20) * sizeof(struct
  185.                         t_struct), "Things");
  186.                 else
  187.                     ptr = get_farmem(20 * sizeof(struct t_struct), "Things");
  188.  
  189.                 if (!ptr)
  190.                 {
  191.                     error("Maximum number of Things reached");
  192.                     draw_map();
  193.                     return 0;
  194.                 }
  195.                 things = ptr;
  196.                 t_max += 20;
  197.             }
  198.  
  199.             things[t_size].x = re_x();
  200.             things[t_size].y = re_y();
  201.             things[t_size].angle = default_angle;
  202.             things[t_size].type = default_type;
  203.             things[t_size++].flags = default_flags;
  204.  
  205.             if (things_on == 2)
  206.                 z = shp_offsets[1];
  207.             else
  208.                 z = shp_offsets[0];
  209.             dis = 8 / scalers[scale] * 2;
  210.  
  211.             for (i=0; i<thing_max; i++)
  212.             {
  213.                 if (thing_types[i] == default_type)
  214.                 {
  215.                     if (things_on == 2)
  216.                         z = shp_offsets[thing_shapes[i]+1];
  217.                     else
  218.                         z = shp_offsets[thing_shapes[i]];
  219.                     dis = thing_rad[i] / scalers[scale] * 2;
  220.                     break;
  221.                 }
  222.             }
  223.  
  224.             lthing_num[lthing_count] = t_size - 1;
  225.             lthingx[lthing_count] = crossx + 2;
  226.             lthingy[lthing_count] = crossy + 2;
  227.             if (things_on == -1)
  228.                 lthing_offsets[lthing_count] = dis;
  229.             else
  230.                 lthing_offsets[lthing_count] = z;
  231.             cur_drag = lthing_count++;
  232.  
  233.             edit_mode = 1;
  234.             return 0;
  235.         }
  236.  
  237.         if (button_status & 2)
  238.         {
  239.             if (marked)
  240.             {
  241.                 sort_marked(mthings);
  242.                 i = *mthings;
  243.                 while (i--)
  244.                     del_thing(mthings[i+2]);
  245.  
  246.                 unmark_all();
  247.                 cur_thing = -1;
  248.                 draw_map();
  249.                 await_release_on();
  250.  
  251.             } else if (cur_thing != -1) {
  252.                 del_thing(lthing_num[cur_thing]);
  253.                 cur_thing = -1;
  254.                 draw_map();
  255.                 await_release_on();
  256.             }
  257.         }
  258.  
  259.         if (button_status & 4)
  260.         {
  261.             plot_marked(0);
  262.             if (cur_thing == -1)
  263.                 change_thing(-1);
  264.             else
  265.                 change_thing(lthing_num[cur_thing]);
  266.             return 0;
  267.         }
  268.  
  269.         if (button_status & 8)
  270.         {
  271.             mouse_off();
  272.             if (cur_thing != -1)
  273.             {
  274.                 setcolor(cur_box_color);
  275.                 box_local_thing(cur_thing);
  276.                 cur_box_color = 0;
  277.             }
  278.  
  279.             if (!boxmark(4) && cur_thing != -1)
  280.                 mark_thing(cur_thing);
  281.         }
  282.  
  283.         if (keypress)
  284.         {
  285.             if (keypress == 13)
  286.             {
  287.                 if (cur_thing != -1)
  288.                 {
  289.                     i = lthing_num[cur_thing];
  290.                     default_type = things[i].type;
  291.                     default_angle = things[i].angle;
  292.                     default_flags = things[i].flags;
  293.                 }
  294.             } else {
  295.                 mouse_off();
  296.                 if (cur_thing != -1)
  297.                 {
  298.                     setcolor(cur_box_color);
  299.                     box_local_thing(cur_thing);
  300.                     cur_box_color = 0;
  301.                 }
  302.                 plot_marked(0);
  303.                 toptext2("", "");
  304.                 return keypress;
  305.             }
  306.         }
  307.     }
  308. }
  309.  
  310. void change_thing(int thing)
  311. {
  312.     char msg[4096], title[41], desc[41], old_image[4096];
  313.     int i, num, type, angle, flags, shape, x=38, y=20, init=0;
  314.     int masks[] = { 0x01, 0x02, 0x04, 0x10, 0x8 };
  315.     int angles[] = { 90, 135, 45, 180, 0, 225, 315, 270 };
  316.  
  317.     mouse_off();
  318.     strcpy(title, "Change default Thing");
  319.     type = default_type;
  320.     angle = default_angle;
  321.     flags = default_flags;
  322.  
  323.     if (thing != -1)
  324.     {
  325.         sprintf(title, "Change Thing #%d", thing);
  326.         type = things[thing].type;
  327.         angle = things[thing].angle;
  328.         flags = things[thing].flags;
  329.     }
  330.  
  331.     if (*mthings)
  332.     {
  333.         strcpy(title, "Change marked Things");
  334.         init = -2;
  335.     }
  336.     set_button_statuses(init);
  337.  
  338. relist:
  339.     set_window(x, y, 1);
  340.     strcpy(desc, "???");
  341.     shape = 0;
  342.     for (i=0; i<thing_max; i++)
  343.     {
  344.         if (thing_types[i] == type)
  345.         {
  346.             _fstrcpy(desc, thing_names[i]);
  347.             shape = thing_shapes[i];
  348.             break;
  349.         }
  350.     }
  351.     sprintf(msg, "%s\t\n"
  352.         "@ Type: %-5d  -or-   [ Picklist ]\t\n"
  353.         "(%s)\t\n", title, type, desc);
  354.     text_to_window(0, 0, msg, x);
  355.  
  356.     sprintf(msg, "Angle: %d degrees\n\n"
  357.         "90\t"
  358.         "135   @   45 \t"
  359.         "@     @\t\n"
  360.         "@       @\t\n"
  361.         "@     @\t"
  362.         "225   @   315\t"
  363.         "270\t\n"
  364.         "@ Other\t", angle);
  365.  
  366.     text_to_window(0, 6, msg, 17);
  367.     text_to_window(0, 12, "|180          0\n", 0);
  368.     text_to_window(17, 9, "Availability:\t\n"
  369.         "@ Skill levels 1 & 2\n"
  370.         "@ Skill level 3\n"
  371.         "@ Skill level 4\n"
  372.         "@ Deathmatch mode\n"
  373.         "@ Deaf\n", 20);
  374.  
  375.     line(51, 127, 91, 127);
  376.     line(71, 109, 71, 145);
  377.     line(57, 115, 85, 139);
  378.     line(57, 139, 85, 115);
  379.  
  380.     draw_buttons();
  381.     set_window_bars();
  382.     draw_item(shape, win.left+2, win.top+2, old_image);
  383.     while (1)
  384.     {
  385.         for (i=1; i<15; i++)
  386.             b.pos[i].on = 0;
  387.  
  388.         for (i=0; i<8; i++)
  389.             if (angle == angles[i])
  390.                 break;
  391.  
  392.         b.pos[i+1].on = 1;
  393.         for (i=0; i<5; i++)
  394.             if (flags & masks[i])
  395.                 b.pos[i+10].on = 1;
  396.  
  397.         if ((num = window_check()) == -1 || num == -99)
  398.             break;
  399.  
  400.         if (button_status & 4 && init && num >= 0)
  401.         {
  402.             if (b.pos[num].status == -2)
  403.                 b.pos[num].status = 0;
  404.             else
  405.                 b.pos[num].status = -2;
  406.  
  407.             if (num > 0 && num < 10)
  408.                 for (i=1; i<10; i++)
  409.                     b.pos[i].status = b.pos[num].status;
  410.  
  411.             draw_buttons();
  412.             continue;
  413.         }
  414.  
  415.         if (num == 0)
  416.         {
  417.             update_button(0);
  418.             type = get_number(11, 2, type, 32767, 0);
  419.             if ((shape = print_typedesc(type)) == thing_max)
  420.                 shape = 0;
  421.             else
  422.                 shape = thing_shapes[shape];
  423.  
  424.             putimage(win.left+2, win.top+2, old_image, 0);
  425.             draw_item(shape, win.left+2, win.top+2, old_image);
  426.             continue;
  427.         }
  428.  
  429.         if (num == -2)
  430.         {
  431.             b.pos[0].status = 0;
  432.             type = picklist(type);
  433.             draw_map();
  434.             await_release();
  435.             goto relist;
  436.         }
  437.  
  438.         if (num < 9)
  439.         {
  440.             for (i=1; i<10; i++)
  441.                 update_button(i);
  442.             angle = angles[num-1];
  443.             print_angle(angle);
  444.             continue;
  445.         }
  446.  
  447.         if (num == 9)
  448.         {
  449.             for (i=1; i<10; i++)
  450.                 update_button(i);
  451.             erase_text(win.left + 60, win.top + 64, 13);
  452.             angle = get_number(7, 6, angle, 359, 0);
  453.             print_angle(angle);
  454.             continue;
  455.         }
  456.  
  457.         update_button(num);
  458.         flags ^= masks[num-10];
  459.     }
  460.  
  461.     if (num == -1)
  462.     {
  463.         if (*mthings)
  464.         {
  465.             int z, mask=0;
  466.  
  467.             for (i=0; i<5; i++)
  468.                 if (b.pos[i+10].status)
  469.                 {
  470.                     flags &= ~masks[i];
  471.                     mask |= masks[i];
  472.                 }
  473.  
  474.             mask |= 0xFFE0;
  475.             flags &= 0x001F;
  476.  
  477.             for (i=0; i<*mthings; i++)
  478.             {
  479.                 z = mthings[i+2];
  480.  
  481.                 if (!b.pos[0].status)
  482.                     things[z].type = type;
  483.                 if (!b.pos[9].status)
  484.                     things[z].angle = angle;
  485.                 things[z].flags &= mask;
  486.                 things[z].flags |= flags;
  487.             }
  488.  
  489.         } else if (thing == -1) {
  490.             default_type = type;
  491.             default_angle = angle;
  492.             default_flags = flags;
  493.  
  494.         } else {
  495.             things[thing].type = type;
  496.             things[thing].angle = angle;
  497.             things[thing].flags &= 0xFFE0; /* don't change unknowns */
  498.             things[thing].flags |= flags;
  499.         }
  500.     }
  501.  
  502.     draw_map();
  503.     await_release();
  504.     set_button_statuses(0);
  505.     return;
  506. }
  507.  
  508. int picklist(int num)
  509. {
  510.     char msg[60], dots[] = "....", temp[6];
  511.     int i, list_num, list_size, columns, rows, type;
  512.     int old_num, new_num, cross_status, repos=0;
  513.     int xx[50], yy[50], index[50], x, y, shp;
  514.  
  515.     rows = (maxy / 20) * 2 - 3; /* make sure it's an odd number */
  516.     columns = thing_name_size + 13;
  517.     list_size = (rows - 7) / 2;
  518.     cross_status = cross_on;
  519.     cross_on = 0;
  520.  
  521.     list_num = 0;
  522.     for (i=0; i<thing_max; i++)
  523.         if (thing_types[i] == num)
  524.         {
  525.             list_num = i - list_size / 2;
  526.             repos = list_size / 2 + 1;
  527.             break;
  528.         }
  529.  
  530. re_list:
  531.     if (list_num < 0)
  532.         list_num += thing_max; /* wrap around */
  533.  
  534.     set_window(columns, rows, 0);
  535.     text_to_window(0, 0, "Select type:\t\n\n[ Back ]\t", columns);
  536.     text_to_window(0, rows-2, "[ More ]\t", columns);
  537.     for (i=0; i<list_size; i++)
  538.     {
  539.         type = thing_types[list_num];
  540.         sprintf(msg, "%s%d: %Fs\n", &dots[strlen(itoa(type, temp, 10))-1],
  541.             type, thing_names[list_num]);
  542.         text_to_window(6, i*2+5, msg, 0);
  543.         yy[i] = i * 20 + 57;
  544.         xx[i] = draw_thing2( (i & 1) * 24 + 14, yy[i], list_num);
  545.         xx[i] += win.left;
  546.         yy[i] += win.top;
  547.         index[i] = list_num++;
  548.         if (list_num >= thing_max)
  549.             list_num = 0;
  550.     }
  551.     draw_buttons();
  552.     set_cancel_bar();
  553.     if (repos)
  554.     {
  555.         mousex = xx[repos-1];
  556.         mousey = yy[repos-1];
  557.         repos = 0;
  558.     }
  559.  
  560.     mouse_on();
  561.     old_num = -1;
  562.  
  563.     while (mouse_check()); /* wait for mouse button release */
  564.     while (1)
  565.     {
  566.         while (!mouse_check() && !keypress)
  567.         {
  568.             new_num = -1;
  569.             for (i=0; i<list_size; i++)
  570.             {
  571.                 if (mousex > win.left+50 && abs(mousey - yy[i]) < 10)
  572.                     new_num = i;
  573.                 if (abs(mousex - xx[i]) + abs(mousey - yy[i]) < 16)
  574.                     new_num = i;
  575.             }
  576.  
  577.             if (new_num != old_num)
  578.             {
  579.                 if (old_num != -1)
  580.                 {
  581.                     mouse_off();
  582.                     box_thing(x, y, shp); /* turn off box */
  583.                     setcolor(255);
  584.                     reprint_line(index[old_num], old_num, columns-6);
  585.                     mouse_on();
  586.                 }
  587.                 if (new_num != -1)
  588.                 {
  589.                     x = xx[new_num];
  590.                     y = yy[new_num];
  591.                     shp = shp_offsets[thing_shapes[index[new_num]]];
  592.  
  593.                     mouse_off();
  594.                     box_thing(x, y, shp); /* turn on box */
  595.                     setcolor(254);
  596.                     reprint_line(index[new_num], new_num, columns-6);
  597.                     mouse_on();
  598.                 }
  599.                 old_num = new_num;
  600.             }
  601.         }
  602.  
  603.         if (keypress)
  604.         {
  605.             if (keypress == 27)
  606.             {
  607.                 mouse_off();
  608.                 cross_on = cross_status;
  609.                 return num;
  610.             }
  611.  
  612.             if (keypress == 13 && new_num != -1)
  613.             {
  614.                 mouse_off();
  615.                 cross_on = cross_status;
  616.                 return thing_types[index[new_num]];
  617.             }
  618.  
  619.             if (keypress == 1073) /* page up */
  620.             {
  621.                 list_num -= list_size * 2;
  622.                 mouse_off();
  623.                 goto re_list;
  624.             }
  625.  
  626.             if (keypress == 1081) /* page down */
  627.             {
  628.                 mouse_off();
  629.                 goto re_list;
  630.             }
  631.  
  632.             if (keypress == 1071) /* home */
  633.             {
  634.                 list_num = 0;
  635.                 mouse_off();
  636.                 goto re_list;
  637.             }
  638.             continue; /* end of key checks, below is mouse button pressed */
  639.         }
  640.  
  641.         if (mousex < win.canbar + 47 &&
  642.             mousex > win.canbar + 2 &&
  643.             mousey < win.bottom + 9 &&
  644.             mousey > win.bottom - 2)
  645.         {
  646.             mouse_off();
  647.             cross_on = cross_status;
  648.             return num;
  649.         }
  650.  
  651.         if (line_dist(bigb.pos[0].x1, bigb.pos[0].y,
  652.             bigb.pos[0].x2, bigb.pos[0].y) < 7)
  653.         {
  654.             list_num -= list_size * 2;
  655.             mouse_off();
  656.             goto re_list;
  657.         }
  658.  
  659.         if (line_dist(bigb.pos[1].x1, bigb.pos[1].y,
  660.             bigb.pos[1].x2, bigb.pos[1].y) < 7)
  661.         {
  662.             mouse_off();
  663.             goto re_list;
  664.         }
  665.  
  666.         if (new_num != -1)
  667.         {
  668.             mouse_off();
  669.             cross_on = cross_status;
  670.             return thing_types[index[new_num]];
  671.         }
  672.     }
  673. }
  674.  
  675. void reprint_line(int num, int yy, int max)
  676. {
  677.     char msg[41], dots[] = "....", temp[6];
  678.     int x, y, type;
  679.  
  680.     x = win.left + 52;
  681.     y = win.top + yy * 20 + 54;
  682.     type = thing_types[num];
  683.     sprintf(msg, "%s%d: %Fs", &dots[strlen(itoa(type, temp, 10))-1],
  684.         type, thing_names[num]);
  685.     erase_text(x, y, max);
  686.     outtextxy(x, y, msg);
  687.     return;
  688. }
  689.  
  690. int draw_thing2(int xpos, int ypos, int num)
  691. {
  692.     char far *shape;
  693.     int i, shape_no;
  694.     int xsize, ysize; /* size of shape */
  695.     int xhalf, yhalf; /* size of half the shape */
  696.  
  697.     shape_no = thing_shapes[num];
  698.     if (shape_no > 9 && shape_no < 170) /* monster shape */
  699.         shape_no += 4;
  700.     if (shape_no >= no_shapes)
  701.         fatal_error("shape # out of bounds");
  702.     shape = shapes + shp_offsets[shape_no]; /* point to the shape */
  703.     xhalf = *shape >> 1; /* quick div by 2 */
  704.     yhalf = *(shape+2) >> 1;
  705.  
  706.     if ((xpos - xhalf) < 4)
  707.         xpos = xhalf + 4;
  708.     if ((xpos + xhalf) > 49)
  709.         xpos = 49 - xhalf;
  710.  
  711.     putimage(xpos-xhalf, ypos-yhalf, shape, 3);
  712.     return xpos;
  713. }
  714.  
  715. int print_typedesc(int num)
  716. {
  717.     char desc[41];
  718.     int i, x, y;
  719.  
  720.     strcpy(desc, "(???)");
  721.     for (i=0; i<thing_max; i++)
  722.     {
  723.         if (thing_types[i] == num)
  724.         {
  725.             sprintf(desc, "(%Fs)", thing_names[i]);
  726.             break;
  727.         }
  728.     }
  729.  
  730.     x = (win.left + win.right) / 2 - strlen(desc)*4 + 2;
  731.     y = win.top + 44;
  732.     erase_text(win.left, y, 38);
  733.     outtextxy(x, y, desc);
  734.     return i;
  735. }
  736.  
  737. void print_angle(int num)
  738. {
  739.     char msg[14];
  740.     int x, y;
  741.  
  742.     x = win.left + 60;
  743.     y = win.top + 64;
  744.     erase_text(x, y, 13);
  745.     sprintf(msg, "%d degrees", num);
  746.     outtextxy(x, y, msg);
  747.     return;
  748. }
  749.  
  750. void box_local_thing(int num)
  751. {
  752.     int m;
  753.  
  754.     if (num == -1) return;
  755.  
  756.     if (m = mouse)
  757.         mouse_off();
  758.     if (things_on != -1)
  759.         box_thing(lthingx[num], lthingy[num], lthing_offsets[num]);
  760.     else {
  761.         int x, y, x1, y1, x2, y2, rad;
  762.  
  763.         x = lthingx[num];
  764.         y = lthingy[num];
  765.         rad = lthing_offsets[num];
  766.         x1 = x - rad - 1;
  767.         y1 = y - rad - 1;
  768.         x2 = x + rad + 1;
  769.         y2 = y + rad + 1;
  770.  
  771.         setwritemode(XOR_PUT);
  772.         line(x1, y1, x2, y1);
  773.         line(x1, y1+1, x1, y2-1);
  774.         line(x2, y1+1, x2, y2-1);
  775.         line(x1, y2, x2, y2);
  776.         setwritemode(COPY_PUT);
  777.     }
  778.     if (m)
  779.         mouse_on();
  780.     return;
  781. }
  782.  
  783. void box_thing(int x1, int y1, uint offset)
  784. {
  785.     char far *ptr;
  786.     int x2, y2;
  787.  
  788.     ptr = shapes + offset;
  789.     x1 -= (ptr[0] >> 1) + 1;
  790.     y1 -= (ptr[2] >> 1) + 1;
  791.     x2 = x1 + ptr[0] + 2;
  792.     y2 = y1 + ptr[2] + 2;
  793.  
  794.     setwritemode(XOR_PUT);
  795.     line(x1, y1, x2, y1);
  796.     line(x1, y1+1, x1, y2-1);
  797.     line(x2, y1+1, x2, y2-1);
  798.     line(x1, y2, x2, y2);
  799.     setwritemode(COPY_PUT);
  800.     return;
  801. }
  802.  
  803. int thing_drag(void)
  804. {
  805.     int i, j, z, x, y, dx, dy, dx2, dy2, origx, origy;
  806.  
  807.     origx = x = crossx + 2;
  808.     origy = y = crossy + 2;
  809.  
  810.     while (1)
  811.     {
  812.         if (crossx+2 != x || crossy+2 != y)
  813.         {
  814.             dx = crossx + 2 - x;
  815.             dy = crossy + 2 - y;
  816.             dx2 = dx * scalers[scale] / 2;
  817.             dy2 = dy * scalers[scale] / 2;
  818.             x = crossx + 2;
  819.             y = crossy + 2;
  820.  
  821.             if (*mthings)
  822.             {
  823.                 plot_marked(0);
  824.                 for (i=0; i<*mthings; i++)
  825.                 {
  826.                     z = mthings[i+2];
  827.                     things[z].x += dx2;
  828.                     things[z].y -= dy2;
  829.  
  830.                     for (j=0; j<lthing_count; j++)
  831.                         if (lthing_num[j] == z)
  832.                         {
  833.                             lthingx[j] += dx;
  834.                             lthingy[j] += dy;
  835.                             break;
  836.                         }
  837.                 }
  838.                 color_num--;
  839.                 plot_marked(-1);
  840.  
  841.             } else {
  842.                 mouse_off();
  843.                 setcolor(cur_box_color);
  844.                 box_local_thing(cur_drag);
  845.  
  846.                 lthingx[cur_drag] += dx;
  847.                 lthingy[cur_drag] += dy;
  848.                 box_local_thing(cur_drag);
  849.                 mouse_on();
  850.  
  851.                 z = lthing_num[cur_drag];
  852.                 things[z].x += dx2;
  853.                 things[z].y -= dy2;
  854.             }
  855.         }
  856.  
  857.         if (wait(8))
  858.         {
  859.             if (marked)
  860.                 plot_marked(-1);
  861.  
  862.             else {
  863.                 i = rand_color();
  864.                 setcolor(i ^ cur_box_color);
  865.                 cur_box_color = i;
  866.                 box_local_thing(cur_drag);
  867.             }
  868.         }
  869.  
  870.         if (!(mouse_check() & 1))
  871.         {
  872.             draw_map();
  873.             old_mark_color = edit_mode = 0;
  874.             return 0;
  875.         }
  876.  
  877.         if (button_status & 2)
  878.         {
  879.             del_thing(cur_drag);
  880.             mouse_off();
  881.             draw_map();
  882.             await_release();
  883.             edit_mode = 0;
  884.             return 0;
  885.         }
  886.     }
  887. }
  888.  
  889. void del_thing(int thing)
  890. {
  891.     int i;
  892.  
  893.     if (thing != t_size-1)
  894.         for (i=thing; i<t_size-1; i++)
  895.             things[i] = things[i+1];
  896.     t_size--;
  897.     return;
  898. }
  899.  
  900. void draw_item(int num, int x, int y, char *save)
  901. {
  902.     char far *shape;
  903.     int xsize, ysize;
  904.  
  905.     shape = shapes + shp_offsets[num]; /* point to the shape */
  906.     xsize = *shape;
  907.     ysize = *(shape+2);
  908.  
  909.     getimage(x, y, x + xsize, y + ysize, save);
  910.     putimage(x, y, shape, 3);
  911.     return;
  912. }
  913.