diff --git a/src/Text/Layout/Table.hs b/src/Text/Layout/Table.hs
--- a/src/Text/Layout/Table.hs
+++ b/src/Text/Layout/Table.hs
@@ -4,7 +4,7 @@
 -- text and fancy tables with styling support.
 --
 -- == Some examples
--- Layouting text as a plain grid:
+-- Layouting text as a plain grid (given a list of rows):
 --
 -- >>> putStrLn $ layoutToString [["a", "b"], ["c", "d"]] (repeat def)
 -- a b
@@ -12,7 +12,7 @@
 --
 -- Fancy table without header:
 --
--- >>> putStrLn $ layoutTableToString [rowGroup [["Jack", "184.74"]], rowGroup [["Jane", "162.2"]]] Nothing [def , numL] unicodeRoundS
+-- >>> putStrLn $ layoutTableToString [rowGroup [["Jack", "184.74"]], rowGroup [["Jane", "162.2"]]] def [def , numCol] unicodeRoundS
 -- ╭──────┬────────╮
 -- │ Jack │ 184.74 │
 -- ├──────┼────────┤
@@ -25,12 +25,7 @@
 --                                    , rowGroup [["Short text", "100200.5"]]
 --                                    ]
 --                                    (Just (["Title", "Length"], repeat def))
---                                    [ fixedLeftL 20
---                                    , ColSpec (fixed 10)
---                                                 center
---                                                 dotAlign
---                                                 ellipsisCutMark
---                                    ]
+--                                    [fixedLeftCol 20, column (fixed 10) center dotAlign ellipsisCutMark]
 --                                    unicodeRoundS
 -- ╭──────────────────────┬────────────╮
 -- │        Title         │   Length   │
@@ -43,36 +38,42 @@
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE MultiWayIf #-}
 module Text.Layout.Table
