Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Komag
Roku Guru

Bug? Unreliable "tab" in text strings

I'm trying to get a reliable Tab in my text strings, but I often (not always) get an "n" instead of a Tab on the screen. In the two screens below, I changed NOTHING, I simply reloaded the channel. There is no rhyme nor reason!





I've tried actual Tabs in my text (by pressing Tab on my keyboard), and I've tried the tab character via adding Chr(9) to the string. Both ways give the same results - sometimes works, sometimes gives an "n", and I've even seen it once give a "(" in place of every Tab instead of the usual "n".

It's driving me crazy. I need to way to absolutely guarantee this will not happen. One way is to simply forego the tabs, but the paragraphs look so much better with them. There has to be a way.

Recent testing is with Roku 3 4200X, v7.0, build 9021
0 Kudos
14 REPLIES 14
TheEndless
Channel Surfer

Re: Bug? Unreliable "tab" in text strings

Is there a reason you can't just use spaces to indent the first line of each paragraph? Seems like that would be an easy and reliable solution.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
Komag
Roku Guru

Re: Bug? Unreliable "tab" in text strings

That was the first thing I tried - they are just ignored. Am I doing it wrong? I tried actual spaces, I tried building the string starting with Chr(32) + Chr(32) + Chr(32), nothing worked. If you have used spaces and it works I would love to do that.
0 Kudos
TheEndless
Channel Surfer

Re: Bug? Unreliable "tab" in text strings

"Komag" wrote:
That was the first thing I tried - they are just ignored. Am I doing it wrong? I tried actual spaces, I tried building the string starting with Chr(32) + Chr(32) + Chr(32), nothing worked. If you have used spaces and it works I would love to do that.

Interesting. I've noticed that several screens also seem to trim off ellipses (...) as well, which is extremely frustrating. Have you tried a non-breaking space? Chr(160)
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
Komag
Roku Guru

Re: Bug? Unreliable "tab" in text strings

YES, that does the trick! No more random "n"! Thank you!

How did you find that code#? I looked up ascii tables, but I guess that must be wrong.
0 Kudos
TheEndless
Channel Surfer

Re: Bug? Unreliable "tab" in text strings

I did a Bing ( :oops: err... Google? ) search for "Non-breaking space character code".   is a pretty standard web character that allows for adding a space without affecting the wrapping of a line. Thought it might work for your purposes. Glad it did!
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
EnTerr
Roku Guru

Re: Bug? Unreliable "tab" in text strings

"Komag" wrote:
I'm trying to get a reliable Tab in my text strings, but I often (not always) get an "n" instead of a Tab on the screen. In the two screens below, I changed NOTHING, I simply reloaded the channel. There is no rhyme nor reason!
...
Recent testing is with Roku 3 4200X, v7.0, build 9021

This is not a helpful bug report.
What exactly were you testing? Which component or function used to output text? No clue.
It seems as if someone is stripping whitespace at string ends (akin to ifStringOps.trim() but not quite) - and wrongly at that, give the phantom "n".
Can you show a 5-10 line code example that can reproduce the issue?
0 Kudos
Komag
Roku Guru

Re: Bug? Unreliable "tab" in text strings

My text system is a little complicated, I wasn't exactly trying to submit a good bug report, but rather to see if anyone had experienced anything like this (based on symptoms) or if anyone had ideas. Luckily, the non-breaking space worked like a charm.

I suppose there are two issues:

