/* dialog.c * * Functions to handle the following dialogs * using the Windows native GUI: * Track properties * Day selection * Performance report * Preferences * Assign rolling stock * Train properties * Station schedule * Itinerary definition */ #include #include #include #include #include "trsim.h" #include "resource.h" #include "trsimres.h" extern void CenterDialog(HWND hDlg); extern HINSTANCE ghInstance; extern char *station_schedule_cur; static char dlen[256]; static char dspeed[256]; static char dname[256]; static char dkm[256]; static char dlinkeast[256]; static char dlinkwest[256]; static Track *win_trk; static int item_list[] = { IDC_STATIC1, IDC_STATIC2, IDC_STATIC3, IDC_STATIC4, IDC_STATIC5, IDC_STATIC6, IDC_STATIC7, IDC_STATIC8, IDC_STATIC9, IDC_STATIC10, IDC_STATIC11, IDC_STATIC12, 0 }; static void localize_window(HWND hWnd) { char buffer[256]; char *p; GetWindowText(hWnd, buffer, sizeof(buffer)); p = L(buffer); if(p != buffer) SetWindowText(hWnd, p); } static void localize_texts(HWND hDlg) { HWND hItem; int i; localize_window(hDlg); for(i = 0; item_list[i]; ++i) { hItem = GetDlgItem(hDlg, item_list[i]); localize_window(hItem); } } LRESULT CALLBACK TrackDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { if(msg == WM_COMMAND) { if(wParam == IDOK) { GetDlgItemText(hDlg, IDC_EDIT1, dlen, 256); GetDlgItemText(hDlg, IDC_EDIT2, dname, 256); GetDlgItemText(hDlg, IDC_EDIT3, dspeed, 256); GetDlgItemText(hDlg, IDC_EDIT4, dlinkeast, 256); GetDlgItemText(hDlg, IDC_EDIT5, dlinkwest, 256); GetDlgItemText(hDlg, IDC_EDIT6, dkm, 256); set_track_properties(win_trk, dlen, dname, dspeed, dkm, dlinkwest, dlinkeast); EndDialog(hDlg, TRUE); return TRUE; } if(wParam == IDCANCEL) EndDialog(hDlg, FALSE); return TRUE; } if(msg == WM_INITDIALOG) { SetDlgItemText(hDlg, IDC_EDIT1, dlen); SetDlgItemText(hDlg, IDC_EDIT2, dname); SetDlgItemText(hDlg, IDC_EDIT3, dspeed); SetDlgItemText(hDlg, IDC_EDIT4, dlinkeast); SetDlgItemText(hDlg, IDC_EDIT5, dlinkwest); SetDlgItemText(hDlg, IDC_EDIT6, dkm); localize_texts(hDlg); SetFocus(GetDlgItem(hDlg, IDC_EDIT1)); CenterDialog(hDlg); return TRUE; } return FALSE; } LRESULT CALLBACK SigDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { char buff[30]; if(msg == WM_COMMAND) { if(wParam == IDOK) { GetDlgItemText(hDlg, IDC_EDIT1, dname, 256); GetDlgItemText(hDlg, IDC_EDIT2, dlinkeast, 256); GetDlgItemText(hDlg, IDC_EDIT3, dlinkwest, 256); win_trk->fixedred = (char)SendDlgItemMessage(hDlg, IDC_CHECK1, BM_GETCHECK, 0, 0); win_trk->nopenalty = (char)SendDlgItemMessage(hDlg, IDC_CHECK2, BM_GETCHECK, 0, 0); win_trk->signalx = (char)SendDlgItemMessage(hDlg, IDC_CHECK3, BM_GETCHECK, 0, 0); set_track_properties(win_trk, "", dname, "", "", dlinkwest, dlinkeast); EndDialog(hDlg, TRUE); return TRUE; } if(wParam == IDCANCEL) EndDialog(hDlg, FALSE); return TRUE; } if(msg == WM_INITDIALOG) { sprintf(buff, "%d, %d", win_trk->x, win_trk->y); SetDlgItemText(hDlg, IDC_SIGCOORD, buff); SetDlgItemText(hDlg, IDC_EDIT1, dname); SetDlgItemText(hDlg, IDC_EDIT2, dlinkeast); SetDlgItemText(hDlg, IDC_EDIT3, dlinkwest); SendDlgItemMessage(hDlg, IDC_CHECK1, BM_SETCHECK, win_trk->fixedred, 0); SendDlgItemMessage(hDlg, IDC_CHECK2, BM_SETCHECK, win_trk->nopenalty, 0); SendDlgItemMessage(hDlg, IDC_CHECK3, BM_SETCHECK, win_trk->signalx, 0); localize_texts(hDlg); localize_window(GetDlgItem(hDlg, IDC_CHECK1)); localize_window(GetDlgItem(hDlg, IDC_CHECK2)); localize_window(GetDlgItem(hDlg, IDC_CHECK3)); SetFocus(GetDlgItem(hDlg, IDC_EDIT1)); CenterDialog(hDlg); return TRUE; } return FALSE; } static char *trigger_cmds[] = { "click x,y", "fast", "slow", "shunt train", "reverse train", "traininfo train", "stationinfo train", "accelerate speed train", "decelerate speed train", NULL }; static void fillComboBox(HWND hList, char **items) { int i; SendMessage(hList, CB_RESETCONTENT, 0, (LPARAM)0); for(i = 0; items[i]; ++i) { SendMessage(hList, CB_ADDSTRING, 0, (LPARAM)items[i]); } } LRESULT CALLBACK TriggerDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { char buff[30]; HWND hList; int i; if(msg == WM_COMMAND) { if(LOWORD(wParam) == IDOK) { GetDlgItemText(hDlg, IDC_EDIT1, dname, 256); GetDlgItemText(hDlg, IDC_EDIT3, dlinkwest, 256); GetDlgItemText(hDlg, IDC_EDIT4, dspeed, 256); set_track_properties(win_trk, "", dname, dspeed, "", dlinkwest, ""); EndDialog(hDlg, TRUE); return TRUE; } if(LOWORD(wParam) == IDCANCEL) EndDialog(hDlg, FALSE); if(LOWORD(wParam) == IDC_COMBO1 && HIWORD(wParam) == CBN_SELCHANGE) { hList = GetDlgItem(hDlg, IDC_COMBO1); i = SendMessage(hList, CB_GETCURSEL, 0, (LPARAM)0); strcpy(buff, trigger_cmds[i]); for(i = 0; buff[i] && buff[i] != ' '; ++i); buff[i + 1] = 0; SetDlgItemText(hDlg, IDC_EDIT1, buff); SetFocus(GetDlgItem(hDlg, IDC_EDIT1)); SendDlgItemMessage(hDlg, IDC_EDIT1, EM_SETSEL, i + 1, i + 1); } return TRUE; } if(msg == WM_INITDIALOG) { sprintf(buff, "%d, %d", win_trk->x, win_trk->y); localize_texts(hDlg); SetDlgItemText(hDlg, IDC_SIGCOORD, buff); SetDlgItemText(hDlg, IDC_EDIT1, dname); SetDlgItemText(hDlg, IDC_EDIT3, dlinkwest); SetDlgItemText(hDlg, IDC_EDIT4, dspeed); hList = GetDlgItem(hDlg, IDC_COMBO1); localize_window(GetDlgItem(hDlg, IDC_COMBO1)); fillComboBox(hList, trigger_cmds); SetFocus(GetDlgItem(hDlg, IDC_EDIT1)); CenterDialog(hDlg); return TRUE; } return FALSE; } int win_track_properties_dialog(Track *t) { int s; win_trk = t; sprintf(dlen, "%ld", t->length); strcpy(dname, t->station ? t->station : ""); sprintf(dspeed, "%d/%d/%d/%d", t->speed[0], t->speed[1], t->speed[2], t->speed[3]); if(t->km) sprintf(dkm, "%d.%d", t->km / 1000, t->km % 1000); else dkm[0] = 0; sprintf(dlinkeast, "%d,%d", t->elinkx, t->elinky); sprintf(dlinkwest, "%d,%d", t->wlinkx, t->wlinky); if(t->type == TSIGNAL) s = DialogBox(ghInstance, MAKEINTRESOURCE(SIGNALPROP), 0, SigDlgProc); else if(t->type == TRIGGER) s = DialogBox(ghInstance, MAKEINTRESOURCE(TRIGGERPROP1), 0, TriggerDlgProc); else s = DialogBox(ghInstance, MAKEINTRESOURCE(TRACKPROP), 0, TrackDlgProc); if(s) { invalidate_field(); repaint_all(); pointer_at(t->x, t->y); /* update track info in labels */ } return 0; } static struct perftbl { int cntid, valid, totid; int *cntpt, *valpt; } perfdlgtbl[] = { { IDC_DESTCNT, IDC_DESTVAL, IDC_DESTTOT, &perf_tot.wrong_dest, &perf_vals.wrong_dest }, { IDC_LATECNT, IDC_LATEVAL, IDC_LATETOT, &perf_tot.late_trains, &perf_vals.late_trains }, { IDC_PLATFORMCNT, IDC_PLATFORMVAL, IDC_PLATFORMTOT, &perf_tot.wrong_platform, &perf_vals.wrong_platform }, { IDC_DENIEDCNT, IDC_DENIEDVAL, IDC_DENIEDTOT, &perf_tot.denied, &perf_vals.denied }, { IDC_WAITCNT, IDC_WAITVAL, IDC_WAITTOT, &perf_tot.waiting_train, &perf_vals.waiting_train }, { IDC_THROWNCNT, IDC_THROWNVAL, IDC_THROWNTOT, &perf_tot.thrown_switch, &perf_vals.thrown_switch }, { IDC_CLEAREDCNT, IDC_CLEAREDVAL, IDC_CLEAREDTOT, &perf_tot.cleared_signal, &perf_vals.cleared_signal }, { IDC_STOCKCNT, IDC_STOCKVAL, IDC_STOCKTOT, &perf_tot.wrong_assign, &perf_vals.wrong_assign }, { IDC_TURNEDCNT, IDC_TURNEDVAL, IDC_TURNEDTOT, &perf_tot.turned_train, &perf_vals.turned_train }, { 0 } }; LRESULT CALLBACK PerformanceDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { struct perftbl *p; char buff[256]; if(msg == WM_COMMAND) { if(wParam == IDOK) EndDialog(hDlg, FALSE); return TRUE; } if(msg == WM_INITDIALOG) { localize_texts(hDlg); for(p = perfdlgtbl; p->cntid; ++p) { sprintf(buff, "%d x", *p->cntpt); SetDlgItemText(hDlg, p->cntid, buff); sprintf(buff, "%d =", *p->valpt); SetDlgItemText(hDlg, p->valid, buff); sprintf(buff, "%d", *p->cntpt * *p->valpt); SetDlgItemText(hDlg, p->totid, buff); } CenterDialog(hDlg); return TRUE; } return FALSE; } void win_performance_dialog(void) { DialogBox(ghInstance, MAKEINTRESOURCE(PERFORMANCE), 0, PerformanceDlgProc); } static struct opttbl { int id; int *ptr; } optdlgtbl[] = { { IDC_FULLSTATUS, &terse_status }, { IDC_STATUSTOP, &status_on_top }, { IDC_SOUNDON, &beep_on_alert }, { IDC_ENTERSOUND, &beep_on_enter }, { IDC_VIEWSPEED, &show_speeds }, { IDC_AUTOLINK, &auto_link }, { IDC_SHOWGRID, &show_grid }, { IDC_VIEWBLOCKS, &show_blocks }, { IDC_SHOWSECS, &show_seconds }, { IDC_ITALIAN, &signal_traditional }, { IDC_HARD, &hard_counters }, { IDC_SHOWLINKS, &show_links }, { 0 }, }; LRESULT CALLBACK OptionsDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { struct opttbl *p; int i; if(msg == WM_COMMAND) { switch(wParam) { case IDOK: for(p = optdlgtbl; p->id; ++p) *p->ptr = SendDlgItemMessage(hDlg, p->id, BM_GETCHECK, 0, 0); case IDCANCEL: EndDialog(hDlg, FALSE); } return TRUE; } if(msg == WM_INITDIALOG) { localize_texts(hDlg); for(i = 0; optdlgtbl[i].id; ++i) localize_window(GetDlgItem(hDlg, optdlgtbl[i].id)); localize_window(GetDlgItem(hDlg, IDCANCEL)); for(p = optdlgtbl; p->id; ++p) SendDlgItemMessage(hDlg, p->id, BM_SETCHECK, *p->ptr ? 1 : 0, 0); CenterDialog(hDlg); return TRUE; } return FALSE; } void win_options_dialog(void) { DialogBox(ghInstance, MAKEINTRESOURCE(PREFERENCES), 0, OptionsDlgProc); } LRESULT CALLBACK SelectDayDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { if(msg == WM_COMMAND) { switch(wParam) { case IDOK: run_day = 0; if(IsDlgButtonChecked(hDlg, IDC_RADIO1)) run_day = 1; else if(IsDlgButtonChecked(hDlg, IDC_RADIO2)) run_day = 2; else if(IsDlgButtonChecked(hDlg, IDC_RADIO3)) run_day = 4; else if(IsDlgButtonChecked(hDlg, IDC_RADIO4)) run_day = 8; else if(IsDlgButtonChecked(hDlg, IDC_RADIO5)) run_day = 16; else if(IsDlgButtonChecked(hDlg, IDC_RADIO6)) run_day = 32; else if(IsDlgButtonChecked(hDlg, IDC_RADIO7)) run_day = 64; case IDCANCEL: EndDialog(hDlg, FALSE); return TRUE; case IDC_RADIO1: case IDC_RADIO2: case IDC_RADIO3: case IDC_RADIO4: case IDC_RADIO5: case IDC_RADIO6: case IDC_RADIO7: SendDlgItemMessage(hDlg, IDC_RADIO1, BM_SETCHECK, wParam == IDC_RADIO1, 0); SendDlgItemMessage(hDlg, IDC_RADIO2, BM_SETCHECK, wParam == IDC_RADIO2, 0); SendDlgItemMessage(hDlg, IDC_RADIO3, BM_SETCHECK, wParam == IDC_RADIO3, 0); SendDlgItemMessage(hDlg, IDC_RADIO4, BM_SETCHECK, wParam == IDC_RADIO4, 0); SendDlgItemMessage(hDlg, IDC_RADIO5, BM_SETCHECK, wParam == IDC_RADIO5, 0); SendDlgItemMessage(hDlg, IDC_RADIO6, BM_SETCHECK, wParam == IDC_RADIO6, 0); SendDlgItemMessage(hDlg, IDC_RADIO7, BM_SETCHECK, wParam == IDC_RADIO7, 0); } return TRUE; } if(msg == WM_INITDIALOG) { CenterDialog(hDlg); localize_texts(hDlg); localize_window(GetDlgItem(hDlg, IDC_RADIO1)); localize_window(GetDlgItem(hDlg, IDC_RADIO2)); localize_window(GetDlgItem(hDlg, IDC_RADIO3)); localize_window(GetDlgItem(hDlg, IDC_RADIO4)); localize_window(GetDlgItem(hDlg, IDC_RADIO5)); localize_window(GetDlgItem(hDlg, IDC_RADIO6)); localize_window(GetDlgItem(hDlg, IDC_RADIO7)); return TRUE; } return FALSE; } void win_select_day_dialog(void) { DialogBox(ghInstance, MAKEINTRESOURCE(SELECTDAY), 0, SelectDayDlgProc); } LV_ITEM lvi; struct wcol { char *text; short lr; short width; }; void add_lcolumn(HWND hList, int idx, char *txt, int width) { LV_COLUMN lvcolumn; memset(&lvcolumn, 0, sizeof(lvcolumn)); lvcolumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; lvcolumn.fmt = LVCFMT_LEFT; lvcolumn.cx = width; lvcolumn.pszText = txt; lvcolumn.iSubItem = idx + 1; SendMessage(hList, LVM_INSERTCOLUMN, idx, (LPARAM)&lvcolumn); } void add_rcolumn(HWND hList, int idx, char *txt, int width) { LV_COLUMN lvcolumn; memset(&lvcolumn, 0, sizeof(lvcolumn)); lvcolumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; lvcolumn.fmt = LVCFMT_RIGHT; lvcolumn.cx = width; lvcolumn.pszText = txt; lvcolumn.cchTextMax = 7; lvcolumn.iSubItem = idx + 1; SendMessage(hList, LVM_INSERTCOLUMN, idx, (LPARAM)&lvcolumn); } void add_all_columns(HWND hList, struct wcol *cp) { int i; for(i = 0; cp->text; ++i, ++cp) if(cp->lr == 'l') add_lcolumn(hList, i, cp->text, cp->width); else add_rcolumn(hList, i, cp->text, cp->width); } void set_row(HWND hList, int row, void *n) { /* Initialize LV_ITEM members that are common to all items. */ lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE; lvi.state = 0; lvi.stateMask = 0; lvi.pszText = LPSTR_TEXTCALLBACK; lvi.iImage = 0; lvi.iItem = row; lvi.iSubItem = 0; lvi.lParam = (LPARAM) n; ListView_InsertItem(hList, &lvi); } char *en_timetable[] = { "Station", "Arrival", "Departure", "Minimum stop (sec)", 0 }; struct wcol train_timetable[] = { { "Station", 'l', 120 }, { "Arrival", 'r', 60 }, { "Departure", 'r', 70 }, { "Minimum stop (sec)", 'r', 90 }, { 0 } }; int sort_stops; void format_node(char *dest, TrainStop *ts, int x) { dest[0] = 0; if(!ts) return; switch(x) { case 0: strcpy(dest, ts->station); break; case 1: strcpy(dest, format_time(ts->arrival)); break; case 2: strcpy(dest, format_time(ts->departure)); break; case 3: sprintf(dest, "%d", ts->minstop); break; } } int CALLBACK cmpTrainStops(LPARAM a, LPARAM b, LPARAM colmode) { TrainStop *pa = (TrainStop *)a, *pb = (TrainStop *)b; int res = 0; int col = colmode < 0 ? -colmode : colmode; switch(col) { case 1: res = strcmp(pa->station, pb->station); break; case 2: if(pa->arrival > pb->arrival) res = 1; if(pa->arrival < pb->arrival) res = -1; break; case 3: if(pa->departure > pb->departure) res = 1; if(pa->departure < pb->departure) res = -1; } return colmode < 0 ? -res : res; } void update_timetable(HWND hList, Train *tr, int sort_col) { int i; char *p; char buff[256]; TrainStop *ts; ListView_DeleteAllItems(hList); i = 0; for(ts = tr->stops; ts; ts = ts->next) ++i; ListView_SetItemCount(hList, i); i = 0; for(ts = tr->stops; ts; ts = ts->next) { strcpy(buff, ts->station); if((p = strchr(buff, '@'))) *p = 0; if(!findStationNamed(buff)) continue; set_row(hList, i++, ts); } } void update_list(HWND hList, NMHDR *hdr) { if(hdr->code == LVN_GETDISPINFO) { LV_DISPINFO *di = (LV_DISPINFO *)hdr; if(di->item.mask & LVIF_TEXT) { TrainStop *ts = (TrainStop *)di->item.lParam; if(ts) format_node(di->item.pszText, ts, di->item.iSubItem); } } else if(hdr->code == LVN_COLUMNCLICK) { NM_LISTVIEW *lvp = (NM_LISTVIEW *)hdr; if(lvp->iSubItem + 1 == sort_stops || -(lvp->iSubItem + 1) == sort_stops) sort_stops = -sort_stops; else sort_stops = -(lvp->iSubItem + 1); ListView_SortItems(hList, cmpTrainStops, (LPARAM)sort_stops); } } static Train *train_info_tr; LRESULT CALLBACK TrainInfoDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { Train *t; int i; char buff[256]; int len; char *notes; if(msg == WM_COMMAND) { switch(wParam) { case IDC_PRINT: train_print(train_info_tr); return TRUE; case IDOK: case IDCANCEL: EndDialog(hDlg, FALSE); return TRUE; } return TRUE; } if(msg == WM_NOTIFY) { NMHDR *hdr = (NMHDR *)lParam; if(wParam == IDC_TIMETABLE) update_list(GetDlgItem(hDlg, IDC_TIMETABLE), hdr); } if(msg == WM_INITDIALOG) { localize_texts(hDlg); CenterDialog(hDlg); for(i = 0; en_timetable[i]; ++i) train_timetable[i].text = L(en_timetable[i]); add_all_columns(GetDlgItem(hDlg, IDC_TIMETABLE), train_timetable); t = train_info_tr; update_timetable(GetDlgItem(hDlg, IDC_TIMETABLE), t, 0); SetDlgItemText(hDlg, IDC_TRAINNAME, t->name ? t->name : ""); sprintf(buff, "%d", t->type + 1); SetDlgItemText(hDlg, IDC_TRAINTYPE, buff); SetDlgItemText(hDlg, IDC_TIMEIN, format_time(t->timein)); SetDlgItemText(hDlg, IDC_TIMEOUT, format_time(t->timeout)); SetDlgItemText(hDlg, IDC_ENTRY, t->entrance ? t->entrance : ""); SetDlgItemText(hDlg, IDC_EXIT, t->exit ? t->exit : ""); SetDlgItemText(hDlg, IDC_WAITFOR, t->waitfor ? t->waitfor : ""); SetDlgItemText(hDlg, IDC_STOCK, t->stock ? t->stock : ""); buff[0] = 0; if(t->length) sprintf(buff, "%d", t->length); SetDlgItemText(hDlg, IDC_LENGTH, buff); buff[0] = 0; for(i = 0; i < 7; ++i) if(t->days & (1 << i)) sprintf(buff + strlen(buff), "%d", i+1); SetDlgItemText(hDlg, IDC_RUNSON, buff); len = 0; for(i = 0; i < t->nnotes; ++i) len += strlen(t->notes[i]) + 1; if(len) { notes = (char *)malloc(len); *notes = 0; for(i = 0; i < t->nnotes; ++i) { strcat(notes, t->notes[i]); strcat(notes, "\r\n"); } SetDlgItemText(hDlg, IDC_NOTES, notes); } else SetDlgItemText(hDlg, IDC_NOTES, ""); buff[0] = 0; if(t->length) sprintf(buff, "%d", t->length); SetDlgItemText(hDlg, IDC_LENGTH, buff); return TRUE; } return FALSE; } void win_train_info_dialog(Train *t) { train_info_tr = t; DialogBox(ghInstance, MAKEINTRESOURCE(TRAININFO), 0, TrainInfoDlgProc); } static Train **assign_list; static int nassign, maxassign; static Train *assign_tr; static int sort_assign; static char *en_assign[] = { "Train", "Departure", "Platform", "Destination", "Arrival", 0 }; static struct wcol assign_cols[] = { { "Train", 'l', 60 }, { "Departure", 'r', 60 }, { "Platform", 'r', 40 }, { "Destination", 'l', 120 }, { "Arrival", 'r', 60 }, { 0 } }; void format_assign(char *dest, Train *t, int x) { char *p; dest[0] = 0; if(!t) return; switch(x) { case 0: strcpy(dest, t->name); break; case 1: strcpy(dest, format_time(t->timein)); break; case 2: if((p = strchr(t->entrance, '@'))) strcpy(dest, p + 1); break; case 3: strcpy(dest, t->exit); break; case 4: sprintf(dest, format_time(t->timeout)); break; } } int CALLBACK cmpAssignTrains(LPARAM a, LPARAM b, LPARAM colmode) { Train *pa = (Train *)a, *pb = (Train *)b; int res = 0; int col = colmode < 0 ? -colmode : colmode; switch(col) { case 1: res = strcmp(pa->name, pb->name); break; case 2: if(pa->timein > pb->timein) res = 1; if(pa->timein < pb->timein) res = -1; break; case 3: res = strcmp(pa->exit, pb->exit); break; case 4: if(pa->timein > pb->timein) res = 1; if(pa->timein < pb->timein) res = -1; } return colmode < 0 ? -res : res; } void update_assignlist(HWND hList, NMHDR *hdr) { if(hdr->code == LVN_GETDISPINFO) { LV_DISPINFO *di = (LV_DISPINFO *)hdr; if(di->item.mask & LVIF_TEXT) { Train *t = (Train *)di->item.lParam; if(t) format_assign(di->item.pszText, t, di->item.iSubItem); } } else if(hdr->code == LVN_COLUMNCLICK) { NM_LISTVIEW *lvp = (NM_LISTVIEW *)hdr; if(lvp->iSubItem + 1 == sort_assign || -(lvp->iSubItem + 1) == sort_assign) sort_assign = -sort_assign; else sort_assign = (lvp->iSubItem + 1); ListView_SortItems(hList, cmpAssignTrains, (LPARAM)sort_assign); } } void setup_assignlist(HWND hList, char *station, int sort_col) { int i; ListView_DeleteAllItems(hList); ListView_SetItemCount(hList, nassign); for(i = 0; i < nassign; ++i) set_row(hList, i, assign_list[i]); } LRESULT CALLBACK AssignDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { Train *t; int i; if(msg == WM_COMMAND) { switch(wParam) { case IDC_SHUNT: shunt_train(assign_tr); EndDialog(hDlg, FALSE); break; case IDC_SPLIT: split_train(assign_tr); EndDialog(hDlg, FALSE); break; case IDC_PROPERTIES: i = ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_ASSIGNLIST)); if(i == -1) return FALSE; train_info_dialog(assign_list[i]); return TRUE; case IDOK: i = ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_ASSIGNLIST)); if(i == -1) return FALSE; assign_train(assign_list[i], assign_tr); case IDCANCEL: EndDialog(hDlg, FALSE); return TRUE; } return TRUE; } if(msg == WM_NOTIFY) { NMHDR *hdr = (NMHDR *)lParam; if(wParam == IDC_ASSIGNLIST) { if(hdr->code == NM_DBLCLK) { NM_LISTVIEW *lvp = (NM_LISTVIEW *)hdr; if(lvp->iItem < nassign) { assign_train(assign_list[lvp->iItem], assign_tr); EndDialog(hDlg, FALSE); return TRUE; } } else update_assignlist(GetDlgItem(hDlg, IDC_ASSIGNLIST), hdr); } } if(msg == WM_INITDIALOG) { char buff[256]; CenterDialog(hDlg); localize_texts(hDlg); for(i = 0; en_assign[i]; ++i) assign_cols[i].text = L(en_assign[i]); add_all_columns(GetDlgItem(hDlg, IDC_ASSIGNLIST), assign_cols); t = assign_tr; sprintf(buff, L("Assigning stock of train %s arrived at station %s"), t->name, t->exit); SetDlgItemText(hDlg, IDC_SOURCE, buff); setup_assignlist(GetDlgItem(hDlg, IDC_ASSIGNLIST), t->exit, 0); /* Try to automatically chose the train that will * receive the material. First we look for a train * specified in the arrived train. */ if(t->stock) { for(i = 0; i < nassign; ++i) if(!strcmp(t->stock, assign_list[i]->name)) goto set_default; return TRUE; } for(i = 0; i < nassign; ++i) if(!t->waitfor && !strcmp(assign_list[i]->exit, t->entrance)) goto set_default; return TRUE; set_default: SetFocus(GetDlgItem(hDlg, IDC_ASSIGNLIST)); ListView_SetSelectionMark(GetDlgItem(hDlg, IDC_ASSIGNLIST), i); ListView_SetItemState(GetDlgItem(hDlg, IDC_ASSIGNLIST), i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); ListView_EnsureVisible(GetDlgItem(hDlg, IDC_ASSIGNLIST), i, 1); return FALSE; /* tell the system to not change the focus! */ } return FALSE; } void win_assign_dialog(Train *t) { assign_tr = t; nassign = maxassign = 0; for(t = schedule; t; t = t->next) { if(t->status == train_READY && sameStation(t->entrance, assign_tr->exit) && (!t->days || (t->days & run_day))) { if(nassign >= maxassign) { maxassign += 20; if(!assign_list) assign_list = malloc(sizeof(Train *) * maxassign); else assign_list = realloc(assign_list, sizeof(Train *) * maxassign); } assign_list[nassign++] = t; } } DialogBox(ghInstance, MAKEINTRESOURCE(ASSIGNTO), 0, AssignDlgProc); if(assign_list) free(assign_list); assign_list = 0; } static char *en_schedule[] = { "Train", "Arrival", "From", "Departure", "To", "Plat.", "Runs on", "Notes", 0 }; static struct wcol station_sched[] = { { "Train", 'l', 60 }, { "Arrival", 'r', 60 }, { "From", 'l', 100 }, { "Departure", 'r', 60 }, { "To", 'l', 100 }, { "Plat.", 'r', 40 }, { "Runs on", 'l', 60 }, { "Notes", 'l', 200 }, { 0 } }; static Track **all_stations; static int station_idx; static int sort_station; void format_station_sched(char *dest, struct station_sched *sc, int x) { int i; char *p; dest[0] = 0; if(!sc) return; switch(x) { case 0: strcpy(dest, sc->tr->name); break; case 1: if(!sc->transit && sc->arrival != -1) strcpy(dest, format_time(sc->arrival)); break; case 2: if(sc->arrival != -1) strcpy(dest, sc->tr->entrance); break; case 3: if(sc->transit) sprintf(dest, "(%s)", format_time(sc->departure)); else if(sc->departure != -1) strcpy(dest, format_time(sc->departure)); break; case 4: if(sc->departure != -1) strcpy(dest, sc->tr->exit); break; case 5: if(sc->stopname && (p = strchr(sc->stopname, '@'))) strcpy(dest, p + 1); break; case 6: if(!sc->tr->days) break; for(i = 0; i < 7; ++i) if(sc->tr->days & (1 << i)) sprintf(dest + strlen(dest), "%d", i+1); break; case 7: if(sc->tr->nnotes) strcpy(dest, sc->tr->notes[0]); break; } } int CALLBACK cmpStationTrains(LPARAM a, LPARAM b, LPARAM colmode) { struct station_sched *pa = (struct station_sched *)a, *pb = (struct station_sched *)b; int res = 0; int col = colmode < 0 ? -colmode : colmode; long t1, t2; switch(col) { case 1: res = strcmp(pa->tr->name, pb->tr->name); break; case 2: if((t1 = pa->arrival) == -1) t1 = pa->departure; if((t2 = pb->arrival) == -1) t2 = pb->departure; if(t1 < t2) res = -1; else if(t1 > t2) res = 1; break; case 3: if(pa->arrival == -1) res = -1; else if(pb->arrival == -1) res = 1; else res = strcmp(pa->tr->entrance, pb->tr->entrance); break; case 4: if((t1 = pa->departure) == -1) t1 = pa->arrival; if((t2 = pb->departure) == -1) t2 = pb->arrival; if(t1 < t2) res = -1; else if(t1 > t2) res = 1; break; case 5: if(pa->departure == -1) res = -1; else if(pb->departure == -1) res = 1; else res = strcmp(pa->tr->exit, pb->tr->exit); } return colmode < 0 ? -res : res; } void add_all_stations(HWND hList) { int i; char buff[256]; char *p; SendMessage(hList, CB_RESETCONTENT, 0, 0); for(i = 0; all_stations[i]; ++i) { strcpy(buff, all_stations[i]->station); if(!platform_schedule) { if((p = strchr(buff, '@'))) *p = 0; } SendMessage(hList, CB_ADDSTRING, 0, (LPARAM)buff); } } void update_stationsched(HWND hList, NMHDR *hdr) { if(hdr->code == LVN_GETDISPINFO) { LV_DISPINFO *di = (LV_DISPINFO *)hdr; if(di->item.mask & LVIF_TEXT) { struct station_sched *sc = (struct station_sched *)di->item.lParam; if(sc) format_station_sched(di->item.pszText, sc, di->item.iSubItem); } } else if(hdr->code == LVN_COLUMNCLICK) { NM_LISTVIEW *lvp = (NM_LISTVIEW *)hdr; if(lvp->iSubItem + 1 == sort_station || -(lvp->iSubItem + 1) == sort_station) sort_station = -sort_station; else sort_station = -(lvp->iSubItem + 1); ListView_SortItems(hList, cmpStationTrains, (LPARAM)sort_station); } } void setup_stationsched(HWND hList, char *station, int sort_col) { int i; struct station_sched *sc; build_station_schedule(station); ListView_DeleteAllItems(hList); i = 0; for(sc = stat_sched; sc; sc = sc->next) ++i; ListView_SetItemCount(hList, i); i = 0; for(sc = stat_sched; sc; sc = sc->next) set_row(hList, i++, sc); } LRESULT CALLBACK StationSchedDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { int i; if(msg == WM_COMMAND) { switch(LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hDlg, FALSE); break; case IDC_PLATFORM: platform_schedule = SendDlgItemMessage(hDlg, IDC_PLATFORM, BM_GETCHECK, 0, 0) == 0; free(all_stations); all_stations = get_station_list(); add_all_stations(GetDlgItem(hDlg, IDC_STATIONLIST)); station_idx = 0; SendDlgItemMessage(hDlg, IDC_STATIONLIST, CB_SETCURSEL, 0, 0); setup_stationsched(GetDlgItem(hDlg, IDC_STATIONSCHED), all_stations[0]->station, 0); break; case IDC_PRINT: i = SendDlgItemMessage(hDlg, IDC_STATIONLIST, CB_GETCURSEL, 0, 0); station_schedule_cur = all_stations[i]->station; do_station_list_print(); break; case IDC_STATIONLIST: if(HIWORD(wParam) == CBN_SELENDOK) { i = SendDlgItemMessage(hDlg, IDC_STATIONLIST, CB_GETCURSEL, 0, 0); setup_stationsched(GetDlgItem(hDlg, IDC_STATIONSCHED), all_stations[i]->station, 0); } break; } return TRUE; } if(msg == WM_NOTIFY) { NMHDR *hdr = (NMHDR *)lParam; if(wParam == IDC_STATIONSCHED) update_stationsched(GetDlgItem(hDlg, IDC_STATIONSCHED), hdr); } if(msg == WM_INITDIALOG) { CenterDialog(hDlg); localize_texts(hDlg); for(i = 0; en_schedule[i]; ++i) station_sched[i].text = L(en_schedule[i]); add_all_columns(GetDlgItem(hDlg, IDC_STATIONSCHED), station_sched); add_all_stations(GetDlgItem(hDlg, IDC_STATIONLIST)); SendDlgItemMessage(hDlg, IDC_STATIONLIST, CB_SETCURSEL, station_idx, 0); setup_stationsched(GetDlgItem(hDlg, IDC_STATIONSCHED), all_stations[station_idx]->station, 0); SendDlgItemMessage(hDlg, IDC_PLATFORM, BM_SETCHECK, platform_schedule == 0, 0); localize_window(GetDlgItem(hDlg, IDC_PLATFORM)); return TRUE; } return FALSE; } void win_station_sched_dialog(char *station) { int i; all_stations = get_station_list(); if(!all_stations) { do_alert(L("No stations in this layout!")); return; } station_idx = 0; if(station) for(i = 0; all_stations[i]; ++i) if(sameStation(all_stations[i]->station, station)) { station_idx = i; break; } DialogBox(ghInstance, MAKEINTRESOURCE(STATIONSCHED), 0, StationSchedDlgProc); free(all_stations); } static Itinerary *win_it; LRESULT CALLBACK ItineraryDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { char buff[256]; char buff1[256]; if(msg == WM_COMMAND) { switch(wParam) { case IDOK: GetDlgItemText(hDlg, IDC_ITINNAME, buff, sizeof(buff)); GetDlgItemText(hDlg, IDC_ITINNEXT, buff1, sizeof(buff1)); if(!set_itin_name(win_it, buff, buff1)) return TRUE; case IDCANCEL: EndDialog(hDlg, FALSE); break; } return TRUE; } if(msg == WM_INITDIALOG) { CenterDialog(hDlg); localize_texts(hDlg); SetDlgItemText(hDlg, IDC_ITINNAME, win_it->name); SetDlgItemText(hDlg, IDC_ITINNEXT, win_it->nextitin); sprintf(buff, L("From signal '%s'"), win_it->signame); SetDlgItemText(hDlg, IDC_ITINFROM, buff); return TRUE; } return FALSE; } void win_itinerary_dialog(Itinerary *it) { win_it = it; DialogBox(ghInstance, MAKEINTRESOURCE(ITINERARY), 0, ItineraryDlgProc); } LRESULT CALLBACK AboutDlgProc(HWND hDlg, WPARAM msg, WPARAM wParam, LPARAM lParam) { if(msg == WM_COMMAND) { switch(LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hDlg, FALSE); break; } } if(msg == WM_INITDIALOG) { CenterDialog(hDlg); localize_texts(hDlg); return TRUE; } return FALSE; } void win_about_dialog(void) { DialogBox(ghInstance, MAKEINTRESOURCE(ABOUTBOX), 0, AboutDlgProc); } void init_win_dialogs(void) { track_properties_dialog = win_track_properties_dialog; performance_dialog = win_performance_dialog; options_dialog = win_options_dialog; select_day_dialog = win_select_day_dialog; train_info_dialog = win_train_info_dialog; assign_dialog = win_assign_dialog; station_sched_dialog = win_station_sched_dialog; itinerary_dialog = win_itinerary_dialog; about_dialog = win_about_dialog; }