/* track.c - Created by Giampiero Caprino This file is part of Train Director Train Director is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Train Director is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Train Director; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #if !defined(__unix__) #include #endif #include "trsim.h" #include "ask.h" #define OLD /* old way of drawing tracks */ int terse_status; extern int current_tool; grcolor fieldcolors[MAXFIELDCOL]; int auto_link = 1; int show_links = 1; int link_startx, link_starty; int current_macro = -1; char *current_macro_name; Track **macros; int nmacros, maxmacros; VLines n_s_layout[] = { { HGRID / 2 + 1, 0, HGRID / 2 + 1, VGRID - 1 }, { HGRID / 2 - 0, 0, HGRID / 2 - 0, VGRID - 1 }, { -1 } }; SegDir n_s_segs[] = { SEG_N, SEG_S, SEG_END }; SegDir sw_n_segs[] = { SEG_SW, SEG_N, SEG_END }; SegDir nw_s_segs[] = { SEG_NW, SEG_S, SEG_END }; SegDir w_e_segs[] = { SEG_W, SEG_E, SEG_END }; SegDir nw_e_segs[] = { SEG_NW, SEG_E, SEG_END }; SegDir sw_e_segs[] = { SEG_SW, SEG_E, SEG_END }; SegDir w_ne_segs[] = { SEG_W, SEG_NE, SEG_END }; SegDir w_se_segs[] = { SEG_W, SEG_SE, SEG_END }; SegDir nw_se_segs[] = { SEG_NW, SEG_SE, SEG_END }; SegDir sw_ne_segs[] = { SEG_SW, SEG_NE, SEG_END }; SegDir ne_s_segs[] = { SEG_NE, SEG_S, SEG_END }; SegDir se_n_segs[] = { SEG_SE, SEG_N, SEG_END }; SegDir itin_segs[] = { SEG_NW, SEG_SW, SEG_NE, SEG_SE, SEG_W, SEG_E, SEG_END }; VLines sw_n_layout[] = { { HGRID / 2 + 1, 0, HGRID / 2 + 1, VGRID / 2 }, { HGRID / 2 - 0, 0, HGRID / 2 - 0, VGRID / 2 }, { HGRID / 2 + 1, VGRID / 2, 1, VGRID - 1 }, { HGRID / 2 - 0, VGRID / 2, 0, VGRID - 1 }, { HGRID / 2 - 0, VGRID / 2 - 1, 0, VGRID - 2 }, { -1 } }; VLines nw_s_layout[] = { { 1, 0, HGRID / 2 + 1, VGRID / 2 }, { 0, 0, HGRID / 2 - 0, VGRID / 2 }, { 0, 1, HGRID / 2 - 1, VGRID / 2 }, { HGRID / 2 + 1, VGRID / 2 - 0, HGRID / 2 + 1, VGRID - 1 }, { HGRID / 2 - 0, VGRID / 2 - 0, HGRID / 2 - 0, VGRID - 1 }, { -1 } }; VLines se_n_layout[] = { { HGRID / 2 + 1, 0, HGRID / 2 + 1, VGRID / 2 }, { HGRID / 2 - 0, 0, HGRID / 2 - 0, VGRID / 2 }, { HGRID / 2 + 1, VGRID / 2, HGRID - 1, VGRID - 2 }, { HGRID / 2 - 0, VGRID / 2, HGRID - 1, VGRID - 1 }, { HGRID / 2 - 0, VGRID / 2 + 1, HGRID - 2, VGRID - 1 }, { -1 } }; VLines ne_s_layout[] = { { HGRID / 2, VGRID / 2 - 1, HGRID - 2, 0 }, { HGRID / 2, VGRID / 2, HGRID - 1, 0 }, { HGRID / 2 + 1, VGRID / 2, HGRID - 1, 1 }, { HGRID / 2 + 1, VGRID / 2 - 0, HGRID / 2 + 1, VGRID - 1 }, { HGRID / 2 - 0, VGRID / 2 - 0, HGRID / 2 - 0, VGRID - 1 }, { -1 } }; VLines w_e_layout[] = { /*{ 0, VGRID / 2 - 1, HGRID - 1, VGRID / 2 - 1 },*/ { 0, VGRID / 2 - 0, HGRID - 1, VGRID / 2 - 0 }, { 0, VGRID / 2 + 1, HGRID - 1, VGRID / 2 + 1 }, { -1 } }; VLines nw_e_layout[] = { { 1, 0, HGRID / 2, VGRID / 2 - 1 }, { 0, 0, HGRID / 2, VGRID / 2 - 0 }, { 0, 1, HGRID / 2, VGRID / 2 + 1 }, /*{ HGRID / 2, VGRID / 2 - 1, HGRID - 1, VGRID / 2 - 1 },*/ { HGRID / 2, VGRID / 2 - 0, HGRID - 1, VGRID / 2 - 0 }, { HGRID / 2, VGRID / 2 + 1, HGRID - 1, VGRID / 2 + 1 }, { -1 } }; VLines sw_e_layout[] = { { 0, VGRID - 2, HGRID / 2 - 1, VGRID / 2 /*- 1*/ }, { 0, VGRID - 1, HGRID / 2, VGRID / 2 - 0 }, { 1, VGRID - 1, HGRID / 2, VGRID / 2 + 1 }, /*{ HGRID / 2, VGRID / 2 - 1, HGRID - 1, VGRID / 2 - 1 },*/ { HGRID / 2, VGRID / 2 - 0, HGRID - 1, VGRID / 2 - 0 }, { HGRID / 2, VGRID / 2 + 1, HGRID - 1, VGRID / 2 + 1 }, { -1 } }; VLines w_ne_layout[] = { /*{ 0, VGRID / 2 - 1, HGRID / 2, VGRID / 2 - 1 },*/ { 0, VGRID / 2 - 0, HGRID / 2, VGRID / 2 - 0 }, { 0, VGRID / 2 + 1, HGRID / 2, VGRID / 2 + 1 }, { HGRID / 2, VGRID / 2 - 1, HGRID - 2, 0 }, { HGRID / 2, VGRID / 2 - 0, HGRID - 1, 0 }, { HGRID / 2, VGRID / 2 + 1, HGRID - 1, 1 }, { -1 } }; VLines w_se_layout[] = { /*{ 0, VGRID / 2 - 1, HGRID / 2 - 0, VGRID / 2 - 1 },*/ { 0, VGRID / 2 - 0, HGRID / 2, VGRID / 2 - 0 }, { 0, VGRID / 2 + 1, HGRID / 2, VGRID / 2 + 1 }, { HGRID / 2 + 1, VGRID / 2 /*- 1*/, HGRID - 1, VGRID - 2 }, { HGRID / 2, VGRID / 2 - 0, HGRID - 1, VGRID - 1 }, { HGRID / 2, VGRID / 2 + 1, HGRID - 2, VGRID - 1 }, { -1 } }; VLines sweng_sw_ne_straight[] = { { 0, VGRID - 2, HGRID - 2, 0 }, { 0, VGRID - 1, HGRID - 1, 0 }, { 1, VGRID - 1, HGRID - 1, 1 }, { 0, VGRID / 2, HGRID / 2 - 1, VGRID / 2 }, { 0, VGRID / 2 + 1, HGRID / 2 - 1, VGRID / 2 + 1 }, { HGRID / 2 + 1, VGRID / 2 + 1, HGRID - 1, VGRID / 2 + 1 }, { HGRID / 2 + 1, VGRID / 2 - 0, HGRID - 1, VGRID / 2 - 0 }, { -1 } }; VLines sweng_sw_ne_switched[] = { { 0, VGRID / 2, HGRID - 2, 0 }, { 0, VGRID / 2 + 1, HGRID - 1, 0 }, { 0, VGRID - 1, HGRID - 1, VGRID / 2 }, { 1, VGRID - 1, HGRID - 1, VGRID / 2 + 1 }, { -1 } }; VLines sweng_nw_se_straight[] = { { 1, 0, HGRID - 1, VGRID - 2 }, { 0, 0, HGRID - 1, VGRID - 1 }, { 0, 1, HGRID - 2, VGRID - 1 }, { 0, VGRID / 2, HGRID / 2 - 1, VGRID / 2 }, { 0, VGRID / 2 + 1, HGRID / 2 - 1, VGRID / 2 + 1 }, { HGRID / 2 + 1, VGRID / 2 + 1, HGRID - 1, VGRID / 2 + 1 }, { HGRID / 2 + 1, VGRID / 2 - 0, HGRID - 1, VGRID / 2 - 0 }, { -1 } }; VLines sweng_nw_se_switched[] = { { 0, 0, HGRID - 1, VGRID / 2 }, { 0, 1, HGRID - 1, VGRID / 2 + 1 }, { 0, VGRID / 2, HGRID - 1, VGRID - 2 }, { 1, VGRID / 2 + 1, HGRID - 1, VGRID - 1 }, { -1 } }; VLines swengv_sw_ne_straight[] = { { HGRID / 2 + 1, 0, HGRID / 2 + 1, VGRID - 1 }, { HGRID / 2 - 0, 0, HGRID / 2 - 0, VGRID - 1 }, { 0, VGRID - 2, HGRID - 2, 0 }, { 0, VGRID - 1, HGRID - 1, 0 }, { 1, VGRID - 1, HGRID - 1, 1 }, { -1 } }; VLines swengv_sw_ne_switched[] = { { 0, VGRID - 2, HGRID / 2 - 0, 0 }, { 0, VGRID - 1, HGRID / 2 + 1, 0 }, { HGRID / 2 - 0, VGRID - 1, HGRID - 1, 0 }, { HGRID / 2 + 1, VGRID - 1, HGRID - 1, 1 }, { -1 } }; VLines swengv_nw_se_straight[] = { { HGRID / 2 + 1, 0, HGRID / 2 + 1, VGRID - 1 }, { HGRID / 2 - 0, 0, HGRID / 2 - 0, VGRID - 1 }, { 1, 0, HGRID - 1, VGRID - 2 }, { 0, 0, HGRID - 1, VGRID - 1 }, { 0, 1, HGRID - 2, VGRID - 1 }, { -1 } }; VLines swengv_nw_se_switched[] = { { 0, 0, HGRID / 2 - 1, VGRID - 1 }, { 0, 1, HGRID / 2 - 0, VGRID - 1 }, { HGRID / 2 - 0, 0, HGRID - 1, VGRID - 2 }, { HGRID / 2 + 1, 0, HGRID - 1, VGRID - 1 }, { -1 } }; VLines block_layout[] = { { HGRID / 2, VGRID / 2 - 1, HGRID / 2, VGRID / 2 + 2 }, { -1 } }; VLines block_layout_ns[] = { { HGRID / 2 - 1, VGRID / 2, HGRID / 2 + 2, VGRID / 2 }, { -1 } }; VLines nw_se_layout[] = { { 1, 0, HGRID - 1, VGRID - 2 }, { 0, 0, HGRID - 1, VGRID - 1 }, { 0, 1, HGRID - 2, VGRID - 1 }, { -1 } }; VLines sw_ne_layout[] = { { 0, VGRID - 2, HGRID - 2, 0 }, { 0, VGRID - 1, HGRID - 1, 0 }, { 1, VGRID - 1, HGRID - 1, 1 }, { -1 } }; VLines switch_rect[] = { { 0, 0, HGRID - 1, 0 }, { HGRID - 1, 0, HGRID - 1, VGRID - 1 }, { 0, 0, 0, VGRID - 1 }, { 0, VGRID - 1, HGRID - 1, VGRID - 1 }, { -1 } }; VLines w_e_platform_out[] = { { 0, VGRID / 2 - 3, HGRID - 1, VGRID / 2 - 3 }, { 0, VGRID / 2 + 3, HGRID - 1, VGRID / 2 + 3 }, { 0, VGRID / 2 - 3, 0, VGRID / 2 + 3 }, { HGRID - 1, VGRID / 2 - 3, HGRID - 1, VGRID / 2 + 3 }, { -1 } }; VLines w_e_platform_in[] = { { 1, VGRID / 2 - 2, HGRID - 2, VGRID / 2 - 2 }, { 1, VGRID / 2 - 1, HGRID - 2, VGRID / 2 - 1 }, { 1, VGRID / 2 - 0, HGRID - 2, VGRID / 2 - 0 }, { 1, VGRID / 2 + 1, HGRID - 2, VGRID / 2 + 1 }, { 1, VGRID / 2 + 2, HGRID - 2, VGRID / 2 + 2 }, { -1 } }; VLines n_s_platform_out[] = { { HGRID / 2 - 3, 0, HGRID / 2 - 3, VGRID - 1 }, { HGRID / 2 + 3, 0, HGRID / 2 + 3, VGRID - 1 }, { HGRID / 2 - 3, 0, HGRID / 2 + 3, 0 }, { HGRID / 2 - 3, VGRID - 1, HGRID / 2 + 3, VGRID - 1 }, { -1 } }; VLines n_s_platform_in[] = { { HGRID / 2 - 2, 1, HGRID / 2 - 2, VGRID - 2 }, { HGRID / 2 - 1, 1, HGRID / 2 - 1, VGRID - 2 }, { HGRID / 2 - 0, 1, HGRID / 2 - 0, VGRID - 2 }, { HGRID / 2 + 1, 1, HGRID / 2 + 1, VGRID - 2 }, { HGRID / 2 + 2, 1, HGRID / 2 + 2, VGRID - 2 }, { -1 } }; VLines itin_layout[] = { { 0, 0, HGRID - 1, VGRID - 1 }, { 0, VGRID / 2, HGRID - 1, VGRID / 2 }, { 0, VGRID - 1, HGRID - 1, 0 }, { -1 } }; VLines etrigger_layout[] = { { 1, 2, HGRID - 2, 2 }, { 1, 2, HGRID / 2, VGRID - 2 }, { HGRID / 2, VGRID - 2, HGRID - 2, 2 }, { -1 } }; VLines wtrigger_layout[] = { { 1, VGRID - 2, HGRID - 2, VGRID - 2 }, { 1, VGRID - 2, HGRID / 2, 2 }, { HGRID / 2, 2, HGRID - 2, VGRID - 2 }, { -1 } }; VLines ntrigger_layout[] = { { 2, 1, 2, VGRID - 2 }, { 2, 1, HGRID - 2, VGRID / 2 }, { 2, VGRID - 2, HGRID - 2, VGRID / 2 }, { -1 } }; VLines strigger_layout[] = { { HGRID - 2, 1, HGRID - 2, VGRID - 2 }, { 2, VGRID / 2, HGRID - 2, 1 }, { 2, VGRID / 2, HGRID - 2, VGRID - 2 }, { -1 } }; #if 0 VLines w_link[] = { { 0, VGRID / 2, HGRID / 2, VGRID / 2 }, { HGRID / 2, VGRID / 2, HGRID / 2 + 4, VGRID / 2 - 4 }, { HGRID / 2, VGRID / 2, HGRID / 2 + 4, VGRID / 2 + 4 }, { -1 } }; VLines e_link[] = { { HGRID / 2 - 4, VGRID / 2 - 4, HGRID / 2, VGRID / 2 }, { HGRID / 2 - 4, VGRID / 2 + 4, HGRID / 2, VGRID / 2 }, { HGRID / 2, VGRID / 2, HGRID - 1, VGRID / 2 }, { -1 } }; #endif void *e_train_pmap_default[4]; void *w_train_pmap_default[4]; void *e_car_pmap_default[4]; void *w_car_pmap_default[4]; void *e_train_pmap[4]; static const char * e_train_xpm[] = { "13 10 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", "........... ", ".XXXXXXXXX.. ", ".X..X..X..X..", ".XXXXXXXXXXX.", ".XXXXXXXXXXX.", ".............", " ... ... ", " ", " "}; void *w_train_pmap[4]; static const char * w_train_xpm[] = { "13 10 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ...........", " ..XXXXXXXXX.", "..X.X..X..XX.", ".XXXXXXXXXXX.", ".XXXXXXXXXXX.", ".............", " ... ... ", " ", " "}; void *w_car_pmap[4]; void *e_car_pmap[4]; static const char * car_xpm[] = { /* same for both e and w */ "13 10 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", "............ ", ".XXXXXXXXXX. ", ".X..X..X..X. ", ".XXXXXXXXXX. ", "XXXXXXXXXXXX ", "............ ", " ... ... ", " ", " "}; static void *speed_pmap; static const char *speed_xpm[] = { "8 3 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", "X c #000000000000", " .... ", " .. .. ", " .... "}; static void *camera_pmap; static const char *camera_xpm[] = { "13 10 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", "X c #0000FFFFFFFF", " ", " .. ", " ........... ", " . .. . ", " . ... . ", " . . . . ", " . ... . ", " . . ", " ........... ", " "}; static void *itin_pmap; static const char *itin_xpm[] = { "8 9 4 1", " c lightgray", ". c #000000000000", "X c gray", "# c black", " ", " .... ", " ...... ", "..XXXX..", ".XXXXXX.", "..XXXX..", "#......#", " #....# ", " #### " }; static void *n_sig_pmap[2]; /* R, G */ static void *n_sigx_pmap[2]; static const char *n_sig_xpm[] = { "7 9 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ... ", " .GGG. ", " .GGG. ", " .GGG. ", " ... ", " . ", " . ", " ..... "}; static const char *n_sigx_xpm[] = { "7 9 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ..... ", " .GGG. ", " .GGG. ", " .GGG. ", " ..... ", " . ", " . ", " ..... "}; static void *s_sig_pmap[2]; /* R, G */ static void *s_sigx_pmap[2]; static const char *s_sig_xpm[] = { "7 9 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ..... ", " . ", " . ", " ... ", " .GGG. ", " .GGG. ", " .GGG. ", " ... "}; static const char *s_sigx_xpm[] = { "7 9 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ..... ", " . ", " . ", " ..... ", " .GGG. ", " .GGG. ", " .GGG. ", " ..... "}; static void *n_sig2_pmap[4]; /* R, G */ static void *n_sig2x_pmap[4]; static const char *n_sig2_xpm[] = { "7 13 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ... ", " .GGG. ", " .GGG. ", " .GGG. ", " ... ", " ... ", " .XXX. ", " .XXX. ", " .XXX. ", " ... ", " . ", " . ", " ..... "}; static const char *n_sig2x_xpm[] = { "7 13 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ..... ", " .GGG. ", " .GGG. ", " .GGG. ", " ..... ", " ..... ", " .XXX. ", " .XXX. ", " .XXX. ", " ..... ", " . ", " . ", " ..... "}; static void *s_sig2_pmap[4]; /* R, G */ static void *s_sig2x_pmap[4]; /* R, G */ static const char *s_sig2_xpm[] = { "7 13 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ..... ", " . ", " . ", " ... ", " .XXX. ", " .XXX. ", " .XXX. ", " ... ", " ... ", " .GGG. ", " .GGG. ", " .GGG. ", " ... "}; static const char *s_sig2x_xpm[] = { "7 13 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ..... ", " . ", " . ", " ..... ", " .XXX. ", " .XXX. ", " .XXX. ", " ..... ", " ..... ", " .GGG. ", " .GGG. ", " .GGG. ", " ..... "}; static void *e_sig_pmap[2]; /* R, G */ static void *e_sigx_pmap[2]; static const char *e_sig_xpm[] = { "9 7 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", ". ... ", ". .GGG.", ".....GGG.", ". .GGG.", ". ... "}; static const char *e_sigx_xpm[] = { "9 7 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", ". .....", ". .GGG.", ".....GGG.", ". .GGG.", ". ....."}; static void *w_sig_pmap[2]; /* R, G */ static void *w_sigx_pmap[2]; static const char *w_sig_xpm[] = { "9 7 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", " ... .", ".GGG. .", ".GGG.....", ".GGG. .", " ... ." }; static const char *w_sigx_xpm[] = { "9 7 3 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", "..... .", ".GGG. .", ".GGG.....", ".GGG. .", "..... ." }; static void *e_sig2_pmap[4]; /* RR, GR, GG, GO */ static void *e_sig2x_pmap[4]; static const char *e_sig2_xpm[] = { "13 7 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", ". ... ... ", ". .XXX..GGG.", "....XXX..GGG.", ". .XXX..GGG.", ". ... ... "}; static const char *e_sig2x_xpm[] = { "13 7 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", ". ..........", ". .XXX..GGG.", "....XXX..GGG.", ". .XXX..GGG.", ". .........."}; static void *e_sigP_pmap[4]; /* RR, GR, GG, GO */ static const char *e_sigP_xpm[] = { "13 7 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", ". ...... ... ", ". XXXXX..GGG.", "....X.X..GGG.", ". ..XXX..GGG.", ". ...... ... "}; static void *w_sig2_pmap[4]; /* RR, GR, GG, GO */ static void *w_sig2x_pmap[4]; static const char *w_sig2_xpm[] = { "13 7 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", " ... ... .", ".GGG..XXX. .", ".GGG..XXX....", ".GGG..XXX. .", " ... ... ."}; static const char *w_sig2x_xpm[] = { "13 7 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", ".......... .", ".GGG..XXX. .", ".GGG..XXX....", ".GGG..XXX. .", ".......... ."}; static void *w_sigP_pmap[4]; /* RR, GR, GG, GO */ static const char *w_sigP_xpm[] = { "13 7 4 1", " c #FFFFFFFFFFFF", ". c #000000000000", NULL, /*"G c #0000FFFFFFFF",*/ NULL, /*"X c #0000FFFFFFFF",*/ " ", " ", " ... ...... .", ".GGG..XXX.. .", ".GGG..X.X....", ".GGG..XXXXX .", " ... ...... ."}; static char buff[256]; void init_pmaps(void) { int r, g, b; int fgr, fgg, fgb; char bufffg[64]; getcolor_rgb(fieldcolors[COL_TRACK], &fgr, &fgg, &fgb); sprintf(bufffg, ". c #%02x00%02x00%02x00", fgr, fgg, fgb); getcolor_rgb(fieldcolors[COL_BACKGROUND], &r, &g, &b); sprintf(buff, " c #%02x00%02x00%02x00", r, g, b); sprintf(buff, " c lightgray", r, g, b); e_train_xpm[1] = w_train_xpm[1] = car_xpm[1] = buff; e_train_xpm[2] = w_train_xpm[2] = car_xpm[2] = bufffg; e_train_xpm[3] = w_train_xpm[3] = car_xpm[3] = "X c orange"; e_train_pmap[0] = get_pixmap(e_train_xpm); w_train_pmap[0] = get_pixmap(w_train_xpm); e_car_pmap[0] = w_car_pmap[0] = get_pixmap(car_xpm); e_train_xpm[3] = w_train_xpm[3] = car_xpm[3] = "X c cyan"; e_train_pmap[1] = get_pixmap(e_train_xpm); w_train_pmap[1] = get_pixmap(w_train_xpm); e_car_pmap[1] = w_car_pmap[1] = get_pixmap(car_xpm); e_train_xpm[3] = w_train_xpm[3] = car_xpm[3] = "X c blue"; e_train_pmap[2] = get_pixmap(e_train_xpm); w_train_pmap[2] = get_pixmap(w_train_xpm); e_car_pmap[2] = w_car_pmap[2] = get_pixmap(car_xpm); e_train_xpm[3] = w_train_xpm[3] = car_xpm[3] = "X c yellow"; e_train_pmap[3] = get_pixmap(e_train_xpm); w_train_pmap[3] = get_pixmap(w_train_xpm); e_car_pmap[3] = w_car_pmap[3] = get_pixmap(car_xpm); sprintf(bufffg, ". c #%02x00%02x00%02x00", fgr, fgg, fgb); sprintf(buff, " c #%02x00%02x00%02x00", r, g, b); sprintf(buff, " c lightgray", r, g, b); n_sig_xpm[1] = s_sig_xpm[1] = e_sig_xpm[1] = w_sig_xpm[1] = n_sigx_xpm[1] = s_sigx_xpm[1] = e_sigx_xpm[1] = w_sigx_xpm[1] = buff; n_sig_xpm[2] = s_sig_xpm[2] = e_sig_xpm[2] = w_sig_xpm[2] = n_sigx_xpm[2] = s_sigx_xpm[2] = e_sigx_xpm[2] = w_sigx_xpm[2] = bufffg; n_sig_xpm[3] = s_sig_xpm[3] = e_sig_xpm[3] = w_sig_xpm[3] = n_sigx_xpm[3] = s_sigx_xpm[3] = e_sigx_xpm[3] = w_sigx_xpm[3] = "G c red"; n_sig_pmap[0] = get_pixmap(n_sig_xpm); s_sig_pmap[0] = get_pixmap(s_sig_xpm); e_sig_pmap[0] = get_pixmap(e_sig_xpm); w_sig_pmap[0] = get_pixmap(w_sig_xpm); n_sigx_pmap[0] = get_pixmap(n_sigx_xpm); s_sigx_pmap[0] = get_pixmap(s_sigx_xpm); e_sigx_pmap[0] = get_pixmap(e_sigx_xpm); w_sigx_pmap[0] = get_pixmap(w_sigx_xpm); n_sig_xpm[3] = s_sig_xpm[3] = e_sig_xpm[3] = w_sig_xpm[3] = n_sigx_xpm[3] = s_sigx_xpm[3] = e_sigx_xpm[3] = w_sigx_xpm[3] = "G c green"; n_sig_pmap[1] = get_pixmap(n_sig_xpm); s_sig_pmap[1] = get_pixmap(s_sig_xpm); e_sig_pmap[1] = get_pixmap(e_sig_xpm); w_sig_pmap[1] = get_pixmap(w_sig_xpm); n_sigx_pmap[1] = get_pixmap(n_sigx_xpm); s_sigx_pmap[1] = get_pixmap(s_sigx_xpm); e_sigx_pmap[1] = get_pixmap(e_sigx_xpm); w_sigx_pmap[1] = get_pixmap(w_sigx_xpm); e_sig2_xpm[1] = w_sig2_xpm[1] = n_sig2_xpm[1] = s_sig2_xpm[1] = e_sig2x_xpm[1] = w_sig2x_xpm[1] = n_sig2x_xpm[1] = s_sig2x_xpm[1] = e_sigP_xpm[1] = w_sigP_xpm[1] = buff; e_sig2_xpm[2] = w_sig2_xpm[2] = n_sig2_xpm[2] = s_sig2_xpm[2] = e_sig2x_xpm[2] = w_sig2x_xpm[2] = n_sig2x_xpm[2] = s_sig2x_xpm[2] = e_sigP_xpm[2] = w_sigP_xpm[2] = bufffg; e_sig2_xpm[3] = w_sig2_xpm[3] = n_sig2_xpm[3] = s_sig2_xpm[3] = e_sig2x_xpm[3] = w_sig2x_xpm[3] = n_sig2x_xpm[3] = s_sig2x_xpm[3] = e_sigP_xpm[3] = w_sigP_xpm[3] = "G c red"; e_sig2_xpm[4] = w_sig2_xpm[4] = n_sig2_xpm[4] = s_sig2_xpm[4] = e_sig2x_xpm[4] = w_sig2x_xpm[4] = n_sig2x_xpm[4] = s_sig2x_xpm[4] = "X c red"; e_sigP_xpm[4] = w_sigP_xpm[4] = "X c gray"; e_sig2_pmap[0] = get_pixmap(e_sig2_xpm); w_sig2_pmap[0] = get_pixmap(w_sig2_xpm); e_sigP_pmap[0] = get_pixmap(e_sigP_xpm); w_sigP_pmap[0] = get_pixmap(w_sigP_xpm); n_sig2_pmap[0] = get_pixmap(n_sig2_xpm); s_sig2_pmap[0] = get_pixmap(s_sig2_xpm); e_sig2x_pmap[0] = get_pixmap(e_sig2x_xpm); w_sig2x_pmap[0] = get_pixmap(w_sig2x_xpm); n_sig2x_pmap[0] = get_pixmap(n_sig2x_xpm); s_sig2x_pmap[0] = get_pixmap(s_sig2x_xpm); e_sig2_xpm[3] = w_sig2_xpm[3] = n_sig2_xpm[3] = s_sig2_xpm[3] = e_sig2x_xpm[3] = w_sig2x_xpm[3] = n_sig2x_xpm[3] = s_sig2x_xpm[3] = "G c green"; e_sigP_xpm[3] = w_sigP_xpm[3] = "G c green"; e_sig2_xpm[4] = w_sig2_xpm[4] = n_sig2_xpm[4] = s_sig2_xpm[4] = e_sig2x_xpm[4] = w_sig2x_xpm[4] = n_sig2x_xpm[4] = s_sig2x_xpm[4] = "X c red"; e_sigP_xpm[4] = w_sigP_xpm[4] = "X c gray"; e_sig2_pmap[1] = get_pixmap(e_sig2_xpm); w_sig2_pmap[1] = get_pixmap(w_sig2_xpm); e_sigP_pmap[1] = get_pixmap(e_sigP_xpm); w_sigP_pmap[1] = get_pixmap(w_sigP_xpm); n_sig2_pmap[1] = get_pixmap(n_sig2_xpm); s_sig2_pmap[1] = get_pixmap(s_sig2_xpm); e_sig2x_pmap[1] = get_pixmap(e_sig2x_xpm); w_sig2x_pmap[1] = get_pixmap(w_sig2x_xpm); n_sig2x_pmap[1] = get_pixmap(n_sig2x_xpm); s_sig2x_pmap[1] = get_pixmap(s_sig2x_xpm); e_sig2_xpm[3] = w_sig2_xpm[3] = n_sig2_xpm[3] = s_sig2_xpm[3] = e_sig2x_xpm[3] = w_sig2x_xpm[3] = n_sig2x_xpm[3] = s_sig2x_xpm[3] = "G c green"; e_sig2_xpm[4] = w_sig2_xpm[4] = n_sig2_xpm[4] = s_sig2_xpm[4] = e_sig2x_xpm[4] = w_sig2x_xpm[4] = n_sig2x_xpm[4] = s_sig2x_xpm[4] = "X c green"; e_sigP_xpm[4] = w_sigP_xpm[4] = "X c white"; e_sig2_pmap[2] = get_pixmap(e_sig2_xpm); w_sig2_pmap[2] = get_pixmap(w_sig2_xpm); e_sigP_pmap[2] = get_pixmap(e_sigP_xpm); w_sigP_pmap[2] = get_pixmap(w_sigP_xpm); n_sig2_pmap[2] = get_pixmap(n_sig2_xpm); s_sig2_pmap[2] = get_pixmap(s_sig2_xpm); e_sig2x_pmap[2] = get_pixmap(e_sig2x_xpm); w_sig2x_pmap[2] = get_pixmap(w_sig2x_xpm); n_sig2x_pmap[2] = get_pixmap(n_sig2x_xpm); s_sig2x_pmap[2] = get_pixmap(s_sig2x_xpm); e_sig2_xpm[3] = w_sig2_xpm[3] = n_sig2_xpm[3] = s_sig2_xpm[3] = e_sig2x_xpm[3] = w_sig2x_xpm[3] = n_sig2x_xpm[3] = s_sig2x_xpm[3] = "G c red"; e_sigP_xpm[3] = w_sigP_xpm[3] = "G c red"; e_sig2_xpm[4] = w_sig2_xpm[4] = n_sig2_xpm[4] = s_sig2_xpm[4] = e_sig2x_xpm[4] = w_sig2x_xpm[4] = n_sig2x_xpm[4] = s_sig2x_xpm[4] = "X c orange"; e_sigP_xpm[4] = w_sigP_xpm[4] = "X c white"; e_sig2_pmap[3] = get_pixmap(e_sig2_xpm); w_sig2_pmap[3] = get_pixmap(w_sig2_xpm); e_sigP_pmap[3] = get_pixmap(e_sigP_xpm); w_sigP_pmap[3] = get_pixmap(w_sigP_xpm); /*n_sig2_pmap[3] = get_pixmap(n_sig2_xpm); s_sig2_pmap[3] = get_pixmap(s_sig2_xpm);*/ e_sig2x_pmap[3] = get_pixmap(e_sig2x_xpm); w_sig2x_pmap[3] = get_pixmap(w_sig2x_xpm); sprintf(buff, " c #%02x00%02x00%02x00", r, g, b); sprintf(bufffg, ". c #%02x00%02x00%02x00", fgr, fgg, fgb); speed_xpm[1] = buff; speed_xpm[2] = bufffg; speed_pmap = get_pixmap(speed_xpm); for(r = 0; r < 4; ++r) { e_train_pmap_default[r] = e_train_pmap[r]; w_train_pmap_default[r] = w_train_pmap[r]; e_car_pmap_default[r] = e_car_pmap[r]; w_car_pmap_default[r] = w_car_pmap[r]; } } Track *track_new(void) { Track *t; t = malloc(sizeof(Track)); memset(t, 0, sizeof(Track)); t->xsize = 1; t->ysize = 1; t->type = NOTRACK; t->direction = NODIR; t->fgcolor = fieldcolors[COL_TRACK]; return(t); } void track_delete(Track *t) { Track *t1, *old; if(t == layout) layout = t->next; else { old = layout; for(t1 = old->next; t1 != t; t1 = t1->next) old = t1; old->next = t->next; } if(t->station) free(t->station); free(t); link_all_tracks(); } void track_name(Track *t, char *name) { if(t->station) free(t->station); t->station = strdup(name); } void track_draw(Track *t) { int fg; VLines *lns; fg = t->fgcolor; switch(t->status) { case ST_FREE: break; case ST_BUSY: fg = color_red; break; case ST_READY: fg = color_green; break; case ST_WORK: fg = color_blue; } switch(t->direction) { case TRK_N_S: #ifndef OLD draw_segments(t->x, t->y, n_s_segs, fg); goto n; #else lns = n_s_layout; break; #endif case SW_N: #ifndef OLD draw_segments(t->x, t->y, sw_n_segs, fg); goto n; #else lns = sw_n_layout; break; #endif case NW_S: #ifndef OLD draw_segments(t->x, t->y, nw_s_segs, fg); goto n; #else lns = nw_s_layout; break; #endif case W_E: #ifndef OLD draw_segments(t->x, t->y, w_e_segs, fg); goto n; #else lns = w_e_layout; break; #endif case NW_E: #ifndef OLD draw_segments(t->x, t->y, nw_e_segs, fg); goto n; #else lns = nw_e_layout; break; #endif case SW_E: #ifndef OLD draw_segments(t->x, t->y, sw_e_segs, fg); goto n; #else lns = sw_e_layout; break; #endif case W_NE: #ifndef OLD draw_segments(t->x, t->y, w_ne_segs, fg); goto n; #else lns = w_ne_layout; break; #endif case W_SE: #ifndef OLD draw_segments(t->x, t->y, w_se_segs, fg); goto n; #else lns = w_se_layout; break; #endif case NW_SE: #ifndef OLD draw_segments(t->x, t->y, nw_se_segs, fg); goto n; #else lns = nw_se_layout; break; #endif case SW_NE: #ifndef OLD draw_segments(t->x, t->y, sw_ne_segs, fg); goto n; #else lns = sw_ne_layout; break; #endif case NE_S: #ifndef OLD draw_segments(t->x, t->y, ne_s_segs, fg); goto n; #else lns = ne_s_layout; break; #endif case SE_N: #ifndef OLD draw_segments(t->x, t->y, se_n_segs, fg); goto n; #else lns = se_n_layout; break; #endif case XH_NW_SE: fg = t->direction; t->direction = NW_SE; track_draw(t); t->direction = W_E; track_draw(t); t->direction = fg; return; case XH_SW_NE: fg = t->direction; t->direction = SW_NE; track_draw(t); t->direction = W_E; track_draw(t); t->direction = fg; return; case X_X: fg = t->direction; t->direction = SW_NE; track_draw(t); t->direction = NW_SE; track_draw(t); t->direction = fg; return; case X_PLUS: fg = t->direction; t->direction = TRK_N_S; track_draw(t); t->direction = W_E; track_draw(t); t->direction = fg; return; } draw_layout(t->x, t->y, lns, fg); n: if(show_blocks && t->direction == W_E && t->length >= 100) draw_layout(t->x, t->y, block_layout, fieldcolors[TRACK]); if(show_blocks && t->direction == TRK_N_S && t->length >= 100) draw_layout(t->x, t->y, block_layout_ns, fieldcolors[TRACK]); if(editing && show_links) { if(t->wlinkx && t->wlinky) draw_link(t->x, t->y, t->wlinkx, t->wlinky, conf.linkcolor2); if(t->elinkx && t->elinky) draw_link(t->x, t->y, t->elinkx, t->elinky, conf.linkcolor2); } if(!show_speeds) return; if(t->speed[0] + t->speed[1] + t->speed[2] + t->speed[3]) draw_pixmap(t->x, t->y, speed_pmap); } void switch_draw(Track *t) { int fg; int tmp; fg = t->fgcolor; switch(t->status) { case ST_FREE: break; case ST_BUSY: fg = color_red; break; case ST_READY: fg = color_green; break; case ST_WORK: fg = color_blue; } tmp = t->direction; switch(tmp) { case 0: if(editing) { t->direction = W_NE; track_draw(t); t->direction = W_E; track_draw(t); } else if(t->switched) { t->direction = W_NE; track_draw(t); } else t->direction = W_E; track_draw(t); break; case 1: if(editing) { t->direction = NW_E; track_draw(t); t->direction = W_E; track_draw(t); } else if(t->switched) { t->direction = NW_E; track_draw(t); } else t->direction = W_E; track_draw(t); break; case 2: if(editing) { t->direction = W_SE; track_draw(t); t->direction = W_E; track_draw(t); } else if(t->switched) { t->direction = W_SE; track_draw(t); } else t->direction = W_E; track_draw(t); break; case 3: if(editing) { t->direction = SW_E; track_draw(t); t->direction = W_E; track_draw(t); } else if(t->switched) { t->direction = SW_E; track_draw(t); } else t->direction = W_E; track_draw(t); break; case 4: if(editing) { t->direction = SW_E; track_draw(t); t->direction = SW_NE; } else if(t->switched) t->direction = SW_E; else t->direction = SW_NE; track_draw(t); break; case 5: if(editing) { t->direction = W_NE; track_draw(t); t->direction = SW_NE; } else if(t->switched) t->direction = W_NE; else t->direction = SW_NE; track_draw(t); break; case 6: if(editing) { t->direction = NW_E; track_draw(t); t->direction = NW_SE; } else if(t->switched) { t->direction = NW_E; } else t->direction = NW_SE; track_draw(t); break; case 7: if(editing) { t->direction = W_SE; track_draw(t); t->direction = NW_SE; } else if(t->switched) t->direction = W_SE; else t->direction = NW_SE; track_draw(t); break; case 8: /* horizontal english switch */ if(t->switched && !editing) draw_layout(t->x, t->y, sweng_sw_ne_switched, fg); else draw_layout(t->x, t->y, sweng_sw_ne_straight, fg); break; case 9: /* horizontal english switch */ if(t->switched && !editing) draw_layout(t->x, t->y, sweng_nw_se_switched, fg); else draw_layout(t->x, t->y, sweng_nw_se_straight, fg); break; case 10: if(editing) { t->direction = W_SE; track_draw(t); t->direction = W_NE; } else if (t->switched) t->direction = W_SE; else t->direction = W_NE; track_draw(t); break; case 11: if(editing) { t->direction = SW_E; track_draw(t); t->direction = NW_E; } else if (t->switched) t->direction = SW_E; else t->direction = NW_E; track_draw(t); break; case 12: if(editing) { t->direction = TRK_N_S; track_draw(t); t->direction = SW_N; } else if(t->switched) t->direction = SW_N; else t->direction = TRK_N_S; track_draw(t); break; case 13: if(editing) { t->direction = TRK_N_S; track_draw(t); t->direction = SE_N; } else if(t->switched) t->direction = SE_N; else t->direction = TRK_N_S; track_draw(t); break; case 14: if(editing) { t->direction = TRK_N_S; track_draw(t); t->direction = NW_S; } else if(t->switched) t->direction = NW_S; else t->direction = TRK_N_S; track_draw(t); break; case 15: if(editing) { t->direction = TRK_N_S; track_draw(t); t->direction = NE_S; } else if(t->switched) t->direction = NE_S; else t->direction = TRK_N_S; track_draw(t); break; case 16: /* vertical english switch */ if(t->switched && !editing) draw_layout(t->x, t->y, swengv_sw_ne_switched, fg); else draw_layout(t->x, t->y, swengv_sw_ne_straight, fg); break; case 17: /* vertical english switch */ if(t->switched && !editing) draw_layout(t->x, t->y, swengv_nw_se_switched, fg); else draw_layout(t->x, t->y, swengv_nw_se_straight, fg); break; case 18: if(editing) { t->direction = SW_NE; track_draw(t); t->direction = SW_N; } else if(t->switched) t->direction = SW_N; else t->direction = SW_NE; track_draw(t); break; case 19: if(editing) { t->direction = SW_NE; track_draw(t); t->direction = NE_S; } else if(t->switched) t->direction = NE_S; else t->direction = SW_NE; track_draw(t); break; case 20: if(editing) { t->direction = NW_SE; track_draw(t); t->direction = SE_N; } else if(t->switched) t->direction = SE_N; else t->direction = NW_SE; track_draw(t); break; case 21: if(editing) { t->direction = NW_SE; track_draw(t); t->direction = NW_S; } else if(t->switched) t->direction = NW_S; else t->direction = NW_SE; track_draw(t); break; case 22: if(editing) { t->direction = NW_S; track_draw(t); t->direction = NE_S; } else if(t->switched) t->direction = NW_S; else t->direction = NE_S; track_draw(t); break; case 23: if(editing) { t->direction = SW_N; track_draw(t); t->direction = SE_N; } else if(t->switched) t->direction = SW_N; else t->direction = SE_N; track_draw(t); break; } if(!t->norect) draw_layout(t->x, t->y, switch_rect, fieldcolors[TRACK]); t->direction = tmp; } void platform_draw(Track *t) { switch(t->direction) { case W_E: draw_layout(t->x, t->y, w_e_platform_out, fieldcolors[TRACK]); draw_layout(t->x, t->y, w_e_platform_in, color_darkgray); break; case N_S: draw_layout(t->x, t->y, n_s_platform_out, fieldcolors[TRACK]); draw_layout(t->x, t->y, n_s_platform_in, color_darkgray); break; } } void signal_draw(Track *t) { grcolor color = color_red; int i; void *p = 0; i = 0; /* RR */ if(t->fleeted) { if(t->status == ST_GREEN) { if(t->nowfleeted) i = 2; /* GG */ else i = 1; /* GR */ } else if(t->nowfleeted) i = 3; /* RO */ switch(t->direction) { case W_E: p = signal_traditional ? (t->signalx ? e_sig2x_pmap[i] : e_sig2_pmap[i]) : e_sigP_pmap[i]; break; case E_W: p = signal_traditional ? (t->signalx ? w_sig2x_pmap[i] : w_sig2_pmap[i]) : w_sigP_pmap[i]; break; case N_S: p = t->signalx ? s_sig2x_pmap[i] : s_sig2_pmap[i]; break; case S_N: p = t->signalx ? n_sig2x_pmap[i] : n_sig2_pmap[i]; break; } if(p) draw_pixmap(t->x, t->y, p); if(editing && show_links && t->controls) draw_link(t->x, t->y, t->controls->x, t->controls->y, conf.linkcolor); return; } if(t->status == ST_GREEN) i = 1; switch(t->direction) { case W_E: p = t->signalx ? e_sigx_pmap[i] : e_sig_pmap[i]; break; case E_W: p = t->signalx ? w_sigx_pmap[i] : w_sig_pmap[i]; break; case N_S: p = t->signalx ? s_sigx_pmap[i] : s_sig_pmap[i]; break; case S_N: p = t->signalx ? n_sigx_pmap[i] : n_sig_pmap[i]; break; } if(p) draw_pixmap(t->x, t->y, p); if(editing && show_links && t->controls) draw_link(t->x, t->y, t->controls->x, t->controls->y, conf.linkcolor); } void train_draw(Track *t, Train *trn) { void *pixels; if(!e_train_pmap[0]) { init_pmaps(); } if(trn->direction == W_E) pixels = trn->epix == -1 ? e_train_pmap[trn->type] : pixmaps[trn->epix].pixels; else pixels = trn->wpix == -1 ? w_train_pmap[trn->type] : pixmaps[trn->wpix].pixels; draw_pixmap(t->x, t->y, pixels); } void car_draw(Track *t, Train *trn) { void *pixels; if(!e_car_pmap[0]) { init_pmaps(); } if(trn->direction == W_E) pixels = trn->ecarpix == -1 ? e_car_pmap[trn->type] : carpixmaps[trn->ecarpix].pixels; else pixels = trn->wcarpix == -1 ? w_car_pmap[trn->type] : carpixmaps[trn->wcarpix].pixels; draw_pixmap(t->x, t->y, pixels); } void text_draw(Track *t) { Track *lnk; if(!t->station) return; tr_fillrect(t->x, t->y); draw_layout_text1(t->x, t->y, t->station, t->direction); if(!editing || !show_links) return; if(t->elinkx && t->elinky) draw_link(t->x, t->y, t->elinkx, t->elinky, conf.linkcolor); else if(t->wlinkx && t->wlinky) draw_link(t->x, t->y, t->wlinkx, t->wlinky, conf.linkcolor); } void link_draw(Track *t) { tr_fillrect(t->x, t->y); if(t->direction == W_E) draw_layout_text1(t->x, t->y, "...to...", 1); else draw_layout_text1(t->x, t->y, "Link...", 1); } void macro_draw(Track *t) { tr_fillrect(t->x, t->y); if(t->direction == 0) draw_layout_text1(t->x, t->y, "Macro", 1); else draw_layout_text1(t->x, t->y, "Place", 1); } void itin_draw(Track *t) { if(!itin_pmap) itin_pmap = get_pixmap(itin_xpm); tr_fillrect(t->x, t->y); #ifdef OLD /*draw_layout(t->x, t->y, itin_layout, color_black);*/ draw_pixmap(t->x, t->y, itin_pmap); #else #endif if(t->station) draw_layout_text1(t->x + 1, t->y, t->station, t->direction == 1); } void trigger_draw(Track *t) { VLines *img; #if 0 if(t->wlinkx < t->x) { /* decide which based on * positiob of linked track */ img = ntrigger_layout; } else if(t->wlinkx > t->x) { img = strigger_layout; } else if(t->wlinky < t->y) { img = etrigger_layout; } else if(t->wlinky > t->y) { img = wtrigger_layout; } else /* linked to itself? impossible! */ return; #else switch(t->direction) { case S_N: img = ntrigger_layout; break; case N_S: img = strigger_layout; break; case W_E: img = etrigger_layout; break; case E_W: img = wtrigger_layout; break; default: return; } #endif draw_layout(t->x, t->y, img, color_blue); } void image_draw(Track *t) { char buff[256]; char *p; if(!camera_pmap) camera_pmap = get_pixmap(camera_xpm); if(t->direction || !t->station || !*t->station) {/* filename! */ if(!t->pixels) t->pixels = camera_pmap; } else if(!t->pixels) { t->pixels = get_pixmap_file(t->station); if(!t->pixels) { /* for UNIX, try lower case name */ strcpy(buff, t->station); for(p = buff; *p; ++p) if(*p >= 'A' && *p <= 'Z') *p += ' '; t->pixels = get_pixmap_file(buff); } if(!t->pixels) { sprintf(buff, "%s '%s'.", L("Error reading"), t->station); do_alert(buff); t->pixels = camera_pmap; } } draw_pixmap(t->x, t->y, t->pixels); } void track_paint(Track *t) { tr_fillrect(t->x, t->y); switch(t->type) { case TRACK: track_draw(t); break; case SWITCH: switch_draw(t); break; case PLATFORM: platform_draw(t); break; case TSIGNAL: signal_draw(t); break; case TRAIN: /* trains are handled differently */ /* train_draw(t); */ break; case TEXT: text_draw(t); break; case LINK: link_draw(t); break; case IMAGE: image_draw(t); break; case MACRO: macro_draw(t); break; case ITIN: itin_draw(t); break; case TRIGGER: trigger_draw(t); break; default: return; } } char *train_next_stop(Train *t, int *final) { Track *tr; static char buff[256]; TrainStop *ts, *last; *final = 0; if(t->status != train_RUNNING && t->status != train_WAITING && t->status != train_STOPPED) return ""; buff[0] = 0; last = 0; for(ts = t->stops; ts; ts = ts->next) { if(!ts->minstop) continue; if(!(tr = findStationNamed(ts->station)) || tr->type != TRACK) continue; if(ts->stopped) continue; if(!last || ts->arrival < last->arrival) last = ts; } if(!last) { tr = findStationNamed(t->exit); if(!tr || tr->type == TEXT) return ""; *final = 1; sprintf(buff, " %s %s %s %s ", L("Final stop"), t->exit, L("at"), format_time(t->timeout)); } else sprintf(buff, " %s %s %s %s ", L("Next stop"), last->station, L("at"), format_time(last->arrival)); return buff; } char *train_status0(Train *t, int full) { static char buff[256]; int i, j, k, final; if(terse_status) full = 0; buff[0] = 0; i = 0; switch(t->status) { case train_READY: if(!t->days || !run_day || (t->days & run_day)) return L("ready"); sprintf(buff, "%s ", L("Canceled - runs on")); k = strlen(buff); for(i = 1, j = '1'; i < 0x80; i <<= 1, ++j) if(t->days & i) buff[k++] = j; buff[k] = 0; return buff; case train_RUNNING: if(full) strcpy(buff, train_next_stop(t, &final)); if(t->shunting) strcpy(buff + strlen(buff), L("Shunting")); else if(full) { if(final) sprintf(buff + strlen(buff), "%s: %d Km/h", L("Speed"), t->curspeed); else sprintf(buff + strlen(buff), "%s: %d Km/h %s %s", L("Speed"), t->curspeed, L("to"), t->exit); } else sprintf(buff + strlen(buff), "%s %s", L("Running. Dest."), t->exit); return buff; case train_STOPPED: if(full) { sprintf(buff, "%s %s ", L("Stopped. ETD"), format_time(t->timedep)); if(full) strcat(buff, train_next_stop(t, &final)); if(!final) { strcat(buff, L("Dest")); strcat(buff, " "); strcat(buff, t->exit); } } else sprintf(buff, "%s %s %s %s", L("Stopped. ETD"), format_time(t->timedep), L("Dest."), t->exit); return buff; case train_DELAY: sprintf(buff, "%s %s", L("Delayed entry at"), t->entrance); return buff; case train_WAITING: sprintf(buff, "%s. %s%s %s", L("Waiting"), full ? train_next_stop(t, &final) : "", L("Dest."), t->exit); return buff; case train_DERAILED: return L("derailed"); case train_ARRIVED: if(t->wrongdest) sprintf(buff, "%s %s %s %s", L("Arrived at"), t->exited, L("instead of"), t->exit); else if(t->timeexited / 60 > t->timeout / 60) sprintf(buff, "%s %d %s %s", L("Arrived"), (t->timeexited - t->timeout) / 60, L("min. late at"), t->exit); else sprintf(buff, L("Arrived on time")); if(t->stock) sprintf(buff + strlen(buff), " - %s %s", L("stock for"), t->stock); return buff; } return ""; } char *train_status(Train *t) { return train_status0(t, 0); } void walk_vertical(Track *trk, Track *t, trkdir *ndir) { if(*ndir == N_S) { if(t->elinkx && t->elinky) { trk->x = t->elinkx; trk->y = t->elinky; return; } trk->x = t->x; trk->y = t->y + 1; return; } if(t->wlinkx && t->wlinky) { trk->x = t->wlinkx; trk->y = t->wlinky; return; } trk->x = t->x; trk->y = t->y - 1; } void walk_vertical_switch(Track *trk, Track *t, trkdir *ndir) { switch(t->direction) { case 12: if(*ndir == W_E) *ndir = S_N; if(*ndir == S_N) { trk->x = t->x; trk->y = t->y - 1; } else if(t->switched) { trk->x = t->x - 1; trk->y = t->y + 1; *ndir = E_W; } else { trk->x = t->x; trk->y = t->y + 1; } break; case 13: if(*ndir == E_W) *ndir = S_N; if(*ndir == S_N) { trk->x = t->x; trk->y = t->y - 1; } else if(t->switched) { trk->x = t->x + 1; trk->y = t->y + 1; *ndir = W_E; } else { trk->x = t->x; trk->y = t->y + 1; } break; case 14: if(*ndir == W_E) *ndir = N_S; if(*ndir == N_S) { trk->x = t->x; trk->y = t->y + 1; } else if(t->switched) { trk->x = t->x - 1; trk->y = t->y - 1; *ndir = E_W; } else { trk->x = t->x; trk->y = t->y - 1; } break; case 15: if(*ndir == E_W) *ndir = N_S; if(*ndir == N_S) { trk->x = t->x; trk->y = t->y + 1; } else if(t->switched) { trk->x = t->x + 1; trk->y = t->y - 1; *ndir = W_E; } else { trk->x = t->x; trk->y = t->y - 1; } break; case 18: if(t->switched) { if(*ndir == W_E) *ndir = S_N; if(*ndir == S_N) { trk->x = t->x; trk->y = t->y - 1; } else { trk->x = t->x - 1; trk->y = t->y + 1; *ndir = E_W; } break; } if(*ndir == W_E) { trk->x = t->x + 1; trk->y = t->y - 1; } else { trk->x = t->x - 1; trk->y = t->y + 1; } break; case 19: if(t->switched) { if(*ndir == E_W) *ndir = N_S; if(*ndir == S_N) { trk->x = t->x + 1; trk->y = t->y - 1; *ndir = W_E; } else { trk->x = t->x; trk->y = t->y + 1; } break; } if(*ndir == W_E) { trk->x = t->x + 1; trk->y = t->y - 1; } else { trk->x = t->x - 1; trk->y = t->y + 1; } break; case 20: if(t->switched) { if(*ndir == E_W) *ndir = S_N; if(*ndir == N_S) { trk->x = t->x + 1; trk->y = t->y + 1; *ndir = W_E; } else { trk->x = t->x; trk->y = t->y - 1; } break; } if(*ndir == W_E) { trk->x = t->x + 1; trk->y = t->y + 1; } else { trk->x = t->x - 1; trk->y = t->y - 1; } break; case 21: if(t->switched) { if(*ndir == W_E) *ndir = N_S; if(*ndir == S_N) { trk->x = t->x - 1; trk->y = t->y - 1; *ndir = E_W; } else { trk->x = t->x; trk->y = t->y + 1; } break; } if(*ndir == W_E) { trk->x = t->x + 1; trk->y = t->y + 1; } else { trk->x = t->x - 1; trk->y = t->y - 1; } break; case 22: if(t->switched) { if(*ndir == S_N) { trk->x = t->x - 1; trk->y = t->y - 1; *ndir = E_W; break; } } else if(*ndir == S_N) { trk->x = t->x + 1; trk->y = t->y - 1; *ndir = W_E; break; } trk->x = t->x; trk->y = t->y + 1; *ndir = N_S; break; case 23: if(t->switched) { if(*ndir == N_S) { trk->x = t->x - 1; trk->y = t->y + 1; *ndir = E_W; break; } } else if(*ndir == N_S) { trk->x = t->x + 1; trk->y = t->y + 1; *ndir = W_E; break; } trk->x = t->x; trk->y = t->y - 1; *ndir = S_N; break; } } Track *track_walkeast(Track *t, trkdir *ndir) { static Track trk; if(t->direction != TRK_N_S && t->elinkx && t->elinky) { trk.x = t->elinkx; trk.y = t->elinky; return &trk; } trk.x = t->x + 1; trk.y = t->y; switch(t->direction) { case NW_SE: case W_SE: ++trk.y; break; case SW_NE: case W_NE: --trk.y; break; case SW_N: if(*ndir == N_S) { trk.x = t->x - 1; trk.y = t->y + 1; *ndir = E_W; break; } trk.y = t->y - 1; trk.x = t->x; *ndir = S_N; break; case NW_S: if(*ndir == S_N) { *ndir = E_W; trk.x = t->x - 1; trk.y = t->y - 1; break; } trk.x = t->x; trk.y = t->y + 1; *ndir = N_S; break; case NE_S: if(*ndir == S_N) { *ndir = W_E; trk.x = t->x + 1; trk.y = t->y - 1; break; } trk.x = t->x; trk.y = t->y + 1; *ndir = N_S; break; case SE_N: if(*ndir == N_S) { trk.x = t->x + 1; trk.y = t->y + 1; *ndir = W_E; break; } trk.y = t->y - 1; trk.x = t->x; *ndir = S_N; break; case TRK_N_S: walk_vertical(&trk, t, ndir); break; default: *ndir = W_E; } return &trk; } Track *track_walkwest(Track *t, trkdir *ndir) { static Track trk; if(t->direction != TRK_N_S && t->wlinkx && t->wlinky) { trk.x = t->wlinkx; trk.y = t->wlinky; return &trk; } trk.x = t->x - 1; trk.y = t->y; switch(t->direction) { case SW_N: if(*ndir == N_S) { ++trk.y; *ndir = E_W; break; } *ndir = S_N; case SW_NE: case SW_E: ++trk.y; break; case NW_S: if(*ndir == N_S) { trk.x = t->x; trk.y = t->y + 1; break; } *ndir = E_W; case NW_SE: case NW_E: --trk.y; break; case NE_S: if(*ndir == S_N) { trk.x = t->x + 1; trk.y = t->y - 1; *ndir = W_E; break; } *ndir = N_S; trk.y = t->y + 1; trk.x = t->x; break; case SE_N: if(*ndir == N_S) { trk.x = t->x + 1; trk.y = t->y + 1; *ndir = W_E; break; } *ndir = S_N; trk.x = t->x; trk.y = t->y - 1; break; case TRK_N_S: walk_vertical(&trk, t, ndir); break; default: *ndir = E_W; } return &trk; } Track *swtch_walkeast(Track *t, trkdir *ndir) { static Track trk; trk.x = t->x; trk.y = t->y; switch(t->direction) { case 0: ++trk.x; if(t->switched) --trk.y; break; case 1: case 3: case 11: ++trk.x; break; case 2: ++trk.x; if(t->switched) ++trk.y; break; case 4: ++trk.x; if(!t->switched) --trk.y; break; case 5: ++trk.x; --trk.y; break; case 6: ++trk.x; if(!t->switched) ++trk.y; break; case 7: ++trk.x; ++trk.y; break; case 8: /* These are special cases handled in findPath() */ case 9: case 16: case 17: break; case 10: ++trk.x; if(t->switched) ++trk.y; else --trk.y; break; case 12: case 13: case 14: case 15: case 18: case 19: case 20: case 21: case 22: case 23: walk_vertical_switch(&trk, t, ndir); break; } return &trk; } Track *swtch_walkwest(Track *t, trkdir *ndir) { static Track trk; trk.x = t->x; trk.y = t->y; switch(t->direction) { case 1: --trk.x; if(t->switched) --trk.y; break; case 0: case 2: case 10: --trk.x; break; case 3: --trk.x; if(t->switched) ++trk.y; break; case 4: --trk.x; ++trk.y; break; case 5: --trk.x; if(!t->switched) ++trk.y; break; case 7: --trk.x; if(!t->switched) --trk.y; break; case 6: --trk.x; --trk.y; break; case 8: /* These are special cases handled in findPath() */ case 9: case 16: case 17: break; case 11: --trk.x; if(t->switched) ++trk.y; else --trk.y; break; case 12: case 13: case 14: case 15: case 18: case 19: case 20: case 21: case 22: case 23: walk_vertical_switch(&trk, t, ndir); } return &trk; } void check_layout_errors(void) { Track *t, *t1; char buff[256]; int firsttime = 1; for(t = layout; t; t = t->next) { buff[0] = 0; if(t->type == TSIGNAL) { if(!t->controls) sprintf(buff, "%s %d,%d %s.\n", L("Signal at"), t->x, t->y, L("not linked to any track")); else switch(t->direction) { case E_W: case signal_WEST_FLEETED: case N_S: if(!t->controls->wsignal) sprintf(buff, "%s %d,%d - %s %d,%d.\n", L("Track at"), t->controls->x, t->controls->y, L("not controlled by signal at"), t->x, t->y); break; case W_E: case signal_EAST_FLEETED: case S_N: if(!t->controls->esignal) sprintf(buff, "%s %d,%d - %s %d,%d.\n", L("Track at"), t->controls->x, t->controls->y, L("not controlled by signal at"), t->x, t->y); break; } } if(t->type == TRACK) { if(t->wlinkx && t->wlinky) { if(!(t1 = findTrack(t->wlinkx, t->wlinky))) sprintf(buff, "%s %d,%d %s %d,%d.\n", L("Track at"), t->x, t->y, L("linked to non-existant track at"), t->wlinkx, t->wlinky); else if(!findTrack(t1->elinkx, t1->elinky) && !findTrack(t1->wlinkx, t1->wlinky)) sprintf(buff, "%s %d,%d %s %d,%d.\n", L("Track at"), t1->x, t1->y, L("not linked back to"), t->x, t->y); } else if(t->elinkx && t->elinky) { if(!(t1 = findTrack(t->elinkx, t->elinky))) sprintf(buff, "%s %d,%d %s %d,%d.\n", L("Track at"), t->x, t->y, L("linked to non-existant track at"), t->elinkx, t->elinky); else if(!findTrack(t1->elinkx, t1->elinky) && !findTrack(t1->wlinkx, t1->wlinky)) sprintf(buff, "%s %d,%d %s %d,%d.\n", L("Track at"), t1->x, t1->y, L("not linked back to"), t->x, t->y); } } if(t->type == SWITCH) { if(t->wlinkx && t->wlinky) { if(!(t1 = findSwitch(t->wlinkx, t->wlinky))) sprintf(buff, "%s %d,%d %s %d,%d.\n", L("Switch at"), t->x, t->y, L("linked to non-existant switch at"), t->wlinkx, t->wlinky); else if(t1->wlinkx != t->x || t1->wlinky != t->y) sprintf(buff, "%s %d,%d %s %d,%d.\n", L("Switch at"), t1->x, t1->y, L("not linked back to switch at"), t->x, t->y); } } if(buff[0]) { if(firsttime) layout_error(L("Checking for errors in layout...\n")); firsttime = 0; layout_error(buff); } } end_layout_error(); } void link_tracks(Track *t, Track *t1) { switch(t->type) { case TRACK: if(t1->type != TRACK) { error(L("Only like tracks can be linked.")); return; } if(t1->direction != W_E && t1->direction != TRK_N_S) { error(L("Only horizontal or vertical tracks can be linked automatically.\nTo link other track types, use the track properties dialog.")); return; } /* if(t->direction != t1->direction) { error("You can't link horizontal to vertical tracks."); return; } */ if(t->direction == TRK_N_S) { if(!findTrack(t->x, t->y + 1)) { t->elinkx = t1->x; t->elinky = t1->y; } else { t->wlinkx = t1->x; t->wlinky = t1->y; } if(!findTrack(t1->x , t1->y + 1)) { t1->elinkx = t->x; t1->elinky = t->y; } else { t1->wlinkx = t->x; t1->wlinky = t->y; } break; } if(!findTrack(t->x + 1, t->y) && !findSwitch(t->x + 1, t->y)) { t->elinkx = t1->x; t->elinky = t1->y; } else { t->wlinkx = t1->x; t->wlinky = t1->y; } if(!findTrack(t1->x - 1, t1->y) && !findSwitch(t1->x - 1, t1->y)) { t1->wlinkx = t->x; t1->wlinky = t->y; } else { t1->elinkx = t->x; t1->elinky = t->y; } break; case SWITCH: if(t1->type != SWITCH) { error(L("Only like tracks can be linked.")); return; } t->wlinkx = t1->x; t->wlinky = t1->y; t1->wlinkx = t->x; t1->wlinky = t->y; break; case TSIGNAL: if(t1->type != TRACK) { error(L("Signals can only be linked to a track.")); return; } t->wlinkx = t1->x; t->wlinky = t1->y; t->controls = findTrack(t1->x, t1->y); break; case TRIGGER: if(t1->type != TRACK) { error(L("Triggers can only be linked to a track.")); return; } t->wlinkx = t1->x; t->wlinky = t1->y; t->controls = findTrack(t1->x, t1->y); break; case TEXT: if(t1->type != TRACK) { error(L("Entry/Exit points can only be linked to a track.")); return; } if(t1->x < t->x) { t->wlinkx = t1->x; t->wlinky = t1->y; } else { t->elinkx = t1->x; t->elinky = t1->y; } break; } } void auto_link_track(Track *t) { int x, y; Track *t1; x = t->x; y = t->y; switch(t->direction) { case W_E: ++y; break; case E_W: --y; break; case N_S: --x; break; case S_N: ++x; break; } t1 = findTrack(x, y); if(t1 && t1->type == TRACK && (t1->direction == W_E || t1->direction == TRK_N_S)) link_tracks(t, t1); } int macro_select(void) { Track *t; char buff[256]; if(!macros) { maxmacros = 1; macros = (Track **)calloc(sizeof(Track *), maxmacros); } buff[0] = 0; if(!openFileDialog(buff)) return 0; remove_ext(buff); if(!(t = load_field(buff))) return 0; if(current_macro_name) free(current_macro_name); current_macro_name = strdup(buff); clean_field(t); /* if(macros[0]) clean_field(macros[0]); macros[0] = t; current_macro = 0; nmacros = 1; maxmacros = 1; */ return 1; } void macro_place(int xbase, int ybase) { Track *mp; Track *t, *t1; int x, y; int oldtool; if(!current_macro_name) return; oldtool = current_tool; mp = load_field_tracks(current_macro_name); while(mp) { t1 = mp->next; x = mp->x + xbase; y = mp->y + ybase; if((t = findTrack(x, y)) || (t = findSwitch(x, y)) || (t = findSignal(x, y)) || (t = findText(x, y)) || (t = findPlatform(x, y)) || (t = findImage(x, y))) { track_delete(t); } mp->x = x; mp->y = y; if(mp->elinkx && mp->elinky) { mp->elinkx += xbase; mp->elinky += ybase; } if(mp->wlinkx && mp->wlinky) { mp->wlinkx += xbase; mp->wlinky += ybase; } mp->next = layout; layout = mp; link_all_tracks(); mp = t1; } invalidate_field(); repaint_all(); current_tool = oldtool; } void track_place(int x, int y) { Track *t, *t1; int needall; if(current_tool >= 0 && tooltbl[current_tool].type == MACRO) { if(!current_macro_name || tooltbl[current_tool].direction == 0) { select_tool(current_tool - 1); return; } macro_place(x, y); return; } if(current_tool >= 0 && tooltbl[current_tool].type == LINK) { if(tooltbl[current_tool].direction == 0) { if(!findTrack(x, y) && !findSignal(x, y) && !findSwitch(x, y) && !findText(x, y) && !findTrackType(x, y, TRIGGER)) return; /* there must be a track */ link_startx = x; link_starty = y; select_tool(current_tool + 1); return; } if(link_startx == -1) { select_tool(current_tool - 1); return; } if(!(t = findTrack(link_startx, link_starty)) && !(t = findSwitch(link_startx, link_starty)) && !(t = findSignal(link_startx, link_starty)) && !(t = findText(link_startx, link_starty)) && !(t = findTrackType(link_startx, link_starty, TRIGGER))) { return; } if(!(t1 = findTrack(x, y)) && !(t1 = findSignal(x, y)) && !(t1 = findSwitch(x, y)) && !(t1 = findText(x, y))) { return; } if(t->type == TRIGGER && t1->type != TRACK) return; link_startx = -1; link_starty = -1; link_tracks(t, t1); select_tool(current_tool - 1); return; } needall = 0; if((t = findTrack(x, y)) || (t = findSwitch(x, y)) || (t = findSignal(x, y)) || (t = findText(x, y)) || (t = findPlatform(x, y)) || (t = findImage(x, y)) || (t = findTrackType(x, y, ITIN)) || (t = findTrackType(x, y, TRIGGER))) { needall = 1; track_delete(t); link_all_tracks(); } if(current_tool == 0) { /* delete element */ repaint_all(); return; } t = track_new(); t->x = x; t->y = y; t->type = tooltbl[current_tool].type; t->direction = tooltbl[current_tool].direction; t->next = layout; if(t->type == TEXT) t->station = strdup("Abc"); else if(t->type == IMAGE) t->direction = 0; else if(t->type == TSIGNAL) { if(t->direction & 2) { t->fleeted = 1; t->direction &= ~2; } else t->fleeted = 0; if(auto_link) auto_link_track(t); } else if(t->type == TRIGGER && auto_link) auto_link_track(t); layout = t; link_all_tracks(); if(needall || is_windows) repaint_all(); else track_paint(t); } void track_properties(int x, int y) { Track *t; char buff[256]; if((t = findImage(x, y))) { buff[0] = 0; if(t->station) strcpy(buff, t->station); if(!openImageDialog(buff)) return; remove_ext(buff); strcat(buff, ".xpm"); if(t->station) free(t->station); t->pixels = 0; t->station = strdup(buff); repaint_all(); return; } if((t = findSignal(x,y)) && signal_properties_dialog) { signal_properties_dialog(t); return; } if((t = findTrackType(x, y, TRIGGER)) && trigger_properties_dialog) { trigger_properties_dialog(t); return; } if((t = findTrack(x, y)) || (t = findText(x, y)) || (t = findSignal(x, y)) || /* (t = findImage(x, y)) || */ (t = findTrackType(x, y, ITIN)) || (t = findTrackType(x, y, TRIGGER))) { track_properties_dialog(t); /* This uses the native Windows dialog -> track_properties_dialog(t);*/ } }