#CONSTANT TRUE = 1
#CONSTANT FALSE = 0
#CONSTANT SCROLLBARSIZE = 12
#CONSTANT TITLEBARSIZE = 18
#CONSTANT MIN_WIDTH = 40
#CONSTANT MIN_HEIGHT = 30
#CONSTANT VK_BACKSPACE = 8
#CONSTANT VK_RETURN = 13
#CONSTANT VK_DELETE = 211
#CONSTANT VK_COPY = 3
#CONSTANT VK_PASTE = 22
Global NEW_FILE$ = "Untitled"
Global CLICK_FLAG = 0         : `mouse is pressed down
Global CARET_STAMP = 0        : `timestamp for cursor blink rate
Global CARET$ = "|"           : `the cursor to display
Global VK_FLAG = 0            : `if an arrow key is being pressed
global _mouseFlag = 0         : `used with menu functions
Global status_message$ = ""   : `message displayed in status bar
 
 
type Menu
   name as string              ` name of this menu
   active as boolean           ` enabled/disabled
   width as integer            ` width of this menu
   count as integer            ` item count
endtype
 
type MenuItem
   parentID as integer         `id of menu this item belongs to
   item as string              `name of this item
   enabled as boolean          `enabled/disabled
   check as integer            `unused
endtype
 
type Files
   name as string              `name of file for read/write
   maxWidth as integer         `number of chars in longest line
   textIndex as integer        `beginnging of this file's text in the string array
   textEnd as integer          `ending of this file's text in the string array
endtype
 
type Window
   x as integer                `X position of window
   y as integer                `Y position of window
   width as integer            `width of window
   height as integer           `height of window
   fileIndex as integer        `index in file array this window references
   thumbX as integer           `scrollbar thumb X position (horizontal)
   thumbY as integer           `scrollbar thumb Y position (vertical)
   thumbHeight as integer      `scrollbar thumb height (vertical)
   thumbWidth as integer       `scrollbar thumb width (horizontal)
   thumbXFlag as boolean       `horizontal scrollbar moving
   thumbYFlag as boolean       `vertical scrollbar moving
   thumbOffsetX as integer     `offset from where mouse clicked horizontal scrollbar
   thumbOffsetY as integer     `offset from where mouse clicked vertical scrollbar
   showVertical as boolean     `show/hide vertical scrollbar
   showHorizontal as boolean   `show/hide horizontal scrollbar
   titleFlag as boolean        `window is being dragged
   titleOffsetX as integer     `offset of where window title bar was grabbed with mouse X
   titleOffsetY as integer     `offset of where window title bar was grabbed with mouse Y
   resizeFlag as boolean       `window is being resized
   resizeOffsetX as integer    `offset X from where mouse clicked resize corner
   resizeOffsetY as integer    `offset Y from where mouse clicked resize corner
   startingLine as integer     `what line number to start displaying text from (vertical scrolling)
   startingChar as integer     `what character position to start displaying text from (horizontal scrolling)
   showLineNumbers as boolean  `show/hide line number border
   visibleLines as integer     `how many lines this window can display at one time
   visibleChars as integer     `how many characters across this window can display at one time
   selectedRow as integer      `what line number is being edited
   caretPos as integer         `character position of cursor in 'selectedRow'
endtype
 
 
type SelectionNode
   row as integer              `which line of text (from array __textLines$)
   char as integer             `character position within that line
endtype
 
type SelectionRange
   start as SelectionNode      `beginning of selection
   finish as SelectionNode     `end of selection
endtype
 
Global _selection as SelectionRange
 
 
dim __openFiles(0) as Files   : `array of opened files
dim __windows(0) as Window    : `array of displayed windows
dim __textLines$(0) as string : `holds lines of text from all files
                              : `"File" indices reference this array
 
dim menus() as Menu           : `array of menus
dim menuItems() as MenuItem   : `array of menu items from all menus
 
 
MENU_FILE = addMenu("File")
MENU_EDIT = addMenu("Edit")
MENU_TOOLS = addMenu("Tools")
addMenuItem(MENU_FILE,"New",TRUE,-1)
addMenuItem(MENU_FILE,"Open",TRUE,-1)
addMenuItem(MENU_FILE,"Save",TRUE,-1)
addMenuItem(MENU_FILE,"Save As",TRUE,-1)
addMenuItem(MENU_FILE,"Close Window",TRUE,-1)
addMenuItem(MENU_FILE,"------------",TRUE,-1)
addMenuItem(MENU_FILE,"Exit",TRUE,-1)
addMenuItem(MENU_EDIT,"Cut",TRUE,-1)
addMenuItem(MENU_EDIT,"Copy",TRUE,-1)
addMenuItem(MENU_EDIT,"Paste",TRUE,-1)
addMenuItem(MENU_TOOLS,"Word Count",TRUE,-1)
addMenuItem(MENU_TOOLS,"Character Count",TRUE,-1)
 
 
set display mode 1024,768,16
`sync on
`backdrop on
`color backdrop rgb(0,0,255)
 
 
`openFile("c:teTest.txt") : `non-existant file, creates blank
`openFile("c:test.txt")
`openFile("c:vraylog.txt")
`openFile("c:thing.txt")
 
status_message$ = "status bar"
 
 
DO
   cls
 
   handleWindows()
 
   handleMenus()
 
   handleStatusBar()
 
   `text 2,200,prevRow$
   `fastsync
LOOP
 
 
 
REM **********************************
REM handles all functionality of menus
REM **********************************
function handleMenus()
   _mc = mouseclick()
   if _mc = 0 then _mouseFlag = 0
   v$ = _handleMenus$(_mc)
   if v$ = "Edit-Copy" then copyText()
   if v$ = "Edit-Paste" then pasteText()
   if v$ = "File-New" then openFile(NEW_FILE$)
   if v$ = "File-Open" then openDialog()
   if v$ = "File-Save" then saveFile("")
   if v$ = "File-Save As" then saveAsDialog()
   if v$ = "File-Exit" then end
   if v$ = "File-Close Window" then closeWindow()
   if v$ = "Tools-Word Count" then countWords()
   if v$ = "Tools-Character Count" then countCharacters()
 
endfunction
 
 
 