-    ( -- * Layout types and combinators
-      -- $layout
-      ColSpec
+    ( -- * Layout combinators
+      -- | Specify how a column is rendered with the combinators in this
+      -- section. Sensible default values are provided with 'def'.
+
+      module Data.Default.Class
+
+      -- ** Columns
+    , ColSpec
     , column
     , numCol
     , fixedCol
     , fixedLeftCol
+      -- ** Length of columns
     , LenSpec
     , expand
     , fixed
     , expandUntil
     , fixedUntil
+      -- ** Positional alignment
     , Position
     , H
     , left
     , right
     , center
+      -- ** Alignment of cells at characters
     , AlignSpec
     , noAlign
     , charAlign
     , predAlign
     , dotAlign
-    , isAligned
-    , OccSpec
-    , CutMarkSpec
-    , ellipsisCutMark
+      -- ** Cut marks
+    , CutMark
     , noCutMark
     , singleCutMark
-    , cutMark
-    , module Data.Default.Class
+    , doubleCutMark
+    , ellipsisCutMark
 
       -- * Basic grid and table layout
     , layoutToCells
@@ -112,6 +113,7 @@
     , alignFixed
 
       -- * Column modifaction primitives
+      -- | Render your own kind of tables with the following functions.
     , ColModInfo
     , widthCMI
     , unalignedCMI
@@ -122,6 +124,7 @@
     , widthAI
     , deriveColModInfos
     , deriveAlignInfo
+    , OccSpec
     ) where
 
 -- TODO AlignSpec:   multiple alignment points - useful?
@@ -129,7 +132,7 @@
 -- TODO RowGroup:    optional: provide extra layout for a RowGroup
 -- TODO ColModInfo:  provide a special version of ensureWidthOfCMI to force header visibility
 -- TODO ColSpec:     add some kind of combinator to construct ColSpec values (e.g. via Monoid, see optparse-applicative)
--- TODO OccSpec:     expose smart constructors
+-- TODO              move functions not related to direct end-user into Primitives
 
 import qualified Control.Arrow as A
 import           Data.List
@@ -138,73 +141,30 @@
 
 import           Text.Layout.Table.Justify
 import           Text.Layout.Table.Style
-import           Text.Layout.Table.Position
+import           Text.Layout.Table.Position.Internal
+import           Text.Layout.Table.Primitives.AlignSpec.Internal
 import           Text.Layout.Table.Primitives.Basic
+import           Text.Layout.Table.Primitives.Column
+import           Text.Layout.Table.Primitives.LenSpec.Internal
+import           Text.Layout.Table.Primitives.Occurence
 import           Text.Layout.Table.Internal
 
 -------------------------------------------------------------------------------
 -- Layout types and combinators
 -------------------------------------------------------------------------------
-{- $layout
-    Specify the layout of columns.
--}
 
-column :: LenSpec -> Position H -> AlignSpec -> CutMarkSpec -> ColSpec
-column = ColSpec
-
-instance Default ColSpec where
-    def = column def def def def
-
--- | Allows columns to use as much space as needed.
-expand :: LenSpec
-expand = Expand
-
--- | Fixes column length to a specific width.
-fixed :: Int -> LenSpec
-fixed = Fixed
-
--- | The column will expand as long as it is smaller as the given width.
-expandUntil :: Int -> LenSpec
-expandUntil = ExpandUntil
-
--- | The column will be at least as wide as the given width.
-fixedUntil :: Int -> LenSpec
-fixedUntil = FixedUntil
-
--- | Don't align text.
-noAlign :: AlignSpec
-noAlign = NoAlign
-
-predAlign :: (Char -> Bool) -> AlignSpec
-predAlign p = AlignPred $ OccSpec p 0
-
-charAlign :: Char -> AlignSpec
-charAlign = predAlign . (==)
-
--- | Align all text at the first dot from left.
+-- | Align all text at the first dot from the left. This is most useful for
+-- floating point numbers.
 dotAlign :: AlignSpec
 dotAlign = charAlign '.'
 
-isAligned :: AlignSpec -> Bool
-isAligned as = case as of
-    NoAlign -> False
-    _       -> True
-
--- | No alignment is the default.
-instance Default AlignSpec where
-    def = noAlign
-
-instance Default LenSpec where
-    def = Expand
-
-
 -- | Numbers are positioned on the right and aligned on the floating point dot.
 numCol :: ColSpec
-numCol = ColSpec def right dotAlign def
+numCol = column def right dotAlign def
 
 -- | Fixes the column length and positions according to the given 'Position'.
 fixedCol :: Int -> Position H -> ColSpec
-fixedCol l pS = ColSpec (Fixed l) pS def def
+fixedCol l pS = column (Fixed l) pS def def
 
 -- | Fixes the column length and positions on the left.
 fixedLeftCol :: Int -> ColSpec
@@ -233,7 +193,7 @@
 -- >>> trimOrPad left (singleCutMark "..") 10 "A longer text."
 -- "A longer.."
 --
-trimOrPad :: Position o -> CutMarkSpec -> Int -> String -> String
+trimOrPad :: Position o -> CutMark -> Int -> String -> String
 trimOrPad p = case p of
     Start  -> fitRightWith
     Center -> fitCenterWith
@@ -256,50 +216,112 @@
 
 -- | Aligns a column using a fixed width, fitting it to the width by either
 -- filling or cutting while respecting the alignment.
-alignFixed :: Position o -> CutMarkSpec -> Int -> OccSpec -> AlignInfo -> String -> String
+alignFixed :: Position o -> CutMark -> Int -> OccSpec -> AlignInfo -> String -> String
 alignFixed _ cms 0 _  _                  _               = ""
 alignFixed _ cms 1 _  _                  s@(_ : (_ : _)) = applyMarkLeftWith cms " "
 alignFixed p cms i oS ai@(AlignInfo l r) s               =
     let n = l + r - i
-    in if n <= 0
-       then pad p i $ align oS ai s
-       else case splitAtOcc oS s of
+    in case splitAtOcc oS s of
         (ls, rs) -> case p of
             Start  ->
                 let remRight = r - n
                 in if remRight < 0
                    then fitRight (l + remRight) $ fillLeft l ls
-                   else fillLeft l ls ++ fitRight remRight rs
+                   else fitRight (l + remRight) $ fillLeft l ls ++ rs
             End    ->
                 let remLeft = l - n
                 in if remLeft < 0
                    then fitLeft (r + remLeft) $ fillRight r rs
-                   else fitLeft remLeft ls ++ fillRight r rs
+                   else fitLeft (r + remLeft) $ ls ++ fillRight r rs
             Center ->
-                let (q, rem) = n `divMod` 2
-                    remLeft  = l - q
-                    remRight = r - q - rem
-                in if | remLeft < 0   -> fitLeft (remRight + remLeft) $ fitRight remRight rs
-                      | remRight < 0  -> fitRight (remLeft + remRight) $ fitLeft remLeft ls
-                      | remLeft == 0  -> applyMarkLeftWith cms $ fitRight remRight rs
-                      | remRight == 0 -> applyMarkRight $ fitLeft remLeft ls
-                      | otherwise     -> fitRight (remRight + remLeft) $ fitLeft remLeft ls ++ rs
+                {-
+                   This is really complicated, maybe there can be found
+                   something better.
+                  
+                   First case l > r:
+                  
+                         l
+                   |<----'----->|
+                   |<-----------x----->|
+                                |--.-->|
+                                    r
+                        c1 = (l + r) div 2
+                        |
+                   |<---'--->|<---.--->|
+                             .    |
+                             .    c2 = c1 + (l + r) mod 2
+                             .
+                             .  d2 = d1 + i mod 2
+                             .  |
+                       |<-.->|<-'-->|
+                          |
+                          d1 = i div 2
+                  
+                       |<----.----->|
+                             i
+                                 
+                   needed length on the left side:
+                       l - c1 + d1
+                  
+                   needed length on the right side:
+                       d2 - (l - c1)
+                  
+                   Second case l < r:
+                   
+                  
+                       l
+                   |<--'-->|
+                   |<------x---------->|
+                           |<----.---->|
+                                 r
+                        c1 = (l + r) div 2
+                        |
+                   |<---'--->|<---.--->|
+                             .    |
+                             .    c2 = c1 + (l + r) mod 2
+                             .
+                             .  d2 = d1 + i mod 2
+                             .  |
+                       |<-.->|<-'-->|
+                          |
+                          d1 = i div 2
+                  
+                       |<----.----->|
+                             i
+                                 
+                   needed length on the left side:
+                       d1 - (r - c2)
+                  
+                   needed length on the right side:
+                       (c1 - l) + d2
+                -}
+                let (c, remC)        = (l + r) `divMod` 2
+                    (d, remD)        = i `divMod` 2
+                    d2               = d + remD
+                    c2               = c + remC
+                    -- Note: widthL and widthR can be negative if there is no
+                    -- width left and we need to further trim into the other
+                    -- side.
+                    (widthL, widthR) = if l > c
+                                       then (l - c2 + d, d2 - (l - c2))
+                                       else (d - (r - c), (c2 - l) + d2)
+                    lenL             = length ls
+                    lenR             = length rs
+
+                    toCutLfromR      = negate $ min 0 widthL
+                    toCutRfromL      = max 0 $ negate widthR
+                    (markL, funL)    = if lenL > widthL
+                                       then (applyMarkLeftWith cms, take (widthL - toCutRfromL) . drop (lenL - widthL))
+                                       else (id                   , fillLeft (widthL - toCutRfromL) . take (lenL - toCutRfromL))
+                    (markR, funR)    = if lenR > widthR
+                                       then (applyMarkRight, take widthR)
+                                       else (id            , fillRight widthR)
+                in markL $ markR $ funL ls ++ drop toCutLfromR (funR rs)
   where
     fitRight       = fitRightWith cms
     fitLeft        = fitLeftWith cms
     applyMarkRight = applyMarkRightWith cms
 
-splitAtOcc :: OccSpec -> String -> (String, String)
-splitAtOcc (OccSpec p occ) = A.first reverse . go 0 []
-  where
-    go n ls xs = case xs of
-        []      -> (ls, [])
-        x : xs' -> if p x
-                   then if n == occ
-                        then (ls, xs)
-                        else go (succ n) (x : ls) xs'
-                   else go n (x : ls) xs'
-
 -- | Specifies how a column should be modified.
 data ColModInfo = FillAligned OccSpec AlignInfo
                 | FillTo Int
@@ -341,12 +363,12 @@
 ensureWidthOfCMI = ensureWidthCMI . length
 
 -- | Generates a function which modifies a given 'String' according to
--- 'Position H', 'CutMarkSpec' and 'ColModInfo'.
-columnModifier :: Position H -> CutMarkSpec -> ColModInfo -> (String -> String)
+-- 'Text.Layout.Table.Position.Position', 'CutMark' and 'ColModInfo'.
+columnModifier :: Position H -> CutMark -> ColModInfo -> (String -> String)
 columnModifier pos cms lenInfo = case lenInfo of
     FillAligned oS ai -> align oS ai
     FillTo maxLen     -> pad pos maxLen
-    FitTo lim mT  ->
+    FitTo lim mT      ->
         maybe (trimOrPad pos cms lim) (uncurry $ alignFixed pos cms lim) mT
 
 -- TODO factor out
@@ -369,27 +391,27 @@
 deriveColModInfos specs = zipWith ($) (fmap fSel specs) . transpose
   where
     fSel (lenSpec, alignSpec) = case alignSpec of
-        NoAlign        -> let fitTo i             = const $ FitTo i Nothing
-                              expandUntil f i max = if f (max <= i)
-                                                    then FillTo max
-                                                    else fitTo i max
-                              fun                 = case lenSpec of
-                                  Expand        -> FillTo
-                                  Fixed i       -> fitTo i
-                                  ExpandUntil i -> expandUntil id i
-                                  FixedUntil i  -> expandUntil not i
-                          in fun . maximum . map length
-        AlignPred oS -> let fitToAligned i     = FitTo i . Just . (,) oS
-                            fillAligned        = FillAligned oS
-                            expandUntil f i ai = if f (widthAI ai <= i)
-                                                 then fillAligned ai
-                                                 else fitToAligned i ai
-                            fun                = case lenSpec of
-                                Expand        -> fillAligned
-                                Fixed i       -> fitToAligned i
-                                ExpandUntil i -> expandUntil id i
-                                FixedUntil i  -> expandUntil not i
-                         in fun . foldMap (deriveAlignInfo oS)
+        NoAlign     -> let fitTo i             = const $ FitTo i Nothing
+                           expandUntil f i max = if f (max <= i)
+                                                 then FillTo max
+                                                 else fitTo i max
+                           fun                 = case lenSpec of
+                               Expand        -> FillTo
+                               Fixed i       -> fitTo i
+                               ExpandUntil i -> expandUntil id i
+                               FixedUntil i  -> expandUntil not i
+                       in fun . maximum . map length
+        AlignOcc oS -> let fitToAligned i     = FitTo i . Just . (,) oS
+                           fillAligned        = FillAligned oS
+                           expandUntil f i ai = if f (widthAI ai <= i)
+                                                then fillAligned ai
+                                                else fitToAligned i ai
+                           fun                = case lenSpec of
+                               Expand        -> fillAligned
+                               Fixed i       -> fitToAligned i
+                               ExpandUntil i -> expandUntil id i
+                               FixedUntil i  -> expandUntil not i
+                        in fun . foldMap (deriveAlignInfo oS)
 
 
 -- | Generate the 'AlignInfo' of a cell using the 'OccSpec'.
@@ -404,16 +426,16 @@
 layoutToCells :: [[String]] -> [ColSpec] -> [[String]]
 layoutToCells tab specs = zipWith apply tab
                         . repeat
-                        . zipWith (uncurry columnModifier) (map (position A.&&& cutMarkSpec) specs)
+                        . zipWith (uncurry columnModifier) (map (position A.&&& cutMark) specs)
                         $ deriveColModInfos (map (lenSpec A.&&& alignSpec) specs) tab
   where
     apply = zipWith $ flip ($)
 
--- | Behaves like 'layoutCells' but produces lines by joining with whitespace.
+-- | Behaves like 'layoutToCells' but produces lines by joining with whitespace.
 layoutToLines :: [[String]] -> [ColSpec] -> [String]
 layoutToLines tab specs = map unwords $ layoutToCells tab specs
 
--- | Behaves like 'layoutCells' but produces a 'String' by joining with the
+-- | Behaves like 'layoutToCells' but produces a 'String' by joining with the
 -- newline character.
 layoutToString :: [[String]] -> [ColSpec] -> String
 layoutToString tab specs = intercalate "\n" $ layoutToLines tab specs
@@ -445,7 +467,7 @@
 instance Default HeaderColSpec where
     def = headerColumn center Nothing
 
-headerColumn :: Position H -> Maybe CutMarkSpec -> HeaderColSpec
+headerColumn :: Position H -> Maybe CutMark -> HeaderColSpec
 headerColumn = HeaderColSpec
 
 -- | Layouts a good-looking table with a optional header. Note that specifying
@@ -479,8 +501,8 @@
     (addHeaderLines, fitHeaderIntoCMIs, realTopH, realTopL, realTopC, realTopR) = case optHeaderInfo of
         Just (h, headerColSpecs) ->
             let headerLine    = vLine ' ' headerV (zipApply h headerRowMods)
-                headerRowMods = zipWith3 (\(HeaderColSpec pos optCutMarkSpec) cutMarkSpec ->
-                                              columnModifier pos $ fromMaybe cutMarkSpec optCutMarkSpec
+                headerRowMods = zipWith3 (\(HeaderColSpec pos optCutMark) cutMark ->
+                                              columnModifier pos $ fromMaybe cutMark optCutMark
                                          )
                                          headerColSpecs
                                          cMSs
@@ -502,7 +524,7 @@
             , groupTopR
             )
 
-    cMSs             = map cutMarkSpec specs
+    cMSs             = map cutMark specs
     posSpecs         = map position specs
     applyRowMods xss = zipWith zipApply xss $ repeat rowMods
     rowMods          = zipWith3 columnModifier posSpecs cMSs cMIs
diff --git a/src/Text/Layout/Table/Internal.hs b/src/Text/Layout/Table/Internal.hs
--- a/src/Text/Layout/Table/Internal.hs
+++ b/src/Text/Layout/Table/Internal.hs
@@ -1,30 +1,16 @@
 module Text.Layout.Table.Internal where
 
+import Data.Default.Class
+
 import Text.Layout.Table.Position
 import Text.Layout.Table.Primitives.Basic
 
--- | Specifies the layout of a column.
-data ColSpec = ColSpec
-             { lenSpec     :: LenSpec
-             , position    :: Position H
-             , alignSpec   :: AlignSpec
-             , cutMarkSpec :: CutMarkSpec
-             }
-
--- | Determines how long a column will be.
-data LenSpec = Expand | Fixed Int | ExpandUntil Int | FixedUntil Int
-
--- | Determines whether a column will align at a specific letter.
-data AlignSpec = AlignPred OccSpec | NoAlign
-
--- | Specifies an occurence of a letter.
-data OccSpec = OccSpec (Char -> Bool) Int
-
 -- | Groups rows together, which are not seperated from each other.
 data RowGroup = RowGroup
               { rows     :: [[String]] 
               }
 
 -- | Specifies how a header is layout, by omitting the cut mark it will use the
--- one specified in the 'ColSpec' like the other cells in that column.
-data HeaderColSpec = HeaderColSpec (Position H) (Maybe CutMarkSpec)
+-- one specified in the 'Text.Layout.Primitives.Column.ColSpec' like the other
+-- cells in that column.
+data HeaderColSpec = HeaderColSpec (Position H) (Maybe CutMark)
diff --git a/src/Text/Layout/Table/Justify.hs b/src/Text/Layout/Table/Justify.hs
--- a/src/Text/Layout/Table/Justify.hs
+++ b/src/Text/Layout/Table/Justify.hs
@@ -18,7 +18,7 @@
 import Data.List
 
 import Text.Layout.Table.Primitives.Basic
-import Text.Layout.Table.Position
+import Text.Layout.Table.Position.Internal
 
 -- | Justifies texts and presents the resulting lines in a grid structure (each
 -- text in one column).
@@ -37,6 +37,8 @@
 >>> columnsAsGrid top [justifyText 10 "This text will not fit on one line.", ["42", "23"]]
 [["This  text","42"],["will   not","23"],["fit on one",""],["line.",""]]
 
+The result is intended to be used with 'Text.Layout.Table.layoutToCells' or with
+'Text.Layout.Table.rowGroup'.
 -}
 columnsAsGrid :: Position V -> [[[a]]] -> [[[a]]]
 columnsAsGrid vPos = transpose . vpadCols vPos []
