Add mutex functions to Gtk and remove the funky threaded intialisation function.

-- -*-haskell-*-
--  GIMP Toolkit (GTK) General
--
--  Author : Axel Simon, Manuel M. T. Chakravarty
--
--  Created: 8 December 1998
--
--  Copyright (C) 2000..2005 Axel Simon, Manuel M. T. Chakravarty
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2.1 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Lesser General Public License for more details.
--
-- TODO
--
-- quitAddDestroy, quitAdd, quitRemove
--
-- |
-- Maintainer  : gtk2hs-users@lists.sourceforge.net
-- Stability   : provisional
-- Portability : portable (depends on GHC)
--
-- library initialization, main event loop, and events
--
module Graphics.UI.Gtk.General.General (
--  getDefaultLanguage,
  -- * Initialisation
  initGUI,

  -- ** Support for OS threads
  unsafeInitGUIForThreadedRTS,
  postGUISync,
  postGUIAsync,
  threadsEnter,
  threadsLeave,

  -- * Main event loop
  mainGUI,
  mainQuit,

  -- ** Less commonly used event loop functions
  eventsPending,
  mainLevel,
  mainIteration,
  mainIterationDo,

  -- * Grab widgets
  grabAdd,
  grabGetCurrent,
  grabRemove,

  -- * Timeout and idle callbacks
  Priority,
  priorityLow,
  priorityDefaultIdle,
  priorityHighIdle,
  priorityDefault,
  priorityHigh,
  timeoutAdd,
  timeoutAddFull,
  timeoutRemove,
  idleAdd,
  idleRemove,
  inputAdd,
  inputRemove,
  IOCondition,
  HandlerId
  ) where

import System.Environment (getProgName, getArgs)
import Control.Monad      (liftM, mapM, when)
import Control.Concurrent (rtsSupportsBoundThreads, newEmptyMVar,
                           putMVar, takeMVar)
import Data.IORef         (IORef, newIORef, readIORef, writeIORef)

