Main Page | Data Structures | Directories | File List | Data Fields | Globals

mouse.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------- *
00002  * mouse.c
00003  * This file is part of lincity.
00004  * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
00005  * ---------------------------------------------------------------------- */
00006 #include "lcconfig.h"
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include "lcstring.h"
00010 #include "common.h"
00011 #include "lctypes.h"
00012 #include "lcintl.h"
00013 #include "lin-city.h"
00014 #include "mouse.h"
00015 #include "engglobs.h"
00016 #include "cliglobs.h"
00017 #include "engine.h"
00018 #include "screen.h"
00019 #include "mps.h"
00020 #include "fileutil.h"
00021 #include "lchelp.h"
00022 #include "pbar.h"
00023 #include "lclib.h"
00024 #include "module_buttons.h"
00025 
00026 #define DEBUG_MT_CODE 1
00027 
00028 extern Update_Scoreboard update_scoreboard;
00029 
00030 /* ---------------------------------------------------------------------- *
00031  * Private global variables
00032  * ---------------------------------------------------------------------- */
00033 static struct mouse_button_struct buttons[NUM_BUTTONS];
00034 static int mt_length; 
00035 static int mt_grp;
00036 static char mt_name[20];
00037 static short mouse_buffer_fresh = 0;
00038 
00039 void check_bulldoze_area (int x, int y);
00040 
00041 /* Mouse registry */
00042 
00043 static int mhandle_count;
00044 
00045 static Mouse_Handle * mhandle_first;
00046 static Mouse_Handle * mhandle_last;
00047 static Mouse_Handle * mhandle_current;
00048 
00049 /* Screen area mouse handles */
00050 /* XXX: These handlers should live elsewhere */
00051 static Mouse_Handle * main_win_mhandle;
00052 static Mouse_Handle * other_buttons_mhandle;
00053 static Mouse_Handle * market_cb_mhandle;
00054 static Mouse_Handle * help_mhandle;
00055 static Mouse_Handle * loadsave_mhandle;
00056 
00057 
00058 /* ---------------------------------------------------------------------- *
00059  * cs_mouse_handler
00060  * --
00061  * If the event was a mouse click or mouse release, enc_button contains 
00062  * the button identifier (e.g. LC_MOUSE_LEFTBUTTON) or'd with the 
00063  * action identifier (e.g. LC_MOUSE_RELEASE).  If the event was just a 
00064  * mouse move, then enc_button is 0.  You cannot specify multiple 
00065  * mouse buttons clicked at the same time using this interface.
00066  * ---------------------------------------------------------------------- */
00067 
00068 void
00069 cs_mouse_handler (int enc_button, int dx, int dy)
00070 {
00071     int x, y;
00072     int group = 0;
00073     int button = enc_button & ~LC_MOUSE_RELEASE & ~LC_MOUSE_PRESS;
00074     int button_pressed = enc_button & LC_MOUSE_PRESS;
00075     int button_released = enc_button & LC_MOUSE_RELEASE;
00076     int button_idx = button - 1;
00077 
00078     x = cs_mouse_x;
00079     y = cs_mouse_y;
00080 
00081 #if defined (SVGALIB)
00082     cs_mouse_x += dx * MOUSE_SENSITIVITY;
00083     cs_mouse_y += dy * MOUSE_SENSITIVITY;
00084 #else
00085     cs_mouse_x += dx;
00086     cs_mouse_y += dy;
00087 #endif
00088 
00089 #if defined (SVGALIB)
00090     if (cs_mouse_x >= cs_mouse_xmax)
00091         cs_mouse_x = cs_mouse_xmax;
00092     if (cs_mouse_y >= cs_mouse_ymax)
00093         cs_mouse_y = cs_mouse_ymax;
00094     if (cs_mouse_x < 0)
00095         cs_mouse_x = 0;
00096     if (cs_mouse_y < 0)
00097         cs_mouse_y = 0;
00098 #endif
00099  
00100     if (cs_mouse_x != x || cs_mouse_y != y)
00101         move_mouse (cs_mouse_x, cs_mouse_y);
00102     x = cs_mouse_x;
00103     y = cs_mouse_y;
00104 
00105     /* see if we are all the way up */
00106     if (!mouse_initialized)
00107         return;
00108 
00109     /* button press */
00110     if (button_pressed) {
00111 
00112         /* maintain button press status */
00113         pixel_to_mappoint(cs_mouse_x, cs_mouse_y, 
00114                           &buttons[button_idx].mappoint_x, 
00115                           &buttons[button_idx].mappoint_y);
00116         buttons[button_idx].x = cs_mouse_x;
00117         buttons[button_idx].y = cs_mouse_y;
00118         buttons[button_idx].pressed = 1;
00119 
00120         /* Try the event list before moving on to special cases */
00121         if (!mouse_handle_click(x, y, button)) {
00122             switch (button) {
00123             case LC_MOUSE_LEFTBUTTON:
00124                 if (market_cb_flag) {
00125                     do_market_cb_mouse (x, y);
00126                     break;
00127                 }
00128                 else if (port_cb_flag) {
00129                     do_port_cb_mouse (x, y);
00130                     break;
00131                 }
00132                 else if (help_flag) {
00133                     do_help_mouse (x, y, button);
00134                     break;
00135                 }
00136                 else if (prefs_flag) {
00137                     do_prefs_mouse (x, y, button);
00138                     break;
00139                 }
00140 
00141                 else if (load_flag || save_flag) 
00142                     return;
00143 
00144                 /* This is the main screen */
00145                 if (mouse_in_rect(&scr.main_win,x,y)) {
00146                     do_mouse_main_win(x, y, button);
00147                     refresh_main_screen ();
00148                     break;
00149                 }
00150 
00151                 /* GCS Remove overlay  */
00152                 /* This use of mouse clicks seems to contradict 
00153                     Corey's mouse handler code */
00154                 if (main_screen_flag == MAIN_SCREEN_EQUALS_MINI) {
00155                     main_screen_flag = MAIN_SCREEN_NORMAL_FLAG;
00156                     refresh_main_screen ();
00157                 }
00158 
00159                 /* Other points too */
00160                 do_mouse_other_buttons(x, y, button);
00161         
00162                 break;
00163         
00164             case LC_MOUSE_RIGHTBUTTON:
00165             case LC_MOUSE_MIDDLEBUTTON:
00166                 /* GCS FIX: This is my fix for right clicks on 
00167                    main screen during yn_dialogs causing dialog to 
00168                    be overwritten by screen content (similar effect
00169                    for market_cb overwritten by mps).  This fix could
00170                    be better, but will be better to confirm behavior
00171                    for X version before deciding final fix.
00172                 */
00173                 if (market_cb_flag) {
00174                     // should dismiss cb?
00175                     break;
00176                 }
00177                 else if (port_cb_flag) {
00178                     // should dismiss cb?
00179                     break;
00180                 }
00181                 else if (help_flag) {
00182                     // do_help_mouse (x, y, button);   maybe should??
00183                     break;
00184                 }
00185                 else if (prefs_flag) {
00186                     break;
00187                 }
00188                 else if (db_flag) {
00189                     break;
00190                 }
00191                 else if (db_okflag) {
00192                     break;
00193                 }
00194                 else if (load_flag || save_flag) 
00195                     return;
00196 
00197                 /* GCS Remove overlay  */
00198                 if (main_screen_flag == MAIN_SCREEN_EQUALS_MINI) {
00199                     main_screen_flag = MAIN_SCREEN_NORMAL_FLAG;
00200                     refresh_main_screen ();
00201                 }
00202 
00203                 /* This is the main screen */
00204                 if (mouse_in_rect(&scr.main_win,x,y)) {
00205                     do_mouse_main_win(x, y, button);
00206                     refresh_main_screen ();
00207                     break;
00208                 }
00209 
00210                 /* Other points too */
00211                 do_mouse_other_buttons(x, y, button);
00212 
00213                 break;
00214 
00215             default: 
00216                 printf("Unknown mouse button in cs_mouse_handler\n");
00217             }
00218         } /* mouse_handle_click couldn't. */
00219     } else if (button_released) { 
00220         button = enc_button - 16; /* probably shouldn't use this temporarily */
00221       
00222         pixel_to_mappoint(cs_mouse_x, cs_mouse_y, 
00223                           &buttons[button_idx].r_mappoint_x, 
00224                           &buttons[button_idx].r_mappoint_y);
00225       
00226         buttons[button_idx].r_x = cs_mouse_x;
00227         buttons[button_idx].r_y = cs_mouse_y;
00228         buttons[button_idx].pressed = 0;
00229       
00230         switch (button) {
00231         case LC_MOUSE_LEFTBUTTON:
00232             mt_draw(cs_mouse_x, cs_mouse_y, MT_SUCCESS);
00233             break;
00234         case LC_MOUSE_RIGHTBUTTON:
00235             break;
00236         case LC_MOUSE_MIDDLEBUTTON:
00237             break;
00238         default: 
00239             break;
00240         };
00241         button = 0; /* backwards compatibility */      
00242 
00243         /* mouse moved */
00244     } else {
00245         if (buttons[LC_MOUSE_LEFTBUTTON-1].pressed 
00246             && GROUP_IS_TRANSPORT(selected_module_group))
00247         {
00248             mt_draw(cs_mouse_x, cs_mouse_y, MT_CONTINUE);
00249         }
00250     }
00251     cs_mouse_button = button;
00252 }
00253 
00254 void
00255 move_mouse (int x, int y)
00256 {
00257     Rect* mw = &scr.main_win;
00258     int size;
00259 
00260     size = (main_groups[selected_module_group].size) * 16;
00261 
00262     /* GCS: we don't check for load_flag/save_flag because these guys
00263        set db_flag = 1 */
00264     if (mouse_in_rect(&scr.main_win,x,y)
00265         && market_cb_flag == 0 && port_cb_flag == 0 
00266         && prefs_flag == 0 && help_flag == 0 
00267         && db_flag == 0 && db_okflag == 0)
00268     {
00269         int mwoffset_x;
00270         int mwoffset_y;
00271         if (x > (mw->x + mw->w) - size)
00272             x = (mw->x + mw->w) - size;
00273         if (y > (mw->y + mw->h) - size)
00274             y = (mw->y + mw->h) - size;
00275         mwoffset_x = mw->x % 16;
00276         mwoffset_y = mw->y % 16;
00277         x -= mwoffset_x;
00278         y -= mwoffset_y;
00279         x &= 0xff0;
00280         y &= 0xff0;
00281         x += mwoffset_x;
00282         y += mwoffset_y;
00283 
00284         hide_mouse ();
00285         mouse_hide_count--;
00286         draw_square_mouse (x, y, size);
00287     }
00288     else
00289     {
00290         hide_mouse ();
00291         mouse_hide_count--;
00292         draw_normal_mouse (x, y);
00293         if (mappoint_stats_flag != 0 && market_cb_flag == 0
00294             && port_cb_flag == 0)
00295         {
00296             mappoint_stats_flag = 0;
00297             update_scoreboard.mps = 1;
00298         }
00299     }
00300 }
00301 
00302 void
00303 hide_mouse (void)
00304 {
00305     mouse_hide_count++;
00306     if (mouse_hide_count == 1) {
00307         if (mouse_type == MOUSE_TYPE_SQUARE)
00308             hide_square_mouse ();
00309         else
00310             hide_normal_mouse ();
00311     }
00312 }
00313 
00314 void
00315 redraw_mouse (void)
00316 {
00317     mouse_hide_count--;
00318     if (mouse_hide_count > 0)
00319         return;
00320     mouse_hide_count = 0;
00321     if (mouse_type == MOUSE_TYPE_SQUARE)
00322         redraw_square_mouse ();
00323     else
00324         redraw_normal_mouse ();
00325 }
00326 
00327 void
00328 draw_square_mouse (int x, int y, int size)      /* size is pixels */
00329 {
00330     if (mouse_type == MOUSE_TYPE_NORMAL) {
00331         hide_normal_mouse ();
00332         mouse_type = MOUSE_TYPE_SQUARE;
00333         kmouse_val = 16;
00334     }
00335     omx = x;
00336     omy = y;
00337 #if defined (WIN32)
00338     cs_square_mouse_visible = 1;
00339     RefreshArea (omx - 2, omy - 2, omx + size + 1, omy + size + 1);
00340 #else
00341     Fgl_getbox (x - 2, y - 2, size + 4, 2, under_square_mouse_pointer_top);
00342     Fgl_getbox (x - 2, y, 2, size, under_square_mouse_pointer_left);
00343     Fgl_getbox (x + size, y, 2, size, under_square_mouse_pointer_right);
00344     Fgl_getbox (x - 2, y + size, size + 4, 2, under_square_mouse_pointer_bottom);
00345     mouse_buffer_fresh = 1;
00346 
00347     Fgl_hline (x - 2, y - 2, x + size + 1, yellow (31));
00348     Fgl_hline (x - 1, y - 1, x + size, blue (31));
00349     Fgl_hline (x - 2, y + size + 1, x + size + 1, yellow (31));
00350     Fgl_hline (x - 1, y + size, x + size, blue (31));
00351     Fgl_line (x - 2, y - 1, x - 2, y + size + 1, yellow (31));
00352     Fgl_line (x - 1, y, x - 1, y + size, blue (31));
00353     Fgl_line (x + size + 1, y - 1, x + size + 1, y + size + 1, yellow (31));
00354     Fgl_line (x + size, y, x + size, y + size, blue (31));
00355 #endif
00356 }
00357 
00358 void
00359 hide_square_mouse (void)
00360 {
00361     int size;
00362 
00363     size = (main_groups[selected_module_group].size) * 16;
00364 #if defined (WIN32)
00365     cs_square_mouse_visible = 0;
00366     RefreshArea (omx - 3, omy - 3, omx + size + 2, omy + size + 2);
00367 #else
00368     if (mouse_buffer_fresh) {
00369       Fgl_putbox (omx - 2, omy - 2, size + 4, 2, under_square_mouse_pointer_top);
00370       Fgl_putbox (omx - 2, omy, 2, size, under_square_mouse_pointer_left);
00371       Fgl_putbox (omx + size, omy, 2, size, under_square_mouse_pointer_right);
00372       Fgl_putbox (omx - 2, omy + size, size + 4, 2, 
00373                   under_square_mouse_pointer_bottom);
00374       mouse_buffer_fresh = 0;
00375     } else {
00376       //      printf ("Mouse buffer stale in hide_mouse!  Not putting back!\n");
00377     }
00378 #endif
00379 }
00380 
00381 void
00382 redraw_square_mouse (void)
00383 {
00384     int size;
00385 
00386     size = (main_groups[selected_module_group].size) * 16;
00387 
00388 #if defined (WIN32)
00389     cs_square_mouse_visible = 1;
00390     RefreshArea (omx - 2, omy - 2, omx + size + 1, omy + size + 1);
00391 #else
00392     Fgl_getbox (omx - 2, omy - 2, size + 4, 2, under_square_mouse_pointer_top);
00393     Fgl_getbox (omx - 2, omy, 2, size, under_square_mouse_pointer_left);
00394     Fgl_getbox (omx + size, omy, 2, size, under_square_mouse_pointer_right);
00395     Fgl_getbox (omx - 2, omy + size, size + 4, 2, under_square_mouse_pointer_bottom);
00396     mouse_buffer_fresh = 1;
00397 
00398     Fgl_hline (omx - 2, omy - 2, omx + size + 1, yellow (31));
00399     Fgl_hline (omx - 1, omy - 1, omx + size, blue (31));
00400     Fgl_hline (omx - 2, omy + size + 1, omx + size + 1, yellow (31));
00401     Fgl_hline (omx - 1, omy + size, omx + size, blue (31));
00402     Fgl_line (omx - 2, omy - 1, omx - 2, omy + size + 1, yellow (31));
00403     Fgl_line (omx - 1, omy, omx - 1, omy + size, blue (31));
00404     Fgl_line (omx + size + 1, omy - 1, omx + size + 1, omy + size + 1, yellow (31));
00405     Fgl_line (omx + size, omy, omx + size, omy + size, blue (31));
00406 #endif
00407 }
00408 
00409 void
00410 draw_normal_mouse (int x, int y)
00411 {
00412     if (mouse_type == MOUSE_TYPE_SQUARE) {
00413         hide_square_mouse ();
00414         mouse_type = MOUSE_TYPE_NORMAL;
00415         kmouse_val = 8;
00416     }
00417 #if defined (SVGALIB)
00418     Fgl_getbox (x, y, 8, 8, under_mouse_pointer);
00419     if (x > cs_mouse_xmax - 8 || y > cs_mouse_ymax - 8) {
00420         Fgl_enableclipping ();
00421         Fgl_setclippingwindow (0, 0, cs_mouse_xmax, cs_mouse_ymax);
00422         Fgl_putbox (x, y, 8, 8, mouse_pointer);
00423         Fgl_disableclipping ();
00424     } else {
00425         Fgl_putbox (x, y, 8, 8, mouse_pointer);
00426     }
00427 #endif
00428     mox = x;
00429     moy = y;
00430 }
00431 
00432 void
00433 hide_normal_mouse (void)
00434 {
00435 #if defined (SVGALIB)
00436     if (mox > cs_mouse_xmax - 8 || moy > cs_mouse_ymax - 8) {
00437         Fgl_enableclipping ();
00438         Fgl_setclippingwindow (0, 0, cs_mouse_xmax, cs_mouse_ymax);
00439         Fgl_putbox (mox, moy, 8, 8, under_mouse_pointer);
00440         Fgl_disableclipping ();
00441     } else {
00442         Fgl_putbox (mox, moy, 8, 8, under_mouse_pointer);
00443     }
00444 #endif
00445 }
00446 
00447 void
00448 redraw_normal_mouse (void)
00449 {
00450 #if defined (SVGALIB)
00451     if (mox > cs_mouse_xmax - 8 || moy > cs_mouse_ymax - 8) {
00452         Fgl_enableclipping ();
00453         Fgl_setclippingwindow (0, 0, cs_mouse_xmax, cs_mouse_ymax);
00454         Fgl_getbox (mox, moy, 8, 8, under_mouse_pointer);
00455         Fgl_putbox (mox, moy, 8, 8, mouse_pointer);
00456         Fgl_disableclipping ();
00457     } else {
00458         /* may have changed */
00459         Fgl_getbox (mox, moy, 8, 8, under_mouse_pointer);
00460         Fgl_putbox (mox, moy, 8, 8, mouse_pointer);
00461     }
00462 #endif
00463 }
00464 
00465 void
00466 do_mouse_main_win (int px, int py, int button)
00467 {
00468     Rect* mw = &scr.main_win;
00469     int size;
00470     int x, y; /* mappoint */
00471 
00472     if (button == LC_MOUSE_MIDDLEBUTTON)
00473         return;
00474 
00475     pixel_to_mappoint(px, py, &x, &y);
00476 
00477     /* Bring up mappoint_stats for any right mouse click */
00478     if (button == LC_MOUSE_RIGHTBUTTON) {
00479         if (MP_TYPE(x,y) == CST_USED) {
00480             mappoint_stats (MP_INFO(x,y).int_1, MP_INFO(x,y).int_2, button);
00481         } else {
00482             mappoint_stats (x, y, button);
00483         }
00484         return;
00485     }
00486 
00487     /* Check rocket launches */
00488     if (button == LC_MOUSE_LEFTBUTTON) {
00489         int xx, yy;
00490         if (MP_TYPE(x,y) == CST_USED) {
00491             xx = MP_INFO(x,y).int_1;
00492             yy = MP_INFO(x,y).int_2;
00493         } else {
00494           xx = x;
00495           yy = y;
00496         }
00497         if (MP_TYPE(xx,yy) >= CST_ROCKET_5 && MP_TYPE(xx,yy) <= CST_ROCKET_7) {
00498           if (ask_launch_rocket_click (xx,yy)) {
00499             launch_rocket (xx, yy);
00500           }
00501         }
00502     }
00503 
00504     /* Handle multitransport */
00505     if (button == LC_MOUSE_LEFTBUTTON && 
00506         GROUP_IS_TRANSPORT(selected_module_group)) {
00507         if (mt_draw (px, py, MT_START)) {
00508             /* We need to set mps to current location, since the user might 
00509                click on the transport to see the mps */
00510             mappoint_stats (x, y, button);
00511             return;
00512         }
00513     }
00514 
00515     /* Handle bulldozing */
00516     if (selected_module_type == CST_GREEN && button != LC_MOUSE_RIGHTBUTTON) {
00517         check_bulldoze_area (x, y);
00518         return;
00519     }
00520 
00521     /* Bring up mappoint_stats for certain left mouse clicks */
00522     if (MP_TYPE(x,y) != CST_GREEN) {
00523         if (MP_TYPE(x,y) == CST_USED) {
00524             mappoint_stats (MP_INFO(x,y).int_1, MP_INFO(x,y).int_2, button);
00525         } else {
00526             mappoint_stats (x, y, button);
00527         }
00528         return;
00529     }
00530 
00531     /* OK, by now we are certain that the user wants to place the item.  
00532        Set the origin based on the size of the selected_module_type, and 
00533        see if the selected item will fit. */
00534     size = main_groups[selected_module_group].size;
00535     if (px > (mw->x + mw->w) - size*16)
00536         px = (mw->x + mw->w) - size*16;
00537     if (py > (mw->y + mw->h) - size*16)
00538         py = (mw->y + mw->h) - size*16;
00539     pixel_to_mappoint(px, py, &x, &y);
00540 
00541     if (size >= 2)
00542     {
00543         if (MP_TYPE(x + 1,y) != CST_GREEN
00544             || MP_TYPE(x,y + 1) != CST_GREEN
00545             || MP_TYPE(x + 1,y + 1) != CST_GREEN)
00546             return;
00547     }
00548     if (size >= 3)
00549     {
00550         if (MP_TYPE(x + 2,y) != CST_GREEN
00551             || MP_TYPE(x + 2,y + 1) != CST_GREEN
00552             || MP_TYPE(x + 2,y + 2) != CST_GREEN
00553             || MP_TYPE(x + 1,y + 2) != CST_GREEN
00554             || MP_TYPE(x,y + 2) != CST_GREEN)
00555             return;
00556     }
00557     if (size == 4)
00558     {
00559         if (MP_TYPE(x + 3,y) != CST_GREEN
00560             || MP_TYPE(x + 3,y + 1) != CST_GREEN
00561             || MP_TYPE(x + 3,y + 2) != CST_GREEN
00562             || MP_TYPE(x + 3,y + 3) != CST_GREEN
00563             || MP_TYPE(x + 2,y + 3) != CST_GREEN
00564             || MP_TYPE(x + 1,y + 3) != CST_GREEN
00565             || MP_TYPE(x,y + 3) != CST_GREEN)
00566             return;
00567     }
00568 
00569     /* Place the selected item */
00570     switch (place_item (x, y, selected_module_type)) {
00571     case 0:
00572         /* Success */
00573         break;
00574     case -1:
00575         /* Not enough money */
00576         no_credit_build_msg (selected_module_group);
00577         break;
00578     case -2:
00579         /* Improper port placement */
00580         /* TRANSLATORS: The part about the cup of tea is one of Ian's 
00581            jokes, but the part about ports needing to be connected 
00582            to rivers is true.  */
00583         if (yn_dial_box (_("WARNING"),
00584                          _("Ports need to be"),
00585                          _("connected to rivers!"),
00586                          _("Want to make a cup of tea?")) != 0)
00587             while (yn_dial_box (_("TEA BREAK"),
00588                                 _("Boil->pour->wait->stir"),
00589                                 _("stir->pour->stir->wait->drink...ahhh"),
00590                                 _("Have you finished yet?")) == 0);
00591         break;
00592     }
00593 }
00594 
00595 void
00596 do_mouse_other_buttons (int x, int y, int button)
00597 {
00598     Rect* mw = &scr.main_win;
00599 
00600     if (0) {} /* XXX: Cute, very cute */
00601 
00602     /* main screen border scroll areas */
00603 
00604     /* up */
00605     else if (x >= (mw->x - 8) && x < (mw->x + mw->w + 8)
00606              && y >= (mw->y - 8) && y < mw->y) {
00607         int new_origin_y;
00608         if (button == LC_MOUSE_RIGHTBUTTON) {
00609             new_origin_y = main_screen_originy - RIGHT_MOUSE_MOVE_VAL;
00610         } else {
00611             new_origin_y = main_screen_originy - 1;
00612         }
00613         adjust_main_origin (main_screen_originx, new_origin_y, 1);
00614     }
00615     /* down */
00616     else if (x >= (mw->x - 8) && x < (mw->x + mw->w + 8)
00617              && y > (mw->y + mw->h)
00618              && y < (mw->y + mw->h + 16)) {     /* 16 for bigger area */
00619         int new_origin_y;
00620         if (button == LC_MOUSE_RIGHTBUTTON) {
00621             new_origin_y = main_screen_originy + RIGHT_MOUSE_MOVE_VAL;
00622         } else {
00623             new_origin_y = main_screen_originy + 1;
00624         }
00625         adjust_main_origin (main_screen_originx, new_origin_y, 1);
00626     }
00627     /* left */
00628     else if (x >= (mw->x - 16) && x < mw->x
00629              && y >= (mw->y - 8) && y < (mw->y + mw->h + 8)) {
00630         int new_origin_x;
00631         if (button == LC_MOUSE_RIGHTBUTTON) {
00632             new_origin_x = main_screen_originx - RIGHT_MOUSE_MOVE_VAL;
00633         } else {
00634             new_origin_x = main_screen_originx - 1;
00635         }
00636         adjust_main_origin (new_origin_x, main_screen_originy, 1);
00637     }
00638     /* right */
00639     else if (x > (mw->x + mw->w)
00640              && x < (mw->x + mw->w + 8)
00641              && y > (mw->y - 8) && y < (mw->y + mw->w + 8)) {
00642         int new_origin_x;
00643         if (button == LC_MOUSE_RIGHTBUTTON) {
00644             new_origin_x = main_screen_originx + RIGHT_MOUSE_MOVE_VAL;
00645         } else {
00646             new_origin_x = main_screen_originx + 1;
00647         }
00648         adjust_main_origin (new_origin_x, main_screen_originy, 1);
00649     }
00650 
00651     /* This is the mini window. Clicking here move the main window 
00652        to this point 
00653     */
00654 
00655 /*** Miniscreen selector buttons removed in CVS Revision 1.24 ***/
00656 
00657     /* this is the menu button */
00658     else if (mouse_in_rect (&scr.menu_button,x,y)) {
00659         activate_help ("menu.hlp");
00660     }
00661 
00662     /* this is the help button */
00663     else if (mouse_in_rect (&scr.help_button,x,y)) {
00664         activate_help ("index.hlp");
00665     }
00666 
00667     /* this is the results (stats) button */
00668     else if (mouse_in_rect (&scr.results_button,x,y)) {
00669         if (button == LC_MOUSE_RIGHTBUTTON)
00670             return;
00671         window_results ();
00672     }
00673 
00674     /* Advance mps screen if clicked on */
00675     else if (mouse_in_rect (&scr.mappoint_stats,x,y)) {
00676         if (button == LC_MOUSE_RIGHTBUTTON) {
00677             switch (mps_global_style) {
00678             case MPS_GLOBAL_FINANCE:
00679                 activate_help ("finance.hlp");
00680                 break;
00681             case MPS_GLOBAL_OTHER_COSTS:
00682                 activate_help ("other-costs.hlp");
00683                 break;
00684             case MPS_GLOBAL_HOUSING:
00685                 activate_help ("housing.hlp");
00686                 break;
00687             }
00688             return;
00689         }
00690         advance_mps_style ();
00691         refresh_mps ();
00692     }
00693 
00694    /* Advance monthgraph screen if clicked on */
00695     else if (mouse_in_rect (&scr.monthgraph,x,y)) {
00696         if (button == LC_MOUSE_RIGHTBUTTON) {
00697             if (monthgraph_style == MONTHGRAPH_STYLE_ECONOMY) {
00698                 activate_help ("economy.hlp");
00699             } else {
00700                 activate_help ("sustain.hlp");
00701             }
00702             return;
00703         }
00704         advance_monthgraph_style ();
00705         refresh_monthgraph ();
00706     }
00707 
00708     /*
00709       // no more buttons to click on, see if it's help for somewhere else.
00710       // ***************************
00711     */
00712 
00713     if (mouse_in_rect (&scr.pbar_area,x,y)) {
00714       pbar_mouse(x, y, button);
00715       return;
00716     }
00717 
00718     if (button == LC_MOUSE_RIGHTBUTTON) {
00719 
00720 #if defined (FINANCE_WINDOW)
00721 
00722       /* now check for finance window */
00723       if (x >= FINANCE_X && x <= (FINANCE_X + FINANCE_W)
00724           && y >= FINANCE_Y && y <= (FINANCE_Y + FINANCE_H))
00725         {
00726           activate_help ("finance.hlp");
00727           return;
00728         }
00729 #endif
00730       
00731       
00732 #if defined (commentout)
00733       /* GCS FIX -- This is obsolete, right??? */
00734       /*     -- If so, can delete scr.sust from geometry.c */
00735       /* now check for the sustain window */
00736       else if (mouse_in_rect (&scr.sust,x,y)) {
00737         activate_help ("sustain.hlp");
00738         return;
00739       }
00740 #endif
00741     }
00742 }
00743 
00744 
00745 void
00746 check_bulldoze_area (int x, int y)
00747 {
00748     int xx, yy, g;
00749     if (MP_TYPE(x,y) == CST_USED) {
00750         xx = MP_INFO(x,y).int_1;
00751         yy = MP_INFO(x,y).int_2;
00752     } else {
00753         xx = x;
00754         yy = y;
00755     }
00756     g = MP_GROUP(xx,yy);
00757 
00758     /* GCS: Free bulldozing of most recently placed item is disabled.
00759        Still not sure how this can be done w/ multiplayer. */
00760     if (g == GROUP_MONUMENT && monument_bul_flag == 0) {
00761         if (yn_dial_box (_("WARNING"),
00762                          _("Bulldozing a monument costs"),
00763                          _("a lot of money."),
00764                          _("Want to bulldoze?")) == 0)
00765             return;
00766         monument_bul_flag = 1;
00767     }
00768     else if (g == GROUP_RIVER && river_bul_flag == 0) {
00769         if (yn_dial_box (_("WARNING"),
00770                          _("Bulldozing a section of river"),
00771                          _("costs a lot of money."),
00772                          _("Want to bulldoze?")) == 0)
00773             return;
00774         river_bul_flag = 1;
00775     }
00776     else if (g == GROUP_SHANTY && shanty_bul_flag == 0) {
00777         if (yn_dial_box (_("WARNING"),
00778                          _("Bulldozing a shanty town costs a"),
00779                          _("lot of money and may cause a fire."),
00780                          _("Want to bulldoze?")) == 0)
00781             return;
00782         shanty_bul_flag = 1;
00783     }
00784     else if (g == GROUP_TIP) {
00785         ok_dial_box ("nobull-tip.mes", BAD, 0L);
00786         return;
00787     }
00788 
00789     bulldoze_item (xx,yy);
00790 }
00791 
00792 void
00793 fire_area (int x, int y)
00794 {
00795   do_bulldoze_area (CST_FIRE_1, x, y);
00796   refresh_main_screen ();
00797   /*
00798     // update transport or we get stuff put in
00799     // the area from connected tracks etc.
00800   */
00801 }
00802 
00803 /* Called from event handler when middle button is held while moving
00804    the mouse.  Will probably handle multi-transport eventually */
00805 
00806 /* XXX: Need to put this in a header somewhere */
00807 
00808 void 
00809 drag_screen (void) 
00810 {
00811     Rect* mw = &scr.main_win;
00812     int cur_mappoint_x = 0;
00813     int cur_mappoint_y = 0;
00814 
00815     int cur_winpoint_x = 0;
00816     int cur_winpoint_y = 0;
00817   
00818     int origin_x = 0;
00819     int origin_y = 0;
00820 
00821     int in_main_window;
00822 
00823     if (buttons[LC_MOUSE_MIDDLEBUTTON-1].mappoint_x == 0) 
00824         return;   /* Not pressed in main window */
00825 
00826     in_main_window = pixel_to_mappoint(cs_mouse_x, cs_mouse_y, 
00827                                        &cur_mappoint_x, &cur_mappoint_y);
00828   
00829     pixel_to_winpoint(cs_mouse_x, cs_mouse_y, &cur_winpoint_x, &cur_winpoint_y);
00830   
00831     origin_x = 
00832             buttons[LC_MOUSE_MIDDLEBUTTON-1].mappoint_x - cur_winpoint_x;  
00833     origin_y =  
00834             buttons[LC_MOUSE_MIDDLEBUTTON-1].mappoint_y - cur_winpoint_y;  
00835 
00836     adjust_main_origin (origin_x, origin_y, 1);
00837 }
00838 
00839 void
00840 do_market_cb_template (int x, int y, int is_market_cb)
00841 {
00842     int old_flags = MP_INFO(mcbx,mcby).flags;
00843     Rect* mcb = &scr.market_cb;
00844     int is_sell;
00845 
00846     static Mouse_Handle * checkbox_mhandle;
00847     static Mouse_Handle * omni_mhandle;
00848 
00849     hide_mouse ();
00850     if (!mouse_in_rect(mcb,x,y)) {
00851         if (is_market_cb) {
00852             close_market_cb ();
00853         } else {
00854             close_port_cb ();
00855         }
00856         redraw_mouse ();
00857         return;
00858     }
00859 
00860     if (x >= mcb->x + 8 && x <= mcb->x + 6 * 8) {
00861         is_sell = 0;
00862     } else if (x >= mcb->x + 10 * 8 && x <= mcb->x + mcb->w - 8) {
00863         is_sell = 1;
00864     } else {
00865         redraw_mouse ();
00866         return;
00867     }
00868 
00869     /* jobs */
00870     if (is_market_cb && y >= mcb->y + 36 + (CB_SPACE * 0) 
00871       && y <= mcb->y + 52 + (CB_SPACE * 0))     {
00872         int flag = is_sell ? FLAG_MS_JOBS : FLAG_MB_JOBS;
00873         MP_INFO(mcbx,mcby).flags ^= flag;
00874         draw_cb_box (0, is_sell, MP_INFO(mcbx,mcby).flags & flag);
00875     }
00876     /* food */
00877     else if (y >= mcb->y + 36 + (CB_SPACE * 1) 
00878       && y <= mcb->y + 52 + (CB_SPACE * 1)) {
00879         int flag = is_sell ? FLAG_MS_FOOD : FLAG_MB_FOOD;
00880         MP_INFO(mcbx,mcby).flags ^= flag;
00881         draw_cb_box (1, is_sell, MP_INFO(mcbx,mcby).flags & flag);
00882     }
00883     /* coal */
00884     else if (y >= mcb->y + 36 + (CB_SPACE * 2)
00885       && y <= mcb->y + 52 + (CB_SPACE * 2)) {
00886         int flag = is_sell ? FLAG_MS_COAL : FLAG_MB_COAL;
00887         MP_INFO(mcbx,mcby).flags ^= flag;
00888         draw_cb_box (2, is_sell, MP_INFO(mcbx,mcby).flags & flag);
00889     }
00890     /* ore */
00891     else if (y >= mcb->y + 36 + (CB_SPACE * 3) 
00892       && y <= mcb->y + 52 + (CB_SPACE * 3)) {
00893         int flag = is_sell ? FLAG_MS_ORE : FLAG_MB_ORE;
00894         MP_INFO(mcbx,mcby).flags ^= flag;
00895         draw_cb_box (3, is_sell, MP_INFO(mcbx,mcby).flags & flag);
00896     }
00897     /* goods */
00898     else if (y >= mcb->y + 36 + (CB_SPACE * 4) 
00899       && y <= mcb->y + 52 + (CB_SPACE * 4)) {
00900         int flag = is_sell ? FLAG_MS_GOODS : FLAG_MB_GOODS;
00901         MP_INFO(mcbx,mcby).flags ^= flag;
00902         draw_cb_box (4, is_sell, MP_INFO(mcbx,mcby).flags & flag);
00903     }
00904     /* steel */
00905     else if (y >= mcb->y + 36 + (CB_SPACE * 5)
00906       && y <= mcb->y + 52 + (CB_SPACE * 5)) {
00907         int flag = is_sell ? FLAG_MS_STEEL : FLAG_MB_STEEL;
00908         MP_INFO(mcbx,mcby).flags ^= flag;
00909         draw_cb_box (5, is_sell, MP_INFO(mcbx,mcby).flags & flag);
00910     }
00911 
00912     redraw_mouse ();
00913 
00914 #if defined (NETWORK_ENABLE)
00915     if (MP_INFO(mcbx,mcby).flags != old_flags) {
00916         send_flags (mcbx,mcby);
00917     }
00918 #endif
00919 }
00920 
00921 void
00922 do_market_cb_mouse (int x, int y)
00923 {
00924     do_market_cb_template (x, y, 1);
00925 }
00926 
00927 void
00928 do_port_cb_mouse (int x, int y)
00929 {
00930     do_market_cb_template (x, y, 0);
00931 }
00932 
00933 void 
00934 no_credit_build_msg (int selected_group)
00935 {
00936 #ifdef GROUP_POWER_SOURCE_NO_CREDIT
00937   if (selected_group == GROUP_POWER_SOURCE) {
00938     ok_dial_box ("no-credit-solar-power.mes", BAD, 0L);
00939     return;
00940   }
00941 #endif
00942 #ifdef GROUP_UNIVERSITY_NO_CREDIT
00943   if (selected_group == GROUP_UNIVERSITY) {
00944     ok_dial_box ("no-credit-university.mes", BAD, 0L);
00945     return;
00946   }
00947 #endif
00948 #ifdef GROUP_PARKLAND_NO_CREDIT
00949   if (selected_group == GROUP_PARKLAND) {
00950     ok_dial_box ("no-credit-parkland.mes", BAD, 0L);
00951     return;
00952   }
00953 #endif
00954 #ifdef GROUP_RECYCLE_NO_CREDIT
00955   if (selected_group == GROUP_RECYCLE) {
00956     ok_dial_box ("no-credit-recycle.mes", BAD, 0L);
00957     return;
00958   }
00959 #endif
00960 #ifdef GROUP_ROCKET
00961   if (selected_group == GROUP_ROCKET) {
00962     ok_dial_box ("no-credit-rocket.mes", BAD, 0L);
00963     return;
00964   }
00965 #endif
00966   return;
00967 }
00968 
00969 void
00970 choose_residence (void)
00971 {
00972     int cost;
00973     FILE* tempfile;
00974     char* s = (char*) malloc (lc_save_dir_len + 9);
00975 
00976     sprintf (s, "%s%c%s", lc_save_dir, PATH_SLASH, "res.tmp");
00977     if ((tempfile = fopen (s, "w")) == 0)
00978         do_error ("Can't write res.tmp");
00979     free (s);
00980 
00981     fprintf (tempfile,
00982              /* TRANSLATORS: Don't translate the leading "text" */
00983              _("text -1 20 Choose the type of residence you want\n"));
00984     fprintf (tempfile,
00985              "text -1 30 =====================================\n");
00986     fprintf (tempfile,
00987              _("text -1 45 (LB=Low Birthrate HB=High Birthrate)\n"));
00988     fprintf (tempfile,
00989              _("text -1 55 (LD=Low Deathrate HD=High Deathrate)\n"));
00990     fprintf (tempfile, 
00991              _("text -1 85 Low Tech\n"));
00992 
00993     cost = get_group_cost(GROUP_RESIDENCE_LL);
00994     fprintf (tempfile, _("text 68 106 Cost %4d\n"), cost);
00995     fprintf (tempfile, "icon 85 120 reslowlow.csi\n");
00996     fprintf (tempfile, "button 83 118 52 52 return1\n");
00997     /* TRANSLATORS: Only translate "pop" <<for population>> */
00998     fprintf (tempfile, _("tbutton 82 180 return1 pop 50\n"));
00999     /* TRANSLATORS: Only translate LB, HD (low birth, high death) */
01000     fprintf (tempfile, _("text 89 195 LB HD\n"));
01001 
01002     cost = get_group_cost(GROUP_RESIDENCE_ML);
01003     fprintf (tempfile, _("text 155 106 Cost %4d\n"), cost);
01004     fprintf (tempfile, "icon 170 120 resmedlow.csi\n");
01005     fprintf (tempfile, "button 168 118 52 52 return2\n");
01006     fprintf (tempfile, _("tbutton 164 180 return2 pop 100\n"));
01007     fprintf (tempfile, _("text 175 195 HB LD\n"));
01008 
01009     cost = get_group_cost(GROUP_RESIDENCE_HL);
01010     fprintf (tempfile, _("text 238 106 Cost %4d\n"), cost);
01011     fprintf (tempfile, "icon 255 120 reshilow.csi\n");
01012     fprintf (tempfile, "button 253 118 52 52 return3\n");
01013     fprintf (tempfile, _("tbutton 250 180 return3 pop 200\n"));
01014     fprintf (tempfile, _("text 261 195 HB HD\n"));
01015 
01016     fprintf (tempfile, _("text -1 215 Click on one to select\n"));
01017     fprintf (tempfile, "text -1 225 ======================\n");
01018 
01019     if (((tech_level * 10) / MAX_TECH_LEVEL) > 2) {
01020         fprintf (tempfile, _("text -1 255 High Tech\n"));
01021 
01022         cost = get_group_cost(GROUP_RESIDENCE_LH);
01023         fprintf (tempfile, _("text 68 276 Cost %4d\n"), cost);
01024         fprintf (tempfile, "icon 85 290 reslowhi.csi\n");
01025         fprintf (tempfile, "button 83 288 52 52 return4\n");
01026         fprintf (tempfile, _("tbutton 78 350 return4 pop 100\n"));
01027         fprintf (tempfile, _("text 89 365 LB HD\n"));
01028 
01029         cost = get_group_cost(GROUP_RESIDENCE_MH);
01030         fprintf (tempfile, _("text 155 276 Cost %4d\n"), cost);
01031         fprintf (tempfile, "icon 170 290 resmedhi.csi\n");
01032         fprintf (tempfile, "button 168 288 52 52 return5\n");
01033         fprintf (tempfile, _("tbutton 164 350 return5 pop 200\n"));
01034         fprintf (tempfile, _("text 175 365 HB LD\n"));
01035 
01036         cost = get_group_cost(GROUP_RESIDENCE_HH);
01037         fprintf (tempfile, _("text 238 276 Cost %4d\n"), cost);
01038         fprintf (tempfile, "icon 255 290 reshihi.csi\n");
01039         fprintf (tempfile, "button 253 288 52 52 return6\n");
01040         fprintf (tempfile, _("tbutton 250 350 return6 pop 400\n"));
01041         fprintf (tempfile, _("text 261 365 HB HD\n"));
01042     }
01043 
01044     fclose (tempfile);
01045     block_help_exit = 1;
01046     activate_help ("res.tmp");
01047 }
01048 
01049 
01050 /* We can only draw temporary transport on GROUP_TRACK, GROUP_ROAD,
01051    GROUP_RAIL, or GROUP_BARE.  For temporary draws over GROUP_BARE, 
01052    FLAG_IS_TRANSPORT is not set.  For temporary draws over existing 
01053    transport of a different type, FLAG_IS_TRANSPORT is set, and 
01054    FLAG_MULTI_TRANSPORT_PREV will be set to 0 if the existing transport is 
01055    of the cheaper sort (e.g. GROUP_TRACK when overwriting with GROUP_ROAD), 
01056    and set to 1 if the existing transport if the more expensive sort
01057    (e.g. GROUP_RAIL when overwriting GROUP_ROAD).
01058 */
01059 inline int
01060 mt_erase(int x, int y)
01061 {
01062     if (x < 0 || y < 0 || x >= WORLD_SIDE_LEN || y >= WORLD_SIDE_LEN)
01063         return 1;
01064     if (MP_INFO(x,y).flags & FLAG_MULTI_TRANSPORT) {
01065         if (MP_INFO(x,y).flags & FLAG_IS_TRANSPORT) {
01066             if (!(MP_INFO(x,y).flags & FLAG_MULTI_TRANS_PREV)) {
01067                 if (mt_grp == GROUP_TRACK) {
01068                     MP_TYPE(x,y) = CST_ROAD_LR;
01069                     MP_GROUP(x,y) = GROUP_ROAD;
01070                 } else {
01071                     MP_TYPE(x,y) = CST_TRACK_LR;
01072                     MP_GROUP(x,y) = GROUP_TRACK;
01073                 }
01074             } else {
01075                 if (mt_grp == GROUP_RAIL) {
01076                     MP_TYPE(x,y) = CST_ROAD_LR;
01077                     MP_GROUP(x,y) = GROUP_ROAD;
01078                 } else {
01079                     MP_TYPE(x,y) = CST_RAIL_LR;
01080                     MP_GROUP(x,y) = GROUP_RAIL;
01081                 }
01082             }
01083         } else {
01084             MP_TYPE(x,y) = CST_GREEN;
01085             MP_GROUP(x,y) = GROUP_BARE;
01086         }
01087         MP_INFO(x,y).flags &= ~FLAG_MULTI_TRANSPORT;
01088         return 1;
01089     } else if ((MP_INFO(x,y).flags & FLAG_IS_TRANSPORT) 
01090                && (mt_grp == MP_GROUP(x,y))) {
01091         return 1;
01092     }
01093     return 0;
01094 }
01095 
01096 inline int
01097 mt_temp(int x, int y)
01098 {
01099     if (x < 0 || y < 0 || x >= WORLD_SIDE_LEN || y >= WORLD_SIDE_LEN)
01100         return 1;
01101     if (MP_INFO(x,y).flags & FLAG_IS_TRANSPORT) {
01102         if (MP_GROUP(x,y) == mt_grp) {
01103             return 1;
01104         } else if (!overwrite_transport_flag) {
01105             return 0;
01106         } else {
01107             if ((MP_GROUP(x,y) == GROUP_TRACK) ||
01108                 ((MP_GROUP(x,y) == GROUP_ROAD) && (mt_grp == GROUP_TRACK)))
01109             {
01110                 MP_INFO(x,y).flags &= ~FLAG_MULTI_TRANS_PREV;
01111             } else {
01112                 MP_INFO(x,y).flags |= FLAG_MULTI_TRANS_PREV;
01113             }
01114             mt_length++;
01115             MP_TYPE(x,y) = selected_module_type;
01116             MP_GROUP(x,y) = mt_grp;
01117             MP_INFO(x,y).flags |= FLAG_MULTI_TRANSPORT;
01118             return 1;
01119         }
01120     } else if (MP_GROUP(x,y) == GROUP_BARE) { 
01121         mt_length++;
01122         MP_TYPE(x,y) = selected_module_type;
01123         MP_GROUP(x,y) = mt_grp;
01124         MP_INFO(x,y).flags |= FLAG_MULTI_TRANSPORT;
01125         return 1;
01126     }
01127     return 0;
01128 }
01129 
01130 inline int
01131 mt_perm(int x, int y)
01132 {
01133     /* By now, it has already been mt_erase()'d */
01134     if (x < 0 || y < 0 || x >= WORLD_SIDE_LEN || y >= WORLD_SIDE_LEN)
01135         return 1;
01136     if (MP_INFO(x,y).flags & FLAG_IS_TRANSPORT) {
01137         if (MP_GROUP(x,y) == mt_grp) {
01138             return 1;
01139         } else if (!overwrite_transport_flag) {
01140             return 0;
01141         } else {
01142             bulldoze_item(x,y);
01143             place_item (x,y,selected_module_type);
01144             return 1;
01145         }
01146     } else if (MP_GROUP(x,y) == GROUP_BARE) { 
01147         place_item (x,y,selected_module_type);
01148         return 1;
01149     }
01150     return 0;
01151 }
01152 
01153 int
01154 do_mt_draw (int x1, int x2, int y1, int y2, int (*mode)())
01155 {
01156     int dir = 1;
01157     int horiz = 1;
01158     int vert = 2;
01159     int x_dir = cmp(x1, x2);
01160     int y_dir = cmp(y1, y2);
01161     int ix = x1;
01162     int iy = y1;
01163 
01164     mt_length = 0;
01165 
01166     if (!mode(ix, iy))
01167         return 0;
01168 
01169     while ((ix != x2 || iy != y2) && dir) {
01170         /* try horizontal, unless already vertical */
01171         if (dir == 1) {
01172             if (ix == x2) {
01173                 horiz = 0;
01174                 dir = vert;
01175             } else if (mode(ix+x_dir, iy)) {
01176                 horiz = 1;
01177                 vert = 2;
01178                 ix += x_dir;
01179             } else {
01180                 horiz = 0;
01181                 dir = vert;
01182             }
01183         } else if (dir == 2) {
01184             if (iy == y2) {
01185                 vert = 0;
01186                 dir = horiz;
01187             } else if (mode(ix, iy+y_dir)) {
01188                 horiz = 1;
01189                 vert = 2;
01190                 iy += y_dir;
01191             } else {
01192                 vert = 0;
01193                 dir = horiz;
01194             }
01195         }
01196     }
01197     if (dir) {  /* still had one direction to pick from, must have succeeded */
01198         return 1;
01199     } else {
01200         return 0;
01201     }
01202 }
01203 
01204 int
01205 mt_draw (int cxp, int cyp, int flag) /* c[xy]p are pixel coordinates */
01206 {
01207 
01208 #define STATUS_MESSAGE_LENGTH 80
01209     static int dx, dy; /* old current point; drawn point */
01210     static int ox, oy; /* coordinates for original button press */
01211     int cx, cy;   /* current mappoint coordinates */
01212     int draw_ret;
01213     char s[STATUS_MESSAGE_LENGTH];
01214 
01215     if (flag != MT_START && !mt_flag) 
01216         return 0;
01217     
01218     pixel_to_mappoint(cxp, cyp,  &cx, &cy);
01219 
01220     switch(flag) {
01221     case MT_SUCCESS:
01222         if (ox == 0)
01223             return 0;
01224         draw_ret = do_mt_draw(ox, dx, oy, dy, mt_erase);
01225 
01226         if (!draw_ret) {
01227             /* If mt_erase failed it is because we don't have clearance
01228                to build the road.  So clean up and exit. */
01229             mt_flag = 0;
01230             draw_main_window_box (green (8)); 
01231             status_message(0,0);
01232         }
01233         else if (draw_ret = do_mt_draw(ox, cx, oy, cy, mt_perm)) {
01234 
01235             print_total_money ();
01236             mt_flag = 0;
01237             draw_main_window_box (green (8)); 
01238             status_message(0,0);
01239         } else {
01240             /* This shouldn't happen.  Clean up and continue anyway.  */
01241             mt_flag = 0;
01242             status_message(0,0);
01243             draw_main_window_box (green (8)); 
01244         }
01245         dx = 0; dy = 0;
01246         ox = 0; oy = 0;
01247         break;
01248       
01249     case MT_FAIL:       
01250         mt_flag = 0;
01251         draw_main_window_box (green (8));
01252         draw_ret = do_mt_draw(ox, dx, oy, dy, mt_erase);
01253         status_message(0,0);
01254 
01255         dx = 0; dy = 0;
01256         ox = 0; oy = 0;
01257         break;
01258 
01259     case MT_CONTINUE: 
01260         if ((dx == cx && dy == cy) || ox == 0) 
01261             return 0;
01262         draw_ret = do_mt_draw(ox, dx, oy, dy, mt_erase);
01263 
01264         draw_ret = do_mt_draw(ox, cx, oy, cy, mt_temp);
01265 
01266         if (!draw_ret) {
01267             draw_ret = do_mt_draw(ox, cx, oy, cy, mt_erase);
01268             snprintf(s,STATUS_MESSAGE_LENGTH-1,
01269                      _("Can't build %s over that!"), mt_name);
01270         } else {
01271             snprintf(s,STATUS_MESSAGE_LENGTH-1,
01272                      _("%d sections of %s will cost %3d to build"),
01273                      mt_length, mt_name, 
01274                      mt_length * get_type_cost(selected_module_type));
01275         }
01276 
01277         status_message(0,s);
01278         dx = cx; dy = cy;
01279         break;
01280 
01281     case MT_START:
01282         /* XXX: we assume that a transport type is selected.   */
01283 
01284         if ((mt_grp = get_group_of_type(selected_module_type)) < 0 )
01285           return 0;
01286 
01287         get_type_name(selected_module_type,mt_name);
01288 
01289         dx = dy = 0;
01290         ox = buttons[LC_MOUSE_LEFTBUTTON-1].mappoint_x;
01291         oy = buttons[LC_MOUSE_LEFTBUTTON-1].mappoint_y;
01292         draw_ret = do_mt_draw(ox, cx, oy, cy, mt_temp);
01293 
01294         if (!draw_ret) {
01295             draw_ret = do_mt_draw(ox, cx, oy, cy, mt_erase);
01296             return 0;
01297         }
01298         dx = cx;
01299         dy = cy;
01300         mt_flag = 1;
01301         draw_main_window_box (cyan (20));
01302         break;
01303 
01304     default:
01305         ;
01306     }
01307 
01308     connect_transport_main_screen ();
01309     update_main_screen (0);
01310     return (1);
01311 }
01312 
01313 int 
01314 cmp(int n1, int n2)
01315 {
01316     if (n1 != n2) 
01317         return (n1 < n2) ? 1 : -1;
01318     else
01319         return 0;
01320 }
01321 
01322 void
01323 init_mouse_registry()
01324 {
01325     mhandle_first = NULL;
01326     mhandle_last = NULL;
01327     mhandle_current = NULL;
01328     mhandle_count = 0;
01329 }
01330 
01331 /* Add and return an entry in the registry.  Add it at the beginning, so
01332    it supercedes earlier entries in mouse_handle_click() */
01333 Mouse_Handle *
01334 mouse_register(Rect * r, void (*function)(int, int, int)) 
01335 {
01336     mhandle_current = (Mouse_Handle *)lcalloc(sizeof(Mouse_Handle));
01337     mhandle_count++;
01338     if (mhandle_first == NULL) {
01339         mhandle_current->next = NULL;
01340         mhandle_current->prev = NULL;
01341     } else {
01342         mhandle_current->next = mhandle_first;
01343         mhandle_first->prev = mhandle_current;
01344         mhandle_current->prev = NULL;
01345     }
01346 
01347     mhandle_first = mhandle_current;
01348 
01349     mhandle_current->r = r;
01350     mhandle_current->handler = function;
01351 
01352     return mhandle_current;
01353 }
01354 
01355 
01356 /* Remove an entry from the registry */
01357 void 
01358 mouse_unregister(Mouse_Handle * mhandle)
01359 {
01360     if (mhandle->prev == NULL) {
01361         if (mhandle_first != mhandle) 
01362             printf("debug: mhandle_first != mhandle\n");
01363         if (mhandle->next != NULL) {
01364             mhandle_first = mhandle->next;
01365             mhandle_first->prev = NULL;
01366         } else {
01367             mhandle_first = NULL;
01368         }
01369     } else if (mhandle->next == NULL) {
01370         mhandle->prev->next = NULL;
01371     } else {
01372         mhandle->prev->next = mhandle->next;
01373         mhandle->next->prev = mhandle->prev;
01374     }
01375 
01376     free(mhandle);
01377     mhandle_count--;
01378 }
01379 
01380 /* Loop through the registry until we find a handler for an area.  
01381    BEWARE!!!  Some handlers unregister themselves when called.  Assume 
01382    mhandle_current is undefined after calling mhandle_current->handler()
01383 */
01384 int 
01385 mouse_handle_click(int x, int y, int button) 
01386 {
01387     mhandle_current = mhandle_first;
01388 
01389     while (mhandle_current != NULL) {
01390         if (mouse_in_rect(mhandle_current->r,x,y)) {
01391             mhandle_current->handler(x - mhandle_current->r->x, 
01392                                      y - mhandle_current->r->y, button);
01393             return 1;
01394         }
01395         
01396         mhandle_current = mhandle_current->next;
01397     }
01398 
01399     return 0;
01400 }
01401     

Generated on Sun Dec 26 11:23:25 2004 for lincity by  doxygen 1.3.9.1