diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -156,7 +156,7 @@ struct AIListWindow : public Window { { switch (widget) { case AIL_WIDGET_LIST: { // Select one of the AIs - int sel = (pt.y - this->GetWidget(AIL_WIDGET_LIST)->pos_y) / this->line_height + this->vscroll.GetPosition() - 1; + int sel = this->vscroll.GetScrolledRowFromWidget(pt.y, this, AIL_WIDGET_LIST, 0, this->line_height) - 1; if (sel < (int)this->ai_info_list->size()) { this->selected = sel; this->SetDirty(); @@ -597,7 +597,7 @@ struct AIConfigWindow : public Window { } case AIC_WIDGET_LIST: { // Select a slot - this->selected_slot = (CompanyID)((pt.y - this->GetWidget(widget)->pos_y) / this->line_height + this->vscroll.GetPosition()); + this->selected_slot = (CompanyID)this->vscroll.GetScrolledRowFromWidget(pt.y, this, widget, 0, this->line_height); this->InvalidateData(); if (click_count > 1 && this->selected_slot != INVALID_COMPANY) ShowAIListWindow((CompanyID)this->selected_slot); break; diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -443,25 +443,27 @@ public: case RVW_WIDGET_LEFT_MATRIX: case RVW_WIDGET_RIGHT_MATRIX: { - uint i = (pt.y - this->GetWidget(RVW_WIDGET_LEFT_MATRIX)->pos_y) / this->resize.step_height; - uint16 click_scroll_pos = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.GetPosition() : this->vscroll2.GetPosition(); - uint16 click_scroll_cap = widget == RVW_WIDGET_LEFT_MATRIX ? this->vscroll.GetCapacity() : this->vscroll2.GetCapacity(); - byte click_side = widget == RVW_WIDGET_LEFT_MATRIX ? 0 : 1; - size_t engine_count = this->engines[click_side].Length(); + uint i; + byte click_side; + if (widget == RVW_WIDGET_LEFT_MATRIX) { + i = this->vscroll.GetScrolledRowFromWidget(pt.y, this, RVW_WIDGET_LEFT_MATRIX); + click_side = 0; + } else { + i = this->vscroll2.GetScrolledRowFromWidget(pt.y, this, RVW_WIDGET_RIGHT_MATRIX); + click_side = 1; + } + size_t engine_count = this->engines[click_side].Length(); - if (i < click_scroll_cap) { - i += click_scroll_pos; - EngineID e = engine_count > i ? this->engines[click_side][i] : INVALID_ENGINE; - if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected - this->sel_engine[click_side] = e; - if (click_side == 0) { - this->engines[1].ForceRebuild(); - this->reset_sel_engine = true; - } - this->SetDirty(); - } + EngineID e = engine_count > i ? this->engines[click_side][i] : INVALID_ENGINE; + if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected + this->sel_engine[click_side] = e; + if (click_side == 0) { + this->engines[1].ForceRebuild(); + this->reset_sel_engine = true; + } + this->SetDirty(); break; - } + } } } diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -249,13 +249,10 @@ public: switch (widget) { default: break; case BBSW_BRIDGE_LIST: { - uint i = ((int)pt.y - this->GetWidget(BBSW_BRIDGE_LIST)->pos_y) / this->resize.step_height; - if (i < this->vscroll.GetCapacity()) { - i += this->vscroll.GetPosition(); - if (i < this->bridges->Length()) { - this->BuildBridge(i); - delete this; - } + uint i = this->vscroll.GetScrolledRowFromWidget(pt.y, this, BBSW_BRIDGE_LIST); + if (i < this->bridges->Length()) { + this->BuildBridge(i); + delete this; } } break; diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1055,7 +1055,7 @@ struct BuildVehicleWindow : Window { break; case BUILD_VEHICLE_WIDGET_LIST: { - uint i = (pt.y - this->GetWidget(BUILD_VEHICLE_WIDGET_LIST)->pos_y) / this->resize.step_height + this->vscroll.GetPosition(); + uint i = this->vscroll.GetScrolledRowFromWidget(pt.y, this, BUILD_VEHICLE_WIDGET_LIST); size_t num_items = this->eng_list.Length(); this->sel_engine = (i < num_items) ? this->eng_list[i] : INVALID_ENGINE; this->SetDirty(); diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -531,9 +531,8 @@ public: break; case SLWW_DRIVES_DIRECTORIES_LIST: { // Click the listbox - int y = (pt.y - this->GetWidget(SLWW_DRIVES_DIRECTORIES_LIST)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height; - - if (y < 0 || (y += this->vscroll.GetPosition()) >= this->vscroll.GetCount()) return; + int y = this->vscroll.GetScrolledRowFromWidget(pt.y, this, SLWW_DRIVES_DIRECTORIES_LIST, WD_FRAMERECT_TOP); + if (y == INT_MAX) return; const FiosItem *file = _fios_items.Get(y); diff --git a/src/group_gui.cpp b/src/group_gui.cpp --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -417,12 +417,7 @@ public: break; case GRP_WIDGET_LIST_GROUP: { // Matrix Group - uint16 id_g = (pt.y - this->GetWidget(GRP_WIDGET_LIST_GROUP)->pos_y) / (int)this->tiny_step_height; - - if (id_g >= this->vscroll2.GetCapacity()) return; - - id_g += this->vscroll2.GetPosition(); - + uint id_g = this->vscroll2.GetScrolledRowFromWidget(pt.y, this, GRP_WIDGET_LIST_GROUP, 0, this->tiny_step_height); if (id_g >= this->groups.Length()) return; this->group_sel = this->groups[id_g]->index; @@ -433,11 +428,7 @@ public: } case GRP_WIDGET_LIST_VEHICLE: { // Matrix Vehicle - uint32 id_v = (pt.y - this->GetWidget(GRP_WIDGET_LIST_VEHICLE)->pos_y) / (int)this->resize.step_height; - if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds - - id_v += this->vscroll.GetPosition(); - + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, GRP_WIDGET_LIST_VEHICLE); if (id_v >= this->vehicles.Length()) return; // click out of list bound const Vehicle *v = this->vehicles[id_v]; @@ -511,17 +502,11 @@ public: break; case GRP_WIDGET_LIST_GROUP: { // Maxtrix group - uint16 id_g = (pt.y - this->GetWidget(GRP_WIDGET_LIST_GROUP)->pos_y) / (int)this->tiny_step_height; const VehicleID vindex = this->vehicle_sel; - this->vehicle_sel = INVALID_VEHICLE; - this->SetDirty(); - if (id_g >= this->vscroll2.GetCapacity()) return; - - id_g += this->vscroll2.GetPosition(); - + uint id_g = this->vscroll2.GetScrolledRowFromWidget(pt.y, this, GRP_WIDGET_LIST_GROUP, 0, this->tiny_step_height); if (id_g >= this->groups.Length()) return; DoCommandP(0, this->groups[id_g]->index, vindex, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_ADD_VEHICLE)); @@ -529,17 +514,11 @@ public: } case GRP_WIDGET_LIST_VEHICLE: { // Maxtrix vehicle - uint32 id_v = (pt.y - this->GetWidget(GRP_WIDGET_LIST_VEHICLE)->pos_y) / (int)this->resize.step_height; const VehicleID vindex = this->vehicle_sel; - this->vehicle_sel = INVALID_VEHICLE; - this->SetDirty(); - if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds - - id_v += this->vscroll.GetPosition(); - + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, GRP_WIDGET_LIST_VEHICLE); if (id_v >= this->vehicles.Length()) return; // click out of list bound const Vehicle *v = this->vehicles[id_v]; diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -459,9 +459,8 @@ public: switch (widget) { case DPIW_MATRIX_WIDGET: { const IndustrySpec *indsp; - int y = (pt.y - this->GetWidget(DPIW_MATRIX_WIDGET)->pos_y) / this->resize.step_height + this->vscroll.GetPosition(); - - if (y >= 0 && y < count) { // Is it within the boundaries of available data? + int y = this->vscroll.GetScrolledRowFromWidget(pt.y, this, DPIW_MATRIX_WIDGET); + if (y < this->count) { // Is it within the boundaries of available data? this->selected_index = y; this->selected_type = this->index[y]; indsp = (this->selected_type == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(this->selected_type); @@ -1194,11 +1193,7 @@ public: break; case IDW_INDUSTRY_LIST: { - int y = (pt.y - this->GetWidget(widget)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height; - uint16 p; - - if (!IsInsideMM(y, 0, this->vscroll.GetCapacity())) return; - p = y + this->vscroll.GetPosition(); + uint p = this->vscroll.GetScrolledRowFromWidget(pt.y, this, IDW_INDUSTRY_LIST, WD_FRAMERECT_TOP); if (p < this->industries.Length()) { if (_ctrl_pressed) { ShowExtraViewPortWindow(this->industries[p]->location.tile); diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -590,11 +590,7 @@ public: { switch (widget) { case NCLWW_MATRIX: { - uint32 id_v = (pt.y - this->GetWidget(NCLWW_MATRIX)->pos_y) / this->resize.step_height; - - if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds - id_v += this->vscroll.GetPosition(); - + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, NCLWW_MATRIX); if (id_v >= this->content.Length()) return; // click out of bounds this->selected = *this->content.Get(id_v); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -689,11 +689,7 @@ public: break; case NGWW_MATRIX: { // Matrix to show networkgames - uint32 id_v = (pt.y - this->GetWidget(NGWW_MATRIX)->pos_y) / this->resize.step_height; - - if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds - id_v += this->vscroll.GetPosition(); - + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, NGWW_MATRIX); this->server = (id_v < this->servers.Length()) ? this->servers[id_v] : NULL; this->list_pos = (server == NULL) ? SLP_INVALID : id_v; this->SetDirty(); @@ -1170,9 +1166,7 @@ struct NetworkStartServerWindow : public break; case NSSW_SELMAP: { // Select map - int y = (pt.y - this->GetWidget(NSSW_SELMAP)->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL; - - y += this->vscroll.GetPosition(); + int y = this->vscroll.GetScrolledRowFromWidget(pt.y, this, NSSW_SELMAP, WD_FRAMERECT_TOP, FONT_HEIGHT_NORMAL); if (y >= this->vscroll.GetCount()) return; this->map = (y == 0) ? NULL : _fios_items.Get(y - 1); @@ -1631,11 +1625,7 @@ struct NetworkLobbyWindow : public Windo break; case NLWW_MATRIX: { // Company list - uint32 id_v = (pt.y - this->GetWidget(NLWW_MATRIX)->pos_y) / this->resize.step_height; - - if (id_v >= this->vscroll.GetCapacity()) break; - - id_v += this->vscroll.GetPosition(); + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, NLWW_MATRIX); this->company = (id_v >= this->server->info.companies_on) ? INVALID_COMPANY : NetworkLobbyFindCompanyIndex(id_v); this->SetDirty(); diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -423,9 +423,8 @@ struct NewGRFInspectWindow : Window { if (nif->variables == NULL) return; /* Get the line, make sure it's within the boundaries. */ - int line = (pt.y - this->GetWidget(NIW_MAINPANEL)->pos_y - TOP_OFFSET) / this->resize.step_height; - if (line >= this->vscroll.GetCapacity()) return; - line += this->vscroll.GetPosition(); + int line = this->vscroll.GetScrolledRowFromWidget(pt.y, this, NIW_MAINPANEL, TOP_OFFSET); + if (line == INT_MAX) return; /* Find the variable related to the line */ for (const NIVariable *niv = nif->variables; niv->name != NULL; niv++, line--) { diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -482,8 +482,7 @@ struct NewGRFWindow : public QueryString } case SNGRFS_FILE_LIST: { // Select an active GRF. - NWidgetBase *nw = this->GetWidget(SNGRFS_FILE_LIST); - uint i = (pt.y - nw->pos_y) / nw->resize_y + this->vscroll.GetPosition(); + uint i = this->vscroll.GetScrolledRowFromWidget(pt.y, this, SNGRFS_FILE_LIST); GRFConfig *c; for (c = this->actives; c != NULL && i > 0; c = c->next, i--) {} @@ -526,8 +525,7 @@ struct NewGRFWindow : public QueryString } case SNGRFS_AVAIL_LIST: { // Select a non-active GRF. - NWidgetBase *nw = this->GetWidget(SNGRFS_AVAIL_LIST); - uint i = (pt.y - nw->pos_y) / nw->resize_y + this->vscroll2.GetPosition(); + uint i = this->vscroll2.GetScrolledRowFromWidget(pt.y, this, SNGRFS_AVAIL_LIST); this->active_sel = NULL; if (i < this->avails.Length()) { this->avail_sel = this->avails[i]; diff --git a/src/news_gui.cpp b/src/news_gui.cpp --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -1014,7 +1014,7 @@ struct MessageHistoryWindow : Window { NewsItem *ni = _latest_news; if (ni == NULL) return; - for (int n = (pt.y - this->GetWidget(MHW_BACKGROUND)->pos_y - WD_FRAMERECT_TOP) / this->line_height + this->vscroll.GetPosition(); n > 0; n--) { + for (int n = this->vscroll.GetScrolledRowFromWidget(pt.y, this, MHW_BACKGROUND, WD_FRAMERECT_TOP, this->line_height); n > 0; n--) { ni = ni->prev; if (ni == NULL) return; } diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -1327,10 +1327,7 @@ public: case BRSW_NEWST_LIST: { const StationSpec *statspec; - int y = (pt.y - this->GetWidget(BRSW_NEWST_LIST)->pos_y) / this->line_height; - - if (y >= this->vscroll.GetCapacity()) return; - y += this->vscroll.GetPosition(); + int y = this->vscroll.GetScrolledRowFromWidget(pt.y, this, BRSW_NEWST_LIST, 0, this->line_height); if (y >= _railstation.station_count) return; /* Check station availability callback */ diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1550,11 +1550,8 @@ struct GameSettingsWindow : Window { { if (widget != SETTINGSEL_OPTIONSPANEL) return; - int y = pt.y - this->GetWidget(widget)->pos_y - SETTINGTREE_TOP_OFFSET; // Shift y coordinate - if (y < 0) return; // Clicked above first entry - - byte btn = this->vscroll.GetPosition() + y / this->resize.step_height; // Compute which setting is selected - if (y % this->resize.step_height > this->resize.step_height - 2) return; // Clicked too low at the setting + uint btn = this->vscroll.GetScrolledRowFromWidget(pt.y, this, SETTINGSEL_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET - 1); + if (btn == INT_MAX) return; uint cur_row = 0; SettingEntry *pe = _settings_main_page.FindEntry(btn, &cur_row); diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -148,11 +148,8 @@ struct SignListWindow : Window, SignList virtual void OnClick(Point pt, int widget, int click_count) { if (widget == SLW_LIST) { - uint id_v = (pt.y - this->GetWidget(SLW_LIST)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height; - - if (id_v >= this->vscroll.GetCapacity()) return; - id_v += this->vscroll.GetPosition(); - if (id_v >= this->vscroll.GetCount()) return; + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, SLW_LIST, WD_FRAMERECT_TOP); + if (id_v == INT_MAX) return; const Sign *si = this->signs[id_v]; ScrollMainWindowToTile(TileVirtXY(si->x, si->y)); diff --git a/src/station_gui.cpp b/src/station_gui.cpp --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -535,12 +535,7 @@ public: { switch (widget) { case SLW_LIST: { - uint32 id_v = (pt.y - this->GetWidget(SLW_LIST)->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL; - - if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds - - id_v += this->vscroll.GetPosition(); - + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, SLW_LIST, 0, FONT_HEIGHT_NORMAL); if (id_v >= this->stations.Length()) return; // click out of list bound const Station *st = this->stations[id_v]; @@ -1152,7 +1147,7 @@ struct StationViewWindow : public Window { switch (widget) { case SVW_WAITING: - this->HandleCargoWaitingClick((pt.y - this->GetWidget(SVW_WAITING)->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL + this->vscroll.GetPosition()); + this->HandleCargoWaitingClick(this->vscroll.GetScrolledRowFromWidget(pt.y, this, SVW_WAITING, WD_FRAMERECT_TOP, FONT_HEIGHT_NORMAL)); break; case SVW_LOCATION: @@ -1416,7 +1411,7 @@ struct SelectStationWindow : Window { { if (widget != JSW_PANEL) return; - uint32 st_index = (pt.y - this->GetWidget(JSW_PANEL)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height + this->vscroll.GetPosition(); + uint st_index = this->vscroll.GetScrolledRowFromWidget(pt.y, this, JSW_PANEL, WD_FRAMERECT_TOP); bool distant_join = (st_index > 0); if (distant_join) st_index--; diff --git a/src/subsidy_gui.cpp b/src/subsidy_gui.cpp --- a/src/subsidy_gui.cpp +++ b/src/subsidy_gui.cpp @@ -41,11 +41,7 @@ struct SubsidyListWindow : Window { { if (widget != SLW_PANEL) return; - int y = (pt.y - this->GetWidget(SLW_PANEL)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height; - if (!IsInsideMM(y, 0, this->vscroll.GetCapacity())) return; - - y += this->vscroll.GetPosition(); - + int y = this->vscroll.GetScrolledRowFromWidget(pt.y, this, SLW_PANEL, WD_FRAMERECT_TOP); int num = 0; const Subsidy *s; FOR_ALL_SUBSIDIES(s) { diff --git a/src/town_gui.cpp b/src/town_gui.cpp --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -873,12 +873,7 @@ public: break; case TDW_CENTERTOWN: { // Click on Town Matrix - uint16 id_v = (pt.y - this->GetWidget(widget)->pos_y - WD_FRAMERECT_TOP) / this->resize.step_height; - - if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds - - id_v += this->vscroll.GetPosition(); - + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, TDW_CENTERTOWN, WD_FRAMERECT_TOP); if (id_v >= this->towns.Length()) return; // click out of town bounds const Town *t = this->towns[id_v]; diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -528,11 +528,8 @@ struct RefitWindow : public Window { { switch (widget) { case VRW_MATRIX: { // listbox - int y = pt.y - this->GetWidget(VRW_MATRIX)->pos_y; - if (y >= 0) { - this->sel = (y / (int)this->resize.step_height) + this->vscroll.GetPosition(); - this->InvalidateData(1); - } + this->sel = this->vscroll.GetScrolledRowFromWidget(pt.y, this, VRW_MATRIX); + this->InvalidateData(1); if (click_count == 1) break; } @@ -1213,13 +1210,8 @@ public: return; case VLW_WIDGET_LIST: { // Matrix to show vehicles - uint32 id_v = (pt.y - this->GetWidget(VLW_WIDGET_LIST)->pos_y) / this->resize.step_height; const Vehicle *v; - - if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds - - id_v += this->vscroll.GetPosition(); - + uint id_v = this->vscroll.GetScrolledRowFromWidget(pt.y, this, VLW_WIDGET_LIST); if (id_v >= this->vehicles.Length()) return; // click out of list bound v = this->vehicles[id_v];