[Xfce4-commits] <mousepad:master> * mousepad/mousepad-document.c: Fix column number in statusbar. First column is 0 and not 1. * mousepad/mousepad-dialogs.c: Improve the go to dialog. You can now set the column number too. * mousepad/mousepad-window{.c, -ui.xml}: Improve the menu layout big time. Make mnemonics consistent right now. A couple of name, tooltip and keybindings changes. Internal names make more sense now. * mousepad/mousepad-{window, view}.c Add option to paste from history. The history holds the last 9 history cut/copied items from Mousepad. * mousepad/mousepad-window.c: New from template menu. Works the same as the implementation in Thunar. Menu is generated the first time the file menu is shown. Same for the recent menu. * mousepad/mousepad-{window, view}.c: Add option to toggle between column and normal selections. Put it in View -> Change to Column Selection. To make this work properly I've removed multi selection. Code got much easier and a co uple of complex functions were dropped. * mousepad/mousepad-window{.c, -ui.xml}: Put search menu items in the edit menu, since you will most likely access them from keybindings most of the time. * mousepad/mousepad-window.c: Cleanuped up a lot of functions. * mousepad/mousepad-window.c: Check if files exists when generating the recent menu, remove it when it was not found. Also unref the action after adding it to the action group, fixes an ugly memory leak, since the recent info isn't released eighter. * mousepad/mousepad-util.c: Add faster function to escape underscores in the recent menu. Drop the previous function used for this. * mousepad/mousepad-private.h: Add macros around g_object_(get/set) _qdata and use them instead of the existing g_object_(get/set) _data functions. * mousepad/mousepad-view.c: Fix indent with (shift) tab. * mousepad/mousepad-view.c: Improve line number drawing. Only redraw the line numbers in the expose area and some other cha nges to reduce the amount of redraws and iter calls. * mousepad/mousepad-view.c: Use the IM to type in multi selections, the previous way was deprecated and this fixes a couple of weird issues. * mousepad/mousepad-view.c: Show realtime selection size in column selections. * mousepad/mousepad-{document, view, window}.c: Put selection change in a separate signal to avoid multiple update the the action group. * mousepad/mousepad-view.c: Avoid a lot of statusbar updates and column selection redraws during dragging by comparing the old and new cursor position. On the other hand, the 'only draw the visible area during drag' trick has been partly removed to properly display the selection length during a column draw that covers more then the window height. * mousepad/mousepad-{util, view}.c: Add functions to change the case of a selection. * mousepad/mousepad-view.c: Add function to replace tabs with spaces and vice versa. The replacements are inlined, so you don't see visual changes in the document. Actions are not usable during column selections. * mousepad/mousepad-window.c: Make the arrow buttons in the notebook work. * mousepad/mousepad-window.c: Close document on middle click on the tab, this is a stupid feature, but since everyone requests it on apps with tabs: add it to save a bugzilla report. * mousepad/mousepad-{window, view}.c: Add actions to increase or decrease the indentation of line(s) using the menu or keybindings. * mousepad/mousepad-{window, view}.c: Add an action to duplicate a line or selection. Only work for normal selections or no selection. * mousepad/mousepad-{window, view}.c: Add an action to move the selected lines up and down. Not implemented for column selections (yet). Menu actions are insensitive when there is no regual selection. * mousepad/mousepad-{window, view}.c: Add option to strip trailing spaces and tabs. * mousepad/mousepad-window.c: Add a file to the recent history aft er saving it under another name. * mousepad/mousepad-window{.c, -ui.xml}: Add line ending type in the document menu. * mousepad/mousepad-window.c: Avoid one menu update when adding or removing a new document to the window. * mousepad/mousepad-document.c: Change tab label color when the document is modified or readonly. * ChangeLog: Properly break lines.

Nick Schermer noreply at xfce.org
Sat May 5 21:31:03 CEST 2012


Updating branch refs/heads/master
         to 562a27b0824e528841b1a58b01d8c9978f4bd05e (commit)
       from 976c9707d60945030612eaf79db2e577135fe4ef (commit)

commit 562a27b0824e528841b1a58b01d8c9978f4bd05e
Author: Nick Schermer <nick at xfce.org>
Date:   Thu Dec 6 20:11:21 2007 +0000

    * mousepad/mousepad-document.c: Fix column number in statusbar.
      First column is 0 and not 1.
    * mousepad/mousepad-dialogs.c: Improve the go to dialog. You can now
      set the column number too.
    * mousepad/mousepad-window{.c,-ui.xml}: Improve the menu layout big
      time. Make mnemonics consistent right now. A couple of name,
      tooltip and keybindings changes. Internal names make more sense
      now.
    * mousepad/mousepad-{window,view}.c Add option to paste from
      history. The history holds the last 9 history cut/copied items
      from Mousepad.
    * mousepad/mousepad-window.c: New from template menu. Works the
      same as the implementation in Thunar. Menu is generated the first
      time the file menu is shown. Same for the recent menu.
    * mousepad/mousepad-{window,view}.c: Add option to toggle between
      column and normal selections. Put it in View -> Change to Column
      Selection. To make this work properly I've removed multi
      selection. Code got much easier and a couple of complex functions
      were dropped.
    * mousepad/mousepad-window{.c,-ui.xml}: Put search menu items in
      the edit menu, since you will most likely access them from
      keybindings most of the time.
    * mousepad/mousepad-window.c: Cleanuped up a lot of functions.
    * mousepad/mousepad-window.c: Check if files exists when generating
      the recent menu, remove it when it was not found. Also unref the
      action after adding it to the action group, fixes an ugly memory
      leak, since the recent info isn't released eighter.
    * mousepad/mousepad-util.c: Add faster function to escape
      underscores in the recent menu. Drop the previous function used
      for this.
    * mousepad/mousepad-private.h: Add macros around g_object_(get/set)
      _qdata and use them instead of the existing g_object_(get/set)
      _data functions.
    * mousepad/mousepad-view.c: Fix indent with (shift) tab.
    * mousepad/mousepad-view.c: Improve line number drawing. Only
      redraw the line numbers in the expose area and some other changes
      to reduce the amount of redraws and iter calls.
    * mousepad/mousepad-view.c: Use the IM to type in multi selections,
      the previous way was deprecated and this fixes a couple of weird
      issues.
    * mousepad/mousepad-view.c: Show realtime selection size in column
      selections.
    * mousepad/mousepad-{document,view,window}.c: Put selection change
      in a separate signal to avoid multiple update the the action
      group.
    * mousepad/mousepad-view.c: Avoid a lot of statusbar updates and
      column selection redraws during dragging by comparing the old and
      new cursor position. On the other hand, the 'only draw the visible
      area during drag' trick has been partly removed to properly
      display the selection length during a column draw that covers
      more then the window height.
    * mousepad/mousepad-{util,view}.c: Add functions to change the case
      of a selection.
    * mousepad/mousepad-view.c: Add function to replace tabs with spaces
      and vice versa. The replacements are inlined, so you don't see
      visual changes in the document. Actions are not usable during
      column selections.
    * mousepad/mousepad-window.c: Make the arrow buttons in the notebook
      work.
    * mousepad/mousepad-window.c: Close document on middle click on the
      tab, this is a stupid feature, but since everyone requests it on
      apps with tabs: add it to save a bugzilla report.
    * mousepad/mousepad-{window,view}.c: Add actions to increase or
      decrease the indentation of line(s) using the menu or keybindings.
    * mousepad/mousepad-{window,view}.c: Add an action to duplicate a
      line or selection. Only work for normal selections or no
      selection.
    * mousepad/mousepad-{window,view}.c: Add an action to move the
      selected lines up and down. Not implemented for column selections
      (yet). Menu actions are insensitive when there is no regual
      selection.
    * mousepad/mousepad-{window,view}.c: Add option to strip trailing
      spaces and tabs.
    * mousepad/mousepad-window.c: Add a file to the recent history
      after saving it under another name.
    * mousepad/mousepad-window{.c,-ui.xml}: Add line ending type in the
      document menu.
    * mousepad/mousepad-window.c: Avoid one menu update when adding or
      removing a new document to the window.
    * mousepad/mousepad-document.c: Change tab label color when the
      document is modified or readonly.
    * ChangeLog: Properly break lines.
    
    
    (Old svn revision: 26441)

 ChangeLog                           |  589 ++++++----
 mousepad/main.c                     |   12 +-
 mousepad/mousepad-application.c     |   39 +-
 mousepad/mousepad-dialogs.c         |  199 ++--
 mousepad/mousepad-dialogs.h         |   38 +-
 mousepad/mousepad-document.c        |  134 ++-
 mousepad/mousepad-document.h        |   35 +-
 mousepad/mousepad-encoding-dialog.c |    2 +-
 mousepad/mousepad-file.c            |    8 +-
 mousepad/mousepad-file.h            |    4 +-
 mousepad/mousepad-private.h         |   16 +-
 mousepad/mousepad-search-bar.c      |   12 +-
 mousepad/mousepad-util.c            |  135 ++-
 mousepad/mousepad-util.h            |    6 +
 mousepad/mousepad-view.c            | 1602 ++++++++++++++++---------
 mousepad/mousepad-view.h            |   51 +-
 mousepad/mousepad-window-ui.xml     |   81 +-
 mousepad/mousepad-window.c          | 2264 ++++++++++++++++++++++++++---------
 po/mousepad.pot                     |  584 +++++++---
 19 files changed, 4055 insertions(+), 1756 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 711aa0d..3f3b0a1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,113 +1,222 @@
+2007-xx-xx	Nick Schermer <nick at xfce.org>
+
+	* mousepad/mousepad-document.c: Fix column number in statusbar.
+	  First column is 0 and not 1.
+	* mousepad/mousepad-dialogs.c: Improve the go to dialog. You can now
+	  set the column number too.
+	* mousepad/mousepad-window{.c,-ui.xml}: Improve the menu layout big
+	  time. Make mnemonics consistent right now. A couple of name,
+	  tooltip and keybindings changes. Internal names make more sense
+	  now.
+	* mousepad/mousepad-{window,view}.c Add option to paste from
+	  history. The history holds the last 9 history cut/copied items
+	  from Mousepad.
+	* mousepad/mousepad-window.c: New from template menu. Works the
+	  same as the implementation in Thunar. Menu is generated the first
+	  time the file menu is shown. Same for the recent menu.
+	* mousepad/mousepad-{window,view}.c: Add option to toggle between
+	  column and normal selections. Put it in View -> Change to Column
+	  Selection. To make this work properly I've removed multi
+	  selection. Code got much easier and a couple of complex functions
+	  were dropped.
+	* mousepad/mousepad-window{.c,-ui.xml}: Put search menu items in
+	  the edit menu, since you will most likely access them from
+	  keybindings most of the time.
+	* mousepad/mousepad-window.c: Cleanuped up a lot of functions.
+	* mousepad/mousepad-window.c: Check if files exists when generating
+	  the recent menu, remove it when it was not found. Also unref the
+	  action after adding it to the action group, fixes an ugly memory
+	  leak, since the recent info isn't released eighter.
+	* mousepad/mousepad-util.c: Add faster function to escape
+	  underscores in the recent menu. Drop the previous function used
+	  for this.
+	* mousepad/mousepad-private.h: Add macros around g_object_(get/set)
+	  _qdata and use them instead of the existing g_object_(get/set)
+	  _data functions.
+	* mousepad/mousepad-view.c: Fix indent with (shift) tab.
+	* mousepad/mousepad-view.c: Improve line number drawing. Only
+	  redraw the line numbers in the expose area and some other changes
+	  to reduce the amount of redraws and iter calls.
+	* mousepad/mousepad-view.c: Use the IM to type in multi selections,
+	  the previous way was deprecated and this fixes a couple of weird
+	  issues.
+	* mousepad/mousepad-view.c: Show realtime selection size in column
+	  selections.
+	* mousepad/mousepad-{document,view,window}.c: Put selection change
+	  in a separate signal to avoid multiple update the the action
+	  group.
+	* mousepad/mousepad-view.c: Avoid a lot of statusbar updates and
+	  column selection redraws during dragging by comparing the old and
+	  new cursor position. On the other hand, the 'only draw the visible
+	  area during drag' trick has been partly removed to properly
+	  display the selection length during a column draw that covers
+	  more then the window height.
+	* mousepad/mousepad-{util,view}.c: Add functions to change the case
+	  of a selection.
+	* mousepad/mousepad-view.c: Add function to replace tabs with spaces
+	  and vice versa. The replacements are inlined, so you don't see
+	  visual changes in the document. Actions are not usable during
+	  column selections.
+	* mousepad/mousepad-window.c: Make the arrow buttons in the notebook
+	  work.
+	* mousepad/mousepad-window.c: Close document on middle click on the
+	  tab, this is a stupid feature, but since everyone requests it on
+	  apps with tabs: add it to save a bugzilla report.
+	* mousepad/mousepad-{window,view}.c: Add actions to increase or
+	  decrease the indentation of line(s) using the menu or keybindings.
+	* mousepad/mousepad-{window,view}.c: Add an action to duplicate a
+	  line or selection. Only work for normal selections or no
+	  selection.
+	* mousepad/mousepad-{window,view}.c: Add an action to move the
+	  selected lines up and down. Not implemented for column selections
+	  (yet). Menu actions are insensitive when there is no regual
+	  selection.
+	* mousepad/mousepad-{window,view}.c: Add option to strip trailing
+	  spaces and tabs.
+	* mousepad/mousepad-window.c: Add a file to the recent history
+	  after saving it under another name.
+	* mousepad/mousepad-window{.c,-ui.xml}: Add line ending type in the
+	  document menu.
+	* mousepad/mousepad-window.c: Avoid one menu update when adding or
+	  removing a new document to the window.
+	* mousepad/mousepad-document.c: Change tab label color when the
+	  document is modified or readonly.
+	* ChangeLog: Properly break lines.
+
+
 2007-11-29	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-document.c: Make tab close button a bit smaller.
 
 
 2007-11-29	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-window.c: Use a box for packing the window elements.
-	  A table was not really needed, and boxes are a bit faster in calculating
-	  child sizes.
+
+	* mousepad/mousepad-window.c: Use a box for packing the window
+	  elements. A table was not really needed, and boxes are a bit
+	  faster in calculating child sizes.
 	* mousepad/mousepad-window.c: Remove unused variable.
 
 
 2007-11-29	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-print.c: Use bold attribute for labels, so there
-	  is no html in the strings.
+
+	* mousepad/mousepad-print.c: Use bold attribute for labels, so
+	  there is no html in the strings.
 
 
 2007-11-29	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-utils.c: Add functions that extent the default
 	  Gtk word start/end function. Use them in the search functions,
 	  transpose and double click selection.
-	* mousepad/mousepad-view.c: Implement transpose for multi selections.
+	* mousepad/mousepad-view.c: Implement transpose for multi
+	  selections.
 	* mousepad/mousepad-view.c: Improve word swap function.
-	* docs/manual/C/Mousepad.xml.in: Other layout of the help file. Content
-	  will follow.
-	* mousepad/mousepad-{document,window,view}.c: Show the selection length
-	  in the statusbar. Also merged two signals and a couple of functions.
-	* mousepad/mousepad-window.c: Change default keybinding of new document
-	  (Ctrl+N) and new window (Shift+Ctrl+N). Assign Ctrl+T to transpose.
-	* mousepad/mousepad-window.c: Update the window title after saving a
-	  file with a new name.
-	* mousepad/mousepad-file.c: Set readonly to FALSE when starting with
-	  a non-existing filename in the argument.
+	* docs/manual/C/Mousepad.xml.in: Other layout of the help file.
+	  Content will follow.
+	* mousepad/mousepad-{document,window,view}.c: Show the selection
+	  length in the statusbar. Also merged two signals and a couple of
+	  functions.
+	* mousepad/mousepad-window.c: Change default keybinding of new
+	  document (Ctrl+N) and new window (Shift+Ctrl+N). Assign Ctrl+T to
+	  transpose.
+	* mousepad/mousepad-window.c: Update the window title after saving
+	  a file with a new name.
+	* mousepad/mousepad-file.c: Set readonly to FALSE when starting
+	  with a non-existing filename in the argument.
 	* mousepad/mousepad-print.c: Improve the print backend. Settings are
 	  now saved. You can set the paper type, toggle options for line
 	  numbers, wrap and page heading and use a custom font.
 
 
 2007-10-26	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-view.c: Implement transpose:
-	   - Selection on one line: Inverse selected text.
-	   - Multiple lines selected: Invert seleted lines.
-	   - Cursor is inside a word: Swap chars on each side of the cursor.
-	   - Cursor is outside a word: Swap word left and right of the cursor.
-	   - Cursor at the start of a line: Swap line with the line above.
-	   - Cursor at the end of a line: Swap line with the line below.
-	Will add support for multi- and column-selections later. Thanks to
-	Textmate for this great idea.
+
+	* mousepad/mousepad-view.c: Implement transpose:  - Selection on one
+	  line: Inverse selected text.
+	  - Multiple lines selected: Invert seleted lines.
+	  - Cursor is inside a word: Swap chars on each side of the cursor.
+	  - Cursor is outside a word: Swap word left and right of the
+	    cursor.
+	  - Cursor at the start of a line: Swap line with the line above.
+	  - Cursor at the end of a line: Swap line with the line below.
+	  Will add support for multi- and column-selections later. Thanks to
+	  Textmate for this great idea.
 
 
 2007-10-26	Nick Schermer <nick at xfce.org>
-	* MousepadHelp.in, mousepad/mousepad-{dialogs,window}.{c,h}:
-	  Add support for the help file.
+
+	* MousepadHelp.in, mousepad/mousepad-{dialogs,window}.{c,h}: Add
+	  support for the help file.
 	* Mousepad.spec.in: Add spec file.
 
 
 2007-10-25	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-view.c: Redraw selection on theme change.
 
 
 2007-10-25	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-view.c: Reimplemented multi-selection. It is also
-	  possible to do multi editing (typing in all the selections), select
-	  random words in the document (they will be copied to the clipboard as
-	  a list of words) and multi insert (create a drag without content or
-	  drag at the end of lines). Multiple selection will also be merged
-	  when possible. This proably has some rough edges, but it works pretty
-	  good. Keyboard multi drags will be added later.
-	* docs/manual/C/Mousepad.xml.in: Add a bit of info about multiple- and
-	  column-selections, but I'm not very good at this.
-	* mousepad/mousepad-{window.c,window-ui.xml}: Use our edit menu on right
-	  click, so copy/paste/delete works with multi selections. Also saves a
-	  bit of code since it integrates with the ui-manager.
+
+	* mousepad/mousepad-view.c: Reimplemented multi-selection. It is
+	  also possible to do multi editing (typing in all the selections),
+	  select random words in the document (they will be copied to the
+	  clipboard as a list of words) and multi insert (create a drag
+	  without content or drag at the end of lines). Multiple selection
+	  will also be merged when possible. This proably has some rough
+	  edges, but it works pretty good. Keyboard multi drags will be
+	  added later.
+	* docs/manual/C/Mousepad.xml.in: Add a bit of info about multiple-
+	  and column-selections, but I'm not very good at this.
+	* mousepad/mousepad-{window.c,window-ui.xml}: Use our edit menu on
+	  right click, so copy/paste/delete works with multi selections.
+	  Also saves a bit of code since it integrates with the ui-manager.
 
 
 2007-10-23	Nick Schermer <nick at xfce.org>
+
 	* configure.in.in, po/POTFILES.in: Fix dist-check. Thank to Brian
 	  for the hint.
-	* mousepad/mousepad-{dialogs,window}.c: Implement tab size menu. You
-	  can set the default tab sizes in the rc file (MiscDefaultTabSizes).
-	* mousepad/mousepad-window{-ui.xml,.c}: Reorder menus a bit. Go menu
-	  is now called 'Navigation' and the 'go to line' item is added to this
-	  menu. The document menu contains the tab size menu from now on.
+	* mousepad/mousepad-{dialogs,window}.c: Implement tab size menu.
+	  You can set the default tab sizes in the rc file
+	  (MiscDefaultTabSizes).
+	* mousepad/mousepad-window{-ui.xml,.c}: Reorder menus a bit. Go
+	  menu is now called 'Navigation' and the 'go to line' item is
+	  added to this menu. The document menu contains the tab size menu
+	  from now on.
 	* Rename some functions and vars to more suitable names.
 
 
 2007-10-22	Nick Schermer <nick at xfce.org>
-	* configure.in.in: Make sure __OPTIMIZE__ is enabled in normal builds.
-	* mousepad/mousepad-private.h: Tune G_LIKELY macros for pure booleans.
+
+	* configure.in.in: Make sure __OPTIMIZE__ is enabled in normal
+	  builds.
+	* mousepad/mousepad-private.h: Tune G_LIKELY macros for pure
+	  booleans.
 
 
 2007-10-22	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-window.c: Idea of the previous commit was good,
 	  but the implementation wasn't. Fix that.
 
 
 2007-10-21	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-window.c: Make the recent manager a singleton
 	  in the application, this is also done in gtk 2.12. We also
 	  initialize the recent manager when needed, since it's quite
-	  expensive to create one. This should improve the startup speed
-	  a bit.
+	  expensive to create one. This should improve the startup speed a
+	  bit.
 
 
 2007-10-21	Nick Schermer <nick at xfce.org>
+
 	* docs/: Import basic manual files.
 	* configure.in.in, mousepad/Makefile.am: Don't search for startup-
 	  notification and gtk-unix-print. We don't use this in the code.
 
 
 2007-10-18	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-view.c: Respect input methods and don't insert
 	  text when the textview is not editable.
 	* mousepad/mousepad-{file,document,window}.c: Properly handle
@@ -116,6 +225,7 @@
 
 
 2007-10-18	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-utils.{c,h}: Add iter function to move the iter
 	  in front of text. Code used from one of the indentation functions.
 	* mousepad/mousepad-view.c: Add code for a smart home button: when
@@ -126,31 +236,34 @@
 
 
 2007-10-17	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-window.c: Cleanup some code and get rid of the
 	  multiple action groups.
 
 
 2007-10-17	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-window.c: Decrease the menu lock when a window
-	  is closed and disconnect the recent manager handler (this is a
-	  bug since 2.12 because the manager is a floating object).
+	  is closed and disconnect the recent manager handler (this is a bug
+	  since 2.12 because the manager is a floating object).
 
 
 2007-10-17	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-{window,util}.c: Fix compiler warnings.
 
 
 2007-10-16	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-dialogs.c: Set the correct default return
-	  in the jump dialog.
+
+	* mousepad/mousepad-dialogs.c: Set the correct default return in
+	  the jump dialog.
 	* mousepad/mousepad-replace-{dialog,window,preferences}.{c,h}:
 	  Implement the new replace dialog.
-	* Remove options from the type-ahead bar, it was too bloated
-	  and those options are now available in the replace dialog.
-	* mousepad/mousepad-document.c: The MousepadDocument now holds
-	  utf-8 valid names, the MousepadFile the real filename.
-	* mousepad/mousepad-window.c: Full tab dnd (detach) with
-	  Gtk+ 2.12.
+	* Remove options from the type-ahead bar, it was too bloated and
+	  those options are now available in the replace dialog.
+	* mousepad/mousepad-document.c: The MousepadDocument now holds utf-8
+	  valid names, the MousepadFile the real filename.
+	* mousepad/mousepad-window.c: Full tab dnd (detach) with Gtk+ 2.12.
 	* mousepad/mousepad-encoding-dialog.{c,h}: Add a encoding dialog.
 	  This dialog should help users to find the right encoding for a
 	  document.
@@ -177,288 +290,299 @@
 	  remember after 5 months ;).
 
 
-2007-05-22	Nick Schermer <nick at xfce.org
+2007-05-22	Nick Schermer <nick at xfce.org>
+
 	* *.*: Remove copyright lines.
 
 
 2007-05-20	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-{preferences,search-bar,document}.c,
-	  mousepad/mousepad-types.h: Add match whole word option.
+
+	* mousepad/mousepad-{preferences,search-bar,document}.c, mousepad/
+	  mousepad-types.h: Add match whole word option.
 
 
 2007-05-20	Nick Schermer <nick at xfce.org>
-	* mousepad/Makefile.am: Use the new exo-csource
-	  --strip-comments and --strip-content arguments.
+
+	* mousepad/Makefile.am: Use the new exo-csource --strip-comments
+	  and --strip-content arguments.
 
 
 2007-05-20	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-view.c: Initialize variables, so gcc is
-	  happy.
+
+	* mousepad/mousepad-view.c: Initialize variables, so gcc is happy.
 	* README: Add some lines.
-	* mousepad/mousepad-window.c: Ctrl + Shift + v is the shortcut
-	  to paste in a column.
+	* mousepad/mousepad-window.c: Ctrl + Shift + v is the shortcut to
+	  paste in a column.
 
 
 2007-05-17	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-view.c: Cleanup the line number code.
-	  This version is a bit faster and removed a bunch of code.
-	* mousepad/mousepad-view.c: Cleanup the indentation code. You
-	  can also increase the (vertical) selected text with Shift +
-	  Space and decrease with Shift + Backspace. I though this
-	  might be useful for developers.
-	* mousepad/mousepad-view.c: Vertical selection using the mouse
-	  and Ctrl + Shift. Keyboard vertical selection is not possible
-	  because that adds too much code for (hardly) nothing. You can
-	  (un-)indent the block with Tab, Shift + Tab and the 2 new
-	  space (in/de)crease commands above.
-	* mousepad/mousepad-view.c: Draw a vertical line to separate
-	  the line numbers from the text, this looks beter with light
-	  themes (IMHO).
-	* mousepad/mousepad-window.c: Add 'paste column' option to
-	  paste the clipboard text in a column under the cursor.
-	* mousepad/mousepad-window.c: Set stock menu names to NULL so
-	  Gtk fills the default (translated) name,  makes your binary
-	  smaller and translators happy.
-	* mousepad/mousepad-{search-bar,document}.c: Fix segfault with
-	  empty string in the search bar and highlighting enabled.
+
+	* mousepad/mousepad-view.c: Cleanup the line number code. This
+	  version is a bit faster and removed a bunch of code.
+	* mousepad/mousepad-view.c: Cleanup the indentation code. You can
+	  also increase the (vertical) selected text with Shift + Space and
+	  decrease with Shift + Backspace. I though this might be useful for
+	  developers.
+	* mousepad/mousepad-view.c: Vertical selection using the mouse and
+	  Ctrl + Shift. Keyboard vertical selection is not possible because
+	  that adds too much code for (hardly) nothing. You can (un-)indent
+	  the block with Tab, Shift + Tab and the 2 new space (in/de)crease
+	  commands above.
+	* mousepad/mousepad-view.c: Draw a vertical line to separate the
+	  line numbers from the text, this looks beter with light themes.
+	* mousepad/mousepad-window.c: Add 'paste column' option to paste
+	  the clipboard text in a column under the cursor.
+	* mousepad/mousepad-window.c: Set stock menu names to NULL so Gtk
+	  fills the default (translated) name,  makes your binary smaller
+	  and translators happy.
+	* mousepad/mousepad-{search-bar,document}.c: Fix segfault with empty
+	  string in the search bar and highlighting enabled.
 	* TODO: Add items.
 
 
 2007-05-12	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-window.c: Add extra tests if the file
-	  really exists, because Gtk file dialogs hang if the
-	  file does not exists.
+
+	* mousepad/mousepad-window.c: Add extra tests if the file really
+	  exists, because Gtk file dialogs hang if the file does not exists.
 
 
 2007-05-12	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-window.c: Jump to active file when
-	  opening a new document.
+
+	* mousepad/mousepad-window.c: Jump to active file when opening a new
+	  document.
 
 
 2007-05-10	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-undo.c: Don't store a string (or even
