buffers.sl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. %
  2. % Buffers.SL - Buffer Collection Manipulation Functions
  3. %
  4. % Author: Alan Snyder
  5. % Hewlett-Packard/CRC
  6. % Date: 12 July 1982
  7. %
  8. % Further changes by Will Galway, University of Utah.
  9. % This file contains functions that manipulate the set of existing
  10. % buffers. It is intended that someday EMODE will be reorganized
  11. % so that all such functions will eventually be in this file.
  12. %
  13. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  14. % 5-Aug-82, WFG:
  15. % Some functions moved here from EMODE1.RED, changes made to
  16. % support arbitrary "data-modes".
  17. (load common)
  18. (fluid '(declared_data_modes BufferNames CurrentBufferName))
  19. (setf declared_data_modes NIL)
  20. % Declare (or redeclare) a "data-mode" name and associated routine for
  21. % creating a buffer of that mode.
  22. % Also see "declare_file_mode", used to associate data modes with filenames
  23. % (or "file extensions").
  24. (de declare_data_mode (name buffer-creator)
  25. (let ((old-decl (Ass (function string-equal) name declared_data_modes)))
  26. (cond
  27. (old-decl
  28. (setf (cdr old-decl) buffer-creator))
  29. (T
  30. (setf declared_data_modes
  31. (cons (cons name buffer-creator) declared_data_modes))))))
  32. % Create a buffer with name given by BufferName (an identifier), using
  33. % routine buffer-creator to create the buffer's environment. Puts the
  34. % (name . environment) pair into "BufferNames" alist, returns the
  35. % environment.
  36. (de CreateBuffer (BufferName buffer-creator)
  37. (cond
  38. ((atsoc BufferName BufferNames)
  39. % Complain if the buffer already exists.
  40. (EMODEError (list "Buffer" BufferName "exists")))
  41. % Otherwise, enter the (name . environment) pair into the association
  42. % list of buffers.
  43. (T
  44. (let ((env (apply buffer-creator NIL)))
  45. (setf BufferNames
  46. (cons (cons BufferName env) BufferNames))
  47. env))))
  48. % Switch to a new current buffer, creating it if necessary. (But without
  49. % establishing that buffer's keyboard bindings.) Use buffer-creator to
  50. % create the buffer, or ask the user for a hint if buffer-creator is NIL.
  51. % Create a "view" of the selected buffer, "destroying" the "current view".
  52. % NEED TO contrast this with "SelectBuffer", which (in effect) gives us an
  53. % "invisible view" (or "internal view"?) of a buffer? (A "view" to be used
  54. % for internal purposes, rather than for use from the keyboard.)
  55. (de select_or_create_buffer (buffer-name buffer-creator)
  56. (cond
  57. % Don't do anything if trying to select the "current buffer".
  58. ((not (eq buffer-name CurrentBufferName))
  59. (prog (new-env)
  60. (return
  61. (cond
  62. % Just select the buffer if it's already present.
  63. ((setf new-env (atsoc buffer-name BufferNames))
  64. (setf new-env (cdr new-env)) % get cdr of (name . env)
  65. % Now "look into" the newly selected buffer.
  66. % Get rid of the current "view", replace it with the new
  67. % view. Go through fancy foot work to create new view in
  68. % context of current view.
  69. (let ((new-view
  70. (apply
  71. (cdr (atsoc 'buffers_view_creator new-env))
  72. (list buffer-name))))
  73. (remove_current_view)
  74. (SelectWindow new-view)))
  75. % Otherwise, create the new buffer if not already around.
  76. (T
  77. (while (null buffer-creator)
  78. (let
  79. ((mode-name
  80. (prompt_for_string
  81. (BldMsg "Mode for buffer %w: " buffer-name)
  82. % Default mode-name is "text", should this be
  83. % parameterized?
  84. "text"
  85. )))
  86. % Use "generalized assoc" function to look up the
  87. % associated creator, if any.
  88. (setf buffer-creator
  89. (Ass
  90. (function string-equal)
  91. mode-name
  92. declared_data_modes))
  93. % "Beep" if unknown mode-name (and ask again).
  94. (cond
  95. ((null buffer-creator) (ding))
  96. % Otherwise, extract "good part" of (mode-name .
  97. % buffer-creator) pair.
  98. (T
  99. (setf buffer-creator (cdr buffer-creator))))))
  100. (show_message (BldMsg "Creating buffer %w" buffer-name))
  101. (setf new-env (CreateBuffer buffer-name buffer-creator))
  102. % Get rid of the current "view", replace it with the new view.
  103. (let ((new-view
  104. (apply
  105. (cdr (atsoc 'buffers_view_creator new-env))
  106. (list buffer-name))))
  107. (remove_current_view)
  108. (SelectWindow new-view)))))))))
  109. % "Choose" a buffer (name taken from keyboard), make it the current buffer
  110. % and establish its mode as the current mode.
  111. (de ChooseBuffer ()
  112. (let
  113. ((buffer-name
  114. (String-UpCase (prompt_for_string "Buffer Name: "
  115. last_buffername))))
  116. % Strings with 1 character have size 0, avoid creating something with
  117. % the empty string for a name!
  118. (cond
  119. ((Geq (size buffer-name) 0)
  120. % Set up new default buffername for next ChooseBuffer.
  121. (setf last_buffername (Id2String CurrentBufferName))
  122. (select_or_create_buffer (intern buffer-name) NIL)
  123. (EstablishCurrentMode)))))
  124. % Create a (default) "view" (or "window") into a text buffer. Details of
  125. % the window location (etc?) depend on the current window layout.
  126. (de create_text_view (buffer-name)
  127. (cond
  128. % If the current buffer also uses a "text view".
  129. ((eq buffers_view_creator (function create_text_view))
  130. % Just modify (destructively) the current "view" (or "window")
  131. % environment to look into the new buffer, return the current
  132. % environment.
  133. (SelectBuffer buffer-name)
  134. % Let window know what buffer it's looking into (wierd)!
  135. (setf WindowsBufferName buffer-name)
  136. % Save (and return) the current "view" environment.
  137. (SaveEnv CurrentWindowDescriptor))
  138. % Otherwise (if current view isn't into "text"), create a framed window
  139. % of an appropriate size and at an appropriate location.
  140. % (For lack of a better idea, just use a window like that used by "two
  141. % window" mode.)
  142. (T
  143. % Make sure two_window_midpoint is a reasonable value.
  144. (cond
  145. ((or
  146. (not (numberp two_window_midpoint))
  147. (LessP two_window_midpoint 3)
  148. (GreaterP two_window_midpoint (difference (row ScreenDelta) 5)))
  149. (setf two_window_midpoint
  150. (fix (times 0.5 (difference (row ScreenDelta) 2))))))
  151. (FramedWindowDescriptor
  152. buffer-name
  153. % Upper left corner
  154. (coords
  155. (sub1 (Column ScreenBase))
  156. (plus (Row ScreenBase) two_window_midpoint 1))
  157. (coords
  158. (plus 2 (Column ScreenDelta))
  159. (plus (difference (row ScreenDelta) two_window_midpoint) -2))))))
  160. % Declare the routine for creating "text mode" buffers.
  161. (declare_data_mode "text" 'create_text_buffer)
  162. % Return the environment for a "raw" text buffer (everything except
  163. % keyboard bindings).
  164. (de create_raw_text_buffer ()
  165. % Environment bindings for this buffer.
  166. % May prefer to use backquote to do this, but current version is buggy
  167. % for lists of the form `( (a .b) ). Also, it's important not to share
  168. % any substructure with other alists built by this routine.
  169. (list
  170. % The following 4 "per buffer" variables should be defined for a buffer
  171. % of any "data mode". Also need to define ModeEstablishExpressions,
  172. % but that's left to the caller of this routine.
  173. (cons 'buffers_view_creator 'create_text_view)
  174. (cons 'buffers_file_reader 'read_channel_into_text_buffer)
  175. (cons 'buffers_file_writer 'write_text_buffer_to_channel)
  176. (cons 'buffers_file NIL) % Name of file associated with buffer.
  177. % Variables unique to "text data mode" follow.
  178. % Initial vector allows only one line. (Should really be parameterized
  179. % somehow?)
  180. (cons 'CurrentBufferText (MkVect 0)) % 0 is upper bound, one element.
  181. (cons 'CurrentBufferSize 1) % Start with one line of text (but zero
  182. % characters in the line! )
  183. (cons 'CurrentLine NIL)
  184. (cons 'CurrentLineIndex 0)
  185. (cons 'point 0)
  186. % MarkLineIndex corresponds to CurrentLineIndex, but for "mark".
  187. (cons 'MarkLineIndex 0)
  188. (cons 'MarkPoint 0) % Corresponds to "point".
  189. ))
  190. % Create a text buffer--uses "raw text" environment "plus" keyboard
  191. % bindings appropriate for "text".
  192. (de create_text_buffer ()
  193. (cons
  194. (cons 'ModeEstablishExpressions FundamentalTextMode)
  195. (create_raw_text_buffer)))
  196. (declare_data_mode "rlisp" 'create_rlisp_buffer)
  197. (declare_data_mode "lisp" 'create_lisp_buffer)
  198. % Return the environment for a new "Rlisp" buffer.
  199. (de create_rlisp_buffer ()
  200. % Same as "text buffer" but with a different keyboard dispatch table.
  201. (cons
  202. (cons 'ModeEstablishExpressions RlispMode)
  203. (create_raw_text_buffer)))
  204. % Return the environment for a new "lisp" buffer.
  205. (de create_lisp_buffer ()
  206. (cons
  207. (cons 'ModeEstablishExpressions LispMode)
  208. (create_raw_text_buffer)))
  209. (de buffer-create (buffer-name buffer-creator)
  210. % Create a new buffer. The name of the new buffer will be the specified name
  211. % if no buffer already exists with that name. Otherwise, a similar name will
  212. % be chosen. The actual buffer name is returned. The buffer is not
  213. % selected.
  214. (setq buffer-name (buffer-make-unique-name buffer-name))
  215. (CreateBuffer buffer-name buffer-creator)
  216. buffer-name
  217. )
  218. (de buffer-make-unique-name (buffer-name)
  219. % Return a buffer name not equal to the name of any existing buffer.
  220. (for*
  221. (with (root-name (string-concat (id2string buffer-name) "-")))
  222. (for count 0 (+ count 1))
  223. (for name buffer-name
  224. (intern (string-concat root-name (BldMsg "%d" count))))
  225. (do (if (not (buffer-exists name)) (exit name)))
  226. ))
  227. (de buffer-exists (buffer-name)
  228. (atsoc buffer-name BufferNames))
  229. (de buffer-kill (buffer-name)
  230. (if (and (buffer-exists buffer-name) (> (length BufferNames) 1))
  231. (progn
  232. (setq BufferNames (DelatQ buffer-name BufferNames))
  233. (if (eq CurrentBufferName buffer-name)
  234. (progn (setq CurrentBufferName nil)
  235. (SelectBuffer (car (car BufferNames)))))
  236. (if (eq WindowsBufferName buffer-name)
  237. (setq WindowsBufferName CurrentBufferName))
  238. ))
  239. )
  240. (de select-buffer-if-existing (buffer-name)
  241. % This function will select and establish the specified buffer, if it exists.
  242. % Otherwise, it will select and establish an arbitrary existing buffer.
  243. (prog (buffer-env)
  244. (if (setq buffer-env (atsoc buffer-name BufferNames))
  245. (setq buffer-env (cdr buffer-env))
  246. (if (setq buffer-env (atsoc 'MAIN BufferNames))
  247. (progn (setq buffer-name 'MAIN) (setq buffer-env (cdr buffer-env)))
  248. (progn
  249. (setq buffer-name (car (car BufferNames)))
  250. (setq buffer-env (cdr (car BufferNames)))
  251. )
  252. ))
  253. (if CurrentBufferName (DeSelectBuffer CurrentBufferName))
  254. (RestoreEnv buffer-env)
  255. (setq CurrentBufferName buffer-name)
  256. (EstablishCurrentMode)
  257. ))