-- FileIOFunktionen
-----------------------------------
-- CREATED:
-- c03 Alex da Franca -- alex@farbflash.de
-- PROPERTIES:
--!memberProperties: [#name: "FileIOFunktionen", #scripttype: #parent, #scriptSyntax: #lingo, #comments: "~/Documents/Scripts/lingo/FileIOFunktionen.ls"]
--
-- DESCRIPTION: FileIO Handlers
-- -
--
-- REQUIRES:
-- (Prerequisites)
--
-- USAGE:
-- -
--
-- EXAMPLE:
-- -
-----------------------------------

on _____________________PROPERTY_DECLARATION me
end
-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
property ancestor

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
on ___________________STANDARD_EVENTS me
end
-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on new me
  Script_Root_Object = member("Script_Root_Object")
  if ilk(Script_Root_Object) = #member then
    if Script_Root_Object.type = #script then
      ancestor = new(script "Script_Root_Object")
      mSetScriptName me, "FileIOFunktionen"
    end if
  end if
  return me
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
on ___________________PUBLIC_EVENTS me
end
-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-- xxxxxxxxxxxxxxxxxx Read text in (if no path is provided show open dialog)
-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetTextFromFile me, pfad, readByteArray, useCharSet
  retval = ""
  if the runmode contains "Plugin" then return retval
  
  fio = new(xtra "fileio")
  if not objectP(fio) then return retval
  
  useCharSet = string(useCharSet)
  if length(useCharSet) > 0 then
    if xscr().mGetVersionNumber() > 11.4 then
      ------------- don't need to check whether the given charset is supported
      ------------- as it is simply ignored, if it isn't
      ------------- and it also gets reset so that the next instance of fileio
      ------------- uses the default utf-8 again
      --      installedCharSets = _system.getInstalledCharSets()
      --      if installedCharSets.getPos(useCharSet) > 0 then fio.setCharSet(useCharSet)
      fio.setCharSet(useCharSet)
    end if
  end if
  
  if (voidP(pfad) or (pfad = "")) then pfad = mGetFilePathFromUser(me)
  
  if ilk(pfad) = #string then
    if pfad.length > 0 then
      fio.openFile(pfad, 1)
      if fio.status() = 0 then
        if readByteArray = 1 then retval = fio.readByteArray(fio.getlength())
        else retval = fio.readFile()
        fio.closeFile()
      end if
    end if
  end if
  fio = void
  return retval
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetByteArrayFromFile me, thePath
  return mGetTextFromFile(me, thePath, (xscr().mGetVersionNumber() > 11.49))
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-- xxxxxxxxxxxxxxxxxx Read text asynchron -> works in projector, authoring AND shockwave
-- requires parentscript "NetTextReaderPS"
-- example:

-- paramList = [:]
-- paramList[#theURL] = mGetRelativePath("someFile.txt") -- "http://www.ff.com/somefile.txt" -- ABSOLUTE PATH !!
-- paramList[#handler] = #callbackFromGetText
-- paramList[#target] = instance
-- -- optional:
-- paramList[#theTimeOut] = 4000 -- milliseconds until operation times out
-- paramList[#progressHandler] = #progresscallbackFromGetText -- event sent whenever the percent done changes
-- paramList[#isByteArray] = 0 -- boolean value, only D11
-- paramList[#charset] = "windows-1252" -- string, only D11
-- -- paramList[#customdata] = "whatever you need"
-- xscr(#FileIOFunktionen).mGetTextFromFileAsync(paramList)

--
--on callbackFromGetText me, paramList
--  theTextResult = string(paramList.getaprop(#theTextResult))
--  if length(theTextResult) > 0 then
--    -- do something with theTextResult
--  else
--    alert string(paramList.getaprop(#theNetError)
--  end if
--end


on mGetTextFromFileAsync me, paramList
  fname = string(paramList.getaprop(#theURL))
  internetLink = (offset("://", fname) > 0)
  if not(internetLink) then internetLink = (fname starts "www.")
  if the runmode contains "plugin" or internetLink then
    
    --    scr = xscr().mGetInstance("NetLingoManagerPS")
    --    if ilk(scr) = #instance then
    --      scr.mStartNetOP(paramList)
    --    else
      scr = xscr().mGetInstance("NetTextReaderPS")
    if ilk(scr) = #instance then
      scr.mAddJob(paramList)
    else
      paramList.setaprop(#theTextResult, "")
      paramList.setaprop(#theNetError, "Script NetTextReaderPS not found")
      call(paramList.getaprop(#handler), [paramList.getaprop(#target)], paramList)
    end if
    --    end if
  else
    paramList.setaprop(#theTextResult, mGetTextFromFile(me, paramList.getaprop(#theURL), paramList[#isByteArray], paramList[#charset]))
    theResult = xscr().mDoDelayedCallback(paramList)
    if theResult <> 1 then call(paramList.getaprop(#handler), [paramList.getaprop(#target)], paramList)
  end if
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetByteArrayFromFileAsync me, paramList
  paramList[#isByteArray] = 1
  mGetTextFromFileAsync me, paramList
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-- xxxxxxxxxxxxxxxxxx Write text out to a file
-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mSaveToTextFile me, theText, pfad, theTitle, theDefaultName, startfolder, useCharSet
  retval = 0
  
  if ilk(theText) <> #string then return retval
  
  if the runmode contains "plugin" then
    if ilk(theDefaultName) <> #string then theDefaultName = "Untitled"
    gotonetpage("mailto:alex@farbflash.de?subject="&theDefaultName&"&body="&urlencode(theText))
    return 1
  else
    fio = new(xtra "fileio")
    if not objectP(fio) then return retval
    
    useCharSet = string(useCharSet)
    if length(useCharSet) > 0 then
      if xscr().mGetVersionNumber() > 11.4 then
        ------------- don't need to check whether the given charset is supported
        ------------- as it is simply ignored, if it isn't
        ------------- and it also gets reset so that the next instance of fileio
        ------------- uses the default utf-8 again
        --      installedCharSets = _system.getInstalledCharSets()
        --      if installedCharSets.getPos(useCharSet) > 0 then fio.setCharSet(useCharSet)
        fio.setCharSet(useCharSet)
      end if
    end if
    
    
    if ilk(theTitle) <> #string then theTitle = "Save File"
    
    if ilk(theDefaultName) <> #string then theDefaultName = "Untitled"
    
    if (voidP(pfad) or (pfad = "")) then
      if call(#mCheckForXtra, mGetXScript(), "BudAPI") = 1 then
        startfolder = string(startfolder)
        
        resetUNames = 0
        if the platform contains "mac" then
        if baSysFolder("prefs") starts "/" then
          baReturnUnixNames(0)
          resetUNames = 1
        end if
        end if
        if length(startfolder) > 0 then
          pfad = baGetFilename("save", startfolder, theDefaultName, "", 524288+2+4+4194304, theTitle, false, -1, -1)
        else
        pfad = baGetFilename("save", "", theDefaultName, "", 524288+2+4+4194304, theTitle, false, -1, -1)
        end if
        
        if resetUNames = 1 then baReturnUnixNames(1)
        
      else
        pfad = fio.displaySave(theTitle, theDefaultName)
      end if
    end if
    
    if ilk(pfad) = #string then
      if pfad.length > 0 then
        
        fio.openFile(pfad, 0)
        if fio.status() = 0 then fio.delete()
        
        fio.createFile(pfad)
        if fio.status() = 0 then
          
          fio.openFile(pfad, 2)
          if fio.status() = 0 then
            
            fio.writeString(theText)
            
            --            retval = (fio.status() = 0)
            if fio.status() = 0 then retval = pfad
            
            fio.closeFile()
          end if
        end if
      end if
    end if
    
    fio = 0
    
  end if
  
  return retval
end


-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-- xxxxxxxxxxxxxxxxxx append string to file
-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


on mAppendTextToFile me, theText, pfad
  retval = 0
  
  if ilk(theText) <> #string then return retval
  
  pfad = string(pfad)
  
  olddelim = the itemdelimiter
  the itemdelimiter = the last char of the moviepath
  fname = the last item of pfad
  the itemdelimiter = olddelim
  
  if the runmode contains "plugin" then
    if not(fname.length) then fname = "Untitled.txt"
    altertext = getpref(fname)
    if voidP(altertext) then altertext = theText
    else put RETURN & theText after altertext
    setpref(fname, altertext)
    return 1
  else
    
    fio = new(xtra "fileio")
    if not objectP(fio) then return retval
    
    if pfad.length then
      
      if not xscr().mCheckFileExists(pfad) then
        if xscr().mCheckFileExists(the moviepath & pfad) then
          fio.createFile(the moviepath & fname)
        else
          theText = RETURN & theText
        end if
        fio.openFile(the moviepath & pfad, 0)
      else
        
        theText = RETURN & theText
        fio.openFile(pfad, 0)
      end if
      
    else
      pfad = the moviepath & the moviename & "_log.txt"
      
      if not xscr().mCheckFileExists(pfad) then fio.createFile(pfad)
      else theText = RETURN & theText
      
      fio.openFile(pfad, 0)
    end if
    
    if fio.status() <> 0 then
      fio = 0
      return retval
    end if
    
    fio.setPosition(fio.getLength())
    
    fio.writeString(theText)
    
    retval = (fio.status() = 0)
    
    fio.closeFile()
    fio = 0
    
  end if
  
  return retval
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mExportSelectedText me, theType
  
  cl = the activecastlib
  sel = the selection of castlib cl
  if not sel.count then exit
  memref = member(sel[1][1], cl)
  if [#text, #field].getPos(memref.type) < 1 then exit
  
  theDefaultName = memref.name
  
  theType = string(theType)
  
  if length(theType) < 1 then
    if offset(".", theDefaultName) > 1 then
      theType = theDefaultName.char[offset(".", theDefaultName) + 1 .. length(theDefaultName)]
    end if
  end if
  
  if memref.type = #field then theType = "txt"
  
  if ["txt", "rtf", "htm", "html"].getPos(theType) < 1 then theType = "txt"
  
  
  if theDefaultName = "" then theDefaultName = "Untitled." & theType
  if offset(".", theDefaultName) < 1 then put "." & theType after theDefaultName
  
  case theType of
    "rtf":
      derText = memref.rtf
    "htm", "html":
      derText = memref.html
    otherwise:
      derText = memref.text
  end case
  
  mSaveToTextFile me, derText, "", "Save file", theDefaultName
  
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetPathNameFromUser me
  return mGetFilePathFromUser(me)
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetFilePathFromUser me, startDir, defaultName, filetypes, prompt
  -----------------------------------
  -- CREATED: -
  -- ACTION: Asks the user for a path to a file and returns the filepath
  -- INPUT: <startDir> ; string ; the directory to start the file selection dialog (only if buddyApi xtra is installed)
  --        <defaultName> ; string ; pre-entered filename (only if buddyApi xtra is installed)
  --        <filetypes> ; string ; filetype filter (only if buddyApi xtra is installed)
  --        <prompt> ; string ; Caption of the dialog (only if buddyApi xtra is installed)
  -- RETURNS: string ; absolute pathname delimited by the pathdelimiter of the current platform (widnows: "\", mac: ":") or "", if user canceled the process
  -- EXAMPLE: relPath = xscr(#FileIOFunktionen).mGetFilePathFromUser(the moviepath, "soundRadius.xml", ".xml", "Please select soundradius scriptsettings")
  -----------------------------------
  
  retval = ""
  
  if the runmode contains "Plugin" then return retval
  
  if call(#mCheckForXtra, mGetXScript(), "BudAPI") = 1 then
    
    resetUNames = 0
    if the platform contains "mac" then
    if baSysFolder("prefs") starts "/" then
      baReturnUnixNames(0)
      resetUNames = 1
    end if
    end if
    
    startDir = string(startDir)
    defaultName = string(defaultName)
    filetypes = string(filetypes)
    if length(filetypes) < 1 then filetypes = "*.*"
    prompt = string(prompt)
    
    retval = baGetFilename("open", startDir, defaultName, filetypes, 524288+4+2+4194304, prompt, false, -2, -1)
    
    if resetUNames = 1 then baReturnUnixNames(1)
    
    return retval
    
  else
    
    
    fio = new(xtra "fileio")
    
    if not objectP(fio) then return retval
    
    retval = fio.displayOpen()
    
    fio = void
    
  end if
  
  return retval
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetMovieRelativePathFromUser me, startDir, defaultName, filetypes, prompt
  -----------------------------------
  -- CREATED: 14.12.2009
  -- ACTION: Asks the user for a path to a file
  --         Takes care, that the file starts with the moviepath => is WITHIN the moviepath,
  --         otherwise it calls itself until either the user selects a relative file or cancels the process.
  --         Converts path delimiters to "/" => normalize the pathdelimiter for both platforms
  -- INPUT: <startDir> ; string ; the directory to start the file selection dialog (only if buddyApi xtra is installed)
  --        <defaultName> ; string ; pre-entered filename (only if buddyApi xtra is installed)
  --        <filetypes> ; string ; filetype filter (only if buddyApi xtra is installed)
  --                               SPECIAL VALUE: can be "folder", which would not return a path to a folder,
  --                               but rather a path to a folder
  --        <prompt> ; string ; Caption of the dialog (only if buddyApi xtra is installed)
  -- RETURNS: string ; relative pathname delimited by "/" or "", if user canceled the process
  -- EXAMPLE: relPath = xscr(#FileIOFunktionen).mGetMovieRelativePathFromUser(the moviepath, "soundRadius.xml", ".xml", "Please select soundradius scriptsettings")
  -----------------------------------
  
  if filetypes = "folder" then
    searchItem = "folder"
    thePath = mGetFolderPathFromUser(me)
  else
    searchItem = "file"
    thePath = mGetFilePathFromUser(me, startDir, defaultName, filetypes, prompt)
  end if
  if length(thePath) > 0 then
    if offset(the moviepath, thePath) <> 1 then
      alert "This " & searchItem & " is NOT within the moviepath. Please choose a " & searchItem & ", which is inside the current movie's path!"
      return mGetMovieRelativePathFromUser(me, startDir, defaultName, filetypes, prompt)
    end if
    delete char 1 to length(the moviepath) of thePath
    delim = the last char of the moviepath
    if delim <> "/" then
      offs = offset(delim, thePath)
      repeat while offs > 0
        put "/" into char offs of thePath
        offs = offset(delim, thePath)
      end repeat
    end if
    if filetypes = "folder" then
      if the last char of thePath <> "/" then put "/" after thePath
      end if
    end if
    return thePath
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetFolderPathFromUser me
  retval = ""
  
  if the runmode contains "Plugin" then return retval
  
  if xscr().mCheckForXtra("BudAPI") = 1 then -- if buddy is present...
    
    resetUNames = 0
    if the platform contains "mac" then
    if baSysFolder("prefs") starts "/" then
      baReturnUnixNames(0)
      resetUNames = 1
    end if
    end if
    
    retval = baGetFolder( "", "Select a folder", 3, "", 50, 50 )
    
    if resetUNames = 1 then baReturnUnixNames(1)
    
  else if xscr().mCheckForXtra("FileXtra4") = 1 then -- if not buddy then try filextra
    fx = (xtra "filextra4").new()
    if objectP(fx) then
      retval = fx.fx_FolderSelectDialog("")
    end if
    fx = 0
  else
    fio = new(xtra "fileio")
    if not objectP(fio) then return retval
    retval = fio.displayOpen()
    if length(retval) > 0 then
      olddelim = the itemdelimiter
      the itemdelimiter = the last char of the moviepath
      delete the last item of retval
      put the itemdelimiter after retval
      the itemdelimiter = olddelim
    end if
    fio = void
  end if
  
  return retval
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetFileList me, folderpath
  if the runmode contains "plugin" then return []
  
  if length(string(folderpath)) < 1 then folderpath = mGetFolderPathFromUser(me)
  if length(folderpath) < 1 then return []
  
  if xscr().mCheckForXtra("BudAPI") then -- if buddy is present...
    
    --  -- budApi version:
    retval = baFileList(folderpath, "*.*")
    
  else if xscr().mCheckForXtra("FileXtra4") then -- if not buddy then try filextra
    --  -- filextra4 version:
    fx = (xtra "filextra4").new()
    if objectP(fx) then
      retval = fx.fx_FolderToList(folderpath)
      delim = the last char of the moviepath
      if length(delim) < 1 then
        if not(the runmode contains "plug") then
          delim = the last char of the applicationpath
        end if
      end if
      if length(delim) < 1 then delim = "/"
      repeat with n = count(retval) down to 1
        if the last char of retval[n] = delim then retval.deleteAt(n)
      end repeat
    end if
    fx = 0
    
  else
    
    retval = []
    n = 1
    this = getnthfilenameinfolder(folderpath, n)
    repeat while length(this) > 0
      if length(getnthfilenameinfolder(folderpath & this, 1)) = 0 then retval.add(this)
      n = n + 1
      this = getnthfilenameinfolder(folderpath, n)
    end repeat
  end if
  
  return retval
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetFolderList me, folderpath
  if the runmode contains "plugin" then return []
  
  if length(string(folderpath)) < 1 then folderpath = mGetFolderPathFromUser(me)
  if length(folderpath) < 1 then return []
  
  if xscr().mCheckForXtra("BudAPI") then -- if buddy is present...
    --  -- budApi version:
    retval = baFolderList(folderpath)
    
  else if xscr().mCheckForXtra("FileXtra4") then -- if not buddy then try filextra
    --  -- filextra4 version:
    fx = (xtra "filextra4").new()
    if objectP(fx) then
      retval = fx.fx_FolderToList(folderpath)
      delim = the last char of the moviepath
      if length(delim) < 1 then
        if not(the runmode contains "plug") then
          delim = the last char of the applicationpath
        end if
      end if
      if length(delim) < 1 then delim = "/"
      repeat with n = count(retval) down to 1
        
        if the last char of retval[n] <> delim then
          retval.deleteAt(n)
        else
          str = retval[n]
          --          delete the last char of str
          retval[n] = str
        end if
        
      end repeat
    end if
    fx = 0
    
  else
    
    retval = []
    n = 1
    this = getnthfilenameinfolder(folderpath, n)
    repeat while length(this) > 0
      if length(getnthfilenameinfolder(folderpath & this, 1)) > 0 then retval.add(this)
      n = n + 1
      this = getnthfilenameinfolder(folderpath, n)
    end repeat
  end if
  
  return retval
  
end


-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mGetFileAndFolderList me, folderpath
  if the runmode contains "plugin" then return []
  
  if length(string(folderpath)) < 1 then folderpath = mGetFolderPathFromUser(me)
  if length(folderpath) < 1 then return []
  
  if xscr().mCheckForXtra("BudAPI") then -- if buddy is present...
    --  -- budApi version:
    retval = baFolderList(folderpath)
    filelist = baFileList(folderpath, "*.*")
    repeat with f in filelist
      retval.add(f)
    end repeat
    
  else if xscr().mCheckForXtra("FileXtra4") then -- if not buddy then try filextra
    --  -- filextra4 version:
    fx = (xtra "filextra4").new()
    if objectP(fx) then
      retval = fx.fx_FolderToList(folderpath)
    end if
    fx = 0
    
  else
    
    retval = []
    n = 1
    this = getnthfilenameinfolder(folderpath, n)
    repeat while length(this) > 0
      retval.add(this)
      n = n + 1
      this = getnthfilenameinfolder(folderpath, n)
    end repeat
    
  end if
  
  return retval
  
end



-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-- xxxxxxxxxxxxxxxxxx Export BMP with FileIO Xtra
-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on mExportBitmapFIO me, imageObj, pfadname
  retval = 0
  --  statusmessage = "Compiling bitmap data"
  
  -- Initialize byteList, get image information from cast member
  byteList = []
  
  --  imageMember = member("sample")
  --  imageObj    = imageMember.image
  
  if ilk(imageObj) <> #image then return retval
  
  imageWidth  = imageObj.width
  imageHeight = imageObj.height
  bitmapSize  = imageWidth*imageHeight*3
  
  if bitmapSize = 0 then return retval
  
  -- Add bitmap file header information
  headerSize = 54
  headLength = headerSize - 14
  fileSize   = headerSize + bitmapSize + 0
  byteList = appendByteData(me, byteList, #string, "BM")        -- Bitmap type
  byteList = appendByteData(me, byteList, #uint32, fileSize)    -- File size
  byteList = appendByteData(me, byteList, #uint32, 0)           -- Unused
  byteList = appendByteData(me, byteList, #uint32, headerSize)  -- Offset to bitmap data
  byteList = appendByteData(me, byteList, #uint32, headLength)  -- Length of file header (minus previous bytes)
  byteList = appendByteData(me, byteList, #uint32, imageWidth)  -- Bitmap width
  byteList = appendByteData(me, byteList, #uint32, imageHeight) -- Bitmap height
  byteList = appendByteData(me, byteList, #uint16, 1)           -- Number of bitmap "planes"
  byteList = appendByteData(me, byteList, #uint16, 24)          -- Bits per pixel
  byteList = appendByteData(me, byteList, #uint32, 0)           -- Compression type
  byteList = appendByteData(me, byteList, #uint32, 0)           -- Bitmap data size
  byteList = appendByteData(me, byteList, #uint32, 0)           -- Horizontal resolution (not required)
  byteList = appendByteData(me, byteList, #uint32, 0)           -- Vertical resolution (not required)
  byteList = appendByteData(me, byteList, #uint32, 0)           -- Color count
  byteList = appendByteData(me, byteList, #uint32, 0)           -- Important color count
  
  -- The # of bytes for each row of pixels must be divisible by 4, so each line is padded with 0 to 3 bytes
  padBytes = integer((32 - ((imageWidth*3*8) mod 32))/8) mod 4
  
  -- Add bitmap image data
  repeat with y = imageHeight-1 down to 0
    repeat with x = 0 to imageWidth-1
      pixel = imageObj.getPixel(x, y)
      byteList.append(pixel.blue)
      byteList.append(pixel.green)
      byteList.append(pixel.red)
    end repeat
    repeat with padNum = 1 to padBytes
      byteList.append(0)
    end repeat
  end repeat
  
  --  statusmessage = "Saving file"
  
  -- Save the image
  retval = writeBinaryFile(me, pfadname, byteList, 1, 1, 1)
  
  --  statusmessage = "File saved"
  return retval
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--
-- Converts lingo variables into the specified data type and appends the
-- resulting byte values to the linear list named "byteList"
--
on appendByteData me, byteList, dataType, dataValue
  if byteList.listP and dataType.symbolP then
    case datatype of
      #string:
        if dataValue.stringP then
          repeat with index = 1 to dataValue.length
            byteList.append(charToNum(dataValue.char[index]))
          end repeat
        end if
        
      otherwise:
        numBytes = 0
        listlength = byteList.count
        
        dataTypes = [#uint16:2, #uint32:4]
        if dataTypes.findPos(dataType) > 0 then numBytes = dataTypes.getAProp(dataType)
        
        repeat with index = numBytes down to 1
          divisor = integer(power(2,((index-1)*8)))
          result  = dataValue/divisor
          dataValue = dataValue - divisor*result
          byteList[listLength+index] = result
        end repeat
    end case
  end if
  
  return byteList
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--
-- Uses FileIO to write the values of the byteList linear list into the file specified
-- by "filePath" with options for selecting a start position in the file and also
--
on writeBinaryFile me, filePath, byteList, fileStartByte, listStartByte, deleteOriginalFile
  retval = 0
  
  fio = new(xtra "fileIO")
  
  if ilk(filePath) <> #string then filePath = fio.displaySave("Save Bitmap:","Untitled.bmp")
  if not(filePath.length) then return retval
  
  if deleteOriginalFile then
    fio.openFile(filePath, 0)
    if fio.status() = 0 then fio.delete()
    fio.createFile(filePath)
  end if
  fio.openFile(filePath, 2)
  
  if fio.status() <> 0 then
    fio.createFile(filePath)
    fio.openFile(filePath, 2)
  end if
  
  if fio.status() = 0 then
    listLength = byteList.count
    if fileStartByte.voidP then fileStartByte = 1
    if listStartByte.voidP then listStartByte = 1
    fio.setPosition(fileStartByte-1)
    
    repeat with index = listStartByte to listLength
      fio.writeChar(numToChar(byteList[index]))
    end repeat
    retval = 1
  end if
  
  fio.closeFile()
  fio = 0
  return retval
end

-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

on interface me
  str = "FileIO Scripts  by alex da franca c2003 -- alex@farbflash.de -- all rigths reserved"
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mGetTextFromFile me, pfad" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mGetTextFromFileAsync me, paramList" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mSaveToTextFile me, theText, pfad, theTitle, theDefaultName" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mAppendTextToFile me, theText, pfad" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mExportSelectedText me, theType" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mGetPathNameFromUser me" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mGetFilePathFromUser me" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mGetFolderPathFromUser me" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mGetFileList me, folderpath" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mGetFolderList me, folderpath" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on mExportBitmapFIO me, imageObj, pfadname" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on appendByteData me, byteList, dataType, dataValue" after str
  put RETURN & "" after str
  
  put RETURN & "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" after str
  put RETURN & "-- xxxxxxxxxxxxxxxxxx Description" after str
  put RETURN & "on writeBinaryFile me, filePath, byteList, fileStartByte, listStartByte, deleteOriginalFile" after str
  put RETURN & "" after str
  return str
end
