Setting Miniwindows to Scroll?

Posted by Natasi on Tue 14 Apr 2009 02:45 AM — 28 posts, 115,810 views.

#0
Hi, I finally got a Channel Capture working, that grabs certain channels from the mud I play and displays them in a miniwindow. Right now I have it set so when it reaches 12 lines of text it resets and clears the window and starts over, but I would like to set it to instead scroll as more entries are input. Would anyone know how this can be achieved, to have a scrollbar on a miniwindow?

I can post code if needed, thanks for any help!
USA #1
I'm not sure about a scrollbar, but for the moment, as a stopgap measure, you could try this. Store each line in a table with table.insert(). When you reach 13 lines, table.remove() the oldest. It emulates a scrolling display, but it doesn't actually have a scrollbar.
Australia Forum Administrator #2
Exactly. I did something similar in a plugin that shows trace information in a scrolling window:

http://www.gammon.com.au/forum/?id=9218

The function that does the displaying does exactly what Twisol said, it removes from a table if you have exceeded the maximum lines, and then adds the new line to the back.

It also uses WindowRectOp to clear the window prior to drawing or you would have text everywhere.

The relevant lines are here:



-- display one line
function Display_Line (line, text)

  local left = TEXT_INSET
  local top = (line - 1) * font_height
  
  WindowText (win, "f", text, left, top, WINDOW_WIDTH - TEXT_INSET, 0, WINDOW_TEXT_COLOUR)
  
end -- Display_Line


-- here on trace
function OnPluginTrace (line)

  -- blank existing window contents
  WindowRectOp (win, 2, 0, 0, 0, 0, WINDOW_BACKGROUND_COLOUR)
  
  -- remove first line if filled up
  if #lines >= max_lines then
    table.remove (lines, 1)
  end -- if 

  -- add new line, time-stamped
  table.insert (lines, os.date ("%H:%M:%S ") .. line)
  
  -- display all lines
  for k, v in ipairs (lines) do
    Display_Line (k, v)
  end -- for
  
  -- force window redisplay
  WindowShow (win,  true)  -- show it 
  
end -- end OnPluginTrace


#3
Here comes my first, useful post!

I went ahead and wrote up a script that starts with a table of 15 strings, which represent the output from your MUD, and then it writes the first 10 of those lines to a white Miniwindow.

