Design tab: build constraint labels from UTF-8, not the C locale

Drawing a line or a rounded rectangle crashed the Linux AppImage: the
constraint list labels were formatted from narrow literals holding "—",
"·" and "°". wx converts a bare char* with the current locale, and the
AppImage's AppRun sets LC_ALL=C, so the conversion failed, the format
string came out NULL and wxString::Format dereferenced it
(wxFormatConverterBase<wchar_t>::Convert, from constraint_label via
rebuild_constraint_list). A build started under a UTF-8 locale never
showed it.

These literals, and the "…" of the interference report, now go through
wxString::FromUTF8, as the panel's other non-ASCII literals already do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK4VgguuCAk2hZLWgcjJb9
This commit is contained in:
Claude
2026-09-30 08:34:32 +00:00
parent ae1dc95756
commit f4cdeb1706
+9 -6
View File
@@ -5687,7 +5687,7 @@ void DesignPanel::on_check_interference()
list += (k ? ", " : "") + wxString::Format(_L("%s ↔ %s %.2f mm³"), body_name(sorted[k].body_a),
body_name(sorted[k].body_b), sorted[k].volume);
if (sorted.size() > shown)
list += ", …";
list += wxString::FromUTF8(", …");
set_status(StatusKind::Warning, wxString::Format(_L("%zu overlapping pairs: %s"), sorted.size(), list));
}
@@ -7966,14 +7966,17 @@ wxString DesignPanel::constraint_label(const SketchEntityConstraintDef& d) const
case SketchEntity::Type::BSpline: c = 'B'; break;
}
}
// Non-ASCII narrow literals go through FromUTF8: wx converts a bare char* with the
// current locale, and under LC_ALL=C (the AppImage sets it) "—"/"·"/"°" fail to convert —
// an empty string, or a NULL format string that crashes wxString::Format.
wxString s; s << wxUniChar(c) << ei; // avoid %c assert in Unicode build
if (r == SketchPointRole::P1) s += "·P1";
else if (r == SketchPointRole::Center) s += "·Ctr";
else if (r == SketchPointRole::P0) s += "·P0";
if (r == SketchPointRole::P1) s += wxString::FromUTF8("·P1");
else if (r == SketchPointRole::Center) s += wxString::FromUTF8("·Ctr");
else if (r == SketchPointRole::P0) s += wxString::FromUTF8("·P0");
return s;
};
auto two = [&](const wxString& name) {
return d.eb >= 0 ? wxString::Format("%s %s — %s", name, tag(d.ea, d.ra), tag(d.eb, d.rb))
return d.eb >= 0 ? wxString::Format(wxString::FromUTF8("%s %s — %s"), name, tag(d.ea, d.ra), tag(d.eb, d.rb))
: wxString::Format("%s %s", name, tag(d.ea, d.ra));
};
switch (d.type) {
@@ -7996,7 +7999,7 @@ wxString DesignPanel::constraint_label(const SketchEntityConstraintDef& d) const
tag(d.ea, d.ra), tag(d.eb, d.rb));
case T::SymmetricAboutX: return wxString::Format(_L("Symmetric about X axis %s — %s"),
tag(d.ea, d.ra), tag(d.eb, d.rb));
case T::Angle: return wxString::Format("%s = %s°", two(_L("Angle")), en_format(d.value * 180.0 / M_PI, 1));
case T::Angle: return wxString::Format(wxString::FromUTF8("%s = %s°"), two(_L("Angle")), en_format(d.value * 180.0 / M_PI, 1));
case T::Radius: return wxString::Format("%s %s = %s", _L("Radius"), tag(d.ea, d.ra), en_format(d.value));
case T::Diameter: return wxString::Format("%s %s = %s", _L("Diameter"), tag(d.ea, d.ra), en_format(d.value));
case T::PointOnLine: return two(_L("On line"));