-	  prepend it in a GString) when the user is inserting text.
-	  This saves a whole bunch of relocations (Bug #2737). We also
-	  flush the insert buffer after a redo and don't copy strings
-	  when inverting a delete step. This should bring the memory
-	  usage of the undo manager to a minimum.
+
+	* mousepad/mousepad-undo.c: Don't store a string (or even prepend it
+	  in a GString) when the user is inserting text. This saves a whole
+	  bunch of relocations (Bug #2737). We also flush the insert buffer
+	  after a redo and don't copy strings when inverting a delete step.
+	  This should bring the memory usage of the undo manager to a
+	  minimum.
 	* TODO: Add some undo manager reminders.
-	* mousepad/mousepad-window.c: Fix compiler warning when
-	  debugging is enabled.
-	* mousepad/mousepad-application.c: Change from append to
-	  prepend.
+	* mousepad/mousepad-window.c: Fix compiler warning when debugging is
+	  enabled.
+	* mousepad/mousepad-application.c: Change from append to prepend.
 
 
 2007-05-08	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-window.c: Rename function so it matches
-	  the standard mousepad_window_* names.
+
+	* mousepad/mousepad-window.c: Rename function so it matches the
+	  standard mousepad_window_* names.
 
 
 2007-05-08	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-window.c: Open a new tab when the notebook
-	  is double clicked. Also fix some indentation.
+
+	* mousepad/mousepad-window.c: Open a new tab when the notebook is
+	  double clicked. Also fix some indentation.
 
 
 2007-05-01	Nick Schermer <nick at xfce.org>
+
 	* configure.in.in: Don't break on a broken glibc.
 
 
 2007-05-01	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-dbus-infos.xml, mousepad/mousepad-undo.c,
 	  mousepad/mousepad-view.c: Fix some typos and replace tabs.
 
 
 2007-05-01	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-{document,window}.c: Allow uri and tab
-	  drops inside the textview widget.
-	* mousepad/mousepad-window.c: Hide the searchbar when all the
-	  tabs are closed and make sure nothing segfaults when no
-	  active document is found.
-	* mousepad/mousepad-window.c: Make sure the textview is
-	  focused when a new document has been added.
+
+	* mousepad/mousepad-{document,window}.c: Allow uri and tab drops
+	  inside the textview widget.
+	* mousepad/mousepad-window.c: Hide the searchbar when all the tabs
+	  are closed and make sure nothing segfaults when no active document
+	  is found.
+	* mousepad/mousepad-window.c: Make sure the textview is focused when
+	  a new document has been added.
 
 
 2007-04-28	Nick Schermer <nick at xfce.org>
+
 	* TODO: Removed the items I've fixed.
 	* Changelog: Break after 70 characters.
-	* mousepad/mousepad-{document,statusbar}.c: Hide the visible
-	  event box window.
-	* mousepad/mousepad-statusbar: The statusbar is now on top of
-	  the Gtk statusbar.
-	* mousepad/mousepad-window.c: Add support for dropping uris
-	  in the main window. Droping in the textview doesn't work
-	  yet.
+	* mousepad/mousepad-{document,statusbar}.c: Hide the visible event
+	  box window.
+	* mousepad/mousepad-statusbar: The statusbar is now on top of the
+	  Gtk statusbar.
+	* mousepad/mousepad-window.c: Add support for dropping uris in the
+	  main window. Droping in the textview doesn't work yet.
 	* mousepad/mousepad-window.c: Add tab dnd. This required some
-	  function reordering, but in the end it was quite easy and
-	  made the code more logical. I've also changed the window
-	  behaviour: when you close all the tabs in a window, an empty
-	  window is left. This is easier for tab dnd.
+	  function reordering, but in the end it was quite easy and made the
+	  code more logical. I've also changed the window behaviour: when
+	  you close all the tabs in a window, an empty window is left. This
+	  is easier for tab dnd.
 	* mousepad/mousepad-{application,window}.c: Beter handing of
 	  application windows. Also added detachable tabs.
-	* mousepad/mousepad-{properties,window}.c: The last settings
-	  of line numbers and auto indent are now stored.
-	* mousepad/mousepad-window.c: Beter locking of menu updates,
-	  this avoids some unneeded menu updates and also made the
-	  start time of Mousepad equal to Leafpad (and probably also
-	  Mosuepad 0.2.x), which is quite nice since it supports a
-	  whole bunch of extra features.
-	* mousepad/mousepad-window.c: Removed the 'close all windows'
-	  option from the menu and the code. Not need for a text
-	  editor IMHO.
+	* mousepad/mousepad-{properties,window}.c: The last settings of line
+	  numbers and auto indent are now stored.
+	* mousepad/mousepad-window.c: Beter locking of menu updates, this
+	  avoids some unneeded menu updates and also made the start time of
+	  Mousepad equal to Leafpad (and probably also Mosuepad 0.2.x),
+	  which is quite nice since it supports a whole bunch of extra
+	  features.
+	* mousepad/mousepad-window.c: Removed the 'close all windows' option
+	  from the menu and the code. Not need for a text editor IMHO.
 
 
 2007-04-21	Nick Schermer <nick at xfce.org>
+
 	* TODO: Fix some typos and add some new ideas and reminders.
 
 
 2007-04-20	Nick Schermer <nick at xfce.org>
+
 	* TODO: Add some stuff.
 
 
 2007-04-20	Nick Schermer <nick at xfce.org>
+
 	* TODO, NEWS: Update and expand both documents.
 
 
 2007-04-19	Erik Harrison <erikharrison at xfce.org>
+
 	* mousepad/mousepad-search-bar.c, mousepad-window.c: Fix some
 	  compiler warnings.
 
 
 2007-04-12	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-undo.c: Improve the behavior of the undo
-	  manager. It now merges multiple spaces, new lines are a
-	  separate undo action and when you redo some steps and then
-	  start editing again we append the redo-ed steps in reversed
-	  order with an inverted action, so you can undo every thing
-	  afterwards. This consumes a bit more memory compared to the
-	  old behavior (which simply removed every redo-ed step), but
-	  it's much more consistent.
+	  manager. It now merges multiple spaces, new lines are a separate
+	  undo action and when you redo some steps and then start editing
+	  again we append the redo-ed steps in reversed order with an
+	  inverted action, so you can undo every thing afterwards. This
+	  consumes a bit more memory compared to the old behavior (which
+	  simply removed every redo-ed step), but it's much more consistent.
 
 
 2007-04-11	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-{window,view}.c: Fix some potential leaks,
-	  I'm not really sure, but it doesn't hurt...
+
+	* mousepad/mousepad-{window,view}.c: Fix some potential leaks, I'm
+	  not really sure, but it doesn't hurt...
 
 
 2007-04-11	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-statusbar.c: Destroy the tool items
-	  together with the searchbar (memory leak from valgrind).
+
+	* mousepad/mousepad-statusbar.c: Destroy the tool items together
+	  with the searchbar (memory leak from valgrind).
 
 
 2007-04-11	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-{document,window,statusbar}: You can now
-	  click the OVR text in the statusbar to toggle the overwrite
-	  mode.
-	* mousepad/mousepad-{document,window,undo}: Initial version
-	  of an undo manager. Not finished yet.
-	* mousepad/Makefile.am, mousepad/mousepad-csource.pl: Remove
-	  my perl script because it has some problems.
+
+	* mousepad/mousepad-{document,window,statusbar}: You can now click
+	  the OVR text in the statusbar to toggle the overwrite mode.
+	* mousepad/mousepad-{document,window,undo}: Initial version of an
+	  undo manager. Not finished yet.
+	* mousepad/Makefile.am, mousepad/mousepad-csource.pl: Remove my perl
+	  script because it has some problems.
 	* Remove some empty object functions.
 
 
 2007-04-06	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-document.c: Fix segfault from previous
-	  commit.
-	* mousepad/mousepad-document.c: Fix bug in searching
-	  backwards, we have to jump one iter backwards before
-	  searching, because we start with the character right from
-	  the first iter. Also removed the equal check because it's
-	  not needed and only causing problems with backwards
-	  searching on the first character in the buffer.
+
+	* mousepad/mousepad-document.c: Fix segfault from previous commit.
+	* mousepad/mousepad-document.c: Fix bug in searching backwards, we
+	  have to jump one iter backwards before searching, because we start
+	  with the character right from the first iter. Also removed the
+	  equal check because it's not needed and only causing problems with
+	  backwards searching on the first character in the buffer.
 
 
 2007-04-06	Nick Schermer <nick at xfce.org>
-	* mousepad/mousepad-window.c: Fix opening recent files that
-	  do not exist.
-	* mousepad/mousepad-window.c, mousepad/mousepad-document.c:
-	  Update the window title correctly and remove the unused
-	  notify::title signals.
+
+	* mousepad/mousepad-window.c: Fix opening recent files that do not
+	  exist.
+	* mousepad/mousepad-window.c, mousepad/mousepad-document.c: Update
+	  the window title correctly and remove the unused notify::title
+	  signals.
 
 
 2007-04-06	Nick Schermer <nick at xfce.org>
+
 	* mousepad/mousepad-document.c: Because we don't use invisible
-	  characters in the text buffer, I was able to write a custom
-	  iter search function that can search in both directions, can
-	  be case insensitive, no string duplications and above all:
-	  is't over 10x faster then the gtk version. This gives a nice
-	  performance boost to the highlight function.
-	* mousepad/mousepad-search-bar.c: Connected the last signals
-	  and added a wrap around option to the search bar.
+	  characters in the text buffer, I was able to write a custom iter
+	  search function that can search in both directions, can be case
+	  insensitive, no string duplications and above all: is't over 10x
+	  faster then the gtk version. This gives a nice performance boost
+	  to the highlight function.
+	* mousepad/mousepad-search-bar.c: Connected the last signals and
+	  added a wrap around option to the search bar.
 
 
 2007-04-05	Nick Schermer <nick at xfce.org>
 
 	* mousepad/mousepad-document.c: Remove unused properties.
-	* mousepad/mousepad-{exo,window,preoperties,search-bar}:
-	  Remove the exo bindings, mousepad only depends on Gtk and
-	  libxfce4util.
-	* mousepad/mousepad-csource.pl: Perl script to generate the
-	  menu code. This script also strips the code between the xml
-	  blocks, so a minimal amount of text is added to the binary
-	  (ie. it produces better code then exo-csource).
+	* mousepad/mousepad-{exo,window,preoperties,search-bar}: Remove the
+	  exo bindings, mousepad only depends on Gtk and libxfce4util.
+	* mousepad/mousepad-csource.pl: Perl script to generate the menu
+	  code. This script also strips the code between the xml blocks, so
+	  a minimal amount of text is added to the binary (ie. it produces
+	  better code then exo-csource).
 
 
 2007-04-04	Nick Schermer <nick at xfce.org>
 
-	* po/: Update the POTFILES.in file and regenerate the pot
-	  file.
-	* mousepad/mousepad-document.c: Make the scroll offset
-	  smaller, so the textview doesn't jump around while searching.
-	* mousepad/mousepad-search-bar.c: Make sure the search signal
-	  is send when the search field is empty after a backspace,
-	  so no text is selected in the buffer.
+	* po/: Update the POTFILES.in file and regenerate the pot file.
+	* mousepad/mousepad-document.c: Make the scroll offset smaller, so
+	  the textview doesn't jump around while searching.
+	* mousepad/mousepad-search-bar.c: Make sure the search signal is
+	  send when the search field is empty after a backspace, so no text
+	  is selected in the buffer.
 	* Remove some leftover tabs.
 
 
 2007-04-04	Nick Schermer <nick at xfce.org>
 
-	* configure.in.in: Mousepad does not depend on exo anymore.
-	  Only when you run in maintainer-mode, exo-csource is required.
+	* configure.in.in: Mousepad does not depend on exo anymore. Only
+	  when you run in maintainer-mode, exo-csource is required.
 	* mousepad/mousepad-document.*: Renamed mousepad-screen to
 	  mousepad-document.
-	* mousepad/mousepad-{search-bar,document,window).*: Added
-	  function for searching, including the type-ahead search bar.
-	* mousepad/mousepad-statusbar.*: A custom statusbar suitable
-	  for displaying the tooltips, overwrite/insert and the line-
-	  and column-number.
-	* mousepad/mousepad-exo.*: The exo-bindings so we don't depend
-	  on exo anymore, although I want to get rid of all of them.
-	* mousepad/mousepad-marshal.list: Custom marshal for sending
-	  search signals.
-	* mousepad/mousepad-types.h: Search types
-	  (a mousepad-enum-types.{c,h} is generated during build).
+	* mousepad/mousepad-{search-bar,document,window).*: Added function
+	  for searching, including the type-ahead search bar.
+	* mousepad/mousepad-statusbar.*: A custom statusbar suitable for
+	  displaying the tooltips, overwrite/insert and the line- and
+	  column-number.
+	* mousepad/mousepad-exo.*: The exo-bindings so we don't depend on
+	  exo anymore, although I want to get rid of all of them.
+	* mousepad/mousepad-marshal.list: Custom marshal for sending search
+	  signals.
+	* mousepad/mousepad-types.h: Search types (a
+	  mousepad-enum-types.{c,h} is generated during build).
 	* Various performance improvements and code cleanups.
 
 
 2007-03-03	Nick Schermer <nick at xfce.org>
 
-	* mousepad/mousepad-dialogs.{c,h}: Add response actions for
-	  Mousepad so it's easier to understand what happens.
+	* mousepad/mousepad-dialogs.{c,h}: Add response actions for Mousepad
+	  so it's easier to understand what happens.
 	* mousepad/mousepad-window.c, * mousepad/mousepad-screen.{c,h}:
 	  Basic support for document reloading.
 
 
 2007-03-03	Nick Schermer <nick at xfce.org>
 
-	* configure.in.in, mousepad/Makefile.am: Remove the PCRE
-	  dependency. I should have removed this earier after some
-	  testing.
+	* configure.in.in, mousepad/Makefile.am: Remove the PCRE dependency.
+	  I should have removed this earier after some testing.
 
 
 2007-03-03	Nick Schermer <nick at xfce.org>
 
-	* mousepad/mousepad-dialogs.{c,h}: New file for the dialogs
-	  so the mousepad-window file becomes more readable.
-	* mousepad/mousepad-window.c: Split some function and reorder
-	  them a bit.
-	* mousepad/mousepad-window.c: The items in the go menu now
-	  have the filename as statusbar tooltip.
+	* mousepad/mousepad-dialogs.{c,h}: New file for the dialogs so the
+	  mousepad-window file becomes more readable.
+	* mousepad/mousepad-window.c: Split some function and reorder them
+	  a bit.
+	* mousepad/mousepad-window.c: The items in the go menu now have the
+	  filename as statusbar tooltip.
 	* mousepad/mousepad-window.c: Check if the file is externally
 	  modified before writing. If it is, ask the user what to do.
-	* mousepad/main.c, mousepad/mousepad-dbus.{c,h},
-	  mousepad/mousepad-dbus-infos.xml: Support for terminating a
-	  running mousepad instance (that is connected to dbus), using
-	  mousepad -q.
+	* mousepad/main.c, mousepad/mousepad-dbus.{c,h}, mousepad/mousepad-
+	  dbus-infos.xml: Support for terminating a running mousepad
+	  instance (that is connected to dbus), using mousepad -q.
 	* mousepad/*: Add function destriptions for Erik (and others).
 
 
@@ -469,38 +593,37 @@
 
 2007-02-18	Nick Schermer <nick at xfce.org>
 
-	* mousepad/mousepad-window.c: Prevent multiple recent- and
-	  go-menu updates when multiple items are opened or the recent
-	  history is cleared.
+	* mousepad/mousepad-window.c: Prevent multiple recent- and go-menu
+	  updates when multiple items are opened or the recent history is
+	  cleared.
 
 
 2007-02-18	Nick Schermer <nick at xfce.org>
 
-	* TODO, mousepad/mousepad-window.c: Add option to the recent
-	  menu to clear the history.
+	* TODO, mousepad/mousepad-window.c: Add option to the recent menu
+	  to clear the history.
 	* mousepad/mousepad-window.c: The recent items are now in the
-	  Mousepad group so it's easier to filter them when removing.
-	  The list is also sorted by the most recently used item.
-	* mousepad/mousepad-window.c: Fix problem in checking if the
-	  file was already openened.
+	  Mousepad group so it's easier to filter them when removing. The
+	  list is also sorted by the most recently used item.
+	* mousepad/mousepad-window.c: Fix problem in checking if the file
+	  was already openened.
 	* mousepad/mousepad-window.c: You can now reorder tabs.
-	* mousepad/mousepad-window.c: A tab is now inserted right from
-	  the current active tab.
-	* mousepad/mousepad-screen.c: Untitled documents now have a
-	  number like "Untitled #". The number is increased as long
-	  as the application is running.
+	* mousepad/mousepad-window.c: A tab is now inserted right from the
+	  current active tab.
+	* mousepad/mousepad-screen.c: Untitled documents now have a number
+	  like "Untitled #". The number is increased as long as the
+	  application is running.
 	* mousepad/mousepad-window.c: Added first parts of code for a
 	  statusbar.
 
 2007-02-17	Nick Schermer <nick at xfce.org>
 
 	* TODO: Remind myself to fix problems with UTF-8 filenames.
-	* mousepad/mousepad-window.c: Fix crash when opening files
-	  with the command line.
+	* mousepad/mousepad-window.c: Fix crash when opening files with the
+	  command line.
 	* Mousepad.desktop.in.in, Mousepad.desktop.in.in: Mousepad
 	  executable is now lowercase again.
-	* mousepad/mousepad-screen.c: Remove unused signals from the
-	   Class.
+	* mousepad/mousepad-screen.c: Remove unused signals from the  Class.
 
 2007-02-17	Nick Schermer <nick at xfce.org>
 
diff --git a/mousepad/main.c b/mousepad/main.c
index 2780b8e..2dd937a 100644
--- a/mousepad/main.c
+++ b/mousepad/main.c
@@ -45,15 +45,15 @@ static gboolean   opt_quit = FALSE;
 
 
 /* command line options */
-static GOptionEntry option_entries[] =
+static const GOptionEntry option_entries[] =
 {
 #ifdef HAVE_DBUS
-  { "disable-server", '\0', 0, G_OPTION_ARG_NONE, &opt_disable_server, N_("Do not register with the D-BUS session message bus"), NULL, },
-  { "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_("Quit a running Mousepad instance"), NULL, },
+  { "disable-server", '\0', 0, G_OPTION_ARG_NONE, &opt_disable_server, N_("Do not register with the D-BUS session message bus"), NULL },
+  { "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_("Quit a running Mousepad instance"), NULL },
 #endif
-  { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_("Print version information and exit"), NULL, },
+  { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_("Print version information and exit"), NULL },
   { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, NULL },
-  { NULL, },
+  { NULL },
 };
 
 
@@ -84,7 +84,7 @@ main (gint argc, gchar **argv)
     g_thread_init (NULL);
 
   /* initialize gtk+ */
-  if (!gtk_init_with_args (&argc, &argv, _("[FILES...]"), option_entries, GETTEXT_PACKAGE, &error))
+  if (!gtk_init_with_args (&argc, &argv, _("[FILES...]"), (GOptionEntry *) option_entries, GETTEXT_PACKAGE, &error))
     {
       /* check if we have an error message */
       if (G_LIKELY (error == NULL))
diff --git a/mousepad/mousepad-application.c b/mousepad/mousepad-application.c
index 9df01ca..da50fe0 100644
--- a/mousepad/mousepad-application.c
+++ b/mousepad/mousepad-application.c
@@ -64,25 +64,6 @@ static GObjectClass *mousepad_application_parent_class;
 
 
 
-MousepadApplication*
-mousepad_application_get (void)
-{
-  static MousepadApplication *application = NULL;
-
-  if (G_LIKELY (application))
-    {
-      g_object_ref (G_OBJECT (application));
-    }
-  else
-    {
-      application = g_object_new (MOUSEPAD_TYPE_APPLICATION, NULL);
-    }
-
-  return application;
-}
-
-
-
 GType
 mousepad_application_get_type (void)
 {
@@ -174,6 +155,26 @@ mousepad_application_finalize (GObject *object)
 
 
 
+MousepadApplication*
+mousepad_application_get (void)
+{
+  static MousepadApplication *application = NULL;
+
+  if (G_UNLIKELY (application == NULL))
+    {
+      application = g_object_new (MOUSEPAD_TYPE_APPLICATION, NULL);
+      g_object_add_weak_pointer (G_OBJECT (application), (gpointer) &application);
+    }
+  else
+    {
+      g_object_ref (G_OBJECT (application));
+    }
+
+  return application;
+}
+
+
+
 gboolean
 mousepad_application_has_windows (MousepadApplication *application)
 {
diff --git a/mousepad/mousepad-dialogs.c b/mousepad/mousepad-dialogs.c
index b1c9ab2..adaffc3 100644
--- a/mousepad/mousepad-dialogs.c
+++ b/mousepad/mousepad-dialogs.c
@@ -42,7 +42,11 @@ mousepad_dialogs_show_about (GtkWindow *parent)
                          "destroy-with-parent", TRUE,
                          "license", XFCE_LICENSE_GPL,
                          "logo-icon-name", PACKAGE_NAME,
+#if GTK_CHECK_VERSION (2,12,0)
+                         "program-name", PACKAGE_NAME,
+#else
                          "name", PACKAGE_NAME,
+#endif
                          "version", PACKAGE_VERSION,
                          "translator-credits", _("translator-credits"),
                          "website", "http://www.xfce.org/",
@@ -166,20 +170,59 @@ mousepad_dialogs_other_tab_size (GtkWindow *parent,
 
 
 
-gint
-mousepad_dialogs_go_to_line (GtkWindow *parent,
-                             gint       current_line,
-                             gint       last_line)
+static void
+mousepad_dialogs_go_to_line_changed (GtkSpinButton *line_spin,
+                                     GtkSpinButton *col_spin)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter    iter;
+
+  _mousepad_return_if_fail (GTK_IS_SPIN_BUTTON (line_spin));
+  _mousepad_return_if_fail (GTK_IS_SPIN_BUTTON (col_spin));
+
+  /* get the text buffer */
+  buffer = mousepad_object_get_data (G_OBJECT (col_spin), "buffer");
+
+  /* debug check */
+  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+
+  /* get iter at line */
+  gtk_text_buffer_get_iter_at_line (buffer, &iter, gtk_spin_button_get_value_as_int (line_spin) - 1);
+
+  /* move the iter to the end of the line if needed */
+  if (!gtk_text_iter_ends_line (&iter))
+    gtk_text_iter_forward_to_line_end (&iter);
+
+  /* update column spin button range */
+  gtk_spin_button_set_range (col_spin, 0, gtk_text_iter_get_line_offset (&iter));
+}
+
+
+
+gboolean
+mousepad_dialogs_go_to (GtkWindow     *parent,
+                        GtkTextBuffer *buffer)
 {
-  GtkWidget     *dialog;
-  GtkWidget     *hbox;
-  GtkWidget     *label;
-  GtkWidget     *button;
-  GtkAdjustment *adjustment;
-  gint           line_number = 0;
+  GtkWidget    *dialog;
+  GtkWidget    *vbox;
+  GtkWidget    *hbox;
+  GtkWidget    *label;
+  GtkWidget    *line_spin;
+  GtkWidget    *col_spin;
+  GtkSizeGroup *size_group;
+  GtkTextIter   iter;
+  gint          line, column, lines;
+  gint          response;
+
+  /* get cursor iter */
+  gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
+  line = gtk_text_iter_get_line (&iter) + 1;
+
+  /* get number of lines */
+  lines = gtk_text_buffer_get_line_count (buffer);
 
   /* build the dialog */
-  dialog = gtk_dialog_new_with_buttons (_("Go To Line"),
+  dialog = gtk_dialog_new_with_buttons (_("Go To"),
                                         parent,
                                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
                                         GTK_STOCK_CANCEL, MOUSEPAD_RESPONSE_CANCEL,
@@ -188,36 +231,82 @@ mousepad_dialogs_go_to_line (GtkWindow *parent,
   gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_JUMP_TO);
   gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
 
-  hbox = gtk_hbox_new (FALSE, 8);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
-  gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
+  vbox = gtk_vbox_new (FALSE, 6);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), vbox, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+  gtk_widget_show (vbox);
+
+  /* create size group */
+  size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+  /* line number box */
+  hbox = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
   gtk_widget_show (hbox);
 
   label = gtk_label_new_with_mnemonic (_("_Line number:"));
-  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+  gtk_size_group_add_widget (size_group, label);
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
   gtk_widget_show (label);
 
-  /* the spin button adjustment */
-  adjustment = (GtkAdjustment *) gtk_adjustment_new (current_line, 1, last_line, 1, 10, 0);
+  line_spin = gtk_spin_button_new_with_range (1, lines, 1);
+  gtk_entry_set_activates_default (GTK_ENTRY (line_spin), TRUE);
+  gtk_box_pack_start (GTK_BOX (hbox), line_spin, FALSE, FALSE, 0);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), line_spin);
+  gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (line_spin), TRUE);
+  gtk_entry_set_width_chars (GTK_ENTRY (line_spin), 8);
+  gtk_widget_show (line_spin);
+
+  /* column box */
+  hbox = gtk_hbox_new (FALSE, 12);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+  gtk_widget_show (hbox);
 
-  /* the spin button */
-  button = gtk_spin_button_new (adjustment, 1, 0);
-  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (button), TRUE);
-  gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (button), TRUE);
-  gtk_entry_set_width_chars (GTK_ENTRY (button), 8);
-  gtk_entry_set_activates_default (GTK_ENTRY (button), TRUE);
-  gtk_label_set_mnemonic_widget (GTK_LABEL(label), button);
-  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
-  gtk_widget_show (button);
+  label = gtk_label_new_with_mnemonic (_("C_olumn number:"));
+  gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+  gtk_size_group_add_widget (size_group, label);
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+  gtk_widget_show (label);
+
+  col_spin = gtk_spin_button_new_with_range (0, 0, 1);
+  gtk_entry_set_activates_default (GTK_ENTRY (col_spin), TRUE);
+  mousepad_object_set_data (G_OBJECT (col_spin), "buffer", buffer);
+  gtk_box_pack_start (GTK_BOX (hbox), col_spin, FALSE, FALSE, 0);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), col_spin);
+  gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (col_spin), TRUE);
+  gtk_entry_set_width_chars (GTK_ENTRY (col_spin), 8);
+  gtk_widget_show (col_spin);
+
+  /* signal to monitor column number */
+  g_signal_connect (G_OBJECT (line_spin), "value-changed", G_CALLBACK (mousepad_dialogs_go_to_line_changed), col_spin);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (line_spin), line);
 
   /* run the dialog */
-  if (gtk_dialog_run (GTK_DIALOG (dialog)) == MOUSEPAD_RESPONSE_JUMP_TO)
-    line_number = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (button));
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+  if (response == MOUSEPAD_RESPONSE_JUMP_TO)
+    {
+      /* hide the dialog */
+      gtk_widget_hide (dialog);
+
+      /* get new position */
+      line = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (line_spin)) - 1;
+      column = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (col_spin));
+
+      /* get iter */
+      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, line, column);
+
+      /* get cursor position */
+      gtk_text_buffer_place_cursor (buffer, &iter);
+    }
+
+  /* release size group */
+  g_object_unref (G_OBJECT (size_group));
 
   /* destroy the dialog */
   gtk_widget_destroy (dialog);
 
-  return line_number;
+  return (response == MOUSEPAD_RESPONSE_JUMP_TO);
 }
 
 
@@ -304,65 +393,23 @@ mousepad_dialogs_save_changes (GtkWindow *parent)
 
 
 gint
-mousepad_dialogs_ask_overwrite (GtkWindow   *parent,
-                                const gchar *filename)
+mousepad_dialogs_revert (GtkWindow *parent)
 {
   GtkWidget *dialog;
   gint       response;
 
+  /* setup the question dialog */
   dialog = gtk_message_dialog_new (parent,
                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                   GTK_MESSAGE_QUESTION,
-                                   GTK_BUTTONS_NONE,
-                                   _("The file has been externally modified. Are you sure "
-                                     "you want to save the file?"));
-
-  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                            _("If you save the file, the external changes "
-                                              "to \"%s\" will be lost."), filename);
-
-  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, MOUSEPAD_RESPONSE_CANCEL);
-  gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
-                                mousepad_util_image_button (GTK_STOCK_SAVE, _("_Overwrite")),
-                                MOUSEPAD_RESPONSE_OVERWRITE);
-  gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
-                                mousepad_util_image_button (GTK_STOCK_REFRESH, _("_Reload")),
-                                MOUSEPAD_RESPONSE_RELOAD);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_CANCEL);
-
-  /* run the dialog */
-  response = gtk_dialog_run (GTK_DIALOG (dialog));
-
-  /* destroy the dialog */
-  gtk_widget_destroy (dialog);
-
-  return response;
-}
-
-
-
-gint
-mousepad_dialogs_ask_reload (GtkWindow *parent)
-{
-  GtkWidget *dialog;
-  gint       response;
-
-  dialog = gtk_message_dialog_new (parent,
-                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                   GTK_MESSAGE_QUESTION,
-                                   GTK_BUTTONS_NONE,
+                                   GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
                                    _("Do you want to save your changes before reloading?"));
   gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                            _("If you reload the file, you changes will be lost."));
-
+                                   _("If you revert the file, all unsaved changes will be lost."));
   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
                           GTK_STOCK_CANCEL, MOUSEPAD_RESPONSE_CANCEL,
                           GTK_STOCK_SAVE_AS, MOUSEPAD_RESPONSE_SAVE_AS,
+                          GTK_STOCK_REVERT_TO_SAVED, MOUSEPAD_RESPONSE_REVERT,
                           NULL);
-  gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
-                                mousepad_util_image_button (GTK_STOCK_REFRESH, _("_Reload")),
-                                MOUSEPAD_RESPONSE_RELOAD);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), MOUSEPAD_RESPONSE_CANCEL);
 
   /* run the dialog */
   response = gtk_dialog_run (GTK_DIALOG (dialog));
diff --git a/mousepad/mousepad-dialogs.h b/mousepad/mousepad-dialogs.h
index af47175..5ecfc15 100644
--- a/mousepad/mousepad-dialogs.h
+++ b/mousepad/mousepad-dialogs.h
@@ -30,41 +30,37 @@ enum {
   MOUSEPAD_RESPONSE_JUMP_TO,
   MOUSEPAD_RESPONSE_OK,
   MOUSEPAD_RESPONSE_OVERWRITE,
-  MOUSEPAD_RESPONSE_RELOAD,
   MOUSEPAD_RESPONSE_REPLACE,
+  MOUSEPAD_RESPONSE_REVERT,
   MOUSEPAD_RESPONSE_SAVE,
   MOUSEPAD_RESPONSE_SAVE_AS,
   MOUSEPAD_RESPONSE_CHECK_ENTRY
 };
 
-GtkWidget *mousepad_dialogs_image_button   (const gchar  *stock_id,
-                                            const gchar  *label);
+GtkWidget *mousepad_dialogs_image_button   (const gchar   *stock_id,
+                                            const gchar   *label);
 
-void       mousepad_dialogs_show_about     (GtkWindow    *parent);
+void       mousepad_dialogs_show_about     (GtkWindow     *parent);
 
-void       mousepad_dialogs_show_error     (GtkWindow    *parent,
-                                            const GError *error,
-                                            const gchar  *message);
+void       mousepad_dialogs_show_error     (GtkWindow     *parent,
+                                            const GError  *error,
+                                            const gchar   *message);
 
-void       mousepad_dialogs_show_help      (GtkWindow    *parent,
-                                            const gchar  *page,
-                                            const gchar  *offset);
+void       mousepad_dialogs_show_help      (GtkWindow     *parent,
+                                            const gchar   *page,
+                                            const gchar   *offset);
 
-gint       mousepad_dialogs_other_tab_size (GtkWindow    *parent,
-                                            gint          active_size);
+gint       mousepad_dialogs_other_tab_size (GtkWindow     *parent,
+                                            gint           active_size);
 
-gint       mousepad_dialogs_go_to_line     (GtkWindow    *parent,
-                                            gint          current_line,
-                                            gint          last_line);
+gboolean   mousepad_dialogs_go_to          (GtkWindow     *parent,
+                                            GtkTextBuffer *buffer;);
 
-gboolean   mousepad_dialogs_clear_recent   (GtkWindow    *parent);
+gboolean   mousepad_dialogs_clear_recent   (GtkWindow     *parent);
 
-gint       mousepad_dialogs_save_changes   (GtkWindow    *parent);
+gint       mousepad_dialogs_save_changes   (GtkWindow     *parent);
 
-gint       mousepad_dialogs_ask_overwrite  (GtkWindow    *parent,
-                                            const gchar  *filename);
-
-gint       mousepad_dialogs_ask_reload     (GtkWindow    *parent);
+gint       mousepad_dialogs_revert         (GtkWindow     *parent);
 
 G_END_DECLS
 
