1 /* ---------------------------------------------------------------------- *
2 * mouse.c
3 * This file is part of lincity.
4 * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
5 * ---------------------------------------------------------------------- */
6 #include "lcconfig.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "lcstring.h"
10 #include "common.h"
11 #include "lctypes.h"
12 #include "lcintl.h"
13 #include "lin-city.h"
14 #include "mouse.h"
15 #include "engglobs.h"
16 #include "cliglobs.h"
17 #include "engine.h"
18 #include "screen.h"
19 #include "mps.h"
20 #include "fileutil.h"
21 #include "lchelp.h"
22 #include "pbar.h"
23 #include "lclib.h"
24 #include "module_buttons.h"
25
26 #define DEBUG_MT_CODE 1
27
28 extern Update_Scoreboard update_scoreboard;
29
30 /* ---------------------------------------------------------------------- *
31 * Private global variables
32 * ---------------------------------------------------------------------- */
33 static struct mouse_button_struct buttons[NUM_BUTTONS];
34 static int mt_length;
35 static int mt_grp;
36 static char mt_name[20];
37 static short mouse_buffer_fresh = 0;
38
39 void check_bulldoze_area (int x, int y);
40
41 /* Mouse registry */
42
43 static int mhandle_count;
44
45 static Mouse_Handle * mhandle_first;
46 static Mouse_Handle * mhandle_last;
47 static Mouse_Handle * mhandle_current;
48
49 /* ---------------------------------------------------------------------- *
50 * cs_mouse_handler
51 * --
52 * If the event was a mouse click or mouse release, enc_button contains
53 * the button identifier (e.g. LC_MOUSE_LEFTBUTTON) or'd with the
54 * action identifier (e.g. LC_MOUSE_RELEASE). If the event was just a
55 * mouse move, then enc_button is 0. You cannot specify multiple
56 * mouse buttons clicked at the same time using this interface.
57 * ---------------------------------------------------------------------- */
58
59 void
cs_mouse_handler(int enc_button,int dx,int dy)60 cs_mouse_handler (int enc_button, int dx, int dy)
61 {
62 int x, y;
63 int button = enc_button & ~LC_MOUSE_RELEASE & ~LC_MOUSE_PRESS;
64 int button_pressed = enc_button & LC_MOUSE_PRESS;
65 int button_released = enc_button & LC_MOUSE_RELEASE;
66 int button_idx = button - 1;
67
68 x = cs_mouse_x;
69 y = cs_mouse_y;
70
71 #if defined (SVGALIB)
72 cs_mouse_x += dx * MOUSE_SENSITIVITY;
73 cs_mouse_y += dy * MOUSE_SENSITIVITY;
74 #else
75 cs_mouse_x += dx;
76 cs_mouse_y += dy;
77 #endif
78
79 #if defined (SVGALIB)
80 if (cs_mouse_x >= cs_mouse_xmax)
81 cs_mouse_x = cs_mouse_xmax;
82 if (cs_mouse_y >= cs_mouse_ymax)
83 cs_mouse_y = cs_mouse_ymax;
84 if (cs_mouse_x < 0)
85 cs_mouse_x = 0;
86 if (cs_mouse_y < 0)
87 cs_mouse_y = 0;
88 #endif
89
90 if (cs_mouse_x != x || cs_mouse_y != y)
91 move_mouse (cs_mouse_x, cs_mouse_y);
92 x = cs_mouse_x;
93 y = cs_mouse_y;
94
95 /* see if we are all the way up */
96 if (!mouse_initialized)
97 return;
98
99 /* button press */
100 if (button_pressed) {
101
102 /* maintain button press status */
103 pixel_to_mappoint(cs_mouse_x, cs_mouse_y,
104 &buttons[button_idx].mappoint_x,
105 &buttons[button_idx].mappoint_y);
106 buttons[button_idx].x = cs_mouse_x;
107 buttons[button_idx].y = cs_mouse_y;
108 buttons[button_idx].pressed = 1;
109
110 /* Try the event list before moving on to special cases */
111 if (!mouse_handle_click(x, y, button)) {
112 switch (button) {
113 case LC_MOUSE_LEFTBUTTON:
114 if (market_cb_flag) {
115 do_market_cb_mouse (x, y);
116 break;
117 }
118 else if (port_cb_flag) {
119 do_port_cb_mouse (x, y);
120 break;
121 }
122 else if (help_flag) {
123 do_help_mouse (x, y, button);
124 break;
125 }
126 else if (prefs_flag) {
127 do_prefs_mouse (x, y, button);
128 break;
129 }
130
131 else if (load_flag || save_flag)
132 return;
133
134 /* This is the main screen */
135 if (mouse_in_rect(&scr.main_win,x,y)) {
136 do_mouse_main_win(x, y, button);
137 refresh_main_screen ();
138 break;
139 }
140
141 /* GCS Remove overlay */
142 /* This use of mouse clicks seems to contradict
143 Corey's mouse handler code */
144 if (main_screen_flag == MAIN_SCREEN_EQUALS_MINI) {
145 main_screen_flag = MAIN_SCREEN_NORMAL_FLAG;
146 refresh_main_screen ();
147 }
148
149 /* Other points too */
150 do_mouse_other_buttons(x, y, button);
151
152 break;
153
154 case LC_MOUSE_RIGHTBUTTON:
155 case LC_MOUSE_MIDDLEBUTTON:
156 /* GCS FIX: This is my fix for right clicks on
157 main screen during yn_dialogs causing dialog to
158 be overwritten by screen content (similar effect
159 for market_cb overwritten by mps). This fix could
160 be better, but will be better to confirm behavior
161 for X version before deciding final fix.
162 */
163 if (market_cb_flag) {
164 // should dismiss cb?
165 break;
166 }
167 else if (port_cb_flag) {
168 // should dismiss cb?
169 break;
170 }
171 else if (help_flag) {
172 // do_help_mouse (x, y, button); maybe should??
173 break;
174 }
175 else if (prefs_flag) {
176 break;
177 }
178 else if (db_flag) {
179 break;
180 }
181 else if (db_okflag) {
182 break;
183 }
184 else if (load_flag || save_flag)
185 return;
186
187 /* GCS Remove overlay */
188 if (main_screen_flag == MAIN_SCREEN_EQUALS_MINI) {
189 main_screen_flag = MAIN_SCREEN_NORMAL_FLAG;
190 refresh_main_screen ();
191 }
192
193 /* This is the main screen */
194 if (mouse_in_rect(&scr.main_win,x,y)) {
195 do_mouse_main_win(x, y, button);
196 refresh_main_screen ();
197 break;
198 }
199
200 /* Other points too */
201 do_mouse_other_buttons(x, y, button);
202
203 break;
204
205 default:
206 printf("Unknown mouse button in cs_mouse_handler\n");
207 }
208 } /* mouse_handle_click couldn't. */
209 } else if (button_released) {
210 button = enc_button - 16; /* probably shouldn't use this temporarily */
211
212 pixel_to_mappoint(cs_mouse_x, cs_mouse_y,
213 &buttons[button_idx].r_mappoint_x,
214 &buttons[button_idx].r_mappoint_y);
215
216 buttons[button_idx].r_x = cs_mouse_x;
217 buttons[button_idx].r_y = cs_mouse_y;
218 buttons[button_idx].pressed = 0;
219
220 switch (button) {
221 case LC_MOUSE_LEFTBUTTON:
222 mt_draw(cs_mouse_x, cs_mouse_y, MT_SUCCESS);
223 break;
224 case LC_MOUSE_RIGHTBUTTON:
225 break;
226 case LC_MOUSE_MIDDLEBUTTON:
227 break;
228 default:
229 break;
230 };
231 button = 0; /* backwards compatibility */
232
233 /* mouse moved */
234 } else {
235 if (buttons[LC_MOUSE_LEFTBUTTON-1].pressed
236 && GROUP_IS_TRANSPORT(selected_module_group))
237 {
238 mt_draw(cs_mouse_x, cs_mouse_y, MT_CONTINUE);
239 }
240 }
241 cs_mouse_button = button;
242 }
243
244 void
move_mouse(int x,int y)245 move_mouse (int x, int y)
246 {
247 Rect* mw = &scr.main_win;
248 int size;
249
250 size = (main_groups[selected_module_group].size) * 16;
251
252 /* GCS: we don't check for load_flag/save_flag because these guys
253 set db_flag = 1 */
254 if (mouse_in_rect(&scr.main_win,x,y)
255 && market_cb_flag == 0 && port_cb_flag == 0
256 && prefs_flag == 0 && help_flag == 0
257 && db_flag == 0 && db_okflag == 0)
258 {
259 int mwoffset_x;
260 int mwoffset_y;
261 if (x > (mw->x + mw->w) - size)
262 x = (mw->x + mw->w) - size;
263 if (y > (mw->y + mw->h) - size)
264 y = (mw->y + mw->h) - size;
265 mwoffset_x = mw->x % 16;
266 mwoffset_y = mw->y % 16;
267 x -= mwoffset_x;
268 y -= mwoffset_y;
269 x &= 0xff0;
270 y &= 0xff0;
271 x += mwoffset_x;
272 y += mwoffset_y;
273
274 hide_mouse ();
275 mouse_hide_count--;
276 draw_square_mouse (x, y, size);
277 }
278 else
279 {
280 hide_mouse ();
281 mouse_hide_count--;
282 draw_normal_mouse (x, y);
283 if (mappoint_stats_flag != 0 && market_cb_flag == 0
284 && port_cb_flag == 0)
285 {
286 mappoint_stats_flag = 0;
287 update_scoreboard.mps = 1;
288 }
289 }
290 }
291
292 void
hide_mouse(void)293 hide_mouse (void)
294 {
295 mouse_hide_count++;
296 if (mouse_hide_count == 1) {
297 if (mouse_type == MOUSE_TYPE_SQUARE)
298 hide_square_mouse ();
299 else
300 hide_normal_mouse ();
301 }
302 }
303
304 void
redraw_mouse(void)305 redraw_mouse (void)
306 {
307 mouse_hide_count--;
308 if (mouse_hide_count > 0)
309 return;
310 mouse_hide_count = 0;
311 if (mouse_type == MOUSE_TYPE_SQUARE)
312 redraw_square_mouse ();
313 else
314 redraw_normal_mouse ();
315 }
316
317 void
draw_square_mouse(int x,int y,int size)318 draw_square_mouse (int x, int y, int size) /* size is pixels */
319 {
320 if (mouse_type == MOUSE_TYPE_NORMAL) {
321 hide_normal_mouse ();
322 mouse_type = MOUSE_TYPE_SQUARE;
323 kmouse_val = 16;
324 }
325 omx = x;
326 omy = y;
327 #if defined (WIN32)
328 cs_square_mouse_visible = 1;
329 RefreshArea (omx - 2, omy - 2, omx + size + 1, omy + size + 1);
330 #else
331 Fgl_getbox (x - 2, y - 2, size + 4, 2, under_square_mouse_pointer_top);
332 Fgl_getbox (x - 2, y, 2, size, under_square_mouse_pointer_left);
333 Fgl_getbox (x + size, y, 2, size, under_square_mouse_pointer_right);
334 Fgl_getbox (x - 2, y + size, size + 4, 2, under_square_mouse_pointer_bottom);
335 mouse_buffer_fresh = 1;
336
337 Fgl_hline (x - 2, y - 2, x + size + 1, yellow (31));
338 Fgl_hline (x - 1, y - 1, x + size, blue (31));
339 Fgl_hline (x - 2, y + size + 1, x + size + 1, yellow (31));
340 Fgl_hline (x - 1, y + size, x + size, blue (31));
341 Fgl_line (x - 2, y - 1, x - 2, y + size + 1, yellow (31));
342 Fgl_line (x - 1, y, x - 1, y + size, blue (31));
343 Fgl_line (x + size + 1, y - 1, x + size + 1, y + size + 1, yellow (31));
344 Fgl_line (x + size, y, x + size, y + size, blue (31));
345 #endif
346 }
347
348 void
hide_square_mouse(void)349 hide_square_mouse (void)
350 {
351 int size;
352
353 size = (main_groups[selected_module_group].size) * 16;
354 #if defined (WIN32)
355 cs_square_mouse_visible = 0;
356 RefreshArea (omx - 3, omy - 3, omx + size + 2, omy + size + 2);
357 #else
358 if (mouse_buffer_fresh) {
359 Fgl_putbox (omx - 2, omy - 2, size + 4, 2, under_square_mouse_pointer_top);
360 Fgl_putbox (omx - 2, omy, 2, size, under_square_mouse_pointer_left);
361 Fgl_putbox (omx + size, omy, 2, size, under_square_mouse_pointer_right);
362 Fgl_putbox (omx - 2, omy + size, size + 4, 2,
363 under_square_mouse_pointer_bottom);
364 mouse_buffer_fresh = 0;
365 } else {
366 // printf ("Mouse buffer stale in hide_mouse! Not putting back!\n");
367 }
368 #endif
369 }
370
371 void
redraw_square_mouse(void)372 redraw_square_mouse (void)
373 {
374 int size;
375
376 size = (main_groups[selected_module_group].size) * 16;
377
378 #if defined (WIN32)
379 cs_square_mouse_visible = 1;
380 RefreshArea (omx - 2, omy - 2, omx + size + 1, omy + size + 1);
381 #else
382 Fgl_getbox (omx - 2, omy - 2, size + 4, 2, under_square_mouse_pointer_top);
383 Fgl_getbox (omx - 2, omy, 2, size, under_square_mouse_pointer_left);
384 Fgl_getbox (omx + size, omy, 2, size, under_square_mouse_pointer_right);
385 Fgl_getbox (omx - 2, omy + size, size + 4, 2, under_square_mouse_pointer_bottom);
386 mouse_buffer_fresh = 1;
387
388 Fgl_hline (omx - 2, omy - 2, omx + size + 1, yellow (31));
389 Fgl_hline (omx - 1, omy - 1, omx + size, blue (31));
390 Fgl_hline (omx - 2, omy + size + 1, omx + size + 1, yellow (31));
391 Fgl_hline (omx - 1, omy + size, omx + size, blue (31));
392 Fgl_line (omx - 2, omy - 1, omx - 2, omy + size + 1, yellow (31));
393 Fgl_line (omx - 1, omy, omx - 1, omy + size, blue (31));
394 Fgl_line (omx + size + 1, omy - 1, omx + size + 1, omy + size + 1, yellow (31));
395 Fgl_line (omx + size, omy, omx + size, omy + size, blue (31));
396 #endif
397 }
398
399 void
draw_normal_mouse(int x,int y)400 draw_normal_mouse (int x, int y)
401 {
402 if (mouse_type == MOUSE_TYPE_SQUARE) {
403 hide_square_mouse ();
404 mouse_type = MOUSE_TYPE_NORMAL;
405 kmouse_val = 8;
406 }
407 #if defined (SVGALIB)
408 Fgl_getbox (x, y, 8, 8, under_mouse_pointer);
409 if (x > cs_mouse_xmax - 8 || y > cs_mouse_ymax - 8) {
410 Fgl_enableclipping ();
411 Fgl_setclippingwindow (0, 0, cs_mouse_xmax, cs_mouse_ymax);
412 Fgl_putbox (x, y, 8, 8, mouse_pointer);
413 Fgl_disableclipping ();
414 } else {
415 Fgl_putbox (x, y, 8, 8, mouse_pointer);
416 }
417 #endif
418 mox = x;
419 moy = y;
420 }
421
422 void
hide_normal_mouse(void)423 hide_normal_mouse (void)
424 {
425 #if defined (SVGALIB)
426 if (mox > cs_mouse_xmax - 8 || moy > cs_mouse_ymax - 8) {
427 Fgl_enableclipping ();
428 Fgl_setclippingwindow (0, 0, cs_mouse_xmax, cs_mouse_ymax);
429 Fgl_putbox (mox, moy, 8, 8, under_mouse_pointer);
430 Fgl_disableclipping ();
431 } else {
432 Fgl_putbox (mox, moy, 8, 8, under_mouse_pointer);
433 }
434 #endif
435 }
436
437 void
redraw_normal_mouse(void)438 redraw_normal_mouse (void)
439 {
440 #if defined (SVGALIB)
441 if (mox > cs_mouse_xmax - 8 || moy > cs_mouse_ymax - 8) {
442 Fgl_enableclipping ();
443 Fgl_setclippingwindow (0, 0, cs_mouse_xmax, cs_mouse_ymax);
444 Fgl_getbox (mox, moy, 8, 8, under_mouse_pointer);
445 Fgl_putbox (mox, moy, 8, 8, mouse_pointer);
446 Fgl_disableclipping ();
447 } else {
448 /* may have changed */
449 Fgl_getbox (mox, moy, 8, 8, under_mouse_pointer);
450 Fgl_putbox (mox, moy, 8, 8, mouse_pointer);
451 }
452 #endif
453 }
454
455 void
do_mouse_main_win(int px,int py,int button)456 do_mouse_main_win (int px, int py, int button)
457 {
458 Rect* mw = &scr.main_win;
459 int size;
460 int x, y; /* mappoint */
461 int mod_x, mod_y; /* upper left coords of module clicked on */
462 int mps_result;
463
464 if (button == LC_MOUSE_MIDDLEBUTTON)
465 return;
466
467 pixel_to_mappoint(px, py, &x, &y);
468
469 if (MP_TYPE(x,y) == CST_USED) {
470 mod_x = MP_INFO(x,y).int_1;
471 mod_y = MP_INFO(x,y).int_2;
472 } else {
473 mod_x = x;
474 mod_y = y;
475 }
476
477 /* Bring up mappoint_stats for any right mouse click */
478 /* XXX: Environmental (right click) MPS should show the clicked
479 square, not the master square */
480 if (button == LC_MOUSE_RIGHTBUTTON) {
481 mps_set(mod_x, mod_y, MPS_ENV);
482 return;
483 }
484
485 /* Check rocket launches */
486 /* XXX: put this in modules/rocket.c */
487 /* XXX: wait for second click to ask for launch */
488 if (button == LC_MOUSE_LEFTBUTTON) {
489 if (MP_TYPE(mod_x,mod_y) >= CST_ROCKET_5 &&
490 MP_TYPE(mod_x,mod_y) <= CST_ROCKET_7) {
491 if (ask_launch_rocket_click (mod_x,mod_y)) {
492 launch_rocket (mod_x, mod_y);
493 }
494 }
495 }
496
497 /* Handle multitransport */
498 if (button == LC_MOUSE_LEFTBUTTON &&
499 GROUP_IS_TRANSPORT(selected_module_group)) {
500 if (mt_draw (px, py, MT_START)) {
501 /* We need to set mps to current location, since the user might
502 click on the transport to see the mps */
503
504 mps_set(mod_x, mod_y, MPS_MAP);
505 return;
506 }
507 }
508
509 /* Handle bulldozing */
510 if (selected_module_type == CST_GREEN && button != LC_MOUSE_RIGHTBUTTON) {
511 check_bulldoze_area (x, y);
512 return;
513 }
514
515 /* Bring up mappoint_stats for certain left mouse clicks */
516 /* XXX: Need to check market and port double-clicks here */
517 if (MP_TYPE(x,y) != CST_GREEN) {
518 mps_result = mps_set(mod_x, mod_y, MPS_MAP);
519
520 if (mps_result >= 1) {
521 if (MP_GROUP(mod_x,mod_y) == GROUP_MARKET)
522 {
523 clicked_market_cb (mod_x, mod_y);
524 return;
525 }
526 else if (MP_GROUP(mod_x,mod_y) == GROUP_PORT)
527 {
528 clicked_port_cb (mod_x, mod_y);
529 return;
530 }
531 }
532 return;
533 }
534
535 /* OK, by now we are certain that the user wants to place the item.
536 Set the origin based on the size of the selected_module_type, and
537 see if the selected item will fit. */
538 size = main_groups[selected_module_group].size;
539 if (px > (mw->x + mw->w) - size*16)
540 px = (mw->x + mw->w) - size*16;
541 if (py > (mw->y + mw->h) - size*16)
542 py = (mw->y + mw->h) - size*16;
543 pixel_to_mappoint(px, py, &x, &y);
544
545 if (size >= 2)
546 {
547 if (MP_TYPE(x + 1,y) != CST_GREEN
548 || MP_TYPE(x,y + 1) != CST_GREEN
549 || MP_TYPE(x + 1,y + 1) != CST_GREEN)
550 return;
551 }
552 if (size >= 3)
553 {
554 if (MP_TYPE(x + 2,y) != CST_GREEN
555 || MP_TYPE(x + 2,y + 1) != CST_GREEN
556 || MP_TYPE(x + 2,y + 2) != CST_GREEN
557 || MP_TYPE(x + 1,y + 2) != CST_GREEN
558 || MP_TYPE(x,y + 2) != CST_GREEN)
559 return;
560 }
561 if (size == 4)
562 {
563 if (MP_TYPE(x + 3,y) != CST_GREEN
564 || MP_TYPE(x + 3,y + 1) != CST_GREEN
565 || MP_TYPE(x + 3,y + 2) != CST_GREEN
566 || MP_TYPE(x + 3,y + 3) != CST_GREEN
567 || MP_TYPE(x + 2,y + 3) != CST_GREEN
568 || MP_TYPE(x + 1,y + 3) != CST_GREEN
569 || MP_TYPE(x,y + 3) != CST_GREEN)
570 return;
571 }
572
573 /* Place the selected item */
574 switch (place_item (x, y, selected_module_type)) {
575 case 0:
576 /* Success */
577 break;
578 case -1:
579 /* Not enough money */
580 no_credit_build_msg (selected_module_group);
581 break;
582 case -2:
583 /* Improper port placement */
584 /* TRANSLATORS: The part about the cup of tea is one of Ian's
585 jokes, but the part about ports needing to be connected
586 to rivers is true. */
587 if (yn_dial_box (_("WARNING"),
588 _("Ports need to be"),
589 _("connected to rivers!"),
590 _("Want to make a cup of tea?")) != 0)
591 while (yn_dial_box (_("TEA BREAK"),
592 _("Boil->pour->wait->stir"),
593 _("stir->pour->stir->wait->drink...ahhh"),
594 _("Have you finished yet?")) == 0);
595 break;
596 }
597 }
598
599 void
do_mouse_other_buttons(int x,int y,int button)600 do_mouse_other_buttons (int x, int y, int button)
601 {
602 Rect* mw = &scr.main_win;
603
604 if (0) {} /* XXX: Cute, very cute */
605
606 /* main screen border scroll areas */
607
608 /* up */
609 else if (x >= (mw->x - 8) && x < (mw->x + mw->w + 8)
610 && y >= (mw->y - 8) && y < mw->y) {
611 int new_origin_y;
612 if (button == LC_MOUSE_RIGHTBUTTON) {
613 new_origin_y = main_screen_originy - RIGHT_MOUSE_MOVE_VAL;
614 } else {
615 new_origin_y = main_screen_originy - 1;
616 }
617 adjust_main_origin (main_screen_originx, new_origin_y, 1);
618 }
619 /* down */
620 else if (x >= (mw->x - 8) && x < (mw->x + mw->w + 8)
621 && y > (mw->y + mw->h)
622 && y < (mw->y + mw->h + 16)) { /* 16 for bigger area */
623 int new_origin_y;
624 if (button == LC_MOUSE_RIGHTBUTTON) {
625 new_origin_y = main_screen_originy + RIGHT_MOUSE_MOVE_VAL;
626 } else {
627 new_origin_y = main_screen_originy + 1;
628 }
629 adjust_main_origin (main_screen_originx, new_origin_y, 1);
630 }
631 /* left */
632 else if (x >= (mw->x - 16) && x < mw->x
633 && y >= (mw->y - 8) && y < (mw->y + mw->h + 8)) {
634 int new_origin_x;
635 if (button == LC_MOUSE_RIGHTBUTTON) {
636 new_origin_x = main_screen_originx - RIGHT_MOUSE_MOVE_VAL;
637 } else {
638 new_origin_x = main_screen_originx - 1;
639 }
640 adjust_main_origin (new_origin_x, main_screen_originy, 1);
641 }
642 /* right */
643 else if (x > (mw->x + mw->w)
644 && x < (mw->x + mw->w + 8)
645 && y > (mw->y - 8) && y < (mw->y + mw->w + 8)) {
646 int new_origin_x;
647 if (button == LC_MOUSE_RIGHTBUTTON) {
648 new_origin_x = main_screen_originx + RIGHT_MOUSE_MOVE_VAL;
649 } else {
650 new_origin_x = main_screen_originx + 1;
651 }
652 adjust_main_origin (new_origin_x, main_screen_originy, 1);
653 }
654
655 /* This is the mini window. Clicking here move the main window
656 to this point
657 */
658
659 /*** Miniscreen selector buttons removed in CVS Revision 1.24 ***/
660
661 /* this is the menu button */
662 else if (mouse_in_rect (&scr.menu_button,x,y)) {
663 activate_help ("menu.hlp");
664 }
665
666 /* this is the help button */
667 else if (mouse_in_rect (&scr.help_button,x,y)) {
668 activate_help ("index.hlp");
669 }
670
671 /* this is the results (stats) button */
672 else if (mouse_in_rect (&scr.results_button,x,y)) {
673 if (button == LC_MOUSE_RIGHTBUTTON)
674 return;
675 window_results ();
676 }
677
678 /* XXX: WCK: This is broken; should be a mouse handler in
679 mps.c anyway */
680 /* Advance mps screen if clicked on */
681 else if (mouse_in_rect (&scr.mappoint_stats,x,y)) {
682 if (button == LC_MOUSE_RIGHTBUTTON) {
683 switch (mps_global_style) {
684 case MPS_GLOBAL_FINANCE:
685 activate_help ("finance.hlp");
686 break;
687 case MPS_GLOBAL_OTHER_COSTS:
688 activate_help ("other-costs.hlp");
689 break;
690 case MPS_GLOBAL_HOUSING:
691 activate_help ("housing.hlp");
692 break;
693 }
694 return;
695 }
696 mps_global_advance();
697 }
698
699 /* Advance monthgraph screen if clicked on */
700 else if (mouse_in_rect (&scr.monthgraph,x,y)) {
701 if (button == LC_MOUSE_RIGHTBUTTON) {
702 if (monthgraph_style == MONTHGRAPH_STYLE_ECONOMY) {
703 activate_help ("economy.hlp");
704 } else {
705 activate_help ("sustain.hlp");
706 }
707 return;
708 }
709 advance_monthgraph_style ();
710 refresh_monthgraph ();
711 }
712
713 /*
714 // no more buttons to click on, see if it's help for somewhere else.
715 // ***************************
716 */
717
718 if (mouse_in_rect (&scr.pbar_area,x,y)) {
719 pbar_mouse(x, y, button);
720 return;
721 }
722
723 if (button == LC_MOUSE_RIGHTBUTTON) {
724
725 #if defined (FINANCE_WINDOW)
726
727 /* now check for finance window */
728 if (x >= FINANCE_X && x <= (FINANCE_X + FINANCE_W)
729 && y >= FINANCE_Y && y <= (FINANCE_Y + FINANCE_H))
730 {
731 activate_help ("finance.hlp");
732 return;
733 }
734 #endif
735
736
737 #if defined (commentout)
738 /* GCS FIX -- This is obsolete, right??? */
739 /* -- If so, can delete scr.sust from geometry.c */
740 /* now check for the sustain window */
741 else if (mouse_in_rect (&scr.sust,x,y)) {
742 activate_help ("sustain.hlp");
743 return;
744 }
745 #endif
746 }
747 }
748
749
750 void
check_bulldoze_area(int x,int y)751 check_bulldoze_area (int x, int y)
752 {
753 int xx, yy, g;
754 if (MP_TYPE(x,y) == CST_USED) {
755 xx = MP_INFO(x,y).int_1;
756 yy = MP_INFO(x,y).int_2;
757 } else {
758 xx = x;
759 yy = y;
760 }
761 g = MP_GROUP(xx,yy);
762
763 /* GCS: Free bulldozing of most recently placed item is disabled.
764 Still not sure how this can be done w/ multiplayer. */
765 if (g == GROUP_MONUMENT && monument_bul_flag == 0) {
766 if (yn_dial_box (_("WARNING"),
767 _("Bulldozing a monument costs"),
768 _("a lot of money."),
769 _("Want to bulldoze?")) == 0)
770 return;
771 monument_bul_flag = 1;
772 }
773 else if (g == GROUP_RIVER && river_bul_flag == 0) {
774 if (yn_dial_box (_("WARNING"),
775 _("Bulldozing a section of river"),
776 _("costs a lot of money."),
777 _("Want to bulldoze?")) == 0)
778 return;
779 river_bul_flag = 1;
780 }
781 else if (g == GROUP_SHANTY && shanty_bul_flag == 0) {
782 if (yn_dial_box (_("WARNING"),
783 _("Bulldozing a shanty town costs a"),
784 _("lot of money and may cause a fire."),
785 _("Want to bulldoze?")) == 0)
786 return;
787 shanty_bul_flag = 1;
788 }
789 else if (g == GROUP_TIP) {
790 ok_dial_box ("nobull-tip.mes", BAD, 0L);
791 return;
792 }
793
794 bulldoze_item (xx,yy);
795 }
796
797 /* XXX: mouse.c? wtf! */
798 void
fire_area(int x,int y)799 fire_area (int x, int y)
800 {
801 do_bulldoze_area (CST_FIRE_1, x, y);
802 refresh_main_screen ();
803 /*
804 // update transport or we get stuff put in
805 // the area from connected tracks etc.
806 */
807 }
808
809 /* Called from event handler when middle button is held while moving
810 the mouse. Will probably handle multi-transport eventually */
811
812 /* XXX: Need to put this in a header somewhere */
813
814 void
drag_screen(void)815 drag_screen (void)
816 {
817 int cur_mappoint_x = 0;
818 int cur_mappoint_y = 0;
819
820 int cur_winpoint_x = 0;
821 int cur_winpoint_y = 0;
822
823 int origin_x = 0;
824 int origin_y = 0;
825
826 int in_main_window;
827
828 if (buttons[LC_MOUSE_MIDDLEBUTTON-1].mappoint_x == 0)
829 return; /* Not pressed in main window */
830
831 in_main_window = pixel_to_mappoint(cs_mouse_x, cs_mouse_y,
832 &cur_mappoint_x, &cur_mappoint_y);
833
834 pixel_to_winpoint(cs_mouse_x, cs_mouse_y, &cur_winpoint_x, &cur_winpoint_y);
835
836 origin_x =
837 buttons[LC_MOUSE_MIDDLEBUTTON-1].mappoint_x - cur_winpoint_x;
838 origin_y =
839 buttons[LC_MOUSE_MIDDLEBUTTON-1].mappoint_y - cur_winpoint_y;
840
841 adjust_main_origin (origin_x, origin_y, 1);
842 }
843
844 void
do_market_cb_template(int x,int y,int is_market_cb)845 do_market_cb_template (int x, int y, int is_market_cb)
846 {
847 Rect* mcb = &scr.market_cb;
848 int is_sell;
849
850 hide_mouse ();
851 if (!mouse_in_rect(mcb,x,y)) {
852 if (is_market_cb) {
853 close_market_cb ();
854 } else {
855 close_port_cb ();
856 }
857 redraw_mouse ();
858 return;
859 }
860
861 if (x >= mcb->x + 8 && x <= mcb->x + 6 * 8) {
862 is_sell = 0;
863 } else if (x >= mcb->x + 10 * 8 && x <= mcb->x + mcb->w - 8) {
864 is_sell = 1;
865 } else {
866 redraw_mouse ();
867 return;
868 }
869
870 /* jobs */
871 if (is_market_cb && y >= mcb->y + 36 + (CB_SPACE * 0)
872 && y <= mcb->y + 52 + (CB_SPACE * 0)) {
873 int flag = is_sell ? FLAG_MS_JOBS : FLAG_MB_JOBS;
874 MP_INFO(mcbx,mcby).flags ^= flag;
875 draw_cb_box (0, is_sell, MP_INFO(mcbx,mcby).flags & flag);
876 }
877 /* food */
878 else if (y >= mcb->y + 36 + (CB_SPACE * 1)
879 && y <= mcb->y + 52 + (CB_SPACE * 1)) {
880 int flag = is_sell ? FLAG_MS_FOOD : FLAG_MB_FOOD;
881 MP_INFO(mcbx,mcby).flags ^= flag;
882 draw_cb_box (1, is_sell, MP_INFO(mcbx,mcby).flags & flag);
883 }
884 /* coal */
885 else if (y >= mcb->y + 36 + (CB_SPACE * 2)
886 && y <= mcb->y + 52 + (CB_SPACE * 2)) {
887 int flag = is_sell ? FLAG_MS_COAL : FLAG_MB_COAL;
888 MP_INFO(mcbx,mcby).flags ^= flag;
889 draw_cb_box (2, is_sell, MP_INFO(mcbx,mcby).flags & flag);
890 }
891 /* ore */
892 else if (y >= mcb->y + 36 + (CB_SPACE * 3)
893 && y <= mcb->y + 52 + (CB_SPACE * 3)) {
894 int flag = is_sell ? FLAG_MS_ORE : FLAG_MB_ORE;
895 MP_INFO(mcbx,mcby).flags ^= flag;
896 draw_cb_box (3, is_sell, MP_INFO(mcbx,mcby).flags & flag);
897 }
898 /* goods */
899 else if (y >= mcb->y + 36 + (CB_SPACE * 4)
900 && y <= mcb->y + 52 + (CB_SPACE * 4)) {
901 int flag = is_sell ? FLAG_MS_GOODS : FLAG_MB_GOODS;
902 MP_INFO(mcbx,mcby).flags ^= flag;
903 draw_cb_box (4, is_sell, MP_INFO(mcbx,mcby).flags & flag);
904 }
905 /* steel */
906 else if (y >= mcb->y + 36 + (CB_SPACE * 5)
907 && y <= mcb->y + 52 + (CB_SPACE * 5)) {
908 int flag = is_sell ? FLAG_MS_STEEL : FLAG_MB_STEEL;
909 MP_INFO(mcbx,mcby).flags ^= flag;
910 draw_cb_box (5, is_sell, MP_INFO(mcbx,mcby).flags & flag);
911 }
912
913 redraw_mouse ();
914
915 #if defined (NETWORK_ENABLE)
916 if (MP_INFO(mcbx,mcby).flags != old_flags) {
917 send_flags (mcbx,mcby);
918 }
919 #endif
920 }
921
922 void
do_market_cb_mouse(int x,int y)923 do_market_cb_mouse (int x, int y)
924 {
925 do_market_cb_template (x, y, 1);
926 }
927
928 void
do_port_cb_mouse(int x,int y)929 do_port_cb_mouse (int x, int y)
930 {
931 do_market_cb_template (x, y, 0);
932 }
933
934 void
no_credit_build_msg(int selected_group)935 no_credit_build_msg (int selected_group)
936 {
937 #ifdef GROUP_POWER_SOURCE_NO_CREDIT
938 if (selected_group == GROUP_POWER_SOURCE) {
939 ok_dial_box ("no-credit-solar-power.mes", BAD, 0L);
940 return;
941 }
942 #endif
943 #ifdef GROUP_UNIVERSITY_NO_CREDIT
944 if (selected_group == GROUP_UNIVERSITY) {
945 ok_dial_box ("no-credit-university.mes", BAD, 0L);
946 return;
947 }
948 #endif
949 #ifdef GROUP_PARKLAND_NO_CREDIT
950 if (selected_group == GROUP_PARKLAND) {
951 ok_dial_box ("no-credit-parkland.mes", BAD, 0L);
952 return;
953 }
954 #endif
955 #ifdef GROUP_RECYCLE_NO_CREDIT
956 if (selected_group == GROUP_RECYCLE) {
957 ok_dial_box ("no-credit-recycle.mes", BAD, 0L);
958 return;
959 }
960 #endif
961 #ifdef GROUP_ROCKET
962 if (selected_group == GROUP_ROCKET) {
963 ok_dial_box ("no-credit-rocket.mes", BAD, 0L);
964 return;
965 }
966 #endif
967 return;
968 }
969
970 void
choose_residence(void)971 choose_residence (void)
972 {
973 int cost;
974 FILE* tempfile;
975 char* s = (char*) malloc (lc_save_dir_len + 9);
976
977 sprintf (s, "%s%c%s", lc_save_dir, PATH_SLASH, "res.tmp");
978 if ((tempfile = fopen (s, "w")) == 0)
979 do_error ("Can't write res.tmp");
980 free (s);
981
982 fprintf (tempfile,
983 /* TRANSLATORS: Don't translate the leading "text" */
984 _("text -1 20 Choose the type of residence you want\n"));
985 fprintf (tempfile,
986 "text -1 30 =====================================\n");
987 fprintf (tempfile,
988 _("text -1 45 (LB=Low Birthrate HB=High Birthrate)\n"));
989 fprintf (tempfile,
990 _("text -1 55 (LD=Low Deathrate HD=High Deathrate)\n"));
991 fprintf (tempfile,
992 _("text -1 85 Low Tech\n"));
993
994 cost = get_group_cost(GROUP_RESIDENCE_LL);
995 fprintf (tempfile, _("text 68 106 Cost %4d\n"), cost);
996 fprintf (tempfile, "icon 85 120 reslowlow.csi\n");
997 fprintf (tempfile, "button 83 118 52 52 return1\n");
998 /* TRANSLATORS: Only translate "pop" <<for population>> */
999 fprintf (tempfile, _("tbutton 82 180 return1 pop 50\n"));
1000 /* TRANSLATORS: Only translate LB, HD (low birth, high death) */
1001 fprintf (tempfile, _("text 89 195 LB HD\n"));
1002
1003 cost = get_group_cost(GROUP_RESIDENCE_ML);
1004 fprintf (tempfile, _("text 155 106 Cost %4d\n"), cost);
1005 fprintf (tempfile, "icon 170 120 resmedlow.csi\n");
1006 fprintf (tempfile, "button 168 118 52 52 return2\n");
1007 fprintf (tempfile, _("tbutton 164 180 return2 pop 100\n"));
1008 fprintf (tempfile, _("text 175 195 HB LD\n"));
1009
1010 cost = get_group_cost(GROUP_RESIDENCE_HL);
1011 fprintf (tempfile, _("text 238 106 Cost %4d\n"), cost);
1012 fprintf (tempfile, "icon 255 120 reshilow.csi\n");
1013 fprintf (tempfile, "button 253 118 52 52 return3\n");
1014 fprintf (tempfile, _("tbutton 250 180 return3 pop 200\n"));
1015 fprintf (tempfile, _("text 261 195 HB HD\n"));
1016
1017 fprintf (tempfile, _("text -1 215 Click on one to select\n"));
1018 fprintf (tempfile, "text -1 225 ======================\n");
1019
1020 if (((tech_level * 10) / MAX_TECH_LEVEL) > 2) {
1021 fprintf (tempfile, _("text -1 255 High Tech\n"));
1022
1023 cost = get_group_cost(GROUP_RESIDENCE_LH);
1024 fprintf (tempfile, _("text 68 276 Cost %4d\n"), cost);
1025 fprintf (tempfile, "icon 85 290 reslowhi.csi\n");
1026 fprintf (tempfile, "button 83 288 52 52 return4\n");
1027 fprintf (tempfile, _("tbutton 78 350 return4 pop 100\n"));
1028 fprintf (tempfile, _("text 89 365 LB HD\n"));
1029
1030 cost = get_group_cost(GROUP_RESIDENCE_MH);
1031 fprintf (tempfile, _("text 155 276 Cost %4d\n"), cost);
1032 fprintf (tempfile, "icon 170 290 resmedhi.csi\n");
1033 fprintf (tempfile, "button 168 288 52 52 return5\n");
1034 fprintf (tempfile, _("tbutton 164 350 return5 pop 200\n"));
1035 fprintf (tempfile, _("text 175 365 HB LD\n"));
1036
1037 cost = get_group_cost(GROUP_RESIDENCE_HH);
1038 fprintf (tempfile, _("text 238 276 Cost %4d\n"), cost);
1039 fprintf (tempfile, "icon 255 290 reshihi.csi\n");
1040 fprintf (tempfile, "button 253 288 52 52 return6\n");
1041 fprintf (tempfile, _("tbutton 250 350 return6 pop 400\n"));
1042 fprintf (tempfile, _("text 261 365 HB HD\n"));
1043 }
1044
1045 fclose (tempfile);
1046 block_help_exit = 1;
1047 activate_help ("res.tmp");
1048 }
1049
1050
1051 /* We can only draw temporary transport on GROUP_TRACK, GROUP_ROAD,
1052 GROUP_RAIL, or GROUP_BARE. For temporary draws over GROUP_BARE,
1053 FLAG_IS_TRANSPORT is not set. For temporary draws over existing
1054 transport of a different type, FLAG_IS_TRANSPORT is set, and
1055 FLAG_MULTI_TRANSPORT_PREV will be set to 0 if the existing transport is
1056 of the cheaper sort (e.g. GROUP_TRACK when overwriting with GROUP_ROAD),
1057 and set to 1 if the existing transport if the more expensive sort
1058 (e.g. GROUP_RAIL when overwriting GROUP_ROAD).
1059 */
1060 int
mt_erase(int x,int y)1061 mt_erase(int x, int y)
1062 {
1063 if (x < 0 || y < 0 || x >= WORLD_SIDE_LEN || y >= WORLD_SIDE_LEN)
1064 return 1;
1065 if (MP_INFO(x,y).flags & FLAG_MULTI_TRANSPORT) {
1066 if (MP_INFO(x,y).flags & FLAG_IS_TRANSPORT) {
1067 if (!(MP_INFO(x,y).flags & FLAG_MULTI_TRANS_PREV)) {
1068 if (mt_grp == GROUP_TRACK) {
1069 MP_TYPE(x,y) = CST_ROAD_LR;
1070 MP_GROUP(x,y) = GROUP_ROAD;
1071 } else {
1072 MP_TYPE(x,y) = CST_TRACK_LR;
1073 MP_GROUP(x,y) = GROUP_TRACK;
1074 }
1075 } else {
1076 if (mt_grp == GROUP_RAIL) {
1077 MP_TYPE(x,y) = CST_ROAD_LR;
1078 MP_GROUP(x,y) = GROUP_ROAD;
1079 } else {
1080 MP_TYPE(x,y) = CST_RAIL_LR;
1081 MP_GROUP(x,y) = GROUP_RAIL;
1082 }
1083 }
1084 } else {
1085 MP_TYPE(x,y) = CST_GREEN;
1086 MP_GROUP(x,y) = GROUP_BARE;
1087 }
1088 MP_INFO(x,y).flags &= ~FLAG_MULTI_TRANSPORT;
1089 return 1;
1090 } else if ((MP_INFO(x,y).flags & FLAG_IS_TRANSPORT)
1091 && (mt_grp == MP_GROUP(x,y))) {
1092 return 1;
1093 }
1094 return 0;
1095 }
1096
1097 int
mt_temp(int x,int y)1098 mt_temp(int x, int y)
1099 {
1100 if (x < 0 || y < 0 || x >= WORLD_SIDE_LEN || y >= WORLD_SIDE_LEN)
1101 return 1;
1102 if (MP_INFO(x,y).flags & FLAG_IS_TRANSPORT) {
1103 if (MP_GROUP(x,y) == mt_grp) {
1104 return 1;
1105 } else if (!overwrite_transport_flag) {
1106 return 0;
1107 } else {
1108 if ((MP_GROUP(x,y) == GROUP_TRACK) ||
1109 ((MP_GROUP(x,y) == GROUP_ROAD) && (mt_grp == GROUP_TRACK)))
1110 {
1111 MP_INFO(x,y).flags &= ~FLAG_MULTI_TRANS_PREV;
1112 } else {
1113 MP_INFO(x,y).flags |= FLAG_MULTI_TRANS_PREV;
1114 }
1115 mt_length++;
1116 MP_TYPE(x,y) = selected_module_type;
1117 MP_GROUP(x,y) = mt_grp;
1118 MP_INFO(x,y).flags |= FLAG_MULTI_TRANSPORT;
1119 return 1;
1120 }
1121 } else if (MP_GROUP(x,y) == GROUP_BARE) {
1122 mt_length++;
1123 MP_TYPE(x,y) = selected_module_type;
1124 MP_GROUP(x,y) = mt_grp;
1125 MP_INFO(x,y).flags |= FLAG_MULTI_TRANSPORT;
1126 return 1;
1127 }
1128 return 0;
1129 }
1130
1131 int
mt_perm(int x,int y)1132 mt_perm(int x, int y)
1133 {
1134 /* By now, it has already been mt_erase()'d */
1135 if (x < 0 || y < 0 || x >= WORLD_SIDE_LEN || y >= WORLD_SIDE_LEN)
1136 return 1;
1137 if (MP_INFO(x,y).flags & FLAG_IS_TRANSPORT) {
1138 if (MP_GROUP(x,y) == mt_grp) {
1139 return 1;
1140 } else if (!overwrite_transport_flag) {
1141 return 0;
1142 } else {
1143 bulldoze_item(x,y);
1144 place_item (x,y,selected_module_type);
1145 return 1;
1146 }
1147 } else if (MP_GROUP(x,y) == GROUP_BARE) {
1148 place_item (x,y,selected_module_type);
1149 return 1;
1150 }
1151 return 0;
1152 }
1153
1154 int
do_mt_draw(int x1,int x2,int y1,int y2,int (* mode)())1155 do_mt_draw (int x1, int x2, int y1, int y2, int (*mode)())
1156 {
1157 int dir = 1;
1158 int horiz = 1;
1159 int vert = 2;
1160 int x_dir = cmp(x1, x2);
1161 int y_dir = cmp(y1, y2);
1162 int ix = x1;
1163 int iy = y1;
1164
1165 mt_length = 0;
1166
1167 if (!mode(ix, iy))
1168 return 0;
1169
1170 while ((ix != x2 || iy != y2) && dir) {
1171 /* try horizontal, unless already vertical */
1172 if (dir == 1) {
1173 if (ix == x2) {
1174 horiz = 0;
1175 dir = vert;
1176 } else if (mode(ix+x_dir, iy)) {
1177 horiz = 1;
1178 vert = 2;
1179 ix += x_dir;
1180 } else {
1181 horiz = 0;
1182 dir = vert;
1183 }
1184 } else if (dir == 2) {
1185 if (iy == y2) {
1186 vert = 0;
1187 dir = horiz;
1188 } else if (mode(ix, iy+y_dir)) {
1189 horiz = 1;
1190 vert = 2;
1191 iy += y_dir;
1192 } else {
1193 vert = 0;
1194 dir = horiz;
1195 }
1196 }
1197 }
1198 if (dir) { /* still had one direction to pick from, must have succeeded */
1199 return 1;
1200 } else {
1201 return 0;
1202 }
1203 }
1204
1205 int
mt_draw(int cxp,int cyp,int flag)1206 mt_draw (int cxp, int cyp, int flag) /* c[xy]p are pixel coordinates */
1207 {
1208
1209 #define STATUS_MESSAGE_LENGTH 80
1210 static int dx, dy; /* old current point; drawn point */
1211 static int ox, oy; /* coordinates for original button press */
1212 int cx, cy; /* current mappoint coordinates */
1213 int draw_ret;
1214 char s[STATUS_MESSAGE_LENGTH];
1215
1216 if (flag != MT_START && !mt_flag)
1217 return 0;
1218
1219 pixel_to_mappoint(cxp, cyp, &cx, &cy);
1220
1221 switch(flag) {
1222 case MT_SUCCESS:
1223 if (ox == 0)
1224 return 0;
1225 draw_ret = do_mt_draw(ox, dx, oy, dy, mt_erase);
1226
1227 if (!draw_ret) {
1228 /* If mt_erase failed it is because we don't have clearance
1229 to build the road. So clean up and exit. */
1230 mt_flag = 0;
1231 draw_main_window_box (green (8));
1232 status_message(0,0);
1233 }
1234 else if ((draw_ret = do_mt_draw(ox, cx, oy, cy, mt_perm))) {
1235
1236 print_total_money ();
1237 mt_flag = 0;
1238 draw_main_window_box (green (8));
1239 status_message(0,0);
1240 } else {
1241 /* This shouldn't happen. Clean up and continue anyway. */
1242 mt_flag = 0;
1243 status_message(0,0);
1244 draw_main_window_box (green (8));
1245 }
1246 dx = 0; dy = 0;
1247 ox = 0; oy = 0;
1248 break;
1249
1250 case MT_FAIL:
1251 mt_flag = 0;
1252 draw_main_window_box (green (8));
1253 draw_ret = do_mt_draw(ox, dx, oy, dy, mt_erase);
1254 status_message(0,0);
1255
1256 dx = 0; dy = 0;
1257 ox = 0; oy = 0;
1258 break;
1259
1260 case MT_CONTINUE:
1261 if ((dx == cx && dy == cy) || ox == 0)
1262 return 0;
1263 draw_ret = do_mt_draw(ox, dx, oy, dy, mt_erase);
1264
1265 draw_ret = do_mt_draw(ox, cx, oy, cy, mt_temp);
1266
1267 if (!draw_ret) {
1268 draw_ret = do_mt_draw(ox, cx, oy, cy, mt_erase);
1269 snprintf(s,STATUS_MESSAGE_LENGTH-1,
1270 _("Can't build %s over that!"), mt_name);
1271 } else {
1272 snprintf(s,STATUS_MESSAGE_LENGTH-1,
1273 _("%d sections of %s will cost %3d to build"),
1274 mt_length, mt_name,
1275 mt_length * get_type_cost(selected_module_type));
1276 }
1277
1278 status_message(0,s);
1279 dx = cx; dy = cy;
1280 break;
1281
1282 case MT_START:
1283 /* XXX: we assume that a transport type is selected. */
1284
1285 if ((mt_grp = get_group_of_type(selected_module_type)) < 0 )
1286 return 0;
1287
1288 get_type_name(selected_module_type,mt_name);
1289
1290 dx = dy = 0;
1291 ox = buttons[LC_MOUSE_LEFTBUTTON-1].mappoint_x;
1292 oy = buttons[LC_MOUSE_LEFTBUTTON-1].mappoint_y;
1293 draw_ret = do_mt_draw(ox, cx, oy, cy, mt_temp);
1294
1295 if (!draw_ret) {
1296 draw_ret = do_mt_draw(ox, cx, oy, cy, mt_erase);
1297 return 0;
1298 }
1299 dx = cx;
1300 dy = cy;
1301 mt_flag = 1;
1302 draw_main_window_box (cyan (20));
1303 break;
1304
1305 default:
1306 ;
1307 }
1308
1309 connect_transport_main_screen ();
1310 update_main_screen (0);
1311 return (1);
1312 }
1313
1314 int
cmp(int n1,int n2)1315 cmp(int n1, int n2)
1316 {
1317 if (n1 != n2)
1318 return (n1 < n2) ? 1 : -1;
1319 else
1320 return 0;
1321 }
1322
1323 void
init_mouse_registry()1324 init_mouse_registry()
1325 {
1326 mhandle_first = NULL;
1327 mhandle_last = NULL;
1328 mhandle_current = NULL;
1329 mhandle_count = 0;
1330 }
1331
1332 /* Add and return an entry in the registry. Add it at the beginning, so
1333 it supercedes earlier entries in mouse_handle_click() */
1334 Mouse_Handle *
mouse_register(Rect * r,void (* function)(int,int,int))1335 mouse_register(Rect * r, void (*function)(int, int, int))
1336 {
1337 mhandle_current = (Mouse_Handle *)lcalloc(sizeof(Mouse_Handle));
1338 mhandle_count++;
1339 if (mhandle_first == NULL) {
1340 mhandle_current->next = NULL;
1341 mhandle_current->prev = NULL;
1342 } else {
1343 mhandle_current->next = mhandle_first;
1344 mhandle_first->prev = mhandle_current;
1345 mhandle_current->prev = NULL;
1346 }
1347
1348 mhandle_first = mhandle_current;
1349
1350 mhandle_current->r = r;
1351 mhandle_current->handler = function;
1352
1353 return mhandle_current;
1354 }
1355
1356
1357 /* Remove an entry from the registry */
1358 void
mouse_unregister(Mouse_Handle * mhandle)1359 mouse_unregister(Mouse_Handle * mhandle)
1360 {
1361 if (mhandle->prev == NULL) {
1362 if (mhandle_first != mhandle)
1363 printf("debug: mhandle_first != mhandle\n");
1364 if (mhandle->next != NULL) {
1365 mhandle_first = mhandle->next;
1366 mhandle_first->prev = NULL;
1367 } else {
1368 mhandle_first = NULL;
1369 }
1370 } else if (mhandle->next == NULL) {
1371 mhandle->prev->next = NULL;
1372 } else {
1373 mhandle->prev->next = mhandle->next;
1374 mhandle->next->prev = mhandle->prev;
1375 }
1376
1377 free(mhandle);
1378 mhandle_count--;
1379 }
1380
1381 /* Loop through the registry until we find a handler for an area.
1382 BEWARE!!! Some handlers unregister themselves when called. Assume
1383 mhandle_current is undefined after calling mhandle_current->handler()
1384 */
1385 int
mouse_handle_click(int x,int y,int button)1386 mouse_handle_click(int x, int y, int button)
1387 {
1388 mhandle_current = mhandle_first;
1389
1390 while (mhandle_current != NULL) {
1391 if (mouse_in_rect(mhandle_current->r,x,y)) {
1392 mhandle_current->handler(x - mhandle_current->r->x,
1393 y - mhandle_current->r->y, button);
1394 return 1;
1395 }
1396
1397 mhandle_current = mhandle_current->next;
1398 }
1399
1400 return 0;
1401 }
1402
1403