diff --git a/src/Text/Layout/Table/Position.hs b/src/Text/Layout/Table/Position.hs
--- a/src/Text/Layout/Table/Position.hs
+++ b/src/Text/Layout/Table/Position.hs
@@ -1,31 +1,13 @@
 {-# LANGUAGE PatternSynonyms #-}
-module Text.Layout.Table.Position where
-
-import Data.Default.Class
-
--- | Specifies a position relative from a beginning.
-data Position orientation = Start | Center | End deriving Show
-
-instance Default (Position o) where
-    def = Start
-
--- | Horizontal orientation.
-data H
-
--- | Vertical orientation
-data V
-
-left :: Position H
-left = Start
-
-right :: Position H
-right = End
-
-center :: Position o
-center = Center
-
-top :: Position V
-top = Start
+module Text.Layout.Table.Position
+    ( Position
+    , H
+    , V
+    , left
+    , right
+    , center
+    , top
+    , bottom
+    ) where
 
-bottom :: Position V
-bottom = End
+import Text.Layout.Table.Position.Internal
diff --git a/src/Text/Layout/Table/Position/Internal.hs b/src/Text/Layout/Table/Position/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Layout/Table/Position/Internal.hs
@@ -0,0 +1,30 @@
+module Text.Layout.Table.Position.Internal where
+
+import Data.Default.Class
+
+-- | Specifies a position relative from a beginning.
+data Position orientation = Start | Center | End deriving Show
+
+instance Default (Position o) where
+    def = Start
+
+-- | Horizontal orientation.
+data H
+
+-- | Vertical orientation
+data V
+
+left :: Position H
+left = Start
+
+right :: Position H
+right = End
+
+center :: Position orientation
+center = Center
+
+top :: Position V
+top = Start
+
+bottom :: Position V
+bottom = End
diff --git a/src/Text/Layout/Table/Primitives/AlignSpec.hs b/src/Text/Layout/Table/Primitives/AlignSpec.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Layout/Table/Primitives/AlignSpec.hs
@@ -0,0 +1,9 @@
+module Text.Layout.Table.Primitives.AlignSpec
+    ( AlignSpec
+    , noAlign
+    , occSpecAlign
+    , predAlign
+    , charAlign
+    ) where
+
+import Text.Layout.Table.Primitives.AlignSpec.Internal
diff --git a/src/Text/Layout/Table/Primitives/AlignSpec/Internal.hs b/src/Text/Layout/Table/Primitives/AlignSpec/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Layout/Table/Primitives/AlignSpec/Internal.hs
@@ -0,0 +1,34 @@
+module Text.Layout.Table.Primitives.AlignSpec.Internal
+    ( AlignSpec(..)
+    , noAlign
+    , occSpecAlign
+    , predAlign
+    , charAlign
+    ) where
+
+import Data.Default.Class
+
+import Text.Layout.Table.Primitives.Occurence
+
+-- | Determines whether a column will align at a specific letter.
+data AlignSpec = AlignOcc OccSpec | NoAlign
+
+-- | No alignment is the default.
+instance Default AlignSpec where
+    def = noAlign
+
+-- | Don't align text.
+noAlign :: AlignSpec
+noAlign = NoAlign
+
+-- | Construct an 'AlignSpec' by giving an occurence specification.
+occSpecAlign :: OccSpec -> AlignSpec
+occSpecAlign = AlignOcc
+
+-- | Align at the first match of a predicate.
+predAlign :: (Char -> Bool) -> AlignSpec
+predAlign = occSpecAlign . predOccSpec
+
+-- | Align text at the first occurence of a given 'Char'.
+charAlign :: Char -> AlignSpec
+charAlign = predAlign . (==)
diff --git a/src/Text/Layout/Table/Primitives/Basic.hs b/src/Text/Layout/Table/Primitives/Basic.hs
--- a/src/Text/Layout/Table/Primitives/Basic.hs
+++ b/src/Text/Layout/Table/Primitives/Basic.hs
@@ -2,26 +2,31 @@
 -- filled or fitted to a specific length.
 module Text.Layout.Table.Primitives.Basic
     ( -- * Cut marks
-      CutMarkSpec
-    , cutMark
+      CutMark
+    , doubleCutMark
     , singleCutMark
     , noCutMark
     , ellipsisCutMark
 
       -- * String-related tools
     , spaces
+
+      -- ** Filling
     , fillLeft'
     , fillLeft
     , fillRight
     , fillCenter'
     , fillCenter
+      -- ** Fitting
     , fitRightWith
     , fitLeftWith
     , fitCenterWith
+      -- ** Applying cut marks
     , applyMarkLeftWith
     , applyMarkRightWith
 
       -- * List-related tools
+      -- ** Filling
     , fillStart'
     , fillStart
     , fillEnd
@@ -34,31 +39,29 @@
 
 -- | Specifies how the place looks where a 'String' has been cut. Note that the
 -- cut mark may be cut itself, to fit into a column.
-data CutMarkSpec = CutMarkSpec
+data CutMark = CutMark
                  { leftMark  :: String
                  , rightMark :: String
                  }
 
-instance Default CutMarkSpec where
+instance Default CutMark where
     def = ellipsisCutMark
 
-instance Show CutMarkSpec where
-    show (CutMarkSpec l r) = "cutMark " ++ show l ++ ' ' : show (reverse r)
-
--- | Display custom characters on a cut.
-cutMark :: String -> String -> CutMarkSpec
-cutMark l r = CutMarkSpec l (reverse r)
+-- | Specify two different cut marks, one for cuts on the left and one for cuts
+-- on the right.
+doubleCutMark :: String -> String -> CutMark
+doubleCutMark l r = CutMark l (reverse r)
 
--- | Use the same cut mark for left and right.
-singleCutMark :: String -> CutMarkSpec
-singleCutMark l = cutMark l (reverse l)
+-- | Use the cut mark on both sides by reversing it on the other.
+singleCutMark :: String -> CutMark
+singleCutMark l = doubleCutMark l (reverse l)
 
--- | Don't use a cut mark.
-noCutMark :: CutMarkSpec
+-- | Don't show any cut mark when text is cut.
+noCutMark :: CutMark
 noCutMark = singleCutMark ""
 
 -- | A single unicode character showing three dots is used as cut mark.
-ellipsisCutMark :: CutMarkSpec
+ellipsisCutMark :: CutMark
 ellipsisCutMark = singleCutMark "…"
 
 spaces :: Int -> String
@@ -104,7 +107,7 @@
 fillCenter = fillBoth ' '
 
 -- | Fits to the given length by either trimming or filling it to the right.
-fitRightWith :: CutMarkSpec -> Int -> String -> String
+fitRightWith :: CutMark -> Int -> String -> String
 fitRightWith cms i s =
     if length s <= i
     then fillRight i s
@@ -112,7 +115,7 @@
          --take i $ take (i - mLen) s ++ take mLen m
 
 -- | Fits to the given length by either trimming or filling it to the right.
-fitLeftWith :: CutMarkSpec -> Int -> String -> String
+fitLeftWith :: CutMark -> Int -> String -> String
 fitLeftWith cms i s =
     if lenS <= i
     then fillLeft' i lenS s
@@ -122,7 +125,7 @@
 
 -- | Fits to the given length by either trimming or filling it on both sides,
 -- but when only 1 character should be trimmed it will trim left.
-fitCenterWith :: CutMarkSpec -> Int -> String -> String
+fitCenterWith :: CutMark -> Int -> String -> String
 fitCenterWith cms i s             = 
     if diff >= 0
     then fillCenter' i lenS s
@@ -135,12 +138,12 @@
     halfLenS   = lenS `div` 2
     (halfI, r) = i `divMod` 2
 
--- | Applies a 'CutMarkSpec' to the left of a 'String', while preserving the length.
-applyMarkLeftWith :: CutMarkSpec -> String -> String
+-- | Applies a 'CutMark' to the left of a 'String', while preserving the length.
+applyMarkLeftWith :: CutMark -> String -> String
 applyMarkLeftWith cms = applyMarkLeftBy leftMark cms
 
--- | Applies a 'CutMarkSpec' to the right of a 'String', while preserving the length.
-applyMarkRightWith :: CutMarkSpec -> String -> String
+-- | Applies a 'CutMark' to the right of a 'String', while preserving the length.
+applyMarkRightWith :: CutMark -> String -> String
 applyMarkRightWith cms = reverse . applyMarkLeftBy rightMark cms . reverse
 
 applyMarkLeftBy :: (a -> String) -> a -> String -> String
diff --git a/src/Text/Layout/Table/Primitives/Column.hs b/src/Text/Layout/Table/Primitives/Column.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Layout/Table/Primitives/Column.hs
@@ -0,0 +1,31 @@
+module Text.Layout.Table.Primitives.Column
+    ( ColSpec
+    , lenSpec
+    , position
+    , alignSpec
+    , cutMark
+    , column
+    ) where
+
+import Data.Default.Class
+
+import Text.Layout.Table.Position
+import Text.Layout.Table.Primitives.AlignSpec
+import Text.Layout.Table.Primitives.Basic
+import Text.Layout.Table.Primitives.LenSpec
+
+
+-- | Specifies the layout of a column.
+data ColSpec = ColSpec
+             { lenSpec     :: LenSpec
+             , position    :: Position H
+             , alignSpec   :: AlignSpec
+             , cutMark     :: CutMark
+             }
+
+instance Default ColSpec where
+    def = column def def def def
+
+-- | Smart constructor to specify a column.
+column :: LenSpec -> Position H -> AlignSpec -> CutMark -> ColSpec
+column = ColSpec
diff --git a/src/Text/Layout/Table/Primitives/LenSpec.hs b/src/Text/Layout/Table/Primitives/LenSpec.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Layout/Table/Primitives/LenSpec.hs
@@ -0,0 +1,9 @@
+module Text.Layout.Table.Primitives.LenSpec
+    ( LenSpec
+    , expand
+    , fixed
+    , expandUntil
+    , fixedUntil
+    ) where
+
+import Text.Layout.Table.Primitives.LenSpec.Internal
diff --git a/src/Text/Layout/Table/Primitives/LenSpec/Internal.hs b/src/Text/Layout/Table/Primitives/LenSpec/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Layout/Table/Primitives/LenSpec/Internal.hs
@@ -0,0 +1,31 @@
+module Text.Layout.Table.Primitives.LenSpec.Internal
+    ( LenSpec (..)
+    , expand
+    , fixed
+    , expandUntil
+    , fixedUntil
+    ) where
+
+import Data.Default.Class
+
+-- | Determines how long a column will be.
+data LenSpec = Expand | Fixed Int | ExpandUntil Int | FixedUntil Int
+
+instance Default LenSpec where
+    def = expand
+
+-- | Allows columns to use as much space as needed.
+expand :: LenSpec
+expand = Expand
+
+-- | Fixes column length to a specific width.
+fixed :: Int -> LenSpec
+fixed = Fixed
+
+-- | The column will expand as long as it is smaller as the given width.
+expandUntil :: Int -> LenSpec
+expandUntil = ExpandUntil
+
+-- | The column will be at least as wide as the given width.
+fixedUntil :: Int -> LenSpec
+fixedUntil = FixedUntil
diff --git a/src/Text/Layout/Table/Primitives/Occurence.hs b/src/Text/Layout/Table/Primitives/Occurence.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Layout/Table/Primitives/Occurence.hs
@@ -0,0 +1,26 @@
+module Text.Layout.Table.Primitives.Occurence
+    ( OccSpec
+    , predOccSpec
+    , splitAtOcc
+    ) where
+
+import Control.Arrow
+
+-- | Specifies an occurence of a letter.
+data OccSpec = OccSpec (Char -> Bool) Int
+
+-- | Construct an occurence specification by using a predicate.
+predOccSpec :: (Char -> Bool) -> OccSpec
+predOccSpec p = OccSpec p 0
+
+-- | Use an occurence specification to split a 'String'.
+splitAtOcc :: OccSpec -> String -> (String, String)
+splitAtOcc (OccSpec p occ) = first reverse . go 0 []
+  where
+    go n ls xs = case xs of
+        []      -> (ls, [])
+        x : xs' -> if p x
+                   then if n == occ
+                        then (ls, xs)
+                        else go (succ n) (x : ls) xs'
+                   else go n (x : ls) xs'
diff --git a/table-layout.cabal b/table-layout.cabal
--- a/table-layout.cabal
+++ b/table-layout.cabal
@@ -6,7 +6,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.4.0.1
+version:             0.5.0.0
 
 synopsis:            Layout text as grid or table.
 
@@ -51,17 +51,28 @@
 
 
 library
-  -- Modules exported by the library.
-  exposed-modules:     Text.Layout.Table, Text.Layout.Table.Justify, Text.Layout.Table.Style, Text.Layout.Table.Position, Text.Layout.Table.Primitives.Basic, Text.Layout.Table.Internal
+  exposed-modules:     Text.Layout.Table,
+                       Text.Layout.Table.Justify,
+                       Text.Layout.Table.Style,
+                       Text.Layout.Table.Position, 
+                       Text.Layout.Table.Primitives.Basic, 
+                       Text.Layout.Table.Primitives.AlignSpec, 
+                       Text.Layout.Table.Primitives.Column,
+                       Text.Layout.Table.Primitives.LenSpec,
+                       Text.Layout.Table.Primitives.Occurence,
+                       Text.Layout.Table.Internal
   
-  -- Modules included in this library but not exported.
-  -- other-modules:       
+  other-modules:       
+                       Text.Layout.Table.Primitives.AlignSpec.Internal,
+                       Text.Layout.Table.Primitives.LenSpec.Internal,
+                       Text.Layout.Table.Position.Internal
+
   
   -- LANGUAGE extensions used by modules in this package.
   other-extensions:    RecordWildCards, MultiWayIf
   
   -- Other library packages from which modules are imported.
-  build-depends:       base >=4.8 && <4.9, data-default-class ==0.0.1
+  build-depends:       base >=4.8 && <4.9, data-default-class >=0.0.1 && < 0.1
   
   -- Directories containing source files.
   hs-source-dirs:      src
@@ -71,7 +82,22 @@
 
 executable table-layout-test-styles
   main-is:             Test.hs
-  build-depends:       base >=4.8 && <4.9, data-default-class ==0.0.1
+  build-depends:       base >=4.8 && <4.9, data-default-class >=0.0.1 && < 0.1
   hs-source-dirs:      src
   other-modules:       Text.Layout.Table
+  default-language:    Haskell2010
+
+test-suite table-layout-tests
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test-suite, src
+  main-is:             Spec.hs
+  build-depends:       base,
+                       --Cabal,
+                       QuickCheck >=2.8 && < 2.9,
+                       HUnit ==1.3.*,
+                       data-default-class >=0.0.1 && < 0.1,
+                       hspec
+
+  other-modules:       Text.Layout.Table, Text.Layout.Table.Primitives.Basic
+
   default-language:    Haskell2010
diff --git a/test-suite/Spec.hs b/test-suite/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test-suite/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