diff --git a/mousepad/mousepad-document.c b/mousepad/mousepad-document.c
index 3c388dc..9dce17c 100644
--- a/mousepad/mousepad-document.c
+++ b/mousepad/mousepad-document.c
@@ -50,7 +50,10 @@ static void      mousepad_document_finalize                (GObject
 static void      mousepad_document_notify_cursor_position  (GtkTextBuffer          *buffer,
                                                             GParamSpec             *pspec,
                                                             MousepadDocument       *document);
-static void      mousepad_document_toggle_overwrite        (GtkTextView            *textview,
+static void      mousepad_document_notify_has_selection    (GtkTextBuffer          *buffer,
+                                                            GParamSpec             *pspec,
+                                                            MousepadDocument       *document);
+static void      mousepad_document_notify_overwrite        (GtkTextView            *textview,
                                                             GParamSpec             *pspec,
                                                             MousepadDocument       *document);
 static void      mousepad_document_drag_data_received      (GtkWidget              *widget,
@@ -63,6 +66,7 @@ static void      mousepad_document_drag_data_received      (GtkWidget
                                                             MousepadDocument       *document);
 static void      mousepad_document_filename_changed        (MousepadDocument       *document,
                                                             const gchar            *filename);
+static void      mousepad_document_label_color             (MousepadDocument       *document);
 static void      mousepad_document_tab_button_clicked      (GtkWidget              *widget,
                                                             MousepadDocument       *document);
 
@@ -71,8 +75,9 @@ enum
 {
   CLOSE_TAB,
   CURSOR_CHANGED,
+  SELECTION_CHANGED,
   OVERWRITE_CHANGED,
-  LAST_SIGNAL,
+  LAST_SIGNAL
 };
 
 struct _MousepadDocumentClass
@@ -160,6 +165,14 @@ mousepad_document_class_init (MousepadDocumentClass *klass)
                   _mousepad_marshal_VOID__INT_INT_INT,
                   G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
 
+  document_signals[SELECTION_CHANGED] =
+    g_signal_new (I_("selection-changed"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_NO_HOOKS,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__INT,
+                  G_TYPE_NONE, 1, G_TYPE_INT);
+
   document_signals[OVERWRITE_CHANGED] =
     g_signal_new (I_("overwrite-changed"),
                   G_TYPE_FROM_CLASS (gobject_class),
@@ -186,6 +199,7 @@ mousepad_document_init (MousepadDocument *document)
   /* initialize the variables */
   document->priv->utf8_filename = NULL;
   document->priv->utf8_basename = NULL;
+  document->priv->label = NULL;
 
   /* setup the scolled window */
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (document), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
@@ -246,7 +260,9 @@ mousepad_document_init (MousepadDocument *document)
 
   /* attach signals to the text view and buffer */
   g_signal_connect (G_OBJECT (document->buffer), "notify::cursor-position", G_CALLBACK (mousepad_document_notify_cursor_position), document);
-  g_signal_connect (G_OBJECT (document->textview), "notify::overwrite", G_CALLBACK (mousepad_document_toggle_overwrite), document);
+  g_signal_connect (G_OBJECT (document->buffer), "notify::has-selection", G_CALLBACK (mousepad_document_notify_has_selection), document);
+  g_signal_connect_swapped (G_OBJECT (document->buffer), "modified-changed", G_CALLBACK (mousepad_document_label_color), document);
+  g_signal_connect (G_OBJECT (document->textview), "notify::overwrite", G_CALLBACK (mousepad_document_notify_overwrite), document);
   g_signal_connect (G_OBJECT (document->textview), "drag-data-received", G_CALLBACK (mousepad_document_drag_data_received), document);
 }
 
@@ -281,7 +297,7 @@ mousepad_document_notify_cursor_position (GtkTextBuffer    *buffer,
                                           MousepadDocument *document)
 {
   GtkTextIter iter;
-  guint       line, column, selection;
+  gint        line, column, selection;
   gint        tab_size;
 
   _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
@@ -297,10 +313,10 @@ mousepad_document_notify_cursor_position (GtkTextBuffer    *buffer,
   tab_size = mousepad_view_get_tab_size (document->textview);
 
   /* get the column */
-  column = mousepad_util_get_real_line_offset (&iter, tab_size) + 1;
+  column = mousepad_util_get_real_line_offset (&iter, tab_size);
 
   /* get length of the selection */
-  selection = mousepad_view_get_selection_length (document->textview);
+  selection = mousepad_view_get_selection_length (document->textview, NULL);
 
   /* emit the signal */
   g_signal_emit (G_OBJECT (document), document_signals[CURSOR_CHANGED], 0, line, column, selection);
@@ -309,7 +325,35 @@ mousepad_document_notify_cursor_position (GtkTextBuffer    *buffer,
 
 
 static void
-mousepad_document_toggle_overwrite (GtkTextView      *textview,
+mousepad_document_notify_has_selection (GtkTextBuffer    *buffer,
+                                        GParamSpec       *pspec,
+                                        MousepadDocument *document)
+{
+  gint     selection;
+  gboolean is_column_selection;
+
+  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+  /* get length of the selection */
+  selection = mousepad_view_get_selection_length (document->textview, &is_column_selection);
+
+  /* don't send large numbers */
+  if (selection > 1)
+    selection = 1;
+
+  /* if it's a column selection with content */
+  if (selection == 1 && is_column_selection)
+    selection = 2;
+
+  /* emit the signal */
+  g_signal_emit (G_OBJECT (document), document_signals[SELECTION_CHANGED], 0, selection);
+}
+
+
+
+static void
+mousepad_document_notify_overwrite (GtkTextView      *textview,
                                     GParamSpec       *pspec,
                                     MousepadDocument *document)
 {
@@ -379,12 +423,40 @@ mousepad_document_filename_changed (MousepadDocument *document,
 
           /* set the tab tooltip */
           mousepad_util_set_tooltip (document->priv->ebox, utf8_filename);
+
+          /* update label color */
+          mousepad_document_label_color (document);
         }
     }
 }
 
 
 
+static void
+mousepad_document_label_color (MousepadDocument *document)
+{
+  const GdkColor green = {0, 0x0000, 0x9999, 0x0000};
+  const GdkColor red   = {0, 0xffff, 0x0000, 0x0000};
+  gboolean       readonly, modified;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (document->buffer));
+  _mousepad_return_if_fail (MOUSEPAD_IS_FILE (document->file));
+
+  if (document->priv->label)
+    {
+      /* get states */
+      readonly = mousepad_file_get_read_only (document->file);
+      modified = gtk_text_buffer_get_modified (document->buffer);
+
+      /* update colors */
+      gtk_widget_modify_fg (document->priv->label, GTK_STATE_NORMAL, modified ? &red : (readonly ? &green : NULL));
+      gtk_widget_modify_fg (document->priv->label, GTK_STATE_ACTIVE, modified ? &red : (readonly ? &green : NULL));
+    }
+}
+
+
+
 void
 mousepad_document_set_overwrite (MousepadDocument *document,
                                  gboolean          overwrite)
@@ -443,26 +515,7 @@ mousepad_document_focus_textview (MousepadDocument *document)
 
 
 void
-mousepad_document_go_to_line (MousepadDocument *document,
-                              gint              line_number)
-{
-  GtkTextIter iter;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (document->buffer));
-
-  /* move the cursor */
-  gtk_text_buffer_get_iter_at_line (document->buffer, &iter, line_number - 1);
-  gtk_text_buffer_place_cursor (document->buffer, &iter);
-
-  /* make sure the cursor is in the visible area */
-  mousepad_view_put_cursor_on_screen (document->textview);
-}
-
-
-
-void
-mousepad_document_send_statusbar_signals (MousepadDocument *document)
+mousepad_document_send_signals (MousepadDocument *document)
 {
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
 
@@ -470,28 +523,10 @@ mousepad_document_send_statusbar_signals (MousepadDocument *document)
   mousepad_document_notify_cursor_position (document->buffer, NULL, document);
 
   /* re-send the overwrite signal */
-  mousepad_document_toggle_overwrite (GTK_TEXT_VIEW (document->textview), NULL, document);
-}
-
+  mousepad_document_notify_overwrite (GTK_TEXT_VIEW (document->textview), NULL, document);
 
-
-void
-mousepad_document_line_numbers (MousepadDocument *document,
-                                gint             *current_line,
-                                gint             *last_line)
-{
-  GtkTextIter iter;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
-  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (document->buffer));
-
-  /* get the current line number */
-  gtk_text_buffer_get_iter_at_mark (document->buffer, &iter, gtk_text_buffer_get_insert (document->buffer));
-  *current_line = gtk_text_iter_get_line (&iter) + 1;
-
-  /* get the last line number */
-  gtk_text_buffer_get_end_iter (document->buffer, &iter);
-  *last_line = gtk_text_iter_get_line (&iter) + 1;
+  /* re-send the selection status */
+  mousepad_document_notify_has_selection (document->buffer, NULL, document);
 }
 
 
@@ -518,6 +553,9 @@ mousepad_document_get_tab_label (MousepadDocument *document)
   gtk_container_add (GTK_CONTAINER (document->priv->ebox), document->priv->label);
   gtk_widget_show (document->priv->label);
 
+  /* set label color */
+  mousepad_document_label_color (document);
+
   /* create the button */
   button = gtk_button_new ();
   gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
diff --git a/mousepad/mousepad-document.h b/mousepad/mousepad-document.h
index c07f4d5..a35c7d0 100644
--- a/mousepad/mousepad-document.h
+++ b/mousepad/mousepad-document.h
@@ -61,37 +61,30 @@ struct _MousepadDocument
   GtkTextTag              *tag;
 };
 
-GType             mousepad_document_get_type                 (void) G_GNUC_CONST;
+GType             mousepad_document_get_type       (void) G_GNUC_CONST;
 
-MousepadDocument *mousepad_document_new                      (void);
+MousepadDocument *mousepad_document_new            (void);
 
-void              mousepad_document_set_font                 (MousepadDocument      *document,
-                                                              const gchar           *font_name);
+void              mousepad_document_set_font       (MousepadDocument *document,
+                                                    const gchar      *font_name);
 
-void              mousepad_document_set_overwrite            (MousepadDocument      *document,
-                                                              gboolean               overwrite);
+void              mousepad_document_set_overwrite  (MousepadDocument *document,
+                                                    gboolean          overwrite);
 
-void              mousepad_document_set_word_wrap            (MousepadDocument      *document,
-                                                              gboolean               word_wrap);
+void              mousepad_document_set_word_wrap  (MousepadDocument *document,
+                                                    gboolean          word_wrap);
 
-void              mousepad_document_focus_textview           (MousepadDocument      *document);
+void              mousepad_document_focus_textview (MousepadDocument *document);
 
-void              mousepad_document_go_to_line               (MousepadDocument      *document,
-                                                              gint                   line_number);
+void              mousepad_document_send_signals   (MousepadDocument *document);
 
-void              mousepad_document_send_statusbar_signals   (MousepadDocument      *document);
+GtkWidget        *mousepad_document_get_tab_label  (MousepadDocument *document);
 
-void              mousepad_document_line_numbers             (MousepadDocument      *document,
-                                                              gint                  *current_line,
-                                                              gint                  *last_line);
+const gchar      *mousepad_document_get_basename   (MousepadDocument *document);
 
-GtkWidget        *mousepad_document_get_tab_label            (MousepadDocument      *document);
+const gchar      *mousepad_document_get_filename   (MousepadDocument *document);
 
-const gchar      *mousepad_document_get_basename             (MousepadDocument      *document);
-
-const gchar      *mousepad_document_get_filename             (MousepadDocument      *document);
-
-gboolean          mousepad_document_get_word_wrap            (MousepadDocument      *document);
+gboolean          mousepad_document_get_word_wrap  (MousepadDocument *document);
 
 G_END_DECLS
 
diff --git a/mousepad/mousepad-encoding-dialog.c b/mousepad/mousepad-encoding-dialog.c
index 02fb332..238e1fb 100644
--- a/mousepad/mousepad-encoding-dialog.c
+++ b/mousepad/mousepad-encoding-dialog.c
@@ -354,7 +354,7 @@ mousepad_encoding_dialog_test_encodings_idle (gpointer user_data)
       /* get the first model iter, if there is one */
       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dialog->store), &needle))
         {
-          while (TRUE)
+          for (;;)
             {
               /* get the column value */
               gtk_tree_model_get (GTK_TREE_MODEL (dialog->store), &needle, COLUMN_UNPRINTABLE, &value, -1);
diff --git a/mousepad/mousepad-file.c b/mousepad/mousepad-file.c
index b0ed998..15efa86 100644
--- a/mousepad/mousepad-file.c
+++ b/mousepad/mousepad-file.c
@@ -34,7 +34,7 @@
 
 
 #define MAX_ENCODING_CHECK_CHARS       (10000)
-#define MOUSEPAD_GET_LINE_END_CHARS(a) ((a) == MOUSEPAD_LINE_END_WIN32 ? "\r\n\0" : ((a) == MOUSEPAD_LINE_END_MAC ? "\r\0" : "\n\0"))
+#define MOUSEPAD_GET_LINE_END_CHARS(a) ((a) == MOUSEPAD_LINE_END_DOS ? "\r\n\0" : ((a) == MOUSEPAD_LINE_END_MAC ? "\r\0" : "\n\0"))
 
 
 enum
@@ -298,7 +298,7 @@ mousepad_file_open (MousepadFile  *file,
   if (g_file_test (file->filename, G_FILE_TEST_EXISTS) == FALSE)
     {
       file->readonly = FALSE;
-      
+
       return TRUE;
     }
 
@@ -324,7 +324,7 @@ mousepad_file_open (MousepadFile  *file,
       gtk_text_buffer_get_start_iter (file->buffer, &end);
 
       /* read the content of the file */
-      while (TRUE)
+      for (;;)
         {
           /* read the line */
           status = g_io_channel_read_line (channel, &string, &length, &terminator_pos, error);
@@ -347,7 +347,7 @@ mousepad_file_open (MousepadFile  *file,
                   else if (strcmp (line_term, "\r") == 0)
                     file->line_ending = MOUSEPAD_LINE_END_MAC;
                   else if (strcmp (line_term, "\r\n") == 0)
-                    file->line_ending = MOUSEPAD_LINE_END_WIN32;
+                    file->line_ending = MOUSEPAD_LINE_END_DOS;
                   else
                     g_warning (_("Unknown line ending detected (%s)"), line_term);
                 }
diff --git a/mousepad/mousepad-file.h b/mousepad/mousepad-file.h
index 034216c..0f65a7f 100644
--- a/mousepad/mousepad-file.h
+++ b/mousepad/mousepad-file.h
@@ -35,8 +35,8 @@ enum _MousepadLineEnding
 {
   MOUSEPAD_LINE_END_NONE,
   MOUSEPAD_LINE_END_UNIX,
-  MOUSEPAD_LINE_END_WIN32,
-  MOUSEPAD_LINE_END_MAC
+  MOUSEPAD_LINE_END_MAC,
+  MOUSEPAD_LINE_END_DOS
 };
 
 GType               mousepad_file_get_type                 (void) G_GNUC_CONST;
diff --git a/mousepad/mousepad-private.h b/mousepad/mousepad-private.h
index dec76ca..8a9fa77 100644
--- a/mousepad/mousepad-private.h
+++ b/mousepad/mousepad-private.h
@@ -34,13 +34,19 @@ G_BEGIN_DECLS
 #define TIMER_START  GTimer *__FUNCTION__timer = g_timer_new();
 #define TIMER_SPLIT  g_print ("%s (%s:%d): %.2f ms\n", __FUNCTION__, __FILE__, __LINE__, g_timer_elapsed (__FUNCTION__timer, NULL) * 1000);
 #define TIMER_STOP   TIMER_SPLIT g_timer_destroy (__FUNCTION__timer);
-#define PRINT_LINE   g_print ("%d\n", __LINE__);
+#define PRINT_LINE   g_print ("%d (%s)\n", __LINE__, __FUNCTION__);
 
 /* optimize the properties */
 #define MOUSEPAD_PARAM_READWRITE (G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
 
-/* support for canonical strings */
-#define I_(string) (g_intern_static_string ((string)))
+/* support for canonical strings and quarks */
+#define I_(string)  (g_intern_static_string (string))
+#define QU_(string) (g_quark_from_static_string (string))
+
+/* convienient function for setting object data */
+#define mousepad_object_set_data(object,key,data)              (g_object_set_qdata ((object), QU_(key), (data)))
+#define mousepad_object_set_data_full(object,key,data,destroy) (g_object_set_qdata_full ((object), QU_(key), (data), (GDestroyNotify) (destroy)))
+#define mousepad_object_get_data(object,key)                   (g_object_get_qdata ((object), QU_(key)))
 
 /* support macros for debugging */
 #ifndef NDEBUG
@@ -82,8 +88,8 @@ G_BEGIN_DECLS
 #undef G_UNLIKELY
 
 #if defined(NDEBUG) && defined(__GNUC__) && (__GNUC__ > 2)
-#define G_LIKELY(expr) (__builtin_expect (!!(expr), 1))
-#define G_UNLIKELY(expr) (__builtin_expect (!!(expr), 0))
+#define G_LIKELY(expr) (__builtin_expect (!!(expr), TRUE))
+#define G_UNLIKELY(expr) (__builtin_expect (!!(expr), FALSE))
 #else
 #define G_LIKELY(expr) (expr)
 #define G_UNLIKELY(expr) (expr)
diff --git a/mousepad/mousepad-search-bar.c b/mousepad/mousepad-search-bar.c
index 1850a30..f2a17a9 100644
--- a/mousepad/mousepad-search-bar.c
+++ b/mousepad/mousepad-search-bar.c
@@ -165,16 +165,16 @@ mousepad_search_bar_class_init (MousepadSearchBarClass *klass)
 
   /* hide the shadow around the toolbar */
   gtk_rc_parse_string ("style \"mousepad-search-bar-style\"\n"
-                       "  {\n"
-                       "    GtkToolbar::shadow-type = GTK_SHADOW_NONE\n"
-                       "  }\n"
+                         "{\n"
+                           "GtkToolbar::shadow-type = GTK_SHADOW_NONE\n"
+                         "}\n"
                        "class \"MousepadSearchBar\" style \"mousepad-search-bar-style\"\n"
 
                        /* add 2px space between the toolbar buttons */
                        "style \"mousepad-button-style\"\n"
-                       "  {\n"
-                       "    GtkToolButton::icon-spacing = 2\n"
-                       "  }\n"
+                         "{\n"
+                           "GtkToolButton::icon-spacing = 2\n"
+                         "}\n"
                        "widget \"MousepadWindow.*.Gtk*ToolButton\" style \"mousepad-button-style\"\n");
 }
 
diff --git a/mousepad/mousepad-util.c b/mousepad/mousepad-util.c
index a0ef459..947507e 100644
--- a/mousepad/mousepad-util.c
+++ b/mousepad/mousepad-util.c
@@ -244,6 +244,130 @@ mousepad_util_key_name (const gchar *name)
 
 
 
+gchar *
+mousepad_util_utf8_strcapital (const gchar *str)
+{
+  gunichar     c;
+  const gchar *p;
+  gchar       *buf;
+  GString     *result;
+  gboolean     upper = TRUE;
+
+  _mousepad_return_val_if_fail (g_utf8_validate (str, -1, NULL), NULL);
+
+  /* create a new string */
+  result = g_string_sized_new (strlen (str));
+
+  /* walk though the string */
+  for (p = str; *p != '\0'; p = g_utf8_next_char (p))
+    {
+      /* get the unicode char */
+      c = g_utf8_get_char (p);
+
+      /* only change the case of alpha chars */
+      if (g_unichar_isalpha (c))
+        {
+          /* check case */
+          if (upper ? g_unichar_isupper (c) : g_unichar_islower (c))
+            {
+              /* currect case is already correct */
+              g_string_append_unichar (result, c);
+            }
+          else
+            {
+              /* convert the case of the char and append it */
+              buf = upper ? g_utf8_strup (p, 1) : g_utf8_strdown (p, 1);
+              g_string_append (result, buf);
+              g_free (buf);
+            }
+
+          /* next char must be lowercase */
+          upper = FALSE;
+        }
+      else
+        {
+          /* append the char */
+          g_string_append_unichar (result, c);
+
+          /* next alpha char uppercase after a space */
+          upper = g_unichar_isspace (c);
+        }
+    }
+
+  /* return the result */
+  return g_string_free (result, FALSE);
+}
+
+
+
+gchar *
+mousepad_util_utf8_stropposite (const gchar *str)
+{
+  gunichar     c;
+  const gchar *p;
+  gchar       *buf;
+  GString     *result;
+
+  _mousepad_return_val_if_fail (g_utf8_validate (str, -1, NULL), NULL);
+
+  /* create a new string */
+  result = g_string_sized_new (strlen (str));
+
+  /* walk though the string */
+  for (p = str; *p != '\0'; p = g_utf8_next_char (p))
+    {
+      /* get the unicode char */
+      c = g_utf8_get_char (p);
+
+      /* only change the case of alpha chars */
+      if (g_unichar_isalpha (c))
+        {
+          /* get the opposite case of the char */
+          if (g_unichar_isupper (c))
+            buf = g_utf8_strdown (p, 1);
+          else
+            buf = g_utf8_strup (p, 1);
+
+          /* append to the buffer */
+          g_string_append (result, buf);
+          g_free (buf);
+        }
+      else
+        {
+          /* append the char */
+          g_string_append_unichar (result, c);
+        }
+    }
+
+  /* return the result */
+  return g_string_free (result, FALSE);
+}
+
+
+
+gchar *
+mousepad_util_escape_underscores (const gchar *str)
+{
+  GString     *result;
+  const gchar *s;
+
+  /* allocate a new string */
+  result = g_string_sized_new (strlen (str));
+
+  /* escape all underscores */
+  for (s = str; *s != '\0'; ++s)
+    {
+      if (G_UNLIKELY (*s == '_'))
+        g_string_append (result, "__");
+      else
+        g_string_append_c (result, *s);
+    }
+
+  return g_string_free (result, FALSE);
+}
+
+
+
 GtkWidget *
 mousepad_util_image_button (const gchar *stock_id,
                             const gchar *label)
@@ -273,7 +397,7 @@ mousepad_util_entry_error (GtkWidget *widget,
   _mousepad_return_if_fail (GTK_IS_WIDGET (widget));
 
   /* get the current error state */
-  pointer = g_object_get_data (G_OBJECT (widget), I_("error-state"));
+  pointer = mousepad_object_get_data (G_OBJECT (widget), "error-state");
 
   /* only change the state when really needed to avoid multiple widget calls */
   if (GPOINTER_TO_INT (pointer) != error)
@@ -283,7 +407,7 @@ mousepad_util_entry_error (GtkWidget *widget,
       gtk_widget_modify_text (widget, GTK_STATE_NORMAL, error ? &white : NULL);
 
       /* set the new state */
-      g_object_set_data (G_OBJECT (widget), I_("error-state"), GINT_TO_POINTER (error));
+      mousepad_object_set_data (G_OBJECT (widget), "error-state", GINT_TO_POINTER (error));
     }
 }
 
@@ -376,15 +500,19 @@ mousepad_util_get_real_line_offset (const GtkTextIter *iter,
   gint        offset = 0;
   GtkTextIter needle = *iter;
 
+  /* move the needle to the start of the line */
   gtk_text_iter_set_line_offset (&needle, 0);
 
+  /* forward the needle until we hit the iter */
   while (!gtk_text_iter_equal (&needle, iter))
     {
+      /* append the real tab offset or 1 */
       if (gtk_text_iter_get_char (&needle) == '\t')
         offset += (tab_size - (offset % tab_size));
       else
         offset++;
 
+      /* next char */
       gtk_text_iter_forward_char (&needle);
     }
 
@@ -469,7 +597,7 @@ mousepad_util_search_iter (const GtkTextIter   *start,
   iter = *start;
 
   /* walk from the start to the end iter */
-  do
+  for (;;)
     {
       /* break when we reach the limit iter */
       if (G_UNLIKELY (gtk_text_iter_equal (&iter, limit)))
@@ -555,7 +683,6 @@ mousepad_util_search_iter (const GtkTextIter   *start,
           || (search_backwards && !gtk_text_iter_backward_char (&iter)))
         break;
     }
-  while (TRUE);
 
   return succeed;
 }
diff --git a/mousepad/mousepad-util.h b/mousepad/mousepad-util.h
index b25681a..687b415 100644
--- a/mousepad/mousepad-util.h
+++ b/mousepad/mousepad-util.h
@@ -74,6 +74,12 @@ gchar     *mousepad_util_config_name              (const gchar         *name);
 
 gchar     *mousepad_util_key_name                 (const gchar         *name);
 
+gchar     *mousepad_util_utf8_strcapital          (const gchar         *str);
+
+gchar     *mousepad_util_utf8_stropposite         (const gchar         *str);
+
+gchar     *mousepad_util_escape_underscores       (const gchar         *str);
+
 GtkWidget *mousepad_util_image_button             (const gchar         *stock_id,
                                                    const gchar         *label);
 
diff --git a/mousepad/mousepad-view.c b/mousepad/mousepad-view.c
index a91c643..5e97b57 100644
--- a/mousepad/mousepad-view.c
+++ b/mousepad/mousepad-view.c
@@ -31,6 +31,8 @@
 
 
 
+#define LINE_NUMBER_MARGIN             (10)
+#define LINE_NUMBER_OFFSET             (4)
 #define mousepad_view_get_buffer(view) (GTK_TEXT_VIEW (view)->buffer)
 
 
@@ -52,25 +54,26 @@ static gboolean  mousepad_view_selection_word_range          (const GtkTextIter
                                                               GtkTextIter        *range_start,
                                                               GtkTextIter        *range_end);
 static void      mousepad_view_selection_key_press_event     (MousepadView       *view,
-                                                              GdkEventKey        *event,
+                                                              const gchar        *text,
+                                                              guint               keyval,
                                                               guint               modifiers);
+static void      mousepad_view_commit_handler                (GtkIMContext       *context,
+                                                              const gchar        *str,
+                                                              MousepadView       *view);
 static void      mousepad_view_selection_delete_content      (MousepadView       *view);
 static void      mousepad_view_selection_destroy             (MousepadView       *view);
-static void      mousepad_view_selection_cleanup_equal_marks (MousepadView       *view);
-static void      mousepad_view_selection_add_marks           (MousepadView       *view,
-                                                              GtkTextIter        *start_iter,
-                                                              GtkTextIter        *end_iter);
 static void      mousepad_view_selection_draw                (MousepadView       *view,
-                                                              gboolean            draw_cursors,
-                                                              gboolean            add_marks);
+                                                              gboolean            append);
 static gboolean  mousepad_view_selection_timeout             (gpointer            user_data);
 static void      mousepad_view_selection_timeout_destroy     (gpointer            user_data);
+static gchar    *mousepad_view_selection_string              (MousepadView       *view);
 static void      mousepad_view_indent_increase               (MousepadView       *view,
                                                               GtkTextIter        *iter);
 static void      mousepad_view_indent_decrease               (MousepadView       *view,
                                                               GtkTextIter        *iter);
 static void      mousepad_view_indent_selection              (MousepadView       *view,
-                                                              gboolean            increase);
+                                                              gboolean            increase,
+                                                              gboolean            force);
 static gchar    *mousepad_view_indent_string                 (GtkTextBuffer      *buffer,
                                                               const GtkTextIter  *iter);
 static gint      mousepad_view_calculate_layout_width        (GtkWidget          *widget,
@@ -89,15 +92,6 @@ static void      mousepad_view_transpose_words               (GtkTextBuffer
 
 
 
-enum _MousepadViewFlags
-{
-  HAS_SELECTION = 1 << 0, /* if there are marks in the selection list */
-  EDITING_MODE  = 1 << 1, /* users can type in the selection */
-  HAS_CONTENT   = 1 << 2, /* selection contains content */
-  DRAGGING      = 1 << 3, /* still dragging */
-  MULTIPLE      = 1 << 4  /* whether this is an multiple selection */
-};
-
 struct _MousepadViewClass
 {
   GtkTextViewClass __parent__;
@@ -107,14 +101,11 @@ struct _MousepadView
 {
   GtkTextView  __parent__;
 
-  /* current status */
-  MousepadViewFlags   flags;
-
   /* the selection style tag */
   GtkTextTag         *selection_tag;
 
   /* list with all the selection marks */
-  GSList             *marks;
+  GSList             *selection_marks;
 
   /* selection timeout id */
   guint               selection_timeout_id;
@@ -125,9 +116,12 @@ struct _MousepadView
   gint                selection_end_x;
   gint                selection_end_y;
 
-  /* length of the selection */
+  /* length of the selection (-1 = zerro width selection, 0 = no selection) */
   gint                selection_length;
 
+  /* if the selection is in editing mode */
+  guint               selection_editing : 1;
+
   /* settings */
   guint               auto_indent : 1;
   guint               line_numbers : 1;
@@ -194,10 +188,17 @@ mousepad_view_init (MousepadView *view)
 
   /* initialize selection variables */
   view->selection_timeout_id = 0;
-  view->flags = 0;
   view->selection_tag = NULL;
-  view->marks = NULL;
+  view->selection_marks = NULL;
   view->selection_length = 0;
+  view->selection_editing = FALSE;
+
+  /* reset drag coordinates */
+  view->selection_start_x = view->selection_end_x = -1;
+  view->selection_start_y = view->selection_end_y = -1;
+
+  g_signal_connect (GTK_TEXT_VIEW (view)->im_context, "commit",
+                    G_CALLBACK (mousepad_view_commit_handler), view);
 }
 
 
@@ -211,9 +212,9 @@ mousepad_view_finalize (GObject *object)
   if (G_UNLIKELY (view->selection_timeout_id != 0))
     g_source_remove (view->selection_timeout_id);
 
-  /* free the selection marks list */
-  if (G_UNLIKELY (view->marks != NULL))
-    g_slist_free (view->marks);
+  /* free the selection marks list (marks are owned by the buffer) */
+  if (G_UNLIKELY (view->selection_marks != NULL))
+    g_slist_free (view->selection_marks);
 
   (*G_OBJECT_CLASS (mousepad_view_parent_class)->finalize) (object);
 }
@@ -226,35 +227,36 @@ mousepad_view_expose (GtkWidget      *widget,
 {
   GtkTextView  *textview = GTK_TEXT_VIEW (widget);
   MousepadView *view = MOUSEPAD_VIEW (widget);
-  gint          y_top, y_offset, y_bottom;
-  gint          y, height;
-  gint          line_number = 0, line_count;
+  gint          y_start, y_offset, y_finish;
+  gint          y_iter, height;
+  gint          line_number, line_count;
   GtkTextIter   iter;
-  gint          width;
+  gint          width, border_width;
   PangoLayout  *layout;
   gchar         str[8]; /* maximum of 10e6 lines */
 
-  if (view->flags != 0
-      && MOUSEPAD_HAS_FLAG (view->flags, HAS_CONTENT) == FALSE
-      && event->window == gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_TEXT))
+  if (G_UNLIKELY (view->selection_length == -1
+      && (view->selection_marks != NULL || view->selection_end_x != -1)
+      && event->window == gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_TEXT)))
     {
-      /* redraw the retangles for the vertical selection */
-      mousepad_view_selection_draw (view, TRUE, FALSE);
+      /* redraw the cursor lines for the vertical selection */
+      mousepad_view_selection_draw (view, FALSE);
     }
   else if (event->window == gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_LEFT))
     {
       /* get the real start position */
       gtk_text_view_window_to_buffer_coords (textview, GTK_TEXT_WINDOW_LEFT,
-                                             0, event->area.y, NULL, &y_top);
+                                             0, event->area.y, NULL, &y_start);
 
-      /* get the bottom position */
-      y_bottom = y_top + event->area.height;
+      /* get the left window y offset (this is *NOT* the textview offset!) */
+      y_offset = event->area.y - y_start;
 
-      /* get the buffer offset (negative value or 0) */
-      y_offset = event->area.y - y_top;
+      /* get the bottom position */
+      y_finish = y_start + event->area.height;
 
-      /* get the start iter */
-      gtk_text_view_get_line_at_y (textview, &iter, y_top, NULL);
+      /* get the start iter and its line number */
+      gtk_text_view_get_line_at_y (textview, &iter, y_start, NULL);
+      line_number = gtk_text_iter_get_line (&iter);
 
       /* get the number of lines in the buffer */
       line_count = gtk_text_buffer_get_line_count (textview->buffer);
@@ -265,57 +267,67 @@ mousepad_view_expose (GtkWidget      *widget,
       /* create the pango layout */
       layout = gtk_widget_create_pango_layout (widget, str);
       pango_layout_get_pixel_size (layout, &width, NULL);
+
+      /* border width */
+      border_width = width + LINE_NUMBER_MARGIN;
+
+      /* check if we need to set the border size again */
+      if (G_UNLIKELY (gtk_text_view_get_border_window_size (textview, GTK_TEXT_WINDOW_LEFT) != border_width))
+        {
+          /* set the new border size */
+          gtk_text_view_set_border_window_size (textview, GTK_TEXT_WINDOW_LEFT, border_width);
+
+          /* leave, we'll redraw on the next expose event */
+          goto bail_out;
+        }
+
+      /* finish the pango layout */
       pango_layout_set_width (layout, width);
       pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
 
-      /* set the width of the left window border */
-      gtk_text_view_set_border_window_size (textview, GTK_TEXT_WINDOW_LEFT, width + 8);
-
       /* draw a vertical line to separate the numbers and text */
       gtk_paint_vline (widget->style, event->window,
                        GTK_WIDGET_STATE (widget),
                        NULL, widget, NULL,
                        event->area.y,
                        event->area.y + event->area.height,
-                       width + 6);
+                       border_width - 2);
 
       /* walk through the lines until we hit the last line */
-      while (line_number < line_count)
+      for (; line_number < line_count; line_number++)
         {
           /* get the y position and the height of the iter */
-          gtk_text_view_get_line_yrange (textview, &iter, &y, &height);
-
-          /* include the buffer offset */
-          y += y_offset;
-
-          /* get the number of the line */
-          line_number = gtk_text_iter_get_line (&iter) + 1;
+          gtk_text_view_get_line_yrange (textview, &iter, &y_iter, &height);
 
           /* create the number */
-          g_snprintf (str, sizeof (str), "%d", line_number);
+          g_snprintf (str, sizeof (str), "%d", line_number + 1);
 
           /* create the pange layout */
-          pango_layout_set_text (layout, str, strlen (str));
+          pango_layout_set_text (layout, str, -1);
 
           /* draw the layout on the left window */
           gtk_paint_layout (widget->style, event->window,
                             GTK_WIDGET_STATE (widget),
                             FALSE, NULL, widget, NULL,
-                            width + 2, y, layout);
+                            width + LINE_NUMBER_OFFSET,
+                            y_iter + y_offset, layout);
 
           /* stop when we reached the end of the expose area */
-          if ((y + height) >= y_bottom)
+          if (y_iter + height >= y_finish)
             break;
 
           /* jump to the next line */
           gtk_text_iter_forward_line (&iter);
         }
 
+      /* label for leaving after setting the left border size */
+      bail_out:
+
       /* release the pango layout */
       g_object_unref (G_OBJECT (layout));
     }
 
-  /* Gtk can draw the text now */
+  /* gtk can draw the text now */
   return (*GTK_WIDGET_CLASS (mousepad_view_parent_class)->expose_event) (widget, event);
 }
 
@@ -359,8 +371,8 @@ mousepad_view_style_set (GtkWidget *widget,
       mousepad_view_set_tab_size (view, view->tab_size);
 
       /* redraw selection */
-      if (view->flags != 0)
-        mousepad_view_selection_draw (view, !MOUSEPAD_HAS_FLAG (view->flags, HAS_CONTENT), FALSE);
+      if (view->selection_marks != NULL)
+        mousepad_view_selection_draw (view, FALSE);
     }
 }
 
@@ -421,7 +433,7 @@ mousepad_view_key_press_event (GtkWidget   *widget,
                     gtk_text_buffer_end_user_action (buffer);
 
                     /* make sure the new string is visible for the user */
-                    mousepad_view_put_cursor_on_screen (view);
+                    mousepad_view_scroll_to_cursor (view);
                   }
 
                 /* cleanup */
@@ -478,7 +490,7 @@ mousepad_view_key_press_event (GtkWidget   *widget,
                gtk_text_buffer_place_cursor (buffer, &iter);
 
              /* make sure the cursor is visible for the user */
-             mousepad_view_put_cursor_on_screen (view);
+             mousepad_view_scroll_to_cursor (view);
 
              return TRUE;
           }
@@ -486,10 +498,25 @@ mousepad_view_key_press_event (GtkWidget   *widget,
 
       case GDK_Delete:
       case GDK_KP_Delete:
+        if (view->selection_marks != NULL && is_editable)
+          {
+            /* delete or destroy the selection */
+            if (view->selection_length > 0)
+              mousepad_view_delete_selection (view);
+            else
+              mousepad_view_selection_destroy (view);
+
+            return TRUE;
+          }
+        break;
+
       case GDK_BackSpace:
-        if (view->flags != 0)
+        if (view->selection_marks != NULL && is_editable)
           {
-            goto selection_key_press;
+            /* backspace in the selection */
+            mousepad_view_selection_key_press_event (view, NULL, GDK_BackSpace, modifiers);
+
+            return TRUE;
           }
         break;
 
@@ -498,14 +525,17 @@ mousepad_view_key_press_event (GtkWidget   *widget,
       case GDK_ISO_Left_Tab:
         if (G_LIKELY (is_editable))
           {
-            if (view->flags != 0)
+            if (view->selection_marks != NULL)
               {
-                goto selection_key_press;
+                /* insert a tab in the selection */
+                mousepad_view_selection_key_press_event (view, NULL, GDK_Tab, modifiers);
+
+                return TRUE;
               }
             else if (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL))
               {
                 /* indent the selection */
-                mousepad_view_indent_selection (view, (modifiers & GDK_SHIFT_MASK));
+                mousepad_view_indent_selection (view, !(modifiers & GDK_SHIFT_MASK), FALSE);
 
                 return TRUE;
               }
@@ -530,21 +560,25 @@ mousepad_view_key_press_event (GtkWidget   *widget,
         break;
 
       default:
-        if (view->flags != 0 && event->length > 0)
+        if (G_UNLIKELY (view->selection_marks != NULL && is_editable))
           {
-            /* label for tab and backspace */
-            selection_key_press:
+            /* block textview updates (from gtk) */
+            gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
 
-            /* handle a key press event for a selection */
-            mousepad_view_selection_key_press_event (view, event, modifiers);
+            /* handle the im context */
+            im_handled = gtk_im_context_filter_keypress (GTK_TEXT_VIEW (view)->im_context, event);
 
-            return TRUE;
+            /* allow textview updates again */
+            gtk_text_view_set_editable (GTK_TEXT_VIEW (view), TRUE);
+
+            /* only leave when the im handle the event */
+            if (im_handled)
+              return TRUE;
           }
-        break;
     }
 
   /* remove the selection when no valid key combination has been pressed */
-  if (G_UNLIKELY (view->flags != 0 && event->is_modifier == FALSE))
+  if (G_UNLIKELY (view->selection_marks != NULL && event->is_modifier == FALSE))
     mousepad_view_selection_destroy (view);
 
   return (*GTK_WIDGET_CLASS (mousepad_view_parent_class)->key_press_event) (widget, event);
@@ -552,6 +586,27 @@ mousepad_view_key_press_event (GtkWidget   *widget,
 
 
 
+static void
+mousepad_view_commit_handler (GtkIMContext *context,
+                              const gchar  *str,
+                              MousepadView *view)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+  _mousepad_return_if_fail (GTK_IS_IM_CONTEXT (context));
+
+  /* if there is a selection, insert this string there too */
+  if (G_UNLIKELY (view->selection_marks != NULL))
+    {
+      /* debug check */
+      _mousepad_return_if_fail (gtk_text_view_get_editable (GTK_TEXT_VIEW (view)) == FALSE);
+
+      /* handle the text input for the multi selection */
+      mousepad_view_selection_key_press_event (view, str, 0, 0);
+    }
+}
+
+
+
 static gboolean
 mousepad_view_button_press_event (GtkWidget      *widget,
                                   GdkEventButton *event)
@@ -561,6 +616,10 @@ mousepad_view_button_press_event (GtkWidget      *widget,
   GtkTextIter    iter, start_iter, end_iter;
   GtkTextBuffer *buffer;
 
+  /* destroy old selection */
+  if (view->selection_marks != NULL && event->button != 3)
+    mousepad_view_selection_destroy (view);
+
   /* work with vertical selection while ctrl is pressed */
   if (event->state & GDK_CONTROL_MASK
       && event->x >= 0
@@ -568,16 +627,12 @@ mousepad_view_button_press_event (GtkWidget      *widget,
       && event->button == 1
       && event->type == GDK_BUTTON_PRESS)
     {
-      /* set the vertical selection start position, inclusing textview offset */
+      /* set the vertical selection start position, including textview offset */
       view->selection_start_x = event->x + textview->xoffset;
       view->selection_start_y = event->y + textview->yoffset;
 
-      /* whether this is going to be a multiple selection */
-      if (view->flags != 0)
-        MOUSEPAD_SET_FLAG (view->flags, MULTIPLE);
-
-      /* enable dragging */
-      MOUSEPAD_SET_FLAG (view->flags, DRAGGING);
+      /* hide cursor */
+      gtk_text_view_set_cursor_visible (textview, FALSE);
 
       /* start a vertical selection timeout */
       view->selection_timeout_id = g_timeout_add_full (G_PRIORITY_LOW, 50, mousepad_view_selection_timeout,
@@ -585,47 +640,24 @@ mousepad_view_button_press_event (GtkWidget      *widget,
 
       return TRUE;
     }
-  else if (event->type == GDK_2BUTTON_PRESS) /* todo, button 1 en pos x coords */
+  else if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
     {
       /* get the iter under the cursor */
       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter,
-                                          event->x + textview->xoffset, event->y + textview->yoffset);
+                                          event->x + textview->xoffset,
+                                          event->y + textview->yoffset);
 
       /* try to select a whole word or space */
       if (mousepad_view_selection_word_range (&iter, &start_iter, &end_iter))
         {
-          /* get buffer */
+          /* get the buffer */
           buffer = mousepad_view_get_buffer (view);
 
-          /* add to normal selection or multiple selection */
-          if (event->state & GDK_CONTROL_MASK)
-            {
-              /* make it a multiple selection when there is already something selected */
-              if (view->flags != 0)
-                MOUSEPAD_SET_FLAG (view->flags, MULTIPLE);
-
-              /* add to the list */
-              mousepad_view_selection_add_marks (view, &start_iter, &end_iter);
-
-              /* redraw */
-              mousepad_view_selection_draw (view, FALSE, FALSE);
+          /* select range */
+          gtk_text_buffer_select_range (buffer, &end_iter, &start_iter);
 
-              /* set the cursor at the end of the word */
-              gtk_text_buffer_place_cursor (buffer, &end_iter);
-            }
-          else
-            {
-              /* select range */
-              gtk_text_buffer_select_range (buffer, &start_iter, &end_iter);
-            }
+          return TRUE;
         }
-
-      return TRUE;
-    }
-  else if (view->flags != 0 && event->button != 3)
-    {
-      /* no drag started or continued */
-      mousepad_view_selection_destroy (view);
     }
 
   return (*GTK_WIDGET_CLASS (mousepad_view_parent_class)->button_press_event) (widget, event);
@@ -638,7 +670,6 @@ mousepad_view_button_release_event (GtkWidget      *widget,
                                     GdkEventButton *event)
 {
   MousepadView  *view = MOUSEPAD_VIEW (widget);
-  gboolean       has_content;
 
   /* end of a vertical selection */
   if (G_UNLIKELY (view->selection_timeout_id != 0))
@@ -646,14 +677,12 @@ mousepad_view_button_release_event (GtkWidget      *widget,
       /* stop the timeout */
       g_source_remove (view->selection_timeout_id);
 
-      /* check if the selection has any content */
-      has_content = MOUSEPAD_HAS_FLAG (view->flags, HAS_CONTENT);
+      /* append the selected marks */
+      mousepad_view_selection_draw (view, TRUE);
 
-      /* prepend the selected marks */
-      mousepad_view_selection_draw (view, !has_content, TRUE);
-
-      /* remove the dragging flag */
-      MOUSEPAD_UNSET_FLAG (view->flags, DRAGGING);
+      /* reset the drag coordinates */
+      view->selection_start_x = view->selection_end_x = -1;
+      view->selection_start_y = view->selection_end_y = -1;
     }
 
   return (*GTK_WIDGET_CLASS (mousepad_view_parent_class)->button_release_event) (widget, event);
@@ -706,85 +735,65 @@ mousepad_view_selection_word_range (const GtkTextIter *iter,
 
 static void
 mousepad_view_selection_key_press_event (MousepadView *view,
-                                         GdkEventKey  *event,
+                                         const gchar  *text,
+                                         guint         keyval,
                                          guint         modifiers)
 {
-  GtkTextIter    start, end;
+  GtkTextIter    start_iter, end_iter;
   GSList        *li;
   GtkTextBuffer *buffer;
-  gboolean       has_content = FALSE;
 
-  _mousepad_return_if_fail (view->marks != NULL);
+  _mousepad_return_if_fail (view->selection_marks != NULL);
+  _mousepad_return_if_fail (view->selection_start_x == -1);
+  _mousepad_return_if_fail (view->selection_end_x == -1);
+  _mousepad_return_if_fail ((keyval == 0 && text != NULL) || keyval != 0);
+  _mousepad_return_if_fail (g_slist_length (view->selection_marks) % 2 == 0);
 
-  /* get buffer */
+  /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
 
   /* begin user action */
   gtk_text_buffer_begin_user_action (buffer);
 
-  /* delete the content when the selection has content, we're not
-   * in editing more or the delete key is pressed */
-  if (MOUSEPAD_HAS_FLAG (view->flags, HAS_CONTENT))
-    {
-      if (!MOUSEPAD_HAS_FLAG (view->flags, EDITING_MODE)
-         || (event->keyval == GDK_Delete || event->keyval == GDK_KP_Delete))
-        {
-          mousepad_view_selection_delete_content (view);
-        }
-    }
+  /* delete the content of the selection when we're not in editing mode yet */
+  if (view->selection_editing == FALSE && view->selection_length > 0)
+    mousepad_view_selection_delete_content (view);
 
   /* enter editing mode */
-  MOUSEPAD_SET_FLAG (view->flags, EDITING_MODE);
+  view->selection_editing = TRUE;
 
-  for (li = view->marks; li != NULL; li = li->next)
+  for (li = view->selection_marks; li != NULL; li = li->next)
     {
       /* get end iter */
-      gtk_text_buffer_get_iter_at_mark (buffer, &end, li->next->data);
+      gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, li->next->data);
 
-      /* handle the events */
-      switch (event->keyval)
+      /* handle the event */
+      if (keyval == GDK_Tab)
         {
-          case GDK_Tab:
-          case GDK_KP_Tab:
-          case GDK_ISO_Left_Tab:
-            /* insert a (soft) tab */
-            mousepad_view_indent_increase (view, &end);
-            break;
-
-          case GDK_BackSpace:
-            /* get start iter */
-            gtk_text_buffer_get_iter_at_mark (buffer, &start, li->data);
-
-            /* only backspace when there is text inside the selection or ctrl is pressed */
-            if (!gtk_text_iter_equal (&start, &end) || modifiers == GDK_CONTROL_MASK)
-              {
-                gtk_text_buffer_backspace (buffer, &end, FALSE, TRUE);
-              }
-            break;
-
-          default:
-            /* insert the typed string */
-            gtk_text_buffer_insert (buffer, &end, event->string, event->length);
-            break;
+          /* insert a (soft) tab */
+          mousepad_view_indent_increase (view, &end_iter);
         }
-
-      /* get the start iter */
-      gtk_text_buffer_get_iter_at_mark (buffer, &start, li->data);
-
-      if (!gtk_text_iter_equal (&start, &end))
+      else if (keyval == GDK_BackSpace)
         {
-          /* select the text */
-          gtk_text_buffer_apply_tag (buffer, view->selection_tag, &start, &end);
+          /* get start iter */
+          gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, li->data);
 
-          /* we have some selected text */
-          has_content = TRUE;
+          /* only backspace when there is text inside the selection or ctrl is pressed */
+          if (!gtk_text_iter_equal (&start_iter, &end_iter) || modifiers == GDK_CONTROL_MASK)
+            gtk_text_buffer_backspace (buffer, &end_iter, FALSE, TRUE);
+        }
+      else if (text != NULL)
+        {
+          /* insert the text */
+          gtk_text_buffer_insert (buffer, &end_iter, text, -1);
         }
 
       /* go to next element in the list */
       li = li->next;
     }
 
-  /* TODO content */
+  /* redraw the content */
+  mousepad_view_selection_draw (view, FALSE);
 
   /* end user action */
   gtk_text_buffer_end_user_action (buffer);
@@ -799,9 +808,9 @@ mousepad_view_selection_delete_content (MousepadView *view)
   GtkTextIter    start_iter, end_iter;
   GSList        *li;
 
-  _mousepad_return_if_fail (view->marks != NULL);
-  _mousepad_return_if_fail (MOUSEPAD_HAS_FLAG (view->flags, HAS_CONTENT));
-  _mousepad_return_if_fail (view->marks == NULL || g_slist_length (view->marks) % 2 == 0);
+  _mousepad_return_if_fail (view->selection_marks != NULL);
+  _mousepad_return_if_fail (view->selection_length > 0);
+  _mousepad_return_if_fail (g_slist_length (view->selection_marks) % 2 == 0);
 
   /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
@@ -810,23 +819,23 @@ mousepad_view_selection_delete_content (MousepadView *view)
   gtk_text_buffer_begin_user_action (buffer);
 
   /* remove everything between the marks */
-  for (li = view->marks; li != NULL; li = li->next)
+  for (li = view->selection_marks; li != NULL; li = li->next)
     {
-      /* get end iter */
+      /* get start iter */
       gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, li->data);
 
       /* next element */
       li = li->next;
 
-      /* get start iter */
+      /* get end iter */
       gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, li->data);
 
-      /* delete */
+      /* delete content between the iters */
       gtk_text_buffer_delete (buffer, &start_iter, &end_iter);
     }
 
-  /* set the selection length to zerro */
-  view->selection_length = 0;
+  /* set the selection length to -1 */
+  view->selection_length = -1;
 
   /* end user action */
   gtk_text_buffer_end_user_action (buffer);
@@ -841,263 +850,93 @@ mousepad_view_selection_destroy (MousepadView *view)
   GSList        *li;
   GtkTextIter    start_iter, end_iter;
 
-  _mousepad_return_if_fail (view->marks != NULL);
-  _mousepad_return_if_fail (view->flags != 0);
+  _mousepad_return_if_fail (view->selection_marks != NULL);
 
   /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
 
+  /* freeze notifications */
+  g_object_freeze_notify (G_OBJECT (buffer));
+
   /* remove the selection tags */
   gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
   gtk_text_buffer_remove_tag (buffer, view->selection_tag, &start_iter, &end_iter);
 
   /* remove all the selection marks */
-  if (G_LIKELY (view->marks))
+  if (G_LIKELY (view->selection_marks))
     {
       /* delete marks from the buffer */
-      for (li = view->marks; li != NULL; li = li->next)
+      for (li = view->selection_marks; li != NULL; li = li->next)
         gtk_text_buffer_delete_mark (buffer, li->data);
 
       /* free the list */
-      g_slist_free (view->marks);
+      g_slist_free (view->selection_marks);
 
       /* null */
-      view->marks = NULL;
+      view->selection_marks = NULL;
     }
 
-  /* reset status */
-  view->flags = 0;
-
   /* set selection length to zerro */
   view->selection_length = 0;
-}
-
-
-
-static void
-mousepad_view_selection_cleanup_equal_marks (MousepadView *view)
-{
-  GtkTextBuffer *buffer;
-  GtkTextIter    start_iter, end_iter;
-  GSList        *li, *lnext;
-
-  _mousepad_return_if_fail (view->marks == NULL || g_slist_length (view->marks) % 2 == 0);
-
-  /* get buffer */
-  buffer = mousepad_view_get_buffer (view);
-
-  for (li = view->marks; li != NULL; li = lnext)
-    {
-      /* get iters */
-      gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, li->data);
-      gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, li->next->data);
-
-      /* get next element */
-      lnext = li->next->next;
-
-      if (gtk_text_iter_equal (&start_iter, &end_iter))
-        {
-          gtk_text_buffer_delete_mark (buffer, li->next->data);
-          view->marks = g_slist_delete_link (view->marks, li->next);
-
-          gtk_text_buffer_delete_mark (buffer, li->data);
-          view->marks = g_slist_delete_link (view->marks, li);
-        }
-    }
-}
-
-
-
-static void
-mousepad_view_selection_add_marks (MousepadView *view,
-                                   GtkTextIter  *start_iter,
-                                   GtkTextIter  *end_iter)
-{
-  GtkTextBuffer *buffer;
-  GtkTextIter    iter;
-  GtkTextMark   *start_mark, *end_mark;
-  GSList        *li, *lnext;
-  gboolean       is_start = FALSE;
-  gboolean       handled_start = FALSE;
-  gint           compare, length;
-
-  _mousepad_return_if_fail (view->marks == NULL || g_slist_length (view->marks) % 2 == 0);
-
-  /* make sure the iters are correctly sorted */
-  gtk_text_iter_order (start_iter, end_iter);
-
-  /* get buffer */
-  buffer = mousepad_view_get_buffer (view);
-
-  /* calculate length of selection */
-  length = gtk_text_iter_get_line_offset (end_iter) - gtk_text_iter_get_line_offset (start_iter);
-
-  /* add to selection length */
-  view->selection_length += length;
-
-  /* create marks */
-  start_mark = gtk_text_buffer_create_mark (buffer, NULL, start_iter, TRUE);
-  end_mark = gtk_text_buffer_create_mark (buffer, NULL, end_iter, FALSE);
 
-  for (li = view->marks; li != NULL; li = lnext)
-    {
-      /* type of mark */
-      is_start = !is_start;
-
-      /* determine next element in the list */
-      lnext = li->next;
-
-      /* get the iter of a mark in the list */
-      gtk_text_buffer_get_iter_at_mark (buffer, &iter, li->data);
-
-      /* search the insert position of the start mark */
-      if (!handled_start)
-        {
-          /* compare iters */
-          compare = gtk_text_iter_compare (&iter, start_iter);
-
-          if (compare >= 0)
-            {
-              if (compare == 0 && gtk_text_iter_equal (start_iter, end_iter))
-                {
-                  /* zerro width insert on top of an existing mark, skip those */
-                  gtk_text_buffer_delete_mark (buffer, start_mark);
-                  gtk_text_buffer_delete_mark (buffer, end_mark);
-
-                  break;
-                }
-              else if (is_start)
-                {
-                  /* inserted before a start mark */
-                  view->marks = g_slist_insert_before (view->marks, li, start_mark);
-                }
-              else
-                {
-                  /* inserted after a start mark, remove the new one */
-                  gtk_text_buffer_delete_mark (buffer, start_mark);
-                }
-
-              /* we've handled the start mark */
-              handled_start = TRUE;
-            }
-        }
-
-      /* handle the end mark */
-      if (handled_start)
-        {
-          /* check if the iter can be merged inside our selection */
-          if (gtk_text_iter_compare (&iter, end_iter) < 0)
-            {
-              /* delete the existing mark from the buffer */
-              gtk_text_buffer_delete_mark (buffer, li->data);
-
-              /* delete item from the list */
-              view->marks = g_slist_delete_link (view->marks, li);
-            }
-          else
-            {
-              /* handle the end mark */
-              if (is_start)
-                view->marks = g_slist_insert_before (view->marks, li, end_mark);
-              else
-                gtk_text_buffer_delete_mark (buffer, end_mark);
+  /* unset editing mode */
+  view->selection_editing = FALSE;
 
-              break;
-            }
-        }
-    }
+  /* show cursor again */
+  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), TRUE);
 