1. Leading spaces are always trimmed
2. Tab character is not always handled correctly (whether actual Tab or Chr(9)
This second case has some more details:
I tried Chr(11) VT vertical tab, Chr(12) FF form feed, and a couple others that I can't remember. Interestingly, they all behaved like Tabs, they made a few spaces. And they all SOMETIMES were replaced with "n"s. I could exit my channel and restart it 10 times, and get 8 times correct indentations and 2 times the "n"s, it was totally inconsistent and unreliable.

Here is the Function I was working on:
FUNCTION longTexts(title AS STRING) AS STRING ' trig by initBook(1) ' Chr(0) null, Chr(9) Tab, Chr(10) LF, Chr(13) CR, Chr(32) sp, Chr(34) dbl quotes, Chr(11) VT, Chr(12) FF, Chr(160) nbsp
' TB = "" + Chr(9)
TB = Chr(9)
' TB = "" + Chr(32) + Chr(32) + Chr(32) ' This doesn't work, no spaces or "tab" appears
' TB = "" + Chr(0) + Chr(32) + Chr(32) + Chr(32) + "" ' This doesn't work either
' PH = "" + Chr(10) + Chr(10) + Chr(9)
' PH = Chr(10) + Chr(10) + Chr(11) + Chr(32) + Chr(32) + Chr(32) + Chr(0) ' Vertical Tab works! But just as prone to "n" bug ' BUT, this retained the spaces after...
' PH = Chr(10) + Chr(10) + Chr(11) ' Just a regular Tab size, prone to "n" bug
' PH = "" + Chr(10) + Chr(10) + Chr(32) + Chr(32) + Chr(32)
' PH = "" + Chr(10) + Chr(10) + Chr(0) + Chr(32) + Chr(32) + Chr(32) + ""
' PH = Chr(10) + Chr(10) + Chr(12) + Chr(32) + Chr(32) + Chr(32) + Chr(12) ' Form Feed works, interesting... ' Nope, Form Feed seems prone to "n" bug too
' but at least between the "n"s are the spaces, maybe there is some other blank character I can stick spaces inbetween
' PH = Chr(10) + Chr(10) + Chr(12) ' Nope, Form Feed seems prone to "n" bug too
PH = Chr(10) + Chr(10) + Chr(160) + Chr(32) + Chr(32) + Chr(32) + Chr(160) ' Wow, Chr(160) nbsp works, thanks to TheEndless
' PH = Chr(10) + Chr(10) + " " + Chr(32) + Chr(32) + Chr(32) + Chr(0)

texts = {
intro: TB + "This is the story of Elendia's Esteem, the highest grace and favor ever bestowed upon a human, only granted once in all the ages known to the recorders." + PH + "In the Kingdom of Evermore, many gods and goddesses compete to influence the lives of the people, to gain their loyalty and worship, and to guide the events of the heavens in their own favor. Elendia is one such diety, a member of the Prime Synod, the ancient council of the gods formed by common consent of those oldest of beings, long ago in a time of chaos and disorder." + PH + "With her rivals Thanor, Kyrindia, and Loxus, Elendia agreed to divide the world into four kingdoms, and she named her domain Evermore, after the longing in her heart to lead the people toward eternal growth and divine progression, never to end, becoming greater evermore." + PH + "In time, peace and order coalesced upon the world, to the satifaction of the Prime Synod, and it was into this order that the Untried emerged. They are the lesser gods, unversed and untested, powerful but limited. They never knew a world of chaos, and their followers come and go. The Untried dain to compete with their elder deities, and cause their mischief as they can." + PH + "The oldest manuscripts of the recorders, copies of copies, tell us the tale of prince Albrecht. He was the youngest son of the king, and unlauded, so he desired to prove his valor." + PH + "In search of a task he might accomplish, he sought out the wisdom of oracles of his day, whom we would now call sages, but from the record it appears they harbored a stronger connection to the heavens than that." + PH + "Albrecht was instructed not to perform some great feat of strength or dexterity, but rather was told to lift others, to become a guidestone in the lives of the many, to better the position of the common man." + PH + "Time passed, and Albrecht pondered how he might fulfill the quest. This feat was like no other he had heard of, yet it rang true in his heart." + PH + "One day, while fasting and meditating atop the highest tower of the kingdom, the Skyward Hand (remnants of its foundation are still visible to this day in Hightowne), he beheld in vision the people of the kingdom. He saw them taking up arms against a dark and shadowy foe, layered in ranks upon the hillsides below them, his people formed all about the top." + PH + "From the earliest shades of dawn to the faintest light of dusk, his people cast down the devils from the hill top, again and again. An endless onslaught, repelled, returning, repelled again." + PH + "As he watched the fighters clash, he saw that the black shapes of the enemy seemed to match the outlines of their brighter counterparts. Indeed, upon close inspection, he believed it was in fact true that each man fought an exact copy of himself, only without light or visage." + PH + "In an instant Albrecht knew the meaning, that each man fought against his baser half, his low instincts, the parts of him that would drag him down and see him mired in self-indulgence. Leaning forward in his trance, he focused his mind forward to the end of the battle. He saw his people begin to prevail, their light shining forth ever more brightly, their dark foes diminishing day by day through the struggle." + PH + "Then, an unexpected thing occurred. Where each shadow fell, a tree sprung up. In his vision, time passed in a strange manner - the trees grew praeternaturally fast, while the men and devils fought impossibly slow. It was such that limbs of men and trees moved at the same speed; struggle matched growth." + PH + "Albrecht witnessed many individuals felling some of the trees and carving out new weapons and shields from the wood. They built homes and lives from it. The whole foundation of their society began to grow by it, and as this occurred, fewer and fewer dark shapes emerged from the valleys below." + PH + "After eons of fighting, living, conquering, his people prevailed. Darkness retreated, leaving a shining city on a hill in its wake. Tall forests of strong trees covered the land, teeming with life and sustenance, while men labored and took joy in their work. Women and children crafted and played and loved, and all were whole and happy." + PH + "The vision faded away, and the young prince Albrecht felt his own form wavering. He was weak and drained, and could not stand. Servants bore him to his room, where he was attended for three days while he regained his strength."

}
RETURN texts[title]
END FUNCTION

After that the big string goes to get split up in to many small lines and positioned on the page according as they fit, divided into multiple pages that can be flipped with right/left. It's my in-game book system.

longTexts() is called by initBook()
FUNCTION initBook(bk) ' trig by interactCheck(1), noted by objctInfo(1) "book", trig ind by useItem(1)
'? "initBook() running"
m.cAA.mainMenu.Lv = -1 ' Turn off main menus ' This would happen if reading a bk fom inven
title = textDatabase(bk.dscr, 1) ' Get the book's title from the text database
text = longTexts(title) ' Get the actual book long-text
dbook = m.drAA.book
dbook.book = TRUE
w = 7*64 + 16
lines = splitBlockText(text, w, m.drAA.font)
pages = []
WHILE lines.Count() > 11 ' Take out first 11 lines and put them into a "page"
page = []
IF lines[ 0] = "" THEN lines.Shift() ' Take out any blank line at the top ' This could possibly reduce lines.Count to exactly 11 (if it was 12)
FOR i = 1 TO 11
page.Push(lines.Shift())
END FOR
pages.Push(page)
END WHILE
IF lines.Count() > 0 THEN pages.Push(lines) ' At this point there should be <= 11 lines left for the last page, and there could be 0 if a blank line was removed from previous page top
dbook.pages = pages
dbook.pg = 0
dbook.pgs = pages.Count() -1
setBookPages()
initBookSprites(dbook)
'SOUND ' play "open book" sound
dbook.theBook = bk ' Store bk so exitBook() can check for any .linkTo deact
IF bk.linkTo <> INVALID THEN doLink("on", bk, y, x, rm) ' If book has a linkTo, do it ' Send trig as "on" (act)
END FUNCTION


And here is splitBlockText() that RokuMarkn gave to me (I've never fully understood it - maybe this is stripping out leading spaces?)


FUNCTION splitBlockText(text AS STRING, width AS INTEGER, font AS OBJECT) AS OBJECT ' trig by prepText(1), drawConvo(1), initBook(1) ' From RokuMarkn, updated to handle New Lines w/ Chr(10)
' Ascii 10 is New Line or Line Feed. Enter into strings like: "Hello."+Chr(10)+"Goodbye." ' Don't use "/n" because both / and n are delims, so all n's cause split!
'timer = createObject("roTimespan") ' For measuring performance
splitTextLines = []
linePos = 0
WHILE TRUE
WHILE text.Mid(linePos, 1) = " " ' Mid(start_index as Integer, num_chars as Integer) as String. Ex: s.Mid(0, 1) returns the first letter of s, while s.Mid(2, 2) returns the 3rd and 4th letters
linePos = linePos +1
END WHILE
endLine = linePos ' Set endLine to the current position, and test it below
' Output line starts here; step thru words.
WHILE TRUE
IF endLine >= text.Len() THEN
IF endLine > linePos THEN splitTextLines.Push(text.Mid(linePos, endLine - linePos))
'? "SplitBlockText() took " timer.totalMilliseconds()
RETURN splitTextLines
END IF
newline = (text.Mid(endLine, 1) = Chr(10)) ' If the second two parts are equivalent, newline will be TRUE
IF NOT newline THEN e = endWord(text, endLine)
IF newline OR font.GetOneLineWidth(text.Mid(linePos, e - linePos), width) >= width THEN
splitTextLines.Push(text.Mid(linePos, endLine - linePos))
linePos = endLine
IF newline THEN linePos = linePos +1
EXIT WHILE
END IF
endLine = e
END WHILE
END WHILE
END FUNCTION

FUNCTION endWord(text AS STRING, index AS INTEGER) AS INTEGER 'trig by SplitBlockText(1), from RokuMarkn on the dev forums
FOR p = index TO text.Len()
IF text.Mid(p, 1) <> " " THEN EXIT FOR
END FOR
FOR p = p TO text.Len()
IF text.Mid(p, 1) = " " OR text.Mid(p, 1) = Chr(10) THEN EXIT FOR ' Handling for New Lines
END FOR
RETURN p
END FUNCTION
0 Kudos
Komag
Roku Guru

Re: Bug? Unreliable "tab" in text strings

After trying again to understand how splitBlockText() is working, I think it is indeed the culprit for stripping leading spaces (which is usually a good thing for what it does). So that's one mystery solved (I think). :oops:

But the Tabs and other characters SOMETIMES making a tab indentation and SOMETIMES putting in an "n" is still a baffling mystery, especially the one time I saw "(" for them all instead of "n"s, it just seems buggy. :?

But for me, the issue is resolved, so thanks again. 😄
0 Kudos
EnTerr
Roku Guru

Re: Bug? Unreliable "tab" in text strings

"Komag" wrote:
...
And here is splitBlockText() that RokuMarkn gave to me (I've never fully understood it - maybe this is stripping out leading spaces?)

Yes, it is stripping out the leading spaces, this part:
      WHILE text.Mid(linePos, 1) = " "     
linePos = linePos +1
END WHILE

It's not necessary - you can comment it out - but to compensate, then change a few lines below "IF newline THEN linePos = linePos +1" to be just "linePos = linePos + 1". i.e. always advance the position, since at this time linePos is at either new line or space, courtesy of endLine() call in previous iteration. And no need for &nbsp; \t \f hocus-pocus

Ugh, now after staring at splitBlockText() for a while i know what you mean by "i never fully understood it" - it's not an easy piece. Actually i just spotted a bug in the code... i think. Namely, if there is a word in the text that is too long* to fit a line of given width, then the code will spin in a loop, filling splitTextLines with empty strings, until runs out of memory or the world ends... whichever comes first.


Regarding the mysterious "n"-fication - i suspect somewhere there is a left-over code from your experiments with viewtopic.php?f=34&t=84213#p481933
If i were troubleshooting this, first step when this happens during a run would be to check if the 1st char in the splitTextLines is indeed "n" or a tab - by either interrupting the program (ctrl-C) and checking variables - or hot-wiring when one of the remote keys is pressed to dump the array to console. That way could judge if the issues is in Draw2D text routines or in the B/S program

(*) e.g. try Pneumonoultramicroscopicsilicovolcanoconiosis or Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
0 Kudos
Need Assistance?
Welcome to the Roku Community! Feel free to search our Community for answers or post your question to get help.

Become a Roku Streaming Expert!

Share your expertise, help fellow streamers, and unlock exclusive rewards as part of the Roku Community. Learn more.