mIRC Home    About    Download    Register    News    Help

Print Thread
$wrap improvement #267237 25/04/20 03:22 AM
Joined: Jul 2006
Posts: 3,702
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 3,702
As discussed in this thread, $wrap needs to support the new $width parameter.
In fact, $wrap does not support the current B and C $width's parameter, which is also a problem to correctly calculate a width.
Also, in the beta change log, there is
Quote
6.Added $width() and $height() sixth $true/$false parameter to enable custom window-specific measurement.
But $height is only documented with 3 parameters currently, would be nice to update the help file regarding $height.

It looks like the word parameter could be extended:

However I'm not too sure how you would pass the B C D parameter of $width inside that word parameter, bNcNdN where N are numbers?

So with an alternative mode 'a' and 'w' for word wrap, the parameter word would be like $wrap(text,font,size,maxwidth,awb0c0d0,N) for 'default' value of B C D, but maybe simple allow 'aw' with default value for B C D

I'd add a 't' switch to change the code point value at which the word wrap occurs: $wrap(text,font,size,maxwidth,awt160,N)

Below is an update of the custom wrap alias, I commented it fully in case that can help.
It uses regex for word wrapping and always wrap on space, but it will also wrap on the character passed as $10 as well, it won't wrap only at the character you passed, but this can easily be modified by removing \x20 everywhere when $10 is passed.

Code
alias wrap2 {
  ;$1 = text $2 = font $3 = size, $4 = maxwidth, $5 = $width's B $6 = $width's C $7 = $width's D $8 = N $9 = wordwrap $10 = optional C
  ;when word wrapping and the words are too big to fit, it tries to split the words
  ;whenever maxwidth is too small to fit the smallest character, return 0 for N = 0 and $null for N > 0
  
  if ($1 == $null) || ($2 == $null) || ($3 == $null) || ($4 == $null) || ($8 == $null) { echo -s * $!wrap2: insufficient params | return }
  ;if the width of text fits maxwidth, we can return immediately
  if ($width($1,$2,$3,$5,$6,$7) <= $4) {
    if ($8 == 0) return 1
    return $1
  }
  ;if no word wrap
  if (!$9) {
    var %index 1,%n 0,%seek,%len $len($1),%len1
    ;as long as there are character left to process, left from right
    while (%index <= %len) {
      %seek = 1
      %len1 = $calc(%len - %index + 1)
      ;as long as the width of the current text is smaller or equal to maxwidth, we get more characters
      while (%seek <= %len1) && ($width($mid($1,%index,%seek),$2,$3,$5,$6,$7) <= $4) inc %seek
      dec %seek
      ;if %seek is 0, the character at %index doesn't fit into maxwidth, it's an error
      if (%seek == 0) {
        if ($8 == 0) return 0
        return
      }
      ;otherwise we increment the line number
      inc %n
      ;if the N parameter equals the line number, we save the data to a temp variable because we still have to process the rest of the character: it's possible that later chunk won't fit maxwidth (fseek = 0 above) and it should report an error then
      if (%n == $8) var -p %item $mid($1,%index,%seek)
      ;increment the index
      %index = %index + %seek
    }
    ;if no error, we reach this point, if %item is there, return it
    if (%item != $null) returnex %item
    ;otherwise if N is 0, return the number of wrapped lines
    if ($8 == 0) return %n
  }
  else {
    ;word wrap, delimiters are always trimmed from result when N > 0
    ;prepare regex pattern, trim consecutives delimiters (either space or $chr($10))
    var %n 0,%rp $iif($chr($10) isin \[]-,\ $+ $v1,$v1),%p /(*UTF8)([^\x20 $+ %rp $+ ]+)([\x20 $+ %rp $+ ]+|$)/,%re $regex(wrap2,$1,/(*UTF8)^([\x20 $+ %rp $+ ]+)/),%index $len($regml(wrap2,1)) + 1,%temp
    ;as long as they are regex match which find the next 'token' separated by space/$chr($10)
    ;build a buffer of tokens with their delimiter
    while ($regex(wrap2,$mid($1,%index),%p)) {
      ;$regml(1) = token
      ;$regml(2) = consecutives delimiter, at least one char
      ;if the width of what's currently in the buffer + the current token without its delimiters, is greater than maxwidth, we split
      var -p %wt %r $+ $regml(wrap2,1)
      if ($width(%wt,$2,$3,$5,$6,$7) > $4) {
        inc %n
        ;%r is the full buffer, if %r is $null, it means we needs to split but there are no token to report, because the maxwidth is too small to contain the smallest token
        if (%r == $null) {
          ;in this case, we do it smart like $wrap, and we try to split the token itself (%wt), this finds the biggest width which fits, for that token
          var %len $len(%wt)
          while (%len) && ($width($left(%wt,%len),$2,$3,$5,$6,$7) > $4) dec %len
          ;if %len is 0, it means that the smallest portion of the token, the first character, does not fit into maxwidth, we report an error
          if (%len == 0) {
            if ($8 == 0) return 0
            return 
          }
          ;otherwise we modify %temp, which hold the number of character we get for that chunk (%wt)
          %temp = %len
          ;we increment the index accordingly so that the next token start from the end of that current token
          inc %index %len
        }
        ;if the N parameter equals the line number, we save the data to a temp variable because we still have to process the rest of the character: it's possible that later chunk won't fit maxwidth (fseek = 0 above) and it should report an error then
        if (%n == $8) var -p %item $mid(%wt,1,%temp)
        ;we just split, so we reset the buffer
        var %r
      }
      ;otherwise we keep adding the token to a buffer and we store (%temp) the number of character the current chunk contains (to account for consecutive delimiters), which will be used for the split
      else {
        var -p %r %r $+ $regml(wrap2,1) $+ $regml(wrap2,2)
        inc %index $len($regml(wrap2,1) $+ $regml(wrap2,2))
        %temp = $len(%r) - $len($regml(wrap2,2))
      }
    }
    inc %n
    ;if no error, we reach this point, if %item is there, return it
    if (%item) returnex %item
    ;otherwise if N is 0, return the number of wrapped lines
    if ($8 == 0) return %n
    ;if maxwidth is greater than what's left of the input after a wrap occured, the main loop above will stop without setting %item, we return what's left.
    if (%n == $8) returnex %wt
  }
}