There are two invisible hotspots which are each 10 pixels x 100 pixels and on the far right side of the Miniwindow situated on top of each other. If you click the top one it'll scroll your text up (provided you're not on the first line) and down (provided you're not out of lines).

What you'll want to work on to suit your needs is changing out the table with MUD's output. I have no idea how many lines you can fit in that table without having any memory/speed issues, so you might want to use Twisol's suggestion and keep it around 100 lines or whatever.

Also! This works off of MouseUp, which means you have to remove your finger from the mouse. You can only get one scroll per click as a consequence. You can easily change:
function MouseUp(flags, hotspot_id)
	scrollbar(hotspot_id)
end

to not have anything in it, and move
scrollbar(hotspot_id)

to
the function MouseDown(). If you do that, you'll want to cancel the scrollbar stuff on CancelMouseDown or it'll keep going no matter where your mouse was after the click.

Here's what is between the script tags in the XML plugin:

text = {
	"1:  This is a line of text",
	"2:  This is a line of text",
	"3:  This is a line of text",
	"4:  This is a line of text",
	"5:  This is a line of text",
	"6:  This is a line of text",
	"7:  This is a line of text",
	"8:  This is a line of text",
	"9:  This is a line of text",
	"10: This is a line of text",
	"11: This is a line of text",
	"12: This is a line of text",
	"13: This is a line of text",
	"14: This is a line of text",
	"15: This is a line of text"
}

lineStart = 1
lineEnd = 10
SBWin = "ScrollbarWindow"..GetPluginID()

function OnPluginInstall()
	init()
end

function init()
	WindowCreate(SBWin, 2, 2, 200, 200, 4, 2, ColourNameToRGB("white"))
	WindowAddHotspot(SBWin, "upHotspot", 190, 0, 0, 100, "MouseOver", "CancelMouseOver", "MouseDown", "CancelMouseDown", "MouseUp", "Scroll up?", 1, 0)
	WindowAddHotspot(SBWin, "downHotspot", 190, 100, 0, 0, "MouseOver", "CancelMouseOver", "MouseDown", "CancelMouseDown", "MouseUp", "Scroll down?", 1, 0)
	WindowFont(SBWin, "font"..SBWin, "Trebuchet MS", 12, true, false, false, false)
	WindowShow(SBWin, true)
	writeLines()
end

function writeLines()
	spacing = 0
	for count = lineStart, lineEnd do
		WindowText(SBWin, "font"..SBWin, text[count], 5, spacing * 15, 0, 0, ColourNameToRGB("black"), false)
		spacing = spacing + 1
	end
end

function refresh()
	WindowRectOp(SBWin, 2, 0, 0, 0, 0, ColourNameToRGB("white"), ColourNameToRGB("white"))
	WindowShow(SBWin, true)

	writeLines()
end

function scrollbar(calledBy)
	if calledBy == "upHotspot" then
		if (lineStart > 1) then
			lineStart = lineStart - 1
			lineEnd = lineEnd - 1
		end
	elseif calledBy == "downHotspot" then
		if (lineEnd < #text) then
			lineStart = lineStart + 1
			lineEnd = lineEnd + 1
		end
	end
	refresh()
end

function MouseOver(flags, hotspot_id)
end

function CancelMouseOver(flags, hotspot_id)
end

function MouseDown(flags, hotspot_id)
end

function CancelMouseDown(flags, hotspot_id)
end

function MouseUp(flags, hotspot_id)
	scrollbar(hotspot_id)
end
#4
Sorry, I judged the mouse functions incorrectly. I'd recomment moving the scrollbar(hotspot_id) to MouseDown. It's an -on- MouseDown rather than a -while- MouseDown, so it still only moves the scrolling text one line.
#5
Ahh, thanks everyone, this should get me to where I need to be!
#6
Ok, going a bit insane trying to figure this out. I'm not a Lua person and this is the first thing I've done with it, building off multiple scripts Nick and others have posted up here.

Below I have posted the code, triggers and the script, and if anyone would be kind enough to explain how to integrate this into Tboydston's suggestion or even the Tables as Nick suggested I would greatly appreciate it.

Here goes:

<triggers>
<trigger
enabled="y"
keep_evaluating="y"
match="^\((.*?)\)\:\s(.*?)$"
script=""
send_to="14"
regexp="y"
>
<send>
world.Execute ("channelText (%1): %2")
</send>
</trigger>
</triggers>

<!-- Aliases -->


<aliases>
<alias
script="channelText"
match="channelText *"
enabled="y"
sequence="100"
>
</alias>

<alias
script="reset_window"
match="resetw"
enabled="y"
sequence="100"
>
</alias>
<alias
script="start_window"
match="startw"
enabled="y"
sequence="100"
>
</alias>
<alias
script="stop_window"
match="stopw"
enabled="y"
sequence="100"
>
</alias>
</aliases>

<!-- Script -->


<script>
<![CDATA[
-- test text

-- window and font info

win = GetPluginID ()
local width = 870
local height = 200
local font = "f2"

-- make window

WindowCreate (win, 0, 0, width, height, 4, 0, ColourNameToRGB("black"))

-- show border so we can see what we are doing

WindowRectOp (win, 1, 1, 1, -1, -1, ColourNameToRGB("#553333"))

-- set up our font

WindowFont (win, font, "Arial", 9)

-- 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 = 0


local counter = 0
-- do each word
function channelText (name, line, wildcards)

if counter > 11 then
WindowCreate (win, 0, 0, width, height, 4, 0, ColourNameToRGB("black"))
WindowRectOp (win, 1, 1, 1, -1, -1, ColourNameToRGB("#553333"))
y = 0
x = 0
WindowShow (win, true)
counter = 0
end

message = wildcards [1]
y = y + line_height
x = left_margin
counter = counter + 1
for word in string.gmatch (message, "%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
counter = counter + 1
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
end

WindowShow (win, true)

function reset_window (name, line, wildcards)
WindowCreate (win, 0, 0, width, height, 4, 0, ColourNameToRGB("black"))
WindowRectOp (win, 1, 1, 1, -1, -1, ColourNameToRGB("#553333"))
y = 0
x = 0
counter = 0
WindowShow (win, true)
end
function start_window (name, line, wildcards)
WindowShow (win, true)
end
function stop_window (name, line, wildcards)
WindowShow (win, false)
end

]]>
</script>
#7
This is in your channelText function:
-- draw the text
WindowText (win, font, word, x, y, 0, 0, ColourNameToRGB("white"))


You're instantly drawing the text after you receive it in the function that waits for text. Instead of drawing the text, insert it into a table.
table.insert(tableForYourMessages, lineToInsert)

Every time you add to the table go ahead and refresh your window.

You can do this with a separate function that will write all the visible lines of text by running through an appropriate point in the table of text. I made the variables lineStart and lineEnd to keep track of my location. You'll want to draw the background over the table (I just draw a white rectangle over the entire thing) before you write the text or all of your lines will get jumbled up.

I think you'd be able to copy+paste my code directly into your plugin and use it immediately. All you'd really need to add is a way to modify the table text (which I suggested earlier). It'd make more sense to write text = {} instead of how I did it for the example. Of course, if you do that you're going to want to change out the miniwindow information to suit your own needs.

Good luck!
#8
I was able to copy/paste yours in, but whenever it refreshed, it overwrote, but I wasn't able to get the tables to work correctly and thus it as just a blank miniwindow and nothing wrote to it anymore.
#9
Why don't you paste the full script now that you're trying to implement the scroll?

It sounds like you might be drawing the white rectangle at the wrong time, so it'd help to see where exactly things are going wrong.

Also, if you put the script inside a pair of [code][/code] tags it'll preserve indentation. Just click the "Check this if you want to use 'forum codes'" button.
Amended on Sun 30 Aug 2009 09:46 AM by Nick Gammon
#10
Erm, sorry, I tried typing the forum code tags without thinking they'd be evaulated. It's just code and /code inside of square brackets.
USA #11
[code] <code goes here> [\code].

Tboydston: Add a backslash before the brackets to make it appear literal. Also don't forget that there's an Edit button to the right of the date. ;)
#12
Here is the full plugin:


<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<!-- MuClient version 4.37 -->

<muclient>
<plugin
   name="ChannelText"
   author="Nick Gammon"
   id="4de91eaa2624f202c4bb6835"
   language="Lua"
   purpose="Shows message"
   date_written="2009-02-08 14:00"
   requires="4.37"
   version="1.0"
   >

</plugin>

<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="^\((.*?)\)\:\s(.*?)$"
   script=""
   send_to="14"
   regexp="y"
  >
  <send>
  	world.Execute ("channelText (%1): %2")
  </send>
  </trigger>
</triggers>

<!--  Aliases  -->


<aliases>
  <alias
   script="channelText"
   match="channelText *"
   enabled="y"
   sequence="100"
  >
  </alias>
  
  <alias
   script="reset_window"
   match="resetw"
   enabled="y"
   sequence="100"
  >
  </alias>
  <alias
   script="start_window"
   match="startw"
   enabled="y"
   sequence="100"
  >
  </alias>
   <alias
   script="stop_window"
   match="stopw"
   enabled="y"
   sequence="100"
  >
  </alias>
</aliases>

<!--  Script  -->


<script>
<![CDATA[
-- test text

-- window and font info

win = GetPluginID ()
local width = 870
local height = 200
local font = "f2"

-- make window

WindowCreate (win, 0, 0, width, height, 4, 0, ColourNameToRGB("black"))

-- show border so we can see what we are doing

WindowRectOp (win, 1, 1, 1, -1, -1, ColourNameToRGB("#553333")) 

-- set up our font

WindowFont (win, font, "Arial", 9)

-- 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 = 0


local counter = 0
-- do each word
function channelText (name, line, wildcards)

	if counter > 11 then
		WindowCreate (win, 0, 0, width, height, 4, 0, ColourNameToRGB("black"))
		WindowRectOp (win, 1, 1, 1, -1, -1, ColourNameToRGB("#553333")) 
		y = 0
		x = 0
		WindowShow (win, true)
		counter = 0
	end

  message = wildcards [1]
   y = y + line_height
   x = left_margin
   counter = counter + 1
for word in string.gmatch (message, "%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
    counter = counter + 1
  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
end

WindowShow (win, true)

function reset_window (name, line, wildcards)
	WindowCreate (win, 0, 0, width, height, 4, 0, ColourNameToRGB("black"))
	WindowRectOp (win, 1, 1, 1, -1, -1, ColourNameToRGB("#553333")) 
	y = 0
	x = 0
	counter = 0
	WindowShow (win, true)
end
function start_window (name, line, wildcards)
	WindowShow (win, true)
end
function stop_window (name, line, wildcards)
	WindowShow (win, false)
end

]]>
</script>

</muclient>

#13
Thanks for all the help, was finally able to piece it all together this morning!

Though, are you able to put multiple miniwindows into one plugin or should they all be seperate?
Netherlands #14
You can put multiple miniwindows in a single plugin. The names used to identify need to differ (and be unique for the entire world - e.g. if PluginA uses the miniwindow 'test', and PluginB uses the miniwindow 'test', then they will clash and operate on the same miniwindow).
Australia Forum Administrator #15
You can certainly have multiple miniwindows in a plugin, as Worstje says, make sure you give them names that are likely to be unique. For example in one of my plugins:


win = GetPluginID ()  -- get a unique name
tempwin = win .. ":temp"


This gives me two names for miniwindows - the first is the plugin ID which should be unique, and the second one appends ":temp" to give a variation on that name, which also should be unique amongst other plugins.

So if you wanted four windows you could do something like this:


win1 = GetPluginID ()  .. ":1"
win2 = GetPluginID ()  .. ":2"
win3 = GetPluginID ()  .. ":3"
win4 = GetPluginID ()  .. ":4"

#16
I'm not sure if the script above already implement this idea I have. At work, and reading too much gives me headache atm. :)

But what you can do is, add 2 more buttons, which moves up/down several line, or even a page. Just like the arrow and double arrow button you find in tape/cd/etc player.

Cheers.
Australia Forum Administrator #17
I wouldn't use multiple miniwindows just to add buttons - that is what hotspots are for. Draw a button on your main window, and make that button rectangle a hotspot. Then when you click on it you can change its colour, play a "click" sound, and do something useful.
#18
Sorry, I should've said hotspot, rather than button. And maybe add 2 more hotspot on top of the 4. Starting with a 'top' hotspot at the right-top hand corner, that scrolls to the top. Then a hotspot below it, for scrolling up 1 page. Then another one below it for scrolling per line. And so on.

That way, you don't have to break the mouse just to move to the top of the page. ;)

Cheers.
#19
I have been trying to combine the different advice in this thread into one plugin.

I have a capture miniwindow that scrolls but I am having trouble adding in the ability for the text to wrap. I have tried several times but I keep failing as I am still very new to this.

Below is my working plugin. Any help to get text to wrap would be appreciated.


<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<!-- This plugin was made using all the code and ideas at http://www.gammon.com.au/forum/?id=9385 -->

<muclient>
<plugin
   name="ChatWindow"
   author="Garrion"
   id="4de91eaa2624f202c4bb6835"
   language="Lua"
   purpose="Move chats to a miniwindow"
   date_written="2009-07-23"
   requires="4.40"
   version="1.0"
   >

</plugin>

<triggers>
  <trigger
   enabled="y"
   ignore_case="y"
   match="(^)(\(pishe\)|\(thieves\)|\(wizards\)|\(warriors\)|\(witches\)|\(assassins\)|\(RRU\)|\(newbiehelpers\)|\(newbie\)) (.*)$"
   regexp="y"
   script="chats"
   sequence="60"
  >
  </trigger>
</triggers>

<!--  Aliases  -->


<aliases>

</aliases>

<!--  Script  -->


<script>
<![CDATA[
  
  -- configuration

  -- window size in pixels
WINDOW_WIDTH = GetInfo (281)
WINDOW_HEIGHT = 200   -- 200 is 16 lines of 9-point Lucida Console
SCROLL_BAR_WIDTH = 18
LEFT_MARGIN = 5
RIGHT_MARGIN = 5

  -- font
FONT_NAME = "Lucida Console"
FONT_SIZE = 9

  -- where to put the window
WINDOW_POSITION = 6  -- see below (6 is top right)

  --[[
Useful positions:

4 = top left
5 = center left-right at top
6 = top right
7 = on right, center top-bottom
8 = on right, at bottom
9 = center left-right at bottom
  --]]


  -- colours
WINDOW_BACKGROUND_COLOUR = ColourNameToRGB ("black")
WINDOW_TEXT_COLOUR = ColourNameToRGB ("silver")
SCROLL_BACKGROUND_COLOUR = ColourNameToRGB ("#E8E8E8")
SCROLL_BAR_COLOUR = ColourNameToRGB ("#C8C8C8")

text = {}

lineStart = 1
lineEnd = 1
SBWin = "ScrollbarWindow"..GetPluginID()

function OnPluginInstall()
	init()
end

function init()
	WindowCreate(SBWin, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_POSITION, 0, WINDOW_BACKGROUND_COLOUR)
	WindowAddHotspot(SBWin, "upHotspot", WINDOW_WIDTH-SCROLL_BAR_WIDTH, 0, 0, 20, "MouseOver", "CancelMouseOver", "MouseDown", "CancelMouseDown", "MouseUp", "Scroll up?", 1, 0)
	WindowAddHotspot(SBWin, "downHotspot", WINDOW_WIDTH-SCROLL_BAR_WIDTH, WINDOW_HEIGHT-20, 0, 0, "MouseOver", "CancelMouseOver", "MouseDown", "CancelMouseDown", "MouseUp", "Scroll down?", 1, 0)
  WindowShow(SBWin, true)

		-- show border so we can see what we are doing
  WindowRectOp (SBWin, 1, 0, 0, 0, 0, SCROLL_BACKGROUND_COLOUR)
  
  	-- show bar and slider
	WindowRectOp(SBWin, 2, WINDOW_WIDTH-SCROLL_BAR_WIDTH, 0, 0, 0, SCROLL_BACKGROUND_COLOUR)
	WindowRectOp (SBWin, 1, WINDOW_WIDTH-SCROLL_BAR_WIDTH+1, 20, WINDOW_WIDTH-1, WINDOW_HEIGHT-20, SCROLL_BAR_COLOUR)
	
	if #text >= 1 then
    writeLines()
  end -- if
end

function writeLines()
	SPACING = 1
	for count = lineStart, lineEnd do
		WindowText(SBWin, "font"..SBWin, text[count], LEFT_MARGIN, SPACING, WINDOW_WIDTH-(RIGHT_MARGIN+SCROLL_BAR_WIDTH), 0, WINDOW_TEXT_COLOUR, false)
    SPACING = SPACING + (font_height + 1)
	end
end

function refresh()
	WindowRectOp(SBWin, 2, 0, 0, 0, 0, WINDOW_BACKGROUND_COLOUR)
	WindowShow(SBWin, true)
  init()
end

  -- capture chats
function chats (name, line, wildcards, styles)

    -- add new line, time-stamped
  table.insert (text, os.date ("%H:%M:%S ") .. line) -- add new line, time-stamped
  
    -- advance the count
  if #text >= max_lines then
    lineStart = lineStart + 1
  end -- if
  
  if #text > 1 then
  	lineEnd = lineEnd + 1
  end -- if
	
  refresh()
end -- chats

function scrollbar(calledBy)
	if calledBy == "upHotspot" then
		if (lineStart > 1) then
			lineStart = lineStart - 1
			lineEnd = lineEnd - 1
		end
	elseif calledBy == "downHotspot" then
		if (lineEnd < #text) then
			lineStart = lineStart + 1
			lineEnd = lineEnd + 1
		end
	end
	refresh()
end

function MouseOver(flags, hotspot_id)
end

function CancelMouseOver(flags, hotspot_id)
end

function MouseDown(flags, hotspot_id)
end

function CancelMouseDown(flags, hotspot_id)
end

function MouseUp(flags, hotspot_id)
	scrollbar(hotspot_id)
end

-- make the window
WindowCreate (SBWin, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_POSITION, 0, 
                         WINDOW_BACKGROUND_COLOUR)  -- create window

  -- define font
WindowFont(SBWin, "font"..SBWin, FONT_NAME, FONT_SIZE)

  -- work out how high it is
font_height = WindowFontInfo (SBWin, "font"..SBWin, 1)  

  -- work out how many lines will fit
max_lines = math.floor (WINDOW_HEIGHT / font_height)

]]>
</script>

</muclient>
Australia Forum Administrator #20
See this thread:

http://www.gammon.com.au/forum/?id=9454

In particular, near the bottom was a small bit of code that wrapped output by breaking up "line" at the wrap_column, at the nearest space. It then called add_line to actually output the line. A variation on that should do it for you.



-- wrap long lines, at a space if possible
  while #line > wrap_column do
  
    -- find a space not followed by a space, closest to the end of the line
    local col = string.find (line:sub (1, wrap_column), "%s%S*$")
    
    if col and col > 2 then
      col = col - 1  -- use the space to indent
    else
      col = wrap_column  -- just cut off at wrap_column
    end -- if

    add_line (line:sub (1, col))
    line = line:sub (col + 1) 
    
  end -- while line > max


#21
Thanks Nick.

I made some adjustments based on that thread and it works to a degree. It will wrap 1 line ok but if it has to wrap on the second line it starts to double up (example below).

Can anyone help to explain what I have done wrong please?

Example of double output:

(Pishe) Garrion: You are in a clean, airy room, with large
 windows overlooking the street outside. A high counter almost
 windows overlooking the street outside. A high counter
 almost completely separates the far half of the room.


Revised plugin in next post.
Amended on Sun 26 Jul 2009 01:35 AM by Garrion
#22

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<!-- This plugin was made using all the code and ideas at http://www.gammon.com.au/forum/?id=9385 -->

<muclient>
<plugin
   name="ChatWindow"
   author="Garrion"
   id="4de91eaa2624f202c4bb6835"
   language="Lua"
   purpose="Move chats to a miniwindow"
   date_written="2009-07-23"
   requires="4.40"
   version="1.0"
   >

</plugin>

<triggers>
  <trigger
   enabled="y"
   ignore_case="y"
   match="(^)(\(number chasers\)|\(pishe\)|\(thieves\)|\(wizards\)|\(warriors\)|\(witches\)|\(assassins\)|\(RRU\)|\(newbiehelpers\)|\(newbie\)) (.*)$"
   regexp="y"
   script="chats"
   sequence="60"
  >
  </trigger>
  
    <trigger
   custom_colour="2"
   enabled="y"
   ignore_case="y"
   match="(^)you (newbie-tell|newbiehelpers-tell)(.*)(\:)(.*)"
   regexp="y"
   script="chats"
   sequence="60"
  >
  </trigger>
</triggers>

<!--  Aliases  -->


<aliases>

</aliases>

<!--  Script  -->


<script>
<![CDATA[
  
  -- configuration

  -- window size in pixels
WINDOW_WIDTH = GetInfo (281)
WINDOW_HEIGHT = 200   -- 200 is 16 lines of 9-point Lucida Console
SCROLL_BAR_WIDTH = 18
LEFT_MARGIN = 5
RIGHT_MARGIN = 5

  -- font
FONT_NAME = "Lucida Console"
FONT_SIZE = 9

  -- where to put the window
WINDOW_POSITION = 6  -- see below (6 is top right)

  --[[
Useful positions:

4 = top left
5 = center left-right at top
6 = top right
7 = on right, center top-bottom
8 = on right, at bottom
9 = center left-right at bottom
  --]]


  -- colours
WINDOW_BACKGROUND_COLOUR = ColourNameToRGB ("black")
WINDOW_TEXT_COLOUR = ColourNameToRGB ("silver")
SCROLL_BACKGROUND_COLOUR = ColourNameToRGB ("#E8E8E8")
SCROLL_BAR_COLOUR = ColourNameToRGB ("#C8C8C8")

text = {}

lineStart = 1
lineEnd = 1
SBWin = "ScrollbarWindow"..GetPluginID()

function OnPluginInstall()
	init()
	Note (wrap_column)
end

function init()
	WindowCreate(SBWin, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_POSITION, 0, WINDOW_BACKGROUND_COLOUR)
	WindowAddHotspot(SBWin, "upHotspot", WINDOW_WIDTH-SCROLL_BAR_WIDTH, 0, 0, 20, "MouseOver", "CancelMouseOver", "MouseDown", "CancelMouseDown", "MouseUp", "Scroll up?", 1, 0)
	WindowAddHotspot(SBWin, "downHotspot", WINDOW_WIDTH-SCROLL_BAR_WIDTH, WINDOW_HEIGHT-20, 0, 0, "MouseOver", "CancelMouseOver", "MouseDown", "CancelMouseDown", "MouseUp", "Scroll down?", 1, 0)
  WindowShow(SBWin, true)

		-- show border so we can see what we are doing
  WindowRectOp (SBWin, 1, 0, 0, 0, 0, SCROLL_BACKGROUND_COLOUR)
  
  	-- show bar and slider
	WindowRectOp(SBWin, 2, WINDOW_WIDTH-SCROLL_BAR_WIDTH, 0, 0, 0, SCROLL_BACKGROUND_COLOUR)
	WindowRectOp (SBWin, 1, WINDOW_WIDTH-SCROLL_BAR_WIDTH+1, 20, WINDOW_WIDTH-1, WINDOW_HEIGHT-20, SCROLL_BAR_COLOUR)
	
	if #text >= 1 then
    writeLines()
  end -- if
end

function writeLines()
	SPACING = 1
	for count = lineStart, lineEnd do
		WindowText(SBWin, "font"..SBWin, text[count], LEFT_MARGIN, SPACING, WINDOW_WIDTH-(RIGHT_MARGIN+SCROLL_BAR_WIDTH), 0, WINDOW_TEXT_COLOUR, false)
    SPACING = SPACING + (font_height + 1)
	end
end

function refresh()
	WindowRectOp(SBWin, 2, 0, 0, 0, 0, WINDOW_BACKGROUND_COLOUR)
	WindowShow(SBWin, true)
  init()
end

  -- capture chats
function chats (name, line, wildcards, styles)

  if #line < wrap_column then
    add_line (line)
    refresh()
  end -- if

  -- wrap long lines, at a space if possible
  --if #text >= 1 then
    while #line > wrap_column do
    
      -- find a space not followed by a space, closest to the end of the line
      local col = string.find (line:sub (1, wrap_column), "%s%S*$")
      
      if col and col > 2 then
        col = col - 1  -- use the space to indent
      else
        col = wrap_column  -- just cut off at wrap_column
      end -- if

      add_line (line:sub (1, col))
      line = line:sub (col + 1) 
      
        -- add remainder of line
      add_line (line)
      
      refresh()
    end -- while line > max
  --end -- if
end -- chats

function add_line (line)

  -- add new line
  table.insert (text, line)
  
  -- advance the count
  if #text >= max_lines then
    lineStart = lineStart + 1
  end -- if
      
  if #text > 1 then
    lineEnd = lineEnd + 1
  end -- if
end -- add_line


function scrollbar(calledBy)
	if calledBy == "upHotspot" then
		if (lineStart > 1) then
			lineStart = lineStart - 1
			lineEnd = lineEnd - 1
		end
	elseif calledBy == "downHotspot" then
		if (lineEnd < #text) then
			lineStart = lineStart + 1
			lineEnd = lineEnd + 1
		end
	end
	refresh()
end

function MouseOver(flags, hotspot_id)
end

function CancelMouseOver(flags, hotspot_id)
end

function MouseDown(flags, hotspot_id)
end

function CancelMouseDown(flags, hotspot_id)
end

function MouseUp(flags, hotspot_id)
	scrollbar(hotspot_id)
end

-- make the window
WindowCreate (SBWin, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_POSITION, 0, 
                         WINDOW_BACKGROUND_COLOUR)  -- create window

  -- define font
WindowFont(SBWin, "font"..SBWin, FONT_NAME, FONT_SIZE)

  -- work out how high it is
font_height = WindowFontInfo (SBWin, "font"..SBWin, 1)  

  -- work out how many lines will fit
max_lines = math.floor (WINDOW_HEIGHT / font_height)

COLUMN = WindowTextWidth (SBWin, "font"..SBWin, " ")

wrap_column = ((WINDOW_WIDTH-SCROLL_BAR_WIDTH)-(RIGHT_MARGIN+LEFT_MARGIN))/COLUMN
]]>
</script>

</muclient>
Australia Forum Administrator #23
You've changed what I had to:


      add_line (line:sub (1, col))
      line = line:sub (col + 1) 
      
        -- add remainder of line
      add_line (line)


Won't that second add_line add the remainder of the line, giving the results you are seeing?
#24
Ahh yes.

I added that after looking at the linked thread. Without it the last line that is only a partial line does not get shown.

I just tested it and that is the part causing the double line. I will have to figure out how to show the last partial line now.

Thanks Nick.
#25
I copy/pasted Garrion's code and tried to make it work on Materia Magica, but I'm having problems making the word wrapping work. Instead of wrapping a line, it's cutting the line off. The changes I've made to Garrion's original code are:
1. Pattern match on trigger.
2. WINDOW_HEIGHT and WINDOW_WIDTH
3. WINDOW_POSITION
I'm pretty sure none of those changes would cause a problem; however, I'll post the code below as I have it now as well. Thanks in advance for the help!
#26
The code:

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<!-- This plugin was made using all the code and ideas at http://www.gammon.com.au/forum/?id=9385 -->

<muclient>
<plugin
   name="ChatWindow"
   author="Garrion"
   id="4de91eaa2624f202c4bb6835"
   language="Lua"
   purpose="Move chats to a miniwindow"
   date_written="2009-07-23"
   requires="4.40"
   version="1.0"
   >

</plugin>

<triggers>
  <trigger
   enabled="y"
   ignore_case="y"
   match="(^)[CLAN] (.*)$"
   regexp="y"
   script="chats"
   sequence="60"
  >
  </trigger>
  <trigger
   enabled="y"
   ignore_case="y"
   match="(^)\'(.*)\' you say\.$"
   regexp="y"
   script="chats"
   sequence="60"
  >
  </trigger>
  <trigger
   enabled="y"
   ignore_case="y"
   match="(^)You say\, (.*)$"
   regexp="y"
   script="chats"
   sequence="60"
  >
  </trigger>

    <trigger
   custom_colour="2"
   enabled="y"
   ignore_case="y"
   match="(^)[(\d+)] (clan members heard you say\, \')(.*)\'"
   regexp="y"
   script="chats"
   sequence="60"
  >
  </trigger>
</triggers>

<!--  Aliases  -->


<aliases>

</aliases>

<!--  Script  -->


<script>
<![CDATA[
  
  -- configuration

  -- window size in pixels
--WINDOW_WIDTH = GetInfo (281)
--WINDOW_HEIGHT = 200   -- 200 is 16 lines of 9-point Lucida Console
WINDOW_WIDTH = 400
WINDOW_HEIGHT = GetInfo (280) - 40
SCROLL_BAR_WIDTH = 18
LEFT_MARGIN = 5
RIGHT_MARGIN = 5

  -- font
FONT_NAME = "Lucida Console"
FONT_SIZE = 9

  -- where to put the window
WINDOW_POSITION = 7  -- see below (6 is top right)

  --[[
Useful positions:

4 = top left
5 = center left-right at top
6 = top right
7 = on right, center top-bottom
8 = on right, at bottom
9 = center left-right at bottom
  --]]


  -- colours
WINDOW_BACKGROUND_COLOUR = ColourNameToRGB ("black")
WINDOW_TEXT_COLOUR = ColourNameToRGB ("silver")
SCROLL_BACKGROUND_COLOUR = ColourNameToRGB ("#E8E8E8")
SCROLL_BAR_COLOUR = ColourNameToRGB ("#C8C8C8")

text = {}

lineStart = 1
lineEnd = 1
SBWin = "ScrollbarWindow"..GetPluginID()

function OnPluginInstall()
	init()
	Note (wrap_column)
end

function init()
	WindowCreate(SBWin, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_POSITION, 0, WINDOW_BACKGROUND_COLOUR)
	WindowAddHotspot(SBWin, "upHotspot", WINDOW_WIDTH-SCROLL_BAR_WIDTH, 0, 0, 20, "MouseOver", "CancelMouseOver", "MouseDown", "CancelMouseDown", "MouseUp", "Scroll up?", 1, 0)
	WindowAddHotspot(SBWin, "downHotspot", WINDOW_WIDTH-SCROLL_BAR_WIDTH, WINDOW_HEIGHT-20, 0, 0, "MouseOver", "CancelMouseOver", "MouseDown", "CancelMouseDown", "MouseUp", "Scroll down?", 1, 0)
  WindowShow(SBWin, true)

		-- show border so we can see what we are doing
  WindowRectOp (SBWin, 1, 0, 0, 0, 0, WINDOW_BACKGROUND_COLOUR)
  
  	-- show bar and slider
	WindowRectOp(SBWin, 2, WINDOW_WIDTH-SCROLL_BAR_WIDTH, 0, 0, 0, SCROLL_BACKGROUND_COLOUR)
	WindowRectOp (SBWin, 1, WINDOW_WIDTH-SCROLL_BAR_WIDTH+1, 20, WINDOW_WIDTH-1, WINDOW_HEIGHT-20, SCROLL_BAR_COLOUR)
	
	if #text >= 1 then
    writeLines()
  end -- if
end

function writeLines()
	SPACING = 1
	for count = lineStart, lineEnd do
		WindowText(SBWin, "font"..SBWin, text[count], LEFT_MARGIN, SPACING, WINDOW_WIDTH-(RIGHT_MARGIN+SCROLL_BAR_WIDTH), 0, WINDOW_TEXT_COLOUR, false)
    SPACING = SPACING + (font_height + 1)
	end
end

function refresh()
	WindowRectOp(SBWin, 2, 0, 0, 0, 0, WINDOW_BACKGROUND_COLOUR)
	WindowShow(SBWin, true)
  init()
end

  -- capture chats
function chats (name, line, wildcards, styles)

  if #line < wrap_column then
    add_line (line)
    refresh()
  end -- if

  -- wrap long lines, at a space if possible
  if #text >= 1 then
    while #line > wrap_column do
    
      -- find a space not followed by a space, closest to the end of the line
      local col = string.find (line:sub (1, wrap_column), "%s%S*$")
      
      if col and col > 2 then
        col = col - 1  -- use the space to indent
      else
        col = wrap_column  -- just cut off at wrap_column
      end -- if

      add_line (line:sub (1, col))
      line = line:sub (col + 1, wrap_column)
      
      refresh()
    end -- while line > max
   end -- if
end -- chats

function add_line (line)

  -- add new line
  table.insert (text, line)
  
  -- advance the count
  if #text >= max_lines then
    lineStart = lineStart + 1
  end -- if
      
  if #text > 1 then
    lineEnd = lineEnd + 1
  end -- if
end -- add_line


function scrollbar(calledBy)
	if calledBy == "upHotspot" then
		if (lineStart > 1) then
			lineStart = lineStart - 1
			lineEnd = lineEnd - 1
		end
	elseif calledBy == "downHotspot" then
		if (lineEnd < #text) then
			lineStart = lineStart + 1
			lineEnd = lineEnd + 1
		end
	end
	refresh()
end

function MouseOver(flags, hotspot_id)
end

function CancelMouseOver(flags, hotspot_id)
end

function MouseDown(flags, hotspot_id)
end

function CancelMouseDown(flags, hotspot_id)
end

function MouseUp(flags, hotspot_id)
	scrollbar(hotspot_id)
end

-- make the window
WindowCreate (SBWin, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_POSITION, 0, 
                         WINDOW_BACKGROUND_COLOUR)  -- create window

  -- define font
WindowFont(SBWin, "font"..SBWin, FONT_NAME, FONT_SIZE)

  -- work out how high it is
font_height = WindowFontInfo (SBWin, "font"..SBWin, 1)  

  -- work out how many lines will fit
max_lines = math.floor (WINDOW_HEIGHT / font_height)

COLUMN = WindowTextWidth (SBWin, "font"..SBWin, " ")

wrap_column = ((WINDOW_WIDTH-SCROLL_BAR_WIDTH)-(RIGHT_MARGIN+LEFT_MARGIN))/COLUMN
]]>
</script>

</muclient>
#27
I may have fixed Garrion's issue by putting #line into a variable and doing a check in order to use addline(line) at the end.

Something like this:

function chats ..
myline = #line

while ..
..
end

if myline > wrap_column then
    add_line (line)
   end
refresh()

end