import System.Glib.FFI
import System.Glib.UTFString
import System.Glib.MainLoop
import Graphics.UI.Gtk.Abstract.Object	(makeNewObject)
{#import Graphics.UI.Gtk.Types#}

{#context lib="gtk" prefix ="gtk"#}

{-
-- | Retreive the current language.
-- * This function returns a String which's pointer can be used later on for
--   comarisions.
--
--getDefaultLanguage :: IO String
--getDefaultLanguage = do
--  strPtr <- {#call unsafe get_default_language#}
--  str <- peekUTFString strPtr
--  destruct strPtr
--  return str
-}

unsafeInitGUIForThreadedRTS = initGUI

-- We compile this module using -#includ"gtk/wingtk.h" to bypass the win32 abi
-- check however we do not compile users programs with this header so if
-- initGUI was ever inlined in a users program, then that program would not
-- bypass the abi check and would fail on startup. So to stop that we must
-- prevent initGUI from being inlined.
{-# NOINLINE initGUI #-}
-- | Initialize the GUI.
--
-- This must be called before any other function in the Gtk2Hs library.
--
-- This function initializes the GUI toolkit and parses all Gtk
-- specific arguments. The remaining arguments are returned. If the
-- initialization of the toolkit fails for whatever reason, an exception
-- is thrown.
--
-- * Throws: @error \"Cannot initialize GUI.\"@
--
--
-- * If you want to use Gtk2Hs and in a multi-threaded application then it is your obligation
--   to ensure that all calls to Gtk+ happen on a single OS thread.
--   If you want to make calls to Gtk2Hs functions from a Haskell thread other
--   than the one that calls this functions and 'mainGUI' then you will have to
--   \'post\' your GUI actions to the main GUI thread. You can do this using
--   'postGUISync' or 'postGUIAsync'. See also 'threadsEnter'.
--
initGUI :: IO [String]
initGUI = do
  when rtsSupportsBoundThreads initialiseGThreads
  threadsEnter
  prog <- getProgName
  args <- getArgs
  let allArgs = (prog:args)
  withMany withUTFString allArgs $ \addrs  ->
    withArrayLen       addrs   $ \argc argv ->
    with	       argv    $ \argvp ->
    with	       argc    $ \argcp -> do
      res <- {#call unsafe init_check#} (castPtr argcp) (castPtr argvp)
      if (toBool res) then do
        argc'   <- peek argcp
        argv'   <- peek argvp
        _:addrs'  <- peekArray argc' argv'  -- drop the program name
        mapM peekUTFString addrs'
        else error "Cannot initialize GUI."

-- g_thread_init aborts the whole program if it's called more than once so
-- we've got to keep track of whether or not we've called it already. Sigh.
--
foreign import ccall "hsgthread.h gtk2hs_threads_initialise"
  initialiseGThreads :: IO ()

-- | Post an action to be run in the main GUI thread.
--
-- The current thread blocks until the action completes and the result is
-- returned.
--
postGUISync :: IO a -> IO a
postGUISync action = do
  resultVar <- newEmptyMVar
  idleAdd (action >>= putMVar resultVar >> return False) priorityDefault
  takeMVar resultVar

-- | Post an action to be run in the main GUI thread.
--
-- The current thread continues and does not wait for the result of the
-- action.
--
postGUIAsync :: IO () -> IO ()
postGUIAsync action = do
  idleAdd (action >> return False) priorityDefault
  return ()

-- | Acquired the global Gtk lock.
--
-- * During normal operation, this lock is held by the thread from which all
--   interaction with Gtk is performed. When calling 'mainGUI', the thread will
--   release this global lock before it waits for user interaction. During this
--   time it is, in principle, possible to use a different OS thread (any other
--   Haskell thread that is bound to the Gtk OS thread will be blocked anyway)
--   to interact with Gtk by explicitly acquiring the lock, calling Gtk functions
--   and releasing the lock. However, the Gtk functions that are called from this
--   different thread may not trigger any calls to the OS since this will
--   lead to a crash on Windows (the Win32 API can only be used from a single
--   thread). Since it is very hard to tell which function only interacts on
--   Gtk data structures and which function call actual OS functions, it
--   is best not to use this feature at all. A better way to perform updates
--   in the background is to spawn a Haskell thread and to perform the update
--   to Gtk widgets using 'postGUIAsync' or 'postGUISync'. These will execute
--   their arguments from the main loop, that is, from the OS thread of Gtk,
--   thereby ensuring that any Gtk and OS function can be called.
--
{#fun unsafe gdk_threads_enter as threadsEnter {} -> `()' #}

-- | Release the global Gtk lock.
--
-- * The use of this function is not recommended. See 'threadsEnter'.
--
{#fun unsafe gdk_threads_leave as threadsLeave {} -> `()' #}

-- | Inquire the number of events pending on the event queue
--
eventsPending :: IO Int
eventsPending  = liftM fromIntegral {#call unsafe events_pending#}

-- | Run the Gtk+ main event loop.
--
mainGUI :: IO ()
mainGUI  = {#call main#}

-- | Inquire the main loop level.
--
-- * Callbacks that take more time to process can call 'mainIteration' to keep
-- the GUI responsive. Each time the main loop is restarted this way, the main
-- loop counter is increased. This function returns this counter.
--
mainLevel :: IO Int
mainLevel  = liftM (toEnum.fromEnum) {#call unsafe main_level#}

-- | Exit the main event loop.
--
mainQuit :: IO ()
mainQuit  = {#call main_quit#}

-- | Process an event, block if necessary.
--
-- * Returns @True@ if 'mainQuit' was called while processing the event.
--
mainIteration :: IO Bool
mainIteration  = liftM toBool {#call main_iteration#}

-- | Process a single event.
--
-- * Called with @True@, this function behaves as 'mainIteration' in that it
-- waits until an event is available for processing. It will return
-- immediately, if passed @False@.
--
-- * Returns @True@ if the 'mainQuit' was called while processing the event.
--
mainIterationDo :: Bool -> IO Bool
mainIterationDo blocking =
  liftM toBool $ {#call main_iteration_do#} (fromBool blocking)

-- | add a grab widget
--
grabAdd :: WidgetClass wd => wd -> IO ()
grabAdd  = {#call grab_add#} . toWidget

-- | inquire current grab widget
--
grabGetCurrent :: IO (Maybe Widget)
grabGetCurrent  = do
  wPtr <- {#call grab_get_current#}
  if (wPtr==nullPtr) then return Nothing else
    liftM Just $ makeNewObject mkWidget (return wPtr)

-- | remove a grab widget
--
grabRemove :: WidgetClass w => w -> IO ()
grabRemove  = {#call grab_remove#} . toWidget

-- -*-haskell-*-
--  GIMP Toolkit (GTK) General
--
--  Author : Axel Simon, Manuel M. T. Chakravarty
--
--  Created: 8 December 1998
--
--  Copyright (C) 2000..2005 Axel Simon, Manuel M. T. Chakravarty
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2.1 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Lesser General Public License for more details.
--
-- TODO
--
-- quitAddDestroy, quitAdd, quitRemove
--
-- |
-- Maintainer  : gtk2hs-users@lists.sourceforge.net
-- Stability   : provisional
-- Portability : portable (depends on GHC)
--
-- library initialization, main event loop, and events
--
module Graphics.UI.Gtk.General.General (
--  getDefaultLanguage,
  -- * Initialisation
  initGUI,

  -- ** Support for OS threads
  unsafeInitGUIForThreadedRTS,
  postGUISync,
  postGUIAsync,

  -- * Main event loop
  mainGUI,
  mainQuit,

  -- ** Less commonly used event loop functions
  eventsPending,
  mainLevel,
  mainIteration,
  mainIterationDo,

  -- * Grab widgets
  grabAdd,
  grabGetCurrent,
  grabRemove,

  -- * Timeout and idle callbacks
  Priority,
  priorityLow,
  priorityDefaultIdle,
  priorityHighIdle,
  priorityDefault,
  priorityHigh,
  timeoutAdd,
  timeoutAddFull,
  timeoutRemove,
  idleAdd,
  idleRemove,
  inputAdd,
  inputRemove,
  IOCondition,
  HandlerId
  ) where

import System.Environment (getProgName, getArgs)
import Control.Monad      (liftM, mapM, when)
import Control.Concurrent (rtsSupportsBoundThreads, newEmptyMVar,
                           putMVar, takeMVar)
import Data.IORef         (IORef, newIORef, readIORef, writeIORef)

import System.Glib.FFI
import System.Glib.UTFString
import System.Glib.MainLoop
import Graphics.UI.Gtk.Abstract.Object	(makeNewObject)
{#import Graphics.UI.Gtk.Types#}

{#context lib="gtk" prefix ="gtk"#}

{-
-- | Retreive the current language.
-- * This function returns a String which's pointer can be used later on for
--   comarisions.
--
--getDefaultLanguage :: IO String
--getDefaultLanguage = do
--  strPtr <- {#call unsafe get_default_language#}
--  str <- peekUTFString strPtr
--  destruct strPtr
--  return str
-}

-- We compile this module using -#includ"gtk/wingtk.h" to bypass the win32 abi
-- check however we do not compile users programs with this header so if
-- initGUI was ever inlined in a users program, then that program would not
-- bypass the abi check and would fail on startup. So to stop that we must
-- prevent initGUI from being inlined.
{-# NOINLINE initGUI #-}
-- | Initialize the GUI.
--
-- This must be called before any other function in the Gtk2Hs library.
--
-- This function initializes the GUI toolkit and parses all Gtk
-- specific arguments. The remaining arguments are returned. If the
-- initialization of the toolkit fails for whatever reason, an exception
-- is thrown.
--
-- * Throws: @error \"Cannot initialize GUI.\"@
--
initGUI :: IO [String]
initGUI = do
  name <- getProgName
  when (rtsSupportsBoundThreads && name /= "<interactive>") $ fail $ "\n" ++
    "initGUI: Gtk+ is single threaded and so cannot safely be used from\n" ++
    "multiple Haskell threads when using GHC's threaded RTS. You can\n" ++
    "avoid this error by relinking your program without using the\n" ++
    "'-threaded' flag. If you have to use the threaded RTS and are\n" ++
    "absolutely sure that you only ever call Gtk+ from a single OS\n" ++
    "thread then you can use the function: unsafeInitGUIForThreadedRTS\n"

  unsafeInitGUIForThreadedRTS

{-# NOINLINE unsafeInitGUIForThreadedRTS #-}
-- | Same as initGUI except that it prints no warning when used with GHC's
-- threaded RTS.
--
-- If you want to use Gtk2Hs and the threaded RTS then it is your obligation
-- to ensure that all calls to Gtk+ happen on a single OS thread.
-- If you want to make calls to Gtk2Hs functions from a Haskell thread other
-- than the one that calls this functions and 'mainGUI' then you will have to
-- \'post\' your GUI actions to the main GUI thread. You can do this using
-- 'postGUISync' or 'postGUIAsync'.
--
unsafeInitGUIForThreadedRTS :: IO [String]
unsafeInitGUIForThreadedRTS = do
  when rtsSupportsBoundThreads initialiseGThreads
  prog <- getProgName
  args <- getArgs
  let allArgs = (prog:args)
  withMany withUTFString allArgs $ \addrs  ->
    withArrayLen       addrs   $ \argc argv ->
    with	       argv    $ \argvp ->
    with	       argc    $ \argcp -> do
      res <- {#call unsafe init_check#} (castPtr argcp) (castPtr argvp)
      if (toBool res) then do
        argc'   <- peek argcp
        argv'   <- peek argvp
        _:addrs'  <- peekArray argc' argv'  -- drop the program name
        mapM peekUTFString addrs'
        else error "Cannot initialize GUI."

-- g_thread_init aborts the whole program if it's called more than once so
-- we've got to keep track of whether or not we've called it already. Sigh.
--
foreign import ccall "hsgthread.h gtk2hs_threads_initialise"
  initialiseGThreads :: IO ()

-- | Post an action to be run in the main GUI thread.
--
-- The current thread blocks until the action completes and the result is
-- returned.
--
postGUISync :: IO a -> IO a
postGUISync action = do
  resultVar <- newEmptyMVar
  idleAdd (action >>= putMVar resultVar >> return False) priorityDefault
  takeMVar resultVar

-- | Post an action to be run in the main GUI thread.
--
-- The current thread continues and does not wait for the result of the
-- action.
--
postGUIAsync :: IO () -> IO ()
postGUIAsync action = do
  idleAdd (action >> return False) priorityDefault
  return ()

-- | Inquire the number of events pending on the event queue
--
eventsPending :: IO Int
eventsPending  = liftM fromIntegral {#call unsafe events_pending#}

-- | Run the Gtk+ main event loop.
--
mainGUI :: IO ()
mainGUI  = {#call main#}

-- | Inquire the main loop level.
--
-- * Callbacks that take more time to process can call 'mainIteration' to keep
-- the GUI responsive. Each time the main loop is restarted this way, the main
-- loop counter is increased. This function returns this counter.
--
mainLevel :: IO Int
mainLevel  = liftM (toEnum.fromEnum) {#call unsafe main_level#}

-- | Exit the main event loop.
--
mainQuit :: IO ()
mainQuit  = {#call main_quit#}

-- | Process an event, block if necessary.
--
-- * Returns @True@ if 'mainQuit' was called while processing the event.
--
mainIteration :: IO Bool
mainIteration  = liftM toBool {#call main_iteration#}

-- | Process a single event.
--
-- * Called with @True@, this function behaves as 'mainIteration' in that it
-- waits until an event is available for processing. It will return
-- immediately, if passed @False@.
--
-- * Returns @True@ if the 'mainQuit' was called while processing the event.
--
mainIterationDo :: Bool -> IO Bool
mainIterationDo blocking =
  liftM toBool $ {#call main_iteration_do#} (fromBool blocking)

-- | add a grab widget
--
grabAdd :: WidgetClass wd => wd -> IO ()
grabAdd  = {#call grab_add#} . toWidget

-- | inquire current grab widget
--
grabGetCurrent :: IO (Maybe Widget)
grabGetCurrent  = do
  wPtr <- {#call grab_get_current#}
  if (wPtr==nullPtr) then return Nothing else
    liftM Just $ makeNewObject mkWidget (return wPtr)

-- | remove a grab widget
--
grabRemove :: WidgetClass w => w -> IO ()
grabRemove  = {#call grab_remove#} . toWidget


sourceBufferSet/GetStyleScheme should pass/return 'Maybe SourceStyleScheme'

{-# LANGUAGE CPP #-}
-- -*-haskell-*-
--  GIMP Toolkit (GTK) SourceBuffer
--
--  Author : Peter Gavin, Andy Stewart
--  derived from sourceview bindings by Axel Simon and Duncan Coutts
--
--  Created: 18 December 2008
--
--  Copyright (C) 2003-2008 Peter Gavin, Duncan Coutts, Axel Simon
--  Copyright (C) 2010 Andy Stewart
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2.1 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Lesser General Public License for more details.
--
-- |
-- Maintainer  : gtk2hs-users@lists.sourceforge.net
-- Stability   : provisional
-- Portability : portable (depends on GHC)
--
module Graphics.UI.Gtk.SourceView.SourceBuffer (
-- * Types
  SourceBuffer,
  SourceBufferClass,

-- * Methods
  castToSourceBuffer,
  sourceBufferNew,
  sourceBufferNewWithLanguage,
  sourceBufferSetHighlightSyntax,
  sourceBufferGetHighlightSyntax,
  sourceBufferSetLanguage,
  sourceBufferGetLanguage,
  sourceBufferSetHighlightMatchingBrackets,
  sourceBufferGetHighlightMatchingBrackets,
  sourceBufferSetStyleScheme,
  sourceBufferGetStyleScheme,
  sourceBufferSetMaxUndoLevels,
  sourceBufferGetMaxUndoLevels,
  sourceBufferGetCanUndo,
  sourceBufferGetCanRedo,
  sourceBufferUndo,
  sourceBufferRedo,
  sourceBufferBeginNotUndoableAction,
  sourceBufferEndNotUndoableAction,
  sourceBufferCreateSourceMark,
  sourceBufferGetSourceMarksAtLine,
  sourceBufferGetSourceMarksAtIter,
  sourceBufferRemoveSourceMarks,
  sourceBufferForwardIterToSourceMark,
  sourceBufferBackwardIterToSourceMark,
  sourceBufferEnsureHighlight,

-- * Attributes
  sourceBufferCanRedo,
  sourceBufferCanUndo,
  sourceBufferHighlightMatchingBrackets,
  sourceBufferHighlightSyntax,
  sourceBufferLanguage,
  sourceBufferSourceStyleScheme,
  sourceBufferMaxUndoLevels,

-- * Signals
  sourceBufferHighlightUpdated,
  sourceBufferRedoSignal,
  sourceBufferUndoSignal,
  sourceBufferSourceMarkUpdated,
  ) where

import Control.Monad	(liftM)
import Data.Maybe    (fromMaybe)

import System.Glib.FFI
import System.Glib.GList
import System.Glib.GObject              (constructNewGObject,
					 makeNewGObject)
{#import System.Glib.Properties#}
import System.Glib.Attributes
import Graphics.UI.Gtk.Abstract.Object	(makeNewObject)
{#import Graphics.UI.Gtk.SourceView.Types#}
{#import Graphics.UI.Gtk.SourceView.Signals#}
{#import Graphics.UI.Gtk.Multiline.TextIter#}

{#import Graphics.UI.Gtk.SourceView.SourceMark#}

{# context lib="gtk" prefix="gtk" #}

-- methods

-- | Create a new 'SourceBuffer', possibly
-- taking a 'TextTagTable'.
--
sourceBufferNew :: Maybe TextTagTable -> IO SourceBuffer
sourceBufferNew tt = constructNewGObject mkSourceBuffer $
  {#call unsafe source_buffer_new#}
  (fromMaybe (TextTagTable nullForeignPtr) tt)

-- | Create a new 'SourceBuffer'
-- with a 'SourceLanguage'.
--
sourceBufferNewWithLanguage :: SourceLanguage -> IO SourceBuffer
sourceBufferNewWithLanguage lang = constructNewGObject mkSourceBuffer $
  {#call unsafe source_buffer_new_with_language#} lang

-- | Controls whether syntax is highlighted in the buffer. If highlight is 'True', the text will be
-- highlighted according to the syntax patterns specified in the language set with
-- 'sourceBufferSetLanguage'. If highlight is 'False', syntax highlighting is disabled and all the
-- 'TextTag' objects that have been added by the syntax highlighting engine are removed from the
-- buffer.
sourceBufferSetHighlightSyntax :: SourceBuffer  -- ^ @buffer@    a 'SourceBuffer'.
                               -> Bool  -- ^ @highlight@ 'True' to enable syntax highlighting, 'False' to disable it.
                               -> IO ()
sourceBufferSetHighlightSyntax sb newVal =
  {#call unsafe source_buffer_set_highlight_syntax#} sb (fromBool newVal)

-- | Determines whether syntax highlighting is activated in the source buffer.
sourceBufferGetHighlightSyntax :: SourceBuffer
                               -> IO Bool  -- ^ returns 'True' if syntax highlighting is enabled, 'False' otherwise.
sourceBufferGetHighlightSyntax sb = liftM toBool $
  {#call unsafe source_buffer_get_highlight_syntax#} sb

-- | Associate a 'SourceLanguage' with the source buffer. If language is not-'Nothing' and syntax
-- highlighting is enabled (see 'sourceBufferSetHighlightSyntax', the syntax patterns defined
-- in language will be used to highlight the text contained in the buffer. If language is 'Nothing', the
-- text contained in the buffer is not highlighted.
sourceBufferSetLanguage :: SourceBuffer
                        -> Maybe SourceLanguage  -- ^ @language@ a 'SourceLanguage' to set, or 'Nothing'.
                        -> IO ()
sourceBufferSetLanguage sb lang =
  {#call unsafe source_buffer_set_language#}
    sb
    (fromMaybe (SourceLanguage nullForeignPtr) lang)

-- | Returns the 'SourceLanguage' associated with the buffer, see 'sourceBufferSetLanguage'.
sourceBufferGetLanguage :: SourceBuffer
                        -> IO (Maybe SourceLanguage) -- ^ returns 'SourceLanguage' associated with the buffer, or 'Nothing'.
sourceBufferGetLanguage sb =
  maybeNull (makeNewGObject mkSourceLanguage) $
  {#call unsafe source_buffer_get_language#} sb

-- | Controls the bracket match highlighting function in the buffer. If activated, when you position your
-- cursor over a bracket character (a parenthesis, a square bracket, etc.) the matching opening or
-- closing bracket character will be highlighted. You can specify the style with the
-- 'sourceBufferSetBracketMatchStyle' function.
sourceBufferSetHighlightMatchingBrackets :: SourceBuffer
                                         -> Bool  -- ^ @highlight@ 'True' if you want matching brackets highlighted.
                                         -> IO ()
sourceBufferSetHighlightMatchingBrackets sb newVal =
  {#call unsafe source_buffer_set_highlight_matching_brackets#} sb (fromBool newVal)

-- | Determines whether bracket match highlighting is activated for the source buffer.
sourceBufferGetHighlightMatchingBrackets :: SourceBuffer
                                         -> IO Bool  -- ^ returns 'True' if the source buffer will highlight matching brackets.
sourceBufferGetHighlightMatchingBrackets sb = liftM toBool $
  {#call unsafe source_buffer_get_highlight_matching_brackets#} sb

-- | Sets style scheme used by the buffer. If scheme is 'Nothing' no style scheme is used.
sourceBufferSetStyleScheme :: SourceBuffer
                           -> Maybe SourceStyleScheme  -- ^ @scheme@ style scheme.
                           -> IO ()
sourceBufferSetStyleScheme sb scheme =
    {#call unsafe source_buffer_set_style_scheme#}
      sb
      (fromMaybe (SourceStyleScheme nullForeignPtr) scheme)

-- | Returns the 'SourceStyleScheme' currently used in buffer.
sourceBufferGetStyleScheme :: SourceBuffer
                           -> IO (Maybe SourceStyleScheme) -- ^ returns the 'SourceStyleScheme' set by 'sourceBufferSetStyleScheme', or 'Nothing'.
sourceBufferGetStyleScheme sb =
    maybeNull (makeNewGObject mkSourceStyleScheme) $
    {#call unsafe source_buffer_get_style_scheme#} sb

-- | Sets the number of undo levels for user actions the buffer will track. If the number of user actions
-- exceeds the limit set by this function, older actions will be discarded.
--
-- If @maxUndoLevels@ is -1, no limit is set.
--
-- A new action is started whenever the function 'textBufferBeginUserAction' is called. In
-- general, this happens whenever the user presses any key which modifies the buffer, but the undo
-- manager will try to merge similar consecutive actions, such as multiple character insertions into
-- one action. But, inserting a newline does start a new action.
sourceBufferSetMaxUndoLevels :: SourceBuffer
                             -> Int  -- ^ @maxUndoLevels@ the desired maximum number of undo levels.
                             -> IO ()
sourceBufferSetMaxUndoLevels sb newVal =
  {#call unsafe source_buffer_set_max_undo_levels#} sb (fromIntegral newVal)

-- | Determines the number of undo levels the buffer will track for buffer edits.
sourceBufferGetMaxUndoLevels :: SourceBuffer
                             -> IO Int -- ^ returns the maximum number of possible undo levels or -1 if no limit is set.
sourceBufferGetMaxUndoLevels sb = liftM fromIntegral $
  {#call unsafe source_buffer_get_max_undo_levels#} sb

-- | Determines whether a source buffer can undo the last action.
sourceBufferGetCanUndo :: SourceBuffer
                       -> IO Bool -- ^ returns 'True' if it's possible to undo the last action.
sourceBufferGetCanUndo sb = liftM toBool $
  {#call unsafe source_buffer_can_undo#} sb

-- | Determines whether a source buffer can redo the last action (i.e. if the last operation was an
-- undo).
sourceBufferGetCanRedo :: SourceBuffer
                       -> IO Bool -- ^ returns 'True' if a redo is possible.
sourceBufferGetCanRedo sb = liftM toBool $
  {#call unsafe source_buffer_can_redo#} sb

-- | Undoes the last user action which modified the buffer. Use 'sourceBufferCanUndo' to check
-- whether a call to this function will have any effect.
--
-- Actions are defined as groups of operations between a call to 'textBufferBeginUserAction'
-- and 'textBufferEndUserAction' on the
-- same line.
sourceBufferUndo :: SourceBuffer -> IO ()
sourceBufferUndo sb =
  {#call source_buffer_undo#} sb

-- | Redoes the last undo operation. Use 'sourceBufferCanRedo' to check whether a call to this
-- function will have any effect.
sourceBufferRedo :: SourceBuffer -> IO ()
sourceBufferRedo sb =
  {#call source_buffer_redo#} sb

-- | Marks the beginning of a not undoable action on the buffer, disabling the undo manager. Typically
-- you would call this function before initially setting the contents of the buffer (e.g. when loading
-- a file in a text editor).
--
-- You may nest 'sourceBufferBeginNotUndoableAction' /
-- 'sourceBufferEndNotUndoableAction' blocks.
sourceBufferBeginNotUndoableAction :: SourceBuffer -> IO ()
sourceBufferBeginNotUndoableAction sb =
  {#call source_buffer_begin_not_undoable_action#} sb

-- | Marks the end of a not undoable action on the buffer. When the last not undoable block is closed
-- through the call to this function, the list of undo actions is cleared and the undo manager is
-- re-enabled.
sourceBufferEndNotUndoableAction :: SourceBuffer -> IO ()
sourceBufferEndNotUndoableAction sb =
  {#call source_buffer_end_not_undoable_action#} sb

-- | Creates a marker in the buffer of the given type.
--
-- *  A marker is
--    semantically very similar to a 'Graphics.UI.Gtk.Multiline.TextMark',
--    except it has a type
--    which is used by the 'SourceView' displaying the buffer to show a
--    pixmap on the left margin, at the line the marker is in.  Because
--    of this, a marker is generally associated to a line and not a
--    character position.  Markers are also accessible through a position
--    or range in the buffer.
--
-- *  Markers are implemented using 'Graphics.UI.Gtk.Multiline.TextMark',
--    so all characteristics
--    and restrictions to marks apply to markers too.  These includes
--    life cycle issues and 'Graphics.UI.Gtk.Multiline.TextMark.onMarkSet'
--    and 'Graphics.UI.Gtk.Multiline.TextMark.onMarkDeleted' signal
--    emissions.
--
-- *  Like a 'Graphics.UI.Gtk.Multiline.TextMark', a 'SourceMarker'
--    can be anonymous if the
--    passed name is @Nothing@.  Also, the buffer owns the markers so you
--    shouldn't unreference it.

sourceBufferCreateSourceMark :: SourceBuffer -- the buffer
                         -> Maybe String -- the name of the mark
                         -> String -- the category of the mark
                         -> TextIter -> IO SourceMark
sourceBufferCreateSourceMark sb name category iter =
  makeNewGObject mkSourceMark $
  maybeWith withCString name       $ \strPtr1 ->
  withCString category $ \strPtr2 ->
  {#call source_buffer_create_source_mark#} sb strPtr1 strPtr2 iter

-- | Returns the list of marks of the given category at line. If category is empty, all marks at line are
-- returned.
sourceBufferGetSourceMarksAtLine :: SourceBuffer  -- ^ @buffer@   a 'SourceBuffer'.
                                 -> Int -- ^ @line@     a line number.
                                 -> String -- ^ @category@ category to search for or empty
                                 -> IO [SourceMark]
sourceBufferGetSourceMarksAtLine buffer line category =
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_get_source_marks_at_line #}
    buffer
    (fromIntegral line)
    categoryPtr
  >>= readGSList
  >>= mapM (\markPtr -> makeNewGObject mkSourceMark (return markPtr))

-- | Returns the list of marks of the given category at iter. If category is empty it returns all marks at
-- iter.
sourceBufferGetSourceMarksAtIter :: SourceBuffer -- ^ @buffer@   a 'SourceBuffer'.
                                 -> TextIter -- ^ @iter@     an iterator.
                                 -> String -- ^ @category@ category to search for or empty
                                 -> IO [SourceMark]
sourceBufferGetSourceMarksAtIter buffer iter category =
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_get_source_marks_at_iter #}
    buffer
    iter
    categoryPtr
  >>= readGSList
  >>= mapM (\markPtr -> makeNewGObject mkSourceMark (return markPtr))

-- | Remove all marks of category between start and end from the buffer. If category is empty, all marks
-- in the range will be removed.
sourceBufferRemoveSourceMarks :: SourceBuffer -- ^ @buffer@   a 'SourceBuffer'.
                              -> TextIter -- ^ @start@    a 'TextIter'
                              -> TextIter -- ^ @end@      a 'TextIter'
                              -> String -- ^ @category@ category to search for or empty
                              -> IO ()
sourceBufferRemoveSourceMarks buffer start end category =
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_remove_source_marks #}
     buffer
     start
     end
     categoryPtr

-- | Moves iter to the position of the next 'SourceMark' of the given category. Returns 'True' if iter was
-- moved. If category is empty, the next source mark can be of any category.
sourceBufferForwardIterToSourceMark :: SourceBuffer -- ^ @buffer@   a 'SourceBuffer'.
                                    -> TextIter -- ^ @iter@     an iterator.
                                    -> String -- ^ @category@ category to search for or emtpy
                                    -> IO Bool -- ^ returns  whether iter moved.
sourceBufferForwardIterToSourceMark buffer iter category =
  liftM toBool $
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_forward_iter_to_source_mark #}
    buffer
    iter
    categoryPtr

-- | Moves iter to the position of the previous 'SourceMark' of the given category. Returns 'True' if iter
-- was moved. If category is empty, the previous source mark can be of any category.
sourceBufferBackwardIterToSourceMark :: SourceBuffer  -- ^ @buffer@   a 'SourceBuffer'.
                                     -> TextIter -- ^ @iter@     an iterator.
                                     -> String -- ^ @category@ category to search for or emtpy
                                     -> IO Bool -- ^ returns  whether iter moved.
sourceBufferBackwardIterToSourceMark buffer iter category =
  liftM toBool $
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_backward_iter_to_source_mark #}
    buffer
    iter
    categoryPtr

-- | Forces buffer to analyze and highlight the given area synchronously.
--
-- Note
--
-- This is a potentially slow operation and should be used only when you need to make sure that some
-- text not currently visible is highlighted, for instance before printing.
sourceBufferEnsureHighlight :: SourceBuffer
                            -> TextIter  -- ^ @start@  start of the area to highlight.
                            -> TextIter  -- ^ @end@    end of the area to highlight.
                            -> IO ()
sourceBufferEnsureHighlight sb start end =
    {#call source_buffer_ensure_highlight#} sb start end

-- | Whether Redo operation is possible.
--
-- Default value: 'False'
--
sourceBufferCanRedo :: ReadAttr SourceBuffer Bool
sourceBufferCanRedo = readAttrFromBoolProperty "can-redo"

-- | Whether Undo operation is possible.
--
-- Default value: 'False'
sourceBufferCanUndo :: ReadAttr SourceBuffer Bool
sourceBufferCanUndo = readAttrFromBoolProperty "can-undo"

-- | Whether to highlight matching brackets in the buffer.
--
-- Default value: 'True'
--
sourceBufferHighlightMatchingBrackets :: Attr SourceBuffer Bool
sourceBufferHighlightMatchingBrackets = newAttrFromBoolProperty "highlight-matching-brackets"

-- | Whether to highlight syntax in the buffer.
--
-- Default value: 'True'
--
sourceBufferHighlightSyntax :: Attr SourceBuffer Bool
sourceBufferHighlightSyntax = newAttrFromBoolProperty "highlight-matching-brackets"

-- | Language object to get highlighting patterns from.
--
sourceBufferLanguage :: Attr SourceBuffer (Maybe SourceLanguage)
sourceBufferLanguage = newAttrFromMaybeObjectProperty "language" gTypeSourceLanguage

-- | Number of undo levels for the buffer. -1 means no limit. This property will only affect the default
-- undo manager.
--
-- Allowed values: >= GMaxulong
--
-- Default value: 1000
--
sourceBufferMaxUndoLevels :: Attr SourceBuffer Int
sourceBufferMaxUndoLevels = newAttrFromIntProperty "max-undo-levels"

-- | Style scheme. It contains styles for syntax highlighting, optionally foreground, background, cursor
-- color, current line color, and matching brackets style.
--
sourceBufferSourceStyleScheme :: Attr SourceBuffer (Maybe SourceStyleScheme)
sourceBufferSourceStyleScheme = newAttrFromMaybeObjectProperty "style-scheme" gTypeSourceStyleScheme

-- |
--
sourceBufferHighlightUpdated :: Signal SourceBuffer (TextIter -> TextIter -> IO ())
sourceBufferHighlightUpdated = Signal $ connect_BOXED_BOXED__NONE "highlight-updated" mkTextIterCopy mkTextIterCopy

-- |
--
sourceBufferRedoSignal :: Signal SourceBuffer (IO ())
sourceBufferRedoSignal = Signal $ connect_NONE__NONE "redo"

-- |
--
sourceBufferUndoSignal :: Signal SourceBuffer (IO ())
sourceBufferUndoSignal = Signal $ connect_NONE__NONE "undo"

-- | The 'sourceBufferMarkUpdated' signal is emitted each time a mark is added to, moved or removed from the
-- buffer.
--
sourceBufferSourceMarkUpdated :: Signal SourceBuffer (TextMark -> IO ())
sourceBufferSourceMarkUpdated = Signal $ connect_OBJECT__NONE "source-mark-updated"

{-# LANGUAGE CPP #-}
-- -*-haskell-*-
--  GIMP Toolkit (GTK) SourceBuffer
--
--  Author : Peter Gavin, Andy Stewart
--  derived from sourceview bindings by Axel Simon and Duncan Coutts
--
--  Created: 18 December 2008
--
--  Copyright (C) 2003-2008 Peter Gavin, Duncan Coutts, Axel Simon
--  Copyright (C) 2010 Andy Stewart
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2.1 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Lesser General Public License for more details.
--
-- |
-- Maintainer  : gtk2hs-users@lists.sourceforge.net
-- Stability   : provisional
-- Portability : portable (depends on GHC)
--
module Graphics.UI.Gtk.SourceView.SourceBuffer (
-- * Types
  SourceBuffer,
  SourceBufferClass,

-- * Methods
  castToSourceBuffer,
  sourceBufferNew,
  sourceBufferNewWithLanguage,
  sourceBufferSetHighlightSyntax,
  sourceBufferGetHighlightSyntax,
  sourceBufferSetLanguage,
  sourceBufferGetLanguage,
  sourceBufferSetHighlightMatchingBrackets,
  sourceBufferGetHighlightMatchingBrackets,
  sourceBufferSetStyleScheme,
  sourceBufferGetStyleScheme,
  sourceBufferSetMaxUndoLevels,
  sourceBufferGetMaxUndoLevels,
  sourceBufferGetCanUndo,
  sourceBufferGetCanRedo,
  sourceBufferUndo,
  sourceBufferRedo,
  sourceBufferBeginNotUndoableAction,
  sourceBufferEndNotUndoableAction,
  sourceBufferCreateSourceMark,
  sourceBufferGetSourceMarksAtLine,
  sourceBufferGetSourceMarksAtIter,
  sourceBufferRemoveSourceMarks,
  sourceBufferForwardIterToSourceMark,
  sourceBufferBackwardIterToSourceMark,
  sourceBufferEnsureHighlight,

-- * Attributes
  sourceBufferCanRedo,
  sourceBufferCanUndo,
  sourceBufferHighlightMatchingBrackets,
  sourceBufferHighlightSyntax,
  sourceBufferLanguage,
  sourceBufferSourceStyleScheme,
  sourceBufferMaxUndoLevels,

-- * Signals
  sourceBufferHighlightUpdated,
  sourceBufferRedoSignal,
  sourceBufferUndoSignal,
  sourceBufferSourceMarkUpdated,
  ) where

import Control.Monad	(liftM)
import Data.Maybe    (fromMaybe)

import System.Glib.FFI
import System.Glib.GList
import System.Glib.GObject              (constructNewGObject,
					 makeNewGObject)
{#import System.Glib.Properties#}
import System.Glib.Attributes
import Graphics.UI.Gtk.Abstract.Object	(makeNewObject)
{#import Graphics.UI.Gtk.SourceView.Types#}
{#import Graphics.UI.Gtk.SourceView.Signals#}
{#import Graphics.UI.Gtk.Multiline.TextIter#}

{#import Graphics.UI.Gtk.SourceView.SourceMark#}

{# context lib="gtk" prefix="gtk" #}

-- methods

-- | Create a new 'SourceBuffer', possibly
-- taking a 'TextTagTable'.
--
sourceBufferNew :: Maybe TextTagTable -> IO SourceBuffer
sourceBufferNew tt = constructNewGObject mkSourceBuffer $
  {#call unsafe source_buffer_new#}
  (fromMaybe (TextTagTable nullForeignPtr) tt)

-- | Create a new 'SourceBuffer'
-- with a 'SourceLanguage'.
--
sourceBufferNewWithLanguage :: SourceLanguage -> IO SourceBuffer
sourceBufferNewWithLanguage lang = constructNewGObject mkSourceBuffer $
  {#call unsafe source_buffer_new_with_language#} lang

-- | Controls whether syntax is highlighted in the buffer. If highlight is 'True', the text will be
-- highlighted according to the syntax patterns specified in the language set with
-- 'sourceBufferSetLanguage'. If highlight is 'False', syntax highlighting is disabled and all the
-- 'TextTag' objects that have been added by the syntax highlighting engine are removed from the
-- buffer.
sourceBufferSetHighlightSyntax :: SourceBuffer  -- ^ @buffer@    a 'SourceBuffer'.
                               -> Bool  -- ^ @highlight@ 'True' to enable syntax highlighting, 'False' to disable it.
                               -> IO ()
sourceBufferSetHighlightSyntax sb newVal =
  {#call unsafe source_buffer_set_highlight_syntax#} sb (fromBool newVal)

-- | Determines whether syntax highlighting is activated in the source buffer.
sourceBufferGetHighlightSyntax :: SourceBuffer
                               -> IO Bool  -- ^ returns 'True' if syntax highlighting is enabled, 'False' otherwise.
sourceBufferGetHighlightSyntax sb = liftM toBool $
  {#call unsafe source_buffer_get_highlight_syntax#} sb

-- | Associate a 'SourceLanguage' with the source buffer. If language is not-'Nothing' and syntax
-- highlighting is enabled (see 'sourceBufferSetHighlightSyntax', the syntax patterns defined
-- in language will be used to highlight the text contained in the buffer. If language is 'Nothing', the
-- text contained in the buffer is not highlighted.
sourceBufferSetLanguage :: SourceBuffer
                        -> Maybe SourceLanguage  -- ^ @language@ a 'SourceLanguage' to set, or 'Nothing'.
                        -> IO ()
sourceBufferSetLanguage sb lang =
  {#call unsafe source_buffer_set_language#}
    sb
    (fromMaybe (SourceLanguage nullForeignPtr) lang)

-- | Returns the 'SourceLanguage' associated with the buffer, see 'sourceBufferSetLanguage'.
sourceBufferGetLanguage :: SourceBuffer
                        -> IO (Maybe SourceLanguage) -- ^ returns 'SourceLanguage' associated with the buffer, or 'Nothing'.
sourceBufferGetLanguage sb =
  maybeNull (makeNewGObject mkSourceLanguage) $
  {#call unsafe source_buffer_get_language#} sb

-- | Controls the bracket match highlighting function in the buffer. If activated, when you position your
-- cursor over a bracket character (a parenthesis, a square bracket, etc.) the matching opening or
-- closing bracket character will be highlighted. You can specify the style with the
-- 'sourceBufferSetBracketMatchStyle' function.
sourceBufferSetHighlightMatchingBrackets :: SourceBuffer
                                         -> Bool  -- ^ @highlight@ 'True' if you want matching brackets highlighted.
                                         -> IO ()
sourceBufferSetHighlightMatchingBrackets sb newVal =
  {#call unsafe source_buffer_set_highlight_matching_brackets#} sb (fromBool newVal)

-- | Determines whether bracket match highlighting is activated for the source buffer.
sourceBufferGetHighlightMatchingBrackets :: SourceBuffer
                                         -> IO Bool  -- ^ returns 'True' if the source buffer will highlight matching brackets.
sourceBufferGetHighlightMatchingBrackets sb = liftM toBool $
  {#call unsafe source_buffer_get_highlight_matching_brackets#} sb

-- | Sets style scheme used by the buffer. If scheme is 'Nothing' no style scheme is used.
sourceBufferSetStyleScheme :: SourceBuffer
                           -> SourceStyleScheme  -- ^ @scheme@ style scheme.
                           -> IO ()
sourceBufferSetStyleScheme sb sss =
    {#call unsafe source_buffer_set_style_scheme#} sb sss

-- | Returns the 'SourceStyleScheme' currently used in buffer.
sourceBufferGetStyleScheme :: SourceBuffer
                           -> IO SourceStyleScheme -- ^ returns the 'SourceStyleScheme' set by 'sourceBufferSetStyleScheme', or 'Nothing'.
sourceBufferGetStyleScheme sb = makeNewGObject mkSourceStyleScheme $
  {#call unsafe source_buffer_get_style_scheme#} sb

-- | Sets the number of undo levels for user actions the buffer will track. If the number of user actions
-- exceeds the limit set by this function, older actions will be discarded.
--
-- If @maxUndoLevels@ is -1, no limit is set.
--
-- A new action is started whenever the function 'textBufferBeginUserAction' is called. In
-- general, this happens whenever the user presses any key which modifies the buffer, but the undo
-- manager will try to merge similar consecutive actions, such as multiple character insertions into
-- one action. But, inserting a newline does start a new action.
sourceBufferSetMaxUndoLevels :: SourceBuffer
                             -> Int  -- ^ @maxUndoLevels@ the desired maximum number of undo levels.
                             -> IO ()
sourceBufferSetMaxUndoLevels sb newVal =
  {#call unsafe source_buffer_set_max_undo_levels#} sb (fromIntegral newVal)

-- | Determines the number of undo levels the buffer will track for buffer edits.
sourceBufferGetMaxUndoLevels :: SourceBuffer
                             -> IO Int -- ^ returns the maximum number of possible undo levels or -1 if no limit is set.
sourceBufferGetMaxUndoLevels sb = liftM fromIntegral $
  {#call unsafe source_buffer_get_max_undo_levels#} sb

-- | Determines whether a source buffer can undo the last action.
sourceBufferGetCanUndo :: SourceBuffer
                       -> IO Bool -- ^ returns 'True' if it's possible to undo the last action.
sourceBufferGetCanUndo sb = liftM toBool $
  {#call unsafe source_buffer_can_undo#} sb

-- | Determines whether a source buffer can redo the last action (i.e. if the last operation was an
-- undo).
sourceBufferGetCanRedo :: SourceBuffer
                       -> IO Bool -- ^ returns 'True' if a redo is possible.
sourceBufferGetCanRedo sb = liftM toBool $
  {#call unsafe source_buffer_can_redo#} sb

-- | Undoes the last user action which modified the buffer. Use 'sourceBufferCanUndo' to check
-- whether a call to this function will have any effect.
--
-- Actions are defined as groups of operations between a call to 'textBufferBeginUserAction'
-- and 'textBufferEndUserAction' on the
-- same line.
sourceBufferUndo :: SourceBuffer -> IO ()
sourceBufferUndo sb =
  {#call source_buffer_undo#} sb

-- | Redoes the last undo operation. Use 'sourceBufferCanRedo' to check whether a call to this
-- function will have any effect.
sourceBufferRedo :: SourceBuffer -> IO ()
sourceBufferRedo sb =
  {#call source_buffer_redo#} sb

-- | Marks the beginning of a not undoable action on the buffer, disabling the undo manager. Typically
-- you would call this function before initially setting the contents of the buffer (e.g. when loading
-- a file in a text editor).
--
-- You may nest 'sourceBufferBeginNotUndoableAction' /
-- 'sourceBufferEndNotUndoableAction' blocks.
sourceBufferBeginNotUndoableAction :: SourceBuffer -> IO ()
sourceBufferBeginNotUndoableAction sb =
  {#call source_buffer_begin_not_undoable_action#} sb

-- | Marks the end of a not undoable action on the buffer. When the last not undoable block is closed
-- through the call to this function, the list of undo actions is cleared and the undo manager is
-- re-enabled.
sourceBufferEndNotUndoableAction :: SourceBuffer -> IO ()
sourceBufferEndNotUndoableAction sb =
  {#call source_buffer_end_not_undoable_action#} sb

-- | Creates a marker in the buffer of the given type.
--
-- *  A marker is
--    semantically very similar to a 'Graphics.UI.Gtk.Multiline.TextMark',
--    except it has a type
--    which is used by the 'SourceView' displaying the buffer to show a
--    pixmap on the left margin, at the line the marker is in.  Because
--    of this, a marker is generally associated to a line and not a
--    character position.  Markers are also accessible through a position
--    or range in the buffer.
--
-- *  Markers are implemented using 'Graphics.UI.Gtk.Multiline.TextMark',
--    so all characteristics
--    and restrictions to marks apply to markers too.  These includes
--    life cycle issues and 'Graphics.UI.Gtk.Multiline.TextMark.onMarkSet'
--    and 'Graphics.UI.Gtk.Multiline.TextMark.onMarkDeleted' signal
--    emissions.
--
-- *  Like a 'Graphics.UI.Gtk.Multiline.TextMark', a 'SourceMarker'
--    can be anonymous if the
--    passed name is @Nothing@.  Also, the buffer owns the markers so you
--    shouldn't unreference it.

sourceBufferCreateSourceMark :: SourceBuffer -- the buffer
                         -> Maybe String -- the name of the mark
                         -> String -- the category of the mark
                         -> TextIter -> IO SourceMark
sourceBufferCreateSourceMark sb name category iter =
  makeNewGObject mkSourceMark $
  maybeWith withCString name       $ \strPtr1 ->
  withCString category $ \strPtr2 ->
  {#call source_buffer_create_source_mark#} sb strPtr1 strPtr2 iter

-- | Returns the list of marks of the given category at line. If category is empty, all marks at line are
-- returned.
sourceBufferGetSourceMarksAtLine :: SourceBuffer  -- ^ @buffer@   a 'SourceBuffer'.
                                 -> Int -- ^ @line@     a line number.
                                 -> String -- ^ @category@ category to search for or empty
                                 -> IO [SourceMark]
sourceBufferGetSourceMarksAtLine buffer line category =
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_get_source_marks_at_line #}
    buffer
    (fromIntegral line)
    categoryPtr
  >>= readGSList
  >>= mapM (\markPtr -> makeNewGObject mkSourceMark (return markPtr))

-- | Returns the list of marks of the given category at iter. If category is empty it returns all marks at
-- iter.
sourceBufferGetSourceMarksAtIter :: SourceBuffer -- ^ @buffer@   a 'SourceBuffer'.
                                 -> TextIter -- ^ @iter@     an iterator.
                                 -> String -- ^ @category@ category to search for or empty
                                 -> IO [SourceMark]
sourceBufferGetSourceMarksAtIter buffer iter category =
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_get_source_marks_at_iter #}
    buffer
    iter
    categoryPtr
  >>= readGSList
  >>= mapM (\markPtr -> makeNewGObject mkSourceMark (return markPtr))

-- | Remove all marks of category between start and end from the buffer. If category is empty, all marks
-- in the range will be removed.
sourceBufferRemoveSourceMarks :: SourceBuffer -- ^ @buffer@   a 'SourceBuffer'.
                              -> TextIter -- ^ @start@    a 'TextIter'
                              -> TextIter -- ^ @end@      a 'TextIter'
                              -> String -- ^ @category@ category to search for or empty
                              -> IO ()
sourceBufferRemoveSourceMarks buffer start end category =
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_remove_source_marks #}
     buffer
     start
     end
     categoryPtr

-- | Moves iter to the position of the next 'SourceMark' of the given category. Returns 'True' if iter was
-- moved. If category is empty, the next source mark can be of any category.
sourceBufferForwardIterToSourceMark :: SourceBuffer -- ^ @buffer@   a 'SourceBuffer'.
                                    -> TextIter -- ^ @iter@     an iterator.
                                    -> String -- ^ @category@ category to search for or emtpy
                                    -> IO Bool -- ^ returns  whether iter moved.
sourceBufferForwardIterToSourceMark buffer iter category =
  liftM toBool $
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_forward_iter_to_source_mark #}
    buffer
    iter
    categoryPtr

-- | Moves iter to the position of the previous 'SourceMark' of the given category. Returns 'True' if iter
-- was moved. If category is empty, the previous source mark can be of any category.
sourceBufferBackwardIterToSourceMark :: SourceBuffer  -- ^ @buffer@   a 'SourceBuffer'.
                                     -> TextIter -- ^ @iter@     an iterator.
                                     -> String -- ^ @category@ category to search for or emtpy
                                     -> IO Bool -- ^ returns  whether iter moved.
sourceBufferBackwardIterToSourceMark buffer iter category =
  liftM toBool $
  withCString category $ \categoryPtr ->
  {#call gtk_source_buffer_backward_iter_to_source_mark #}
    buffer
    iter
    categoryPtr

-- | Forces buffer to analyze and highlight the given area synchronously.
--
-- Note
--
-- This is a potentially slow operation and should be used only when you need to make sure that some
-- text not currently visible is highlighted, for instance before printing.
sourceBufferEnsureHighlight :: SourceBuffer
                            -> TextIter  -- ^ @start@  start of the area to highlight.
                            -> TextIter  -- ^ @end@    end of the area to highlight.
                            -> IO ()
sourceBufferEnsureHighlight sb start end =
    {#call source_buffer_ensure_highlight#} sb start end

-- | Whether Redo operation is possible.
--
-- Default value: 'False'
--
sourceBufferCanRedo :: ReadAttr SourceBuffer Bool
sourceBufferCanRedo = readAttrFromBoolProperty "can-redo"

-- | Whether Undo operation is possible.
--
-- Default value: 'False'
sourceBufferCanUndo :: ReadAttr SourceBuffer Bool
sourceBufferCanUndo = readAttrFromBoolProperty "can-undo"

-- | Whether to highlight matching brackets in the buffer.
--
-- Default value: 'True'
--
sourceBufferHighlightMatchingBrackets :: Attr SourceBuffer Bool
sourceBufferHighlightMatchingBrackets = newAttrFromBoolProperty "highlight-matching-brackets"

-- | Whether to highlight syntax in the buffer.
--
-- Default value: 'True'
--
sourceBufferHighlightSyntax :: Attr SourceBuffer Bool
sourceBufferHighlightSyntax = newAttrFromBoolProperty "highlight-matching-brackets"

-- | Language object to get highlighting patterns from.
--
sourceBufferLanguage :: Attr SourceBuffer (Maybe SourceLanguage)
sourceBufferLanguage = newAttrFromMaybeObjectProperty "language" gTypeSourceLanguage

-- | Number of undo levels for the buffer. -1 means no limit. This property will only affect the default
-- undo manager.
--
-- Allowed values: >= GMaxulong
--
-- Default value: 1000
--
sourceBufferMaxUndoLevels :: Attr SourceBuffer Int
sourceBufferMaxUndoLevels = newAttrFromIntProperty "max-undo-levels"

-- | Style scheme. It contains styles for syntax highlighting, optionally foreground, background, cursor
-- color, current line color, and matching brackets style.
--
sourceBufferSourceStyleScheme :: Attr SourceBuffer (Maybe SourceStyleScheme)
sourceBufferSourceStyleScheme = newAttrFromMaybeObjectProperty "style-scheme" gTypeSourceStyleScheme

-- |
--
sourceBufferHighlightUpdated :: Signal SourceBuffer (TextIter -> TextIter -> IO ())
sourceBufferHighlightUpdated = Signal $ connect_BOXED_BOXED__NONE "highlight-updated" mkTextIterCopy mkTextIterCopy

-- |
--
sourceBufferRedoSignal :: Signal SourceBuffer (IO ())
sourceBufferRedoSignal = Signal $ connect_NONE__NONE "redo"

-- |
--
sourceBufferUndoSignal :: Signal SourceBuffer (IO ())
sourceBufferUndoSignal = Signal $ connect_NONE__NONE "undo"

-- | The 'sourceBufferMarkUpdated' signal is emitted each time a mark is added to, moved or removed from the
-- buffer.
--
sourceBufferSourceMarkUpdated :: Signal SourceBuffer (TextMark -> IO ())
sourceBufferSourceMarkUpdated = Signal $ connect_OBJECT__NONE "source-mark-updated"


[project @ 2002-07-17 16:00:41 by juhp] (treeViewInsertColumnWithAttributes): Haskell implementation to avoid binding to original variad function.

-- -*-haskell-*-
--  GIMP Toolkit (GTK) @entry Widget TreeView@
--
--  Author : Axel Simon
--
--  Created: 9 May 2001
--
--  Version $Revision: 1.5 $ from $Date: 2002/07/17 16:00:41 $
--
--  Copyright (c) 2001 Axel Simon
--
--  This file is free software; you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation; either version 2 of the License, or
--  (at your option) any later version.
--
--  This file is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
-- @description@ --------------------------------------------------------------
--
-- * This widget constitutes the main widget for displaying lists and other
--   structured data.
--
-- @documentation@ ------------------------------------------------------------
--
--
-- @todo@ ---------------------------------------------------------------------
--
-- * treeViewGetPathAtPos is surely useful but has to be used with events in
--   order not to pass GdkWindows around.
--
module TreeView(
  TreeView,
  TreeViewClass,
  castToTreeView,
  treeViewNew,
  treeViewNewWithModel,
  treeViewGetModel,
  treeViewSetModel,
  treeViewGetSelection,
  treeViewGetHadjustment,
  treeViewSetHadjustment,
  treeViewGetVadjustment,
  treeViewSetVadjustment,
  treeViewGetHeadersVisible,
  treeViewSetHeadersVisible,
  treeViewColumnsAutosize,
  treeViewSetHeadersClickable,
  treeViewAppendColumn,
  treeViewRemoveColumn,
  treeViewInsertColumn,
  treeViewInsertColumnWithAttributes,
  treeViewGetColumn,
  treeViewScrollToCell,
  treeViewExpandAll,
  treeViewCollapseAll,
  treeViewCollapseRow
  ) where

import Monad	(liftM)
import Maybe	(fromMaybe)
import Foreign
import UTFCForeign
import Structs	(nullForeignPtr)
import GObject	(objectRef, objectUnref)
import Object	(makeNewObject)
{#import Hierarchy#}
{#import Signal#}
{#import TreeModel#}
{#import TreeViewColumn#}

{# context lib="gtk" prefix="gtk" #}

-- methods

-- @constructor treeViewNew@ Make a new TreeView widget.
--
treeViewNew :: IO TreeView
treeViewNew  = makeNewObject mkTreeView (liftM castPtr {#call tree_view_new#})

-- @constructor treeViewNewWithModel@ Make a new TreeView widget with
-- @ref arg tm@ as the storage model.
--
treeViewNewWithModel :: TreeModelClass tm => tm -> IO TreeView
treeViewNewWithModel tm = makeNewObject mkTreeView $ liftM castPtr $
  {#call tree_view_new_with_model#} (toTreeModel tm)

-- @method treeViewGetModel@ Retrieve the TreeModel that supplies the data for
-- this TreeView. Returns Nothing if no model is currently set.
--
treeViewGetModel :: TreeViewClass tv => tv -> IO (Maybe TreeModel)
treeViewGetModel tv = do
  tmPtr <- {#call unsafe tree_view_get_model#} (toTreeView tv)
  if tmPtr==nullPtr then return Nothing else do
    objectRef tmPtr
    liftM (Just . mkTreeModel) $ newForeignPtr tmPtr (objectUnref tmPtr)

-- @method treeViewSetModel@ Set the TreeModel for the current View.
--
treeViewSetModel :: (TreeViewClass tv, TreeModelClass tm) => tv -> tm -> IO ()
treeViewSetModel tv tm =
  {#call tree_view_set_model#} (toTreeView tv) (toTreeModel tm)

-- @method treeViewGetSelection@ Retrieve a @ref type TreeSelection@ that
-- holds the current selected nodes of the View.
--
treeViewGetSelection :: TreeViewClass tv => tv -> IO TreeSelection
treeViewGetSelection tv = makeNewObject mkTreeSelection $
  {#call unsafe tree_view_get_selection#} (toTreeView tv)

-- @method treeViewGetHadjustment@ Get the @ref arg Adjustment@ that
-- represents the horizontal aspect.
--
treeViewGetHadjustment :: TreeViewClass tv => tv -> IO (Maybe Adjustment)
treeViewGetHadjustment tv = do
  adjPtr <- {#call unsafe tree_view_get_hadjustment#} (toTreeView tv)
  if adjPtr==nullPtr then return Nothing else do
    liftM Just $ makeNewObject mkAdjustment (return adjPtr)

-- @method treeViewSetHadjustment@ Set the @ref arg Adjustment@ that controls
-- the horizontal aspect. If @ref arg adj@ is Nothing then set no Adjustment
-- widget.
--
treeViewSetHadjustment :: TreeViewClass tv => (Maybe Adjustment) -> tv -> IO ()
treeViewSetHadjustment adj tv = {#call tree_view_set_hadjustment#}
  (toTreeView tv) (fromMaybe (mkAdjustment nullForeignPtr) adj)

-- @method treeViewGetVadjustment@ Get the @ref arg Adjustment@ that
-- represents the vertical aspect.
--
treeViewGetVadjustment :: TreeViewClass tv => tv -> IO (Maybe Adjustment)
treeViewGetVadjustment tv = do
  adjPtr <- {#call unsafe tree_view_get_vadjustment#} (toTreeView tv)
  if adjPtr==nullPtr then return Nothing else do
    liftM Just $ makeNewObject mkAdjustment (return adjPtr)

-- @method treeViewSetVadjustment@ Set the @ref arg Adjustment@ that controls
-- the vertical aspect. If @ref arg adj@ is Nothing then set no Adjustment
-- widget.
--
treeViewSetVadjustment :: TreeViewClass tv => (Maybe Adjustment) -> tv -> IO ()
treeViewSetVadjustment adj tv = {#call tree_view_set_vadjustment#}
  (toTreeView tv) (fromMaybe (mkAdjustment nullForeignPtr) adj)

-- @method treeViewGetHeadersVisible@ Query if the column headers are visible.
--
treeViewGetHeadersVisible :: TreeViewClass tv => tv -> IO Bool
treeViewGetHeadersVisible tv = liftM toBool $
  {#call unsafe tree_view_get_headers_visible#} (toTreeView tv)

-- @method treeViewSetHeadersVisible@ Set the visibility state of the column
-- headers.
--
treeViewSetHeadersVisible :: TreeViewClass tv => tv -> Bool -> IO ()
treeViewSetHeadersVisible tv vis = {#call tree_view_set_headers_visible#}
  (toTreeView tv) (fromBool vis)

-- @method treeViewColumnsAutosize@ Resize the columns to their optimal size.
--
treeViewColumnsAutosize :: TreeViewClass tv => tv -> IO ()
treeViewColumnsAutosize tv =
  {#call tree_view_columns_autosize#} (toTreeView tv)

-- @method treeViewSetHeadersClickable@ Set wether the columns headers are
-- sensitive to mouse clicks.
--
-- *  @literal@
--

--
treeViewSetHeadersClickable :: TreeViewClass tv => tv -> Bool -> IO ()
treeViewSetHeadersClickable tv click = {#call tree_view_set_headers_clickable#}
  (toTreeView tv) (fromBool click)

-- @method treeViewAppendColumn@ Append a new column to the TreeView. Returns
-- the new number of columns.
--
treeViewAppendColumn :: TreeViewClass tv => tv -> TreeViewColumn -> IO Int
treeViewAppendColumn tv tvc = liftM fromIntegral $
  {#call tree_view_append_column#} (toTreeView tv) tvc

-- @method treeViewRemoveColumn@ Remove column @ref arg tvc@ from the TreeView
-- widget. The number of remaining columns is returned.
--
treeViewRemoveColumn :: TreeViewClass tv => tv -> TreeViewColumn -> IO Int
treeViewRemoveColumn tv tvc = liftM fromIntegral $
  {#call tree_view_remove_column#} (toTreeView tv) tvc

-- @method treeViewInsertColumn@ Inserts column @ref arg tvc@ into the
-- TreeView widget at the position @ref arg pos@. Returns the number of
-- columns after insertion. Specify -1 for @ref arg pos@ to insert the column
-- at the end.
--
treeViewInsertColumn :: TreeViewClass tv => tv -> TreeViewColumn -> Int ->
                        IO Int
treeViewInsertColumn tv tvc pos = liftM fromIntegral $
  {#call tree_view_insert_column#} (toTreeView tv) tvc (fromIntegral pos)

-- @method treeViewInsertColumnWithAttributes@ Inserts new column into the
-- TreeView @ref arg tv@ at position @ref arg pos@ with title
-- @ref argtitle@, cell renderer @ref arg cr@ and attributes
-- @ref arg attribs@. Specify -1 for @ref arg pos@ to insert the column at
-- the end.
--
treeViewInsertColumnWithAttributes :: (TreeViewClass tv, CellRendererClass cr)
   => tv -> Int -> String -> cr -> [(String,Int)] -> IO ()
treeViewInsertColumnWithAttributes tv pos title cr attribs =
    do
    column <- treeViewColumnNew
    treeViewColumnSetTitle column title
    treeViewColumnPackStart column cr True
    treeViewColumnAddAttributes column cr attribs
    treeViewInsertColumn tv column pos
    return ()

-- @method treeViewGetColumn@ Retrieve the @ref arg pos@ th columns of
-- TreeView. If the index is out of range Nothing is returned.
--
treeViewGetColumn :: TreeViewClass tv => tv -> Int -> IO (Maybe TreeViewColumn)
treeViewGetColumn tv pos = do
  tvcPtr <- {#call unsafe tree_view_get_column#} (toTreeView tv)
    (fromIntegral pos)
  if tvcPtr==nullPtr then return Nothing else
    liftM Just $ makeNewObject mkTreeViewColumn (return tvcPtr)

-- @method treeViewScrollToCell@ Scroll to a cell specified by @ref arg path@
-- and @ref arg tvc@. The cell is aligned within the TreeView widget as
-- follows: horizontally by @ref arg hor@ from left (0.0) to right (1.0) and
-- vertically by @ref arg ver@ from top (0.0) to buttom (1.0).
--
treeViewScrollToCell :: TreeViewClass tv => tv -> TreePath -> TreeViewColumn ->
                        Maybe (Float,Float) -> IO ()
treeViewScrollToCell tv path tvc (Just (ver,hor)) =
  {#call tree_view_scroll_to_cell#}
  (toTreeView tv) path tvc 1 (realToFrac ver) (realToFrac hor)
treeViewScrollToCell tv path tvc Nothing =
  {#call tree_view_scroll_to_cell#}
  (toTreeView tv) path tvc 0 0.0 0.0

-- @method treeViewExpandAll@ Expand all nodes in the TreeView.
--
treeViewExpandAll :: TreeViewClass tv => tv -> IO ()
treeViewExpandAll tv =
  {#call tree_view_expand_all#} (toTreeView tv)

-- @method treeViewCollapseAll@ Collapse all nodes in the TreeView.
--
treeViewCollapseAll :: TreeViewClass tv => tv -> IO ()
treeViewCollapseAll tv =
  {#call tree_view_collapse_all#} (toTreeView tv)

-- Expand a node that is specified by @path. If the flag @all is True every
-- child will be expanded recursively. Returns True if the row existed and
-- had children.(EXPORTED)
--
treeViewExpandRow :: TreeViewClass tv => TreePath -> Bool -> tv -> IO Bool
treeViewExpandRow path all tv = liftM toBool $
  {#call tree_view_expand_row#} (toTreeView tv) path (fromBool all)

-- @method treeViewCollapseRow@ Collapse a row. Returns True if the row
-- existed.
--
treeViewCollapseRow :: TreeViewClass tv => tv -> TreePath -> IO Bool
treeViewCollapseRow tv path = liftM toBool $
  {#call tree_view_collapse_row#} (toTreeView tv) path

-- -*-haskell-*-
--  GIMP Toolkit (GTK) @entry Widget TreeView@
--
--  Author : Axel Simon
--
--  Created: 9 May 2001
--
--  Version $Revision: 1.4 $ from $Date: 2002/07/08 13:22:46 $
--
--  Copyright (c) 2001 Axel Simon
--
--  This file is free software; you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation; either version 2 of the License, or
--  (at your option) any later version.
--
--  This file is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
-- @description@ --------------------------------------------------------------
--
-- * This widget constitutes the main widget for displaying lists and other
--   structured data.
--
-- @documentation@ ------------------------------------------------------------
--
--
-- @todo@ ---------------------------------------------------------------------
--
-- * treeViewGetPathAtPos is surely useful but has to be used with events in
--   order not to pass GdkWindows around.
--
module TreeView(
  TreeView,
  TreeViewClass,
  castToTreeView,
  treeViewNew,
  treeViewNewWithModel,
  treeViewGetModel,
  treeViewSetModel,
  treeViewGetSelection,
  treeViewGetHadjustment,
  treeViewSetHadjustment,
  treeViewGetVadjustment,
  treeViewSetVadjustment,
  treeViewGetHeadersVisible,
  treeViewSetHeadersVisible,
  treeViewColumnsAutosize,
  treeViewSetHeadersClickable,
  treeViewAppendColumn,
  treeViewRemoveColumn,
  treeViewInsertColumn,
  treeViewGetColumn,
  treeViewScrollToCell,
  treeViewExpandAll,
  treeViewCollapseAll,
  treeViewCollapseRow
  ) where

import Monad	(liftM)
import Maybe	(fromMaybe)
import Foreign
import UTFCForeign
import Structs	(nullForeignPtr)
import GObject	(objectRef, objectUnref)
import Object	(makeNewObject)
{#import Hierarchy#}
{#import Signal#}
{#import TreeModel#}

{# context lib="gtk" prefix="gtk" #}

-- methods

-- @constructor treeViewNew@ Make a new TreeView widget.
--
treeViewNew :: IO TreeView
treeViewNew  = makeNewObject mkTreeView (liftM castPtr {#call tree_view_new#})

-- @constructor treeViewNewWithModel@ Make a new TreeView widget with
-- @ref arg tm@ as the storage model.
--
treeViewNewWithModel :: TreeModelClass tm => tm -> IO TreeView
treeViewNewWithModel tm = makeNewObject mkTreeView $ liftM castPtr $
  {#call tree_view_new_with_model#} (toTreeModel tm)

-- @method treeViewGetModel@ Retrieve the TreeModel that supplies the data for
-- this TreeView. Returns Nothing if no model is currently set.
--
treeViewGetModel :: TreeViewClass tv => tv -> IO (Maybe TreeModel)
treeViewGetModel tv = do
  tmPtr <- {#call unsafe tree_view_get_model#} (toTreeView tv)
  if tmPtr==nullPtr then return Nothing else do
    objectRef tmPtr
    liftM (Just . mkTreeModel) $ newForeignPtr tmPtr (objectUnref tmPtr)

-- @method treeViewSetModel@ Set the TreeModel for the current View.
--
treeViewSetModel :: (TreeViewClass tv, TreeModelClass tm) => tv -> tm -> IO ()
treeViewSetModel tv tm =
  {#call tree_view_set_model#} (toTreeView tv) (toTreeModel tm)

-- @method treeViewGetSelection@ Retrieve a @ref type TreeSelection@ that
-- holds the current selected nodes of the View.
--
treeViewGetSelection :: TreeViewClass tv => tv -> IO TreeSelection
treeViewGetSelection tv = makeNewObject mkTreeSelection $
  {#call unsafe tree_view_get_selection#} (toTreeView tv)

-- @method treeViewGetHadjustment@ Get the @ref arg Adjustment@ that
-- represents the horizontal aspect.
--
treeViewGetHadjustment :: TreeViewClass tv => tv -> IO (Maybe Adjustment)
treeViewGetHadjustment tv = do
  adjPtr <- {#call unsafe tree_view_get_hadjustment#} (toTreeView tv)
  if adjPtr==nullPtr then return Nothing else do
    liftM Just $ makeNewObject mkAdjustment (return adjPtr)

-- @method treeViewSetHadjustment@ Set the @ref arg Adjustment@ that controls
-- the horizontal aspect. If @ref arg adj@ is Nothing then set no Adjustment
-- widget.
--
treeViewSetHadjustment :: TreeViewClass tv => (Maybe Adjustment) -> tv -> IO ()
treeViewSetHadjustment adj tv = {#call tree_view_set_hadjustment#}
  (toTreeView tv) (fromMaybe (mkAdjustment nullForeignPtr) adj)

-- @method treeViewGetVadjustment@ Get the @ref arg Adjustment@ that
-- represents the vertical aspect.
--
treeViewGetVadjustment :: TreeViewClass tv => tv -> IO (Maybe Adjustment)
treeViewGetVadjustment tv = do
  adjPtr <- {#call unsafe tree_view_get_vadjustment#} (toTreeView tv)
  if adjPtr==nullPtr then return Nothing else do
    liftM Just $ makeNewObject mkAdjustment (return adjPtr)

-- @method treeViewSetVadjustment@ Set the @ref arg Adjustment@ that controls
-- the vertical aspect. If @ref arg adj@ is Nothing then set no Adjustment
-- widget.
--
treeViewSetVadjustment :: TreeViewClass tv => (Maybe Adjustment) -> tv -> IO ()
treeViewSetVadjustment adj tv = {#call tree_view_set_vadjustment#}
  (toTreeView tv) (fromMaybe (mkAdjustment nullForeignPtr) adj)

-- @method treeViewGetHeadersVisible@ Query if the column headers are visible.
--
treeViewGetHeadersVisible :: TreeViewClass tv => tv -> IO Bool
treeViewGetHeadersVisible tv = liftM toBool $
  {#call unsafe tree_view_get_headers_visible#} (toTreeView tv)

-- @method treeViewSetHeadersVisible@ Set the visibility state of the column
-- headers.
--
treeViewSetHeadersVisible :: TreeViewClass tv => tv -> Bool -> IO ()
treeViewSetHeadersVisible tv vis = {#call tree_view_set_headers_visible#}
  (toTreeView tv) (fromBool vis)

-- @method treeViewColumnsAutosize@ Resize the columns to their optimal size.
--
treeViewColumnsAutosize :: TreeViewClass tv => tv -> IO ()
treeViewColumnsAutosize tv =
  {#call tree_view_columns_autosize#} (toTreeView tv)

-- @method treeViewSetHeadersClickable@ Set wether the columns headers are
-- sensitive to mouse clicks.
--
-- *  @literal@
--

--
treeViewSetHeadersClickable :: TreeViewClass tv => tv -> Bool -> IO ()
treeViewSetHeadersClickable tv click = {#call tree_view_set_headers_clickable#}
  (toTreeView tv) (fromBool click)

-- @method treeViewAppendColumn@ Append a new column to the TreeView. Returns
-- the new number of columns.
--
treeViewAppendColumn :: TreeViewClass tv => tv -> TreeViewColumn -> IO Int
treeViewAppendColumn tv tvc = liftM fromIntegral $
  {#call tree_view_append_column#} (toTreeView tv) tvc

-- @method treeViewRemoveColumn@ Remove column @ref arg tvc@ from the TreeView
-- widget. The number of remaining columns is returned.
--
treeViewRemoveColumn :: TreeViewClass tv => tv -> TreeViewColumn -> IO Int
treeViewRemoveColumn tv tvc = liftM fromIntegral $
  {#call tree_view_remove_column#} (toTreeView tv) tvc

-- @method treeViewInsertColumn@ Inserts column @ref arg tvc@ into the
-- TreeView widget at the position @ref arg pos@. Returns the number of
-- columns after insertion. Specify -1 for @ref arg pos@ to insert the column
-- at the end.
--
treeViewInsertColumn :: TreeViewClass tv => tv -> TreeViewColumn -> Int ->
                        IO Int
treeViewInsertColumn tv tvc pos = liftM fromIntegral $
  {#call tree_view_insert_column#} (toTreeView tv) tvc (fromIntegral pos)

-- @method treeViewGetColumn@ Retrieve the @ref arg pos@ th columns of
-- TreeView. If the index is out of range Nothing is returned.
--
treeViewGetColumn :: TreeViewClass tv => tv -> Int -> IO (Maybe TreeViewColumn)
treeViewGetColumn tv pos = do
  tvcPtr <- {#call unsafe tree_view_get_column#} (toTreeView tv)
    (fromIntegral pos)
  if tvcPtr==nullPtr then return Nothing else
    liftM Just $ makeNewObject mkTreeViewColumn (return tvcPtr)

-- @method treeViewScrollToCell@ Scroll to a cell specified by @ref arg path@
-- and @ref arg tvc@. The cell is aligned within the TreeView widget as
-- follows: horizontally by @ref arg hor@ from left (0.0) to right (1.0) and
-- vertically by @ref arg ver@ from top (0.0) to buttom (1.0).
--
treeViewScrollToCell :: TreeViewClass tv => tv -> TreePath -> TreeViewColumn ->
                        Maybe (Float,Float) -> IO ()
treeViewScrollToCell tv path tvc (Just (ver,hor)) =
  {#call tree_view_scroll_to_cell#}
  (toTreeView tv) path tvc 1 (realToFrac ver) (realToFrac hor)
treeViewScrollToCell tv path tvc Nothing =
  {#call tree_view_scroll_to_cell#}
  (toTreeView tv) path tvc 0 0.0 0.0

-- @method treeViewExpandAll@ Expand all nodes in the TreeView.
--
treeViewExpandAll :: TreeViewClass tv => tv -> IO ()
treeViewExpandAll tv =
  {#call tree_view_expand_all#} (toTreeView tv)

-- @method treeViewCollapseAll@ Collapse all nodes in the TreeView.
--
treeViewCollapseAll :: TreeViewClass tv => tv -> IO ()
treeViewCollapseAll tv =
  {#call tree_view_collapse_all#} (toTreeView tv)

-- Expand a node that is specified by @path. If the flag @all is True every
-- child will be expanded recursively. Returns True if the row existed and
-- had children.(EXPORTED)
--
treeViewExpandRow :: TreeViewClass tv => TreePath -> Bool -> tv -> IO Bool
treeViewExpandRow path all tv = liftM toBool $
  {#call tree_view_expand_row#} (toTreeView tv) path (fromBool all)

-- @method treeViewCollapseRow@ Collapse a row. Returns True if the row
-- existed.
--
treeViewCollapseRow :: TreeViewClass tv => tv -> TreePath -> IO Bool
treeViewCollapseRow tv path = liftM toBool $
  {#call tree_view_collapse_row#} (toTreeView tv) path