-  /* reached end of list */
-  if (li == NULL)
-    {
-      /* still not start mark added, append it to the list */
-      if (!handled_start)
-        view->marks = g_slist_append (view->marks, start_mark);
+  /* update buffer status */
+  g_object_notify (G_OBJECT (buffer), "has-selection");
 
-      /* append end mark */
-      view->marks = g_slist_append (view->marks, end_mark);
-    }
+  /* allow notifications again */
+  g_object_thaw_notify (G_OBJECT (buffer));
 }
 
 
 
 static void
 mousepad_view_selection_draw (MousepadView *view,
-                              gboolean      draw_cursors,
-                              gboolean      add_marks)
+                              gboolean      append)
 {
   GtkTextBuffer *buffer;
   GtkTextView   *textview = GTK_TEXT_VIEW (view);
   GtkTextIter    start_iter, end_iter;
-  gint           line_x, line_y;
+  GdkWindow     *window;
   gint           y, y_begin, y_height, y_end;
-  gboolean       has_content = FALSE;
+  gint           line_x, line_y;
   GdkRectangle   rect;
-  GdkWindow     *window;
+  gint           length = 0;
+  gint           visible_start_y = 0;
+  GtkTextMark   *start_mark, *end_mark;
   GSList        *li;
 
-  _mousepad_return_if_fail (view->marks == NULL || g_slist_length (view->marks) % 2 == 0);
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+  _mousepad_return_if_fail (view->selection_marks == NULL || g_slist_length (view->selection_marks) % 2 == 0);
 
   /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
 
+  /* freeze buffer notifications */
+  g_object_freeze_notify (G_OBJECT (buffer));
+
   /* get the drawable window */
   window = gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_TEXT);
 
-  if (MOUSEPAD_HAS_FLAG (view->flags, HAS_CONTENT))
+  /* cleanup the old selection */
+  if (view->selection_length > 0)
     {
       /* remove the old tags */
       gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
       gtk_text_buffer_remove_tag (buffer, view->selection_tag, &start_iter, &end_iter);
     }
-  else
+  else if (view->selection_length == -1)
     {
       /* invalidate the window so no retangles are left */
       gtk_widget_queue_draw (GTK_WIDGET (view));
     }
 
-  /* if the selection already contains marks, show them first */
-  for (li = view->marks; li != NULL; li = li->next)
-    {
-      /* get the end iter */
-      gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, li->data);
-
-      /* next element in the list */
-      li = li->next;
-
-      if (draw_cursors)
-        {
-          /* get the iter location and size */
-          gtk_text_view_get_iter_location (textview, &start_iter, &rect);
-
-          /* calculate line coordinates */
-          line_x = rect.x - textview->xoffset;
-          line_y = rect.y - textview->yoffset;
-
-          /* draw a line in front of the iter */
-          gdk_draw_line (GDK_DRAWABLE (window),
-                         GTK_WIDGET (view)->style->text_gc[GTK_STATE_NORMAL],
-                         line_x, line_y, line_x, line_y + rect.height - 1);
-        }
-      else
-        {
-          /* get the start iter */
-          gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, li->data);
-
-          /* check if the iters are not equal */
-          if (!gtk_text_iter_equal (&start_iter, &end_iter))
-            {
-              /* apply tag */
-              gtk_text_buffer_apply_tag (buffer, view->selection_tag, &start_iter, &end_iter);
-
-              /* this selection has atleast some content */
-              has_content = TRUE;
-            }
-        }
-    }
-
-  /* when we're still dragging, show the selection in the area */
-  if (MOUSEPAD_HAS_FLAG (view->flags, DRAGGING))
+  /* draw the dragging selection or the marks in the list */
+  if (view->selection_start_y != -1 && view->selection_end_y != -1)
     {
       /* get the start and end iter */
       gtk_text_view_get_iter_at_location (textview, &start_iter, 0, view->selection_start_y);
@@ -1113,6 +952,13 @@ mousepad_view_selection_draw (MousepadView *view,
       /* make sure atleast one line is selected */
       y_end += y_height;
 
+      /* get the visible area */
+      if (G_LIKELY (append == FALSE))
+        {
+          visible_start_y = MIN (y_begin, y_end);
+          visible_start_y = MAX (visible_start_y, textview->yoffset);
+        }
+
       /* walk the lines inside the selection area */
       for (y = y_begin; y < y_end; y += y_height)
         {
@@ -1120,7 +966,17 @@ mousepad_view_selection_draw (MousepadView *view,
           gtk_text_view_get_iter_at_location (textview, &start_iter, view->selection_start_x, y);
           gtk_text_view_get_iter_at_location (textview, &end_iter, view->selection_end_x, y);
 
-          if (draw_cursors)
+          /* make sure the iters are correctly sorted */
+          gtk_text_iter_order (&start_iter, &end_iter);
+
+          /* calculate length of selection */
+          length += gtk_text_iter_get_line_offset (&end_iter) - gtk_text_iter_get_line_offset (&start_iter);
+
+          /* continue if this iter is outside the visible area */
+          if (y < visible_start_y)
+            continue;
+
+          if (length == 0)
             {
               /* get the iter location and size */
               gtk_text_view_get_iter_location (textview, &end_iter, &rect);
@@ -1131,50 +987,82 @@ mousepad_view_selection_draw (MousepadView *view,
 
               /* draw a line in front of the iter */
               gdk_draw_line (GDK_DRAWABLE (window),
-                             GTK_WIDGET (view)->style->text_gc[GTK_STATE_NORMAL],
+                             GTK_WIDGET (view)->style->base_gc[GTK_STATE_SELECTED],
                              line_x, line_y, line_x, line_y + rect.height - 1);
             }
           else if (!gtk_text_iter_equal (&start_iter, &end_iter))
             {
               /* apply tag */
               gtk_text_buffer_apply_tag (buffer, view->selection_tag, &start_iter, &end_iter);
-
-              /* this selection has atleast some content */
-              has_content = TRUE;
             }
           else
             {
               /* when both of the conditions above were not met, we'll
-               * never added them to the marks list */
+               * never added them to the marks list and there is nothing to draw
+               * eighter */
               continue;
             }
 
-          /* prepend to list */
-          if (add_marks)
+          if (append)
             {
-              /* add the marks */
-              mousepad_view_selection_add_marks (view, &start_iter, &end_iter);
+              /* create marks */
+              start_mark = gtk_text_buffer_create_mark (buffer, NULL, &start_iter, TRUE);
+              end_mark = gtk_text_buffer_create_mark (buffer, NULL, &end_iter, FALSE);
+
+              /* append to the list */
+              view->selection_marks = g_slist_append (view->selection_marks, start_mark);
+              view->selection_marks = g_slist_append (view->selection_marks, end_mark);
             }
         }
-
-      /* update selection status */
-      g_object_notify (G_OBJECT (buffer), "cursor-position");
     }
+  else
+    {
+      for (li = view->selection_marks; li != NULL; li = li->next)
+        {
+          /* get the start iter */
+          gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, li->data);
 
-  /* update status when marks have been added */
-  if (add_marks && has_content && MOUSEPAD_HAS_FLAG (view->flags, MULTIPLE))
-    mousepad_view_selection_cleanup_equal_marks (view);
+          /* next element in the list */
+          li = li->next;
 
-  if (has_content)
-    MOUSEPAD_SET_FLAG (view->flags, HAS_CONTENT);
-  else
-    MOUSEPAD_UNSET_FLAG (view->flags, HAS_CONTENT);
+          /* get the end iter */
+          gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, li->data);
+
+          /* calculate length of selection */
+          length += gtk_text_iter_get_line_offset (&end_iter) - gtk_text_iter_get_line_offset (&start_iter);
+
+          if (length == 0)
+            {
+              /* get the iter location and size */
+              gtk_text_view_get_iter_location (textview, &start_iter, &rect);
+
+              /* calculate line coordinates */
+              line_x = rect.x - textview->xoffset;
+              line_y = rect.y - textview->yoffset;
+
+              /* draw a line in front of the iter */
+              gdk_draw_line (GDK_DRAWABLE (window),
+                             GTK_WIDGET (view)->style->base_gc[GTK_STATE_SELECTED],
+                             line_x, line_y, line_x, line_y + rect.height - 1);
+            }
+          else
+            {
+              /* apply tag */
+              gtk_text_buffer_apply_tag (buffer, view->selection_tag, &start_iter, &end_iter);
+            }
+        }
+    }
 
-  /* there is something in the list, prevent 0 flag */
-  if (view->marks != NULL)
-    MOUSEPAD_SET_FLAG (view->flags, HAS_SELECTION);
+  /* emit signal for selection (type) change */
+  if ((length == 0 && view->selection_length != -1)
+      || (length > 0 && view->selection_length <= 0))
+    g_object_notify (G_OBJECT (buffer), "has-selection");
 
+  /* update the selection length */
+  view->selection_length = length > 0 ? length : -1;
 
+  /* allow sending notifications again */
+  g_object_thaw_notify (G_OBJECT (buffer));
 }
 
 
@@ -1187,9 +1075,7 @@ mousepad_view_selection_timeout (gpointer user_data)
   gint           pointer_x, pointer_y;
   gint           selection_start_x, selection_start_y;
   GtkTextBuffer *buffer;
-  GtkTextIter    iter;
-
-  _mousepad_return_val_if_fail (MOUSEPAD_HAS_FLAG (view->flags, DRAGGING), FALSE);
+  GtkTextIter    iter, cursor;
 
   GDK_THREADS_ENTER ();
 
@@ -1212,26 +1098,27 @@ mousepad_view_selection_timeout (gpointer user_data)
       selection_start_x = view->selection_start_x;
       selection_start_y = view->selection_start_y;
 
-      /* only draw the visible selection during timeout */
-      view->selection_start_x = MAX (view->selection_start_x, textview->xoffset);
-      view->selection_start_y = MAX (view->selection_start_y, textview->yoffset);
-
-      /* show the selection */
-      mousepad_view_selection_draw (view, FALSE, FALSE);
-
-      /* restore the start coordinates */
-      view->selection_start_x = selection_start_x;
-      view->selection_start_y = selection_start_y;
-
       /* get the text buffer */
       buffer = mousepad_view_get_buffer (view);
 
-      /* put the cursor under the mouse pointer */
+      /* get the iter position of the cursor based on the coordinates */
       gtk_text_view_get_iter_at_location (textview, &iter, pointer_x, pointer_y);
-      gtk_text_buffer_place_cursor (buffer, &iter);
 
-      /* put cursor on screen */
-      mousepad_view_put_cursor_on_screen (view);
+      /* get the real cursor position */
+      gtk_text_buffer_get_iter_at_mark (buffer, &cursor, gtk_text_buffer_get_insert (buffer));
+
+      /* redraw the selection when the cursor position changed */
+      if (!gtk_text_iter_equal (&iter, &cursor))
+        {
+          /* show the selection */
+          mousepad_view_selection_draw (view, FALSE);
+
+          /* update the cursor position */
+          gtk_text_buffer_place_cursor (buffer, &iter);
+
+          /* put cursor on screen */
+          mousepad_view_scroll_to_cursor (view);
+        }
     }
 
   GDK_THREADS_LEAVE ();
@@ -1250,9 +1137,8 @@ mousepad_view_selection_timeout_destroy (gpointer user_data)
 
 
 
-static void
-mousepad_view_selection_clipboard (MousepadView *view,
-                                   GtkClipboard *clipboard)
+static gchar *
+mousepad_view_selection_string (MousepadView *view)
 {
   GString       *string;
   GtkTextBuffer *buffer;
@@ -1261,7 +1147,7 @@ mousepad_view_selection_clipboard (MousepadView *view,
   GtkTextIter    start_iter, end_iter;
   GSList        *li;
 
-  _mousepad_return_if_fail (view->marks == NULL || g_slist_length (view->marks) % 2 == 0);
+  _mousepad_return_val_if_fail (view->selection_marks == NULL || g_slist_length (view->selection_marks) % 2 == 0, NULL);
 
   /* create new string */
   string = g_string_new (NULL);
@@ -1269,7 +1155,7 @@ mousepad_view_selection_clipboard (MousepadView *view,
   /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
 
-  for (li = view->marks; li != NULL; li = li->next)
+  for (li = view->selection_marks; li != NULL; li = li->next)
     {
       /* get the iters */
       gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, li->data);
@@ -1282,11 +1168,9 @@ mousepad_view_selection_clipboard (MousepadView *view,
       /* fix the number of new lines between the parts */
       if (previous_line == -1)
         previous_line = line;
-      else if (!MOUSEPAD_HAS_FLAG (view->flags, MULTIPLE))
+      else
         for (; previous_line < line; previous_line++)
           string = g_string_append_c (string, '\n');
-      else
-        string = g_string_append_c (string, '\n');
 
       /* get the text slice */
       slice = gtk_text_buffer_get_slice (buffer, &start_iter, &end_iter, TRUE);
@@ -1298,11 +1182,8 @@ mousepad_view_selection_clipboard (MousepadView *view,
       g_free (slice);
     }
 
-  /* set the clipboard text */
-  gtk_clipboard_set_text (clipboard, string->str, string->len);
-
-  /* free the string */
-  g_string_free (string, TRUE);
+  /* return the string */
+  return g_string_free (string, FALSE);
 }
 
 
@@ -1396,7 +1277,8 @@ mousepad_view_indent_decrease (MousepadView *view,
 
 static void
 mousepad_view_indent_selection (MousepadView *view,
-                                gboolean      increase)
+                                gboolean      increase,
+                                gboolean      force)
 {
   GtkTextBuffer *buffer;
   GtkTextIter    start_iter, end_iter;
@@ -1406,7 +1288,7 @@ mousepad_view_indent_selection (MousepadView *view,
   /* get the textview buffer */
   buffer = mousepad_view_get_buffer (view);
 
-  if (gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter))
+  if (gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter) || force)
     {
       /* begin a user action */
       gtk_text_buffer_begin_user_action (buffer);
@@ -1417,7 +1299,7 @@ mousepad_view_indent_selection (MousepadView *view,
 
       /* only change indentation when an entire line is selected or multiple lines */
       if (start_line != end_line
-          || (gtk_text_iter_starts_line (&start_iter) && gtk_text_iter_ends_line (&end_iter)))
+          || ((gtk_text_iter_starts_line (&start_iter) && gtk_text_iter_ends_line (&end_iter)) || force))
         {
           /* change indentation of each line */
           for (i = start_line; i <= end_line; i++)
@@ -1441,7 +1323,7 @@ mousepad_view_indent_selection (MousepadView *view,
       gtk_text_buffer_end_user_action (buffer);
 
       /* put cursor on screen */
-      mousepad_view_put_cursor_on_screen (view);
+      mousepad_view_scroll_to_cursor (view);
     }
 }
 
@@ -1509,13 +1391,13 @@ mousepad_view_calculate_layout_width (GtkWidget *widget,
 
 
 void
-mousepad_view_put_cursor_on_screen (MousepadView *view)
+mousepad_view_scroll_to_cursor (MousepadView *view)
 {
   GtkTextBuffer *buffer;
 
   _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
 
-  /* get buffer */
+  /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
 
   /* scroll to visible area */
@@ -1537,7 +1419,7 @@ mousepad_view_transpose_multi_selection (GtkTextBuffer *buffer,
   _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
 
   /* get the strings and delete the existing strings */
-  for (li = view->marks; li != NULL; li = li->next)
+  for (li = view->selection_marks; li != NULL; li = li->next)
     {
       /* get the iters */
       gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, li->data);
@@ -1552,7 +1434,7 @@ mousepad_view_transpose_multi_selection (GtkTextBuffer *buffer,
     }
 
   /* insert the strings in reversed order */
-  for (li = view->marks, ls = strings; li != NULL && ls != NULL; li = li->next, ls = ls->next)
+  for (li = view->selection_marks, ls = strings; li != NULL && ls != NULL; li = li->next, ls = ls->next)
     {
       /* get the end iter */
       gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, li->next->data);
@@ -1592,25 +1474,29 @@ mousepad_view_transpose_range (GtkTextBuffer *buffer,
 
   /* get selected text */
   string = gtk_text_buffer_get_slice (buffer, start_iter, end_iter, FALSE);
+  if (G_LIKELY (string))
+    {
+      /* reverse the string */
+      reversed = g_utf8_strreverse (string, -1);
 
-  /* reverse the string */
-  reversed = g_utf8_strreverse (string, -1);
+      /* only change the buffer then the string changed */
+      if (G_LIKELY (reversed && strcmp (reversed, string) != 0))
+        {
+          /* delete the text between the iters */
+          gtk_text_buffer_delete (buffer, start_iter, end_iter);
 
-  /* cleanup */
-  g_free (string);
+          /* insert the reversed string */
+          gtk_text_buffer_insert (buffer, end_iter, reversed, -1);
 
-  /* delete the text between the iters */
-  gtk_text_buffer_delete (buffer, start_iter, end_iter);
+          /* restore start iter */
+          gtk_text_buffer_get_iter_at_offset (buffer, start_iter, offset);
+        }
 
-  /* insert the reversed string */
-  gtk_text_buffer_insert (buffer, end_iter, reversed, -1);
-
-  /* cleanup */
-  g_free (reversed);
-
-  /* restore start iter */
-  gtk_text_buffer_get_iter_at_offset (buffer, start_iter, offset);
-}
+      /* cleanup */
+      g_free (string);
+      g_free (reversed);
+    }
+}
 
 
 
@@ -1760,13 +1646,13 @@ mousepad_view_transpose (MousepadView *view)
 
   _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
 
-  /* get buffer */
+  /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
 
   /* begin user action */
   gtk_text_buffer_begin_user_action (buffer);
 
-  if (view->flags != 0)
+  if (view->selection_marks != NULL)
     {
       /* transpose a multi selection */
       mousepad_view_transpose_multi_selection (buffer, view);
@@ -1786,7 +1672,7 @@ mousepad_view_transpose (MousepadView *view)
         }
 
       /* restore selection */
-      gtk_text_buffer_select_range (buffer, &sel_start, &sel_end);
+      gtk_text_buffer_select_range (buffer, &sel_end, &sel_start);
     }
   else
     {
@@ -1832,17 +1718,24 @@ mousepad_view_clipboard_cut (MousepadView *view)
 {
   GtkClipboard  *clipboard;
   GtkTextBuffer *buffer;
+  gchar         *string;
 
   _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
-  _mousepad_return_if_fail (mousepad_view_get_selection_length (view) > 0);
+  _mousepad_return_if_fail (mousepad_view_get_selection_length (view, NULL) > 0);
 
   /* get the clipboard */
   clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view), GDK_SELECTION_CLIPBOARD);
 
-  if (view->flags != 0)
+  if (view->selection_marks != NULL)
     {
-      /* copy to clipboard */
-      mousepad_view_selection_clipboard (view, clipboard);
+      /* get the selection string */
+      string = mousepad_view_selection_string (view);
+
+      /* set the clipboard text */
+      gtk_clipboard_set_text (clipboard, string, -1);
+
+      /* cleanup */
+      g_free (string);
 
       /* cleanup the vertical selection */
       mousepad_view_selection_delete_content (view);
@@ -1852,7 +1745,7 @@ mousepad_view_clipboard_cut (MousepadView *view)
     }
   else
     {
-      /* get buffer */
+      /* get the buffer */
       buffer = mousepad_view_get_buffer (view);
 
       /* cut from buffer */
@@ -1860,7 +1753,7 @@ mousepad_view_clipboard_cut (MousepadView *view)
     }
 
   /* put cursor on screen */
-  mousepad_view_put_cursor_on_screen (view);
+  mousepad_view_scroll_to_cursor (view);
 }
 
 
@@ -1870,22 +1763,28 @@ mousepad_view_clipboard_copy (MousepadView *view)
 {
   GtkClipboard  *clipboard;
   GtkTextBuffer *buffer;
+  gchar         *string;
 
   _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
-  _mousepad_return_if_fail (mousepad_view_get_selection_length (view) > 0);
+  _mousepad_return_if_fail (mousepad_view_get_selection_length (view, NULL) > 0);
 
   /* get the clipboard */
   clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view), GDK_SELECTION_CLIPBOARD);
 
-
-  if (view->flags != 0)
+  if (view->selection_marks != NULL)
     {
-      /* copy selection to clipboard */
-      mousepad_view_selection_clipboard (view, clipboard);
+      /* get the selection string */
+      string = mousepad_view_selection_string (view);
+
+      /* set the clipboard text */
+      gtk_clipboard_set_text (clipboard, string, -1);
+
+      /* cleanup */
+      g_free (string);
     }
   else
     {
-      /* get buffer */
+      /* get the buffer */
       buffer = mousepad_view_get_buffer (view);
 
       /* copy from buffer */
@@ -1893,98 +1792,114 @@ mousepad_view_clipboard_copy (MousepadView *view)
     }
 
   /* put cursor on screen */
-  mousepad_view_put_cursor_on_screen (view);
+  mousepad_view_scroll_to_cursor (view);
 }
 
 
 
 void
 mousepad_view_clipboard_paste (MousepadView *view,
+                               const gchar  *string,
                                gboolean      paste_as_column)
 {
   GtkClipboard   *clipboard;
   GtkTextBuffer  *buffer;
   GtkTextView    *textview = GTK_TEXT_VIEW (view);
-  gchar          *string;
+  gchar          *text = NULL;
   GtkTextMark    *mark;
   GtkTextIter     iter;
+  GtkTextIter     start_iter, end_iter;
   GdkRectangle    rect;
   gchar         **pieces;
   gint            i, y;
 
-  /* get the clipboard */
-  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view), GDK_SELECTION_CLIPBOARD);
+  if (string == NULL)
+    {
+      /* get the clipboard */
+      clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view), GDK_SELECTION_CLIPBOARD);
+
+      /* get the clipboard text */
+      text = gtk_clipboard_wait_for_text (clipboard);
+
+      /* leave when the text is null */
+      if (G_UNLIKELY (text == NULL))
+        return;
+
+      /* set the string */
+      string = text;
+    }
 
   /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
 
+  /* begin user action */
+  gtk_text_buffer_begin_user_action (buffer);
+
   if (paste_as_column)
     {
-      /* get the clipboard text */
-      string = gtk_clipboard_wait_for_text (clipboard);
-
-      if (G_LIKELY (string))
-        {
-          /* chop the string into pieces */
-          pieces = g_strsplit (string, "\n", -1);
+      /* chop the string into pieces */
+      pieces = g_strsplit (string, "\n", -1);
 
-          /* cleanup */
-          g_free (string);
+      /* get iter at cursor position */
+      mark = gtk_text_buffer_get_insert (buffer);
+      gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
 
-          /* get iter at cursor position */
-          mark = gtk_text_buffer_get_insert (buffer);
-          gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
+      /* get the iter location */
+      gtk_text_view_get_iter_location (textview, &iter, &rect);
 
-          /* get the iter location */
-          gtk_text_view_get_iter_location (textview, &iter, &rect);
+      /* insert the pieces in the buffer */
+      for (i = 0; pieces[i] != NULL; i++)
+        {
+          /* insert the text in the buffer */
+          gtk_text_buffer_insert (buffer, &iter, pieces[i], -1);
 
-          /* begin user action */
-          gtk_text_buffer_begin_user_action (buffer);
+          /* break if the next piece is null */
+          if (G_UNLIKELY (pieces[i+1] == NULL))
+            break;
 
-          /* insert the pieces in the buffer */
-          for (i = 0; pieces[i] != NULL; i++)
+          /* move the iter to the next line */
+          if (!gtk_text_iter_forward_line (&iter))
             {
-              /* insert the text in the buffer */
-              gtk_text_buffer_insert (buffer, &iter, pieces[i], -1);
-
-              /* break if the next piece is null */
-              if (G_UNLIKELY (pieces[i+1] == NULL))
-                break;
-
-              /* move the iter to the next line */
-              if (!gtk_text_iter_forward_line (&iter))
-                {
-                  /* no new line, insert a new line */
-                  gtk_text_buffer_insert (buffer, &iter, "\n", 1);
-                }
-              else
-                {
-                  /* get the y coordinate for this line */
-                  gtk_text_view_get_line_yrange (textview, &iter, &y, NULL);
-
-                  /* get the iter at the correct coordinate */
-                  gtk_text_view_get_iter_at_location (textview, &iter, rect.x, y);
-                }
+              /* no new line, insert a new line */
+              gtk_text_buffer_insert (buffer, &iter, "\n", 1);
             }
+          else
+            {
+              /* get the y coordinate for this line */
+              gtk_text_view_get_line_yrange (textview, &iter, &y, NULL);
 
-          /* cleanup */
-          g_strfreev (pieces);
+              /* get the iter at the correct coordinate */
+              gtk_text_view_get_iter_at_location (textview, &iter, rect.x, y);
+            }
+        }
 
-          /* set the cursor to the last iter position */
-          gtk_text_buffer_place_cursor (buffer, &iter);
+      /* cleanup */
+      g_strfreev (pieces);
 
-          /* end user action */
-          gtk_text_buffer_end_user_action (buffer);
-        }
+      /* set the cursor to the last iter position */
+      gtk_text_buffer_place_cursor (buffer, &iter);
     }
   else
     {
-      /* paste as normal string */
-      gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, gtk_text_view_get_editable (textview));
+      /* get selection bounds */
+      gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter);
+
+      /* remove the existing selection if the iters are not equal */
+      if (!gtk_text_iter_equal (&start_iter, &end_iter))
+        gtk_text_buffer_delete (buffer, &start_iter, &end_iter);
+
+      /* insert string */
+      gtk_text_buffer_insert (buffer, &start_iter, string, -1);
     }
 
+  /* cleanup */
+  g_free (text);
+
+  /* end user action */
+  gtk_text_buffer_end_user_action (buffer);
+
   /* put cursor on screen */
-  mousepad_view_put_cursor_on_screen (view);
+  mousepad_view_scroll_to_cursor (view);
 }
 
 
@@ -1995,9 +1910,9 @@ mousepad_view_delete_selection (MousepadView *view)
   GtkTextBuffer *buffer;
 
   _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
-  _mousepad_return_if_fail (mousepad_view_get_selection_length (view) > 0);
+  _mousepad_return_if_fail (mousepad_view_get_selection_length (view, NULL) > 0);
 
-  if (view->flags != 0)
+  if (view->selection_marks != NULL)
     {
       /* remove the text in our selection */
       mousepad_view_selection_delete_content (view);
@@ -2015,7 +1930,7 @@ mousepad_view_delete_selection (MousepadView *view)
     }
 
   /* put cursor on screen */
-  mousepad_view_put_cursor_on_screen (view);
+  mousepad_view_scroll_to_cursor (view);
 }
 
 
@@ -2029,17 +1944,616 @@ mousepad_view_select_all (MousepadView *view)
   _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
 
   /* cleanup our selection */
-  if (view->flags != 0)
+  if (view->selection_marks != NULL)
     mousepad_view_selection_destroy (view);
 
-  /* get buffer */
+  /* get the buffer */
   buffer = mousepad_view_get_buffer (view);
 
   /* get the start and end iter */
   gtk_text_buffer_get_bounds (buffer, &start, &end);
 
   /* select everything between those iters */
-  gtk_text_buffer_select_range (buffer, &start, &end);
+  gtk_text_buffer_select_range (buffer, &end, &start);
+}
+
+
+
+void
+mousepad_view_change_selection (MousepadView *view)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter    start_iter, end_iter;
+  GdkRectangle   rect;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+  _mousepad_return_if_fail (mousepad_view_get_selection_length (view, NULL) != 0);
+
+  /* get the buffer */
+  buffer = mousepad_view_get_buffer (view);
+
+  /* freeze notifications */
+  g_object_freeze_notify (G_OBJECT (buffer));
+
+  if (view->selection_marks != NULL)
+    {
+      /* get the first and last iter from the selection */
+      gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, view->selection_marks->data);
+      gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, g_slist_last (view->selection_marks)->data);
+
+      /* sort the iters */
+      gtk_text_iter_order (&start_iter, &end_iter);
+
+      /* destroy the selection */
+      mousepad_view_selection_destroy (view);
+
+      /* select the range */
+      gtk_text_buffer_select_range (buffer, &end_iter, &start_iter);
+    }
+  else if (gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter))
+    {
+      /* set the start coordinates */
+      gtk_text_view_get_iter_location (GTK_TEXT_VIEW (view), &start_iter, &rect);
+      view->selection_start_x = rect.x;
+      view->selection_start_y = rect.y;
+
+      /* set the end coordinates */
+      gtk_text_view_get_iter_location (GTK_TEXT_VIEW (view), &end_iter, &rect);
+      view->selection_end_x = rect.x;
+      view->selection_end_y = rect.y;
+
+      /* drop the normal selection and hide cursor */
+      gtk_text_buffer_place_cursor (buffer, &end_iter);
+      gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
+
+      /* poke selection function to add the marks */
+      mousepad_view_selection_draw (view, TRUE);
+
+      /* reset the coordinates */
+      view->selection_start_x = view->selection_start_y = -1;
+      view->selection_end_x = view->selection_end_y = -1;
+    }
+
+  /* allow notifications again */
+  g_object_thaw_notify (G_OBJECT (buffer));
+}
+
+
+
+void
+mousepad_view_convert_selection_case (MousepadView *view,
+                                      gint          type)
+{
+  gchar         *text;
+  gchar         *converted;
+  GtkTextBuffer *buffer;
+  GtkTextIter    start_iter, end_iter;
+  gint           offset = -1;
+  GSList        *li = NULL;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+  _mousepad_return_if_fail (mousepad_view_get_selection_length (view, NULL) > 0);
+
+  /* get the buffer */
+  buffer = mousepad_view_get_buffer (view);
+
+  /* begin a user action */
+  gtk_text_buffer_begin_user_action (buffer);
+
+  if (view->selection_marks == NULL)
+    {
+      /* get selection bounds */
+      gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter);
+
+      /* get string offset */
+      offset = gtk_text_iter_get_offset (&start_iter);
+
+      /* enter the loop without hassle */
+      goto selection_enter;
+    }
+
+  /* replace all selected items */
+  for (li = view->selection_marks; li != NULL; li = li->next)
+    {
+      /* get iters from column selection */
+      gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, li->data);
+      li = li->next;
+      gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, li->data);
+
+      /* label for normal selections */
+      selection_enter:
+
+      /* get the selected string */
+      text = gtk_text_buffer_get_slice (buffer, &start_iter, &end_iter, FALSE);
+      if (G_LIKELY (text != NULL))
+        {
+          switch (type)
+            {
+              case LOWERCASE:
+                converted = g_utf8_strdown (text, -1);
+                break;
+
+              case UPPERCASE:
+                converted = g_utf8_strup (text, -1);
+                break;
+
+              case TITLECASE:
+                converted = mousepad_util_utf8_strcapital (text);
+                break;
+
+              case OPPOSITE_CASE:
+                converted = mousepad_util_utf8_stropposite (text);
+                break;
+
+              default:
+                _mousepad_assert_not_reached ();
+                break;
+            }
+
+          /* only update the buffer if the string changed */
+          if (G_LIKELY (converted && strcmp (text, converted) != 0))
+            {
+              /* debug check */
+              _mousepad_return_if_fail (g_utf8_validate (converted, -1, NULL));
+
+              /* delete old string */
+              gtk_text_buffer_delete (buffer, &start_iter, &end_iter);
+
+              /* insert string */
+              gtk_text_buffer_insert (buffer, &end_iter, converted, -1);
+            }
+
+          /* cleanup */
+          g_free (converted);
+          g_free (text);
+        }
+
+      /* leave for normal selections */
+      if (offset != -1)
+        break;
+    }
+
+  /* restore selection if needed */
+  if (offset != -1)
+    {
+      /* restore start iter */
+      gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, offset);
+
+      /* select range */
+      gtk_text_buffer_select_range (buffer, &end_iter, &start_iter);
+    }
+  else
+    {
+      /* redraw column selection */
+      mousepad_view_selection_draw (view, FALSE);
+    }
+
+  /* end user action */
+  gtk_text_buffer_end_user_action (buffer);
+}
+
+
+
+void
+mousepad_view_convert_spaces_and_tabs (MousepadView *view,
+                                       gint          type)
+{
+  GtkTextBuffer *buffer;
+  GtkTextMark   *mark;
+  GtkTextIter    start_iter, end_iter;
+  GtkTextIter    iter;
+  gint           tab_size;
+  gboolean       in_range = FALSE;
+  gboolean       no_forward;
+  gunichar       c;
+  gint           offset;
+  gint           n_spaces = 0;
+  gint           start_offset = -1;
+  gchar         *string;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+
+  /* get the buffer */
+  buffer = mousepad_view_get_buffer (view);
+
+  /* get the tab size */
+  tab_size = view->tab_size;
+
+  /* get the start and end iter */
+  if (gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter))
+    {
+      /* move to the start of the line when replacing spaces */
+      if (type == SPACES_TO_TABS && !gtk_text_iter_starts_line (&start_iter))
+        gtk_text_iter_set_line_offset (&start_iter, 0);
+
+      /* offset for restoring the selection afterwards */
+      start_offset = gtk_text_iter_get_offset (&start_iter);
+    }
+  else
+    {
+      /* get the document bounds */
+      gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
+    }
+
+  /* leave when the iters are equal (empty docs) */
+  if (gtk_text_iter_equal (&start_iter, &end_iter))
+    return;
+
+  /* begin a user action and free notifications */
+  g_object_freeze_notify (G_OBJECT (buffer));
+  gtk_text_buffer_begin_user_action (buffer);
+
+  /* create a mark to restore the end iter after modifieing the buffer */
+  mark = gtk_text_buffer_create_mark (buffer, NULL, &end_iter, FALSE);
+
+  /* walk the text between the iters */
+  for (;;)
+    {
+      /* get the character */
+      c = gtk_text_iter_get_char (&start_iter);
+
+      /* reset */
+      no_forward = FALSE;
+
+      if (type == SPACES_TO_TABS)
+        {
+          if (c == ' ' || in_range)
+            {
+              if (in_range == FALSE)
+                {
+                  /* set the start iter */
+                  iter = start_iter;
+
+                  /* get the real offset of the start iter */
+                  offset = mousepad_util_get_real_line_offset (&iter, tab_size);
+
+                  /* the number of spaces to inline with the tabs */
+                  n_spaces = tab_size - offset % tab_size;
+                }
+
+              /* check if we can already insert a tab */
+              if (n_spaces == 0)
+                {
+                  /* delete the selected spaces */
+                  gtk_text_buffer_delete (buffer, &iter, &start_iter);
+                  gtk_text_buffer_insert (buffer, &start_iter, "\t", 1);
+
+                  /* restore the end iter */
+                  gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, mark);
+
+                  /* stop being inside a range */
+                  in_range = FALSE;
+
+                  /* no need to forward (iter moved after the insert */
+                  no_forward = TRUE;
+                }
+              else
+                {
+                  /* check whether we're still in a range */
+                  in_range = (c == ' ');
+                }
+
+              /* decrease counter */
+              n_spaces--;
+            }
+
+          /* go to next line if we reached text */
+          if (!g_unichar_isspace (c))
+            {
+              /* continue to the next line if we hit non spaces */
+              gtk_text_iter_forward_line (&start_iter);
+
+              /* make sure there is no valid range anymore */
+              in_range = FALSE;
+
+              /* no need to forward */
+              no_forward = TRUE;
+            }
+        }
+      else if (type == TABS_TO_SPACES && c == '\t')
+        {
+          /* get the real offset of the iter */
+          offset = mousepad_util_get_real_line_offset (&start_iter, tab_size);
+
+          /* the number of spaces to inline with the tabs */
+          n_spaces = tab_size - offset % tab_size;
+
+          /* move one character forwards */
+          iter = start_iter;
+          gtk_text_iter_forward_char (&start_iter);
+
+          /* delete the tab */
+          gtk_text_buffer_delete (buffer, &iter, &start_iter);
+
+          /* create a string with the number of spaces */
+          string = g_strnfill (n_spaces, ' ');
+
+          /* insert the spaces */
+          gtk_text_buffer_insert (buffer, &start_iter, string, n_spaces);
+
+          /* cleanup */
+          g_free (string);
+
+          /* restore the end iter */
+          gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, mark);
+
+          /* iter already moved by the insert */
+          no_forward = TRUE;
+        }
+
+      /* break when the iters are equal (or start is bigger) */
+      if (gtk_text_iter_compare (&start_iter, &end_iter) >= 0)
+        break;
+
+      /* forward the iter */
+      if (G_LIKELY (no_forward == FALSE))
+        gtk_text_iter_forward_char (&start_iter);
+    }
+
+  /* delete our mark */
+  gtk_text_buffer_delete_mark (buffer, mark);
+
+  /* restore the selection if needed */
+  if (start_offset > -1)
+    {
+      /* restore iter and select range */
+      gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_offset);
+      gtk_text_buffer_select_range (buffer, &end_iter, &start_iter);
+    }
+
+  /* end the user action */
+  gtk_text_buffer_end_user_action (buffer);
+  g_object_thaw_notify (G_OBJECT (buffer));
+}
+
+
+
+void
+mousepad_view_strip_trailing_spaces (MousepadView *view)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter    start_iter, end_iter, needle;
+  gint           start, end, i;
+  gunichar       c;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+
+  /* get the buffer */
+  buffer = mousepad_view_get_buffer (view);
+
+  /* get range in line numbers */
+  if (gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter))
+    {
+      start = gtk_text_iter_get_line (&start_iter);
+      end = gtk_text_iter_get_line (&end_iter) + 1;
+    }
+  else
+    {
+      start = 0;
+      end = gtk_text_buffer_get_line_count (buffer);
+    }
+
+  /* begin a user action and free notifications */
+  g_object_freeze_notify (G_OBJECT (buffer));
+  gtk_text_buffer_begin_user_action (buffer);
+
+  /* walk all the selected lines */
+  for (i = start; i < end; i++)
+    {
+      /* get the iter at the line */
+      gtk_text_buffer_get_iter_at_line (buffer, &end_iter, i);
+
+      /* continue if the line is empty */
+      if (gtk_text_iter_ends_line (&end_iter))
+        continue;
+
+      /* move the iter to the end of the line */
+      gtk_text_iter_forward_to_line_end (&end_iter);
+
+      /* initialize the iters */
+      needle = start_iter = end_iter;
+
+      /* walk backwards until we hit something else then a space or tab */
+      while (gtk_text_iter_backward_char (&needle))
+        {
+          /* get the character */
+          c = gtk_text_iter_get_char (&needle);
+
+          /* set the start iter of the spaces range or stop searching */
+          if (c == ' ' || c == '\t')
+            start_iter = needle;
+          else
+            break;
+        }
+
+      /* remove the spaces/tabs if the iters are not equal */
+      if (!gtk_text_iter_equal (&start_iter, &end_iter))
+        gtk_text_buffer_delete (buffer, &start_iter, &end_iter);
+    }
+
+  /* end the user action */
+  gtk_text_buffer_end_user_action (buffer);
+  g_object_thaw_notify (G_OBJECT (buffer));
+}
+
+
+
+void
+mousepad_view_move_selection (MousepadView *view,
+                              gint          type)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter    start_iter, end_iter, iter;
+  GtkTextMark   *mark;
+  gchar         *text;
+  gboolean       insert_eol;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+
+  /* get the buffer */
+  buffer = mousepad_view_get_buffer (view);
+
+  /* begin a user action */
+  gtk_text_buffer_begin_user_action (buffer);
+
+  if (gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter))
+    {
+      if (type == MOVE_LINE_UP)
+        {
+          /* useless action if we're already at the start of the buffer */
+          if (gtk_text_iter_get_line (&start_iter) == 0)
+            goto leave;
+
+          /* set insert point to end of selected line */
+          iter = end_iter;
+          if (!gtk_text_iter_ends_line (&iter))
+            gtk_text_iter_forward_to_line_end (&iter);
+
+          /* make start iter to previous line (can not fail) */
+          gtk_text_iter_backward_line (&start_iter);
+
+          /* move end iter to end of line */
+          end_iter = start_iter;
+          if (!gtk_text_iter_ends_line (&end_iter))
+            gtk_text_iter_forward_to_line_end (&end_iter);
+
+          /* move start iter one line back */
+          insert_eol = !gtk_text_iter_backward_char (&start_iter);
+        }
+      else /* MOVE_LINE_DOWN */
+        {
+          /* useless action if we're already at the end of the buffer */
+          if (gtk_text_iter_get_line (&end_iter) == gtk_text_buffer_get_line_count (buffer) - 1)
+            goto leave;
+
+          /* move insert iter to start of the line */
+          iter = start_iter;
+          if (!gtk_text_iter_starts_line (&iter))
+            gtk_text_iter_set_line_offset (&iter, 0);
+
+          /* move start iter to the start of the line below the selection */
+          start_iter = end_iter;
+          gtk_text_iter_forward_line (&start_iter);
+
+          /* set the end iter */
+          end_iter = start_iter;
+          insert_eol = !gtk_text_iter_forward_line (&end_iter);
+        }
+
+      /* create mark at insert point */
+      mark = gtk_text_buffer_create_mark (buffer, NULL, &iter, TRUE);
+
+      /* copy the line above the selection  */
+      text = gtk_text_buffer_get_slice (buffer, &start_iter, &end_iter, FALSE);
+
+      /* delete the new line that we're going to insert later on */
+      if (insert_eol && type == MOVE_LINE_UP)
+        gtk_text_iter_forward_char (&end_iter);
+      else if (insert_eol && type == MOVE_LINE_DOWN)
+        gtk_text_iter_backward_char (&start_iter);
+
+      /* delete */
+      gtk_text_buffer_delete (buffer, &start_iter, &end_iter);
+
+      /* restore mark */
+      gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
+
+      /* insert new line if needed */
+      if (insert_eol && type == MOVE_LINE_UP)
+        gtk_text_buffer_insert (buffer, &iter, "\n", 1);
+
+      /* insert text */
+      gtk_text_buffer_insert (buffer, &iter, text, -1);
+
+      /* insert new line if needed */
+      if (insert_eol && type == MOVE_LINE_DOWN)
+        gtk_text_buffer_insert (buffer, &iter, "\n", 1);
+
+      /* cleanup */
+      g_free (text);
+
+      /* sometimes we need to restore the selection (left gravity of the selection marks) */
+      if (type == MOVE_LINE_UP)
+        {
+          /* get selection bounds */
+          gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter);
+
+          /* check if we need to restore the selected range */
+          if (gtk_text_iter_equal (&iter, &end_iter))
+            {
+              /* restore end iter from mark and select the range again */
+              gtk_text_buffer_get_iter_at_mark (buffer, &end_iter, mark);
+              gtk_text_buffer_select_range (buffer, &start_iter, &end_iter);
+            }
+        }
+
+      /* delete mark */
+      gtk_text_buffer_delete_mark (buffer, mark);
+    }
+
+  /* labeltje */
+  leave:
+
+  /* end the action */
+  gtk_text_buffer_end_user_action (buffer);
+
+  /* show */
+  mousepad_view_scroll_to_cursor (view);
+}
+
+
+
+void
+mousepad_view_duplicate (MousepadView *view)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter    start_iter, end_iter;
+  gboolean       has_selection;
+  gboolean       insert_eol = FALSE;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+
+  /* get the buffer */
+  buffer = mousepad_view_get_buffer (view);
+
+  /* begin a user action */
+  gtk_text_buffer_begin_user_action (buffer);
+
+  /* get iters */
+  has_selection = gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter);
+
+  /* select entire line */
+  if (has_selection == FALSE)
+    {
+      /* set to the start of the line */
+      if (!gtk_text_iter_starts_line (&start_iter))
+        gtk_text_iter_set_line_offset (&start_iter, 0);
+
+      /* move the other iter to the start of the next line */
+      insert_eol = !gtk_text_iter_forward_line (&end_iter);
+    }
+
+  /* insert a dupplicate of the text before the iter */
+  gtk_text_buffer_insert_range (buffer, &start_iter, &start_iter, &end_iter);
+
+  /* insert a new line if needed */
+  if (insert_eol)
+    gtk_text_buffer_insert (buffer, &start_iter, "\n", 1);
+
+  /* end the action */
+  gtk_text_buffer_end_user_action (buffer);
+}
+
+
+
+void
+mousepad_view_indent (MousepadView *view,
+                      gint          type)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (view));
+
+  /* run a forced indent of the line(s) */
+  mousepad_view_indent_selection (view, type == INCREASE_INDENT, TRUE);
 }
 
 