REM ****************************
REM Handles rendering and UI
REM of all text document windows
REM ****************************
function handleWindows()
   hwind = 0
   count = array count(__windows())
   for i = 1 to count
      _drawWindow(i)
      h = _handleWindowUI(count+1-i)
      if h > hwind then hwind = h
   next i
 
   rem order last window focused on top
   if hwind > 0 and hwind < count
      temp as Window
      temp = __windows(hwind)
      for i = hwind to count-1
         __windows(i) = __windows(i+1)
      next i
      __windows(count) = temp
   endif
   if mouseclick() = 0 then CLICK_FLAG = 0
 
   _handleFocused()
 
endfunction
 
 
REM **********************************
REM Functionality for whichever window
REM currently has focus
REM **********************************
function _handleFocused()
   index = array count(__windows())
   x = __windows(index).x
   y = __windows(index).y
   width = __windows(index).width
   height = __windows(index).height
   thumbX = __windows(index).thumbX
   thumbY = __windows(index).thumbY
   thumbHeight = __windows(index).thumbHeight
   fileIndex = __windows(index).fileIndex
   textIndex = __openFiles(fileIndex).textIndex
   lineCount = __openFiles(fileIndex).textEnd - textIndex
   lineHeight = text height("A")
   visibleLines = __windows(index).visibleLines
 
   editLines(index)
 
   if __windows(index).showVertical = TRUE
      mmz = mousemovez()
      if mmz < 0 then thumbY = thumbY + 10
      if mmz > 0 then thumbY = thumbY - 10
 
      if thumbY < 0 then thumbY = 0
      if thumbY > height-thumbHeight then thumbY = height-thumbHeight
      __windows(index).thumbY = thumbY
      __windows(index).startingLine = textIndex + ((lineCount-visibleLines+1)*thumbY) / (height-thumbHeight)
   endif
endfunction
 
 
 
REM *********************************
REM Handles too many different things
REM than a single function should do
REM *********************************
function editLines(index as integer)
   x = __windows(index).x
   y = __windows(index).y
   width = __windows(index).width
   height = __windows(index).height
   caret = __windows(index).caretPos
   row = __windows(index).selectedRow
   fi = __windows(index).fileIndex
   startingLine = __windows(index).startingLine
   startingChar = __windows(index).startingChar
   fileIndex = __windows(index).fileIndex
   visibleChars = __windows(index).visibleChars
   lineHeight = text height("A")
   charWidth = text width("A")
 
 
   rem position cursor with mouse
   if mouseclick() = 1
 
      if mouseWithin(x,y,x+width,y+height)
         t_row = (mousey() - y) / lineHeight
         t_caretPos = (mousex() - x) / charWidth + startingChar
         t_row = startingLine + t_row
         if t_row > __openFiles(fileIndex).textEnd then t_row = __openFiles(fileIndex).textEnd
         `__windows(index).selectedRow = row
         fPos = len(__textLines$(t_row))
         if t_caretPos > fPos then t_caretPos = fPos
         `caret = __windows(index).caretPos
 
         if CLICK_FLAG = 0
            CLICK_FLAG = 1
 
            row = t_row
            caret = t_caretPos
            __windows(index).caretPos = caret
            __windows(index).selectedRow = row
 
            _selection.start.row = row
            _selection.start.char = caret
 
         else
            _selection.finish.row = t_row
            _selection.finish.char = t_caretPos
         endif
      endif
   endif
 
   rem position cursor with arrow keys
   if upkey() and VK_FLAG = 0
      VK_FLAG = 1
      dec row
      if row < 1 then row = 1
      __windows(index).selectedRow = row
      fPos = len(__textLines$(row))
      if caret > fPos then caret = fPos
   endif
   if downkey() and VK_FLAG = 0
      VK_FLAG = 1
      inc row
      lineCount = __openFiles(fileIndex).textEnd - __openFiles(fileIndex).textIndex
      if row > lineCount then row = lineCount
      __windows(index).selectedRow = row
      fPos = len(__textLines$(row))
      if caret > fPos then caret = fPos
   endif
   if rightkey() and VK_FLAG = 0
      VK_FLAG = 1
      inc caret
      fPos = len(__textLines$(row))
      if caret > fpos then caret = fpos
   endif
   if leftkey() and VK_FLAG = 0
      VK_FLAG = 1
      dec caret
      if caret < 0 then caret = 0
   endif
   if upkey() = 0 and downkey() = 0 and rightkey() = 0 and leftkey() = 0
      VK_FLAG = 0
   else
      __windows(index).caretPos = caret
   endif
 
 
   rem text input
   lineText$ = __textLines$(row)
   buffer$ = entry$()
   for i = 1 to len(buffer$)
      ink rgb(255,255,255),0
      set cursor 10,220
      print asc(mid$(buffer$,i))
      select asc(mid$(buffer$,i))
         case VK_COPY
            copyText()
         endcase
         case VK_PASTE
            pasteText()
         endcase
         case VK_BACKSPACE
            if caret > 0
               t$ = left$(lineText$,caret-1)
               lineText$ = t$ + right$(lineText$, len(lineText$)-len(t$)-1)
               dec caret
            else
               if row > startingLine
                  prevRow$ = __textLines$(row-1)
                  lineText$ = prevRow$ + lineText$
                  deleteLine(fi, row)
                  caret = len(prevRow$)
                  dec row
               endif
            endif
         endcase
         case VK_RETURN
            t$ = left$(lineText$,caret)
            __textLines$(row) = t$
            lineText$ = right$(lineText$, len(lineText$)-len(t$))
            insertLine(fi,lineText$,row+1)
            caret = 0
            inc row
         endcase
         case VK_DELETE
            if caret < len(lineText$)
               t$ = left$(lineText$, caret-1)
               __textLines$(row) = right$(lineText$, len(lineText$)-(len(t$)+1))
            else
 
            endif
         endcase
         case default
            t$ = left$(lineText$,caret)
            lineText$ = t$ + mid$(buffer$,i) + right$(lineText$, len(lineText$)-len(t$))
            inc caret
            if caret-startingChar > visibleChars then __windows(index).startingChar = __windows(index).startingChar+1
         endcase
      endselect
   next i
   clear entry buffer
   __textLines$(row) = lineText$
   __windows(index).caretPos = caret
   __windows(index).selectedRow = row
 
 
   rem check if new scrollbars are needed
   rem horizontal
   if len(lineText$) > __openFiles(fileIndex).maxWidth
       __openFiles(fileIndex).maxWidth = len(lineText$)-1
       _resizeWindow(index)
   endif
   rem vertical
   if (__openFiles(fileIndex).textEnd - __openFiles(fileIndex).textIndex) > __windows(index).visibleLines
      _resizeWindow(index)
   endif
 
 
   rem blinking cursor
   if timer() >= CARET_STAMP+500
      CARET_STAMP = timer()
      if CARET$ = "|"
         CARET$ = ""
      else
         CARET$ = "|"
      endif
   endif
   if startingChar > 0 then caret = caret+1
   if __windows(index).startingChar < 0 then __windows(index).startingChar = 0
   cy = y+(row-startingLine)*lineHeight
   cx = x+(caret-startingChar)*charWidth
   if cy >= y and cy < y+height and cx >= x and cx < x+width then text cx,cy,CARET$
 
