mIRC Homepage
Ok I wrote some code to illistrate what i want, the true code has less lines in the mainwindow than listbox lines (multiple listbox lines map to one line in the mainwindow, how i do this isnt really important for what i need tho)
The mainwindow has some lines that are wrapped and some that are not, any line might be or might not be. In my example I have simply randomized them.
They are liekly to be mostly one way or the other, but could potentially be mixed.


Code:
alias ex1 {
  window -c @ex1
  window -el20 @ex1
  var %i = 1
  while (%i <= 100) {
    var %line, %j = 100
    while (%j) { var %line = $+(%line,$chr(3),$calc(%j % 16) %i) | dec %j }
    aline $iif($r(0,1),-p) @ex1 Line %i ----- %line
    iline -l @ex1 1 Line %i
    inc %i
  }
}
menu @ex1 {
  lbclick : { 
    ///echo -st LBCLICK $active : $1- : $line($active,$1,1)
    sline -l $active $1
    ;^ activate the select the listbox line
    ;
    var %num = $gettok($line($active,$1,1),2,32)
    ;^ get the correct mainwindow linenumber (true code this is more complexe but results the same with %num being the line)
    ;
    var %rev = $chr(22)
    while ($fline($active,$+(%rev,*),1,0)) { rline $active $v1 $mid($line($active,$v1,0),2) }
    ;^ this removes any and all highlighted (reversed) lines in the mainwindow
    ;
    rline $active %num $+(%rev,$line($active,%num,0))
    ;^ highlight (reverse) the selected line in the mainwindow
    ;
    sline $active $line($active,0,0)
    ;^ This line is a patch to make the following line work correctly each time
    ;
    sline $active $calc(%num + 1)
    ;^ This line selects the line following the highlighted line, thus makes the highlighted line appear near the bottom of the mainwindow
    ;
  }
}


OK what im after is to get the mainwindow highlighted line vertically centered in the window, rather than near the bottom like the code does currently
I would like it to work fullscreen and windowed, i not concerned if it goes crappy if someone makes the window so small the line cant be shown, thats just being annoying


Any help anyone?

PS: If all the lines are not wrapped the code was pretty simple...
//sline $active $calc(%num + ($window($active).dh / ($height([],$window($active).font,$window($active).fontsize) + 1) / 2 ))
it's not pretty but it works :tongue:

Code:
alias ex1 {
  window -c @ex1
  window -el20 @ex1
  var %i = 1
  while (%i <= 100) {
    var %line, %j = 100
    while (%j) { var %line = $+(%line,$chr(3),$calc(%j % 16) %i) | dec %j }
    aline $iif($r(0,1),-p) @ex1 Line %i ----- %line
    iline -l @ex1 1 Line %i
    inc %i
  }
}
menu @ex1 {
  lbclick : { 
    ;sline -l $active $1
    var %num = $calc(($line($active,0) + 1) - $1) ,  %rev = $chr(22), %lastsel = $fline($active,$+(%rev,*),1,0))
    echo -s as %lastsel as %num
    if (%lastsel) rline $active %lastsel $mid($line($active,%lastsel,0),2) 
    rline $active %num $+(%rev,$line($active,%num))
    ;sline $active $line($active,0,0)
    selectmiddleline %num $active
  }
}
alias selectmiddleline { 
  var %h = $window($2).dh , %x = $1 , %lineheight , %total = 0 , %wanted = $calc(%h / 2), $&
    %wf = $window($2).font , %wfs = $window($2).fontsize , %w = $window($2).dw
  while ($line($2,%x)) { 
    %lineheight = $wrap($line($2,%x), %wf, %wfs,%w,0) * %wfs
    inc %total %lineheight
    if (%total > %wanted) { sline -a $2 %x | return }
    inc %x
  }
  sline -a $2 $line($2,0)
}


there seems to be a small latency in centering though.

EDIT: I tried cleaning it up a bit to see if that was the problem but it wasn't, you can use the original lbclick and selectmiddleline %num $active at the bottom.
The delay you're talking about is because of $wrap(), which is notoriously slow (although I remember it being optimized a few versions ago). Here's a faster alternative that uses /echo -h and a hidden window to determine the number of wraps:
Code:
alias selectmiddleline { 
  var %x = $1, %wanted = $calc($window(@ex1).dh / 2 / $window(@ex1).fontsize)
  window -h @wrap
  while $line(@ex1,%x) != $null { 
    echo -h @wrap $v1
    if $line(@wrap,0) > %wanted { sline -a @ex1 %x | close -@ @wrap | return }
    inc %x
  }
  close -@ @wrap 
  sline -a @ex1 $line(@ex1,0)
}

