draw_text Word Wrap Fix

################################################################
# RETCON Library
# draw_text Word Wrap Version 1.1
# Author: Matt
################################################################
# PURPOSE
# I don't know if it's a bug or not. I don't think so due to the
# existence of draw_text_ex. But it's really annoying that,
# considering you can draw text boxes with certain heights, that
# draw_text will still shrink a line rather than hit the edge
# and carriage return around. This makes it particularly annoying
# to use in custom windows and other associated text draws since
# carriage returns have to be manually inputted and drawn with the
# draw_text_ex function.
#
# This script fixes/allows for draw_text to be called and issue
# excess text to be drawn on multiple lines.
################################################################
# UPDATE HISTORY
# 1.1 - Now part of the RETCON library. Other scripts in library
#        will now check with RMVXAce standardized global variable
#        $imported if this script exists where necessary, which
#        is defined in this script.
# 1.0 - First draft.
################################################################
# METHODOLOGY
# draw_text method in the Bitmap class is aliased and overwritten.
# Now when text hits the width, it advances to a second line.
# If a given text box is not tall enough to word wrap, then it
# shrinks the text as normal.
#
# I can't imagine this is even remotely optimized, since it literally
# interprets every character in a string, but it gets the job done, and
# it's not like RMVXAce is a highly intensive program anyway.
################################################################
# USAGE
# Use draw_text as normal. The function checks to see if the associated
# string is eligible for word wrapping.
#
# This script will work with variable width fonts.
#
# I honestly don't know how this script will conflict with other
# scripts, so combine them at your own risk. It functions fine with
# the base RMVX Ace, which was the goal. However, I'm sure that there
# are scripts out there who pass in their own methods to draw_text,
# so just something to be considerate of.
#
# I could really use some help testing this script. You know where to
# contact me.
################################################################
# CUSTOMIZATION
#
# No customization necessary. Just plug 'n play like the rest.
################################################################

$imported = {} if $imported.nil?
$imported["RETCON-wordwrap"] = true

class Bitmap

  alias draw_text_old draw_text 

  def draw_text(*args)
    #disassemble the argument passed into draw text to work with variables.
    if args[0].is_a?(Rect)
      rect = args[0]
      x = rect.x
      y = rect.y
      width = rect.width
      height = rect.height
      text = args[1].to_s || ""
      alignment = args[2] || 0
    else
      x = args[0]
      y = args[1]
      width = args[2]
      height = args[3]
      text = args[4].to_s || ""
      alignment = args[5] || 0
    end

    #determine overall width of string
    text_rect = self.text_size(text)
    text_width = text_rect.width
    text_height = text_rect.height

    #check to see if word wrapping occurs. If not, pass into alias and
    #draw_text normally
    if text_width > width && height > text_height * 2
      needs_to_wrap = true
      cycle = 0

      #cycles the number of lines to draw.
      while needs_to_wrap == true
        #inits
        choppedtext = ""
        choppedtext_width = 0
        word_width = 0
        i = 0
        word = ""

        #determines if the width of the string is beyond the width of the given
        #text box
        while choppedtext_width + word_width < width  
          choppedtext = choppedtext + word
          word = ""
          letter = ""

          #builds the word, then attaches it to the string, using whitespace
          #as an indicator.
          while letter != " "
            letter = text[i]
            if letter == nil
              letter = " "
            end
            word = word + letter
            i += 1
          end

          #check to see if the next word added will hit the width
          word_width = get_the_width(word)  
          choppedtext_width = get_the_width(choppedtext)
        end

          #dumps any extra whitespace
          choppedtext = choppedtext.strip

          #draws the first line
          draw_text_old(x, y + text_height * cycle, width, text_height, choppedtext, alignment)
          #removes the drawn text from the string
          text = text.split(choppedtext)[1].to_s

          #determines the remaining length of the string
          text_width = get_the_width(text)

          #if the remaining width is smaller than the string, draw the final line.
          #or if the remaining height is less than the next text line, draw the final
          #line and shrink the text.
          #else, cycle around and draw the next line.
          if text_width < width || height < text_height * (cycle + 1)
            text = text.strip
            draw_text_old(x, y + text_height * (cycle + 1), width, text_height, text, alignment)
            needs_to_wrap = false
          else
            cycle += 1
          end

      end
    else
       draw_text_old(x, y, width, height, text, alignment)
     end

  end

  #gets width with any associated text.
  def get_the_width(ltr)
    stringrect = self.text_size(ltr)
    w = stringrect.width
    return w
  end
end