endfunction
 
 
 
REM *******************************
REM inserts a new line into a file
REM 'fileIndex' file to insert into
REM 'txt' text to insert
REM 'row' line number to insert at
REM *******************************
function insertLine(fileIndex as integer, txt as string, row as integer)
 
   if row < array count(__textLines$())
      array insert at element __textLines$(), row
   else
      array insert at bottom __textLines$()
   endif
   __textLines$(row) = txt
   __openFiles(fileIndex).textEnd = __openFiles(fileIndex).textEnd+1
 
   for f = fileIndex+1 to array count(__openFiles())
      __openFiles(f).textIndex = __openFiles(f).textIndex+1
      __openFiles(f).textEnd = __openFiles(f).textEnd+1
   next f
 
   for w = 1 to array count(__windows())
      if __windows(w).fileIndex > fileIndex then __windows(w).startingLine = __windows(w).startingLine + 1
   next w
 
endfunction
 
 
 
REM ***************************************
REM Removes a line from a text file
REM Adjusts indices of other affected files
REM using the __textLines$() array
REM 'fileIndex' file to remove line from
REM 'row' line number to remove
REM ***************************************
function deleteLine(fileIndex as integer, row as integer)
   array delete element __textLines$(), row
 
   __openFiles(fileIndex).textEnd = __openFiles(fileIndex).textEnd - 1
 
   for f = fileIndex+1 to array count(__openFiles())
      __openFiles(f).textIndex = __openFiles(f).textIndex - 1
      __openFiles(f).textEnd = __openFiles(f).textEnd - 1
   next f
 
   for w = 1 to array count(__windows())
      if __windows(w).fileIndex > fileIndex then __windows(w).startingLine = __windows(w).startingLine - 1
   next w
endfunction
 
 
REM ***********************************
REM Prompts user with a save dialog box
REM Then attempts to save the file
REM ***********************************
function saveAsDialog()
   file$ = removeTrailingSpaces$(_open_save("Text File (*.txt)|*.txt|All Files (*.*)|*.*|",get dir$(),"Save File","*.*",0))
   if file$ <> "" and mid$(file$,1) <> "!" then saveFile(file$)
endfunction
 
 
 
REM *************************************
REM saves a text file
REM if 'file' is an empty string,
REM file is saved under its given path.
REM if 'file' is not empty, the save
REM function acts as a Save As function
REM and saves the file under the new name
REM and associates it with that path
REM from then on.
REM *************************************
function saveFile(file as string)
   index = array count(__windows())
   fileIndex = __windows(index).fileIndex
   start = __openFiles(fileIndex).textIndex
   finish = __openFiles(fileIndex).textEnd
 
 
   if file = ""
      file = __openFiles(fileIndex).name
      if file = NEW_FILE$
         saveAsDialog()
         exitfunction
      endif
      status_message$ = "File saved"
   else
      __openFiles(fileIndex).name = file
      status_message$ = "File saved as "+file
   endif
 
   `tempFile$ = "$_"+file
   `if path exist(tempFile$) then delete file tempFile$
   if path exist(file) then delete file file
   open to write 1, file
   for i = start to finish
      write string 1, __textLines$(i)
   next i
   close file 1
 
 
   `if path exist(file) then delete file file
   `rename file tempFile$, file
 
endfunction
 
 
 
REM ************************************
REM Prompts user with an open dialog box
REM Then attempts to open selected file
REM ************************************
function openDialog()
   file$ = removeTrailingSpaces$(_open_save("Text File (*.txt)|*.txt|All Files (*.*)|*.*|",get dir$(),"Open File","*.*",1))
   if mid$(file$,1) <> "!" then openFile(file$)
endfunction
 
 
 
REM ****************
REM open a text file
REM ****************
function openFile(file as string)
 
   rem local variables
   fileLoaded = 0
   maxWidth = 0
   currentTextIndex = array count(__textLines$())+1
 
   if file = NEW_FILE$
      array insert at bottom __textLines$()
      maxWidth = 1
      fileLoaded = TRUE
   endif
 
   rem does the file exist
   if fileLoaded = FALSE and path exist(file) = TRUE
      rem make sure this is a text file
      `if lower$(right$(file,4)) = ".txt"
         open to read 1, file
         rem read in all the lines from the file into the array
         while file end(1) = 0
            read string 1, z$
            if len(z$) > maxWidth then maxWidth = len(z$)
            array insert at bottom __textLines$()
            __textLines$(array count(__textLines$())) = z$
         endwhile
         close file 1
         fileLoaded = 1
      `endif
   endif
 
   rem file loaded
   if fileLoaded = TRUE
      status_message$ = "File opened: "+file
      rem store structure of file
      array insert at bottom __openFiles()
      fi = array count(__openFiles())
      __openFiles(fi).maxWidth = maxWidth-1
      __openFiles(fi).name = file
      __openFiles(fi).textIndex = currentTextIndex
      __openFiles(fi).textEnd = array count(__textLines$())
      rem create the window
      array insert at bottom __windows()
      i = array count(__windows())
      __windows(i).x = 10
      __windows(i).y = 40
      __windows(i).width = 500
      __windows(i).height = 300
      __windows(i).fileIndex = fi
      __windows(i).startingLine = __openFiles(fi).textIndex
      __windows(i).showLineNumbers = FALSE
      __windows(i).visibleLines = __windows(i).height/text height("A")
      __windows(i).visibleChars = __windows(i).width / text width("W")
      lineCount = __openFiles(fi).textEnd - __openFiles(fi).textIndex
      if lineCount = 0
         __windows(i).thumbHeight = 1
      else
         __windows(i).thumbHeight = (__windows(i).visibleLines * __windows(i).height) / lineCount
      endif
      if __openFiles(fi).maxWidth <= 0
         __openFiles(fi).maxWidth = 1
         __windows(i).thumbWidth = 1
      else
         __windows(i).thumbWidth = ((__windows(i).width/text width("A"))*__windows(i).width) / __openFiles(fi).maxWidth
      endif
      if __windows(i).thumbHeight < __windows(i).height then __windows(i).showVertical = TRUE
      if __windows(i).thumbWidth < __windows(i).width then __windows(i).showHorizontal = TRUE
   endif