The main problem with your approach is that not all lines are wrapped. And while in DaveC's example the wrapped and unwrapped lines are roughly evenly distributed (because of $r(0,1)), this may not be the case in real-world cases. Even in this example, sometimes the line isn't centered exactly (it's as much as 5 lines off). Unfortunately I don't have any alternative or workaround to suggest.
$wrap is not the problem slecting wise (both methods offset the same ammount) non wrapped lines still return 1. I tried to catch the line that exceeded the middle. But i started from the line selected and calculate downwards from there not taking into account that lines above it might be way bigger then the lines below and therefor offsetting the "middle". Your's makes the same mistake but atleast does so damn faster (leave it up to you to come up with a smarter method smile). It comes close enough anyways smile
Quote:
$wrap is not the problem slecting wise (both methods offset the same ammount) non wrapped lines still return 1

By non-wrapped lines I mean "lines added with /aline without the -p switch". If such lines are long, $wrap() returns a number > 1, but in the main window they occupy only 1 physical line. The errors caused by this difference can accumulate, resulting in a big offset from the middle, like Line 77 in the example.

In this respect, our versions are equivalent: all mine does is speed up the the whole thing. As I said before, it doesn't solve the problem nor do I know of a way that does fully, at least not without storing the wrap state of each line that is added (and even then the alignment won't be perfect because /sline 'jumps' between entire lines, not wrapped physical lines).

That said, and provided the above kind of error doesn't get too big, the situation can get a little better if, before /sline makes the next jump, the script checks whether it will end up pushing the highlighted text up further from the middle than before. Here's a version that implements this:
Code:
alias selectmiddleline { 
  var %x = $1, %wanted = $calc($window(@ex1).dh / 2 / $window(@ex1).fontsize), %t
  window -hf @wrap -1 -1 $window(@ex1).dw $window(@ex1).dh
  while $line(@ex1,%x) != $null { 
    %t = $line(@wrap,0)
    echo -h @wrap $v1
    if $calc($line(@wrap,0) - %wanted) > 0 {
      if ($v1 > $calc(%wanted - %t)) dec %x
      sline -a @ex1 %x | close -@ @wrap | return 
    }   
    inc %x
  }
  close -@ @wrap 
  sline -a @ex1 $line(@ex1,0)
}


EDIT: corrected a silly omission regarding the size of the hidden @wrap window
Quote:

By non-wrapped lines I mean "lines added with /aline without the -p switch".


Ahh yes of course, your totally right.
Thanks to both of you Querty and Mp3dreamz, excellent work both, i was just lost before, i couldnt think of anyway at all to do it.

I took on what was said and solutioned the wrapped/unwrapped lines problem, using a marker on each line that is not wrapped, so when they are reproduced in the @wrap window they can be dealt with according to the marker. This has reduced the displacment problem alot. Im still working on perfecting an exact center, but its very close now.

When creating the original lines, if there unwrapped i lead off with a double ctrl-U

Below is what i added in the example code, but is pretty much the same in the real code.

Code:
alias ex1 {
  window -c @ex1
  window -el20 @ex1
  var %i = 1
  while (%i <= 100) {
    var %line, %j = 100
    while (%j) { var %line = $+(%line,$chr(3),$calc(%j % 16) %i) | dec %j }
    [color:blue]if ($r(0,1)) { aline -p @ex1 Line %i ----- %line } | else { aline @ex1 $str($chr(31),2) $+ Line %i ----- %line }
    ;^ any line not wrapping leades off with to ctrl-u's
    ;[/color]
    iline -l @ex1 1 Line %i
    inc %i
  }
}
menu @ex1 {
  lbclick : { 
    ///echo -st LBCLICK $active : $1- : $line($active,$1,1)
    sline -l $active $1
    var %num = $gettok($line($active,$1,1),2,32)
    var %rev = $chr(22)
    while ($fline($active,$+(%rev,*),1,0)) { rline $active $v1 $mid($line($active,$v1,0),2) }
    rline $active %num $+(%rev,$line($active,%num,0))
    selectmiddleline %num
  }
}  
alias selectmiddleline { 
  var %x = $1, %wanted = $calc($window(@ex1).dh / 2 / $window(@ex1).fontsize) , %t, %text
  window -hf @wrap -1 -1 $window(@ex1).dw $window(@ex1).dh
  while $line(@ex1,%x) != $null {
    %text = $v1
    %t = $line(@wrap,0)
    [color:blue]if ($asc($mid(%text,2)) != 31) { echo -h @wrap %text } | else { echo @wrap . }
    ;^ if second character on line is NOT a ctrl-u then it a wrapped line so display it, else just show a "." to represent a single line
    ; 2nd character as line might be the selected line being ctrl-R,ctrl-U,ctrl-U or an unselected line ctrl-U,ctrl-U
    ;[/color]
    if $calc($line(@wrap,0) - %wanted) > 0 {
      if ($v1 > $calc(%wanted - %t)) { dec %x }
      sline -a @ex1 %x | sline -a @ex1 %x | sline -a @ex1 %x | close -@ @wrap | return 
      ;^ still expreneced the odd aligment problem so simple /sline x3 to fix it.
      ;
    }   
    inc %x
  }
  close -@ @wrap 
  sline -a @ex1 $line(@ex1,0) | sline -a @ex1 $line(@ex1,0) | sline -a @ex1 $line(@ex1,0)
  ;^ still expreneced the odd aligment problem so simple /sline x3 to fix it.
  ;
}


* im still tweaking the alignment somewhat, looking at the idea of seeing how many lines are in the selected line ($1), then halfing that value, would make a selected line of say 5 lines, have only a value of 2.5, which i think well help align it more, but thats for me to have to work out.

Again thanks to both of u for the solution.

DaveC
© mIRC Discussion Forums