How would I do this? I can't seem to get text to wrap to the next line in the miniwindows.
MiniWindow text wrapping?
Posted by Thorndraco on Mon 05 Jan 2009 02:34 AM — 11 posts, 45,003 views.
function string.wrap(str, limit, indent, indent1)
indent = indent or ""
indent1 = indent1 or indent
limit = limit or 72
local here = 1-#indent1
return indent1..str:gsub("(%s+)()(%S+)()",
function(sp, st, word, fi)
if fi-here > limit then
here = st - #indent
return "\n"..indent..word
end
end)
end
local i = 0
for _,v in ipairs(utils.split(TEXTTOPRINT:wrap(30, " ", ""), "\n")) do
WindowText(win,font, v, 0, i * fontheight, width, (i+1) * fontheight, color, false)
i=i+1
end
TEXTTOPRINT, fontheight, width, and color need to be specified in your other code, so this isn't just cut'n'paste.
But it doesn't happen automatically.
[string "Trigger: "]:19: unfinished string near '"'
In mine line 19 is this one:
return "\n"..indent..word
In mine line 19 is this one:
return "\n"..indent..word
all the quotes are balanced. Everything copy correctly?
try changing the "\n" to string.char(13)
Is this in a trigger's Send field or in your main script?
try changing the "\n" to string.char(13)
Is this in a trigger's Send field or in your main script?
If you are doing send-to-script I think the \n becomes a linefeed, which is why you are getting the error. Willfa probably showed something from a script file, which doesn't have this problem.
As for the wrapping, text is not automatically wrapped, as Willfa said, this is a feature, not a bug. ;)
The general technique to do this would be:
You would need to allow for words that are too wide to fit anyway, so if the x-position was already the left margin, output the word anyway.
As for the wrapping, text is not automatically wrapped, as Willfa said, this is a feature, not a bug. ;)
The general technique to do this would be:
- Break the text into words delimited by spaces (eg. using string.gmatch)
- For each word:
- See if the x-position (horizontal) plus the width of the next word (see WindowTextWidth) will fit into the number of pixels you want for the width
- If so, write the word to the current line, and update the x-position
- If not, start a new line (update the y-position) and set the x-position back to some low figure (eg. 0, 1, 5 or whatever margin you want)
You would need to allow for words that are too wide to fit anyway, so if the x-position was already the left margin, output the word anyway.
string.char(13) worked fine.
Yes this is a send-to-script trigger.
Here I'll explain what I'm hoping to do:
I want pages and whispers to print to a miniwindow. I want to append new messages like you can do with the notepad and possibly allow for scrolling to read previous messages (though having previous lines scroll up would be fine as well). I tried the notepad route and it's just way too annoying and isn't flexible enough.
I'm new to Lua, but willing to learn.
Yes this is a send-to-script trigger.
Here I'll explain what I'm hoping to do:
I want pages and whispers to print to a miniwindow. I want to append new messages like you can do with the notepad and possibly allow for scrolling to read previous messages (though having previous lines scroll up would be fine as well). I tried the notepad route and it's just way too annoying and isn't flexible enough.
I'm new to Lua, but willing to learn.
This is what I have so far, but it won't print anything to the window:
pages = "%0"
win = GetPluginID ()
WindowCreate (win, 0, 0, 700, 200, 12, 0, ColourNameToRGB("black"))
WindowShow (win, true)
WindowFont (win, "f2", "Tahoma", 12, false, true, false, false)
function string.wrap(str, limit, indent, indent1)
indent = indent or ""
indent1 = indent1 or indent
limit = limit or 72
local here = 1-#indent1
return indent1..str:gsub("(%s+)()(%S+)()",
function(sp, st, word, fi)
if fi-here > limit then
here = st - #indent
return string.char(13)..indent..word
end
end)
end
local i = 0
for _,v in ipairs(utils.split(pages:wrap(30, " ", ""), string.char(13))) do
WindowText(win,font, v, 0, i * 12, 700, (i+1) * 12, ColourNameToRGB("white"), false)
i=i+1
end
EDIT: Scratch that, forgot to change font to "f2"
What this does do though is the width doesn't seem to work correctly as it stops at about 200pixels instead of 700 and the fontheight has to be set to nearly double to keep lines from overlapping.
pages = "%0"
win = GetPluginID ()
WindowCreate (win, 0, 0, 700, 200, 12, 0, ColourNameToRGB("black"))
WindowShow (win, true)
WindowFont (win, "f2", "Tahoma", 12, false, true, false, false)
function string.wrap(str, limit, indent, indent1)
indent = indent or ""
indent1 = indent1 or indent
limit = limit or 72
local here = 1-#indent1
return indent1..str:gsub("(%s+)()(%S+)()",
function(sp, st, word, fi)
if fi-here > limit then
here = st - #indent
return string.char(13)..indent..word
end
end)
end
local i = 0
for _,v in ipairs(utils.split(pages:wrap(30, " ", ""), string.char(13))) do
WindowText(win,font, v, 0, i * 12, 700, (i+1) * 12, ColourNameToRGB("white"), false)
i=i+1
end
EDIT: Scratch that, forgot to change font to "f2"
What this does do though is the width doesn't seem to work correctly as it stops at about 200pixels instead of 700 and the fontheight has to be set to nearly double to keep lines from overlapping.
You can't do it like that as you are not calculating the width of the word in a variable-pitch font. You need to do along the lines of what I suggested. This works for me:
You can test that in an Immediate window. The code above breaks the text into words, and tries to fit each word on the line, starting a new line if necessary. It does not honour newlines (or multiple consecutive spaces).
For a newline (eg. a new chat line) simply start a new line as it does above, ie.
-- test text
pages = [[
I want pages and whispers to print to a miniwindow. I want to append new messages like you can do with the
notepad and possibly allow for scrolling to read previous messages (though having previous lines scroll up would
be fine as well). I tried the notepad route and it's just way too annoying and isn't flexible enough.
]]
-- window and font info
win = GetPluginID ()
local width = 700
local height = 200
local font = "f2"
-- make window
WindowCreate (win, 0, 0, width, height, 12, 0, ColourNameToRGB("darkslategray"))
-- show border so we can see what we are doing
WindowRectOp (win, 1, 1, 1, -1, -1, ColourNameToRGB("blue"))
-- set up our font
WindowFont (win, font, "Tahoma", 9, false, true, false, false)
-- how far in to draw
local left_margin = 5
local right_margin = 5
-- derive stuff from font
local space_width = WindowTextWidth (win, font, " ")
local line_height = WindowFontInfo (win, font, 1)
-- starting point
local x = left_margin
local y = line_height
-- do each word
for word in string.gmatch (pages, "%S+") do
local word_width = WindowTextWidth (win, font, word)
-- time to start a new line?
if (word_width + x) > (width - right_margin) and (x > left_margin) then
y = y + line_height
x = left_margin
end -- if
-- draw the text
WindowText (win, font, word, x, y, 0, 0, ColourNameToRGB("white"))
-- advance past the word and a single space
x = x + word_width + space_width
end -- for loop
WindowShow (win, true)
You can test that in an Immediate window. The code above breaks the text into words, and tries to fit each word on the line, starting a new line if necessary. It does not honour newlines (or multiple consecutive spaces).
For a newline (eg. a new chat line) simply start a new line as it does above, ie.
y = y + line_height
x = left_margin
Thank you this has been a tremendous help!
This is also helping me to understand Lua better as I'm pulling this apart and seeing why it works. So, thank you for that as well.
This is also helping me to understand Lua better as I'm pulling this apart and seeing why it works. So, thank you for that as well.
This is something I'd like to get working for myself, as well. I've taken the code here (more or less), put it into appropriate triggers, and gotten it all to work.
I'd like to retain style due to chats/tells/says being different colors (and configurable through the mud, something I do change on occasion), though I could arbitrarily set those details within the script in each trigger. Also, I use a fixed width font religiously and so I can code with that assumption in mind.
The biggie is keeping prior chats stored away so that every time the chat window gets updated, I'm not simply starting the window from scratch with just the one trigger's text. That is, I'd like to tack on each incoming trigger text to the bottom and then find a way to 'scroll' the text as it comes.
What I came up with was padding each incoming text so that it filled an appropriate multiple of my miniwindow's width in letters. Then I concatenate in certain control words so my script would know what color to print them, as well as hint at where newlines should be added. All of this would be stored in a MUSH variable, which I'd reference each script call. Take the prior block of text, append the newly triggered text and padding, chop off the beginning text that won't fit, paint the miniwindow.
Sound about right, or is there a better way I'm overlooking?
I'd like to retain style due to chats/tells/says being different colors (and configurable through the mud, something I do change on occasion), though I could arbitrarily set those details within the script in each trigger. Also, I use a fixed width font religiously and so I can code with that assumption in mind.
The biggie is keeping prior chats stored away so that every time the chat window gets updated, I'm not simply starting the window from scratch with just the one trigger's text. That is, I'd like to tack on each incoming trigger text to the bottom and then find a way to 'scroll' the text as it comes.
What I came up with was padding each incoming text so that it filled an appropriate multiple of my miniwindow's width in letters. Then I concatenate in certain control words so my script would know what color to print them, as well as hint at where newlines should be added. All of this would be stored in a MUSH variable, which I'd reference each script call. Take the prior block of text, append the newly triggered text and padding, chop off the beginning text that won't fit, paint the miniwindow.
Sound about right, or is there a better way I'm overlooking?
Please see the forum thread: http://gammon.com.au/forum/?id=9996.
In there I show how you can direct all output from the main window to a miniwindow, wrapping to the width of the window, including if you use a variable-pitch font.
By simply changing the trigger from matching on "*" to whatever your chat line looks like, you could redirect chats only.
The plugin retains text colour, wraps at whatever width you specify for it (at the nearest space), and keeps x lines of output, where x is a number you specify in the plugin.
Also, near the bottom of that post I suggest an amendment that will keep the background colour of each style as well.