endfunction
 
 
 
REM *************************************
REM copies selected text to the clipboard
REM from the currently active window
REM *************************************
function copyText()
   selectionFlag = 1
   if _selection.start.row = _selection.finish.row and _selection.start.char = _selection.finish.char then selectionFlag = 0
   if _selection.start.char > _selection.finish.char then selectionFlag = 0
 
   copy$ = ""
   if selectionFlag = 1
      `if _selection.start.row = _selection.finish.row
      for i = _selection.start.row to _selection.finish.row
         t$ = __textLines$(i)
         a = 1
         b = len(t$)
         if i = _selection.start.row
            a = _selection.start.char
            if a > 1 then a = a+1
         endif
         if i = _selection.finish.row : b = _selection.finish.char : newLine$ = "" : else : newLine$ = chr$(10) : endif
         copy$ = copy$ + substring$(t$,a,b) + newLine$
      next i
   endif
   write to clipboard copy$
endfunction
 
 
 
REM ****************************************
REM pastes contents of clipboard into window
REM at the cursor's position
REM BUGGY!!! why?
REM ****************************************
function pasteText()
   rem focused window is always at end of array
   index = array count(__windows())
   fileIndex = __windows(index).fileIndex
   textIndex = __openFiles(fileIndex).textIndex
   caret = __windows(index).caretPos
   row = __windows(index).selectedRow
 
   cb$ = get clipboard$()
   t$ = left$(__textLines$(row),caret)
   e$ = right$(__textLines$(row),len(__textLines$(row))-caret)
   `__textLines$(row) = t$ + cb$
 
 
   for i = 1 to len(cb$)
      c$ = mid$(cb$,i)
      if c$ = chr$(10) OR c$ = chr$(13)
         insertLine(fileIndex, t$, row)
         t$ = ""
         inc row
      else
         t$ = t$ + c$
      endif
   next i
 
   if t$ <> "" then insertLine(fileIndex, t$, row)
 
   __textLines$(row) = __textLines$(row) + e$
 
endfunction
 
 
function handleStatusBar()
   sh = screen height()
   sw = screen width()
   size = 16
   ink rgb(192,192,192),0
   box 0,sh-size,sw,sh
 
   ink 0,0
   line 0,sh-size,sw,sh-size
   line 0,sh-size,0,sh
   text 10,sh-size,status_message$
 
