diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,10 +1,83 @@
-User-visible changes in hledger (see also hledger-lib):
+User-visible changes in hledger and hledger-lib.
 
+
+0.25 (2015/4/7)
+
+- GHC 7.10 compatibility (#239)
+
+- build with terminfo support on POSIX systems by default
+    
+    On non-windows systems, we now build with terminfo support by
+    default, useful for detecting terminal width and other things.
+
+    This requires the C curses dev libaries, which makes POSIX
+    installation slightly harder; if it causes problems you can
+    disable terminfo support with the new `curses` cabal flag, eg:
+    cabal install -f-curses ... (or cabal might try this
+    automatically, I'm not sure).
+
+- register: use the full terminal width, respect COLUMNS, allow column width adjustment
+    
+    On POSIX systems, register now uses the full terminal width by
+    default. Specifically, the output width is set from:
+    
+    1. a --width option
+    2. or a COLUMNS environment variable (NB: not the same as a bash shell var)
+    3. or on POSIX (non-windows) systems, the current terminal width
+    4. or the default, 80 characters.
+    
+    Also, register's --width option now accepts an optional
+    description column width following the overall width (--width
+    WIDTH[,DESCWIDTH]). This also sets the account column width, since
+    the available space (WIDTH-41) is divided up between these two
+    columns. Here's a diagram:
+    
+    <--------------------------------- width (W) ---------------------------------->
+    date (10)  description (D)       account (W-41-D)     amount (12)   balance (12)
+    DDDDDDDDDD dddddddddddddddddddd  aaaaaaaaaaaaaaaaaaa  AAAAAAAAAAAA  AAAAAAAAAAAA
+    
+    Examples:
+    $ hledger reg                 # use terminal width on posix
+    $ hledger reg -w 100          # width 100, equal description/account widths
+    $ hledger reg -w 100,40       # width 100, wider description
+    $ hledger reg -w $COLUMNS,100 # terminal width and set description width
+
+- balance: new -T/--row-total and -A/--average options
+
+  In multicolumn balance reports, -T/--row-total now shows a row totals
+  column and -A/--average shows a row averages column.
+  This helps eg to see monthly average expenses (hledger bal ^expenses -MA).
+
+  NB our use of -T deviates from Ledger's UI, where -T sets a custom
+  final total expression.
+
+- balance: -N is now short for --no-total
+- balance: fix partially-visible totals row with --no-total
+    
+    A periodic (not using --cumulative or --historical) balance report
+    with --no-total now hides the totals row properly.
+
+- journal, csv: comment lines can also start with *
+    
+    As in Ledger. This means you can embed emacs org/outline-mode nodes in
+    your journal file and manipulate it like an outline.
+
 0.24.1 (2015/3/15)
 
-- timelog: show hours with 2 decimal places, not 1 (#237)
-- fix balance accumulation through assertions in several commodities (#195)
-- fix rendering of week 52 heading in weekly reports
+- journal: fix balance accumulation across assertions (#195)
+    
+    A sequence of balance assertions asserting first one commodity, then
+    another, then the first again, was not working.
+
+- timelog: show hours with two decimal places instead of one (#237)
+- in weekly reports, simplify week 52's heading like the others
+- disallow trailing garbage in a number of parsers
+
+    Trailing garbage is no longer ignored when parsing the following:
+    balance --format option, register --width option, hledger-rewrite
+    options, hledger add's inputs, CSV amounts, posting amounts,
+    posting dates in tags.
+
 - allow utf8-string-1 (fpco/stackage/#426)
 
 0.24 (2014/12/25)
diff --git a/Hledger/Cli/Add.hs b/Hledger/Cli/Add.hs
--- a/Hledger/Cli/Add.hs
+++ b/Hledger/Cli/Add.hs
@@ -3,12 +3,14 @@
 |-}
 
 {-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-unused-do-bind #-}
-{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable, RecordWildCards, TypeOperators, FlexibleContexts #-}
+{-# LANGUAGE CPP, ScopedTypeVariables, DeriveDataTypeable, RecordWildCards, TypeOperators, FlexibleContexts #-}
 
 module Hledger.Cli.Add
 where
 
-import Control.Applicative ((<*))
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative.Compat ((<*))
+#endif
 import Control.Exception as E
 import Control.Monad
 import Control.Monad.Trans (liftIO)
diff --git a/Hledger/Cli/Balance.hs b/Hledger/Cli/Balance.hs
--- a/Hledger/Cli/Balance.hs
+++ b/Hledger/Cli/Balance.hs
@@ -261,13 +261,15 @@
  ,modeGroupFlags = C.Group {
      groupUnnamed = [
       flagNone ["tree"] (\opts -> setboolopt "tree" opts) "show accounts as a tree (default in simple reports)"
-     ,flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show accounts as a list (default in multicolumn)"
+     ,flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show accounts as a list (default in multicolumn mode)"
      ,flagReq  ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "flat mode: omit N leading account name parts"
      ,flagReq  ["format"] (\s opts -> Right $ setopt "format" s opts) "FORMATSTR" "tree mode: use this custom line format"
      ,flagNone ["no-elide"] (\opts -> setboolopt "no-elide" opts) "tree mode: don't squash boring parent accounts"
-     ,flagNone ["no-total"] (\opts -> setboolopt "no-total" opts) "don't show the final total"
-     ,flagNone ["cumulative"] (\opts -> setboolopt "cumulative" opts) "multicolumn mode: show accumulated ending balances"
      ,flagNone ["historical","H"] (\opts -> setboolopt "historical" opts) "multicolumn mode: show historical ending balances"
+     ,flagNone ["cumulative"] (\opts -> setboolopt "cumulative" opts) "multicolumn mode: show accumulated ending balances"
+     ,flagNone ["average","A"] (\opts -> setboolopt "average" opts) "multicolumn mode: show a row average column"
+     ,flagNone ["row-total","T"] (\opts -> setboolopt "row-total" opts) "multicolumn mode: show a row total column"
+     ,flagNone ["no-total","N"] (\opts -> setboolopt "no-total" opts) "don't show the final total row"
      ]
      ++ outputflags
     ,groupHidden = []
@@ -393,85 +395,124 @@
 
 -- | Render a multi-column balance report as CSV.
 multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
-multiBalanceReportAsCsv opts (MultiBalanceReport (colspans, items, coltotals)) =
-  ("account" : "short account" : "indent" : map showDateSpan colspans) :
-  [a : a' : show i : map showMixedAmountOneLineWithoutPrice amts | ((a,a',i), amts) <- items]
+multiBalanceReportAsCsv opts (MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =
+  ("account" : "short account" : "indent" : map showDateSpan colspans
+   ++ (if row_total_ opts then ["total"] else [])
+   ++ (if average_ opts then ["average"] else [])
+  ) :
+  [a : a' : show i :
+   map showMixedAmountOneLineWithoutPrice
+   (amts
+    ++ (if row_total_ opts then [rowtot] else [])
+    ++ (if average_ opts then [rowavg] else []))
+  | ((a,a',i), amts, rowtot, rowavg) <- items]
   ++
   if no_total_ opts
   then []
-  else [["totals", "", ""] ++ map showMixedAmountOneLineWithoutPrice coltotals]
+  else [["totals", "", ""]
+        ++ map showMixedAmountOneLineWithoutPrice (
+           coltotals
+           ++ (if row_total_ opts then [tot] else [])
+           ++ (if average_ opts then [avg] else [])
+           )]
 
 -- | Render a multi-column period balance report as plain text suitable for console output.
 periodBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String
-periodBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, coltotals)) =
+periodBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =
   unlines $
   ([printf "Balance changes in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $
   trimborder $ lines $
-   render
-    id
-    ((" "++) . showDateSpan)
-    showMixedAmountOneLineWithoutPrice
-    $ Table
-      (T.Group NoLine $ map (Header . padright acctswidth) accts)
-      (T.Group NoLine $ map Header colspans)
-      (map snd items')
-    +----+
-    totalrow
+   render id (" "++) showMixedAmountOneLineWithoutPrice $
+    addtotalrow $
+     Table
+     (T.Group NoLine $ map (Header . padright acctswidth) accts)
+     (T.Group NoLine $ map Header colheadings)
+     (map rowvals items')
   where
     trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)
+    colheadings = map showDateSpan colspans
+                  ++ (if row_total_ opts then ["  Total"] else [])
+                  ++ (if average_ opts then ["Average"] else [])
     items' | empty_ opts = items
            | otherwise   = items -- dbg "2" $ filter (any (not . isZeroMixedAmount) . snd) $ dbg "1" items
     accts = map renderacct items'
-    renderacct ((a,a',i),_)
+    renderacct ((a,a',i),_,_,_)
       | tree_ opts = replicate ((i-1)*2) ' ' ++ a'
       | otherwise  = maybeAccountNameDrop opts a
     acctswidth = maximum $ map length $ accts
-    totalrow | no_total_ opts = row "" []
-             | otherwise      = row "" coltotals
+    rowvals (_,as,rowtot,rowavg) = as
+                                   ++ (if row_total_ opts then [rowtot] else [])
+                                   ++ (if average_ opts then [rowavg] else [])
+    addtotalrow | no_total_ opts = id
+                | otherwise      = (+----+ (row "" $
+                                    coltotals
+                                    ++ (if row_total_ opts then [tot] else [])
+                                    ++ (if average_ opts then [avg] else [])
+                                    ))
 
 -- | Render a multi-column cumulative balance report as plain text suitable for console output.
 cumulativeBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String
-cumulativeBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, coltotals)) =
+cumulativeBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =
   unlines $
   ([printf "Ending balances (cumulative) in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $
   trimborder $ lines $
-   render id ((" "++) . maybe "" (showDate . prevday) . spanEnd) showMixedAmountOneLineWithoutPrice $
+   render id (" "++) showMixedAmountOneLineWithoutPrice $
     addtotalrow $
      Table
        (T.Group NoLine $ map (Header . padright acctswidth) accts)
-       (T.Group NoLine $ map Header colspans)
-       (map snd items)
+       (T.Group NoLine $ map Header colheadings)
+       (map rowvals items)
   where
     trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)
+    colheadings = map (maybe "" (showDate . prevday) . spanEnd) colspans
+                  ++ (if row_total_ opts then ["  Total"] else [])
+                  ++ (if average_ opts then ["Average"] else [])
     accts = map renderacct items
-    renderacct ((a,a',i),_)
+    renderacct ((a,a',i),_,_,_)
       | tree_ opts = replicate ((i-1)*2) ' ' ++ a'
       | otherwise  = maybeAccountNameDrop opts a
     acctswidth = maximum $ map length $ accts
+    rowvals (_,as,rowtot,rowavg) = as
+                                   ++ (if row_total_ opts then [rowtot] else [])
+                                   ++ (if average_ opts then [rowavg] else [])
     addtotalrow | no_total_ opts = id
-                | otherwise      = (+----+ row "" coltotals)
+                | otherwise      = (+----+ (row "" $
+                                    coltotals
+                                    ++ (if row_total_ opts then [tot] else [])
+                                    ++ (if average_ opts then [avg] else [])
+                                    ))
 
 -- | Render a multi-column historical balance report as plain text suitable for console output.
 historicalBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String
-historicalBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, coltotals)) =
+historicalBalanceReportAsText opts r@(MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =
   unlines $
   ([printf "Ending balances (historical) in %s:" (showDateSpan $ multiBalanceReportSpan r)] ++) $
   trimborder $ lines $
-   render id ((" "++) . maybe "" (showDate . prevday) . spanEnd) showMixedAmountOneLineWithoutPrice $
+   render id (" "++) showMixedAmountOneLineWithoutPrice $
     addtotalrow $
      Table
        (T.Group NoLine $ map (Header . padright acctswidth) accts)
-       (T.Group NoLine $ map Header colspans)
-       (map snd items)
+       (T.Group NoLine $ map Header colheadings)
+       (map rowvals items)
   where
     trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)
+    colheadings = map (maybe "" (showDate . prevday) . spanEnd) colspans
+                  ++ (if row_total_ opts then ["  Total"] else [])
+                  ++ (if average_ opts then ["Average"] else [])
     accts = map renderacct items
-    renderacct ((a,a',i),_)
+    renderacct ((a,a',i),_,_,_)
       | tree_ opts = replicate ((i-1)*2) ' ' ++ a'
       | otherwise  = maybeAccountNameDrop opts a
     acctswidth = maximum $ map length $ accts
+    rowvals (_,as,rowtot,rowavg) = as
+                             ++ (if row_total_ opts then [rowtot] else [])
+                             ++ (if average_ opts then [rowavg] else [])
     addtotalrow | no_total_ opts = id
-                | otherwise      = (+----+ row "" coltotals)
+                | otherwise      = (+----+ (row "" $
+                                    coltotals
+                                    ++ (if row_total_ opts then [tot] else [])
+                                    ++ (if average_ opts then [avg] else [])
+                                    ))
 
 -- | Figure out the overall date span of a multicolumn balance report.
 multiBalanceReportSpan :: MultiBalanceReport -> DateSpan
diff --git a/Hledger/Cli/Options.hs b/Hledger/Cli/Options.hs
--- a/Hledger/Cli/Options.hs
+++ b/Hledger/Cli/Options.hs
@@ -1,5 +1,4 @@
-{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE CPP, ScopedTypeVariables, DeriveDataTypeable, FlexibleContexts #-}
 {-|
 
 Common cmdargs modes and flags, a command-line options type, and
@@ -43,12 +42,10 @@
   rulesFilePathFromOpts,
   outputFileFromOpts,
   outputFormatFromOpts,
-  -- | For register:
-  OutputWidth(..),
-  Width(..),
   defaultWidth,
-  defaultWidthWithFlag,
   widthFromOpts,
+  -- | For register:
+  registerWidthsFromOpts,
   maybeAccountNameDrop,
   -- | For balance:
   lineFormatFromOpts,
@@ -62,7 +59,9 @@
 )
 where
 
-import Control.Applicative ((<$>), (<*))
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative.Compat ((<$>), (<*))
+#endif
 import qualified Control.Exception as C
 import Control.Monad (when)
 import Data.List
@@ -71,6 +70,9 @@
 import System.Console.CmdArgs
 import System.Console.CmdArgs.Explicit
 import System.Console.CmdArgs.Text
+#ifndef mingw32_HOST_OS
+import System.Console.Terminfo
+#endif
 import System.Directory
 import System.Environment
 import System.Exit (exitSuccess)
@@ -255,7 +257,11 @@
     ,ignore_assertions_ :: Bool
     ,debug_           :: Int            -- ^ debug level, set by @--debug[=N]@. See also 'Hledger.Utils.debugLevel'.
     ,no_new_accounts_ :: Bool           -- add
-    ,width_           :: Maybe String   -- register
+    ,width_           :: Maybe String   -- ^ the --width value provided, if any
+    ,available_width_ :: Int            -- ^ estimated usable screen width, based on
+                                        -- 1. the COLUMNS env var, if set
+                                        -- 2. the width reported by the terminal, if supported
+                                        -- 3. the default (80)
     ,reportopts_      :: ReportOpts
  } deriving (Show, Data, Typeable)
 
@@ -274,18 +280,33 @@
     def
     def
     def
+    defaultWidth
     def
 
 -- | Convert possibly encoded option values to regular unicode strings.
 decodeRawOpts :: RawOpts -> RawOpts
 decodeRawOpts = map (\(name',val) -> (name', fromSystemString val))
 
+-- | Default width for hledger console output, when not otherwise specified.
+defaultWidth :: Int
+defaultWidth = 80
+
 -- | Parse raw option string values to the desired final data types.
 -- Any relative smart dates will be converted to fixed dates based on
 -- today's date. Parsing failures will raise an error.
+-- Also records the terminal width, if supported.
 rawOptsToCliOpts :: RawOpts -> IO CliOpts
 rawOptsToCliOpts rawopts = do
   ropts <- rawOptsToReportOpts rawopts
+  mcolumns <- readMay <$> getEnvSafe "COLUMNS"
+  mtermwidth <-
+#ifdef mingw32_HOST_OS
+    return Nothing
+#else
+    setupTermFromEnv >>= return . flip getCapability termColumns
+    -- XXX Throws a SetupTermError if the terminfo database could not be read, should catch
+#endif
+  let availablewidth = head $ catMaybes [mcolumns, mtermwidth, Just defaultWidth]
   return defcliopts {
               rawopts_         = rawopts
              ,command_         = stringopt "command" rawopts
@@ -297,7 +318,8 @@
              ,debug_           = intopt "debug" rawopts
              ,ignore_assertions_ = boolopt "ignore-assertions" rawopts
              ,no_new_accounts_ = boolopt "no-new-accounts" rawopts -- add
-             ,width_           = maybestringopt "width" rawopts    -- register
+             ,width_           = maybestringopt "width" rawopts
+             ,available_width_ = availablewidth
              ,reportopts_      = ropts
              }
 
@@ -307,9 +329,7 @@
   case lineFormatFromOpts ropts of
     Left err -> optserror $ "could not parse format option: "++err
     Right _ -> return ()
-  case widthFromOpts opts of
-    Left err -> optserror $ "could not parse width option: "++err
-    Right _ -> return ()
+  -- XXX check registerWidthsFromOpts opts
   return opts
 
 -- Currently only used by some extras/ scripts:
@@ -405,6 +425,47 @@
   d <- getCurrentDirectory
   maybe (return Nothing) (fmap Just . expandPath d) $ rules_file_ opts
 
+-- | Get the width in characters to use for console output.
+-- This comes from the --width option, or the COLUMNS environment
+-- variable, or (on posix platforms) the current terminal width, or 80.
+-- Will raise a parse error for a malformed --width argument.
+widthFromOpts :: CliOpts -> Int
+widthFromOpts CliOpts{width_=Nothing, available_width_=w} = w
+widthFromOpts CliOpts{width_=Just s}  =
+    case runParser (read `fmap` many1 digit <* eof) () "(unknown)" s of
+        Left e   -> optserror $ "could not parse width option: "++show e
+        Right w  -> w
+
+-- for register:
+
+-- | Get the width in characters to use for the register command's console output,
+-- and also the description column width if specified (following the main width, comma-separated).
+-- The widths will be as follows:
+-- @
+-- no --width flag - overall width is the available width (COLUMNS, or posix terminal width, or 80); description width is unspecified (auto)
+-- --width W       - overall width is W, description width is auto
+-- --width W,D     - overall width is W, description width is D
+-- @
+-- Will raise a parse error for a malformed --width argument.
+registerWidthsFromOpts :: CliOpts -> (Int, Maybe Int)
+registerWidthsFromOpts CliOpts{width_=Nothing, available_width_=w} = (w, Nothing)
+registerWidthsFromOpts CliOpts{width_=Just s}  =
+    case runParser registerwidthp () "(unknown)" s of
+        Left e   -> optserror $ "could not parse width option: "++show e
+        Right ws -> ws
+    where
+        registerwidthp :: Stream [Char] m t => ParsecT [Char] st m (Int, Maybe Int)
+        registerwidthp = do
+          totalwidth <- read `fmap` many1 digit
+          descwidth <- optionMaybe (char ',' >> read `fmap` many1 digit)
+          eof
+          return (totalwidth, descwidth)
+
+-- | Drop leading components of accounts names as specified by --drop, but only in --flat mode.
+maybeAccountNameDrop :: ReportOpts -> AccountName -> AccountName
+maybeAccountNameDrop opts a | tree_ opts = a
+                            | otherwise  = accountNameDrop (drop_ opts) a
+
 -- for balance, currently:
 
 -- | Parse the format option if provided, possibly returning an error,
@@ -421,56 +482,6 @@
     , FormatField True Nothing Nothing AccountField
     ]
 
--- for register:
-
--- | Output width configuration (for register).
-data OutputWidth =
-    TotalWidth Width    -- ^ specify the overall width
-  | FieldWidths [Width] -- ^ specify each field's width
-  deriving Show
-
--- | A width value.
-data Width =
-    Width Int -- ^ set width to exactly this number of characters
-  | Auto      -- ^ set width automatically from available space
-  deriving Show
-
--- | Default width of hledger console output.
-defaultWidth :: Int
-defaultWidth = 80
-
--- | Width of hledger console output when the -w flag is used with no value.
-defaultWidthWithFlag :: Int
-defaultWidthWithFlag = 120
-
--- | Parse the width option if provided, possibly returning an error,
--- otherwise get the default value.
-widthFromOpts :: CliOpts -> Either String OutputWidth
-widthFromOpts CliOpts{width_=Nothing} = Right $ TotalWidth $ Width defaultWidth
-widthFromOpts CliOpts{width_=Just ""} = Right $ TotalWidth $ Width defaultWidthWithFlag
-widthFromOpts CliOpts{width_=Just s}  = parseWidth s
-
-parseWidth :: String -> Either String OutputWidth
-parseWidth s = case (runParser (outputwidthp <* eof) () "(unknown)") s of
-    Left  e -> Left $ show e
-    Right x -> Right x
-
-outputwidthp :: Stream [Char] m t => ParsecT [Char] st m OutputWidth
-outputwidthp =
-  try (do w <- widthp
-          ws <- many1 (char ',' >> widthp)
-          return $ FieldWidths $ w:ws)
-  <|> TotalWidth `fmap` widthp
-
-widthp :: Stream [Char] m t => ParsecT [Char] st m Width
-widthp = (string "auto" >> return Auto)
-    <|> (Width . read) `fmap` many1 digit
-
--- | Drop leading components of accounts names as specified by --drop, but only in --flat mode.
-maybeAccountNameDrop :: ReportOpts -> AccountName -> AccountName
-maybeAccountNameDrop opts a | tree_ opts = a
-                            | otherwise  = accountNameDrop (drop_ opts) a
-
 -- Other utils
 
 -- | Get the sorted unique precise names and display names of hledger
@@ -552,7 +563,7 @@
   ]
 
 getEnvSafe :: String -> IO String
-getEnvSafe v = getEnv v `C.catch` (\(_::C.IOException) -> return "")
+getEnvSafe v = getEnv v `C.catch` (\(_::C.IOException) -> return "") -- XXX should catch only isDoesNotExistError e
 
 getDirectoryContentsSafe :: FilePath -> IO [String]
 getDirectoryContentsSafe d =
diff --git a/Hledger/Cli/Print.hs b/Hledger/Cli/Print.hs
--- a/Hledger/Cli/Print.hs
+++ b/Hledger/Cli/Print.hs
@@ -94,31 +94,31 @@
 
 transactionToCSV :: Integer -> Transaction -> CSV
 transactionToCSV n t =
-	map (\p -> show n:date:date2:status:code:description:comment:p)
-	 (concatMap postingToCSV $ tpostings t)
-	where
-		description = tdescription t
-		date = showDate (tdate t)
-		date2 = maybe "" showDate (tdate2 t)
-		status = if tstatus t then "*" else ""
-		code = tcode t
-		comment = chomp $ strip $ tcomment t
+  map (\p -> show n:date:date2:status:code:description:comment:p)
+   (concatMap postingToCSV $ tpostings t)
+  where
+    description = tdescription t
+    date = showDate (tdate t)
+    date2 = maybe "" showDate (tdate2 t)
+    status = if tstatus t then "*" else ""
+    code = tcode t
+    comment = chomp $ strip $ tcomment t
 
 postingToCSV :: Posting -> CSV
 postingToCSV p =
-	map (\(a@(Amount {aquantity=q,acommodity=c})) ->
-		let a_ = a{acommodity=""} in
-		let amount = showAmount a_ in
-		let commodity = c in
-		let credit = if q < 0 then showAmount $ negate a_ else "" in
-		let debit  = if q > 0 then showAmount a_ else "" in
-		account:amount:commodity:credit:debit:status:comment:[])
-	 amounts
-	where
-		Mixed amounts = pamount p
-		status = if pstatus p then "*" else ""
-		account = showAccountName Nothing (ptype p) (paccount p)
-		comment = chomp $ strip $ pcomment p
+  map (\(a@(Amount {aquantity=q,acommodity=c})) ->
+    let a_ = a{acommodity=""} in
+    let amount = showAmount a_ in
+    let commodity = c in
+    let credit = if q < 0 then showAmount $ negate a_ else "" in
+    let debit  = if q > 0 then showAmount a_ else "" in
+    account:amount:commodity:credit:debit:status:comment:[])
+   amounts
+  where
+    Mixed amounts = pamount p
+    status = if pstatus p then "*" else ""
+    account = showAccountName Nothing (ptype p) (paccount p)
+    comment = chomp $ strip $ pcomment p
 
 tests_Hledger_Cli_Print = TestList []
   -- tests_showTransactions
diff --git a/Hledger/Cli/Register.hs b/Hledger/Cli/Register.hs
--- a/Hledger/Cli/Register.hs
+++ b/Hledger/Cli/Register.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-|
 
 A ledger-compatible @register@ command.
@@ -31,8 +32,17 @@
       flagNone ["historical","H"] (\opts -> setboolopt "historical" opts) "include prior postings in the running total"
      ,flagNone ["average","A"] (\opts -> setboolopt "average" opts) "show a running average instead of the running total (implies --empty)"
      ,flagNone ["related","r"] (\opts -> setboolopt "related" opts) "show postings' siblings instead"
-     ,flagReq  ["width","w"] (\s opts -> Right $ setopt "width" s opts) "N" "set output width (default: 80)"
-     ]
+     ,flagReq  ["width","w"] (\s opts -> Right $ setopt "width" s opts) "N"
+      (unlines
+       ["set output width (default:"
+#ifdef mingw32_HOST_OS
+       ,(show defaultWidth)
+#else
+       ,"terminal width"
+#endif
+       ,"or COLUMNS. -wN,M sets description width as well)"
+       ])
+    ]
      ++ outputflags
     ,groupHidden = []
     ,groupNamed = [generalflagsgroup1]
@@ -86,12 +96,22 @@
 
 -- | Render one register report line item as plain text. Layout is like so:
 -- @
--- <----------------------------- width (default: 80) ---------------------------->
--- date (10)  description (50%)     account (50%)         amount (12)  balance (12)
+-- <---------------- width (specified, terminal width, or 80) -------------------->
+-- date (10)  description           account              amount (12)   balance (12)
 -- DDDDDDDDDD dddddddddddddddddddd  aaaaaaaaaaaaaaaaaaa  AAAAAAAAAAAA  AAAAAAAAAAAA
+-- @
+-- If description's width is specified, account will use the remaining space.
+-- Otherwise, description and account divide up the space equally.
 --
--- date and description are shown for the first posting of a transaction only.
+-- With a reporting interval, the layout is like so:
 -- @
+-- <---------------- width (specified, terminal width, or 80) -------------------->
+-- date (21)              account                        amount (12)   balance (12)
+-- DDDDDDDDDDDDDDDDDDDDD  aaaaaaaaaaaaaaaaaaaaaaaaaaaaa  AAAAAAAAAAAA  AAAAAAAAAAAA
+-- @
+--
+-- date and description are shown for the first posting of a transaction only.
+--
 postingsReportItemAsText :: CliOpts -> PostingsReportItem -> String
 postingsReportItemAsText opts (mdate, menddate, mdesc, p, b) =
   intercalate "\n" $
@@ -101,11 +121,8 @@
     [printf (spacer ++ "%"++amtw++"s  %"++balw++"s") a b | (a,b) <- zip amtrest balrest ]
 
     where
-      totalwidth = case widthFromOpts opts of
-           Left _                       -> defaultWidth -- shouldn't happen
-           Right (TotalWidth (Width w)) -> w
-           Right (TotalWidth Auto)      -> defaultWidth -- XXX
-           Right (FieldWidths _)        -> defaultWidth -- XXX
+      -- calculate widths
+      (totalwidth,mdescwidth) = registerWidthsFromOpts opts
       amtwidth = 12
       balwidth = 12
       (datewidth, date) = case (mdate,menddate) of
@@ -114,15 +131,15 @@
                             (Just d, Nothing)  -> (10, showDate d)
                             _                  -> (10, "")
       remaining = totalwidth - (datewidth + 1 + 2 + amtwidth + 2 + balwidth)
-      (descwidth, acctwidth) | isJust menddate = (0, remaining-2)
-                             | even remaining  = (r2, r2)
-                             | otherwise       = (r2, r2+1)
+      (descwidth, acctwidth)
+        | hasinterval = (0, remaining - 2)
+        | otherwise   = (w, remaining - 2 - w)
         where
-          r2 = (remaining-2) `div` 2
+            hasinterval = isJust menddate
+            w = fromMaybe ((remaining - 2) `div` 2) mdescwidth
       [datew,descw,acctw,amtw,balw] = map show [datewidth,descwidth,acctwidth,amtwidth,balwidth]
 
-
-
+      -- gather content
       desc = maybe "" (take descwidth . elideRight descwidth) mdesc
       acct = parenthesise $ elideAccountName awidth $ paccount p
          where
diff --git a/hledger.cabal b/hledger.cabal
--- a/hledger.cabal
+++ b/hledger.cabal
@@ -1,5 +1,5 @@
 name:           hledger
-version: 0.24.1
+version: 0.25
 stability:      stable
 category:       Finance, Console
 synopsis:       The main command-line interface for the hledger accounting tool.
@@ -17,7 +17,7 @@
 maintainer:     Simon Michael <simon@joyful.com>
 homepage:       http://hledger.org
 bug-reports:    http://hledger.org/bugs
-tested-with:    GHC==7.2.2, GHC==7.4.2, GHC==7.6.3, GHC==7.8.2
+tested-with:    GHC==7.8.2, GHC==7.10.1
 cabal-version:  >= 1.10
 build-type:     Simple
 -- data-dir:       data
@@ -41,9 +41,19 @@
     Description:   Build with support for multithreaded execution
     Default:       True
 
+flag curses
+    Description:   On POSIX systems, enable curses support for auto-detecting terminal width.
+    Default:       True
 
+flag old-locale
+  description: A compatibility flag, set automatically by cabal.
+               If false then depend on time >= 1.5, 
+               if true then depend on time < 1.5 together with old-locale.
+  default: False
+
+
 library
-  cpp-options: -DVERSION="0.24.1"
+  cpp-options: -DVERSION="0.25"
   ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures
   ghc-options: -fno-warn-type-defaults -fno-warn-orphans
   default-language: Haskell2010
@@ -65,8 +75,9 @@
                   Hledger.Cli.Register
                   Hledger.Cli.Stats
   build-depends:
-                  hledger-lib == 0.24.1
+                  hledger-lib == 0.25
                  ,base >= 4.3 && < 5
+                 ,base-compat >= 0.5.0
                  -- ,cabal-file-th
                  ,containers
                  ,cmdargs >= 0.10 && < 0.11
@@ -77,47 +88,52 @@
                  ,haskeline >= 0.6 && <= 0.8
                  ,HUnit
                  ,mtl
-                 ,old-locale
+                 ,mtl-compat
                  ,old-time
                  ,parsec >= 3
                  ,process
                  ,regex-tdfa
                  ,regexpr >= 0.5.1
                  ,safe >= 0.2
--- http://www.yesodweb.com/blog/2014/04/consolidation-progress
--- in order to support both the old and new versions of shakespeare,
--- you just need to ensure that you have both the shakespeare and
--- deprecated packages listed in your cabal file. In other words, if
--- previously you depended on hamlet, now you should depend on hamlet
--- and shakespeare. When you're ready to drop backwards compatibility,
--- simply put a lower bound of >= 2.0 on shakespeare and remove the
--- deprecated packages.
-                 ,shakespeare-text >= 1.0 && < 1.2
-                 ,shakespeare      >= 1.0 && < 2.1
                  ,split >= 0.1 && < 0.3
                  ,text >= 0.11
                  ,tabular >= 0.2 && < 0.3
-                 ,time
                  ,utf8-string >= 0.3.5 && < 1.1
                  ,wizards == 1.0.*
+  if impl(ghc >= 7.10)
+    -- ghc 7.10 requires shakespeare 2.0.2.2+
+    build-depends: shakespeare      >= 2.0.2.2 && < 2.1
+  else
+    -- for older ghcs, allow shakespeare 2.x or 1.x (which also requires shakespeare-text)
+    -- http://www.yesodweb.com/blog/2014/04/consolidation-progress
+    build-depends:
+                  shakespeare      >= 1.0 && < 2.1
+                 ,shakespeare-text >= 1.0 && < 1.2
+  if flag(old-locale)
+    build-depends: time < 1.5, old-locale
+  else
+    build-depends: time >= 1.5
   if impl(ghc >= 7.4)
     build-depends: pretty-show >= 1.6.4
+  if !os(windows) && flag(curses)
+    build-depends: terminfo
 
 
 executable hledger
   main-is:        hledger-cli.hs
   hs-source-dirs: app
   default-language: Haskell2010
-  cpp-options: -DVERSION="0.24.1"
+  cpp-options: -DVERSION="0.25"
   ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures
   ghc-options: -fno-warn-type-defaults -fno-warn-orphans
   if flag(threaded)
        ghc-options:   -threaded
   -- same as above:
   build-depends:
-                  hledger-lib == 0.24.1
-                 ,hledger == 0.24.1
+                  hledger-lib == 0.25
+                 ,hledger == 0.25
                  ,base >= 4.3 && < 5
+                 ,base-compat >= 0.5.0
                  ,containers
                  ,cmdargs >= 0.10 && < 0.11
                  ,csv
@@ -127,7 +143,7 @@
                  ,haskeline >= 0.6 && <= 0.8
                  ,HUnit
                  ,mtl
-                 ,old-locale
+                 ,mtl-compat
                  ,old-time
                  ,parsec >= 3
                  ,process
@@ -139,9 +155,12 @@
                  ,split >= 0.1 && < 0.3
                  ,tabular >= 0.2 && < 0.3
                  ,text >= 0.11
-                 ,time
                  ,utf8-string >= 0.3.5 && < 1.1
                  ,wizards == 1.0.*
+  if flag(old-locale)
+    build-depends: time < 1.5, old-locale
+  else
+    build-depends: time >= 1.5
   if impl(ghc >= 7.4)
     build-depends: pretty-show >= 1.6.4
 
@@ -157,6 +176,7 @@
   build-depends: hledger-lib
                , hledger
                , base >= 4.3 && < 5
+               , base-compat >= 0.5.0
                , cmdargs
                , containers
                , csv
@@ -166,7 +186,7 @@
                , haskeline
                , HUnit
                , mtl
-               , old-locale
+               , mtl-compat
                , old-time
                , parsec >= 3
                , process
@@ -180,11 +200,14 @@
                , test-framework
                , test-framework-hunit
                , text
-               , time
                , transformers
                , wizards == 1.0.*
   if impl(ghc >= 7.4)
     build-depends: pretty-show >= 1.6.4
+  if flag(old-locale)
+    build-depends: time < 1.5, old-locale
+  else
+    build-depends: time >= 1.5
 
 
 -- not a standard cabal bench test, I think
@@ -198,11 +221,14 @@
   build-depends:    hledger-lib,
                     hledger,
                     base >= 4.3 && < 5,
-                    old-locale,
-                    time,
+                    base-compat >= 0.5.0,
                     html,
                     tabular >= 0.2 && < 0.3,
                     process,
                     filepath,
                     directory
+  if flag(old-locale)
+    build-depends: time < 1.5, old-locale
+  else
+    build-depends: time >= 1.5
   