Looking for a good help channel about mIRC? Check #mircscripting @ irc.swiftirc.net
Re: $wrap improvement [Re: Wims] #267251 28/04/20 01:27 AM
Joined: Jul 2006
Posts: 3,702
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 3,702
I'm not sure if the parameter C = 1 in future wrap call should imply that control code must be preserve on wrapped line or if a new switch should be used, but it makes sense that if you interpret control code, you want them on wrapped lines.

Note that there is a $wrap2 made specifically to retain control code on $wrap here: http://hawkee.com/snippet/17956/

I also made my custom wrap support control codes via a .color property, it uses the $controlat and $colorat identifiers which were suggested here, so it's not the most efficient, but it's merely there to show how to do it.

Code
alias wrap2 {
  ;$1 = text $2 = font $3 = size, $4 = maxwidth, $5 = $width's B $6 = $width's C $7 = $width's D $8 = N $9 = wordwrap $10 = optional C
  ;when word wrapping and the words are too big to fit, it tries to split the words
  ;whenever maxwidth is too small to fit the smallest character, return 0 for N = 0 and $null for N > 0

  if ($1 == $null) || ($2 == $null) || ($3 == $null) || ($4 == $null) || ($8 == $null) { echo -s * $!wrap2: insufficient params | return }
  ;if the width of text fits maxwidth, we can return immediately
  ; var -s %w $width($1,$2,$3,$5,$6,$7)
  if ($width($1,$2,$3,$5,$6,$7) <= $4) {
    if ($8 == 0) return 1
    if ($8 == 1) return $1
  }
  ;if no word wrap
  if (!$9) {
    var %index 1,%n 0,%seek,%len $len($1),%len1
    ;as long as there are character left to process, left from right
    while (%index <= %len) {
      %seek = 1
      %len1 = $calc(%len - %index + 1)
      ;as long as the  width of the current text is smaller or equal to maxwidth, we get more characters
      while (%seek <= %len1) && ($width($mid($1,%index,%seek),$2,$3,$5,$6,$7) <= $4) inc %seek
      dec %seek
      ;if %seek is 0, the character at %index doesn't fit into maxwidth, it's an error
      if (%seek == 0) {
        if ($8 == 0) return 0
        return 
      }
      ;otherwise we increment the line number
      inc %n
      ;if the N parameter equals the line number, we save the data to a temp variable because we still have to process the rest of the character: it's possible that later chunk won't fit maxwidth (fseek = 0 above) and it should report an error then
      if (%n == $8) var -p %item $controlat($1,%index) $+ $mid($1,%index,%seek)
      ;increment the index
      %index = %index + %seek
    }
    ;if no error, we reach this point, if %item is there, return it
    if (%item != $null) returnex %item
    ;otherwise if N is 0, return the number of wrapped lines
    if ($8 == 0) return %n
  }
  else {
    ;word wrap, delimiters are always trimmed from result when N > 0
    ;prepare regex pattern, trim consecutives delimiters (either space or $chr($10))
    var %n 0,%rp $iif($chr($10) isin \[]-,\ $+ $v1,$v1),%p /(*UTF8)([^\x20 $+ %rp $+ ]+)([\x20 $+ %rp $+ ]+|$)/,%re $regex(wrap2,$1,/(*UTF8)^([\x20 $+ %rp $+ ]+)/),%index $len($regml(wrap2,1)) + 1,%temp
    if ($prop == color) var %ctrlat $controlat($1,1)
    ;as long as they are regex match which find the next 'token' separated by space/$chr($10)
    ;build a buffer of tokens with their delimiter
    while ($regex(wrap2,$mid($1,%index),%p)) {
      ;$regml(1) = token
      ;$regml(2) = consecutives delimiter, at least one char
      ;if the width of what's currently in the buffer + the current token without its delimiters, is greater than maxwidth, we split
      var -p %wt %r $+ $regml(wrap2,1)

      if ($width(%wt,$2,$3,$5,$6,$7) > $4) {
        inc %n
        ;%r is the full buffer, if %r is $null, it means we needs to split but there are no token to report, because the maxwidth is too small to contain the smallest token
        if (%r == $null) {
          ;in this case, we do it smart like $wrap, and we try to split the token itself (%wt), this finds the biggest width which fits, for that token
          var %len $len(%wt)
          while (%len) && ($width($left(%wt,%len),$2,$3,$5,$6,$7) > $4) dec %len
          ;if %len is 0, it means that the smallest portion of the token, the first character, does not fit into maxwidth, we report an error
          if (%len == 0) {
            if ($8 == 0) return 0
            return 
          }
          ;otherwise we modify %temp, which hold the number of character we get for that chunk (%wt)
          %temp = %len
          ;we increment the index accordingly so that the next token start from the end of that current token
          inc %index %len
        }
        ;if the N parameter equals the line number, we save the data to a temp variable because we still have to process the rest of the character: it's possible that later chunk won't fit maxwidth (fseek = 0 above) and it should report an error then
        if (%n == $8) {
          var -p %item %ctrlat $+ $mid(%wt,1,%temp)
        }
        ;we just split, so we reset the buffer
        var %r
        ;if .color prop is used, get the control at the current position, which is the start of the future buffer.
        if ($prop == color) %ctrlat = $controlat($1,%index)
      }
      ;otherwise we keep adding the token to a buffer and we store (%temp) the number of character the current chunk contains (to account for consecutive delimiters), which will be used for the split
      else {
        var -p %r %r $+ $regml(wrap2,1) $+ $regml(wrap2,2)
        inc %index $len($regml(wrap2,1) $+ $regml(wrap2,2))
        %temp = $len(%r) - $len($regml(wrap2,2))
      }
    }
    inc %n
    ;if no error, we reach this point, if %item is there, return it
    if (%item) returnex %item
    ;otherwise if N is 0, return the number of wrapped lines
    if ($8 == 0) return %n
    ;if maxwidth is greater than what's left of the input after a wrap occured, the main loop above will stop without setting %item, we return what's left.
    if (%n == $8) returnex %ctrlat $+ %wt
  }
}
alias colorat {
  if ($prop == set) {
    if ($1 != $chr(15)) {
      var %i $iif($2,$2,$gettok(%colorat,2,44))
      %colorat = $1 $+ $iif($1,$iif(%i,$chr(44) $+ %i))
    }
    else %colorat =
  }
  else {
    set -u %colorat
    var %r /(?:\x03(?:(\d+)(?:,(\d+))?)?|(\x0F))/g,%r $regsubex($left($1,$2),%r,$colorat(\1,\2).set)
    %r = %colorat
    unset %colorat
    return $iif(%r != $null,$chr(3) $+ %r)
  }
}

alias controlat {
  if ($prop == set) {
    if ($1 != $chr(15)) {
      if ($1 isin %controlat) %controlat = $remove(%controlat,$1)
      else %controlat = %controlat $+ $1
    }
    else %controlat =
  }
  else {
    set -u %controlat
    var %c $iif($3,$3,kubir),%r $+(/,$chr(40),$left($regsubex($remove(%c,k),/(.)/g,\x $+ $base($replace(\1,u,31,b,2,i,29,r,22),10,16,2) $+ |),-1),|\x0F,$chr(41),/g),%r $regsubex($left($1,$2),%r,$controlat(\1).set)
    %r = %controlat
    unset %controlat
    return %r $+ $iif(k isin %c,$colorat($1,$2))
  }
}


Looking for a good help channel about mIRC? Check #mircscripting @ irc.swiftirc.net