endfunction
 
 
REM *******************
REM draws a text window
REM *******************
function _drawWindow(index as integer)
   x = __windows(index).x
   y = __windows(index).y
   width = __windows(index).width
   height = __windows(index).height
   thumbX = __windows(index).thumbX
   thumbY = __windows(index).thumbY
   fileIndex = __windows(index).fileIndex
   textIndex = __openFiles(fileIndex).textIndex
   lineCount = __openFiles(fileIndex).textEnd - textIndex
   maxWidth = __openFiles(fileIndex).maxWidth
   lineHeight = text height("A")
   charWidth = text width("A")
   visibleChars = __windows(index).visibleChars
   visibleLines = __windows(index).visibleLines
   thumbHeight = __windows(index).thumbHeight
   thumbWidth = __windows(index).thumbWidth
   startingChar = __windows(index).startingChar
 
 
   displayName$ = __openFiles(fileIndex).name
   if text width(displayName$) > width
      t = width/charWidth - 3
      displayName$ = left$(displayName$,t)+"..."
   endif
 
   rem title bar
   if index < array count(__windows())
      c1 = rgb(192,192,192)
      c2 = rgb(128,128,128)
   else
      c1 = rgb(10,36,106)
      c2 = rgb(166,202,240)
   endif
   box x,y-TITLEBARSIZE,x+width+SCROLLBARSIZE,y,c1,c2,c1,c2
   ink rgb(225,225,225),0
   text x+2,y-TITLEBARSIZE,displayName$
 
 
   rem scrollbars
   rem vertical
   rem track
   ink rgb(192,192,192),0
   box x+width,y,x+width+SCROLLBARSIZE,y+height
   rem thumb
   if __windows(index).showVertical = TRUE
      ink rgb(128,128,128),0
      box x+width,y+thumbY,x+width+SCROLLBARSIZE,y+thumbY+thumbHeight
      ink rgb(200,200,200),0
      line x+width,y+thumbY,x+width+SCROLLBARSIZE,y+thumbY
      line x+width,y+thumbY,x+width,y+thumbY+thumbHeight
      ink rgb(40,40,40),0
      line x+width+SCROLLBARSIZE,y+thumbY,x+width+SCROLLBARSIZE,y+thumbY+thumbHeight
      line x+width,y+thumbY+thumbHeight,x+width+SCROLLBARSIZE,y+thumbY+thumbHeight
   endif
   rem horizontal
   rem track
   ink rgb(192,192,192),0
   box x,y+height,x+width,y+height+SCROLLBARSIZE
   rem thumb
   if __windows(index).showHorizontal = TRUE
      ink rgb(128,128,128),0
      box x+thumbX,y+height,x+thumbX+thumbWidth,y+height+SCROLLBARSIZE
      ink rgb(200,200,200),0
      line x+thumbX,y+height,x+thumbX+thumbWidth,y+height
      line x+thumbX,y+height,x+thumbX,y+height+SCROLLBARSIZE
      ink rgb(40,40,40),0
      line x+thumbX,y+height+SCROLLBARSIZE,x+thumbX+thumbWidth,y+height+SCROLLBARSIZE
      line x+thumbX+thumbWidth,y+height,x+thumbX+thumbWidth,y+height+SCROLLBARSIZE
   endif
   rem lower corner where 2 scrollbars meet
   ink rgb(128,128,128),0
   box x+width,y+height,x+width+SCROLLBARSIZE,y+height+SCROLLBARSIZE
 
   rem background
   ink rgb(208,219,219),0
   box x,y,x+width,y+height
   rem background shadow
   ink rgb(25,25,25),0
   box x+4,y+height+SCROLLBARSIZE,x+width+SCROLLBARSIZE+4,y+height+SCROLLBARSIZE+4
   box x+width+SCROLLBARSIZE,y-TITLEBARSIZE+4,x+width+SCROLLBARSIZE+4,y+height+SCROLLBARSIZE
 
 
   rem if show line numbers, draw the border
   if __windows(index).showLineNumbers = TRUE
      tOffset = text width(str$(lineCount)+" ")+4
      box x,y,x+tOffset-4,y+height,rgb(208,219,219),rgb(208,219,219),rgb(160,171,171),rgb(160,171,171)
      ink rgb(128,128,128),0
      box x+tOffset-5,y,x+tOffset-4,y+height
      alignSize = len(str$(lineCount))
   else
      tOffset = 2
   endif
 
 
   selectionFlag = 1
   if _selection.start.row = _selection.finish.row and _selection.start.char = _selection.finish.char then selectionFlag = 0
   if _selection.start.char > _selection.finish.char then selectionFlag = 0
 
 
   rem the text routine
   startingLine = __windows(index).startingLine
   for i = startingLine to startingLine + visibleLines-1
      L = i - startingLine
      if i <= __openFiles(fileIndex).textEnd
         rem display line number border
         if __windows(index).showLineNumbers = TRUE then text x+2,y+L*lineHeight, justify$(str$(i-textIndex+1),alignSize,0)
 
         rem get visible text
         if i > 0 and i <= array count(__textLines$()) then t$ = substring$(__textLines$(i), startingChar,startingChar+visibleChars)
 
         rem reset text color for the line to be displayed
         ink 0,0
         rem draw selection boxes
         if selectionFlag = 1
            rem if this line is part of the selection
            if i >= _selection.start.row and i <= _selection.finish.row
               sy1 = y+L*lineHeight
               rem if this entire line should be highlighted
               if i > _selection.start.row and i < _selection.finish.row
                  sx1 = x+tOffset
                  sx2 = sx1+len(t$)*charWidth
                  ink rgb(0,0,255),0
                  box sx1,sy1,sx2,sy1+lineHeight
                  ink rgb(255,255,255),0
                  text x+tOffset,sy1, t$
               else `i is either first or last row of selection
                  rem if selection is all on same line
                  if _selection.start.row = _selection.finish.row
                     sx1 = x+tOffset+_selection.start.char*charWidth
                     sx2 = x+tOffset+_selection.finish.char*charWidth
                     ink rgb(0,0,255),0
                     box sx1,sy1,sx2,sy1+lineHeight
                     ink rgb(255,255,255),0
                     c1 = _selection.start.char
                     c2 = _selection.finish.char
                     if _selection.start.char < startingChar then c1 = startingChar
                     if _selection.finish.char > startingChar+visibleChars then c2 = startingChar+visibleChars
                     middle$ = substring$(__textLines$(i), c1, c2)
                     edge = 1
                     if _selection.start.char = startingChar then edge = 0
                     text x+tOffset+(_selection.start.char-startingChar-edge)*charWidth,sy1,middle$
                     begin$ = substring$(__textLines$(i),startingChar,_selection.start.char)
                     last$ = substring$(__textLines$(i),_selection.finish.char+1,startingChar+visibleChars)
                     ink 0,0
                     text x+tOffset,sy1,begin$
                     text x+tOffset+(len(middle$+begin$)-edge)*charWidth,sy1,last$
                  else
                     rem first row of a multi-line selection
                     if i = _selection.start.row
                        sx1 = x+tOffset+_selection.start.char*charWidth
                        sx2 = x+tOffset+len(t$)*charWidth
                        begin$ = substring$(__textLines$(i),startingChar,_selection.start.char)
                        last$ = substring$(__textLines$(i),_selection.start.char+1,startingChar+visibleChars)
                        sx1 = x+tOffset+len(begin$)*charWidth
                        sx2 = x+tOffset+len(t$)*charWidth
                        ink rgb(0,0,255),0
                        box sx1,sy1,sx2,sy1+lineHeight
                        ink rgb(255,255,255),0
                        text x+tOffset+len(begin$)*charWidth,sy1,last$
                        ink 0,0
                        text x+tOffset,sy1,begin$
                     else `last row of a multi-line selection
                        sx1 = x+tOffset
                        sx2 = x+tOffset+_selection.finish.char*charWidth
                        begin$ = substring$(__textLines$(i),startingChar,_selection.finish.char)
                        last$ = substring$(__textLines$(i),_selection.finish.char+1,startingChar+visibleChars)
                        sx1 = x+tOffset
                        sx2 = x+tOffset+len(begin$)*charWidth
                        ink rgb(0,0,255),0
                        box sx1,sy1,sx2,sy1+lineHeight
                        ink rgb(255,255,255),0
                        text x+tOffset,sy1,begin$
                        ink 0,0
                        text x+tOffset+len(begin$)*charWidth,sy1,last$
                     endif
                  endif
               endif
            else
               rem display text
               text x+tOffset,y+L*lineHeight, t$
            endif
         else
            rem display text
            text x+tOffset,y+L*lineHeight, t$
         endif
 
 
      endif
   next i
 
