+In particular, it adds the prefix and corresponding text properties. EXTRA
+must be a string and replaces the `%s' specifier in the prefix format.
+CATEGORY (string, symbol or nil) may be used to overule the default
+category taken from local variable or file name. It will replace the `%c'
+specifier in the format. DOTIME, when non-nil, indicates that a
+time-of-day should be extracted from TXT for sorting of this entry, and for
+the `%t' specifier in the format. When DOTIME is a string, this string is
+searched for a time before TXT is. NOPREFIX is a flag and indicates that
+only the correctly processes TXT should be returned - this is used by
+`org-agenda-change-all-lines'."
+ (save-match-data
+ ;; Diary entries sometimes have extra whitespace at the beginning
+ (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
+ (let* ((category (or category
+ org-category
+ (if (buffer-file-name)
+ (file-name-sans-extension
+ (file-name-nondirectory (buffer-file-name)))
+ "")))
+ time ;; needed for the eval of the prefix format
+ (ts (if dotime (concat (if (stringp dotime) dotime "") txt)))
+ (time-of-day (and dotime (org-get-time-of-day ts)))
+ stamp plain s0 s1 s2 rtn)
+ (when (and dotime time-of-day org-prefix-has-time)
+ ;; Extract starting and ending time and move them to prefix
+ (when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
+ (setq plain (string-match org-plain-time-of-day-regexp ts)))
+ (setq s0 (match-string 0 ts)
+ s1 (match-string (if plain 1 2) ts)
+ s2 (match-string (if plain 8 4) ts))
+
+ ;; If the times are in TXT (not in DOTIMES), and the prefix will list
+ ;; them, we might want to remove them there to avoid duplication.
+ ;; The user can turn this off with a variable.
+ (if (and org-agenda-remove-times-when-in-prefix (or stamp plain)
+ (string-match (concat (regexp-quote s0) " *") txt)
+ (if (eq org-agenda-remove-times-when-in-prefix 'beg)
+ (= (match-beginning 0) 0)
+ t))
+ (setq txt (replace-match "" nil nil txt))))
+ ;; Normalize the time(s) to 24 hour
+ (if s1 (setq s1 (org-get-time-of-day s1 'string)))
+ (if s2 (setq s2 (org-get-time-of-day s2 'string))))
+
+ ;; Create the final string
+ (if noprefix
+ (setq rtn txt)
+ ;; Prepare the variables needed in the eval of the compiled format
+ (setq time (cond (s2 (concat s1 "-" s2))
+ (s1 (concat s1 "......"))
+ (t ""))
+ extra (or extra "")
+ category (if (symbolp category) (symbol-name category) category))
+ ;; Evaluate the compiled format
+ (setq rtn (concat (eval org-prefix-format-compiled) txt)))
+
+ ;; And finally add the text properties
+ (add-text-properties
+ 0 (length rtn) (list 'category (downcase category)
+ 'prefix-length (- (length rtn) (length txt))
+ 'time-of-day time-of-day
+ 'dotime dotime)
+ rtn)
+ rtn)))
+
+(defun org-agenda-add-time-grid-maybe (list ndays todayp)
+ (catch 'exit
+ (cond ((not org-agenda-use-time-grid) (throw 'exit list))
+ ((and todayp (member 'today (car org-agenda-time-grid))))
+ ((and (= ndays 1) (member 'daily (car org-agenda-time-grid))))
+ ((member 'weekly (car org-agenda-time-grid)))
+ (t (throw 'exit list)))
+ (let* ((have (delq nil (mapcar
+ (lambda (x) (get-text-property 1 'time-of-day x))
+ list)))
+ (string (nth 1 org-agenda-time-grid))
+ (gridtimes (nth 2 org-agenda-time-grid))
+ (req (car org-agenda-time-grid))
+ (remove (member 'remove-match req))
+ new time)
+ (if (and (member 'require-timed req) (not have))
+ ;; don't show empty grid
+ (throw 'exit list))
+ (while (setq time (pop gridtimes))
+ (unless (and remove (member time have))
+ (setq time (int-to-string time))
+ (push (org-format-agenda-item
+ nil string "" ;; FIXME: put a category?
+ (concat (substring time 0 -2) ":" (substring time -2)))
+ new)
+ (put-text-property
+ 1 (length (car new)) 'face 'org-time-grid-face (car new))))
+ (if (member 'time-up org-agenda-sorting-strategy)
+ (append new list)
+ (append list new)))))
+