Changeset - r26727:e2c8c42642ff
[Not reviewed]
master
0 1 0
Rubidium - 18 months ago 2023-01-06 17:16:28
rubidium@openttd.org
Fix: bad oddness checks

Modulo on a signed number returns negative values for negative values, so
i % 2 == 1 will only return true for positive odd numbers, whereas i % 2 != 0
returns true for both positive and negative odd numbers.
1 file changed with 4 insertions and 4 deletions:
0 comments (0 inline, 0 general)
src/timetable_gui.cpp
Show inline comments
 
@@ -289,55 +289,55 @@ struct TimetableWindow : Window {
 
					}
 
				}
 

	
 
				/* recompute new sel_index */
 
				this->sel_index = 2 * selected_order - (int)travel;
 
				/* travel time of first order needs special handling */
 
				if (this->sel_index == -1) this->sel_index = this->vehicle->GetNumOrders() * 2 - 1;
 
				break;
 
			}
 
		}
 
	}
 

	
 

	
 
	void OnPaint() override
 
	{
 
		const Vehicle *v = this->vehicle;
 
		int selected = this->sel_index;
 

	
 
		this->vscroll->SetCount(v->GetNumOrders() * 2);
 

	
 
		if (v->owner == _local_company) {
 
			bool disable = true;
 
			if (selected != -1) {
 
				const Order *order = v->GetOrder(((selected + 1) / 2) % v->GetNumOrders());
 
				if (selected % 2 == 1) {
 
				if (selected % 2 != 0) {
 
					disable = order != nullptr && (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT));
 
				} else {
 
					disable = order == nullptr || ((!order->IsType(OT_GOTO_STATION) || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) && !order->IsType(OT_CONDITIONAL));
 
				}
 
			}
 
			bool disable_speed = disable || selected % 2 != 1 || v->type == VEH_AIRCRAFT;
 
			bool disable_speed = disable || selected % 2 == 0 || v->type == VEH_AIRCRAFT;
 

	
 
			this->SetWidgetDisabledState(WID_VT_CHANGE_TIME, disable);
 
			this->SetWidgetDisabledState(WID_VT_CLEAR_TIME, disable);
 
			this->SetWidgetDisabledState(WID_VT_CHANGE_SPEED, disable_speed);
 
			this->SetWidgetDisabledState(WID_VT_CLEAR_SPEED, disable_speed);
 
			this->SetWidgetDisabledState(WID_VT_SHARED_ORDER_LIST, !v->IsOrderListShared());
 

	
 
			this->SetWidgetDisabledState(WID_VT_START_DATE, v->orders == nullptr);
 
			this->SetWidgetDisabledState(WID_VT_RESET_LATENESS, v->orders == nullptr);
 
			this->SetWidgetDisabledState(WID_VT_AUTOFILL, v->orders == nullptr);
 
		} else {
 
			this->DisableWidget(WID_VT_START_DATE);
 
			this->DisableWidget(WID_VT_CHANGE_TIME);
 
			this->DisableWidget(WID_VT_CLEAR_TIME);
 
			this->DisableWidget(WID_VT_CHANGE_SPEED);
 
			this->DisableWidget(WID_VT_CLEAR_SPEED);
 
			this->DisableWidget(WID_VT_RESET_LATENESS);
 
			this->DisableWidget(WID_VT_AUTOFILL);
 
			this->DisableWidget(WID_VT_SHARED_ORDER_LIST);
 
		}
 

	
 
		this->SetWidgetLoweredState(WID_VT_AUTOFILL, HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE));
 

	
 
		this->DrawWidgets();
 