endfunction
 
 
 
 
REM ********************
REM handles UI of window
REM ********************
function _handleWindowUI(index as integer)
   x = __windows(index).x
   y = __windows(index).y
   width = __windows(index).width
   height = __windows(index).height
   thumbX = __windows(index).thumbX
   thumbY = __windows(index).thumbY
   thumbHeight = __windows(index).thumbHeight
   thumbWidth = __windows(index).thumbWidth
   fileIndex = __windows(index).fileIndex
   textIndex = __openFiles(fileIndex).textIndex
   lineCount = __openFiles(fileIndex).textEnd - textIndex
   maxWidth = __openFiles(fileIndex).maxWidth
   lineHeight = text height("A")
   visibleLines = __windows(index).visibleLines
   visibleChars = __windows(index).visibleChars
   grabbedWindow = 0
 
   if thumbY < 0 then thumbY = 0
   if thumbY > height-thumbHeight then thumbY = height-thumbHeight
   __windows(index).thumbY = thumbY
 
   if mouseclick() = 1
      rem handle vertical scrollbar
      if __windows(index).showVertical = TRUE
         if CLICK_FLAG = 0 and mouseWithin(x+width,y+thumbY,x+width+SCROLLBARSIZE,y+thumbY+thumbHeight)
            __windows(index).thumbYFlag = TRUE
            __windows(index).thumbOffsetY = thumbY - mousey()
            CLICK_FLAG = 1
         endif
         if __windows(index).thumbYFlag = TRUE
            thumbY = mousey() + __windows(index).thumbOffsetY
            if thumbY < 0 then thumbY = 0
            if thumbY > height-thumbHeight then thumbY = height-thumbHeight
            __windows(index).thumbY = thumbY
            __windows(index).startingLine = textIndex + ((lineCount-visibleLines+1)*thumbY) / (height-thumbHeight)
         endif
      endif
 
      rem handle horizontal scrollbar
      if __windows(index).showHorizontal = TRUE
         if CLICK_FLAG = 0 and mouseWithin(x+thumbX,y+height,x+thumbX+thumbWidth,y+height+SCROLLBARSIZE)
            __windows(index).thumbXFlag = TRUE
            __windows(index).thumbOffsetX = thumbX - mousex()
            CLICK_FLAG = 1
         endif
         if __windows(index).thumbXFlag = TRUE
            thumbX = mousex() + __windows(index).thumbOffsetX
            if thumbX < 0 then thumbX = 0
            if thumbX > width-thumbWidth then thumbX = width-thumbWidth
            __windows(index).thumbX = thumbX
            __windows(index).startingChar = ((maxWidth-visibleChars)*thumbX) / (width-thumbWidth)
         endif
      endif
 
      rem handle titlebar
      if CLICK_FLAG = 0 and mouseWithin(x,y-TITLEBARSIZE,x+width+SCROLLBARSIZE,y)
         __windows(index).titleFlag = TRUE
         __windows(index).titleOffsetX = x - mousex()
         __windows(index).titleOffsetY = y - mousey()
         CLICK_FLAG = 1
      endif
      if __windows(index).titleFlag = TRUE
         __windows(index).x = mousex() + __windows(index).titleOffsetX
         __windows(index).y = mousey() + __windows(index).titleOffsetY
      endif
 
      rem handle resizing
      if CLICK_FLAG = 0 and mouseWithin(x+width,y+height,x+width+SCROLLBARSIZE,y+height+SCROLLBARSIZE)
         __windows(index).resizeFlag = TRUE
         __windows(index).resizeOffsetX = x+width - mousex()
         __windows(index).resizeOffsetY = y+height - mousey()
         CLICK_FLAG = 1
      endif
      if __windows(index).resizeFlag = TRUE
         __windows(index).width = mousex() - __windows(index).x + __windows(index).resizeOffsetX
         __windows(index).height = mousey() - __windows(index).y + __windows(index).resizeOffsetY
         if __windows(index).width < MIN_WIDTH then __windows(index).width = MIN_WIDTH
         if __windows(index).height < MIN_HEIGHT then __windows(index).height = MIN_HEIGHT
         _resizeWindow(index)
      endif
 
      rem if windows was clicked on, make it top component
      if CLICK_FLAG = 0 and mouseWithin(x,y-TITLEBARSIZE,x+width+SCROLLBARSIZE,y+height)
         grabbedWindow = index
         `CLICK_FLAG = 1
      endif
 
   else
      __windows(index).thumbXFlag = FALSE
      __windows(index).thumbYFlag = FALSE
      __windows(index).titleFlag = FALSE
      __windows(index).resizeFlag = FALSE
   endif
 
endfunction grabbedWindow
 
 
 
REM ******************************
REM this is called whenever a
REM window's size has been changed
REM recalculates scrollbar and
REM viewing sizes
REM ******************************
function _resizeWindow(index as integer)
   fi = __windows(index).fileIndex
   lineCount = __openFiles(fi).textEnd - __openFiles(fi).textIndex + 1
   __windows(index).visibleLines = __windows(index).height/text height("A")
   __windows(index).thumbHeight = (__windows(index).visibleLines * __windows(index).height) / lineCount
   __windows(index).thumbWidth = ((__windows(index).width/text width("A"))*__windows(index).width) / __openFiles(fi).maxWidth
   __windows(index).visibleLines = __windows(index).height/text height("A")
   __windows(index).visibleChars = __windows(index).width / text width("W")
 
   if __windows(index).thumbHeight < __windows(index).height
      __windows(index).showVertical = TRUE
   else
      __windows(index).showVertical = FALSE
   endif
   if __windows(index).thumbWidth < __windows(index).width
      __windows(index).showHorizontal = TRUE
   else
      __windows(index).showHorizontal = FALSE
   endif
 
   `__windows(index).thumbX = (__windows(index).startingChar*(__windows(index).width - __windows(index).thumbWidth)) / (__openFiles(fi).maxWidth - __windows(index).visibleChars)
 
endfunction
 
 
 
REM ***************************
REM Create a new drop-down menu
REM ***************************
function addMenu(name as string)
   m as Menu
   m.name = name
   array insert at bottom menus()
   count = array count(menus())
   menus(count) = m
endfunction count
 
 
REM *****************************
REM add a menu item to menu 'pid'
REM *****************************
function addMenuItem(pid as integer, item as string, enabled as boolean, check as integer)
   m as MenuItem
   m.parentID = pid
   m.item = item
   m.enabled = enabled
   m.check = check
   array insert at bottom menuItems()
   menuItems(array count(menuItems())) = m
 
   rem make sure menu is drawn wide enough to handle this item's name
   width = text width(item)+6
   if width > menus(pid).width then menus(pid).width = width
 
   menus(pid).count = menus(pid).count + 1
endfunction
 
 
 