@@ -2059,9 +2573,6 @@ mousepad_view_set_line_numbers (MousepadView *view,
       gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view),
                                             GTK_TEXT_WINDOW_LEFT,
                                             line_numbers ? 20 : 0);
-
-      /* make sure there is an expose event */
-      gtk_widget_queue_draw (GTK_WIDGET (view));
     }
 }
 
@@ -2124,19 +2635,24 @@ mousepad_view_set_insert_spaces (MousepadView *view,
 
 
 gboolean
-mousepad_view_get_selection_length (MousepadView *view)
+mousepad_view_get_selection_length (MousepadView *view,
+                                    gboolean     *is_column_selection)
 {
   GtkTextBuffer *buffer;
   GtkTextIter    sel_start, sel_end;
   gint           sel_length = 0;
+  gboolean       column_selection;
 
   _mousepad_return_val_if_fail (MOUSEPAD_IS_VIEW (view), FALSE);
 
   /* get the text buffer */
   buffer = mousepad_view_get_buffer (view);
 
+  /* whether this is a column selection */
+  column_selection = view->selection_marks != NULL || view->selection_start_x != -1;
+
   /* we have a vertical selection */
-  if (view->flags != 0)
+  if (column_selection)
     {
       /* get the selection count from the selection draw function */
       sel_length = view->selection_length;
@@ -2147,6 +2663,10 @@ mousepad_view_get_selection_length (MousepadView *view)
       sel_length = ABS (gtk_text_iter_get_offset (&sel_end) - gtk_text_iter_get_offset (&sel_start));
     }
 
+  /* whether this is a column selection */
+  if (is_column_selection)
+    *is_column_selection = column_selection;
+
   /* return length */
   return sel_length;
 }
diff --git a/mousepad/mousepad-view.h b/mousepad/mousepad-view.h
index 7623fc3..3cb6b97 100644
--- a/mousepad/mousepad-view.h
+++ b/mousepad/mousepad-view.h
@@ -31,9 +31,35 @@ typedef struct _MousepadViewClass MousepadViewClass;
 typedef struct _MousepadView      MousepadView;
 typedef enum   _MousepadViewFlags MousepadViewFlags;
 
+enum
+{
+  LOWERCASE,
+  UPPERCASE,
+  TITLECASE,
+  OPPOSITE_CASE
+};
+
+enum
+{
+  SPACES_TO_TABS,
+  TABS_TO_SPACES
+};
+
+enum
+{
+  MOVE_LINE_UP,
+  MOVE_LINE_DOWN
+};
+
+enum
+{
+  INCREASE_INDENT,
+  DECREASE_INDENT
+};
+
 GType           mousepad_view_get_type                  (void) G_GNUC_CONST;
 
-void            mousepad_view_put_cursor_on_screen      (MousepadView      *view);
+void            mousepad_view_scroll_to_cursor          (MousepadView      *view);
 
 void            mousepad_view_transpose                 (MousepadView      *view);
 
@@ -42,12 +68,31 @@ void            mousepad_view_clipboard_cut             (MousepadView      *view
 void            mousepad_view_clipboard_copy            (MousepadView      *view);
 
 void            mousepad_view_clipboard_paste           (MousepadView      *view,
+                                                         const gchar       *string,
                                                          gboolean           paste_as_column);
 
 void            mousepad_view_delete_selection          (MousepadView      *view);
 
 void            mousepad_view_select_all                (MousepadView      *view);
 
+void            mousepad_view_change_selection          (MousepadView      *view);
+
+void            mousepad_view_convert_selection_case    (MousepadView      *view,
+                                                         gint               type);
+
+void            mousepad_view_convert_spaces_and_tabs   (MousepadView      *view,
+                                                         gint               type);
+
+void            mousepad_view_strip_trailing_spaces     (MousepadView      *view);
+
+void            mousepad_view_move_selection            (MousepadView      *view,
+                                                         gint               type);
+
+void            mousepad_view_duplicate                 (MousepadView      *view);
+
+void            mousepad_view_indent                    (MousepadView      *view,
+                                                         gint               type);
+
 void            mousepad_view_set_line_numbers          (MousepadView      *view,
                                                          gboolean           line_numbers);
 
@@ -60,7 +105,8 @@ void            mousepad_view_set_tab_size              (MousepadView      *view
 void            mousepad_view_set_insert_spaces         (MousepadView      *view,
                                                          gboolean           insert_spaces);
 
-gint            mousepad_view_get_selection_length      (MousepadView      *view);
+gint            mousepad_view_get_selection_length      (MousepadView      *view,
+                                                         gboolean          *is_column_selection);
 
 gboolean        mousepad_view_get_line_numbers          (MousepadView      *view);
 
@@ -70,6 +116,7 @@ gint            mousepad_view_get_tab_size              (MousepadView      *view
 
 gboolean        mousepad_view_get_insert_spaces         (MousepadView      *view);
 
+
 G_END_DECLS
 
 #endif /* !__MOUSEPAD_VIEW_H__ */
diff --git a/mousepad/mousepad-window-ui.xml b/mousepad/mousepad-window-ui.xml
index 6c5baaa..e271752 100644
--- a/mousepad/mousepad-window-ui.xml
+++ b/mousepad/mousepad-window-ui.xml
@@ -19,29 +19,28 @@
 
   <menubar name="main-menu">
     <menu action="file-menu">
-      <menuitem action="new-tab" />
+      <menuitem action="new" />
       <menuitem action="new-window" />
+      <menuitem action="template-menu" />
       <separator />
-      <menuitem action="open-file" />
-
+      <menuitem action="open" />
       <menu action="recent-menu">
         <menuitem action="no-recent-items" />
         <placeholder name="placeholder-recent-items" />
         <separator />
         <menuitem action="clear-recent" />
       </menu>
-
-      <separator />
-      <menuitem action="save-file" />
-      <menuitem action="save-file-as" />
       <separator />
-      <menuitem action="reload" />
+      <menuitem action="save" />
+      <menuitem action="save-as" />
+      <menuitem action="save-all" />
+      <menuitem action="revert" />
       <separator />
-      <menuitem action="print-document" />
+      <menuitem action="print" />
       <separator />
-      <menuitem action="detach-tab" />
-      <menuitem action="close-tab" />
+      <menuitem action="detach" />
       <separator />
+      <menuitem action="close" />
       <menuitem action="close-window" />
     </menu>
 
@@ -52,15 +51,15 @@
       <menuitem action="cut" />
       <menuitem action="copy" />
       <menuitem action="paste" />
-      <menuitem action="paste-column" />
+      <menu action="paste-menu">
+        <menuitem action="paste-history" />
+        <menuitem action="paste-column" />
+      </menu>
       <menuitem action="delete" />
       <separator />
       <menuitem action="select-all" />
+      <menuitem action="change-selection" />
       <separator />
-      <menuitem action="transpose" />
-    </menu>
-
-    <menu action="search-menu">
       <menuitem action="find" />
       <menuitem action="find-next" />
       <menuitem action="find-previous" />
@@ -73,26 +72,56 @@
       <menuitem action="statusbar" />
     </menu>
 
+    <menu action="text-menu">
+      <menu action="convert-menu">
+        <menuitem action="lowercase" />
+        <menuitem action="uppercase" />
+        <menuitem action="titlecase" />
+        <menuitem action="opposite-case" />
+        <separator />
+        <menuitem action="tabs-to-spaces" />
+        <menuitem action="spaces-to-tabs" />
+        <separator />
+        <menuitem action="strip-trailing" />
+        <separator />
+        <menuitem action="transpose" />
+      </menu>
+      <menu action="move-menu">
+        <menuitem action="line-up" />
+        <menuitem action="line-down" />
+      </menu>
+      <separator />
+      <menuitem action="duplicate" />
+      <separator />
+      <menuitem action="increase-indent" />
+      <menuitem action="decrease-indent" />
+    </menu>
+
     <menu action="document-menu">
       <menuitem action="line-numbers" />
+      <menuitem action="word-wrap" />
       <separator />
       <menuitem action="auto-indent" />
-      <menuitem action="word-wrap" />
       <separator />
       <menu action="tab-size-menu">
-        <placeholder name="placeholder-tab-sizes" />
+        <placeholder name="placeholder-tab-items" />
         <separator />
         <menuitem action="insert-spaces" />
       </menu>
+      <menu action="eol-menu">
+        <menuitem action="unix" />
+        <menuitem action="mac" />
+        <menuitem action="dos" />
+      </menu>
     </menu>
 
     <menu action="navigation-menu">
       <menuitem action="back" />
       <menuitem action="forward" />
       <separator />
-      <placeholder name="placeholder-documents" />
+      <placeholder name="placeholder-file-items" />
       <separator />
-      <menuitem action="go-to-line" />
+      <menuitem action="go-to" />
     </menu>
 
     <menu action="help-menu">
@@ -102,13 +131,13 @@
   </menubar>
 
   <popup action="tab-menu">
-    <menuitem action="save-file" />
-    <menuitem action="save-file-as" />
+    <menuitem action="save" />
+    <menuitem action="save-as" />
     <separator />
-    <menuitem action="reload" />
+    <menuitem action="revert" />
     <separator />
-    <menuitem action="detach-tab" />
-    <menuitem action="close-tab" />
+    <menuitem action="detach" />
+    <menuitem action="close" />
   </popup>
 
   <popup action="textview-menu">
@@ -118,8 +147,6 @@
     <menuitem action="cut" />
     <menuitem action="copy" />
     <menuitem action="paste" />
-    <menuitem action="paste-column" />
-    <menuitem action="delete" />
     <separator />
     <menuitem action="select-all" />
   </popup>
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
index 16dbf3a..9adf5a5 100644
--- a/mousepad/mousepad-window.c
+++ b/mousepad/mousepad-window.c
@@ -50,7 +50,8 @@
 
 
 
-#define PADDING (2)
+#define PADDING                   (2)
+#define PASTE_HISTORY_MENU_LENGTH (30)
 
 #if GTK_CHECK_VERSION (2,12,0)
 static gpointer NOTEBOOK_GROUP = "Mousepad";
@@ -101,8 +102,6 @@ static gboolean          mousepad_window_open_file                    (MousepadW
 static gboolean          mousepad_window_close_document               (MousepadWindow         *window,
                                                                        MousepadDocument       *document);
 static void              mousepad_window_set_title                    (MousepadWindow         *window);
-static void              mousepad_window_toggle_overwrite             (MousepadWindow         *window,
-                                                                       gboolean                overwrite);
 
 /* notebook signals */
 static void              mousepad_window_notebook_notified            (GtkNotebook            *notebook,
@@ -125,6 +124,9 @@ static void              mousepad_window_notebook_menu_position       (GtkMenu
                                                                        gint                   *y,
                                                                        gboolean               *push_in,
                                                                        gpointer                user_data);
+static gboolean          mousepad_window_notebook_button_release_event (GtkNotebook           *notebook,
+                                                                        GdkEventButton        *event,
+                                                                        MousepadWindow        *window);
 static gboolean          mousepad_window_notebook_button_press_event  (GtkNotebook            *notebook,
                                                                        GdkEventButton         *event,
                                                                        MousepadWindow         *window);
@@ -143,6 +145,9 @@ static void              mousepad_window_cursor_changed               (MousepadD
                                                                        gint                    column,
                                                                        gint                    selection,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_selection_changed            (MousepadDocument       *document,
+                                                                       gint                    selection,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_overwrite_changed            (MousepadDocument       *document,
                                                                        gboolean                overwrite,
                                                                        MousepadWindow         *window);
@@ -152,6 +157,11 @@ static void              mousepad_window_can_redo                     (MousepadW
                                                                        gboolean                can_redo);
 
 /* menu functions */
+static void              mousepad_window_menu_templates_fill          (MousepadWindow         *window,
+                                                                       GtkWidget              *menu,
+                                                                       const gchar            *path);
+static void              mousepad_window_menu_templates               (GtkWidget              *item,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_menu_tab_sizes               (MousepadWindow         *window);
 static void              mousepad_window_menu_tab_sizes_update        (MousepadWindow         *window);
 static void              mousepad_window_menu_textview_deactivate     (GtkWidget              *menu,
@@ -167,7 +177,6 @@ static void              mousepad_window_update_gomenu                (MousepadW
 /* recent functions */
 static void              mousepad_window_recent_add                   (MousepadWindow         *window,
                                                                        MousepadFile           *file);
-static gchar            *mousepad_window_recent_escape_underscores    (const gchar            *str);
 static gint              mousepad_window_recent_sort                  (GtkRecentInfo          *a,
                                                                        GtkRecentInfo          *b);
 static void              mousepad_window_recent_manager_init          (MousepadWindow         *window);
@@ -189,31 +198,54 @@ static void              mousepad_window_drag_data_received           (GtkWidget
 /* search bar */
 static void              mousepad_window_hide_search_bar              (MousepadWindow         *window);
 
+/* history clipboard functions */
+static void              mousepad_window_paste_history_add            (MousepadWindow         *window);
+static void              mousepad_window_paste_history_menu_position  (GtkMenu                *menu,
+                                                                       gint                   *x,
+                                                                       gint                   *y,
+                                                                       gboolean               *push_in,
+                                                                       gpointer                user_data);
+static void              mousepad_window_paste_history_activate       (GtkMenuItem            *item,
+                                                                       MousepadWindow         *window);
+static GtkWidget        *mousepad_window_paste_history_menu_item      (const gchar            *text,
+                                                                       const gchar            *mnemonic);
+static GtkWidget        *mousepad_window_paste_history_menu           (MousepadWindow         *window);
+
+/* miscellaneous actions */
+static void              mousepad_window_button_close_tab             (MousepadDocument       *document,
+                                                                       MousepadWindow         *window);
+static gboolean          mousepad_window_delete_event                 (MousepadWindow         *window,
+                                                                       GdkEvent               *event);
+
 /* actions */
-static void              mousepad_window_action_open_new_tab          (GtkAction              *action,
+static void              mousepad_window_action_new                   (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_open_new_window       (GtkAction              *action,
+static void              mousepad_window_action_new_window            (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_open_file             (GtkAction              *action,
+static void              mousepad_window_action_new_from_template     (GtkMenuItem            *item,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_open                  (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_open_recent           (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_clear_recent          (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static gboolean          mousepad_window_action_save_file             (GtkAction              *action,
+static gboolean          mousepad_window_action_save                  (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static gboolean          mousepad_window_action_save_as               (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static gboolean          mousepad_window_action_save_file_as          (GtkAction              *action,
+static void              mousepad_window_action_save_all              (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_reload                (GtkAction              *action,
+static void              mousepad_window_action_revert                (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_print                 (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_detach                (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_close_tab             (GtkAction              *action,
-                                                                       MousepadWindow         *window);
 static void              mousepad_window_action_close                 (GtkAction              *action,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_action_close_window          (GtkAction              *action,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_action_undo                  (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_redo                  (GtkAction              *action,
@@ -224,13 +256,15 @@ static void              mousepad_window_action_copy                  (GtkAction
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_paste                 (GtkAction              *action,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_action_paste_history         (GtkAction              *action,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_action_paste_column          (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_delete                (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_select_all            (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_transpose             (GtkAction              *action,
+static void              mousepad_window_action_change_selection      (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_find                  (GtkAction              *action,
                                                                        MousepadWindow         *window);
@@ -238,42 +272,67 @@ static void              mousepad_window_action_find_next             (GtkAction
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_find_previous         (GtkAction              *action,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_action_replace_destroy       (MousepadWindow         *window);
 static void              mousepad_window_action_replace               (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_select_font           (GtkAction              *action,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_action_statusbar_overwrite   (MousepadWindow         *window,
+                                                                       gboolean                overwrite);
 static void              mousepad_window_action_statusbar             (GtkToggleAction        *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_line_numbers          (GtkToggleAction        *action,
+static void              mousepad_window_action_lowercase             (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_auto_indent           (GtkToggleAction        *action,
+static void              mousepad_window_action_uppercase             (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_titlecase             (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_opposite_case         (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_tabs_to_spaces        (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_spaces_to_tabs        (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_strip_trailing_spaces (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_transpose             (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_move_line_up          (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_move_line_down        (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_duplicate             (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_increase_indent       (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_decrease_indent       (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_line_numbers          (GtkToggleAction        *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_word_wrap             (GtkToggleAction        *action,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_action_auto_indent           (GtkToggleAction        *action,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_action_tab_size              (GtkToggleAction        *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_insert_spaces         (GtkToggleAction        *action,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_action_line_ending           (GtkRadioAction         *action,
+                                                                       GtkRadioAction         *current,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_action_prev_tab              (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_next_tab              (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_goto                  (GtkRadioAction         *action,
+static void              mousepad_window_action_go_to_tab             (GtkRadioAction         *action,
                                                                        GtkNotebook            *notebook);
-static void              mousepad_window_action_go_to_line            (GtkAction              *action,
+static void              mousepad_window_action_go_to_position        (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_contents              (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_about                 (GtkAction              *action,
                                                                        MousepadWindow         *window);
 
-/* miscellaneous actions */
-static void              mousepad_window_button_close_tab             (MousepadDocument       *document,
-                                                                       MousepadWindow         *window);
-static gboolean          mousepad_window_delete_event                 (MousepadWindow         *window,
-                                                                       GdkEvent               *event);
-
-
 
 
 struct _MousepadWindowClass
@@ -283,7 +342,7 @@ struct _MousepadWindowClass
 
 struct _MousepadWindow
 {
-  GtkWindow            __parent__;
+  GtkWindow __parent__;
 
   /* mousepad preferences */
   MousepadPreferences *preferences;
@@ -326,19 +385,21 @@ struct _MousepadWindow
 static const GtkActionEntry action_entries[] =
 {
   { "file-menu", NULL, N_("_File"), NULL, NULL, NULL, },
-    { "new-tab", "tab-new", N_("New Documen_t"), "<control>N", N_("Create a new document"), G_CALLBACK (mousepad_window_action_open_new_tab), },
-    { "new-window", "window-new", N_("_New Window"), "<shift><control>N", N_("Create a new document in a new window"), G_CALLBACK (mousepad_window_action_open_new_window), },
-    { "open-file", GTK_STOCK_OPEN, N_("_Open File"), NULL, N_("Open a file"), G_CALLBACK (mousepad_window_action_open_file), },
-    { "recent-menu", NULL, N_("Open _Recent"), NULL, NULL, NULL, },
+    { "new", GTK_STOCK_NEW, N_("_New"), "<control>N", N_("Create a new document"), G_CALLBACK (mousepad_window_action_new), },
+    { "new-window", NULL, N_("New _Window"), "<shift><control>N", N_("Create a new document in a new window"), G_CALLBACK (mousepad_window_action_new_window), },
+    { "template-menu", NULL, N_("New From Te_mplate"), NULL, NULL, NULL, },
+    { "open", GTK_STOCK_OPEN, N_("_Open..."), NULL, N_("Open a file"), G_CALLBACK (mousepad_window_action_open), },
+    { "recent-menu", NULL, N_("Op_en Recent"), NULL, NULL, NULL, },
       { "no-recent-items", NULL, N_("No items found"), NULL, NULL, NULL, },
       { "clear-recent", GTK_STOCK_CLEAR, N_("Clear _History"), NULL, N_("Clear the recently used files history"), G_CALLBACK (mousepad_window_action_clear_recent), },
-    { "save-file", GTK_STOCK_SAVE, NULL, NULL, N_("Save the current file"), G_CALLBACK (mousepad_window_action_save_file), },
-    { "save-file-as", GTK_STOCK_SAVE_AS, NULL, NULL, N_("Save current document as another file"), G_CALLBACK (mousepad_window_action_save_file_as), },
-    { "reload", GTK_STOCK_REFRESH, N_("Re_load"), NULL, N_("Reload this document."), G_CALLBACK (mousepad_window_action_reload), },
-    { "print-document", GTK_STOCK_PRINT, NULL, "<control>P", N_("Prin the current page"), G_CALLBACK (mousepad_window_action_print), },
-    { "detach-tab", NULL, N_("_Detach Tab"), "<control>D", N_("Move the current document to a new window"), G_CALLBACK (mousepad_window_action_detach), },
-    { "close-tab", GTK_STOCK_CLOSE, N_("C_lose Tab"), "<control>W", N_("Close the current file"), G_CALLBACK (mousepad_window_action_close_tab), },
-    { "close-window", GTK_STOCK_QUIT, N_("_Close Window"), "<control>Q", N_("Quit the program"), G_CALLBACK (mousepad_window_action_close), },
+    { "save", GTK_STOCK_SAVE, NULL, "<control>S", N_("Save the current document"), G_CALLBACK (mousepad_window_action_save), },
+    { "save-as", GTK_STOCK_SAVE_AS, N_("Save _As..."), "<shift><control>S", N_("Save current document as another file"), G_CALLBACK (mousepad_window_action_save_as), },
+    { "save-all", NULL, N_("Save A_ll"), NULL, N_("Save all document in this window"), G_CALLBACK (mousepad_window_action_save_all), },
+    { "revert", GTK_STOCK_REVERT_TO_SAVED, N_("Re_vert"), NULL, N_("Revert to the saved version of the file"), G_CALLBACK (mousepad_window_action_revert), },
+    { "print", GTK_STOCK_PRINT, N_("_Print..."), "<control>P", N_("Prin the current document"), G_CALLBACK (mousepad_window_action_print), },
+    { "detach", NULL, N_("_Detach Tab"), "<control>D", N_("Move the current document to a new window"), G_CALLBACK (mousepad_window_action_detach), },
+    { "close", GTK_STOCK_CLOSE, N_("Close _Tab"), "<control>W", N_("Close the current document"), G_CALLBACK (mousepad_window_action_close), },
+    { "close-window", GTK_STOCK_QUIT, N_("_Close Window"), "<control>Q", N_("Close this window"), G_CALLBACK (mousepad_window_action_close_window), },
 
   { "edit-menu", NULL, N_("_Edit"), NULL, NULL, NULL, },
     { "undo", GTK_STOCK_UNDO, NULL, "<control>Z", N_("Undo the last action"), G_CALLBACK (mousepad_window_action_undo), },
@@ -346,27 +407,45 @@ static const GtkActionEntry action_entries[] =
     { "cut", GTK_STOCK_CUT, NULL, NULL, N_("Cut the selection"), G_CALLBACK (mousepad_window_action_cut), },
     { "copy", GTK_STOCK_COPY, NULL, NULL, N_("Copy the selection"), G_CALLBACK (mousepad_window_action_copy), },
     { "paste", GTK_STOCK_PASTE, NULL, NULL, N_("Paste the clipboard"), G_CALLBACK (mousepad_window_action_paste), },
-    { "paste-column", GTK_STOCK_PASTE, N_("Paste _Column"), "<control><shift>V", N_("Paste the clipboard text in a clumn"), G_CALLBACK (mousepad_window_action_paste_column), },
-    { "delete", GTK_STOCK_DELETE, NULL, NULL, N_("Delete the selected text"), G_CALLBACK (mousepad_window_action_delete), },
-    { "select-all", GTK_STOCK_SELECT_ALL, NULL, NULL, N_("Select the entire document"), G_CALLBACK (mousepad_window_action_select_all), },
-    { "transpose", NULL, N_("_Transpose"), "<control>T", N_("Reverse the order of something"), G_CALLBACK (mousepad_window_action_transpose), },
-
-  { "search-menu", NULL, N_("_Search"), NULL, NULL, NULL, },
+    { "paste-menu", NULL, N_("Paste _Special"), NULL, NULL, NULL, },
+      { "paste-history", NULL, N_("Paste from _History"), NULL, N_("Paste from the clipboard history"), G_CALLBACK (mousepad_window_action_paste_history), },
+      { "paste-column", NULL, N_("Paste as _Column"), NULL, N_("Paste the clipboard text into a column"), G_CALLBACK (mousepad_window_action_paste_column), },
+    { "delete", GTK_STOCK_DELETE, NULL, NULL, N_("Delete the current selection"), G_CALLBACK (mousepad_window_action_delete), },
+    { "select-all", GTK_STOCK_SELECT_ALL, NULL, NULL, N_("Select the text in the entire document"), G_CALLBACK (mousepad_window_action_select_all), },
+    { "change-selection", NULL, N_("Change the selection"), NULL, N_("Change a normal selection into a column selection and vice versa"), G_CALLBACK (mousepad_window_action_change_selection), },
     { "find", GTK_STOCK_FIND, NULL, NULL, N_("Search for text"), G_CALLBACK (mousepad_window_action_find), },
     { "find-next", NULL, N_("Find _Next"), NULL, N_("Search forwards for the same text"), G_CALLBACK (mousepad_window_action_find_next), },
     { "find-previous", NULL, N_("Find _Previous"), NULL, N_("Search backwards for the same text"), G_CALLBACK (mousepad_window_action_find_previous), },
-    { "replace", GTK_STOCK_FIND_AND_REPLACE, NULL, NULL, N_("Search for and replace text"), G_CALLBACK (mousepad_window_action_replace), },
+    { "replace", GTK_STOCK_FIND_AND_REPLACE, N_("Find and Rep_lace..."), NULL, N_("Search for and replace text"), G_CALLBACK (mousepad_window_action_replace), },
 
   { "view-menu", NULL, N_("_View"), NULL, NULL, NULL, },
-    { "font", GTK_STOCK_SELECT_FONT, NULL, NULL, N_("Change the editor font"), G_CALLBACK (mousepad_window_action_select_font), },
+    { "font", GTK_STOCK_SELECT_FONT, N_("Select F_ont..."), NULL, N_("Change the editor font"), G_CALLBACK (mousepad_window_action_select_font), },
+
+  { "text-menu", NULL, N_("_Text"), NULL, NULL, NULL, },
+    { "convert-menu", NULL, N_("_Convert"), NULL, NULL, NULL, },
+      { "uppercase", NULL, N_("to _Uppercase"), NULL, N_("Change the case of the selection to uppercase"), G_CALLBACK (mousepad_window_action_uppercase), },
+      { "lowercase", NULL, N_("to _Lowercase"), NULL, N_("Change the case of the selection to lowercase"), G_CALLBACK (mousepad_window_action_lowercase), },
+      { "titlecase", NULL, N_("to _Title Case"), NULL, N_("Change the case of the selection to title case"), G_CALLBACK (mousepad_window_action_titlecase), },
+      { "opposite-case", NULL, N_("to _Opposite Case"), NULL, N_("Change the case of the selection opposite case"), G_CALLBACK (mousepad_window_action_opposite_case), },
+      { "tabs-to-spaces", NULL, N_("_Tabs to Spaces"), NULL, N_("Convert all tabs to spaces in the selection or document"), G_CALLBACK (mousepad_window_action_tabs_to_spaces), },
+      { "spaces-to-tabs", NULL, N_("_Spaces to Tabs"), NULL, N_("Convert all the leading spaces to tabs in the selected line(s) or document"), G_CALLBACK (mousepad_window_action_spaces_to_tabs), },
+      { "strip-trailing", NULL, N_("St_rip Trailing Spaces"), NULL, N_("Remove all the trailing spaces from the selected line(s) or document"), G_CALLBACK (mousepad_window_action_strip_trailing_spaces), },
+      { "transpose", NULL, N_("_Transpose"), "<control>T", N_("Reverse the order of something"), G_CALLBACK (mousepad_window_action_transpose), },
+    { "move-menu", NULL, N_("_Move Selection"), NULL, NULL, NULL, },
+      { "line-up", NULL, N_("Line _Up"), NULL, N_("Move the selection one line up"), G_CALLBACK (mousepad_window_action_move_line_up), },
+      { "line-down", NULL, N_("Line _Down"), NULL, N_("Move the selection one line down"), G_CALLBACK (mousepad_window_action_move_line_down), },
+    { "duplicate", NULL, N_("D_uplicate Line / Selection"), NULL, N_("Duplicate the current line or selection"), G_CALLBACK (mousepad_window_action_duplicate), },
+    { "increase-indent", GTK_STOCK_INDENT, N_("_Increase Indent"), NULL, N_("Increase indent of selection or line"), G_CALLBACK (mousepad_window_action_increase_indent), },
+    { "decrease-indent", GTK_STOCK_UNINDENT, N_("_Decrease Indent"), NULL, N_("Decrease indent of selection or line"), G_CALLBACK (mousepad_window_action_decrease_indent), },
 
   { "document-menu", NULL, N_("_Document"), NULL, NULL, NULL, },
-    { "tab-size-menu", NULL, N_("_Tab Size"), NULL, NULL, NULL, },
+    { "tab-size-menu", NULL, N_("Tab _Size"), NULL, NULL, NULL, },
+    { "eol-menu", NULL, N_("Line E_nding"), NULL, NULL, NULL, },
 
   { "navigation-menu", NULL, N_("_Navigation"), NULL, },
-    { "back", GTK_STOCK_GO_BACK, NULL, NULL, N_("Select the previous tab"), G_CALLBACK (mousepad_window_action_prev_tab), },
-    { "forward", GTK_STOCK_GO_FORWARD, NULL, NULL, N_("Select the next tab"), G_CALLBACK (mousepad_window_action_next_tab), },
-    { "go-to-line", GTK_STOCK_JUMP_TO, N_("_Go to line..."), NULL, N_("Go to a specific line"), G_CALLBACK (mousepad_window_action_go_to_line), },
+    { "back", GTK_STOCK_GO_BACK, N_("_Previous Tab"), "<control>Page_Up", N_("Select the previous tab"), G_CALLBACK (mousepad_window_action_prev_tab), },
+    { "forward", GTK_STOCK_GO_FORWARD, N_("_Next Tab"), "<control>Page_Down", N_("Select the next tab"), G_CALLBACK (mousepad_window_action_next_tab), },
+    { "go-to", GTK_STOCK_JUMP_TO, N_("_Go to..."), "<control>G", N_("Go to a specific location in the document"), G_CALLBACK (mousepad_window_action_go_to_position), },
 
   { "help-menu", NULL, N_("_Help"), NULL, },
     { "contents", GTK_STOCK_HELP, N_ ("_Contents"), "F1", N_("Display the Mousepad user manual"), G_CALLBACK (mousepad_window_action_contents), },
@@ -375,18 +454,28 @@ static const GtkActionEntry action_entries[] =
 
 static const GtkToggleActionEntry toggle_action_entries[] =
 {
-  { "statusbar", NULL, N_("_Statusbar"), NULL, N_("Change the visibility of the statusbar"), G_CALLBACK (mousepad_window_action_statusbar), FALSE, },
-  { "line-numbers", NULL, N_("_Line Numbers"), NULL, N_("Show line numbers"), G_CALLBACK (mousepad_window_action_line_numbers), FALSE, },
+  { "statusbar", NULL, N_("St_atusbar"), NULL, N_("Change the visibility of the statusbar"), G_CALLBACK (mousepad_window_action_statusbar), FALSE, },
+  { "line-numbers", NULL, N_("Line N_umbers"), NULL, N_("Show line numbers"), G_CALLBACK (mousepad_window_action_line_numbers), FALSE, },
   { "auto-indent", NULL, N_("_Auto Indent"), NULL, N_("Auto indent a new line"), G_CALLBACK (mousepad_window_action_auto_indent), FALSE, },
   { "word-wrap", NULL, N_("_Word Wrap"), NULL, N_("Toggle breaking lines in between words"), G_CALLBACK (mousepad_window_action_word_wrap), FALSE, },
-  { "insert-spaces", NULL, N_("_Insert Spaces"), NULL, N_("Insert spaces when the tab button is pressed"), G_CALLBACK (mousepad_window_action_insert_spaces), FALSE, },
+  { "insert-spaces", NULL, N_("Insert _Spaces"), NULL, N_("Insert spaces when the tab button is pressed"), G_CALLBACK (mousepad_window_action_insert_spaces), FALSE, },
+};
+
+static const GtkRadioActionEntry radio_action_entries[] =
+{
+  { "unix", NULL, N_("Unix (_LF)"), NULL, N_("Set the line ending of the document to Unix (LF)"), MOUSEPAD_LINE_END_UNIX, },
+  { "mac", NULL, N_("Mac (_CR)"), NULL, N_("Set the line ending of the document to Mac (CR)"), MOUSEPAD_LINE_END_MAC, },
+  { "dos", NULL, N_("DOS / Windows (C_R LF)"), NULL, N_("Set the line ending of the document to DOS / Windows (CR LF)"), MOUSEPAD_LINE_END_DOS, },
 };
 
 
 
+/* global variables */
 static GObjectClass *mousepad_window_parent_class;
 static guint         window_signals[LAST_SIGNAL];
 static gint          lock_menu_updates = 0;
+static GSList       *clipboard_history = NULL;
+static guint         clipboard_history_ref_count = 0;
 
 
 
@@ -472,6 +561,7 @@ mousepad_window_init (MousepadWindow *window)
   GtkWidget     *label;
   GtkWidget     *separator;
   GtkWidget     *ebox;
+  GtkWidget     *item;
   GtkAction     *action;
   gint           width, height;
   gboolean       statusbar_visible;
@@ -488,6 +578,9 @@ mousepad_window_init (MousepadWindow *window)
   window->active = NULL;
   window->recent_manager = NULL;
 
+  /* increase clipboard history ref count */
+  clipboard_history_ref_count++;
+
   /* add the preferences to the window */
   window->preferences = mousepad_preferences_get ();
 
@@ -519,6 +612,7 @@ mousepad_window_init (MousepadWindow *window)
   gtk_action_group_set_translation_domain (window->action_group, GETTEXT_PACKAGE);
   gtk_action_group_add_actions (window->action_group, action_entries, G_N_ELEMENTS (action_entries), GTK_WIDGET (window));
   gtk_action_group_add_toggle_actions (window->action_group, toggle_action_entries, G_N_ELEMENTS (toggle_action_entries), GTK_WIDGET (window));
+  gtk_action_group_add_radio_actions (window->action_group, radio_action_entries, G_N_ELEMENTS (radio_action_entries), -1, G_CALLBACK (mousepad_window_action_line_ending), GTK_WIDGET (window));
 
   /* create the ui manager and connect proxy signals for the statusbar */
   window->ui_manager = gtk_ui_manager_new ();
@@ -527,8 +621,10 @@ mousepad_window_init (MousepadWindow *window)
   gtk_ui_manager_insert_action_group (window->ui_manager, window->action_group, 0);
   gtk_ui_manager_add_ui_from_string (window->ui_manager, mousepad_window_ui, mousepad_window_ui_length, NULL);
 
-  /* create the recent menu (idle) */
-  mousepad_window_recent_menu (window);
+  /* build the templates menu when the item is shown for the first time */
+  /* from here we also trigger the idle build of the recent menu */
+  item = gtk_ui_manager_get_widget (window->ui_manager, "/main-menu/file-menu/template-menu");
+  g_signal_connect (G_OBJECT (item), "map", G_CALLBACK (mousepad_window_menu_templates), window);
 
   /* add tab size menu */
   mousepad_window_menu_tab_sizes (window);
@@ -551,10 +647,10 @@ mousepad_window_init (MousepadWindow *window)
     {
       /* install default settings for the root warning text box */
       gtk_rc_parse_string ("style\"mousepad-window-root-style\"\n"
-                           "  {\n"
-                           "    bg[NORMAL]=\"#b4254b\"\n"
-                           "    fg[NORMAL]=\"#fefefe\"\n"
-                           "  }\n"
+                             "{\n"
+                               "bg[NORMAL]=\"#b4254b\"\n"
+                               "fg[NORMAL]=\"#fefefe\"\n"
+                             "}\n"
                            "widget\"MousepadWindow.*.root-warning\"style\"mousepad-window-root-style\"\n"
                            "widget\"MousepadWindow.*.root-warning.GtkLabel\"style\"mousepad-window-root-style\"\n");
 
@@ -598,6 +694,7 @@ mousepad_window_init (MousepadWindow *window)
   g_signal_connect (G_OBJECT (window->notebook), "page-added", G_CALLBACK (mousepad_window_notebook_added), window);
   g_signal_connect (G_OBJECT (window->notebook), "page-removed", G_CALLBACK (mousepad_window_notebook_removed), window);
   g_signal_connect (G_OBJECT (window->notebook), "button-press-event", G_CALLBACK (mousepad_window_notebook_button_press_event), window);
+  g_signal_connect (G_OBJECT (window->notebook), "button-release-event", G_CALLBACK (mousepad_window_notebook_button_release_event), window);
 #if GTK_CHECK_VERSION (2,12,0)
   g_signal_connect (G_OBJECT (window->notebook), "create-window", G_CALLBACK (mousepad_window_notebook_create_window), window);
 #endif
@@ -640,6 +737,9 @@ mousepad_window_finalize (GObject *object)
 {
   MousepadWindow *window = MOUSEPAD_WINDOW (object);
 
+  /* decrease history clipboard ref count */
+  clipboard_history_ref_count--;
+
   /* cancel a scheduled recent menu update */
   if (G_UNLIKELY (window->update_recent_menu_id != 0))
     g_source_remove (window->update_recent_menu_id);
@@ -662,6 +762,13 @@ mousepad_window_finalize (GObject *object)
   /* release the preferences reference */
   g_object_unref (G_OBJECT (window->preferences));
 
+  /* free clipboard history if needed */
+  if (clipboard_history_ref_count == 0 && clipboard_history != NULL)
+    {
+      g_slist_foreach (clipboard_history, (GFunc) g_free, NULL);
+      g_slist_free (clipboard_history);
+    }
+
   (*G_OBJECT_CLASS (mousepad_window_parent_class)->finalize) (object);
 }
 
@@ -704,12 +811,13 @@ mousepad_window_connect_proxy (GtkUIManager   *manager,
                                GtkWidget      *proxy,
                                MousepadWindow *window)
 {
+  _mousepad_return_if_fail (GTK_IS_ACTION (action));
+  _mousepad_return_if_fail (GTK_IS_MENU_ITEM (proxy));
+  _mousepad_return_if_fail (GTK_IS_UI_MANAGER (manager));
+
   /* we want to get informed when the user hovers a menu item */
-  if (GTK_IS_MENU_ITEM (proxy))
-    {
-      g_signal_connect_closure (G_OBJECT (proxy), "select", window->menu_item_selected_closure, FALSE);
-      g_signal_connect_closure (G_OBJECT (proxy), "deselect", window->menu_item_deselected_closure, FALSE);
-    }
+  g_signal_connect_closure (G_OBJECT (proxy), "select", window->menu_item_selected_closure, FALSE);
+  g_signal_connect_closure (G_OBJECT (proxy), "deselect", window->menu_item_deselected_closure, FALSE);
 }
 
 
@@ -720,12 +828,13 @@ mousepad_window_disconnect_proxy (GtkUIManager   *manager,
                                   GtkWidget      *proxy,
                                   MousepadWindow *window)
 {
-  /* undo what we did in connect_proxy() */
-  if (GTK_IS_MENU_ITEM (proxy))
-    {
-      g_signal_handlers_disconnect_matched (G_OBJECT (proxy), G_SIGNAL_MATCH_CLOSURE, 0, 0, window->menu_item_selected_closure, NULL, NULL);
-      g_signal_handlers_disconnect_matched (G_OBJECT (proxy), G_SIGNAL_MATCH_CLOSURE, 0, 0, window->menu_item_deselected_closure, NULL, NULL);
-    }
+  _mousepad_return_if_fail (GTK_IS_ACTION (action));
+  _mousepad_return_if_fail (GTK_IS_MENU_ITEM (proxy));
+  _mousepad_return_if_fail (GTK_IS_UI_MANAGER (manager));
+
+  /* disconnect the signal from mousepad_window_connect_proxy() */
+  g_signal_handlers_disconnect_matched (G_OBJECT (proxy), G_SIGNAL_MATCH_CLOSURE, 0, 0, window->menu_item_selected_closure, NULL, NULL);
+  g_signal_handlers_disconnect_matched (G_OBJECT (proxy), G_SIGNAL_MATCH_CLOSURE, 0, 0, window->menu_item_deselected_closure, NULL, NULL);
 }
 
 
@@ -742,7 +851,7 @@ mousepad_window_menu_item_selected (GtkWidget      *menu_item,
   if (G_LIKELY (window->statusbar != NULL))
     {
       /* get the action from the menu item */
-      action = g_object_get_data (G_OBJECT (menu_item), I_("gtk-action"));
+      action = gtk_widget_get_action (menu_item);
       if (G_LIKELY (action))
         {
           /* read the tooltip from the action, if there is one */
@@ -850,15 +959,18 @@ mousepad_window_open_file (MousepadWindow *window,
   const gchar      *opened_filename;
   GtkWidget        *dialog;
 
-  /* get the number of page in the notebook */
-  if (filename)
-    npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+  _mousepad_return_val_if_fail (filename != NULL && *filename != '\0', FALSE);
 
-  /* walk though the tabs */
+  /* check if the file is already openend */
+  npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
   for (i = 0; i < npages; i++)
     {
       document = MOUSEPAD_DOCUMENT (gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i));
 
+      /* debug check */
+      _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+
       if (G_LIKELY (document))
         {
           /* get the filename */
@@ -879,84 +991,73 @@ mousepad_window_open_file (MousepadWindow *window,
   /* new document */
   document = mousepad_document_new ();
 
-  if (filename)
-    {
-      /* set the filename */
-      mousepad_file_set_filename (document->file, filename);
-
-      /* set the passed encoding */
-      mousepad_file_set_encoding (document->file, encoding);
-
-      try_open_again:
+  /* set the filename */
+  mousepad_file_set_filename (document->file, filename);
 
-      /* lock the undo manager */
-      mousepad_undo_lock (document->undo);
+  /* set the passed encoding */
+  mousepad_file_set_encoding (document->file, encoding);
 
-      /* read the content into the buffer */
-      succeed = mousepad_file_open (document->file, &error);
+  try_open_again:
 
-      /* release the lock */
-      mousepad_undo_unlock (document->undo);
+  /* lock the undo manager */
+  mousepad_undo_lock (document->undo);
 
-      if (G_LIKELY (succeed))
-        {
-          /* add the document to the notebook and connect some signals */
-          mousepad_window_add (window, document);
-
-          /* add to the recent history */
-          mousepad_window_recent_add (window, document->file);
-        }
-      else if (error->domain == G_CONVERT_ERROR)
-        {
-          /* clear the error */
-          g_clear_error (&error);
+  /* read the content into the buffer */
+  succeed = mousepad_file_open (document->file, &error);
 
-          /* run the encoding dialog */
-          dialog = mousepad_encoding_dialog_new (GTK_WINDOW (window), document->file);
+  /* release the lock */
+  mousepad_undo_unlock (document->undo);
 
-          /* run the dialog */
-          response = gtk_dialog_run (GTK_DIALOG (dialog));
+  if (G_LIKELY (succeed))
+    {
+      /* add the document to the notebook and connect some signals */
+      mousepad_window_add (window, document);
 
-          if (response == GTK_RESPONSE_OK)
-            {
-              /* get the selected encoding */
-              new_encoding = mousepad_encoding_dialog_get_encoding (MOUSEPAD_ENCODING_DIALOG (dialog));
+      /* add to the recent history */
+      mousepad_window_recent_add (window, document->file);
+    }
+  else if (error->domain == G_CONVERT_ERROR)
+    {
+      /* clear the error */
+      g_clear_error (&error);
 
-              /* set the document encoding */
-              mousepad_file_set_encoding (document->file, new_encoding);
-            }
+      /* run the encoding dialog */
+      dialog = mousepad_encoding_dialog_new (GTK_WINDOW (window), document->file);
 
-          /* destroy the dialog */
-          gtk_widget_destroy (dialog);
+      /* run the dialog */
+      response = gtk_dialog_run (GTK_DIALOG (dialog));
 
-          /* handle */
-          if (response == GTK_RESPONSE_OK)
-            goto try_open_again;
-          else
-            goto opening_failed;
-        }
-      else
+      if (response == GTK_RESPONSE_OK)
         {
-          opening_failed:
+          /* get the selected encoding */
+          new_encoding = mousepad_encoding_dialog_get_encoding (MOUSEPAD_ENCODING_DIALOG (dialog));
 
-          /* something went wrong, remove the document */
-          gtk_widget_destroy (GTK_WIDGET (document));
+          /* set the document encoding */
+          mousepad_file_set_encoding (document->file, new_encoding);
+        }
 
-          if (error)
-            {
-              /* show the warning */
-              mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to open file"));
+      /* destroy the dialog */
+      gtk_widget_destroy (dialog);
 
-              g_error_free (error);
-            }
-        }
+      /* handle */
+      if (response == GTK_RESPONSE_OK)
+        goto try_open_again;
+      else
+        goto opening_failed;
     }
   else
     {
-      /* no filename, simple add the window and succeed */
-      mousepad_window_add (window, document);
+      opening_failed:
 
-      succeed = TRUE;
+      /* something went wrong, release the document */
+      g_object_unref (G_OBJECT (document));
+
+      if (G_LIKELY (error))
+        {
+          /* show the warning */
+          mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to open file"));
+          g_error_free (error);
+        }
     }
 
   return succeed;
@@ -969,10 +1070,11 @@ mousepad_window_open_files (MousepadWindow  *window,
                             const gchar     *working_directory,
                             gchar          **filenames)
 {
-  gint   n, npages;
-  gchar *filename = NULL;
+  guint  n;
+  gchar *filename;
 
   _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+  _mousepad_return_val_if_fail (working_directory != NULL, FALSE);
   _mousepad_return_val_if_fail (filenames != NULL, FALSE);
   _mousepad_return_val_if_fail (*filenames != NULL, FALSE);
 
@@ -993,21 +1095,24 @@ mousepad_window_open_files (MousepadWindow  *window,
           /* create an absolute file */
           filename = g_build_filename (working_directory, filenames[n], NULL);
         }
+      else
+        {
+          /* looks like a valid filename */
+          filename = NULL;
+        }
 
       /* open a new tab with the file */
       mousepad_window_open_file (window, filename ? filename : filenames[n], NULL);
 
       /* cleanup */
       g_free (filename);
-      filename = NULL;
     }
 
   /* allow menu updates again */
   lock_menu_updates--;
 
   /* check if the window contains tabs */
-  npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
-  if (G_UNLIKELY (npages == 0))
+  if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) == 0)
     return FALSE;
 
   /* update the menus */
@@ -1094,7 +1199,7 @@ mousepad_window_close_document (MousepadWindow   *window,
             break;
 
           case MOUSEPAD_RESPONSE_SAVE:
-            succeed = mousepad_window_action_save_file (NULL, window);
+            succeed = mousepad_window_action_save (NULL, window);
             break;
         }
     }
@@ -1148,18 +1253,6 @@ mousepad_window_set_title (MousepadWindow *window)
 
 
 
-static void
-mousepad_window_toggle_overwrite (MousepadWindow *window,
-                                  gboolean        overwrite)
-{
-  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
-
-  if (G_LIKELY (window->active))
-    mousepad_document_set_overwrite (window->active, overwrite);
-}
-
-
-
 /**
  * Notebook Signal Functions
  **/
@@ -1188,7 +1281,7 @@ mousepad_window_notebook_notified (GtkNotebook    *notebook,
   mousepad_window_update_actions (window);
 
   /* update the statusbar */
-  mousepad_document_send_statusbar_signals (window->active);
+  mousepad_document_send_signals (window->active);
 }
 
 
@@ -1224,6 +1317,7 @@ mousepad_window_notebook_added (GtkNotebook     *notebook,
   /* connect signals to the document for this window */
   g_signal_connect (G_OBJECT (page), "close-tab", G_CALLBACK (mousepad_window_button_close_tab), window);
   g_signal_connect (G_OBJECT (page), "cursor-changed", G_CALLBACK (mousepad_window_cursor_changed), window);
+  g_signal_connect (G_OBJECT (page), "selection-changed", G_CALLBACK (mousepad_window_selection_changed), window);
   g_signal_connect (G_OBJECT (page), "overwrite-changed", G_CALLBACK (mousepad_window_overwrite_changed), window);
   g_signal_connect (G_OBJECT (page), "drag-data-received", G_CALLBACK (mousepad_window_drag_data_received), window);
   g_signal_connect_swapped (G_OBJECT (document->undo), "can-undo", G_CALLBACK (mousepad_window_can_undo), window);
@@ -1240,14 +1334,8 @@ mousepad_window_notebook_added (GtkNotebook     *notebook,
   /* change the visibility of the tabs accordingly */
   gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), always_show_tabs || (npages > 1));
 
-  /* don't focus the notebook */
-  GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
-
   /* update the go menu */
   mousepad_window_update_gomenu (window);
-
-  /* update the window actions */
-  mousepad_window_update_actions (window);
 }
 
 
@@ -1269,6 +1357,7 @@ mousepad_window_notebook_removed (GtkNotebook     *notebook,
   /* disconnect the old document signals */
   g_signal_handlers_disconnect_by_func (G_OBJECT (page), mousepad_window_button_close_tab, window);
   g_signal_handlers_disconnect_by_func (G_OBJECT (page), mousepad_window_cursor_changed, window);
+  g_signal_handlers_disconnect_by_func (G_OBJECT (page), mousepad_window_selection_changed, window);
   g_signal_handlers_disconnect_by_func (G_OBJECT (page), mousepad_window_overwrite_changed, window);
   g_signal_handlers_disconnect_by_func (G_OBJECT (page), mousepad_window_drag_data_received, window);
   g_signal_handlers_disconnect_by_func (G_OBJECT (document->undo), mousepad_window_can_undo, window);
@@ -1277,7 +1366,7 @@ mousepad_window_notebook_removed (GtkNotebook     *notebook,
   g_signal_handlers_disconnect_by_func (G_OBJECT (document->textview), mousepad_window_menu_textview_popup, window);
 
   /* unset the go menu item (part of the old window) */
-  g_object_set_data (G_OBJECT (page), I_("navigation-menu-action"), NULL);
+  mousepad_object_set_data (G_OBJECT (page), "navigation-menu-action", NULL);
 
   /* get the number of pages in this notebook */
   npages = gtk_notebook_get_n_pages (notebook);
@@ -1296,14 +1385,8 @@ mousepad_window_notebook_removed (GtkNotebook     *notebook,
       /* change the visibility of the tabs accordingly */
       gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), always_show_tabs || (npages > 1));
 
-      /* don't focus the notebook */
-      GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
-
       /* update the go menu */
       mousepad_window_update_gomenu (window);
-
-      /* update the actions */
-      mousepad_window_update_actions (window);
     }
 }
 
@@ -1340,7 +1423,7 @@ mousepad_window_notebook_button_press_event (GtkNotebook    *notebook,
 
   _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
 
-  if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+  if (event->type == GDK_BUTTON_PRESS && (event->button == 3 || event->button == 2))
     {
       /* walk through the tabs and look for the tab under the cursor */
       while ((page = gtk_notebook_get_nth_page (notebook, page_num)) != NULL)
@@ -1357,13 +1440,22 @@ mousepad_window_notebook_button_press_event (GtkNotebook    *notebook,
               /* switch to this tab */
               gtk_notebook_set_current_page (notebook, page_num);
 
-              /* get the menu */
-              menu = gtk_ui_manager_get_widget (window->ui_manager, "/tab-menu");
-
-              /* show it */
-              gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
-                              (GtkMenuPositionFunc) mousepad_window_notebook_menu_position, label,
-                              event->button, event->time);
+              /* handle the button action */
+              if (event->button == 3)
+                {
+                  /* get the menu */
+                  menu = gtk_ui_manager_get_widget (window->ui_manager, "/tab-menu");
+
+                  /* show it */
+                  gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+                                  mousepad_window_notebook_menu_position, label,
+                                  event->button, event->time);
+                }
+              else if (event->button == 2)
+                {
+                  /* close the document */
+                  mousepad_window_action_close (NULL, window);
+                }
 
               /* we succeed */
               return TRUE;
@@ -1375,11 +1467,15 @@ mousepad_window_notebook_button_press_event (GtkNotebook    *notebook,
     }
   else if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
     {
-      /* open a new tab */
-      mousepad_window_open_file (window, NULL, NULL);
+      /* check if the event window is the notebook event window (not a tab) */
+      if (event->window == notebook->event_window)
+        {
+          /* create new document */
+          mousepad_window_action_new (NULL, window);
 
-      /* we succeed */
-      return TRUE;
+          /* we succeed */
+          return TRUE;
+        }
     }
 
   return FALSE;
@@ -1387,6 +1483,22 @@ mousepad_window_notebook_button_press_event (GtkNotebook    *notebook,
 
 
 
+static gboolean
+mousepad_window_notebook_button_release_event (GtkNotebook    *notebook,
+                                               GdkEventButton *event,
+                                               MousepadWindow *window)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (window->active), FALSE);
+
+  /* focus the active textview */
+  mousepad_document_focus_textview (window->active);
+
+  return FALSE;
+}
+
+
+
 #if GTK_CHECK_VERSION (2,12,0)
 static GtkNotebook *
 mousepad_window_notebook_create_window (GtkNotebook    *notebook,
@@ -1445,28 +1557,55 @@ mousepad_window_cursor_changed (MousepadDocument *document,
                                 gint              selection,
                                 MousepadWindow   *window)
 {
-  GtkAction *action;
-  gboolean   has_selection;
+
 
   _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
 
-  /* set the new statusbar cursor position and selection length */
   if (window->statusbar)
-    mousepad_statusbar_set_cursor_position (MOUSEPAD_STATUSBAR (window->statusbar), line, column, selection);
+    {
+      /* set the new statusbar cursor position and selection length */
+      mousepad_statusbar_set_cursor_position (MOUSEPAD_STATUSBAR (window->statusbar), line, column, selection);
+    }
+}
+
+
+
+static void
+mousepad_window_selection_changed (MousepadDocument *document,
+                                   gint              selection,
+                                   MousepadWindow   *window)
+{
+  GtkAction *action;
+  gint       i;
 
-  /* whether we have a selection */
-  has_selection = (selection > 0);
+  /* sensitivity of the change selection action */
+  action = gtk_action_group_get_action (window->action_group, "change-selection");
+  gtk_action_set_sensitive (action, selection != 0);
 
-  /* update actions */
-  action = gtk_action_group_get_action (window->action_group, "cut");
-  gtk_action_set_sensitive (action, has_selection);
+  /* actions that are unsensitive during a column selection */
+  const gchar *action_names1[] = { "tabs-to-spaces", "spaces-to-tabs", "duplicate", "strip-trailing" };
+  for (i = 0; i < G_N_ELEMENTS (action_names1); i++)
+    {
+      action = gtk_action_group_get_action (window->action_group, action_names1[i]);
+      gtk_action_set_sensitive (action, selection == 0 || selection == 1);
+    }
 
-  action = gtk_action_group_get_action (window->action_group, "copy");
-  gtk_action_set_sensitive (action, has_selection);
+  /* action that are only sensitive for normal selections */
+  const gchar *action_names2[] = { "line-up", "line-down" };
+  for (i = 0; i < G_N_ELEMENTS (action_names2); i++)
+    {
+      action = gtk_action_group_get_action (window->action_group, action_names2[i]);
+      gtk_action_set_sensitive (action, selection == 1);
+    }
 
-  action = gtk_action_group_get_action (window->action_group, "delete");
-  gtk_action_set_sensitive (action, has_selection);
+  /* actions that are sensitive for all selections with content */
+  const gchar *action_names3[] = { "cut", "copy", "delete", "lowercase", "uppercase", "titlecase", "opposite-case" };
+  for (i = 0; i < G_N_ELEMENTS (action_names3); i++)
+    {
+      action = gtk_action_group_get_action (window->action_group, action_names3[i]);
+      gtk_action_set_sensitive (action, selection > 0);
+    }
 }
 
 
@@ -1514,6 +1653,174 @@ mousepad_window_can_redo (MousepadWindow *window,
  * Menu Functions
  **/
 static void
+mousepad_window_menu_templates_fill (MousepadWindow *window,
+                                     GtkWidget      *menu,
+                                     const gchar    *path)
+{
+  GDir        *dir;
+  GSList      *files_list = NULL;
+  GSList      *dirs_list = NULL;
+  GSList      *li;
+  gchar       *absolute_path;
+  gchar       *label, *dot;
+  const gchar *name;
+  GtkWidget   *item, *image, *submenu;
+
+  /* open the directory */
+  dir = g_dir_open (path, 0, NULL);
+
+  /* read the directory */
+  if (G_LIKELY (dir))
+    {
+      /* walk the directory */
+      for (;;)
+        {
+          /* read the filename of the next file */
+          name = g_dir_read_name (dir);
+
+          /* break when we reached the last file */
+          if (G_UNLIKELY (name == NULL))
+            break;
+
+          /* skip hidden files */
+          if (name[0] == '.')
+            continue;
+
+          /* build absolute path */
+          absolute_path = g_build_path (G_DIR_SEPARATOR_S, path, name, NULL);
+
+          /* check if the file is a regular file or directory */
+          if (g_file_test (absolute_path, G_FILE_TEST_IS_DIR))
+            dirs_list = g_slist_insert_sorted (dirs_list, absolute_path, (GCompareFunc) strcmp);
+          else if (g_file_test (absolute_path, G_FILE_TEST_IS_REGULAR))
+            files_list = g_slist_insert_sorted (files_list, absolute_path, (GCompareFunc) strcmp);
+        }
+
+      /* close the directory */
+      g_dir_close (dir);
+    }
+
+  /* append the directories */
+  for (li = dirs_list; li != NULL; li = li->next)
+    {
+      /* create a newsub menu for the directory */
+      submenu = gtk_menu_new ();
+      g_object_ref_sink (G_OBJECT (submenu));
+      gtk_menu_set_screen (GTK_MENU (submenu), gtk_widget_get_screen (menu));
+
+      /* fill the menu */
+      mousepad_window_menu_templates_fill (window, submenu, li->data);
+
+      /* check if the sub menu contains items */
+      if (G_LIKELY (GTK_MENU_SHELL (submenu)->children != NULL))
+        {
+          /* create directory label */
+          label = g_filename_display_basename (li->data);
+
+          /* append the menu */
+          item = gtk_image_menu_item_new_with_label (label);
+          gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+          gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+          gtk_widget_show (item);
+
+          /* cleanup */
+          g_free (label);
+
+          /* set menu image */
+          image = gtk_image_new_from_icon_name (GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
+          gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+          gtk_widget_show (image);
+        }
+
+      /* cleanup */
+      g_free (li->data);
+      g_object_unref (G_OBJECT (submenu));
+    }
+
+  /* append the files */
+  for (li = files_list; li != NULL; li = li->next)
+    {
+      /* create directory label */
+      label = g_filename_display_basename (li->data);
+
+      /* strip the extension from the label */
+      dot = g_utf8_strrchr (label, -1, '.');
+      if (dot != NULL)
+        *dot = '\0';
+
+      /* create menu item */
+      item = gtk_image_menu_item_new_with_label (label);
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      mousepad_object_set_data_full (G_OBJECT (item), "filename", li->data, g_free);
+      g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (mousepad_window_action_new_from_template), window);
+      gtk_widget_show (item);
+
+      /* set menu image */
+      image = gtk_image_new_from_icon_name (GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
+      gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+      gtk_widget_show (image);
+
+      /* cleanup */
+      g_free (label);
+    }
+
+  /* cleanup */
+  g_slist_free (dirs_list);
+  g_slist_free (files_list);
+}
+
+
+
+static void
+mousepad_window_menu_templates (GtkWidget      *item,
+                                MousepadWindow *window)
+{
+  GtkWidget *submenu;
+  gchar     *templates_path;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (GTK_IS_MENU_ITEM (item));
+  _mousepad_return_if_fail (gtk_menu_item_get_submenu (GTK_MENU_ITEM (item)) == NULL);
+
+  /* schedule the idle build of the recent menu */
+  mousepad_window_recent_menu (window);
+
+  /* get the templates path */
+  templates_path = xfce_get_homefile ("Templates", NULL);
+
+  /* check if the directory exists */
+  if (g_file_test (templates_path, G_FILE_TEST_IS_DIR))
+    {
+      /* create submenu */
+      submenu = gtk_menu_new ();
+      g_object_ref_sink (G_OBJECT (submenu));
+      gtk_menu_set_screen (GTK_MENU (submenu), gtk_widget_get_screen (item));
+
+      /* fill the menu */
+      mousepad_window_menu_templates_fill (window, submenu, templates_path);
+
+      /* set the submenu if it contains items, else hide the item */
+      if (G_LIKELY (GTK_MENU_SHELL (submenu)->children != NULL))
+        gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+      else
+        gtk_widget_hide (item);
+
+      /* release */
+      g_object_unref (G_OBJECT (submenu));
+    }
+  else
+    {
+      /* hide the templates menu item */
+      gtk_widget_hide (item);
+    }
+
+  /* cleanup */
+  g_free (templates_path);
+}
+
+
+
+static void
 mousepad_window_menu_tab_sizes (MousepadWindow *window)
 {
   GtkRadioAction   *action;
@@ -1526,9 +1833,7 @@ mousepad_window_menu_tab_sizes (MousepadWindow *window)
   lock_menu_updates++;
 
   /* get the default tab sizes and active tab size */
-  g_object_get (G_OBJECT (window->preferences),
-                "misc-default-tab-sizes", &tmp,
-                NULL);
+  g_object_get (G_OBJECT (window->preferences), "misc-default-tab-sizes", &tmp, NULL);
 
   /* get sizes array and free the temp string */
   tab_sizes = g_strsplit (tmp, ",", -1);
@@ -1550,9 +1855,9 @@ mousepad_window_menu_tab_sizes (MousepadWindow *window)
           size = CLAMP (size, 1, 32);
 
           /* create action name */
-          name = g_strdup_printf ("tab-size-%d", size);
+          name = g_strdup_printf ("tab-size_%d", size);
 
-          action = gtk_radio_action_new (name, name + 9, NULL, NULL, size);
+          action = gtk_radio_action_new (name, name + 8, NULL, NULL, size);
           gtk_radio_action_set_group (action, group);
           group = gtk_radio_action_get_group (action);
           g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (mousepad_window_action_tab_size), window);
@@ -1563,7 +1868,7 @@ mousepad_window_menu_tab_sizes (MousepadWindow *window)
 
           /* add the action to the go menu */
           gtk_ui_manager_add_ui (window->ui_manager, merge_id,
-                                 "/main-menu/document-menu/tab-size-menu/placeholder-tab-sizes",
+                                 "/main-menu/document-menu/tab-size-menu/placeholder-tab-items",
                                  name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
 
           /* cleanup */
@@ -1585,7 +1890,7 @@ mousepad_window_menu_tab_sizes (MousepadWindow *window)
 
   /* add the action to the go menu */
   gtk_ui_manager_add_ui (window->ui_manager, merge_id,
-                         "/main-menu/document-menu/tab-size-menu/placeholder-tab-sizes",
+                         "/main-menu/document-menu/tab-size-menu/placeholder-tab-items",
                          "tab-size-other", "tab-size-other", GTK_UI_MANAGER_MENUITEM, FALSE);
 
   /* unlock */
@@ -1595,12 +1900,13 @@ mousepad_window_menu_tab_sizes (MousepadWindow *window)
 
 
 static void
-mousepad_window_menu_tab_sizes_update (MousepadWindow  *window)
+mousepad_window_menu_tab_sizes_update (MousepadWindow *window)
 {
   gint       tab_size;
   gchar     *name, *label = NULL;
   GtkAction *action;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* avoid menu actions */
@@ -1610,7 +1916,7 @@ mousepad_window_menu_tab_sizes_update (MousepadWindow  *window)
   tab_size = mousepad_view_get_tab_size (window->active->textview);
 
   /* check if there is a default item with this number */
-  name = g_strdup_printf ("tab-size-%d", tab_size);
+  name = g_strdup_printf ("tab-size_%d", tab_size);
   action = gtk_action_group_get_action (window->action_group, name);
   g_free (name);
 
@@ -1621,8 +1927,8 @@ mousepad_window_menu_tab_sizes_update (MousepadWindow  *window)
     }
   else
     {
-      /* create suitable label */
-      label = g_strdup_printf (_("Other (%d)..."), tab_size);
+      /* create suitable label for the other menu */
+      label = g_strdup_printf (_("Ot_her (%d)..."), tab_size);
     }
 
   /* get other action */
@@ -1633,7 +1939,7 @@ mousepad_window_menu_tab_sizes_update (MousepadWindow  *window)
     gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
 
   /* set action label */
-  g_object_set (G_OBJECT (action), "label", label ? label : _("Other..."), NULL);
+  g_object_set (G_OBJECT (action), "label", label ? label : _("Ot_her..."), NULL);
 
   /* cleanup */
   g_free (label);
@@ -1694,13 +2000,15 @@ mousepad_window_menu_textview_popup (GtkTextView    *textview,
 static void
 mousepad_window_update_actions (MousepadWindow *window)
 {
-  GtkAction        *action;
-  GtkNotebook      *notebook = GTK_NOTEBOOK (window->notebook);
-  MousepadDocument *document;
-  gboolean          cycle_tabs;
-  gint              n_pages;
-  gint              page_num;
-  gboolean          active;
+  GtkAction          *action;
+  GtkNotebook        *notebook = GTK_NOTEBOOK (window->notebook);
+  MousepadDocument   *document;
+  gboolean            cycle_tabs;
+  gint                n_pages;
+  gint                page_num;
+  gboolean            active;
+  MousepadLineEnding  line_ending;
+  const gchar        *action_name;
 
   _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
 
@@ -1728,15 +2036,28 @@ mousepad_window_update_actions (MousepadWindow *window)
       gtk_action_set_sensitive (action, (cycle_tabs && n_pages > 1 ) || (page_num < n_pages - 1));
 
       /* set the reload, detach and save sensitivity */
-      action = gtk_action_group_get_action (window->action_group, "save-file");
+      action = gtk_action_group_get_action (window->action_group, "save");
       gtk_action_set_sensitive (action, !mousepad_file_get_read_only (document->file));
 
-      action = gtk_action_group_get_action (window->action_group, "detach-tab");
+      action = gtk_action_group_get_action (window->action_group, "detach");
       gtk_action_set_sensitive (action, (n_pages > 1));
 
-      action = gtk_action_group_get_action (window->action_group, "reload");
+      action = gtk_action_group_get_action (window->action_group, "revert");
       gtk_action_set_sensitive (action, mousepad_file_get_filename (document->file) != NULL);
 
+      /* line ending type */
+      line_ending = mousepad_file_get_line_ending (document->file);
+      if (G_UNLIKELY (line_ending == MOUSEPAD_LINE_END_MAC))
+        action_name = "mac";
+      else if (G_UNLIKELY (line_ending == MOUSEPAD_LINE_END_DOS))
+        action_name = "dos";
+      else
+        action_name = "unix";
+
+      /* set the corrent line ending type */
+      action = gtk_action_group_get_action (window->action_group, action_name);
+      gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+
       /* toggle the document settings */
       active = mousepad_document_get_word_wrap (document);
       action = gtk_action_group_get_action (window->action_group, "word-wrap");
@@ -1750,6 +2071,7 @@ mousepad_window_update_actions (MousepadWindow *window)
       action = gtk_action_group_get_action (window->action_group, "auto-indent");
       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
 
+      /* update the tabs size menu */
       mousepad_window_menu_tab_sizes_update (window);
 
       active = mousepad_view_get_insert_spaces (document->textview);
@@ -1761,7 +2083,7 @@ mousepad_window_update_actions (MousepadWindow *window)
       mousepad_window_can_redo (window, mousepad_undo_can_redo (document->undo));
 
       /* active this tab in the go menu */
-      action = g_object_get_data (G_OBJECT (document), I_("navigation-menu-action"));
+      action = mousepad_object_get_data (G_OBJECT (document), "navigation-menu-action");
       if (G_LIKELY (action != NULL))
         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
 
@@ -1805,7 +2127,7 @@ mousepad_window_update_gomenu_idle (gpointer user_data)
       /* drop all the previous actions from the action group */
       actions = gtk_action_group_list_actions (window->action_group);
       for (li = actions; li != NULL; li = li->next)
-        if (strncmp (gtk_action_get_name (li->data), "mousepad-document-", 18) == 0)
+        if (strncmp (gtk_action_get_name (li->data), "mousepad-tab-", 13) == 0)
           gtk_action_group_remove_action (window->action_group, GTK_ACTION (li->data));
       g_list_free (actions);
     }
@@ -1821,7 +2143,7 @@ mousepad_window_update_gomenu_idle (gpointer user_data)
       document = MOUSEPAD_DOCUMENT (gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), n));
 
       /* create a new action name */
-      name = g_strdup_printf ("mousepad-document-%d", n);
+      name = g_strdup_printf ("mousepad-tab-%d", n);
 
       /* get the name and file name */
       title = mousepad_document_get_basename (document);
@@ -1831,15 +2153,15 @@ mousepad_window_update_gomenu_idle (gpointer user_data)
       action = gtk_radio_action_new (name, title, tooltip, NULL, n);
       gtk_radio_action_set_group (action, group);
       group = gtk_radio_action_get_group (action);
-      g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (mousepad_window_action_goto), window->notebook);
+      g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (mousepad_window_action_go_to_tab), window->notebook);
 
       /* connect the action to the document to we can easily active it when the user switched from tab */
-      g_object_set_data (G_OBJECT (document), I_("navigation-menu-action"), action);
+      mousepad_object_set_data (G_OBJECT (document), "navigation-menu-action", action);
 
       if (G_LIKELY (n < 9))
         {
           /* create an accelerator and add it to the menu */
-          g_snprintf (accelerator, sizeof (accelerator), "<Alt>%d", n+1);
+          g_snprintf (accelerator, sizeof (accelerator), "<Alt>%d", n + 1);
           gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (action), accelerator);
         }
       else
@@ -1855,7 +2177,7 @@ mousepad_window_update_gomenu_idle (gpointer user_data)
 
       /* add the action to the go menu */
       gtk_ui_manager_add_ui (window->ui_manager, window->gomenu_merge_id,
-                             "/main-menu/navigation-menu/placeholder-documents",
+                             "/main-menu/navigation-menu/placeholder-file-items",
                              name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
 
       /* cleanup */
@@ -1949,40 +2271,6 @@ mousepad_window_recent_add (MousepadWindow *window,
 
 
 
-static gchar *
-mousepad_window_recent_escape_underscores (const gchar *str)
-{
-  GString     *result;
-  gssize       length;
-  const gchar *end, *next;
-
-  length = strlen (str);
-  result = g_string_sized_new (length);
-
-  end = str + length;
-
-  while (str != end)
-    {
-      next = g_utf8_next_char (str);
-
-      switch (*str)
-        {
-          case '_':
-            g_string_append (result, "__");
-            break;
-          default:
-            g_string_append_len (result, str, next - str);
-            break;
-        }
-
-      str = next;
-    }
-
-  return g_string_free (result, FALSE);
-}
-
-
-
 static gint
 mousepad_window_recent_sort (GtkRecentInfo *a,
                              GtkRecentInfo *b)
@@ -2015,9 +2303,10 @@ mousepad_window_recent_menu_idle (gpointer user_data)
   GList          *items, *li, *actions;
   GList          *filtered = NULL;
   GtkRecentInfo  *info;
+  const gchar    *uri;
   const gchar    *display_name;
-  gchar          *uri_display;
   gchar          *tooltip, *name, *label;
+  gchar          *filename, *filename_utf8;
   GtkAction      *action;
   gint            n;
 
@@ -2052,69 +2341,88 @@ mousepad_window_recent_menu_idle (gpointer user_data)
       if (!gtk_recent_info_has_group (li->data, PACKAGE_NAME))
         continue;
 
-      /* append the item */
-      filtered = g_list_prepend (filtered, li->data);
+      /* insert the the list, sorted by date */
+      filtered = g_list_insert_sorted (filtered, li->data, (GCompareFunc) mousepad_window_recent_sort);
     }
 
-  /* sort the filtered items by modification date */
-  filtered = g_list_sort (filtered, (GCompareFunc) mousepad_window_recent_sort);
-
   /* get the recent menu limit number */
   g_object_get (G_OBJECT (window->preferences), "misc-recent-menu-items", &n, NULL);
 
   /* append the items to the menu */
-  for (li = filtered; n > 0 && li != NULL; li = li->next, --n)
+  for (li = filtered; n > 0 && li != NULL; li = li->next)
     {
       info = li->data;
 
-      /* create the action name */
-      name = g_strdup_printf ("recent-info-%d", n);
+      /* get the filename */
+      uri = gtk_recent_info_get_uri (info);
+      filename = g_filename_from_uri (uri, NULL, NULL);
 
-      /* get the name of the item and escape the underscores */
-      display_name = gtk_recent_info_get_display_name (info);
-      label = mousepad_window_recent_escape_underscores (display_name);
+      /* append to the menu if the file exists, else remove it from the history */
+      if (filename && g_file_test (filename, G_FILE_TEST_EXISTS))
+        {
+          /* create the action name */
+          name = g_strdup_printf ("recent-info-%d", n);
 
-      /* create the tooltip with an utf-8 valid version of the filename */
-      uri_display = gtk_recent_info_get_uri_display (info);
-      tooltip = g_strdup_printf (_("Open '%s'"), uri_display);
-      g_free (uri_display);
+          /* get the name of the item and escape the underscores */
+          display_name = gtk_recent_info_get_display_name (info);
+          label = mousepad_util_escape_underscores (display_name);
 
-      /* create the action */
-      action = gtk_action_new (name, label, tooltip, NULL);
+          /* create and utf-8 valid version of the filename */
+          filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+          tooltip = g_strdup_printf (_("Open '%s'"), filename_utf8);
+          g_free (filename_utf8);
 
-      /* cleanup */
-      g_free (tooltip);
-      g_free (label);
+          /* create the action */
+          action = gtk_action_new (name, label, tooltip, NULL);
 
-      /* add the info data and connect a menu signal */
-      g_object_set_data_full (G_OBJECT (action), I_("gtk-recent-info"), gtk_recent_info_ref (info), (GDestroyNotify) gtk_recent_info_unref);
-      g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (mousepad_window_action_open_recent), window);
+          /* cleanup */
+          g_free (tooltip);
+          g_free (label);
 
-      /* add the action to the recent actions group */
-      gtk_action_group_add_action (window->action_group, action);
+          /* add the info data and connect a menu signal */
+          mousepad_object_set_data_full (G_OBJECT (action), "gtk-recent-info", gtk_recent_info_ref (info), gtk_recent_info_unref);
+          g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (mousepad_window_action_open_recent), window);
 
-      /* add the action to the menu */
-      gtk_ui_manager_add_ui (window->ui_manager, window->recent_merge_id,
-                             "/main-menu/file-menu/recent-menu/placeholder-recent-items",
-                             name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
+          /* add the action to the recent actions group */
+          gtk_action_group_add_action (window->action_group, action);
 
-      /* cleanup */
-      g_free (name);
-    }
+          /* release the action */
+          g_object_unref (G_OBJECT (action));
 
-  /* set the visibility of the 'No items found' action */
-  action = gtk_action_group_get_action (window->action_group, "no-recent-items");
-  gtk_action_set_visible (action, (filtered == NULL));
-  gtk_action_set_sensitive (action, FALSE);
+          /* add the action to the menu */
+          gtk_ui_manager_add_ui (window->ui_manager, window->recent_merge_id,
+                                 "/main-menu/file-menu/recent-menu/placeholder-recent-items",
+                                 name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
+
+          /* cleanup */
+          g_free (name);
+
+          /* decrease counter */
+          n--;
+        }
+      else
+        {
+          /* remove the item. don't both the user if this fails */
+          gtk_recent_manager_remove_item (window->recent_manager, uri, NULL);
+        }
+
+      /* cleanup */
+      g_free (filename);
+    }
+
+  /* set the visibility of the 'no items found' action */
+  action = gtk_action_group_get_action (window->action_group, "no-recent-items");
+  gtk_action_set_visible (action, (filtered == NULL));
+  gtk_action_set_sensitive (action, FALSE);
 
   /* set the sensitivity of the clear button */
   action = gtk_action_group_get_action (window->action_group, "clear-recent");
   gtk_action_set_sensitive (action, (filtered != NULL));
 
   /* cleanup */
-  g_list_free (filtered);
   g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
   g_list_free (items);
+  g_list_free (filtered);
 
   /* make sure the ui is up2date to avoid flickering */
   gtk_ui_manager_ensure_update (window->ui_manager);
@@ -2189,8 +2497,7 @@ mousepad_window_recent_clear (MousepadWindow *window)
   /* print a warning is there is one */
   if (G_UNLIKELY (error != NULL))
     {
-      mousepad_dialogs_show_error (GTK_WINDOW (window), error,
-                                   _("Failed to remove an item from the documents history"));
+      mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to clear the recent history"));
       g_error_free (error);
     }
 }
@@ -2211,6 +2518,7 @@ mousepad_window_drag_data_received (GtkWidget        *widget,
                                     MousepadWindow   *window)
 {
   gchar     **uris;
+  gchar      *working_directory;
   GtkWidget  *notebook, **document;
   GtkWidget  *child, *label;
   gint        i, n_pages;
@@ -2224,10 +2532,14 @@ mousepad_window_drag_data_received (GtkWidget        *widget,
       /* extract the uris from the data */
       uris = g_uri_list_extract_uris ((const gchar *)selection_data->data);
 
+      /* get working directory */
+      working_directory = g_get_current_dir ();
+
       /* open the files */
       mousepad_window_open_files (window, NULL, uris);
 
       /* cleanup */
+      g_free (working_directory);
       g_strfreev (uris);
 
       /* finish the drag (copy) */
@@ -2281,6 +2593,9 @@ mousepad_window_drag_data_received (GtkWidget        *widget,
 
 
 
+/**
+ * Find and replace
+ **/
 static gint
 mousepad_window_search (MousepadWindow      *window,
                         MousepadSearchFlags  flags,
@@ -2320,7 +2635,7 @@ mousepad_window_search (MousepadWindow      *window,
 
       /* make sure the selection is visible */
       if (flags & (MOUSEPAD_SEARCH_FLAGS_ACTION_SELECT | MOUSEPAD_SEARCH_FLAGS_ACTION_REPLACE) && nmatches > 0)
-        mousepad_view_put_cursor_on_screen (window->active->textview);
+        mousepad_view_scroll_to_cursor (window->active->textview);
     }
   else
     {
@@ -2355,28 +2670,330 @@ mousepad_window_hide_search_bar (MousepadWindow *window)
 }
 
 
+
+/**
+ * Paste from History
+ **/
+static void
+mousepad_window_paste_history_add (MousepadWindow *window)
+{
+  GtkClipboard *clipboard;
+  gchar        *text;
+  GSList       *li;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+  /* get the current clipboard text */
+  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
+  text = gtk_clipboard_wait_for_text (clipboard);
+
+  /* leave when there is no text */
+  if (G_UNLIKELY (text == NULL))
+    return;
+
+  /* check if the item is already in the history */
+  for (li = clipboard_history; li != NULL; li = li->next)
+    if (strcmp (li->data, text) == 0)
+      break;
+
+  /* append the item or remove it */
+  if (G_LIKELY (li == NULL))
+    {
+      /* add to the list */
+      clipboard_history = g_slist_prepend (clipboard_history, text);
+
+      /* get the 9th item from the list and remove it if it exists */
+      li = g_slist_nth (clipboard_history, 9);
+      if (li != NULL)
+        {
+          /* cleanup */
+          g_free (li->data);
+          clipboard_history = g_slist_delete_link (clipboard_history, li);
+        }
+    }
+  else
+    {
+      /* already in the history, remove it */
+      g_free (text);
+    }
+}
+
+
+
+static void
+mousepad_window_paste_history_menu_position (GtkMenu  *menu,
+                                             gint     *x,
+                                             gint     *y,
+                                             gboolean *push_in,
+                                             gpointer  user_data)
+{
+  MousepadWindow   *window = MOUSEPAD_WINDOW (user_data);
+  MousepadDocument *document = window->active;
+  GtkTextIter       iter;
+  GtkTextMark      *mark;
+  GdkRectangle      location;
+  gint              iter_x, iter_y;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (GTK_IS_TEXT_VIEW (document->textview));
+  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (document->buffer));
+
+  /* get the root coordinates of the texview widget */
+  gdk_window_get_origin (gtk_text_view_get_window (GTK_TEXT_VIEW (document->textview), GTK_TEXT_WINDOW_TEXT), x, y);
+
+  /* get the cursor iter */
+  mark = gtk_text_buffer_get_insert (document->buffer);
+  gtk_text_buffer_get_iter_at_mark (document->buffer, &iter, mark);
+
+  /* get iter location */
+  gtk_text_view_get_iter_location (GTK_TEXT_VIEW (document->textview), &iter, &location);
+
+  /* convert to textview coordinates */
+  gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (document->textview), GTK_TEXT_WINDOW_TEXT,
+                                         location.x, location.y, &iter_x, &iter_y);
+
+  /* add the iter coordinates to the menu popup position */
+  *x += iter_x;
+  *y += iter_y + location.height;
+}
+
+
+
+static void
+mousepad_window_paste_history_activate (GtkMenuItem    *item,
+                                        MousepadWindow *window)
+{
+  const gchar *text;
+
+  _mousepad_return_if_fail (GTK_IS_MENU_ITEM (item));
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+  _mousepad_return_if_fail (MOUSEPAD_IS_VIEW (window->active->textview));
+
+  /* get the menu item text */
+  text = mousepad_object_get_data (G_OBJECT (item), "history-pointer");
+
+  /* paste the text */
+  if (G_LIKELY (text))
+    mousepad_view_clipboard_paste (window->active->textview, text, FALSE);
+}
+
+
+
+static GtkWidget *
+mousepad_window_paste_history_menu_item (const gchar *text,
+                                         const gchar *mnemonic)
+{
+  GtkWidget   *item;
+  GtkWidget   *label;
+  GtkWidget   *hbox;
+  const gchar *s;
+  gchar       *label_str;
+  GString     *string;
+
+  /* create new label string */
+  string = g_string_sized_new (PASTE_HISTORY_MENU_LENGTH);
+
+  /* get the first 30 chars of the clipboard text */
+  if (g_utf8_strlen (text, -1) > PASTE_HISTORY_MENU_LENGTH)
+    {
+      /* append the first 30 chars */
+      s = g_utf8_offset_to_pointer (text, PASTE_HISTORY_MENU_LENGTH);
+      string = g_string_append_len (string, text, s - text);
+
+      /* make it look like a ellipsized string */
+      string = g_string_append (string, "...");
+    }
+  else
+    {
+      /* append the entire string */
+      string = g_string_append (string, text);
+    }
+
+  /* get the string */
+  label_str = g_string_free (string, FALSE);
+
+  /* replace tab and new lines with spaces */
+  label_str = g_strdelimit (label_str, "\n\t\r", ' ');
+
+  /* create a new item */
+  item = gtk_menu_item_new ();
+
+  /* create a hbox */
+  hbox = gtk_hbox_new (FALSE, 14);
+  gtk_container_add (GTK_CONTAINER (item), hbox);
+  gtk_widget_show (hbox);
+
+  /* create the clipboard label */
+  label = gtk_label_new (label_str);
+  gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_widget_show (label);
+
+  /* create the mnemonic label */
+  label = gtk_label_new_with_mnemonic (mnemonic);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), item);
+  gtk_widget_show (label);
+
+  /* cleanup */
+  g_free (label_str);
+
+  return item;
+}
+
+
+
+static GtkWidget *
+mousepad_window_paste_history_menu (MousepadWindow *window)
+{
+  GSList       *li;
+  gchar        *text;
+  gpointer      list_data = NULL;
+  GtkWidget    *item;
+  GtkWidget    *menu;
+  GtkClipboard *clipboard;
+  gchar         mnemonic[4];
+  gint          n;
+
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), NULL);
+
+  /* create new menu and set the screen */
+  menu = gtk_menu_new ();
+  g_object_ref_sink (G_OBJECT (menu));
+  g_signal_connect (G_OBJECT (menu), "deactivate", G_CALLBACK (g_object_unref), NULL);
+  gtk_menu_set_screen (GTK_MENU (menu), gtk_widget_get_screen (GTK_WIDGET (window)));
+
+  /* get the current clipboard text */
+  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
+  text = gtk_clipboard_wait_for_text (clipboard);
+
+  /* append the history items */
+  for (li = clipboard_history, n = 1; li != NULL; li = li->next)
+    {
+      /* skip the active clipboard item */
+      if (G_UNLIKELY (list_data == NULL && text && strcmp (li->data, text) == 0))
+        {
+          /* store the pointer so we can attach it at the end of the menu */
+          list_data = li->data;
+        }
+      else
+        {
+          /* create mnemonic string */
+          g_snprintf (mnemonic, sizeof (mnemonic), "_%d", n++);
+
+          /* create menu item */
+          item = mousepad_window_paste_history_menu_item (li->data, mnemonic);
+          mousepad_object_set_data (G_OBJECT (item), "history-pointer", li->data);
+          gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+          g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (mousepad_window_paste_history_activate), window);
+          gtk_widget_show (item);
+        }
+    }
+
+  /* cleanup */
+  g_free (text);
+
+  if (list_data != NULL)
+    {
+      /* add separator between history and active menu items */
+      if (GTK_MENU_SHELL (menu)->children != NULL)
+        {
+          item = gtk_separator_menu_item_new ();
+          gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+          gtk_widget_show (item);
+        }
+
+      /* create menu item for current clipboard text */
+      item = mousepad_window_paste_history_menu_item (list_data, "_0");
+      mousepad_object_set_data (G_OBJECT (item), "history-pointer", list_data);
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (mousepad_window_paste_history_activate), window);
+      gtk_widget_show (item);
+    }
+  else if (GTK_MENU_SHELL (menu)->children == NULL)
+    {
+      /* create an item to inform the user */
+      item = gtk_menu_item_new_with_label (_("No clipboard data"));
+      gtk_widget_set_sensitive (item, FALSE);
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      gtk_widget_show (item);
+    }
+
+  return menu;
+}
+
+
+
+/**
+ * Miscellaneous Actions
+ **/
+static void
+mousepad_window_button_close_tab (MousepadDocument *document,
+                                  MousepadWindow   *window)
+{
+  gint page_num;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+  /* switch to the tab we're going to close */
+  page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (document));
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page_num);
+
+  /* close the document */
+  mousepad_window_close_document (window, document);
+}
+
+
+
+static gboolean
+mousepad_window_delete_event (MousepadWindow *window,
+                              GdkEvent       *event)
+{
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+
+  /* try to close the window */
+  mousepad_window_action_close_window (NULL, window);
+
+  /* we will close the window when all the tabs are closed */
+  return TRUE;
+}
+
+
+
 /**
  * Menu Actions
  *
  * All those function should be sorted by the menu structure so it's
- * easy to find a function. Remember that some action functions can
- * still be triggered with keybindings, even when there are no tabs
- * opened. There for it should always check if the active document is
- * not NULL.
+ * easy to find a function. The function can always use window->active, since
+ * we can assume there is always an active document inside a window.
  **/
 static void
-mousepad_window_action_open_new_tab (GtkAction      *action,
-                                     MousepadWindow *window)
+mousepad_window_action_new (GtkAction      *action,
+                            MousepadWindow *window)
 {
-  mousepad_window_open_file (window, NULL, NULL);
+  MousepadDocument *document;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+  /* create new document */
+  document = mousepad_document_new ();
+
+  /* add the document to the window */
+  mousepad_window_add (window, document);
 }
 
 
 
 static void
-mousepad_window_action_open_new_window (GtkAction      *action,
-                                        MousepadWindow *window)
+mousepad_window_action_new_window (GtkAction      *action,
+                                   MousepadWindow *window)
 {
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
   /* emit the new window signal */
   g_signal_emit (G_OBJECT (window), window_signals[NEW_WINDOW], 0);
 }
@@ -2384,16 +3001,95 @@ mousepad_window_action_open_new_window (GtkAction      *action,
 
 
 static void
-mousepad_window_action_open_file (GtkAction      *action,
-                                  MousepadWindow *window)
+mousepad_window_action_new_from_template (GtkMenuItem    *item,
+                                          MousepadWindow *window)
 {
-  GtkWidget        *chooser;
-  gchar            *filename;
-  const gchar      *active_filename;
-  GSList           *filenames, *li;
-  MousepadDocument *document = window->active;
+  const gchar      *filename;
+  gchar            *contents;
+  GError           *error = NULL;
+  gboolean          succeed;
+  gsize             length;
+  MousepadDocument *document;
+  GtkTextIter       iter;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (GTK_IS_MENU_ITEM (item));
+
+  /* get the filename from the menu item */
+  filename = mousepad_object_get_data (G_OBJECT (item), "filename");
+
+  /* test if the file exists */
+  if (G_LIKELY (filename && g_file_test (filename, G_FILE_TEST_IS_REGULAR)))
+    {
+      /* get the content of the template */
+      succeed = g_file_get_contents (filename, &contents, &length, &error);
+      if (G_LIKELY (succeed))
+        {
+          /* check if the template is utf-8 valid */
+          succeed = g_utf8_validate (contents, length, NULL);
+          if (G_LIKELY (succeed))
+            {
+              /* create new document */
+              document = mousepad_document_new ();
+
+              /* lock the undo manager */
+              mousepad_undo_lock (document->undo);
+
+              /* set the template content */
+              gtk_text_buffer_set_text (document->buffer, contents, length);
+
+              /* move iter to the start of the document */
+              gtk_text_buffer_get_start_iter (document->buffer, &iter);
+              gtk_text_buffer_place_cursor (document->buffer, &iter);
+
+              /* buffer is not modified */
+              gtk_text_buffer_set_modified (document->buffer, FALSE);
+
+              /* release the lock */
+              mousepad_undo_unlock (document->undo);
+
+              /* add the document to the window */
+              mousepad_window_add (window, document);
+            }
+          else
+            {
+              /* set and error */
+              g_set_error (&error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
+                           _("The template is not UTF-8 valid"));
+            }
+
+          /* cleanup */
+          g_free (contents);
+        }
+
+      if (G_UNLIKELY (succeed == FALSE))
+        {
+          /* show an error */
+          mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to open new file from a template"));
+          g_error_free (error);
+        }
+    }
+  else
+    {
+      /* destroy the menu item */
+      gtk_widget_destroy (GTK_WIDGET (item));
+    }
+}
+
+
+
+static void
+mousepad_window_action_open (GtkAction      *action,
+                             MousepadWindow *window)
+{
+  GtkWidget   *chooser;
+  const gchar *filename;
+  GSList      *filenames, *li;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  /* create new chooser dialog */
+  /* create new file chooser dialog */
   chooser = gtk_file_chooser_dialog_new (_("Open File"),
                                          GTK_WINDOW (window),
                                          GTK_FILE_CHOOSER_ACTION_OPEN,
@@ -2404,16 +3100,10 @@ mousepad_window_action_open_file (GtkAction      *action,
   gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
   gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
 
-  /* open the folder of the currently opened file */
-  if (document)
-    {
-      /* get the filename of the active document */
-      active_filename = mousepad_file_get_filename (document->file);
-
-      /* set the current filename, if there is one */
-      if (active_filename && g_file_test (active_filename, G_FILE_TEST_EXISTS))
-        gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), active_filename);
-    }
+  /* select the active document in the file chooser */
+  filename = mousepad_file_get_filename (window->active->file);
+  if (filename && g_file_test (filename, G_FILE_TEST_EXISTS))
+    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), filename);
 
   /* run the dialog */
   if (G_LIKELY (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT))
@@ -2421,25 +3111,23 @@ mousepad_window_action_open_file (GtkAction      *action,
       /* hide the dialog */
       gtk_widget_hide (chooser);
 
-      /* open the new file */
+      /* get a list of selected filenames */
       filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (chooser));
 
-      /* block menu updates */
+      /* lock menu updates */
       lock_menu_updates++;
 
-      /* open the selected files */
+      /* open all the selected filenames in a new tab */
       for (li = filenames; li != NULL; li = li->next)
         {
-          filename = li->data;
-
-          /* open the file in a new tab */
-          mousepad_window_open_file (window, filename, NULL);
+          /* open the file */
+          mousepad_window_open_file (window, li->data, NULL);
 
           /* cleanup */
-          g_free (filename);
+          g_free (li->data);
         }
 
-      /* free the list */
+      /* cleanup */
       g_slist_free (filenames);
 
       /* allow menu updates again */
@@ -2468,8 +3156,11 @@ mousepad_window_action_open_recent (GtkAction      *action,
   gboolean       succeed = FALSE;
   GtkRecentInfo *info;
 
+  _mousepad_return_if_fail (GTK_IS_ACTION (action));
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
   /* get the info */
-  info = g_object_get_data (G_OBJECT (action), I_("gtk-recent-info"));
+  info = mousepad_object_get_data (G_OBJECT (action), "gtk-recent-info");
 
   if (G_LIKELY (info != NULL))
     {
@@ -2484,21 +3175,27 @@ mousepad_window_action_open_recent (GtkAction      *action,
           /* open the file in a new tab if it exists */
           if (g_file_test (filename, G_FILE_TEST_EXISTS))
             {
-              /* set text offset */
-              offset = strlen (_("Encoding")) + 2;
-
-              /* try to read the encoding we might has saved in the description ;) */
+              /* check if we set the encoding in the recent description */
               description = gtk_recent_info_get_description (info);
-              if (G_LIKELY (description && strlen (description) > offset))
-                encoding = description + offset;
+              if (G_LIKELY (description))
+                {
+                  /* get the offset length */
+                  offset = strlen (_("Encoding")) + 2;
+
+                  /* check if the encoding string looks valid and set it */
+                  if (G_LIKELY (strlen (description) > offset))
+                    encoding = description + offset;
+                }
 
+              /* try to open the file */
               succeed = mousepad_window_open_file (window, filename, encoding);
             }
           else
             {
-              /* create a warning */
+              /* create an error */
               g_set_error (&error,  G_FILE_ERROR, G_FILE_ERROR_IO,
-                           _("Failed to open \"%s\" for reading. It will be removed from the document history"), filename);
+                           _("Failed to open \"%s\" for reading. It will be "
+                             "removed from the document history"), filename);
 
               /* show the warning and cleanup */
               mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to open file"));
@@ -2523,6 +3220,8 @@ static void
 mousepad_window_action_clear_recent (GtkAction      *action,
                                      MousepadWindow *window)
 {
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
   /* ask the user if he or she really want to clear the history */
   if (mousepad_dialogs_clear_recent (GTK_WINDOW (window)))
     {
@@ -2543,37 +3242,34 @@ mousepad_window_action_clear_recent (GtkAction      *action,
 
 
 static gboolean
-mousepad_window_action_save_file (GtkAction      *action,
-                                  MousepadWindow *window)
+mousepad_window_action_save (GtkAction      *action,
+                             MousepadWindow *window)
 {
   MousepadDocument *document = window->active;
   GError           *error = NULL;
   gboolean          succeed = FALSE;
 
-  _mousepad_return_val_if_fail (document != NULL, FALSE);
-  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (document), FALSE);
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (window->active), FALSE);
 
-  if (G_LIKELY (document))
+  if (mousepad_file_get_filename (document->file) == NULL)
     {
-      /* save-as when there is no filename yet */
-      if (mousepad_file_get_filename (document->file) == NULL)
-        {
-          mousepad_window_action_save_file_as (NULL, window);
-        }
-      else
-        {
-          /* save the document */
-          succeed = mousepad_file_save (document->file, &error);
+      /* file has no filename yet, open the save as dialog */
+      mousepad_window_action_save_as (NULL, window);
+    }
+  else
+    {
+      /* save the document */
+      succeed = mousepad_file_save (document->file, &error);
 
-          /* update the window title */
-          mousepad_window_set_title (window);
+      /* update the window title */
+      mousepad_window_set_title (window);
 
-          if (G_UNLIKELY (succeed == FALSE))
-            {
-              /* show the warning */
-              mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to save the document"));
-              g_error_free (error);
-            }
+      if (G_UNLIKELY (succeed == FALSE))
+        {
+          /* show the error */
+          mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to save the document"));
+          g_error_free (error);
         }
     }
 
@@ -2583,89 +3279,199 @@ mousepad_window_action_save_file (GtkAction      *action,
 
 
 static gboolean
-mousepad_window_action_save_file_as (GtkAction      *action,
-                                     MousepadWindow *window)
+mousepad_window_action_save_as (GtkAction      *action,
+                                MousepadWindow *window)
 {
   MousepadDocument *document = window->active;
   gchar            *filename;
-  const gchar      *old_filename;
+  const gchar      *current_filename;
   GtkWidget        *dialog;
-  gboolean          succeed = TRUE;
+  gboolean          succeed = FALSE;
 
-  if (G_LIKELY (document))
-    {
-      /* create the dialog */
-      dialog = gtk_file_chooser_dialog_new (_("Save As"),
-          GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_SAVE,
-          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-          GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
-      gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
-      gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
-      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
+  _mousepad_return_val_if_fail (MOUSEPAD_IS_DOCUMENT (window->active), FALSE);
+
+  /* create the dialog */
+  dialog = gtk_file_chooser_dialog_new (_("Save As"),
+                                        GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_SAVE,
+                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                        GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
+  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+  /* set the current filename if there is one */
+  current_filename = mousepad_file_get_filename (document->file);
+  if (current_filename)
+    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), current_filename);
 
-      /* set the current filename */
-      old_filename = mousepad_file_get_filename (document->file);
-      if (old_filename)
-        gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), old_filename);
+  /* run the dialog */
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+    {
+      /* get the new filename */
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
 
-      /* run the dialog */
-      if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+      if (G_LIKELY (filename))
         {
-          /* get the new filename */
-          filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+          /* set the new filename */
+          mousepad_file_set_filename (document->file, filename);
 
-          if (G_LIKELY (filename))
-            {
-              /* set the new filename */
-              mousepad_file_set_filename (document->file, filename);
+          /* cleanup */
+          g_free (filename);
 
-              /* cleanup */
-              g_free (filename);
+          /* save the file with the function above */
+          succeed = mousepad_window_action_save (NULL, window);
+
+          /* add to the recent history is saving succeeded */
+          if (G_LIKELY (succeed))
+            mousepad_window_recent_add (window, document->file);
+        }
+    }
+
+  /* destroy the dialog */
+  gtk_widget_destroy (dialog);
 
-              /* save the file */
-              succeed = mousepad_window_action_save_file (NULL, window);
+  return succeed;
+}
+
+
+
+static void
+mousepad_window_action_save_all (GtkAction      *action,
+                                 MousepadWindow *window)
+{
+  guint      i, current;
+  gint       page_num;
+  GtkWidget *document;
+  GSList    *li, *unnamed = NULL;
+  gboolean   succeed = TRUE;
+  GError    *error = NULL;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* get the current active tab */
+  current = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
+
+  /* walk though all the document in the window */
+  for (i = 0; i < gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)); i++)
+    {
+      /* get the document */
+      document = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i);
+
+      /* debug check */
+      _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+      /* continue if the document is not modified */
+      if (!gtk_text_buffer_get_modified (MOUSEPAD_DOCUMENT (document)->buffer))
+        continue;
+
+      if (mousepad_file_get_filename (MOUSEPAD_DOCUMENT (document)->file) == NULL)
+        {
+          /* add the document to a queue to bother the user later */
+          unnamed = g_slist_prepend (unnamed, document);
+        }
+      else
+        {
+          /* try to save the file */
+          succeed = mousepad_file_save (MOUSEPAD_DOCUMENT (document)->file, &error);
+
+          /* break on problems */
+          if (G_UNLIKELY (succeed == FALSE))
+            break;
+        }
+    }
+
+  if (G_UNLIKELY (succeed == FALSE))
+    {
+      /* focus the tab that triggered the problem */
+      gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), i);
+
+      /* show the error */
+      mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to save the document"));
+      g_error_free (error);
+    }
+  else
+    {
+      /* open a save as dialog for all the unnamed files */
+      for (li = unnamed; li != NULL; li = li->next)
+        {
+          /* get the documents page number */
+          page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (li->data));
+
+          if (G_LIKELY (page_num > -1))
+            {
+              /* focus the tab we're going to save */
+              gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page_num);
+
+              /* trigger the save as function, break when something went wrong */
+              if (!mousepad_window_action_save_as (NULL, window))
+                break;
             }
         }
 
-      /* destroy the dialog */
-      gtk_widget_destroy (dialog);
+      /* focus the origional doc if everything went fine */
+      if (G_LIKELY (li == NULL))
+        gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), current);
     }
 
-  return succeed;
+  /* cleanup */
+  g_slist_free (unnamed);
 }
 
 
 
 static void
-mousepad_window_action_reload (GtkAction      *action,
+mousepad_window_action_revert (GtkAction      *action,
                                MousepadWindow *window)
 {
   MousepadDocument *document = window->active;
   GError           *error = NULL;
-  gboolean          result;
+  gint              response;
+  gboolean          succeed;
 
-  if (G_LIKELY (document))
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* ask the user if he really wants to do this when the file is modified */
+  if (gtk_text_buffer_get_modified (document->buffer))
     {
-      /* TODO ask user if he/she really want this */
+      /* ask the user if he really wants to revert */
+      response = mousepad_dialogs_revert (GTK_WINDOW (window));
 
-      /* lock the undo manager */
-      mousepad_undo_lock (document->undo);
+      if (response == MOUSEPAD_RESPONSE_SAVE_AS)
+        {
+          /* open the save as dialog, leave when use user did not save (or it failed) */
+          if (!mousepad_window_action_save_as (NULL, window))
+            return;
+        }
+      else if (response == MOUSEPAD_RESPONSE_CANCEL)
+        {
+          /* meh, first click revert and then cancel... pussy... */
+          return;
+        }
 
-      /* clear the undo history */
-      mousepad_undo_clear (document->undo);
+      /* small check for debug builds */
+      _mousepad_return_if_fail (response == MOUSEPAD_RESPONSE_REVERT);
+    }
 
-      /* reload the file */
-      result = mousepad_file_reload (document->file, &error);
+  /* lock the undo manager */
+  mousepad_undo_lock (document->undo);
 
-      /* release the lock */
-      mousepad_undo_unlock (document->undo);
+  /* clear the undo history */
+  mousepad_undo_clear (document->undo);
 
-      if (G_UNLIKELY (result == FALSE))
-        {
-          /* show the warning */
-          mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to reload the document"));
-          g_error_free (error);
-        }
+  /* reload the file */
+  succeed = mousepad_file_reload (document->file, &error);
+
+  /* release the lock */
+  mousepad_undo_unlock (document->undo);
+
+  if (G_UNLIKELY (succeed == FALSE))
+    {
+      /* show the error */
+      mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to reload the document"));
+      g_error_free (error);
     }
 }
 
@@ -2676,15 +3482,24 @@ mousepad_window_action_print (GtkAction      *action,
                               MousepadWindow *window)
 {
   MousepadPrint    *print;
-  MousepadDocument *document = window->active;
   GError           *error = NULL;
   gboolean          succeed;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
   /* create new print operation */
   print = mousepad_print_new ();
 
-  /* print the current document interactive */
-  succeed = mousepad_print_document_interactive (print, document, GTK_WINDOW (window), &error);
+  /* print the current document */
+  succeed = mousepad_print_document_interactive (print, window->active, GTK_WINDOW (window), &error);
+
+  if (G_UNLIKELY (succeed == FALSE))
+    {
+      /* show the error */
+      mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to print the document"));
+      g_error_free (error);
+    }
 
   /* release the object */
   g_object_unref (G_OBJECT (print));
@@ -2696,28 +3511,29 @@ static void
 mousepad_window_action_detach (GtkAction      *action,
                                MousepadWindow *window)
 {
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
 #if GTK_CHECK_VERSION (2,12,0)
   /* invoke function without cooridinates */
   mousepad_window_notebook_create_window (GTK_NOTEBOOK (window->notebook),
                                           GTK_WIDGET (window->active),
                                           -1, -1, window);
 #else
-  MousepadDocument *document = window->active;
-
   /* only detach when there are more then 2 tabs */
-  if (document && gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) >= 2)
+  if (G_LIKELY (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) >= 2))
     {
       /* take a reference */
-      g_object_ref (G_OBJECT (document));
+      g_object_ref (G_OBJECT (window->active));
 
       /* remove the document from the active window */
-      gtk_container_remove (GTK_CONTAINER (window->notebook), GTK_WIDGET (document));
+      gtk_container_remove (GTK_CONTAINER (window->notebook), GTK_WIDGET (window->active));
 
       /* emit the new window with document signal */
-      g_signal_emit (G_OBJECT (window), window_signals[NEW_WINDOW_WITH_DOCUMENT], 0, document, -1, -1);
+      g_signal_emit (G_OBJECT (window), window_signals[NEW_WINDOW_WITH_DOCUMENT], 0, window->active, -1, -1);
 
       /* release our reference */
-      g_object_unref (G_OBJECT (document));
+      g_object_unref (G_OBJECT (window->active));
     }
 #endif
 }
@@ -2725,24 +3541,28 @@ mousepad_window_action_detach (GtkAction      *action,
 
 
 static void
-mousepad_window_action_close_tab (GtkAction      *action,
-                                  MousepadWindow *window)
+mousepad_window_action_close (GtkAction      *action,
+                              MousepadWindow *window)
 {
-  MousepadDocument *document = window->active;
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  if (G_LIKELY (document))
-    mousepad_window_close_document (window, document);
+  /* close active document */
+  mousepad_window_close_document (window, window->active);
 }
 
 
 
 static void
-mousepad_window_action_close (GtkAction      *action,
-                              MousepadWindow *window)
+mousepad_window_action_close_window (GtkAction      *action,
+                                     MousepadWindow *window)
 {
   gint       npages, i;
   GtkWidget *document;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
   /* get the number of page in the notebook */
   npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) - 1;
 
@@ -2752,29 +3572,31 @@ mousepad_window_action_close (GtkAction      *action,
   /* ask what to do with the modified document in this window */
   for (i = npages; i >= 0; --i)
     {
+      /* get the document */
       document = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i);
 
-      if (G_LIKELY (document))
+      /* check for debug builds */
+      _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+
+      /* focus the tab we're going to close */
+      gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), i);
+
+      /* close each document */
+      if (!mousepad_window_close_document (window, MOUSEPAD_DOCUMENT (document)))
         {
-          /* focus the tab we're going to close */
-          gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), i);
+          /* closing cancelled, release menu lock */
+          lock_menu_updates--;
 
-          /* ask user what to do, break when he/she hits the cancel button */
-          if (!mousepad_window_close_document (window, MOUSEPAD_DOCUMENT (document)))
-            {
-              /* update the go menu */
-              mousepad_window_update_gomenu (window);
+          /* rebuild go menu */
+          mousepad_window_update_gomenu (window);
 
-              /* leave the loop */
-              break;
-            }
+          /* leave function */
+          return;
         }
     }
 
-  /* allow updates again */
+  /* release lock */
   lock_menu_updates--;
-
-  /* window will close it self when it contains to tabs */
 }
 
 
@@ -2783,15 +3605,14 @@ static void
 mousepad_window_action_undo (GtkAction      *action,
                              MousepadWindow *window)
 {
-  MousepadDocument *document = window->active;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* undo */
-  mousepad_undo_do_undo (document->undo);
+  mousepad_undo_do_undo (window->active->undo);
 
   /* scroll to visible area */
-  mousepad_view_put_cursor_on_screen (document->textview);
+  mousepad_view_scroll_to_cursor (window->active->textview);
 }
 
 
@@ -2800,15 +3621,14 @@ static void
 mousepad_window_action_redo (GtkAction      *action,
                              MousepadWindow *window)
 {
-  MousepadDocument *document = window->active;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* redo */
-  mousepad_undo_do_redo (document->undo);
+  mousepad_undo_do_redo (window->active->undo);
 
   /* scroll to visible area */
-  mousepad_view_put_cursor_on_screen (document->textview);
+  mousepad_view_scroll_to_cursor (window->active->textview);
 }
 
 
@@ -2819,15 +3639,20 @@ mousepad_window_action_cut (GtkAction      *action,
 {
   GtkEditable *entry;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* get searchbar entry */
   entry = mousepad_search_bar_entry (MOUSEPAD_SEARCH_BAR (window->search_bar));
 
-  if (entry)
+  /* cut from search bar entry or textview */
+  if (G_UNLIKELY (entry))
     gtk_editable_cut_clipboard (entry);
   else
     mousepad_view_clipboard_cut (window->active->textview);
+
+  /* update the history */
+  mousepad_window_paste_history_add (window);
 }
 
 
@@ -2838,15 +3663,20 @@ mousepad_window_action_copy (GtkAction      *action,
 {
   GtkEditable *entry;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* get searchbar entry */
   entry = mousepad_search_bar_entry (MOUSEPAD_SEARCH_BAR (window->search_bar));
 
-  if (entry)
+  /* copy from search bar entry or textview */
+  if (G_UNLIKELY (entry))
     gtk_editable_copy_clipboard (entry);
   else
     mousepad_view_clipboard_copy (window->active->textview);
+
+  /* update the history */
+  mousepad_window_paste_history_add (window);
 }
 
 
@@ -2857,15 +3687,40 @@ mousepad_window_action_paste (GtkAction      *action,
 {
   GtkEditable *entry;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* get searchbar entry */
   entry = mousepad_search_bar_entry (MOUSEPAD_SEARCH_BAR (window->search_bar));
 
-  if (entry)
+  /* paste in search bar entry or textview */
+  if (G_UNLIKELY (entry))
     gtk_editable_paste_clipboard (entry);
   else
-    mousepad_view_clipboard_paste (window->active->textview, FALSE);
+    mousepad_view_clipboard_paste (window->active->textview, NULL, FALSE);
+}
+
+
+
+static void
+mousepad_window_action_paste_history (GtkAction      *action,
+                                      MousepadWindow *window)
+{
+  GtkWidget *menu;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* get the history menu */
+  menu = mousepad_window_paste_history_menu (window);
+
+  /* select the first item in the menu */
+  gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), TRUE);
+
+  /* popup the menu */
+  gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+                  mousepad_window_paste_history_menu_position,
+                  window, 0, gtk_get_current_event_time ());
 }
 
 
@@ -2874,11 +3729,11 @@ static void
 mousepad_window_action_paste_column (GtkAction      *action,
                                      MousepadWindow *window)
 {
-  MousepadDocument *document = window->active;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  mousepad_view_clipboard_paste (document->textview, TRUE);
+  /* paste the clipboard into a column */
+  mousepad_view_clipboard_paste (window->active->textview, NULL, TRUE);
 }
 
 
@@ -2889,12 +3744,14 @@ mousepad_window_action_delete (GtkAction      *action,
 {
   GtkEditable *entry;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* get searchbar entry */
   entry = mousepad_search_bar_entry (MOUSEPAD_SEARCH_BAR (window->search_bar));
 
-  if (entry)
+  /* delete selection in search bar entry or textview */
+  if (G_UNLIKELY (entry))
     gtk_editable_delete_selection (entry);
   else
     mousepad_view_delete_selection (window->active->textview);
@@ -2906,20 +3763,24 @@ static void
 mousepad_window_action_select_all (GtkAction      *action,
                                    MousepadWindow *window)
 {
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
+  /* select everything in the document */
   mousepad_view_select_all (window->active->textview);
 }
 
 
 
 static void
-mousepad_window_action_transpose (GtkAction      *action,
-                                  MousepadWindow *window)
+mousepad_window_action_change_selection (GtkAction      *action,
+                                         MousepadWindow *window)
 {
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  mousepad_view_transpose (window->active->textview);
+  /* change the selection */
+  mousepad_view_change_selection (window->active->textview);
 }
 
 
@@ -2928,6 +3789,10 @@ static void
 mousepad_window_action_find (GtkAction      *action,
                              MousepadWindow *window)
 {
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* create a new search bar is needed */
   if (window->search_bar == NULL)
     {
       /* create a new toolbar and pack it into the box */
@@ -2952,10 +3817,11 @@ static void
 mousepad_window_action_find_next (GtkAction      *action,
                                   MousepadWindow *window)
 {
-  MousepadDocument *document = window->active;
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  /* only find the next occurence when the search bar is initialized */
-  if (G_LIKELY (document && window->search_bar != NULL))
+  /* find the next occurence */
+  if (G_LIKELY (window->search_bar != NULL))
     mousepad_search_bar_find_next (MOUSEPAD_SEARCH_BAR (window->search_bar));
 }
 
@@ -2965,13 +3831,11 @@ static void
 mousepad_window_action_find_previous (GtkAction      *action,
                                       MousepadWindow *window)
 {
-  MousepadDocument *document = window->active;
-
-  _mousepad_return_if_fail (document != NULL);
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  /* only find the previous occurence when the search bar is initialized */
-  if (G_LIKELY (document && window->search_bar != NULL))
+  /* find the previous occurence */
+  if (G_LIKELY (window->search_bar != NULL))
     mousepad_search_bar_find_previous (MOUSEPAD_SEARCH_BAR (window->search_bar));
 }
 
@@ -2980,6 +3844,10 @@ mousepad_window_action_find_previous (GtkAction      *action,
 static void
 mousepad_window_action_replace_destroy (MousepadWindow *window)
 {
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+  /* TODO disconnect tab switch signal */
+
   /* reset the dialog variable */
   window->replace_dialog = NULL;
 }
@@ -2990,7 +3858,10 @@ static void
 mousepad_window_action_replace (GtkAction      *action,
                                 MousepadWindow *window)
 {
-  if (!window->replace_dialog)
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  if (window->replace_dialog == NULL)
     {
       /* create a new dialog */
       window->replace_dialog = mousepad_replace_dialog_new ();
@@ -3003,6 +3874,13 @@ mousepad_window_action_replace (GtkAction      *action,
       /* connect signals */
       g_signal_connect_swapped (G_OBJECT (window->replace_dialog), "destroy", G_CALLBACK (mousepad_window_action_replace_destroy), window);
       g_signal_connect_swapped (G_OBJECT (window->replace_dialog), "search", G_CALLBACK (mousepad_window_search), window);
+
+      /* TODO tab switch update signal */
+    }
+  else
+    {
+      /* focus the existing dialog */
+      gtk_widget_grab_focus (window->replace_dialog);
     }
 }
 
@@ -3015,14 +3893,16 @@ mousepad_window_action_select_font (GtkAction      *action,
   GtkWidget        *dialog;
   MousepadDocument *document;
   gchar            *font_name;
-  guint             npages, i;
+  guint             i;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   dialog = gtk_font_selection_dialog_new (_("Choose Mousepad Font"));
   gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
 
-  /* get the current font */
+  /* set the current font name */
   g_object_get (G_OBJECT (window->preferences), "view-font-name", &font_name, NULL);
-
   if (G_LIKELY (font_name))
     {
       gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
@@ -3032,13 +3912,14 @@ mousepad_window_action_select_font (GtkAction      *action,
   /* run the dialog */
   if (G_LIKELY (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK))
     {
-      /* send the new font to the preferences */
+      /* get the selected font from the dialog */
       font_name = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG (dialog));
+
+      /* store the font in the preferences */
       g_object_set (G_OBJECT (window->preferences), "view-font-name", font_name, NULL);
 
-      /* set the font in all documents in this window */
-      npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
-      for (i = 0; i < npages; i++)
+      /* apply the font in all documents in this window */
+      for (i = 0; i < gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)); i++)
         {
           /* get the document */
           document = MOUSEPAD_DOCUMENT (gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), i));
@@ -3064,18 +3945,33 @@ mousepad_window_action_select_font (GtkAction      *action,
 
 
 static void
+mousepad_window_action_statusbar_overwrite (MousepadWindow *window,
+                                            gboolean        overwrite)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* set the new overwrite mode */
+  mousepad_document_set_overwrite (window->active, overwrite);
+}
+
+
+
+static void
 mousepad_window_action_statusbar (GtkToggleAction *action,
                                   MousepadWindow  *window)
 {
   gboolean show_statusbar;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
   /* whether we show the statusbar */
   show_statusbar = gtk_toggle_action_get_active (action);
 
   /* check if we should drop the statusbar */
   if (!show_statusbar && window->statusbar != NULL)
     {
-      /* just get rid of the statusbar */
+      /* destroy the statusbar */
       gtk_widget_destroy (window->statusbar);
       window->statusbar = NULL;
     }
@@ -3088,11 +3984,17 @@ mousepad_window_action_statusbar (GtkToggleAction *action,
 
       /* overwrite toggle signal */
       g_signal_connect_swapped (G_OBJECT (window->statusbar), "enable-overwrite",
-                                G_CALLBACK (mousepad_window_toggle_overwrite), window);
+                                G_CALLBACK (mousepad_window_action_statusbar_overwrite), window);
 
       /* update the statusbar items */
       if (window->active)
-        mousepad_document_send_statusbar_signals (window->active);
+        {
+          /* debug check */
+          _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+          /* ask document to resend the cursor status signals */
+          mousepad_document_send_signals (window->active);
+        }
     }
 
   /* remember the setting */
@@ -3102,49 +4004,195 @@ mousepad_window_action_statusbar (GtkToggleAction *action,
 
 
 static void
-mousepad_window_action_line_numbers (GtkToggleAction *action,
-                                     MousepadWindow  *window)
+mousepad_window_action_lowercase (GtkAction      *action,
+                                  MousepadWindow *window)
 {
-  gboolean line_numbers;
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* convert selection to lowercase */
+  mousepad_view_convert_selection_case (window->active->textview, LOWERCASE);
+}
+
 
+
+static void
+mousepad_window_action_uppercase (GtkAction      *action,
+                                  MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  /* leave when menu updates are locked */
-  if (lock_menu_updates)
-    return;
+  /* convert selection to uppercase */
+  mousepad_view_convert_selection_case (window->active->textview, UPPERCASE);
+}
 
-  /* get the current state */
-  line_numbers = gtk_toggle_action_get_active (action);
 
-  /* save as the last used line number setting */
-  g_object_set (G_OBJECT (window->preferences), "view-line-numbers", line_numbers, NULL);
 
-  /* update the active document */
-  mousepad_view_set_line_numbers (window->active->textview, line_numbers);
+static void
+mousepad_window_action_titlecase (GtkAction      *action,
+                                  MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* convert selection to titlecase */
+  mousepad_view_convert_selection_case (window->active->textview, TITLECASE);
 }
 
 
 
 static void
-mousepad_window_action_auto_indent (GtkToggleAction *action,
-                                    MousepadWindow  *window)
+mousepad_window_action_opposite_case (GtkAction      *action,
+                                      MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* convert selection to opposite case */
+  mousepad_view_convert_selection_case (window->active->textview, OPPOSITE_CASE);
+}
+
+
+
+static void
+mousepad_window_action_tabs_to_spaces (GtkAction      *action,
+                                       MousepadWindow *window)
 {
-  gboolean auto_indent;
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* convert tabs to spaces */
+  mousepad_view_convert_spaces_and_tabs (window->active->textview, TABS_TO_SPACES);
+}
+
 
+
+static void
+mousepad_window_action_spaces_to_tabs (GtkAction      *action,
+                                       MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  /* leave when menu updates are locked */
-  if (lock_menu_updates)
-    return;
+  /* convert spaces to tabs */
+  mousepad_view_convert_spaces_and_tabs (window->active->textview, SPACES_TO_TABS);
+}
+
+
+
+static void
+mousepad_window_action_strip_trailing_spaces (GtkAction      *action,
+                                              MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* convert spaces to tabs */
+  mousepad_view_strip_trailing_spaces (window->active->textview);
+}
+
+
+
+static void
+mousepad_window_action_transpose (GtkAction      *action,
+                                  MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* transpose */
+  mousepad_view_transpose (window->active->textview);
+}
+
+
+
+static void
+mousepad_window_action_move_line_up (GtkAction      *action,
+                                     MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* move the selection on line up */
+  mousepad_view_move_selection (window->active->textview, MOVE_LINE_UP);
+}
+
+
+
+static void
+mousepad_window_action_move_line_down (GtkAction      *action,
+                                       MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* move the selection on line down */
+  mousepad_view_move_selection (window->active->textview, MOVE_LINE_DOWN);
+}
+
+
+
+static void
+mousepad_window_action_duplicate (GtkAction      *action,
+                                  MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* dupplicate */
+  mousepad_view_duplicate (window->active->textview);
+}
+
+
+
+static void
+mousepad_window_action_increase_indent (GtkAction      *action,
+                                        MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* increase the indent */
+  mousepad_view_indent (window->active->textview, INCREASE_INDENT);
+}
+
+
+
+static void
+mousepad_window_action_decrease_indent (GtkAction      *action,
+                                        MousepadWindow *window)
+{
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* decrease the indent */
+  mousepad_view_indent (window->active->textview, DECREASE_INDENT);
+}
+
+
+
+static void
+mousepad_window_action_line_numbers (GtkToggleAction *action,
+                                     MousepadWindow  *window)
+{
+  gboolean active;
 
-  /* get the current state */
-  auto_indent = gtk_toggle_action_get_active (action);
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
-  /* save as the last auto indent mode */
-  g_object_set (G_OBJECT (window->preferences), "view-auto-indent", auto_indent, NULL);
+  /* leave when menu updates are locked */
+  if (lock_menu_updates == 0)
+    {
+      /* get the current state */
+      active = gtk_toggle_action_get_active (action);
 
-  /* update the active document */
-  mousepad_view_set_auto_indent (window->active->textview, auto_indent);
+      /* save as the last used line number setting */
+      g_object_set (G_OBJECT (window->preferences), "view-line-numbers", active, NULL);
+
+      /* update the active document */
+      mousepad_view_set_line_numbers (window->active->textview, active);
+    }
 }
 
 
@@ -3153,22 +4201,48 @@ static void
 mousepad_window_action_word_wrap (GtkToggleAction *action,
                                   MousepadWindow  *window)
 {
-  gboolean word_wrap;
+  gboolean active;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* leave when menu updates are locked */
-  if (lock_menu_updates)
-    return;
+  if (lock_menu_updates == 0)
+    {
+      /* get the current state */
+      active = gtk_toggle_action_get_active (action);
+
+      /* store this as the last used wrap mode */
+      g_object_set (G_OBJECT (window->preferences), "view-word-wrap", active, NULL);
+
+      /* set the wrapping mode of the current document */
+      mousepad_document_set_word_wrap (window->active, active);
+    }
+}
 
-  /* get the current state */
-  word_wrap = gtk_toggle_action_get_active (action);
 
-  /* store this as the last used wrap mode */
-  g_object_set (G_OBJECT (window->preferences), "view-word-wrap", word_wrap, NULL);
 
-  /* set the wrapping mode of the current document */
-  mousepad_document_set_word_wrap (window->active, word_wrap);
+static void
+mousepad_window_action_auto_indent (GtkToggleAction *action,
+                                    MousepadWindow  *window)
+{
+  gboolean active;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
+  /* leave when menu updates are locked */
+  if (lock_menu_updates == 0)
+    {
+      /* get the current state */
+      active = gtk_toggle_action_get_active (action);
+
+      /* save as the last auto indent mode */
+      g_object_set (G_OBJECT (window->preferences), "view-auto-indent", active, NULL);
+
+      /* update the active document */
+      mousepad_view_set_auto_indent (window->active->textview, active);
+    }
 }
 
 
@@ -3179,18 +4253,17 @@ mousepad_window_action_tab_size (GtkToggleAction *action,
 {
   gboolean tab_size;
 
-  /* leave when menu updates are locked */
-  if (lock_menu_updates)
-    return;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
 
-  if (gtk_toggle_action_get_active (action))
+  /* leave when menu updates are locked */
+  if (lock_menu_updates == 0 && gtk_toggle_action_get_active (action))
     {
+      _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+
       /* get the tab size */
       tab_size = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
 
-      /* other... item clicked */
+      /* whether the other item was clicked */
       if (tab_size == 0)
         {
           /* get tab size from document */
@@ -3212,30 +4285,61 @@ mousepad_window_action_tab_size (GtkToggleAction *action,
 }
 
 
+
 static void
 mousepad_window_action_insert_spaces (GtkToggleAction *action,
                                       MousepadWindow  *window)
 {
   gboolean insert_spaces;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
 
   /* leave when menu updates are locked */
-  if (lock_menu_updates)
-    return;
+  if (lock_menu_updates == 0)
+    {
+      /* get the current state */
+      insert_spaces = gtk_toggle_action_get_active (action);
+
+      /* save as the last auto indent mode */
+      g_object_set (G_OBJECT (window->preferences), "view-insert-spaces", insert_spaces, NULL);
+
+      /* update the active document */
+      mousepad_view_set_insert_spaces (window->active->textview, insert_spaces);
+    }
+}
+
+
 
-  /* get the current state */
-  insert_spaces = gtk_toggle_action_get_active (action);
+static void
+mousepad_window_action_line_ending (GtkRadioAction *action,
+                                    GtkRadioAction *current,
+                                    MousepadWindow *window)
+{
+  MousepadLineEnding eol;
+
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+  _mousepad_return_if_fail (MOUSEPAD_IS_FILE (window->active->file));
+  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (window->active->buffer));
+
+  /* leave when menu updates are locked */
+  if (lock_menu_updates == 0)
+    {
+      /* get selected line ending */
+      eol = gtk_radio_action_get_current_value (current);
 
-  /* save as the last auto indent mode */
-  g_object_set (G_OBJECT (window->preferences), "view-insert-spaces", insert_spaces, NULL);
+      /* set the new line ending on the file */
+      mousepad_file_set_line_ending (window->active->file, eol);
 
-  /* update the active document */
-  mousepad_view_set_insert_spaces (window->active->textview, insert_spaces);
+      /* make buffer as modified to show the user the change is not saved */
+      gtk_text_buffer_set_modified (window->active->buffer, TRUE);
+    }
 }
 
 
 
+
 static void
 mousepad_window_action_prev_tab (GtkAction      *action,
                                  MousepadWindow *window)
@@ -3243,13 +4347,14 @@ mousepad_window_action_prev_tab (GtkAction      *action,
   gint page_num;
   gint n_pages;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
   /* get notebook info */
   page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
   n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
 
   /* switch to the previous tab or cycle to the last tab */
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook),
-                                 (page_num - 1) % n_pages);
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), (page_num - 1) % n_pages);
 }
 
 
@@ -3261,52 +4366,56 @@ mousepad_window_action_next_tab (GtkAction      *action,
   gint page_num;
   gint n_pages;
 
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
   /* get notebook info */
   page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
   n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
 
   /* switch to the next tab or cycle to the first tab */
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook),
-                                 (page_num + 1) % n_pages);
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), (page_num + 1) % n_pages);
 }
 
 
 
 static void
-mousepad_window_action_goto (GtkRadioAction *action,
-                             GtkNotebook    *notebook)
+mousepad_window_action_go_to_tab (GtkRadioAction *action,
+                                  GtkNotebook    *notebook)
 {
   gint page;
 
-  /* leave when the menu is locked */
-  if (lock_menu_updates)
-    return;
+  _mousepad_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+  _mousepad_return_if_fail (GTK_IS_RADIO_ACTION (action));
+  _mousepad_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
 
-  /* get the page number from the action value */
-  page = gtk_radio_action_get_current_value (action);
+  /* leave when the menu is locked or this is not the active radio button */
+  if (lock_menu_updates == 0
+      && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
+    {
+      /* get the page number from the action value */
+      page = gtk_radio_action_get_current_value (action);
 
-  /* set the page */
-  gtk_notebook_set_current_page (notebook, page);
+      /* set the page */
+      gtk_notebook_set_current_page (notebook, page);
+    }
 }
 
 
 
 static void
-mousepad_window_action_go_to_line (GtkAction      *action,
-                                   MousepadWindow *window)
+mousepad_window_action_go_to_position (GtkAction      *action,
+                                       MousepadWindow *window)
 {
-  gint current_line, last_line, line;
-
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
   _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
+  _mousepad_return_if_fail (GTK_IS_TEXT_BUFFER (window->active->buffer));
 
-  /* get the current and last line number */
-  mousepad_document_line_numbers (window->active, &current_line, &last_line);
-
-  /* run the jump to dialog and wait for the response */
-  line = mousepad_dialogs_go_to_line (GTK_WINDOW (window), current_line, last_line);
-
-  if (G_LIKELY (line > 0))
-    mousepad_document_go_to_line (window->active, line);
+  /* run jump dialog */
+  if (mousepad_dialogs_go_to (GTK_WINDOW (window), window->active->buffer))
+    {
+      /* put the cursor on screen */
+      mousepad_view_scroll_to_cursor (window->active->textview);
+    }
 }
 
 
@@ -3315,6 +4424,9 @@ static void
 mousepad_window_action_contents (GtkAction      *action,
                                  MousepadWindow *window)
 {
+  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+
+  /* show help */
   mousepad_dialogs_show_help (GTK_WINDOW (window), NULL, NULL);
 }
 
@@ -3324,40 +4436,8 @@ static void
 mousepad_window_action_about (GtkAction      *action,
                               MousepadWindow *window)
 {
-  mousepad_dialogs_show_about (GTK_WINDOW (window));
-}
-
-
-
-/**
- * Miscellaneous Actions
- **/
-static void
-mousepad_window_button_close_tab (MousepadDocument *document,
-                                  MousepadWindow   *window)
-{
-  gint page_num;
-
-  _mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (document));
   _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
 
-  /* switch to the tab we're going to close */
-  page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (document));
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page_num);
-
-  /* close the document */
-  mousepad_window_close_document (window, document);
-}
-
-
-
-static gboolean
-mousepad_window_delete_event (MousepadWindow *window,
-                              GdkEvent       *event)
-{
-  /* try to close the windows */
-  mousepad_window_action_close (NULL, window);
-
-  /* we will close the window when all the tabs are closed */
-  return TRUE;
+  /* show about dialog */
+  mousepad_dialogs_show_about (GTK_WINDOW (window));
 }
diff --git a/po/mousepad.pot b/po/mousepad.pot
index 2467193..7339f3d 100644
--- a/po/mousepad.pot
+++ b/po/mousepad.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-10-16 21:41+0200\n"
+"POT-Creation-Date: 2007-12-06 21:09+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -56,82 +56,78 @@ msgstr ""
 msgid "Mousepad is a fast text editor for the Xfce Desktop Environment."
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:47
+#: ../mousepad/mousepad-dialogs.c:51
 msgid "translator-credits"
 msgstr ""
 
+#. display an error message to the user
+#: ../mousepad/mousepad-dialogs.c:126
+msgid "Failed to open the documentation browser"
+msgstr ""
+
+#. build dialog
+#: ../mousepad/mousepad-dialogs.c:144
+msgid "Select Tab Size"
+msgstr ""
+
 #. build the dialog
-#: ../mousepad/mousepad-dialogs.c:94
-msgid "Jump To"
+#: ../mousepad/mousepad-dialogs.c:225
+msgid "Go To"
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:108
+#: ../mousepad/mousepad-dialogs.c:247
 msgid "_Line number:"
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:147
+#: ../mousepad/mousepad-dialogs.c:266
+msgid "C_olumn number:"
+msgstr ""
+
+#: ../mousepad/mousepad-dialogs.c:324
 msgid "Remove all entries from the documents history?"
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:152
+#: ../mousepad/mousepad-dialogs.c:329
 msgid "Clear Documents History"
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:155
+#: ../mousepad/mousepad-dialogs.c:332
 msgid ""
 "Clearing the documents history will permanently remove all currently listed "
 "entries."
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:189
+#: ../mousepad/mousepad-dialogs.c:366
 msgid "Do you want to save the changes before closing?"
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:192
+#: ../mousepad/mousepad-dialogs.c:369
 msgid "_Don't Save"
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:200
+#: ../mousepad/mousepad-dialogs.c:377
 msgid "Save Changes"
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:205
+#: ../mousepad/mousepad-dialogs.c:382
 msgid "If you don't save the document, all the changes will be lost."
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:229
-msgid ""
-"The file has been externally modified. Are you sure you want to save the "
-"file?"
-msgstr ""
-
-#: ../mousepad/mousepad-dialogs.c:233
-#, c-format
-msgid "If you save the file, the external changes to \"%s\" will be lost."
-msgstr ""
-
-#: ../mousepad/mousepad-dialogs.c:238
-msgid "_Overwrite"
-msgstr ""
-
-#: ../mousepad/mousepad-dialogs.c:241 ../mousepad/mousepad-dialogs.c:275
-msgid "_Reload"
-msgstr ""
-
-#: ../mousepad/mousepad-dialogs.c:266
+#: ../mousepad/mousepad-dialogs.c:405
 msgid "Do you want to save your changes before reloading?"
 msgstr ""
 
-#: ../mousepad/mousepad-dialogs.c:268
-msgid "If you reload the file, you changes will be lost."
+#: ../mousepad/mousepad-dialogs.c:407
+msgid "If you revert the file, all unsaved changes will be lost."
 msgstr ""
 
-#: ../mousepad/mousepad-document.c:567
+#. pack button, add signal and tooltip
+#: ../mousepad/mousepad-document.c:572
 msgid "Close this tab"
 msgstr ""
 
 #. create an unique untitled document name
-#: ../mousepad/mousepad-document.c:602
+#: ../mousepad/mousepad-document.c:607
 msgid "Untitled"
 msgstr ""
 
@@ -157,34 +153,73 @@ msgstr ""
 msgid "Other:"
 msgstr ""
 
-#: ../mousepad/mousepad-file.c:338
+#: ../mousepad/mousepad-file.c:352
 #, c-format
 msgid "Unknown line ending detected (%s)"
 msgstr ""
 
-#: ../mousepad/mousepad-file.c:346
+#: ../mousepad/mousepad-file.c:360
 #, c-format
 msgid "Converted string is not UTF-8 valid"
 msgstr ""
 
-#: ../mousepad/mousepad-file.c:527
+#: ../mousepad/mousepad-file.c:541
 #, c-format
 msgid "The file \"%s\" you've tried to reload does not exist anymore"
 msgstr ""
 
-#: ../mousepad/mousepad-file.c:564
+#: ../mousepad/mousepad-file.c:578
 #, c-format
 msgid "Failed to read the status of \"%s\""
 msgstr ""
 
-#: ../mousepad/mousepad-preferences.c:502
+#: ../mousepad/mousepad-preferences.c:490
 msgid "Failed to load the preferences."
 msgstr ""
 
-#: ../mousepad/mousepad-preferences.c:598
+#: ../mousepad/mousepad-preferences.c:586
 msgid "Failed to store the preferences."
 msgstr ""
 
+#. set a custom tab label
+#: ../mousepad/mousepad-print.c:163
+msgid "Document Settings"
+msgstr ""
+
+#. create page number
+#: ../mousepad/mousepad-print.c:528
+#, c-format
+msgid "Page %d of %d"
+msgstr ""
+
+#: ../mousepad/mousepad-print.c:738
+msgid "Page Setup"
+msgstr ""
+
+#: ../mousepad/mousepad-print.c:748
+msgid "_Adjust page size and orientation"
+msgstr ""
+
+#: ../mousepad/mousepad-print.c:758
+msgid "Appearance"
+msgstr ""
+
+#: ../mousepad/mousepad-print.c:772
+msgid "Print page _headers"
+msgstr ""
+
+#: ../mousepad/mousepad-print.c:778
+msgid "Print _line numbers"
+msgstr ""
+
+#: ../mousepad/mousepad-print.c:784
+msgid "Enable text _wrapping"
+msgstr ""
+
+#: ../mousepad/mousepad-print.c:795
+msgid "Font"
+msgstr ""
+
 #. set dialog properties
 #: ../mousepad/mousepad-replace-dialog.c:191
 msgid "Replace"
@@ -277,311 +312,564 @@ msgstr ""
 msgid "Mat_ch Case"
 msgstr ""
 
-#: ../mousepad/mousepad-statusbar.c:142
+#: ../mousepad/mousepad-statusbar.c:152
 msgid "Toggle the overwrite mode"
 msgstr ""
 
 #. overwrite label
-#: ../mousepad/mousepad-statusbar.c:147
+#: ../mousepad/mousepad-statusbar.c:157
 msgid "OVR"
 msgstr ""
 
-#. create printable string
-#: ../mousepad/mousepad-statusbar.c:186
+#: ../mousepad/mousepad-statusbar.c:198
 #, c-format
-msgid "Line %d Col %d"
+msgid "Line: %d Column: %d Selection: %d"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:313
+#: ../mousepad/mousepad-statusbar.c:200
+#, c-format
+msgid "Line: %d Column: %d"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:387
 msgid "_File"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:314
-msgid "New Documen_t"
+#: ../mousepad/mousepad-window.c:388
+msgid "_New"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:314
+#: ../mousepad/mousepad-window.c:388
 msgid "Create a new document"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:315
-msgid "_New Window"
+#: ../mousepad/mousepad-window.c:389
+msgid "New _Window"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:315
+#: ../mousepad/mousepad-window.c:389
 msgid "Create a new document in a new window"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:316
-msgid "_Open File"
+#: ../mousepad/mousepad-window.c:390
+msgid "New From Te_mplate"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:391
+msgid "_Open..."
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:316
+#: ../mousepad/mousepad-window.c:391
 msgid "Open a file"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:317
-msgid "Open _Recent"
+#: ../mousepad/mousepad-window.c:392
+msgid "Op_en Recent"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:318
+#: ../mousepad/mousepad-window.c:393
 msgid "No items found"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:319
+#: ../mousepad/mousepad-window.c:394
 msgid "Clear _History"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:319
+#: ../mousepad/mousepad-window.c:394
 msgid "Clear the recently used files history"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:320
-msgid "Save the current file"
+#: ../mousepad/mousepad-window.c:395
+msgid "Save the current document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:396
+msgid "Save _As..."
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:321
+#: ../mousepad/mousepad-window.c:396
 msgid "Save current document as another file"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:322
-msgid "Re_load"
+#: ../mousepad/mousepad-window.c:397
+msgid "Save A_ll"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:322
-msgid "Reload this document."
+#: ../mousepad/mousepad-window.c:397
+msgid "Save all document in this window"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:323
-msgid "Prin the current page"
+#: ../mousepad/mousepad-window.c:398
+msgid "Re_vert"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:324
+#: ../mousepad/mousepad-window.c:398
+msgid "Revert to the saved version of the file"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:399
+msgid "_Print..."
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:399
+msgid "Prin the current document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:400
 msgid "_Detach Tab"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:324
+#: ../mousepad/mousepad-window.c:400
 msgid "Move the current document to a new window"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:325
-msgid "C_lose Tab"
+#: ../mousepad/mousepad-window.c:401
+msgid "Close _Tab"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:325
-msgid "Close the current file"
+#: ../mousepad/mousepad-window.c:401
+msgid "Close the current document"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:326
+#: ../mousepad/mousepad-window.c:402
 msgid "_Close Window"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:326
-msgid "Quit the program"
+#: ../mousepad/mousepad-window.c:402
+msgid "Close this window"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:328
+#: ../mousepad/mousepad-window.c:404
 msgid "_Edit"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:329
+#: ../mousepad/mousepad-window.c:405
 msgid "Undo the last action"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:330
+#: ../mousepad/mousepad-window.c:406
 msgid "Redo the last undone action"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:331
+#: ../mousepad/mousepad-window.c:407
 msgid "Cut the selection"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:332
+#: ../mousepad/mousepad-window.c:408
 msgid "Copy the selection"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:333
+#: ../mousepad/mousepad-window.c:409
 msgid "Paste the clipboard"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:334
-msgid "Paste _Column"
+#: ../mousepad/mousepad-window.c:410
+msgid "Paste _Special"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:411
+msgid "Paste from _History"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:411
+msgid "Paste from the clipboard history"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:412
+msgid "Paste as _Column"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:412
+msgid "Paste the clipboard text into a column"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:334
-msgid "Paste the clipboard text in a clumn"
+#: ../mousepad/mousepad-window.c:413
+msgid "Delete the current selection"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:335
-msgid "Delete the selected text"
+#: ../mousepad/mousepad-window.c:414
+msgid "Select the text in the entire document"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:336
-msgid "Select the entire document"
+#: ../mousepad/mousepad-window.c:415
+msgid "Change the selection"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:338
-msgid "_Search"
+#: ../mousepad/mousepad-window.c:415
+msgid "Change a normal selection into a column selection and vice versa"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:339
+#: ../mousepad/mousepad-window.c:416
 msgid "Search for text"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:340
+#: ../mousepad/mousepad-window.c:417
 msgid "Find _Next"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:340
+#: ../mousepad/mousepad-window.c:417
 msgid "Search forwards for the same text"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:341
+#: ../mousepad/mousepad-window.c:418
 msgid "Find _Previous"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:341
+#: ../mousepad/mousepad-window.c:418
 msgid "Search backwards for the same text"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:342
-msgid "Search for and replace text"
+#: ../mousepad/mousepad-window.c:419
+msgid "Find and Rep_lace..."
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:343
-msgid "Go to a specific line"
+#: ../mousepad/mousepad-window.c:419
+msgid "Search for and replace text"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:345
+#: ../mousepad/mousepad-window.c:421
 msgid "_View"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:346
+#: ../mousepad/mousepad-window.c:422
+msgid "Select F_ont..."
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:422
 msgid "Change the editor font"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:348
+#: ../mousepad/mousepad-window.c:424
+msgid "_Text"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:425
+msgid "_Convert"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:426
+msgid "to _Uppercase"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:426
+msgid "Change the case of the selection to uppercase"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:427
+msgid "to _Lowercase"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:427
+msgid "Change the case of the selection to lowercase"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:428
+msgid "to _Title Case"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:428
+msgid "Change the case of the selection to title case"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:429
+msgid "to _Opposite Case"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:429
+msgid "Change the case of the selection opposite case"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:430
+msgid "_Tabs to Spaces"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:430
+msgid "Convert all tabs to spaces in the selection or document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:431
+msgid "_Spaces to Tabs"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:431
+msgid ""
+"Convert all the leading spaces to tabs in the selected line(s) or document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:432
+msgid "St_rip Trailing Spaces"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:432
+msgid "Remove all the trailing spaces from the selected line(s) or document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:433
+msgid "_Transpose"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:433
+msgid "Reverse the order of something"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:434
+msgid "_Move Selection"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:435
+msgid "Line _Up"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:435
+msgid "Move the selection one line up"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:436
+msgid "Line _Down"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:436
+msgid "Move the selection one line down"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:437
+msgid "D_uplicate Line / Selection"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:437
+msgid "Duplicate the current line or selection"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:438
+msgid "_Increase Indent"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:438
+msgid "Increase indent of selection or line"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:439
+msgid "_Decrease Indent"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:439
+msgid "Decrease indent of selection or line"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:441
 msgid "_Document"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:350
-msgid "_Go"
+#: ../mousepad/mousepad-window.c:442
+msgid "Tab _Size"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:351
+#: ../mousepad/mousepad-window.c:443
+msgid "Line E_nding"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:445
+msgid "_Navigation"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:446
+msgid "_Previous Tab"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:446
 msgid "Select the previous tab"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:352
+#: ../mousepad/mousepad-window.c:447
+msgid "_Next Tab"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:447
 msgid "Select the next tab"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:354
+#: ../mousepad/mousepad-window.c:448
+msgid "_Go to..."
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:448
+msgid "Go to a specific location in the document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:450
 msgid "_Help"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:355
-msgid "About this application"
+#: ../mousepad/mousepad-window.c:451
+msgid "_Contents"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:360
-msgid "_Statusbar"
+#: ../mousepad/mousepad-window.c:451
+msgid "Display the Mousepad user manual"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:360
-msgid "Change the visibility of the statusbar"
+#: ../mousepad/mousepad-window.c:452
+msgid "About this application"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:361
-msgid "_Word Wrap"
+#: ../mousepad/mousepad-window.c:457
+msgid "St_atusbar"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:361
-msgid "Toggle breaking lines in between words"
+#: ../mousepad/mousepad-window.c:457
+msgid "Change the visibility of the statusbar"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:362
-msgid "_Line Numbers"
+#: ../mousepad/mousepad-window.c:458
+msgid "Line N_umbers"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:362
+#: ../mousepad/mousepad-window.c:458
 msgid "Show line numbers"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:363
+#: ../mousepad/mousepad-window.c:459
 msgid "_Auto Indent"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:363
+#: ../mousepad/mousepad-window.c:459
 msgid "Auto indent a new line"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:364
-msgid "_Insert Spaces"
+#: ../mousepad/mousepad-window.c:460
+msgid "_Word Wrap"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:460
+msgid "Toggle breaking lines in between words"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:461
+msgid "Insert _Spaces"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:364
+#: ../mousepad/mousepad-window.c:461
 msgid "Insert spaces when the tab button is pressed"
 msgstr ""
 
+#: ../mousepad/mousepad-window.c:466
+msgid "Unix (_LF)"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:466
+msgid "Set the line ending of the document to Unix (LF)"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:467
+msgid "Mac (_CR)"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:467
+msgid "Set the line ending of the document to Mac (CR)"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:468
+msgid "DOS / Windows (C_R LF)"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:468
+msgid "Set the line ending of the document to DOS / Windows (CR LF)"
+msgstr ""
+
 #. add the label with the root warning
-#: ../mousepad/mousepad-window.c:556
+#: ../mousepad/mousepad-window.c:664
 msgid "Warning, you are using the root account, you may harm your system."
 msgstr ""
 
 #. show the warning
 #. show the warning and cleanup
-#: ../mousepad/mousepad-window.c:935 ../mousepad/mousepad-window.c:2282
+#: ../mousepad/mousepad-window.c:1058 ../mousepad/mousepad-window.c:3201
 msgid "Failed to open file"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:1122
+#: ../mousepad/mousepad-window.c:1243
 msgid "Read Only"
 msgstr ""
 
+#. create other action
+#: ../mousepad/mousepad-window.c:1883
+msgid "Set custom tab size"
+msgstr ""
+
+#. create suitable label for the other menu
+#: ../mousepad/mousepad-window.c:1931
+#, c-format
+msgid "Ot_her (%d)..."
+msgstr ""
+
+#. set action label
+#: ../mousepad/mousepad-window.c:1942
+msgid "Ot_her..."
+msgstr ""
+
 #. build description
-#. set text offset
-#: ../mousepad/mousepad-window.c:1726 ../mousepad/mousepad-window.c:2266
+#. get the offset length
+#: ../mousepad/mousepad-window.c:2242 ../mousepad/mousepad-window.c:3183
 msgid "Encoding"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:1860
+#: ../mousepad/mousepad-window.c:2372
 #, c-format
 msgid "Open '%s'"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:1970
-msgid "Failed to remove an item from the documents history"
+#: ../mousepad/mousepad-window.c:2500
+msgid "Failed to clear the recent history"
 msgstr ""
 
-#. create new chooser dialog
-#: ../mousepad/mousepad-window.c:2175
+#. create an item to inform the user
+#: ../mousepad/mousepad-window.c:2919
+msgid "No clipboard data"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:3058
+#, c-format
+msgid "The template is not UTF-8 valid"
+msgstr ""
+
+#. show an error
+#: ../mousepad/mousepad-window.c:3068
+msgid "Failed to open new file from a template"
+msgstr ""
+
+#. create new file chooser dialog
+#: ../mousepad/mousepad-window.c:3093
 msgid "Open File"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:2279
+#: ../mousepad/mousepad-window.c:3197
 #, c-format
 msgid ""
 "Failed to open \"%s\" for reading. It will be removed from the document "
 "history"
 msgstr ""
 
-#. show the warning
-#: ../mousepad/mousepad-window.c:2349
+#. show the error
+#: ../mousepad/mousepad-window.c:3271 ../mousepad/mousepad-window.c:3391
 msgid "Failed to save the document"
 msgstr ""
 
 #. create the dialog
-#: ../mousepad/mousepad-window.c:2373
+#: ../mousepad/mousepad-window.c:3295
 msgid "Save As"
 msgstr ""
 
-#. show the warning
-#: ../mousepad/mousepad-window.c:2441
+#. show the error
+#: ../mousepad/mousepad-window.c:3473
 msgid "Failed to reload the document"
 msgstr ""
 
-#: ../mousepad/mousepad-window.c:2809
+#. show the error
+#: ../mousepad/mousepad-window.c:3500
+msgid "Failed to print the document"
+msgstr ""
+
+#: ../mousepad/mousepad-window.c:3901
 msgid "Choose Mousepad Font"
 msgstr ""
 


More information about the Xfce4-commits mailing list