ps-print-invisible.el 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. ;;; ps-print-invisible.el - addon to ps-print package that deals
  2. ;; with invisible text printing in xemacs
  3. ;; Author: Greg Chernov
  4. ;;
  5. ;; GNU Emacs is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation; either version 2, or (at your option)
  8. ;; any later version.
  9. ;; GNU Emacs is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  15. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. ;; Boston, MA 02110-1301, USA.
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18. ;;
  19. ;;; Commentary:
  20. ;;
  21. ;; Put ps-print-invisible.el on your load path.
  22. ;; (require 'ps-print-invisible)
  23. ;; ps-print-buffer-with-faces will not print invisible parts of the buffer.
  24. ;; Work with invisible extents/text properties only
  25. ;; (xemacs hideshow and noutline packages).
  26. (defun ps-generate-postscript-with-faces (from to)
  27. ;; Some initialization...
  28. (setq ps-current-effect 0)
  29. ;; Build the reference lists of faces if necessary.
  30. (when (or ps-always-build-face-reference
  31. ps-build-face-reference)
  32. (message "Collecting face information...")
  33. (ps-build-reference-face-lists))
  34. ;; Black/white printer.
  35. (setq ps-black-white-faces-alist nil)
  36. (and (eq ps-print-color-p 'black-white)
  37. (ps-extend-face-list ps-black-white-faces nil
  38. 'ps-black-white-faces-alist))
  39. ;; Generate some PostScript.
  40. (save-restriction
  41. (narrow-to-region from to)
  42. (ps-print-ensure-fontified from to)
  43. (let ((face 'default)
  44. (position to))
  45. (cond
  46. ((memq ps-print-emacs-type '(xemacs lucid))
  47. ;; Build the list of extents...
  48. ;;(debug)
  49. (let ((a (cons 'dummy nil))
  50. record type extent extent-list
  51. (list-invisible (ps-print-find-invisible-xmas from to)))
  52. (ps-x-map-extents 'ps-mapper nil from to a)
  53. (setq a (sort (cdr a) 'car-less-than-car)
  54. extent-list nil)
  55. ;; Loop through the extents...
  56. (while a
  57. (setq record (car a)
  58. position (car record)
  59. record (cdr record)
  60. type (car record)
  61. record (cdr record)
  62. extent (car record))
  63. ;; Plot up to this record.
  64. ;; XEmacs 19.12: for some reason, we're getting into a
  65. ;; situation in which some of the records have
  66. ;; positions less than 'from'. Since we've narrowed
  67. ;; the buffer, this'll generate errors. This is a hack,
  68. ;; but don't call ps-plot-with-face unless from > point-min.
  69. (and (>= from (point-min))
  70. (ps-plot-with-face from (min position (point-max)) face))
  71. (cond
  72. ((eq type 'push)
  73. (and (or (ps-x-extent-face extent)
  74. (extent-property extent 'invisible))
  75. (setq extent-list (sort (cons extent extent-list)
  76. 'ps-extent-sorter))))
  77. ((eq type 'pull)
  78. (setq extent-list (sort (delq extent extent-list)
  79. 'ps-extent-sorter))))
  80. (setq face (if extent-list
  81. (let ((prop (extent-property (car extent-list) 'invisible)))
  82. (if (or (and (eq buffer-invisibility-spec t)
  83. (not (null prop)))
  84. (and (consp buffer-invisibility-spec)
  85. (or (memq prop buffer-invisibility-spec)
  86. (assq prop buffer-invisibility-spec))))
  87. 'emacs--invisible--face
  88. (ps-x-extent-face (car extent-list))))
  89. 'default)
  90. from position
  91. a (cdr a)))))
  92. ((eq ps-print-emacs-type 'emacs)
  93. (let ((property-change from)
  94. (overlay-change from)
  95. (save-buffer-invisibility-spec buffer-invisibility-spec)
  96. (buffer-invisibility-spec nil)
  97. before-string after-string)
  98. (while (< from to)
  99. (and (< property-change to) ; Don't search for property change
  100. ; unless previous search succeeded.
  101. (setq property-change (next-property-change from nil to)))
  102. (and (< overlay-change to) ; Don't search for overlay change
  103. ; unless previous search succeeded.
  104. (setq overlay-change (min (ps-e-next-overlay-change from)
  105. to)))
  106. (setq position (min property-change overlay-change)
  107. before-string nil
  108. after-string nil)
  109. ;; The code below is not quite correct,
  110. ;; because a non-nil overlay invisible property
  111. ;; which is inactive according to the current value
  112. ;; of buffer-invisibility-spec nonetheless overrides
  113. ;; a face text property.
  114. (setq face
  115. (cond ((let ((prop (get-text-property from 'invisible)))
  116. ;; Decide whether this invisible property
  117. ;; really makes the text invisible.
  118. (if (eq save-buffer-invisibility-spec t)
  119. (not (null prop))
  120. (or (memq prop save-buffer-invisibility-spec)
  121. (assq prop save-buffer-invisibility-spec))))
  122. 'emacs--invisible--face)
  123. ((get-text-property from 'face))
  124. (t 'default)))
  125. (let ((overlays (ps-e-overlays-at from))
  126. (face-priority -1)) ; text-property
  127. (while (and overlays
  128. (not (eq face 'emacs--invisible--face)))
  129. (let* ((overlay (car overlays))
  130. (overlay-invisible
  131. (ps-e-overlay-get overlay 'invisible))
  132. (overlay-priority
  133. (or (ps-e-overlay-get overlay 'priority) 0)))
  134. (and (> overlay-priority face-priority)
  135. (setq before-string
  136. (or (ps-e-overlay-get overlay 'before-string)
  137. before-string)
  138. after-string
  139. (or (and (<= (ps-e-overlay-end overlay) position)
  140. (ps-e-overlay-get overlay 'after-string))
  141. after-string)
  142. face-priority overlay-priority
  143. face
  144. (cond
  145. ((if (eq save-buffer-invisibility-spec t)
  146. (not (null overlay-invisible))
  147. (or (memq overlay-invisible
  148. save-buffer-invisibility-spec)
  149. (assq overlay-invisible
  150. save-buffer-invisibility-spec)))
  151. 'emacs--invisible--face)
  152. ((ps-e-overlay-get overlay 'face))
  153. (t face)
  154. ))))
  155. (setq overlays (cdr overlays))))
  156. ;; Plot up to this record.
  157. (and before-string
  158. (ps-plot-string before-string))
  159. (ps-plot-with-face from position face)
  160. (and after-string
  161. (ps-plot-string after-string))
  162. (setq from position)))))
  163. (ps-plot-with-face from to face))))
  164. (defun ps-print-find-invisible-xmas (from to)
  165. (let ((list nil))
  166. (map-extents '(lambda (ex ignored)
  167. (let ((prop (extent-property ex 'invisible)))
  168. (if (or (and (eq buffer-invisibility-spec t)
  169. (not (null prop)))
  170. (or (memq prop buffer-invisibility-spec)
  171. (assq prop buffer-invisibility-spec)))
  172. (setq list (cons (list
  173. (extent-start-position ex)
  174. (extent-end-position ex))
  175. list))))
  176. nil)
  177. (current-buffer)
  178. from to nil 'start-and-end-in-region 'invisible)
  179. (reverse list)))
  180. (defun ps-mapper (extent list)
  181. ;;(debug)
  182. (let ((beg (ps-x-extent-start-position extent))
  183. (end (ps-x-extent-end-position extent))
  184. (inv-lst list-invisible)
  185. (found nil))
  186. (while (and inv-lst
  187. (not found))
  188. (let ((inv-beg (caar inv-lst))
  189. (inv-end (cadar inv-lst)))
  190. (if (and (>= beg inv-beg)
  191. (<= end inv-end)
  192. (not (extent-property extent 'invisible)))
  193. (setq found t))
  194. (setq inv-lst (cdr inv-lst))))
  195. (if (not found)
  196. (nconc list
  197. (list (list beg 'push extent)
  198. (list end 'pull extent)))))
  199. nil)
  200. (provide 'ps-print-invisible)
  201. ;;; ps-print-invisible.el ends here