REM ********************
REM Handles the menus UI
REM ********************
function _handleMenus$(mc as integer)
   v$ = ""
   offsetX = 0
   active = -1
   activeOffset = 0
   rem text height, vertical spacing
   tw = 16
 
 
   rem draw menu bar
   ink rgb(192,192,192),0
   box 0,0,screen width(),tw
 
   rem clock box
   tx = screen width() - (text width("99:99 :AM")+4)
   ink 0,0
   text tx+2,1,getTime$()
   line tx,1,screen width()-1,1
   line tx,1,tx,tw-1
   ink rgb(255,255,255),0
   line tx,tw-1,screen width()-1,tw-1
   line screen width()-1,1,screen width()-1,tw-1
 
   for i = 0 to array count(menus())
      width = text width(menus(i).name)
 
      if mc = 1
         if mousex() >= offsetX and mousex() <= offsetX+width+6 and mousey() >= 0 and mousey() <= tw
            if  _mouseFlag = 0
                _mouseFlag = 1
               if menus(i).active = 0
                  menus(i).active = 1
               else
                  menus(i).active = 0
               endif
               for t = 0 to array count(menus())
                  if t <> i then menus(t).active = 0
               next t
            endif
         endif
      endif
 
      if menus(i).active = 1
         active = i
         activeOffset = offsetX
         ink rgb(0,180,250),0
         box offsetX,0,offsetX+width+6,tw
      else
         `ink rgb(192,192,192),0
      endif
      `box offsetX,0,offsetX+width+6,tw
      ink 0,0
      text offsetX+3,0,menus(i).name
      offsetX = offsetX + width + 6
   next i
 
 
   if active > -1
      ink rgb(192,192,192),0
      box activeOffset,tw,activeOffset+menus(active).width,tw+menus(active).count*tw
      offsetY = 0
      ink 0,0
      for i = 0 to array count(menuItems())
         if menuItems(i).parentID = active
            inc offsetY
            if mousex() > activeOffset and mousex() < activeOffset+menus(active).width and mousey() > offsetY*tw and mousey() < (offsetY+1)*tw
               ink rgb(0,180,250),0
               box activeOffset+1,offsetY*tw+1,activeOffset+menus(active).width-1,(offsetY+1)*tw-1
               rem if this item was clicked
               if mc = 1
                  if _mouseFlag = 0
                     _mouseFlag = 1
                     if menuItems(i).enabled = 1
                        v$ = menus(active).name + "-" + menuItems(i).item
                        menus(active).active = 0
                        exitfunction v$
                     endif
                  endif
               endif
            endif
            if menuItems(i).enabled = 1
               ink 0,0
            else
               ink rgb(120,120,120),0
            endif
            text activeOffset+3,offsetY*tw,menuItems(i).item
         endif
      next i
   endif
 
endfunction v$
 
 
 
REM **************************************
REM Close the active window
REM technically, i should be releasing
REM all the resources used by this window,
REM but im lazy and its 5:30am
REM **************************************
function closeWindow()
   array delete element __windows(), array count(__windows())
 
endfunction
 
 
REM ****************************************
REM Counts words (3 or more characters)
REM and displays the total in the status bar
REM ****************************************
function countWords()
   fileIndex = __windows(array count(__windows())).fileIndex
   start = __openFiles(fileIndex).textIndex
   finish = __openFiles(fileIndex).textEnd
   total = 0
 
   for i = start to finish
      t$ = __textLines$(i)
      temp$ = ""
      for j = 1 to len(t$)
         c$ = mid$(t$,j)
         if c$ = " "
            if len(temp$) > 2 then inc total
            temp$ = ""
         else
            temp$ = temp$ + c$
         endif
      next j
      if len(temp$) > 2 then inc total
   next i
 
   status_message$ = "Word count: "+str$(total)
endfunction
 
 
 
REM ****************************************
REM Counts number of characters
REM and displays the total in the status bar
REM ****************************************
function countCharacters()
   fileIndex = __windows(array count(__windows())).fileIndex
   start = __openFiles(fileIndex).textIndex
   finish = __openFiles(fileIndex).textEnd
   total = 0
 
   for i = start to finish
      inc total, len(__textLines$(i))
   next i
 
   status_message$ = "Character count: "+str$(total)
endfunction
 
 
 
 
REM ****************************
REM returns a substring of 's'
REM beginning and ending indices
REM are both inclusive
REM ****************************
function substring$(s as string, bIndex, eIndex)
   if eIndex < 0 then exitfunction ""
   s = left$(s,eIndex)
   if len(s)-(bIndex-1) < 0 then exitfunction ""
   s = right$(s, len(s)-(bIndex-1))
endfunction s
 
 
 
REM *******************************
REM Returns a string of the current
REM time in 12hour
REM *******************************
function getTime$()
   hour$ = left$(get time$(), 2)
   v = val(hour$)
   day$ = " am"
   if v > 11
      day$ = " pm"
      if v > 12 then hour$ = str$(v-12)
   endif
   if len(hour$) < 2 then hour$ = " "+right$(hour$,1)
 
   min$ = right$(left$(get time$(),5), 2)
   time$ = hour$+":"+min$+day$
endfunction time$
 
 
REM **********************
REM Justifies text
REM 0 for right, 1 for left
REM ***********************
function justify$(s as string, length as integer, alignment as integer)
   if alignment = 0 then s = space$(length - len(s)) + s
   if alignment = 1 then s = s + space$(length - len(s))
endfunction s
 
 
REM ****************************
REM returns 1 if mouse is within
REM the defined box area
REM ****************************
function mouseWithin(x1,y1,x2,y2)
   if mousex() > x1 and mousex() < x2 and mousey() > y1 and mousey() < y2 then exitfunction 1
endfunction 0
 
 
REM ******************************************
REM removes trailing whitespaces from a string
REM ******************************************
function removeTrailingSpaces$(s as string)
   L = len(s)
   for i = L to 1 step -1
      if mid$(s,i) <> " " then exitfunction left$(s,i)
   next i
endfunction ""
 
 
 
 
 
