@@ -11,6 +11,113 @@ extern graphics::Screen *screen;
1111
1212TraceRouteModule *traceRouteModule;
1313
14+ void TraceRouteModule::setResultText (const String &text)
15+ {
16+ resultText = text;
17+ resultLines.clear ();
18+ resultLinesDirty = true ;
19+ }
20+
21+ void TraceRouteModule::clearResultLines ()
22+ {
23+ resultLines.clear ();
24+ resultLinesDirty = false ;
25+ }
26+ #if HAS_SCREEN
27+ void TraceRouteModule::rebuildResultLines (OLEDDisplay *display)
28+ {
29+ if (!display) {
30+ resultLinesDirty = false ;
31+ return ;
32+ }
33+
34+ resultLines.clear ();
35+
36+ if (resultText.length () == 0 ) {
37+ resultLinesDirty = false ;
38+ return ;
39+ }
40+
41+ int maxWidth = display->getWidth () - 4 ;
42+ if (maxWidth <= 0 ) {
43+ resultLinesDirty = false ;
44+ return ;
45+ }
46+
47+ int start = 0 ;
48+ int textLength = resultText.length ();
49+
50+ while (start <= textLength) {
51+ int newlinePos = resultText.indexOf (' \n ' , start);
52+ String segment;
53+
54+ if (newlinePos != -1 ) {
55+ segment = resultText.substring (start, newlinePos);
56+ start = newlinePos + 1 ;
57+ } else {
58+ segment = resultText.substring (start);
59+ start = textLength + 1 ;
60+ }
61+
62+ if (segment.length () == 0 ) {
63+ resultLines.push_back (" " );
64+ continue ;
65+ }
66+
67+ if (display->getStringWidth (segment) <= maxWidth) {
68+ resultLines.push_back (segment);
69+ continue ;
70+ }
71+
72+ String remaining = segment;
73+
74+ while (remaining.length () > 0 ) {
75+ String tempLine = " " ;
76+ int lastGoodBreak = -1 ;
77+ bool lineComplete = false ;
78+
79+ for (int i = 0 ; i < static_cast <int >(remaining.length ()); i++) {
80+ char ch = remaining.charAt (i);
81+ String testLine = tempLine + ch;
82+
83+ if (display->getStringWidth (testLine) > maxWidth) {
84+ if (lastGoodBreak >= 0 ) {
85+ resultLines.push_back (remaining.substring (0 , lastGoodBreak + 1 ));
86+ remaining = remaining.substring (lastGoodBreak + 1 );
87+ lineComplete = true ;
88+ break ;
89+ } else if (tempLine.length () > 0 ) {
90+ resultLines.push_back (tempLine);
91+ remaining = remaining.substring (i);
92+ lineComplete = true ;
93+ break ;
94+ } else {
95+ resultLines.push_back (String (ch));
96+ remaining = remaining.substring (i + 1 );
97+ lineComplete = true ;
98+ break ;
99+ }
100+ } else {
101+ tempLine = testLine;
102+ if (ch == ' ' || ch == ' >' || ch == ' <' || ch == ' -' || ch == ' (' || ch == ' )' || ch == ' ,' ) {
103+ lastGoodBreak = i;
104+ }
105+ }
106+ }
107+
108+ if (!lineComplete) {
109+ if (tempLine.length () > 0 ) {
110+ resultLines.push_back (tempLine);
111+ }
112+ break ;
113+ }
114+ }
115+ }
116+
117+ resultLinesDirty = false ;
118+ }
119+ #endif
120+
14121bool TraceRouteModule::handleReceivedProtobuf (const meshtastic_MeshPacket &mp, meshtastic_RouteDiscovery *r)
15122{
16123 // We only alter the packet in alterReceivedProtobuf()
@@ -406,7 +513,7 @@ bool TraceRouteModule::startTraceRoute(NodeNum node)
406513 if (node == 0 || node == NODENUM_BROADCAST) {
407514 LOG_ERROR (" Invalid node number for trace route: 0x%08x" , node);
408515 runState = TRACEROUTE_STATE_RESULT;
409- resultText = " Invalid node" ;
516+ setResultText ( " Invalid node" ) ;
410517 resultShowTime = millis ();
411518 tracingNode = 0 ;
412519
@@ -420,7 +527,7 @@ bool TraceRouteModule::startTraceRoute(NodeNum node)
420527 if (node == nodeDB->getNodeNum ()) {
421528 LOG_ERROR (" Cannot trace route to self: 0x%08x" , node);
422529 runState = TRACEROUTE_STATE_RESULT;
423- resultText = " Cannot trace self" ;
530+ setResultText ( " Cannot trace self" ) ;
424531 resultShowTime = millis ();
425532 tracingNode = 0 ;
426533
@@ -447,6 +554,8 @@ bool TraceRouteModule::startTraceRoute(NodeNum node)
447554 unsigned long wait = (cooldownMs - (now - lastTraceRouteTime)) / 1000 ;
448555 bannerText = String (" Wait for " ) + String (wait) + String (" s" );
449556 runState = TRACEROUTE_STATE_COOLDOWN;
557+ resultText = " " ;
558+ clearResultLines ();
450559
451560 requestFocus ();
452561 UIFrameEvent e;
@@ -459,6 +568,8 @@ bool TraceRouteModule::startTraceRoute(NodeNum node)
459568 tracingNode = node;
460569 lastTraceRouteTime = now;
461570 runState = TRACEROUTE_STATE_TRACKING;
571+ resultText = " " ;
572+ clearResultLines ();
462573 bannerText = String (" Tracing " ) + getNodeName (node);
463574
464575 LOG_INFO (" TraceRoute UI: Starting trace route to node 0x%08x, requesting focus" , node);
@@ -501,7 +612,7 @@ bool TraceRouteModule::startTraceRoute(NodeNum node)
501612 } else {
502613 LOG_ERROR (" MeshService is NULL!" );
503614 runState = TRACEROUTE_STATE_RESULT;
504- resultText = " Service unavailable" ;
615+ setResultText ( " Service unavailable" ) ;
505616 resultShowTime = millis ();
506617 tracingNode = 0 ;
507618
@@ -514,7 +625,7 @@ bool TraceRouteModule::startTraceRoute(NodeNum node)
514625 } else {
515626 LOG_ERROR (" Failed to allocate TraceRoute packet from router" );
516627 runState = TRACEROUTE_STATE_RESULT;
517- resultText = " Failed to send" ;
628+ setResultText ( " Failed to send" ) ;
518629 resultShowTime = millis ();
519630 tracingNode = 0 ;
520631
@@ -532,7 +643,7 @@ void TraceRouteModule::launch(NodeNum node)
532643 if (node == 0 || node == NODENUM_BROADCAST) {
533644 LOG_ERROR (" Invalid node number for trace route: 0x%08x" , node);
534645 runState = TRACEROUTE_STATE_RESULT;
535- resultText = " Invalid node" ;
646+ setResultText ( " Invalid node" ) ;
536647 resultShowTime = millis ();
537648 tracingNode = 0 ;
538649
@@ -546,7 +657,7 @@ void TraceRouteModule::launch(NodeNum node)
546657 if (node == nodeDB->getNodeNum ()) {
547658 LOG_ERROR (" Cannot trace route to self: 0x%08x" , node);
548659 runState = TRACEROUTE_STATE_RESULT;
549- resultText = " Cannot trace self" ;
660+ setResultText ( " Cannot trace self" ) ;
550661 resultShowTime = millis ();
551662 tracingNode = 0 ;
552663
@@ -568,6 +679,8 @@ void TraceRouteModule::launch(NodeNum node)
568679 unsigned long wait = (cooldownMs - (now - lastTraceRouteTime)) / 1000 ;
569680 bannerText = String (" Wait for " ) + String (wait) + String (" s" );
570681 runState = TRACEROUTE_STATE_COOLDOWN;
682+ resultText = " " ;
683+ clearResultLines ();
571684
572685 requestFocus ();
573686 UIFrameEvent e;
@@ -580,6 +693,8 @@ void TraceRouteModule::launch(NodeNum node)
580693 runState = TRACEROUTE_STATE_TRACKING;
581694 tracingNode = node;
582695 lastTraceRouteTime = now;
696+ resultText = " " ;
697+ clearResultLines ();
583698 bannerText = String (" Tracing " ) + getNodeName (node);
584699
585700 requestFocus ();
@@ -614,22 +729,22 @@ void TraceRouteModule::launch(NodeNum node)
614729 } else {
615730 LOG_ERROR (" MeshService is NULL!" );
616731 runState = TRACEROUTE_STATE_RESULT;
617- resultText = " Service unavailable" ;
732+ setResultText ( " Service unavailable" ) ;
618733 resultShowTime = millis ();
619734 tracingNode = 0 ;
620735 }
621736 } else {
622737 LOG_ERROR (" Failed to allocate TraceRoute packet from router" );
623738 runState = TRACEROUTE_STATE_RESULT;
624- resultText = " Failed to send" ;
739+ setResultText ( " Failed to send" ) ;
625740 resultShowTime = millis ();
626741 tracingNode = 0 ;
627742 }
628743}
629744
630745void TraceRouteModule::handleTraceRouteResult (const String &result)
631746{
632- resultText = result;
747+ setResultText ( result) ;
633748 runState = TRACEROUTE_STATE_RESULT;
634749 resultShowTime = millis ();
635750 tracingNode = 0 ;
@@ -679,83 +794,15 @@ void TraceRouteModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state
679794 display->setFont (FONT_SMALL);
680795
681796 if (resultText.length () > 0 ) {
682- std::vector<String> lines;
683- String currentLine = " " ;
684- int maxWidth = display->getWidth () - 4 ;
685-
686- int start = 0 ;
687- int newlinePos = resultText.indexOf (' \n ' , start);
688-
689- while (newlinePos != -1 || start < static_cast <int >(resultText.length ())) {
690- String segment;
691- if (newlinePos != -1 ) {
692- segment = resultText.substring (start, newlinePos);
693- start = newlinePos + 1 ;
694- newlinePos = resultText.indexOf (' \n ' , start);
695- } else {
696- segment = resultText.substring (start);
697- start = resultText.length ();
698- }
699-
700- if (display->getStringWidth (segment) <= maxWidth) {
701- lines.push_back (segment);
702- } else {
703- // Try to break at better positions (space, >, <, -)
704- String remaining = segment;
705-
706- while (remaining.length () > 0 ) {
707- String tempLine = " " ;
708- int lastGoodBreak = -1 ;
709- bool lineComplete = false ;
710-
711- for (int i = 0 ; i < static_cast <int >(remaining.length ()); i++) {
712- char ch = remaining.charAt (i);
713- String testLine = tempLine + ch;
714-
715- if (display->getStringWidth (testLine) > maxWidth) {
716- if (lastGoodBreak >= 0 ) {
717- // Break at the last good position
718- lines.push_back (remaining.substring (0 , lastGoodBreak + 1 ));
719- remaining = remaining.substring (lastGoodBreak + 1 );
720- lineComplete = true ;
721- break ;
722- } else if (tempLine.length () > 0 ) {
723- lines.push_back (tempLine);
724- remaining = remaining.substring (i);
725- lineComplete = true ;
726- break ;
727- } else {
728- // Single character exceeds width
729- lines.push_back (String (ch));
730- remaining = remaining.substring (i + 1 );
731- lineComplete = true ;
732- break ;
733- }
734- } else {
735- tempLine = testLine;
736- // Mark good break positions
737- if (ch == ' ' || ch == ' >' || ch == ' <' || ch == ' -' || ch == ' (' || ch == ' )' ) {
738- lastGoodBreak = i;
739- }
740- }
741- }
742-
743- if (!lineComplete) {
744- // Reached end of remaining text
745- if (tempLine.length () > 0 ) {
746- lines.push_back (tempLine);
747- }
748- break ;
749- }
750- }
751- }
797+ if (resultLinesDirty) {
798+ rebuildResultLines (display);
752799 }
753800
754801 int lineHeight = FONT_HEIGHT_SMALL + 1 ; // Use proper font height with 1px spacing
755- for (size_t i = 0 ; i < lines .size (); i++) {
802+ for (size_t i = 0 ; i < resultLines .size (); i++) {
756803 int lineY = contentStartY + (i * lineHeight);
757804 if (lineY + FONT_HEIGHT_SMALL <= display->getHeight ()) {
758- display->drawString (x + 2 , lineY, lines [i]);
805+ display->drawString (x + 2 , lineY, resultLines [i]);
759806 }
760807 }
761808 }
@@ -779,7 +826,7 @@ int32_t TraceRouteModule::runOnce()
779826 if (runState == TRACEROUTE_STATE_TRACKING && now - lastTraceRouteTime > trackingTimeoutMs) {
780827 LOG_INFO (" TraceRoute timeout, no response received" );
781828 runState = TRACEROUTE_STATE_RESULT;
782- resultText = " No response received" ;
829+ setResultText ( " No response received" ) ;
783830 resultShowTime = now;
784831 tracingNode = 0 ;
785832
@@ -815,6 +862,8 @@ int32_t TraceRouteModule::runOnce()
815862 // Cooldown finished
816863 LOG_INFO (" TraceRoute cooldown finished, returning to IDLE" );
817864 runState = TRACEROUTE_STATE_IDLE;
865+ resultText = " " ;
866+ clearResultLines ();
818867 bannerText = " " ;
819868 UIFrameEvent e;
820869 e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
@@ -828,6 +877,7 @@ int32_t TraceRouteModule::runOnce()
828877 LOG_INFO (" TraceRoute result display timeout, returning to IDLE" );
829878 runState = TRACEROUTE_STATE_IDLE;
830879 resultText = " " ;
880+ clearResultLines ();
831881 bannerText = " " ;
832882 tracingNode = 0 ;
833883 UIFrameEvent e;
0 commit comments