@@ -484,87 +484,87 @@ struct TimetableWindow : Window {
 
				if (v->timetable_start != 0) {
 
					/* We are running towards the first station so we can start the
 
					 * timetable at the given time. */
 
					SetDParam(0, STR_JUST_DATE_TINY);
 
					SetDParam(1, v->timetable_start);
 
					DrawString(tr, STR_TIMETABLE_STATUS_START_AT);
 
				} else if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) {
 
					/* We aren't running on a timetable yet, so how can we be "on time"
 
					 * when we aren't even "on service"/"on duty"? */
 
					DrawString(tr, STR_TIMETABLE_STATUS_NOT_STARTED);
 
				} else if (v->lateness_counter == 0 || (!_settings_client.gui.timetable_in_ticks && v->lateness_counter / DAY_TICKS == 0)) {
 
					DrawString(tr, STR_TIMETABLE_STATUS_ON_TIME);
 
				} else {
 
					SetTimetableParams(0, 1, abs(v->lateness_counter));
 
					DrawString(tr, v->lateness_counter < 0 ? STR_TIMETABLE_STATUS_EARLY : STR_TIMETABLE_STATUS_LATE);
 
				}
 
				break;
 
			}
 
		}
 
	}
 

	
 
	static inline std::tuple<VehicleOrderID, ModifyTimetableFlags> PackTimetableArgs(const Vehicle *v, uint selected, bool speed)
 
	{
 
		uint order_number = (selected + 1) / 2;
 
		ModifyTimetableFlags mtf = (selected % 2 == 1) ? (speed ? MTF_TRAVEL_SPEED : MTF_TRAVEL_TIME) : MTF_WAIT_TIME;
 
		ModifyTimetableFlags mtf = (selected % 2 != 0) ? (speed ? MTF_TRAVEL_SPEED : MTF_TRAVEL_TIME) : MTF_WAIT_TIME;
 

	
 
		if (order_number >= v->GetNumOrders()) order_number = 0;
 

	
 
		return { order_number, mtf };
 
	}
 

	
 
	void OnClick(Point pt, int widget, int click_count) override
 
	{
 
		const Vehicle *v = this->vehicle;
 

	
 
		switch (widget) {
 
			case WID_VT_ORDER_VIEW: // Order view button
 
				ShowOrdersWindow(v);
 
				break;
 

	
 
			case WID_VT_TIMETABLE_PANEL: { // Main panel.
 
				int selected = GetOrderFromTimetableWndPt(pt.y, v);
 

	
 
				this->CloseChildWindows();
 
				this->sel_index = (selected == INVALID_ORDER || selected == this->sel_index) ? -1 : selected;
 
				break;
 
			}
 

	
 
			case WID_VT_START_DATE: // Change the date that the timetable starts.
 
				ShowSetDateWindow(this, v->index, _date, _cur_year, _cur_year + 15, ChangeTimetableStartCallback, reinterpret_cast<void *>(static_cast<uintptr_t>(v->orders->IsCompleteTimetable() && _ctrl_pressed)));
 
				break;
 

	
 
			case WID_VT_CHANGE_TIME: { // "Wait For" button.
 
				int selected = this->sel_index;
 
				VehicleOrderID real = (selected + 1) / 2;
 

	
 
				if (real >= v->GetNumOrders()) real = 0;
 

	
 
				const Order *order = v->GetOrder(real);
 
				StringID current = STR_EMPTY;
 

	
 
				if (order != nullptr) {
 
					uint time = (selected % 2 == 1) ? order->GetTravelTime() : order->GetWaitTime();
 
					uint time = (selected % 2 != 0) ? order->GetTravelTime() : order->GetWaitTime();
 
					if (!_settings_client.gui.timetable_in_ticks) time /= DAY_TICKS;
 

	
 
					if (time != 0) {
 
						SetDParam(0, time);
 
						current = STR_JUST_INT;
 
					}
 
				}
 

	
 
				this->query_is_speed_query = false;
 
				this->change_timetable_all = _ctrl_pressed && (order != nullptr);
 
				ShowQueryString(current, STR_TIMETABLE_CHANGE_TIME, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED);
 
				break;
 
			}
 

	
 
			case WID_VT_CHANGE_SPEED: { // Change max speed button.
 
				int selected = this->sel_index;
 
				VehicleOrderID real = (selected + 1) / 2;
 

	
 
				if (real >= v->GetNumOrders()) real = 0;
 

	
 
				StringID current = STR_EMPTY;
 
				const Order *order = v->GetOrder(real);
 
				if (order != nullptr) {
 
					if (order->GetMaxSpeed() != UINT16_MAX) {
0 comments (0 inline, 0 general)