diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index 8477b2c..9b6953e 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -1374,6 +1374,7 @@ nil are excluded from the clock summation."
     (if (consp tend) (setq tend (org-float-time tend)))
     (remove-text-properties (point-min) (point-max)
                             '(:org-clock-minutes t
+                              :org-clock-h-minutes t ; bg: property for storing per-heading minutes
                               :org-clock-force-headline-inclusion t))
     (save-excursion
       (goto-char (point-max))
@@ -1417,6 +1418,8 @@ nil are excluded from the clock summation."
 	    (setq level (- (match-end 1) (match-beginning 1)))
 	    (when (or (> t1 0) (> (aref ltimes level) 0))
 	      (when (or headline-included headline-forced)
+                ;; bg: store clocked time of heading (without subheadings
+                (put-text-property (point) (point-at-eol) :org-clock-h-minutes t1)
                 (if headline-included
                     (loop for l from 0 to level do
                           (aset ltimes l (+ (aref ltimes l) t1))))
@@ -1736,14 +1739,60 @@ the currently selected interval size."
 	  (org-update-dblock)
 	  t)))))
 
+
+
+
+;; bg: helper function; used for maintaining assoc list mapping tags to clocked time
+(defun assoc-delete-all (key alist)
+  "Delete from ALIST all elements whose car is `eq' to KEY.
+   Return the modified alist.
+   Elements of ALIST that are not conses are ignored."
+  (while (and (consp (car alist))
+	      (equal (car (car alist)) key))
+    (setq alist (cdr alist)))
+  (let ((tail alist) tail-cdr)
+    (while (setq tail-cdr (cdr tail))
+      (if (and (consp (car tail-cdr))
+	       (equal (car (car tail-cdr)) key))
+	  (setcdr tail (cdr tail-cdr))
+	(setq tail tail-cdr))))
+  alist)
+
+
+
 (defun org-dblock-write:clocktable (params)
-  "Write the standard clocktable."
+  "Write the standard clocktable. If the parameter
+   to_alist is set to a non-nil value, instead of
+   printing the table, the following result is
+   returned:
+    (list tbl tag_times)
+   where
+   - tbl is a list of association lists of the following form:
+       (file . (Filename . Accumulated_Filetime)) (only if scope = agenda
+       (level . Level)
+       (tsp . Timestamp)
+       (title . Title)
+       (hlc . Emphasis character or "")
+       (tag . Clocktag or "")
+       (time . Clocked time 
+           cumulative adding up lower levels if clocktags is not set)
+   - tag_times is an association list mapping clocktags
+     to clocked time for each tag (if parameter clock_tags is non-nil)
+
+  If additionally the 'step' parameter is used, then
+  the returned association list maps each date string denoting the
+  start time of each step to the list structure as explained above. 
+  "
   (catch 'exit
     (let* ((hlchars '((1 . "*") (2 . "/")))
 	   (ins (make-marker))
 	   (total-time nil)
 	   (scope (plist-get params :scope))
 	   (tostring (plist-get  params :tostring))
+           ;; bg: parameter to_alist required for recursive call
+	   (to_alist (plist-get  params :to_alist))
+           ;; bg: Parameter for clock tags
+           (clocktags (plist-get params :clocktags))
 	   (multifile (plist-get  params :multifile))
 	   (header (plist-get  params :header))
 	   (maxlevel (or (plist-get params :maxlevel) 3))
@@ -1754,16 +1803,113 @@ the currently selected interval size."
 	   (te (plist-get params :tend))
 	   (block (plist-get params :block))
 	   (link (plist-get params :link))
+           ;; bg: added parameter tag_times to pass collected tag_times between recursive calls
+	   (tag_times (plist-get params :tag_times))
 	   (tags (plist-get params :tags))
 	   (matcher (if tags (cdr (org-make-tags-matcher tags))))
 	   ipos time p level hlc hdl tsp props content recalc formula pcol
-	   cc beg end pos tbl tbl1 range-text rm-file-column scope-is-list st)
+	   cc beg end pos tbl tbl1 range-text rm-file-column scope-is-list st
+           time_found)
       (setq org-clock-file-total-minutes nil)
+      (when clocktags 
+        ;; bg:
+        ;; if the clocktags feature is set, we have to look at all
+        ;; levels, because the time from the lower level is not
+        ;; summed-up for higher levels
+        (setq maxlevel 1000))
+
+      (defun print_table (tbl tag_times)
+        "Function to print the clocktable. It takes two argumens:
+         tbl is a list with elements that are an association
+         list of the following form:
+               (file . (Filename . Accumulated_Filetime))  (only, if scope = agenda)
+               (level . Level)
+               (tsp . Timestamp)
+               (title . Title)
+               (hlc . Emphasis character or "")
+               (tag . Clocktag or "")
+               (time . Clocked time 
+                        cumulative adding up lower levels if clocktags is not set)
+
+         tag_times is an association list mapping clocktags
+         to added time for the clocktag.
+
+         If tag_times is nil, the function uses performs the normal
+         way of printing the table; it is not nil, it structures the
+         table by clocktags.
+        "
+
+        (let (current_file 
+              (file_time 0) 
+              (alltags_time 0)
+              result 
+              hlc
+                           )
+          (if (not tag_times) 
+              ;; bg: we use original code from org-clock, wrapped
+              ;; into a loop operating on the table "tbl"
+              (progn
+                (loop for line in tbl do
+                      (setq hlc (cdr (assoc 'hlc line)))
+                      (when (not (equal (cadr (assoc 'file line)) current_file))
+                        (when current_file
+                          (push (concat "| " (file-name-nondirectory (or current_file "")) (if timestamp "|" "") "| |*FILE time*|*"
+                                        (org-minutes-to-hh:mm-string
+                                         file_time)
+                                        "*|")
+                                result)
+                          (push "|-" result))
+                        (setq current_file    (cadr (assoc 'file line))
+                              file_time (caddr (assoc 'file line))))
+                      
+                      (push (concat 
+                             (if (assoc 'file line) (format "| %s" (file-name-nondirectory current_file)) "")
+                             "| " (int-to-string (cdr (assoc 'level line)))
+                             "|" (if timestamp (concat (cdr (assoc 'tsp line)) "|") "")
+                             hlc (cdr  (assoc 'title line)) hlc " |"
+                             (make-string (1- (cdr (assoc 'level line))) ?|)
+                             (concat hlc (org-minutes-to-hh:mm-string (cdr (assoc 'time line))) hlc)
+                             " |" ) result)
+                    
+                      
+                      )
+                (push (concat "| " (file-name-nondirectory (or current_file "")) (if timestamp "|" "") "| |*FILE time*|*"
+                              (org-minutes-to-hh:mm-string
+                               file_time)
+                              "*|")
+                      result))
+            ;; bg: we sort the entries by tags
+            (setq tag_times (sort tag_times (lambda (y x) (string-lessp (car x) (car y)))))
+            (loop for tag_time in tag_times do
+                  (setq alltags_time (+ alltags_time (cdr tag_time)))
+                  (loop for line in tbl do
+                      (when (and (string-equal (cdr (assoc 'tag line)) (car tag_time)) (not (equal (cdr (assoc 'time line)) 0)))
+
+                        (push (concat 
+                               (if (assoc 'file line) (format "| %s" (file-name-nondirectory (cadr (assoc 'file line)))) "| ")
+                               "| " (int-to-string (cdr (assoc 'level line))) 
+                               "|" (if timestamp (concat (cdr (assoc 'tsp line)) "|") "")
+                               hlc (cdr  (assoc 'title line)) hlc " |"
+                               (concat hlc (org-minutes-to-hh:mm-string (cdr (assoc 'time line))) hlc)
+                               " |" ) result)))
+                  (push "|-" result)
+                  (push (concat "| " (if (equal "" (car tag_time)) "UNALLOCATED" (car tag_time)) (if timestamp "|" "") "| |*Total*|*"
+                                      (org-minutes-to-hh:mm-string
+                                       (cdr tag_time))
+                                      "*|")
+                              result)
+                  (push "|-" result)
+                  )
+            )
+          (mapconcat 'identity result "\n")
+          )
+        )
+      
       (when step
 	(unless (or block (and ts te))
 	  (error "Clocktable `:step' can only be used with `:block' or `:tstart,:end'"))
-	(org-clocktable-steps params)
-	(throw 'exit nil))
+	
+	(throw 'exit (org-clocktable-steps params)))
       (when block
 	(setq cc (org-clock-special-range block nil t)
 	      ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
@@ -1817,34 +1963,42 @@ the currently selected interval size."
 		 (scope 'agenda)
 		 (p1 (copy-sequence params))
 		 file)
-	    (setq p1 (plist-put p1 :tostring t))
+            ;; bg: for recursion we must collect the results
+            ;; rather than print the table and manipulate the
+            ;; the resulting string
+	    (setq p1 (plist-put p1 :to_alist t)) 
 	    (setq p1 (plist-put p1 :multifile t))
 	    (setq p1 (plist-put p1 :scope 'file))
 	    (org-prepare-agenda-buffers files)
 	    (while (setq file (pop files))
 	      (with-current-buffer (find-buffer-visiting file)
-		(setq tbl1 (org-dblock-write:clocktable p1))
+                (setq p1 (plist-put p1 :tag_times tag_times))
+		(setq tbl_tags (org-dblock-write:clocktable p1)
+                      tbl1 (car tbl_tags)
+                      tag_times (cadr tbl_tags))
 		(when tbl1
-		  (push (org-clocktable-add-file
-			 file
-			 (concat "| |*File time*|*"
-				 (org-minutes-to-hh:mm-string
-				  org-clock-file-total-minutes)
-				 "*|\n"
-				 tbl1)) tbl)
+                  ;; bg: augment each line with information about the file and total file-time
+                  (setq tbl
+                        (append
+                         (mapcar (lambda (x) (cons `(file . ,(list file org-clock-file-total-minutes)) x))
+                                 tbl1) 
+
+                         tbl))
+
 		  (setq total-time (+ (or total-time 0)
 				      org-clock-file-total-minutes))))))))
 	(goto-char pos)
 
 	(unless scope-is-list
-	  (org-clock-sum ts te
-			 (unless (null matcher)
-			   (lambda ()
-			     (let ((tags-list
-				    (org-split-string
-				     (or (org-entry-get (point) "ALLTAGS") "")
-				     ":")))
-			       (eval matcher)))))
+            (if tags 
+                (org-clock-sum ts te (lambda ()
+                                          (let ((tags-list
+                                                 (org-split-string
+                                                  (or (org-entry-get (point) "ALLTAGS") "")
+                                                  ":")))
+                                            (eval matcher))))
+              (org-clock-sum ts te )
+            )
 	  (goto-char (point-min))
 	  (setq st t)
 	  (while (or (and (bobp) (prog1 st (setq st nil))
@@ -1852,7 +2006,14 @@ the currently selected interval size."
 			  (setq p (point-min)))
 		     (setq p (next-single-property-change (point) :org-clock-minutes)))
 	    (goto-char p)
-	    (when (setq time (get-text-property p :org-clock-minutes))
+            (setq time_found
+                  ;; depending on whether clocktimes is set, we collect the
+                  ;; clocked time for the heading only or the cumulative time for
+                  ;; the heading
+                  (if clocktags (setq time (get-text-property p :org-clock-h-minutes))
+                    (setq time (get-text-property p :org-clock-minutes))))
+	    (when 
+                time_found
 	      (save-excursion
 		(beginning-of-line 1)
 		(when (and (looking-at (org-re "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[[:alnum:]_@:]+:\\)?[ \t]*$"))
@@ -1874,18 +2035,51 @@ the currently selected interval size."
 			      (or (cdr (assoc "SCHEDULED" props))
 				  (cdr (assoc "TIMESTAMP" props))
 				  (cdr (assoc "DEADLINE" props))
-				  (cdr (assoc "TIMESTAMP_IA" props)))))
-		  (if (and (not multifile) (= level 1)) (push "|-" tbl))
-		  (push (concat
-			 "| " (int-to-string level) "|"
-			 (if timestamp (concat tsp "|") "")
-			 hlc hdl hlc " |"
-			 (make-string (1- level) ?|)
-			 hlc (org-minutes-to-hh:mm-string time) hlc
-			 " |") tbl))))))
-	(setq tbl (nreverse tbl))
-	(if tostring
-	    (if tbl (mapconcat 'identity tbl "\n") nil)
+				  (cdr (assoc "TIMESTAMP_IA" props))))
+                        ;; determine the clocktag (take the first one if
+                        ;; more than one match
+                        tag (if clocktags
+                                (progn (setq props (org-entry-properties (point)))
+                                       (or (car-safe 
+                                            (remove-if-not 
+                                             (lambda (x) (string-match (format "^%s.*" clocktags) x) )
+                                             (when (cdr (assoc "ALLTAGS" props))
+                                               (split-string (cdr (assoc "ALLTAGS" props)) ":" 1)
+                                               )))
+                                           ""))
+                              "")
+
+                        )
+                  (when clocktags
+                    (let (
+                          (accumulated_time (or (cdr-safe (assoc tag tag_times)) 0))
+                          )
+                      ;; bg: 
+                      ;; we build an association list that maps each clocktag
+                      ;; to the added clocked time. We need to delete old
+                      ;; entries rather than just consing new key-value pairs,
+                      ;; because we later want to sort with respect to tags
+                      (setq tag_times (cons `(,tag . ,(+ time accumulated_time)) 
+                                            (assoc-delete-all tag tag_times)))
+
+                      ))
+
+
+                  (push `(    (level . ,level)
+                              (tsp . ,(if timestamp tsp ""))
+                              (title . ,hdl)
+                              (hlc . ,hlc)
+                              (tag . ,tag)
+                              (time . ,time))
+                        tbl)
+
+                  )))))
+	(if (or tostring to_alist)
+            (progn
+              ;; bg:  we return the table, either printed or as alist
+              (if (and tbl tostring) (print_table tbl tag_times) 
+                (list tbl tag_times)))
+
 	  (goto-char ins)
 	  (insert-before-markers
 	   (or header
@@ -1897,23 +2091,17 @@ the currently selected interval size."
 		"]"
 		(if block (concat ", for " range-text ".") "")
 		"\n\n"))
-	   (if scope-is-list "|File" "")
+	   (if (or clocktags scope-is-list) (if clocktags "|ClockTag" "|File") "")
 	   "|L|" (if timestamp "Timestamp|" "") "Headline|Time|\n")
 	  (setq total-time (or total-time org-clock-file-total-minutes))
 	  (insert-before-markers
 	   "|-\n|"
-	   (if scope-is-list "|" "")
+	   (if (or clocktags scope-is-list) "|" "")
 	   (if timestamp "|Timestamp|" "|")
 	   "*Total time*| *"
 	   (org-minutes-to-hh:mm-string (or total-time 0))
 	   "*|\n|-\n")
-	  (setq tbl (delq nil tbl))
-	  (if (and (stringp (car tbl)) (> (length (car tbl)) 1)
-		   (equal (substring (car tbl) 0 2) "|-"))
-	      (pop tbl))
-	  (insert-before-markers (mapconcat
-				  'identity (delq nil tbl)
-				  (if scope-is-list "\n|-\n" "\n")))
+          (insert-before-markers (print_table tbl tag_times))
 	  (backward-delete-char 1)
 	  (if (setq formula (plist-get params :formula))
 	      (cond
@@ -1953,13 +2141,14 @@ the currently selected interval size."
 
 (defun org-clocktable-steps (params)
   (let* ((p1 (copy-sequence params))
+         (to_alist (plist-get p1 :to_alist))
 	 (ts (plist-get p1 :tstart))
 	 (te (plist-get p1 :tend))
 	 (step0 (plist-get p1 :step))
 	 (step (cdr (assoc step0 '((day . 86400) (week . 604800)))))
 	 (stepskip0 (plist-get p1 :stepskip0))
 	 (block (plist-get p1 :block))
-	 cc range-text step-time)
+	 cc range-text step-time result)
     (when block
       (setq cc (org-clock-special-range block nil t)
 	    ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
@@ -1970,37 +2159,38 @@ the currently selected interval size."
     (setq p1 (plist-put p1 :header ""))
     (setq p1 (plist-put p1 :step nil))
     (setq p1 (plist-put p1 :block nil))
+    (setq p1 (plist-put p1 :to_alist to_alist))
     (while (< ts te)
-      (or (bolp) (insert "\n"))
+      (or to_alist (bolp) (insert "\n"))
       (setq p1 (plist-put p1 :tstart (format-time-string
 				      (org-time-stamp-format nil t)
 				      (seconds-to-time ts))))
       (setq p1 (plist-put p1 :tend (format-time-string
 				    (org-time-stamp-format nil t)
 				    (seconds-to-time (setq ts (+ ts step))))))
-      (insert "\n" (if (eq step0 'day) "Daily report: " "Weekly report starting on: ")
-	      (plist-get p1 :tstart) "\n")
-      (setq step-time (org-dblock-write:clocktable p1))
-      (re-search-forward "#\\+END:")
-      (when (and (equal step-time 0) stepskip0)
-	;; Remove the empty table
-	(delete-region (point-at-bol)
-		       (save-excursion
-			 (re-search-backward "^\\(Daily\\|Weekly\\) report" nil t)
-			 (point))))
-      (end-of-line 0))))
-
-(defun org-clocktable-add-file (file table)
-  (if table
-      (let ((lines (org-split-string table "\n"))
-	    (ff (file-name-nondirectory file)))
-	(mapconcat 'identity
-		   (mapcar (lambda (x)
-			     (if (string-match org-table-dataline-regexp x)
-				 (concat "|" ff x)
-			       x))
-			   lines)
-		   "\n"))))
+      (when (not to_alist)
+        (insert "\n" (if (eq step0 'day) "Daily report: " "Weekly report starting on: ")
+	      (plist-get p1 :tstart) "\n"))
+      ;; bg: 
+      ;; return value is either an association list with clocking info
+      ;; (if to_alist is set) or the total time of the step (if to_alist
+      ;; is not set)
+      (setq step-time_or_alist (org-dblock-write:clocktable p1))
+      (if to_alist 
+          (setq result (cons (cons (plist-get p1 :tstart) step-time_or_alist) result))
+        (re-search-forward "#\\+END:")
+        (when (and (equal step-time 0) stepskip0)
+          ;; Remove the empty table
+          (delete-region (point-at-bol)
+                         (save-excursion
+                           (re-search-backward "^\\(Daily\\|Weekly\\) report" nil t)
+                           (point)))))
+        (when (not to_alist) (end-of-line 0))
+        )
+    result
+    )
+  )
+
 
 (defun org-clock-time% (total &rest strings)
   "Compute a time fraction in percent.