REM ********************************************************
REM *                                                      *
REM *                    Windows Dialogs                   *
REM *                                                      *
REM ********************************************************
 
 
Function _open_save(filter As String,initdir As String,dtitle As String,defext As String,open As Boolean)
   `filter = "Text Documents ( *.txt )|*.txt|All Files ( *.* )|*.*|"
   `initdir = "C:"
   `dtitle = "Open ~ Test"
   `defext = "txt"
   `open = 1 For Open Dialogu, 0 for save dialogue
 
 
   `Get DLL numbers
   user32 As Integer
   comdlg32 As Integer
 
   `Load in required DLL's
   user32 = _find_fee_dll()
   Load DLL "user32.dll",user32
   comdlg32 = _find_fee_dll()
   Load DLL "comdlg32.dll",comdlg32
 
 
   `Get handle ( unique ID ) to the calling ( this ) window
   hwnd As DWord
   hwnd = Call DLL(user32,"GetActiveWindow")
 
 
   `Unload DLL as it is no longer needed
   Delete DLL user32
 
 
   `Get the Memblock Number
   OPENFILENAME As Integer
   OPENFILENAME = _find_free_mem()
   `Make The Memblock containing the OPENFILENAME structure
   Make MemBlock OPENFILENAME,76
 
 
   `Get the pointer to the just created Structure
   lpofn As DWord
   lpofn = Get MemBlock Ptr(OPENFILENAME)
 
 
   `Declare temp variables to hold data for OPENFILENAME structure
   size As Integer
   filebuffer As String
   filebufferptr As DWord
   flags As DWord
 
   filter = filter + "|"
   initdir = initdir + "|"
   dtitle = dtitle + "|"
   defext = defext + "|"
   filebuffer = "|" + Space$(255) + "|"
   filebufferptr = _get_str_ptr(filebuffer)
   flags = 0x00001000 || 0x00000004 || 0x00000002
   size = 0
 
   Write MemBlock DWord OPENFILENAME,0,76                     : `lStructSize
   Write MemBlock DWord OPENFILENAME,4,hwnd                   : `hwndOwner
   `Write MemBlock DWord OPENFILENAME,8,NULL                   : `hInstance
   Write MemBlock DWord OPENFILENAME,12,_get_str_ptr(filter)  : `lpstrFilter
   `Write MemBlock DWord OPENFILENAME,16,0                     : `lpstrCustomFilter
   `Write MemBlock DWord OPENFILENAME,20,NULL                  : `nMaxCustFilter
   Write MemBlock DWord OPENFILENAME,24,1                     : `nFilterIndex
   Write MemBlock DWord OPENFILENAME,28,filebufferptr         : `lpstrFile
   Write MemBlock DWord OPENFILENAME,32,256                   : `nMaxFile
   `Write MemBlock DWord OPENFILENAME,36,0                     : `lpstrFileTitle
   `Write MemBlock DWord OPENFILENAME,40,NULL                  : `nMaxFileTitle
   Write MemBlock DWord OPENFILENAME,44,_get_str_ptr(initdir) : `lpstrInitialDir
   Write MemBlock DWord OPENFILENAME,48,_get_str_ptr(dtitle)  : `lpstrTitle
   Write MemBlock DWord OPENFILENAME,52,flags                 : `Flags
   `Write MemBlock Word OPENFILENAME,56,NULL                   : `nFileOffset
   `Write MemBlock Word OPENFILENAME,58,NULL                   : `nFileExtension
   Write MemBlock DWord OPENFILENAME,60,_get_str_ptr(defext)  : `lpstrDefExt
   `Write MemBlock DWord OPENFILENAME,64,NULL                  : `lCustData
   `Write MemBlock DWord OPENFILENAME,68,NULL                  : `lpfnHook
   `Write MemBlock DWord OPENFILENAME,72,0                     : `lpTemplateName
 
 
   `Call the Command to open the dialouge
   retval As DWord
   If open
      retval = Call DLL(comdlg32,"GetOpenFileNameA",lpofn)
   Else
      retval = Call DLL(comdlg32,"GetSaveFileNameA",lpofn)
   EndIf
 
   `Check if it was sucecfull
   If retval <> 0
      code$ = _get_str(filebufferptr,256)
   Else
      retval = Call DLL(comdlg32,"CommDlgExtendedError")
      Select retval
         Case 0xFFFF : code$ = "!The dialog box could not be created. The common dialog box function's call to the DialogBox function failed. For example, this error occurs if the common dialog box call specifies an invalid window handle." : EndCase
         Case 0x0006 : code$ = "!The common dialog box function failed to find a specified resource." : EndCase
         Case 0x0004 : code$ = "!The ENABLETEMPLATE flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a corresponding instance handle." : EndCase
         Case 0x0002 : code$ = "!The common dialog box function failed during initialization. This error often occurs when sufficient memory is not available." : EndCase
         Case 0x000B : code$ = "!The ENABLEHOOK flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a pointer to a corresponding hook procedure." : EndCase
         Case 0x0008 : code$ = "!The common dialog box function failed to lock a specified resource." : EndCase
         Case 0x0003 : code$ = "!The ENABLETEMPLATE flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a corresponding template." : EndCase
         Case 0x0007 : code$ = "!The common dialog box function failed to load a specified string." : EndCase
         Case 0x0001 : code$ = "!The lStructSize member of the initialization structure for the corresponding common dialog box is invalid." : EndCase
         Case 0x0005 : code$ = "!The common dialog box function failed to load a specified string." : EndCase
         Case 0x3003 : code$ = "!The buffer pointed to by the lpstrFile member of the OPENFILENAME structure is too small for the file name specified by the user. The first two bytes of the lpstrFile buffer contain an integer value specifying the size, in TCHARs, required to receive the full name." : EndCase
         Case 0x0009 : code$ = "!The common dialog box function was unable to allocate memory for internal structures." : EndCase
         Case 0x3002 : code$ = "!A file name is invalid." : EndCase
         Case 0x000A : code$ = "!The common dialog box function was unable to lock the memory associated with a handle." : EndCase
         Case 0x3001 : code$ = "!An attempt to subclass a list box failed because sufficient memory was not available." : EndCase
         Case Default : code$ = "!WHOOPS!" : EndCase
      EndSelect
   EndIF
 
   Delete DLL comdlg32
 
EndFunction code$
 
 
 
Function _get_str_ptr(pstr As String)
   `pstr$ should be a "|" ( NULL ) seperated string.
 
   memnum As Integer
   strlen As Integer
   char As Byte
   memptr As DWord
   strptr As DWord
 
   memnum = _find_free_mem()
   strlen = Len(pstr)
 
   Make MemBlock memnum,strlen
 
   For i = 1 To strlen
      If Mid$(pstr,i) = "|"
         char = 0
      Else
         char = Asc(Mid$(pstr,i))
      EndIf
      Write MemBlock Byte memnum,(i - 1),char
   Next i
 
   memptr = Get MemBlock Ptr(memnum)
 
   strptr = Make Memory(strlen)
 
   Copy Memory strptr,memptr,strlen
 
   Delete MemBlock memnum
 
 
EndFunction strptr
 
 
 
Function _get_str(strptr As DWord,strsize As Integer)
   `strptr is the pointer returned by _get_str_ptr()
   `strsize is the Integer length of the string specified by the pointer
 
   memnum As Integer
   memptr As DWord
   str As String
   char As String
 
   memnum = _find_free_mem()
 
   Make MemBlock memnum,strsize
 
   memptr = Get MemBlock Ptr(memnum)
 
   Copy Memory memptr,strptr,strsize
 
   For i = 1 To strsize
      str = str + Chr$(MemBlock Byte(memnum,i - 1))
   Next i
 
EndFunction str
 
 
 
Function _find_fee_dll()
   retval = 0
   Repeat
      Inc retval
   Until DLL Exist(retval) = 0
EndFunction retval
 
 
 
Function _find_free_mem()
   retval = 50
   Repeat
      Inc retval
   Until MemBlock Exist(retval) = 0
EndFunction retval