(insert-file-contents-as-binary): Share implementation.
[elisp/apel.git] / poem-om.el
1 ;;; poem-om.el --- poem implementation for Mule 1.* and Mule 2.*
2
3 ;; Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
4
5 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
6 ;;         Katsumi Yamaoka  <yamaoka@jpl.org>
7 ;; Keywords: emulation, compatibility, Mule
8
9 ;; This file is part of APEL (A Portable Emacs Library).
10
11 ;; This program is free software; you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation; either version 2, or (at
14 ;; your option) any later version.
15
16 ;; This program is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 ;; General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26 ;;; Code:
27
28 (require 'poe)
29
30
31 ;;; @ version specific features
32 ;;;
33
34 (cond ((= emacs-major-version 19)
35        ;; Suggested by SASAKI Osamu <osamu@shuugr.bekkoame.or.jp>
36        ;; (cf. [os2-emacs-ja:78])
37        (defun fontset-pixel-size (fontset)
38          (let* ((font (get-font-info
39                        (aref (cdr (get-fontset-info fontset)) 0)))
40                 (open (aref font 4)))
41            (if (= open 1)
42                (aref font 5)
43              (if (= open 0)
44                  (let ((pat (aref font 1)))
45                    (if (string-match "-[0-9]+-" pat)
46                        (string-to-number
47                         (substring
48                          pat (1+ (match-beginning 0)) (1- (match-end 0))))
49                      0))
50                ))))
51
52        (define-ccl-program ccl-decode-raw-text
53          '(1
54            ((read r1 r0)
55             (loop
56               (r2 = (r1 == ?\x0d))
57               (r2 &= (r0 == ?\x0a))
58               (if r2
59                   ((write ?\x0a)
60                    (read r1 r0)
61                    (repeat))
62                 ((write r1)
63                  (r1 = (r0 + 0))
64                  (read r0)
65                  (repeat)
66                  ))))
67            (write r1))
68          "Convert line-break code from CRLF to LF.")
69
70        (define-ccl-program ccl-encode-raw-text
71          '(1
72            ((read r0)
73             (loop (write-read-repeat r0))))
74          "Pass through without any conversions.")
75
76        (define-ccl-program ccl-encode-raw-text-CRLF
77          '(2
78            ((loop
79               (read r0)
80               (if (r0 == ?\x0a)
81                   (write "\x0d\x0a")
82                 (write r0))
83               (repeat))))
84          "Convert line-break code from LF to CRLF.")
85
86        (make-coding-system
87         'raw-text 4 ?=
88         "No conversion"
89         nil
90         (cons ccl-decode-raw-text ccl-encode-raw-text))
91
92        (make-coding-system
93         'raw-text-dos 4 ?=
94         "No conversion"
95         nil
96         (cons ccl-decode-raw-text ccl-encode-raw-text-CRLF))
97
98        (make-coding-system
99         'binary nil ?=
100         "No conversion")
101        ))
102
103
104 ;;; @ character set
105 ;;;
106
107 (defalias 'make-char 'make-character)
108
109 (defalias 'find-non-ascii-charset-string 'find-charset-string)
110 (defalias 'find-non-ascii-charset-region 'find-charset-region)
111
112 (defalias 'charset-bytes        'char-bytes)
113 (defalias 'charset-description  'char-description)
114 (defalias 'charset-registry     'char-registry)
115 (defalias 'charset-columns      'char-width)
116 (defalias 'charset-direction    'char-direction)
117
118 (defun charset-chars (charset)
119   "Return the number of characters per dimension of CHARSET."
120   (if (= (logand (nth 2 (character-set charset)) 1) 1)
121       96
122     94))
123
124
125 ;;; @ coding system
126 ;;;
127
128 (defun encode-coding-region (start end coding-system)
129   "Encode the text between START and END to CODING-SYSTEM.
130 \[EMACS 20 emulating function]"
131   ;; If `coding-system' is nil, do nothing.
132   (code-convert-region start end *internal* coding-system))
133
134 (defun decode-coding-region (start end coding-system)
135   "Decode the text between START and END which is encoded in CODING-SYSTEM.
136 \[EMACS 20 emulating function]"
137   ;; If `coding-system' is nil, do nothing.
138   (code-convert-region start end coding-system *internal*))
139
140 ;; XXX: Should we support optional NOCOPY argument? (only in Emacs 20.x)
141 (defun encode-coding-string (str coding-system)
142   "Encode the STRING to CODING-SYSTEM.
143 \[EMACS 20 emulating function]"
144   (if coding-system
145       (code-convert-string str *internal* coding-system)
146     ;;(code-convert-string str *internal* nil) returns nil instead of str.
147     str))
148
149 ;; XXX: Should we support optional NOCOPY argument? (only in Emacs 20.x)
150 (defun decode-coding-string (str coding-system)
151   "Decode the string STR which is encoded in CODING-SYSTEM.
152 \[EMACS 20 emulating function]"
153   (if coding-system
154       (let ((len (length str))
155             ret)
156         (while (and (< 0 len)
157                     (null (setq ret
158                                 (code-convert-string
159                                  (substring str 0 len)
160                                  coding-system *internal*))))
161           (setq len (1- len)))
162         (concat ret (substring str len)))
163     str))
164
165 (defalias 'detect-coding-region 'code-detect-region)
166
167 (defalias 'set-buffer-file-coding-system 'set-file-coding-system)
168
169
170 ;;; @ with code-conversion
171 ;;;
172
173 (defun insert-file-contents-as-coding-system
174   (coding-system filename &optional visit beg end replace)
175   "Like `insert-file-contents', q.v., but CODING-SYSTEM the first arg will
176 be applied to `file-coding-system-for-read'."
177   (let ((file-coding-system-for-read coding-system))
178     (insert-file-contents filename visit beg end replace)))
179
180 (cond
181  ((and (>= emacs-major-version 19) (>= emacs-minor-version 29))
182   ;; for MULE 2.3 based on Emacs 19.34.
183   (defun write-region-as-coding-system
184     (coding-system start end filename &optional append visit lockname)
185     "Like `write-region', q.v., but CODING-SYSTEM the first arg will be
186 applied to `file-coding-system'."
187     (let ((file-coding-system coding-system)
188           jka-compr-compression-info-list jam-zcat-filename-list)
189       (write-region start end filename append visit lockname)))
190
191   (defun find-file-noselect-as-coding-system
192     (coding-system filename &optional nowarn rawfile)
193     "Like `find-file-noselect', q.v., but CODING-SYSTEM the first arg will
194 be applied to `file-coding-system-for-read'."
195     (let ((file-coding-system-for-read coding-system))
196       (find-file-noselect filename nowarn rawfile)))
197   )
198  (t
199   ;; for MULE 2.3 based on Emacs 19.28 or MULE 1.*.
200   (defun write-region-as-coding-system
201     (coding-system start end filename &optional append visit lockname)
202     "Like `write-region', q.v., but CODING-SYSTEM the first arg will be
203 applied to `file-coding-system'."
204     (let ((file-coding-system coding-system)
205           jka-compr-compression-info-list jam-zcat-filename-list)
206       (write-region start end filename append visit)))
207
208   (defun find-file-noselect-as-coding-system
209     (coding-system filename &optional nowarn rawfile)
210     "Like `find-file-noselect', q.v., but CODING-SYSTEM the first arg will
211 be applied to `file-coding-system-for-read'."
212     (let ((file-coding-system-for-read coding-system))
213       (find-file-noselect filename nowarn)))
214   ))
215
216
217 ;;; @ without code-conversion
218 ;;;
219
220 (defmacro as-binary-process (&rest body)
221   (` (let (selective-display    ; Disable ^M to nl translation.
222            ;; Mule
223            mc-flag
224            (default-process-coding-system (cons *noconv* *noconv*))
225            program-coding-system-alist)
226        (,@ body))))
227
228 (defmacro as-binary-input-file (&rest body)
229   (` (let (mc-flag
230            (file-coding-system-for-read *noconv*)
231            )
232        (,@ body))))
233
234 (defmacro as-binary-output-file (&rest body)
235   (` (let (mc-flag
236            (file-coding-system *noconv*)
237            )
238        (,@ body))))
239
240 (defalias 'set-process-input-coding-system 'set-process-coding-system)
241
242 (defun insert-binary-file-contents-literally (filename
243                                               &optional visit beg end replace)
244   "Like `insert-file-contents-literally', q.v., but don't code conversion.
245 A buffer may be modified in several ways after reading into the buffer due
246 to advanced Emacs features, such as file-name-handlers, format decoding,
247 find-file-hooks, etc.
248   This function ensures that none of these modifications will take place."
249   (as-binary-input-file
250    ;; Returns list absolute file name and length of data inserted.
251    (insert-file-contents-literally filename visit beg end replace)))
252
253 (defun insert-file-contents-as-binary (filename
254                                        &optional visit beg end replace)
255   "Like `insert-file-contents', q.v., but don't code and format conversion.
256 Like `insert-file-contents-literary', but it allows find-file-hooks,
257 automatic uncompression, etc.
258
259 Namely this function ensures that only format decoding and character
260 code conversion will not take place."
261   (as-binary-input-file
262    ;; Returns list absolute file name and length of data inserted.
263    (insert-file-contents filename visit beg end replace)))
264
265 (cond
266  ((>= emacs-major-version 19)
267   ;; for MULE 2.*.
268   (defun insert-file-contents-as-raw-text (filename
269                                            &optional visit beg end replace)
270     "Like `insert-file-contents', q.v., but don't code and format conversion.
271 Like `insert-file-contents-literary', but it allows find-file-hooks,
272 automatic uncompression, etc.
273 Like `insert-file-contents-as-binary', but it converts line-break
274 code."
275     ;; Returns list absolute file name and length of data inserted.
276     (insert-file-contents-as-coding-system 'raw-text
277                                            filename visit beg end replace))
278
279   (defun write-region-as-binary (start end filename
280                                        &optional append visit lockname)
281     "Like `write-region', q.v., but don't code conversion."
282     (write-region-as-coding-system 'binary
283                                    start end filename append visit lockname))
284
285   (defun write-region-as-raw-text-CRLF (start end filename
286                                               &optional append visit lockname)
287     "Like `write-region', q.v., but don't code conversion."
288     (write-region-as-coding-system 'raw-text-dos
289                                    start end filename append visit lockname))
290
291   (defun find-file-noselect-as-binary (filename &optional nowarn rawfile)
292     "Like `find-file-noselect', q.v., but don't code and format conversion."
293     (find-file-noselect-as-coding-system 'binary
294                                          filename nowarn rawfile))
295
296   (defun find-file-noselect-as-raw-text (filename &optional nowarn rawfile)
297     "Like `find-file-noselect', q.v., but it does not code and format
298 conversion except for line-break code."
299     (find-file-noselect-as-coding-system 'raw-text
300                                          filename nowarn rawfile))
301   )
302  (t
303   ;; for MULE 1.*.
304   (defun insert-file-contents-as-raw-text (filename
305                                            &optional visit beg end replace)
306     "Like `insert-file-contents', q.v., but don't code and format conversion.
307 Like `insert-file-contents-literary', but it allows find-file-hooks,
308 automatic uncompression, etc.
309 Like `insert-file-contents-as-binary', but it converts line-break
310 code."
311     (save-excursion
312       (save-restriction
313         (narrow-to-region (point)(point))
314         (let ((return-val
315                ;; Returns list absolute file name and length of data inserted.
316                (insert-file-contents-as-binary filename
317                                                visit beg end replace)))
318           (goto-char (point-min))
319           (while (re-search-forward "\r$" nil t)
320             (replace-match ""))
321           (list (car return-val) (buffer-size))))))
322
323   (defun write-region-as-binary (start end filename
324                                        &optional append visit lockname)
325     "Like `write-region', q.v., but don't code conversion."
326     (as-binary-output-file
327      (write-region start end filename append visit)))
328
329   (defun write-region-as-raw-text-CRLF (start end filename
330                                               &optional append visit lockname)
331     "Like `write-region', q.v., but don't code conversion."
332     (let ((the-buf (current-buffer)))
333       (with-temp-buffer
334         (insert-buffer-substring the-buf start end)
335         (goto-char (point-min))
336         (while (re-search-forward "\\(\\=\\|[^\r]\\)\n" nil t)
337           (replace-match "\\1\r\n"))
338         (write-region-as-binary (point-min)(point-max)
339                                 filename append visit))))
340
341   (defun find-file-noselect-as-binary (filename &optional nowarn rawfile)
342     "Like `find-file-noselect', q.v., but don't code and format conversion."
343     (as-binary-input-file (find-file-noselect filename nowarn)))
344
345   (defun find-file-noselect-as-raw-text (filename &optional nowarn rawfile)
346     "Like `find-file-noselect', q.v., but it does not code and format
347 conversion except for line-break code."
348     (save-current-buffer
349       (prog1
350           (set-buffer (find-file-noselect-as-binary filename nowarn rawfile))
351         (let ((flag (buffer-modified-p)))
352           (save-excursion
353             (goto-char (point-min))
354             (while (re-search-forward "\r$" nil t)
355               (replace-match "")))
356           (set-buffer-modified-p flag)))))
357   ))
358
359 (defun open-network-stream-as-binary (name buffer host service)
360   "Like `open-network-stream', q.v., but don't code conversion."
361   (let ((process (open-network-stream name buffer host service)))
362     (set-process-coding-system process *noconv* *noconv*)
363     process))
364
365
366 ;;; @ buffer representation
367 ;;;
368
369 (defsubst-maybe set-buffer-multibyte (flag)
370   "Set the multibyte flag of the current buffer to FLAG.
371 If FLAG is t, this makes the buffer a multibyte buffer.
372 If FLAG is nil, this makes the buffer a single-byte buffer.
373 The buffer contents remain unchanged as a sequence of bytes
374 but the contents viewed as characters do change.
375 \[Emacs 20.3 emulating function]"
376   (setq mc-flag flag)
377   )
378
379
380 ;;; @ character
381 ;;;
382
383 (defalias 'char-charset 'char-leading-char)
384
385 (defun split-char (character)
386   "Return list of charset and one or two position-codes of CHARACTER."
387   (let ((p (1- (char-bytes character)))
388         dest)
389     (while (>= p 1)
390       (setq dest (cons (- (char-component character p) 128) dest)
391             p (1- p)))
392     (cons (char-charset character) dest)))
393
394 (defmacro char-next-index (char index)
395   "Return index of character succeeding CHAR whose index is INDEX."
396   (` (+ (, index) (char-bytes (, char)))))
397
398 (if (subr-fboundp 'char-before)
399     (condition-case err
400         (char-before)
401       (error
402        (when (and (eq (car (get (car err) 'error-conditions))
403                       'wrong-number-of-arguments)
404                   (not (boundp 'si:char-before)))
405          (fset 'si:char-before (symbol-function 'char-before))
406          (defun char-before (&optional pos)
407            "Return character in current buffer preceding position POS.
408 POS is an integer or a buffer pointer.
409 If POS is out of range, the value is nil."
410            (si:char-before (or pos (point)))
411            )))))
412
413 (if (subr-fboundp 'char-after)
414     (condition-case err
415         (char-after)
416       (error
417        (when (and (eq (car (get (car err) 'error-conditions))
418                       'wrong-number-of-arguments)
419                   (not (boundp 'si:char-after)))
420          (fset 'si:char-after (symbol-function 'char-after))
421          (defun char-after (&optional pos)
422            "Return character in current buffer at position POS.
423 POS is an integer or a buffer pointer.
424 If POS is out of range, the value is nil."
425            (si:char-after (or pos (point)))
426            )))))
427
428 ;;; @@ obsoleted aliases
429 ;;;
430 ;;; You should not use them.
431
432 (defalias 'char-length 'char-bytes)
433 ;;(defalias 'char-columns 'char-width)
434
435
436 ;;; @ string
437 ;;;
438
439 (defalias 'string-columns 'string-width)
440
441 (defalias 'string-to-int-list 'string-to-char-list)
442
443 ;; Imported from Mule-2.3
444 (defun-maybe truncate-string (str width &optional start-column)
445   "\
446 Truncate STR to fit in WIDTH columns.
447 Optional non-nil arg START-COLUMN specifies the starting column.
448 \[emu-mule.el; Mule 2.3 emulating function]"
449   (or start-column
450       (setq start-column 0))
451   (let ((max-width (string-width str))
452         (len (length str))
453         (from 0)
454         (column 0)
455         to-prev to ch)
456     (if (>= width max-width)
457         (setq width max-width))
458     (if (>= start-column width)
459         ""
460       (while (< column start-column)
461         (setq ch (aref str from)
462               column (+ column (char-width ch))
463               from (+ from (char-bytes ch))))
464       (if (< width max-width)
465           (progn
466             (setq to from)
467             (while (<= column width)
468               (setq ch (aref str to)
469                     column (+ column (char-width ch))
470                     to-prev to
471                     to (+ to (char-bytes ch))))
472             (setq to to-prev)))
473       (substring str from to))))
474
475 (defalias 'looking-at-as-unibyte 'looking-at)
476
477
478 ;;; @ end
479 ;;;
480
481 (provide 'poem-om)
482
483 ;;; poem-om.el ends here