~ubuntu-branches/ubuntu/intrepid/ecl/intrepid

« back to all changes in this revision

Viewing changes to src/clx/dependent.lisp

  • Committer: Bazaar Package Importer
  • Author(s): Peter Van Eynde
  • Date: 2006-05-17 02:46:26 UTC
  • Revision ID: james.westby@ubuntu.com-20060517024626-lljr08ftv9g9vefl
Tags: upstream-0.9h-20060510
ImportĀ upstreamĀ versionĀ 0.9h-20060510

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;; -*- Mode: Lisp; Package: Xlib; Log: clx.log -*-
 
2
 
 
3
;; This file contains some of the system dependent code for CLX
 
4
 
 
5
;;;
 
6
;;;                      TEXAS INSTRUMENTS INCORPORATED
 
7
;;;                               P.O. BOX 2909
 
8
;;;                            AUSTIN, TEXAS 78769
 
9
;;;
 
10
;;; Copyright (C) 1987 Texas Instruments Incorporated.
 
11
;;;
 
12
;;; Permission is granted to any individual or institution to use, copy, modify,
 
13
;;; and distribute this software, provided that this complete copyright and
 
14
;;; permission notice is maintained, intact, in all copies and supporting
 
15
;;; documentation.
 
16
;;;
 
17
;;; Texas Instruments Incorporated provides this software "as is" without
 
18
;;; express or implied warranty.
 
19
;;;
 
20
 
 
21
(in-package :xlib)
 
22
 
 
23
(proclaim '(declaration array-register))
 
24
 
 
25
#+cmu
 
26
(setf (getf ext:*herald-items* :xlib)
 
27
      `("    CLX X Library " ,*version*))
 
28
 
 
29
 
 
30
;;; The size of the output buffer.  Must be a multiple of 4.
 
31
(defparameter *output-buffer-size* 8192)
 
32
 
 
33
#+explorer
 
34
(zwei:define-indentation event-case (1 1))
 
35
 
 
36
;;; Number of seconds to wait for a reply to a server request
 
37
(defparameter *reply-timeout* nil) 
 
38
 
 
39
#-(or clx-overlapping-arrays (not clx-little-endian))
 
40
(progn
 
41
  (defconstant +word-0+ 0)
 
42
  (defconstant +word-1+ 1)
 
43
 
 
44
  (defconstant +long-0+ 0)
 
45
  (defconstant +long-1+ 1)
 
46
  (defconstant +long-2+ 2)
 
47
  (defconstant +long-3+ 3))
 
48
 
 
49
#-(or clx-overlapping-arrays clx-little-endian)
 
50
(progn
 
51
  (defconstant +word-0+ 1)
 
52
  (defconstant +word-1+ 0)
 
53
 
 
54
  (defconstant +long-0+ 3)
 
55
  (defconstant +long-1+ 2)
 
56
  (defconstant +long-2+ 1)
 
57
  (defconstant +long-3+ 0))
 
58
 
 
59
;;; Set some compiler-options for often used code
 
60
 
 
61
(eval-when (:compile-toplevel :load-toplevel :execute)
 
62
  (defconstant +buffer-speed+ #+clx-debugging 1 #-clx-debugging 3
 
63
    "Speed compiler option for buffer code.")
 
64
  (defconstant +buffer-safety+ #+clx-debugging 3 #-clx-debugging 0
 
65
    "Safety compiler option for buffer code.")
 
66
  (defconstant +buffer-debug+ #+clx-debugging 2 #-clx-debugging 1
 
67
    "Debug compiler option for buffer code>")
 
68
  (defun declare-bufmac ()
 
69
    `(declare (optimize
 
70
               (speed ,+buffer-speed+)
 
71
               (safety ,+buffer-safety+)
 
72
               (debug ,+buffer-debug+))))
 
73
  ;; It's my impression that in lucid there's some way to make a
 
74
  ;; declaration called fast-entry or something that causes a function
 
75
  ;; to not do some checking on args. Sadly, we have no lucid manuals
 
76
  ;; here.  If such a declaration is available, it would be a good
 
77
  ;; idea to make it here when +buffer-speed+ is 3 and +buffer-safety+
 
78
  ;; is 0.
 
79
  (defun declare-buffun ()
 
80
    `(declare (optimize
 
81
               (speed ,+buffer-speed+)
 
82
               (safety ,+buffer-safety+)
 
83
               (debug ,+buffer-debug+)))))
 
84
 
 
85
(declaim (inline card8->int8 int8->card8
 
86
                 card16->int16 int16->card16
 
87
                 card32->int32 int32->card32))
 
88
 
 
89
#-Genera
 
90
(progn
 
91
 
 
92
(defun card8->int8 (x)
 
93
  (declare (type card8 x))
 
94
  (declare (clx-values int8))
 
95
  #.(declare-buffun)
 
96
  (the int8 (if (logbitp 7 x)
 
97
                (the int8 (- x #x100))
 
98
              x)))
 
99
 
 
100
(defun int8->card8 (x)
 
101
  (declare (type int8 x))
 
102
  (declare (clx-values card8))
 
103
  #.(declare-buffun)
 
104
  (the card8 (ldb (byte 8 0) x)))
 
105
 
 
106
(defun card16->int16 (x)
 
107
  (declare (type card16 x))
 
108
  (declare (clx-values int16))
 
109
  #.(declare-buffun)
 
110
  (the int16 (if (logbitp 15 x)
 
111
                 (the int16 (- x #x10000))
 
112
                 x)))
 
113
 
 
114
(defun int16->card16 (x)
 
115
  (declare (type int16 x))
 
116
  (declare (clx-values card16))
 
117
  #.(declare-buffun)
 
118
  (the card16 (ldb (byte 16 0) x)))
 
119
 
 
120
(defun card32->int32 (x)
 
121
  (declare (type card32 x))
 
122
  (declare (clx-values int32))
 
123
  #.(declare-buffun)
 
124
  (the int32 (if (logbitp 31 x)
 
125
                 (the int32 (- x #x100000000))
 
126
                 x)))
 
127
 
 
128
(defun int32->card32 (x)
 
129
  (declare (type int32 x))
 
130
  (declare (clx-values card32))
 
131
  #.(declare-buffun)
 
132
  (the card32 (ldb (byte 32 0) x)))
 
133
 
 
134
)
 
135
 
 
136
#+Genera
 
137
(progn
 
138
 
 
139
(defun card8->int8 (x)
 
140
  (declare lt:(side-effects simple reducible))
 
141
  (if (logbitp 7 x) (- x #x100) x))
 
142
 
 
143
(defun int8->card8 (x)
 
144
  (declare lt:(side-effects simple reducible))
 
145
  (ldb (byte 8 0) x))
 
146
 
 
147
(defun card16->int16 (x)
 
148
  (declare lt:(side-effects simple reducible))
 
149
  (if (logbitp 15 x) (- x #x10000) x))
 
150
 
 
151
(defun int16->card16 (x)
 
152
  (declare lt:(side-effects simple reducible))
 
153
  (ldb (byte 16 0) x))
 
154
 
 
155
(defun card32->int32 (x)
 
156
  (declare lt:(side-effects simple reducible))
 
157
  (sys:%logldb (byte 32 0) x))
 
158
 
 
159
(defun int32->card32 (x)
 
160
  (declare lt:(side-effects simple reducible))
 
161
  (ldb (byte 32 0) x))
 
162
 
 
163
)
 
164
 
 
165
(declaim (inline aref-card8 aset-card8 aref-int8 aset-int8))
 
166
 
 
167
#-(or Genera lcl3.0 excl)
 
168
(progn
 
169
 
 
170
(defun aref-card8 (a i)
 
171
  (declare (type buffer-bytes a)
 
172
           (type array-index i))
 
173
  (declare (clx-values card8))
 
174
  #.(declare-buffun)
 
175
  (the card8 (aref a i)))
 
176
 
 
177
(defun aset-card8 (v a i)
 
178
  (declare (type card8 v)
 
179
           (type buffer-bytes a)
 
180
           (type array-index i))
 
181
  #.(declare-buffun)
 
182
  (setf (aref a i) v))
 
183
 
 
184
(defun aref-int8 (a i)
 
185
  (declare (type buffer-bytes a)
 
186
           (type array-index i))
 
187
  (declare (clx-values int8))
 
188
  #.(declare-buffun)
 
189
  (card8->int8 (aref a i)))
 
190
 
 
191
(defun aset-int8 (v a i)
 
192
  (declare (type int8 v)
 
193
           (type buffer-bytes a)
 
194
           (type array-index i))
 
195
  #.(declare-buffun)
 
196
  (setf (aref a i) (int8->card8 v)))
 
197
 
 
198
)
 
199
 
 
200
#+Genera
 
201
(progn
 
202
 
 
203
(defun aref-card8 (a i)
 
204
  (aref a i))
 
205
 
 
206
(defun aset-card8 (v a i)
 
207
  (zl:aset v a i))
 
208
 
 
209
(defun aref-int8 (a i)
 
210
  (card8->int8 (aref a i)))
 
211
 
 
212
(defun aset-int8 (v a i)
 
213
  (zl:aset (int8->card8 v) a i))
 
214
 
 
215
)
 
216
 
 
217
#+(or excl lcl3.0 clx-overlapping-arrays)
 
218
(declaim (inline aref-card16 aref-int16 aref-card32 aref-int32 aref-card29
 
219
                 aset-card16 aset-int16 aset-card32 aset-int32 aset-card29))
 
220
 
 
221
#+(and clx-overlapping-arrays Genera)
 
222
(progn
 
223
 
 
224
(defun aref-card16 (a i)
 
225
  (aref a i))
 
226
 
 
227
(defun aset-card16 (v a i)
 
228
  (zl:aset v a i))
 
229
 
 
230
(defun aref-int16 (a i)
 
231
  (card16->int16 (aref a i)))
 
232
 
 
233
(defun aset-int16 (v a i)
 
234
  (zl:aset (int16->card16 v) a i)
 
235
  v)
 
236
 
 
237
(defun aref-card32 (a i)
 
238
  (int32->card32 (aref a i)))
 
239
 
 
240
(defun aset-card32 (v a i)
 
241
  (zl:aset (card32->int32 v) a i))
 
242
 
 
243
(defun aref-int32 (a i) (aref a i))
 
244
 
 
245
(defun aset-int32 (v a i)
 
246
  (zl:aset v a i))
 
247
 
 
248
(defun aref-card29 (a i)
 
249
  (aref a i))
 
250
 
 
251
(defun aset-card29 (v a i)
 
252
  (zl:aset v a i))
 
253
 
 
254
)
 
255
 
 
256
#+(and clx-overlapping-arrays (not Genera))
 
257
(progn
 
258
 
 
259
(defun aref-card16 (a i)
 
260
  (aref a i))
 
261
 
 
262
(defun aset-card16 (v a i)
 
263
  (setf (aref a i) v))
 
264
 
 
265
(defun aref-int16 (a i)
 
266
  (card16->int16 (aref a i)))
 
267
 
 
268
(defun aset-int16 (v a i)
 
269
  (setf (aref a i) (int16->card16 v))
 
270
  v)
 
271
 
 
272
(defun aref-card32 (a i)
 
273
  (aref a i))
 
274
 
 
275
(defun aset-card32 (v a i)
 
276
  (setf (aref a i) v))
 
277
 
 
278
(defun aref-int32 (a i)
 
279
  (card32->int32 (aref a i)))
 
280
 
 
281
(defun aset-int32 (v a i)
 
282
  (setf (aref a i) (int32->card32 v))
 
283
  v)
 
284
 
 
285
(defun aref-card29 (a i)
 
286
  (aref a i))
 
287
 
 
288
(defun aset-card29 (v a i)
 
289
  (setf (aref a i) v))
 
290
 
 
291
)
 
292
 
 
293
#+excl
 
294
(progn
 
295
  
 
296
(defun aref-card8 (a i)
 
297
  (declare (type buffer-bytes a)
 
298
           (type array-index i))
 
299
  (declare (clx-values card8))
 
300
  #.(declare-buffun)
 
301
  (the card8 (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
302
                         :unsigned-byte)))
 
303
 
 
304
(defun aset-card8 (v a i)
 
305
  (declare (type card8 v)
 
306
           (type buffer-bytes a)
 
307
           (type array-index i))
 
308
  #.(declare-buffun)
 
309
  (setf (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
310
                    :unsigned-byte) v))
 
311
 
 
312
(defun aref-int8 (a i)
 
313
  (declare (type buffer-bytes a)
 
314
           (type array-index i))
 
315
  (declare (clx-values int8))
 
316
  #.(declare-buffun)
 
317
  (the int8 (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
318
                        :signed-byte)))
 
319
 
 
320
(defun aset-int8 (v a i)
 
321
  (declare (type int8 v)
 
322
           (type buffer-bytes a)
 
323
           (type array-index i))
 
324
  #.(declare-buffun)
 
325
  (setf (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
326
                    :signed-byte) v))
 
327
 
 
328
(defun aref-card16 (a i)
 
329
  (declare (type buffer-bytes a)
 
330
           (type array-index i))
 
331
  (declare (clx-values card16))
 
332
  #.(declare-buffun)
 
333
  (the card16 (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
334
                          :unsigned-word)))
 
335
  
 
336
(defun aset-card16 (v a i)
 
337
  (declare (type card16 v)
 
338
           (type buffer-bytes a)
 
339
           (type array-index i))
 
340
  #.(declare-buffun)
 
341
  (setf (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
342
                    :unsigned-word) v))
 
343
  
 
344
(defun aref-int16 (a i)
 
345
  (declare (type buffer-bytes a)
 
346
           (type array-index i))
 
347
  (declare (clx-values int16))
 
348
  #.(declare-buffun)
 
349
  (the int16 (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
350
                         :signed-word)))
 
351
  
 
352
(defun aset-int16 (v a i)
 
353
  (declare (type int16 v)
 
354
           (type buffer-bytes a)
 
355
           (type array-index i))
 
356
  #.(declare-buffun)
 
357
  (setf (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
358
                    :signed-word) v))
 
359
  
 
360
(defun aref-card32 (a i)
 
361
  (declare (type buffer-bytes a)
 
362
           (type array-index i))
 
363
  (declare (clx-values card32))
 
364
  #.(declare-buffun)
 
365
  (the card32 (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
366
                          :unsigned-long)))
 
367
    
 
368
(defun aset-card32 (v a i)
 
369
  (declare (type card32 v)
 
370
           (type buffer-bytes a)
 
371
           (type array-index i))
 
372
  #.(declare-buffun)
 
373
  (setf (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
374
                    :unsigned-long) v))
 
375
 
 
376
(defun aref-int32 (a i)
 
377
  (declare (type buffer-bytes a)
 
378
           (type array-index i))
 
379
  (declare (clx-values int32))
 
380
  #.(declare-buffun)
 
381
  (the int32 (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
382
                         :signed-long)))
 
383
    
 
384
(defun aset-int32 (v a i)
 
385
  (declare (type int32 v)
 
386
           (type buffer-bytes a)
 
387
           (type array-index i))
 
388
  #.(declare-buffun)
 
389
  (setf (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
390
                    :signed-long) v))
 
391
 
 
392
(defun aref-card29 (a i)
 
393
  (declare (type buffer-bytes a)
 
394
           (type array-index i))
 
395
  (declare (clx-values card29))
 
396
  #.(declare-buffun)
 
397
  (the card29 (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
398
                          :unsigned-long)))
 
399
 
 
400
(defun aset-card29 (v a i)
 
401
  (declare (type card29 v)
 
402
           (type buffer-bytes a)
 
403
           (type array-index i))
 
404
  #.(declare-buffun)
 
405
  (setf (sys:memref a #.(comp::mdparam 'comp::md-svector-data0-adj) i
 
406
                    :unsigned-long) v))
 
407
  
 
408
)
 
409
 
 
410
#+lcl3.0
 
411
(progn
 
412
 
 
413
(defun aref-card8 (a i)
 
414
  (declare (type buffer-bytes a)
 
415
           (type array-index i)
 
416
           (clx-values card8))
 
417
  #.(declare-buffun)
 
418
  (the card8 (lucid::%svref-8bit a i)))
 
419
 
 
420
(defun aset-card8 (v a i)
 
421
  (declare (type card8 v)
 
422
           (type buffer-bytes a)
 
423
           (type array-index i))
 
424
  #.(declare-buffun)
 
425
  (setf (lucid::%svref-8bit a i) v))
 
426
 
 
427
(defun aref-int8 (a i)
 
428
  (declare (type buffer-bytes a)
 
429
           (type array-index i)
 
430
           (clx-values int8))
 
431
  #.(declare-buffun)
 
432
  (the int8 (lucid::%svref-signed-8bit a i)))
 
433
 
 
434
(defun aset-int8 (v a i)
 
435
  (declare (type int8 v)
 
436
           (type buffer-bytes a)
 
437
           (type array-index i))
 
438
  #.(declare-buffun)
 
439
  (setf (lucid::%svref-signed-8bit a i) v))
 
440
 
 
441
(defun aref-card16 (a i)
 
442
  (declare (type buffer-bytes a)
 
443
           (type array-index i)
 
444
           (clx-values card16))
 
445
  #.(declare-buffun)
 
446
  (the card16 (lucid::%svref-16bit a (index-ash i -1))))
 
447
  
 
448
(defun aset-card16 (v a i)
 
449
  (declare (type card16 v)
 
450
           (type buffer-bytes a)
 
451
           (type array-index i))
 
452
  #.(declare-buffun)
 
453
  (setf (lucid::%svref-16bit a (index-ash i -1)) v))
 
454
  
 
455
(defun aref-int16 (a i)
 
456
  (declare (type buffer-bytes a)
 
457
           (type array-index i)
 
458
           (clx-values int16))
 
459
  #.(declare-buffun)
 
460
  (the int16 (lucid::%svref-signed-16bit a (index-ash i -1))))
 
461
  
 
462
(defun aset-int16 (v a i)
 
463
  (declare (type int16 v)
 
464
           (type buffer-bytes a)
 
465
           (type array-index i))
 
466
  #.(declare-buffun)
 
467
  (setf (lucid::%svref-signed-16bit a (index-ash i -1)) v))
 
468
 
 
469
(defun aref-card32 (a i)
 
470
  (declare (type buffer-bytes a)
 
471
           (type array-index i)
 
472
           (clx-values card32))
 
473
  #.(declare-buffun)
 
474
  (the card32 (lucid::%svref-32bit a (index-ash i -2))))
 
475
    
 
476
(defun aset-card32 (v a i)
 
477
  (declare (type card32 v)
 
478
           (type buffer-bytes a)
 
479
           (type array-index i))
 
480
  #.(declare-buffun)
 
481
  (setf (lucid::%svref-32bit a (index-ash i -2)) v))
 
482
 
 
483
(defun aref-int32 (a i)
 
484
  (declare (type buffer-bytes a)
 
485
           (type array-index i)
 
486
           (clx-values int32))
 
487
  #.(declare-buffun)
 
488
  (the int32 (lucid::%svref-signed-32bit a (index-ash i -2))))
 
489
    
 
490
(defun aset-int32 (v a i)
 
491
  (declare (type int32 v)
 
492
           (type buffer-bytes a)
 
493
           (type array-index i))
 
494
  #.(declare-buffun)
 
495
  (setf (lucid::%svref-signed-32bit a (index-ash i -2)) v))
 
496
 
 
497
(defun aref-card29 (a i)
 
498
  (declare (type buffer-bytes a)
 
499
           (type array-index i)
 
500
           (clx-values card29))
 
501
  #.(declare-buffun)
 
502
  (the card29 (lucid::%svref-32bit a (index-ash i -2))))
 
503
 
 
504
(defun aset-card29 (v a i)
 
505
  (declare (type card29 v)
 
506
           (type buffer-bytes a)
 
507
           (type array-index i))
 
508
  #.(declare-buffun)
 
509
  (setf (lucid::%svref-32bit a (index-ash i -2)) v))
 
510
 
 
511
)
 
512
 
 
513
 
 
514
 
 
515
#-(or excl lcl3.0 clx-overlapping-arrays)
 
516
(progn
 
517
 
 
518
(defun aref-card16 (a i)
 
519
  (declare (type buffer-bytes a)
 
520
           (type array-index i))
 
521
  (declare (clx-values card16))
 
522
  #.(declare-buffun)
 
523
  (the card16
 
524
       (logior (the card16
 
525
                    (ash (the card8 (aref a (index+ i +word-1+))) 8))
 
526
               (the card8
 
527
                    (aref a (index+ i +word-0+))))))
 
528
 
 
529
(defun aset-card16 (v a i)
 
530
  (declare (type card16 v)
 
531
           (type buffer-bytes a)
 
532
           (type array-index i))
 
533
  #.(declare-buffun)
 
534
  (setf (aref a (index+ i +word-1+)) (the card8 (ldb (byte 8 8) v))
 
535
        (aref a (index+ i +word-0+)) (the card8 (ldb (byte 8 0) v)))
 
536
  v)
 
537
 
 
538
(defun aref-int16 (a i)
 
539
  (declare (type buffer-bytes a)
 
540
           (type array-index i))
 
541
  (declare (clx-values int16))
 
542
  #.(declare-buffun)
 
543
  (the int16
 
544
       (logior (the int16
 
545
                    (ash (the int8 (aref-int8 a (index+ i +word-1+))) 8))
 
546
               (the card8
 
547
                    (aref a (index+ i +word-0+))))))
 
548
 
 
549
(defun aset-int16 (v a i)
 
550
  (declare (type int16 v)
 
551
           (type buffer-bytes a)
 
552
           (type array-index i))
 
553
  #.(declare-buffun)
 
554
  (setf (aref a (index+ i +word-1+)) (the card8 (ldb (byte 8 8) v))
 
555
        (aref a (index+ i +word-0+)) (the card8 (ldb (byte 8 0) v)))
 
556
  v)
 
557
 
 
558
(defun aref-card32 (a i)
 
559
  (declare (type buffer-bytes a)
 
560
           (type array-index i))
 
561
  (declare (clx-values card32))
 
562
  #.(declare-buffun)
 
563
  (the card32
 
564
       (logior (the card32
 
565
                    (ash (the card8 (aref a (index+ i +long-3+))) 24))
 
566
               (the card29
 
567
                    (ash (the card8 (aref a (index+ i +long-2+))) 16))
 
568
               (the card16
 
569
                    (ash (the card8 (aref a (index+ i +long-1+))) 8))
 
570
               (the card8
 
571
                    (aref a (index+ i +long-0+))))))
 
572
 
 
573
(defun aset-card32 (v a i)
 
574
  (declare (type card32 v)
 
575
           (type buffer-bytes a)
 
576
           (type array-index i))
 
577
  #.(declare-buffun)
 
578
  (setf (aref a (index+ i +long-3+)) (the card8 (ldb (byte 8 24) v))
 
579
        (aref a (index+ i +long-2+)) (the card8 (ldb (byte 8 16) v))
 
580
        (aref a (index+ i +long-1+)) (the card8 (ldb (byte 8 8) v))
 
581
        (aref a (index+ i +long-0+)) (the card8 (ldb (byte 8 0) v)))
 
582
  v)
 
583
 
 
584
(defun aref-int32 (a i)
 
585
  (declare (type buffer-bytes a)
 
586
           (type array-index i))
 
587
  (declare (clx-values int32))
 
588
  #.(declare-buffun)
 
589
  (the int32
 
590
       (logior (the int32
 
591
                    (ash (the int8 (aref-int8 a (index+ i +long-3+))) 24))
 
592
               (the card29
 
593
                    (ash (the card8 (aref a (index+ i +long-2+))) 16))
 
594
               (the card16
 
595
                    (ash (the card8 (aref a (index+ i +long-1+))) 8))
 
596
               (the card8
 
597
                    (aref a (index+ i +long-0+))))))
 
598
 
 
599
(defun aset-int32 (v a i)
 
600
  (declare (type int32 v)
 
601
           (type buffer-bytes a)
 
602
           (type array-index i))
 
603
  #.(declare-buffun)
 
604
  (setf (aref a (index+ i +long-3+)) (the card8 (ldb (byte 8 24) v))
 
605
        (aref a (index+ i +long-2+)) (the card8 (ldb (byte 8 16) v))
 
606
        (aref a (index+ i +long-1+)) (the card8 (ldb (byte 8 8) v))
 
607
        (aref a (index+ i +long-0+)) (the card8 (ldb (byte 8 0) v)))
 
608
  v)
 
609
 
 
610
(defun aref-card29 (a i)
 
611
  (declare (type buffer-bytes a)
 
612
           (type array-index i))
 
613
  (declare (clx-values card29))
 
614
  #.(declare-buffun)
 
615
  (the card29
 
616
       (logior (the card29
 
617
                    (ash (the card8 (aref a (index+ i +long-3+))) 24))
 
618
               (the card29
 
619
                    (ash (the card8 (aref a (index+ i +long-2+))) 16))
 
620
               (the card16
 
621
                    (ash (the card8 (aref a (index+ i +long-1+))) 8))
 
622
               (the card8
 
623
                    (aref a (index+ i +long-0+))))))
 
624
 
 
625
(defun aset-card29 (v a i)
 
626
  (declare (type card29 v)
 
627
           (type buffer-bytes a)
 
628
           (type array-index i))
 
629
  #.(declare-buffun)
 
630
  (setf (aref a (index+ i +long-3+)) (the card8 (ldb (byte 8 24) v))
 
631
        (aref a (index+ i +long-2+)) (the card8 (ldb (byte 8 16) v))
 
632
        (aref a (index+ i +long-1+)) (the card8 (ldb (byte 8 8) v))
 
633
        (aref a (index+ i +long-0+)) (the card8 (ldb (byte 8 0) v)))
 
634
  v)
 
635
 
 
636
)
 
637
 
 
638
(defsetf aref-card8 (a i) (v)
 
639
  `(aset-card8 ,v ,a ,i))
 
640
 
 
641
(defsetf aref-int8 (a i) (v)
 
642
  `(aset-int8 ,v ,a ,i))
 
643
 
 
644
(defsetf aref-card16 (a i) (v)
 
645
  `(aset-card16 ,v ,a ,i))
 
646
 
 
647
(defsetf aref-int16 (a i) (v)
 
648
  `(aset-int16 ,v ,a ,i))
 
649
 
 
650
(defsetf aref-card32 (a i) (v)
 
651
  `(aset-card32 ,v ,a ,i))
 
652
 
 
653
(defsetf aref-int32 (a i) (v)
 
654
  `(aset-int32 ,v ,a ,i))
 
655
 
 
656
(defsetf aref-card29 (a i) (v)
 
657
  `(aset-card29 ,v ,a ,i))
 
658
 
 
659
;;; Other random conversions
 
660
 
 
661
(defun rgb-val->card16 (value)
 
662
  ;; Short floats are good enough
 
663
  (declare (type rgb-val value))
 
664
  (declare (clx-values card16))
 
665
  #.(declare-buffun)
 
666
  ;; Convert VALUE from float to card16
 
667
  (the card16 (values (round (the rgb-val value) #.(/ 1.0s0 #xffff)))))
 
668
 
 
669
(defun card16->rgb-val (value) 
 
670
  ;; Short floats are good enough
 
671
  (declare (type card16 value))
 
672
  (declare (clx-values short-float))
 
673
  #.(declare-buffun)
 
674
  ;; Convert VALUE from card16 to float
 
675
  (the short-float (* (the card16 value) #.(/ 1.0s0 #xffff))))
 
676
 
 
677
(defun radians->int16 (value)
 
678
  ;; Short floats are good enough
 
679
  (declare (type angle value))
 
680
  (declare (clx-values int16))
 
681
  #.(declare-buffun)
 
682
  (the int16 (values (round (the angle value) #.(float (/ pi 180.0s0 64.0s0) 0.0s0)))))
 
683
 
 
684
(defun int16->radians (value)
 
685
  ;; Short floats are good enough
 
686
  (declare (type int16 value))
 
687
  (declare (clx-values short-float))
 
688
  #.(declare-buffun)
 
689
  (the short-float (* (the int16 value) #.(coerce (/ pi 180.0 64.0) 'short-float))))
 
690
 
 
691
 
 
692
#+(or cmu sbcl) (progn
 
693
 
 
694
;;; This overrides the (probably incorrect) definition in clx.lisp.  Since PI
 
695
;;; is irrational, there can't be a precise rational representation.  In
 
696
;;; particular, the different float approximations will always be /=.  This
 
697
;;; causes problems with type checking, because people might compute an
 
698
;;; argument in any precision.  What we do is discard all the excess precision
 
699
;;; in the value, and see if the protocol encoding falls in the desired range
 
700
;;; (64'ths of a degree.)
 
701
;;;
 
702
(deftype angle () '(satisfies anglep))
 
703
 
 
704
(defun anglep (x)
 
705
  (and (typep x 'real)
 
706
       (<= (* -360 64) (radians->int16 x) (* 360 64))))
 
707
 
 
708
)
 
709
 
 
710
 
 
711
;;-----------------------------------------------------------------------------
 
712
;; Character transformation
 
713
;;-----------------------------------------------------------------------------
 
714
 
 
715
 
 
716
;;; This stuff transforms chars to ascii codes in card8's and back.
 
717
;;; You might have to hack it a little to get it to work for your machine.
 
718
 
 
719
(declaim (inline char->card8 card8->char))
 
720
 
 
721
(macrolet ((char-translators ()
 
722
             (let ((alist
 
723
                     `(#-lispm
 
724
                       ;; The normal ascii codes for the control characters.
 
725
                       ,@`((#\Return . 13)
 
726
                           (#\Linefeed . 10)
 
727
                           (#\Rubout . 127)
 
728
                           (#\Page . 12)
 
729
                           (#\Tab . 9)
 
730
                           (#\Backspace . 8)
 
731
                           (#\Newline . 10)
 
732
                           (#\Space . 32))
 
733
                       ;; One the lispm, #\Newline is #\Return, but we'd really like
 
734
                       ;; #\Newline to translate to ascii code 10, so we swap the
 
735
                       ;; Ascii codes for #\Return and #\Linefeed. We also provide
 
736
                       ;; mappings from the counterparts of these control characters
 
737
                       ;; so that the character mapping from the lisp machine
 
738
                       ;; character set to ascii is invertible.
 
739
                       #+lispm
 
740
                       ,@`((#\Return . 10)   (,(code-char  10) . ,(char-code #\Return))
 
741
                           (#\Linefeed . 13) (,(code-char  13) . ,(char-code #\Linefeed))
 
742
                           (#\Rubout . 127)  (,(code-char 127) . ,(char-code #\Rubout))
 
743
                           (#\Page . 12)     (,(code-char  12) . ,(char-code #\Page))
 
744
                           (#\Tab . 9)       (,(code-char   9) . ,(char-code #\Tab))
 
745
                           (#\Backspace . 8) (,(code-char   8) . ,(char-code #\Backspace))
 
746
                           (#\Newline . 10)  (,(code-char  10) . ,(char-code #\Newline))
 
747
                           (#\Space . 32)    (,(code-char  32) . ,(char-code #\Space)))
 
748
                       ;; The rest of the common lisp charater set with the normal
 
749
                       ;; ascii codes for them.
 
750
                       (#\! . 33) (#\" . 34) (#\# . 35) (#\$ . 36)
 
751
                       (#\% . 37) (#\& . 38) (#\' . 39) (#\( . 40)
 
752
                       (#\) . 41) (#\* . 42) (#\+ . 43) (#\, . 44)
 
753
                       (#\- . 45) (#\. . 46) (#\/ . 47) (#\0 . 48)
 
754
                       (#\1 . 49) (#\2 . 50) (#\3 . 51) (#\4 . 52)
 
755
                       (#\5 . 53) (#\6 . 54) (#\7 . 55) (#\8 . 56)
 
756
                       (#\9 . 57) (#\: . 58) (#\; . 59) (#\< . 60)
 
757
                       (#\= . 61) (#\> . 62) (#\? . 63) (#\@ . 64)
 
758
                       (#\A . 65) (#\B . 66) (#\C . 67) (#\D . 68)
 
759
                       (#\E . 69) (#\F . 70) (#\G . 71) (#\H . 72)
 
760
                       (#\I . 73) (#\J . 74) (#\K . 75) (#\L . 76)
 
761
                       (#\M . 77) (#\N . 78) (#\O . 79) (#\P . 80)
 
762
                       (#\Q . 81) (#\R . 82) (#\S . 83) (#\T . 84)
 
763
                       (#\U . 85) (#\V . 86) (#\W . 87) (#\X . 88)
 
764
                       (#\Y . 89) (#\Z . 90) (#\[ . 91) (#\\ . 92)
 
765
                       (#\] . 93) (#\^ . 94) (#\_ . 95) (#\` . 96)
 
766
                       (#\a . 97) (#\b . 98) (#\c . 99) (#\d . 100)
 
767
                       (#\e . 101) (#\f . 102) (#\g . 103) (#\h . 104)
 
768
                       (#\i . 105) (#\j . 106) (#\k . 107) (#\l . 108)
 
769
                       (#\m . 109) (#\n . 110) (#\o . 111) (#\p . 112)
 
770
                       (#\q . 113) (#\r . 114) (#\s . 115) (#\t . 116)
 
771
                       (#\u . 117) (#\v . 118) (#\w . 119) (#\x . 120)
 
772
                       (#\y . 121) (#\z . 122) (#\{ . 123) (#\| . 124)
 
773
                       (#\} . 125) (#\~ . 126))))
 
774
               (cond ((dolist (pair alist nil)
 
775
                        (when (not (= (char-code (car pair)) (cdr pair)))
 
776
                          (return t)))
 
777
                      `(progn
 
778
                         (defconstant *char-to-card8-translation-table*
 
779
                                      ',(let ((array (make-array
 
780
                                                       (let ((max-char-code 255))
 
781
                                                         (dolist (pair alist)
 
782
                                                           (setq max-char-code
 
783
                                                                 (max max-char-code
 
784
                                                                      (char-code (car pair)))))
 
785
                                                         (1+ max-char-code))
 
786
                                                       :element-type 'card8)))
 
787
                                          (dotimes (i (length array))
 
788
                                            (setf (aref array i) (mod i 256)))
 
789
                                          (dolist (pair alist)
 
790
                                            (setf (aref array (char-code (car pair)))
 
791
                                                  (cdr pair)))
 
792
                                          array))
 
793
                         (defconstant *card8-to-char-translation-table*
 
794
                                      ',(let ((array (make-array 256)))
 
795
                                          (dotimes (i (length array))
 
796
                                            (setf (aref array i) (code-char i)))
 
797
                                          (dolist (pair alist)
 
798
                                            (setf (aref array (cdr pair)) (car pair)))
 
799
                                          array))
 
800
                         #-Genera
 
801
                         (progn
 
802
                           (defun char->card8 (char)
 
803
                             (declare (type base-char char))
 
804
                             #.(declare-buffun)
 
805
                             (the card8 (aref (the (simple-array card8 (*))
 
806
                                                   *char-to-card8-translation-table*)
 
807
                                              (the array-index (char-code char)))))
 
808
                           (defun card8->char (card8)
 
809
                             (declare (type card8 card8))
 
810
                             #.(declare-buffun)
 
811
                             (the base-char
 
812
                                  (or (aref (the simple-vector *card8-to-char-translation-table*)
 
813
                                            card8)
 
814
                                      (error "Invalid CHAR code ~D." card8))))
 
815
                           )
 
816
                         #+Genera
 
817
                         (progn
 
818
                           (defun char->card8 (char)
 
819
                             (declare lt:(side-effects reader reducible))
 
820
                             (aref *char-to-card8-translation-table* (char-code char)))
 
821
                           (defun card8->char (card8)
 
822
                             (declare lt:(side-effects reader reducible))
 
823
                             (aref *card8-to-char-translation-table* card8))
 
824
                           )
 
825
                         #-Minima
 
826
                         (dotimes (i 256)
 
827
                           (unless (= i (char->card8 (card8->char i)))
 
828
                             (warn "The card8->char mapping is not invertible through char->card8.  Info:~%~S"
 
829
                                   (list i
 
830
                                         (card8->char i)
 
831
                                         (char->card8 (card8->char i))))
 
832
                             (return nil)))
 
833
                         #-Minima
 
834
                         (dotimes (i (length *char-to-card8-translation-table*))
 
835
                           (let ((char (code-char i)))
 
836
                             (unless (eql char (card8->char (char->card8 char)))
 
837
                               (warn "The char->card8 mapping is not invertible through card8->char.  Info:~%~S"
 
838
                                     (list char
 
839
                                           (char->card8 char)
 
840
                                           (card8->char (char->card8 char))))
 
841
                               (return nil))))))
 
842
                     (t
 
843
                      `(progn
 
844
                         (defun char->card8 (char)
 
845
                           (declare (type base-char char))
 
846
                           #.(declare-buffun)
 
847
                           (the card8 (char-code char)))
 
848
                         (defun card8->char (card8)
 
849
                           (declare (type card8 card8))
 
850
                           #.(declare-buffun)
 
851
                           (the base-char (code-char card8)))
 
852
                         ))))))
 
853
  (char-translators))
 
854
 
 
855
;;-----------------------------------------------------------------------------
 
856
;; Process Locking
 
857
;;
 
858
;;      Common-Lisp doesn't provide process locking primitives, so we define
 
859
;;      our own here, based on Zetalisp primitives.  Holding-Lock is very
 
860
;;      similar to with-lock on The TI Explorer, and a little more efficient
 
861
;;      than with-process-lock on a Symbolics.
 
862
;;-----------------------------------------------------------------------------
 
863
 
 
864
;;; MAKE-PROCESS-LOCK: Creating a process lock.
 
865
 
 
866
#-(or LispM excl Minima sbcl (and cmu mp))
 
867
(defun make-process-lock (name)
 
868
  (declare (ignore name))
 
869
  nil)
 
870
 
 
871
#+excl
 
872
(defun make-process-lock (name)
 
873
  (mp:make-process-lock :name name))
 
874
 
 
875
#+(and LispM (not Genera))
 
876
(defun make-process-lock (name)
 
877
  (vector nil name))
 
878
 
 
879
#+Genera
 
880
(defun make-process-lock (name)
 
881
  (process:make-lock name :flavor 'clx-lock))
 
882
 
 
883
#+Minima
 
884
(defun make-process-lock (name)
 
885
  (minima:make-lock name :recursive t))
 
886
 
 
887
#+(and cmu mp)
 
888
(defun make-process-lock (name)
 
889
  (mp:make-lock name))
 
890
 
 
891
#+sbcl
 
892
(defun make-process-lock (name)
 
893
  (sb-thread:make-mutex :name name))
 
894
 
 
895
;;; HOLDING-LOCK: Execute a body of code with a lock held.
 
896
 
 
897
;;; The holding-lock macro takes a timeout keyword argument.  EVENT-LISTEN
 
898
;;; passes its timeout to the holding-lock macro, so any timeout you want to
 
899
;;; work for event-listen you should do for holding-lock.
 
900
 
 
901
;; If you're not sharing DISPLAY objects within a multi-processing
 
902
;; shared-memory environment, this is sufficient
 
903
#-(or lispm excl lcl3.0 Minima sbcl (and CMU mp) )
 
904
(defmacro holding-lock ((locator display &optional whostate &key timeout) &body body)
 
905
  (declare (ignore locator display whostate timeout))
 
906
  `(progn ,@body))
 
907
 
 
908
;;; HOLDING-LOCK for CMU Common Lisp.
 
909
;;;
 
910
;;; We are not multi-processing, but we use this macro to try to protect
 
911
;;; against re-entering request functions.  This can happen if an interrupt
 
912
;;; occurs and the handler attempts to use X over the same display connection.
 
913
;;; This can happen if the GC hooks are used to notify the user over the same
 
914
;;; display connection.  We inhibit GC notifications since display of them
 
915
;;; could cause recursive entry into CLX.
 
916
;;;
 
917
#+(and CMU (not mp))
 
918
(defmacro holding-lock ((locator display &optional whostate &key timeout)
 
919
                        &body body)
 
920
  `(let #+cmu((ext:*gc-verbose* nil)
 
921
              (ext:*gc-inhibit-hook* nil)
 
922
              (ext:*before-gc-hooks* nil)
 
923
              (ext:*after-gc-hooks* nil))
 
924
        #+sbcl()
 
925
     ,locator ,display ,whostate ,timeout
 
926
     (system:without-interrupts (progn ,@body))))
 
927
 
 
928
;;; HOLDING-LOCK for CMU Common Lisp with multi-processes.
 
929
;;;
 
930
#+(and cmu mp)
 
931
(defmacro holding-lock ((lock display &optional (whostate "CLX wait")
 
932
                              &key timeout)
 
933
                        &body body)
 
934
  (declare (ignore display))
 
935
  `(mp:with-lock-held (,lock ,whostate ,@(and timeout `(:timeout ,timeout)))
 
936
    ,@body))
 
937
 
 
938
#+sbcl
 
939
(defmacro holding-lock ((lock display &optional (whostate "CLX wait")
 
940
                              &key timeout)
 
941
                        &body body)
 
942
  ;; This macro is used by WITH-DISPLAY, which claims to be callable
 
943
  ;; recursively.  So, had better use a recursive lock.
 
944
  ;;
 
945
  ;; FIXME: This is hideously ugly.  If WITH-TIMEOUT handled NIL
 
946
  ;; timeouts...
 
947
  (declare (ignore display whostate))
 
948
  (if timeout
 
949
      `(if ,timeout
 
950
           (handler-case
 
951
               (sb-ext:with-timeout ,timeout
 
952
                 (sb-thread:with-recursive-lock (,lock)
 
953
                   ,@body))
 
954
             (sb-ext:timeout () nil))
 
955
           (sb-thread:with-recursive-lock (,lock)
 
956
             ,@body))
 
957
      `(sb-thread:with-recursive-lock (,lock)
 
958
         ,@body)))
 
959
 
 
960
#+Genera
 
961
(defmacro holding-lock ((locator display &optional whostate &key timeout)
 
962
                        &body body)
 
963
  (declare (ignore whostate))
 
964
  `(process:with-lock (,locator :timeout ,timeout)
 
965
     (let ((.debug-io. (buffer-debug-io ,display)))
 
966
       (scl:let-if .debug-io. ((*debug-io* .debug-io.))
 
967
         ,@body))))
 
968
 
 
969
#+(and lispm (not Genera))
 
970
(defmacro holding-lock ((locator display &optional whostate &key timeout)
 
971
                        &body body)
 
972
  (declare (ignore display))
 
973
  ;; This macro is for use in a multi-process environment.
 
974
  (let ((lock (gensym))
 
975
        (have-lock (gensym))
 
976
        (timeo (gensym)))
 
977
    `(let* ((,lock (zl:locf (svref ,locator 0)))
 
978
            (,have-lock (eq (car ,lock) sys:current-process))
 
979
            (,timeo ,timeout))
 
980
       (unwind-protect 
 
981
           (when (cond (,have-lock)
 
982
                       ((#+explorer si:%store-conditional
 
983
                         #-explorer sys:store-conditional
 
984
                         ,lock nil sys:current-process))
 
985
                       ((null ,timeo)
 
986
                        (sys:process-lock ,lock nil ,(or whostate "CLX Lock")))
 
987
                       ((sys:process-wait-with-timeout
 
988
                            ,(or whostate "CLX Lock") (round (* ,timeo 60.))
 
989
                          #'(lambda (lock process)
 
990
                              (#+explorer si:%store-conditional
 
991
                               #-explorer sys:store-conditional
 
992
                               lock nil process))
 
993
                          ,lock sys:current-process)))
 
994
             ,@body)
 
995
         (unless ,have-lock
 
996
           (#+explorer si:%store-conditional
 
997
            #-explorer sys:store-conditional
 
998
            ,lock sys:current-process nil))))))
 
999
 
 
1000
;; Lucid has a process locking mechanism as well under release 3.0
 
1001
#+lcl3.0
 
1002
(defmacro holding-lock ((locator display &optional whostate &key timeout)
 
1003
                        &body body)
 
1004
  (declare (ignore display))
 
1005
  (if timeout
 
1006
      ;; Hair to support timeout.
 
1007
      `(let ((.have-lock. (eq ,locator lcl:*current-process*))
 
1008
             (.timeout. ,timeout))
 
1009
         (unwind-protect
 
1010
             (when (cond (.have-lock.)
 
1011
                         ((conditional-store ,locator nil lcl:*current-process*))
 
1012
                         ((null .timeout.)
 
1013
                          (lcl:process-lock ,locator)
 
1014
                          t)
 
1015
                         ((lcl:process-wait-with-timeout ,whostate .timeout.
 
1016
                            #'(lambda ()
 
1017
                                (conditional-store ,locator nil lcl:*current-process*))))
 
1018
                         ;; abort the PROCESS-UNLOCK if actually timing out
 
1019
                         (t
 
1020
                          (setf .have-lock. :abort)
 
1021
                          nil))
 
1022
               ,@body)
 
1023
           (unless .have-lock. 
 
1024
             (lcl:process-unlock ,locator))))
 
1025
    `(lcl:with-process-lock (,locator)
 
1026
       ,@body)))
 
1027
 
 
1028
 
 
1029
#+excl
 
1030
(defmacro holding-lock ((locator display &optional whostate &key timeout)
 
1031
                        &body body)
 
1032
  (declare (ignore display))
 
1033
  `(let (.hl-lock. .hl-obtained-lock. .hl-curproc.)
 
1034
     (unwind-protect
 
1035
         (block .hl-doit.
 
1036
           (when mp::*scheduler-stack-group* ; fast test for scheduler running
 
1037
             (setq .hl-lock. ,locator
 
1038
                   .hl-curproc. mp::*current-process*)
 
1039
             (when (and .hl-curproc.    ; nil if in process-wait fun
 
1040
                        (not (eq (mp::process-lock-locker .hl-lock.)
 
1041
                                 .hl-curproc.)))
 
1042
               ;; Then we need to grab the lock.
 
1043
               ,(if timeout
 
1044
                    `(if (not (mp::process-lock .hl-lock. .hl-curproc.
 
1045
                                                ,whostate ,timeout))
 
1046
                         (return-from .hl-doit. nil))
 
1047
                  `(mp::process-lock .hl-lock. .hl-curproc.
 
1048
                                     ,@(when whostate `(,whostate))))
 
1049
               ;; There is an apparent race condition here.  However, there is
 
1050
               ;; no actual race condition -- our implementation of mp:process-
 
1051
               ;; lock guarantees that the lock will still be held when it
 
1052
               ;; returns, and no interrupt can happen between that and the
 
1053
               ;; execution of the next form.  -- jdi 2/27/91
 
1054
               (setq .hl-obtained-lock. t)))
 
1055
           ,@body)
 
1056
       (if (and .hl-obtained-lock.
 
1057
                ;; Note -- next form added to allow error handler inside
 
1058
                ;; body to unlock the lock prematurely if it knows that
 
1059
                ;; the current process cannot possibly continue but will
 
1060
                ;; throw out (or is it throw up?).
 
1061
                (eq (mp::process-lock-locker .hl-lock.) .hl-curproc.))
 
1062
           (mp::process-unlock .hl-lock. .hl-curproc.)))))
 
1063
 
 
1064
#+Minima
 
1065
(defmacro holding-lock ((locator display &optional whostate &key timeout) &body body)
 
1066
  `(holding-lock-1 #'(lambda () ,@body) ,locator ,display
 
1067
                   ,@(and whostate `(:whostate ,whostate))
 
1068
                   ,@(and timeout `(:timeout ,timeout))))
 
1069
 
 
1070
#+Minima
 
1071
(defun holding-lock-1 (continuation lock display &key (whostate "Lock") timeout)
 
1072
  (declare (dynamic-extent continuation))
 
1073
  (declare (ignore display whostate timeout))
 
1074
  (minima:with-lock (lock)
 
1075
    (funcall continuation)))
 
1076
 
 
1077
;;; WITHOUT-ABORTS
 
1078
 
 
1079
;;; If you can inhibit asynchronous keyboard aborts inside the body of this
 
1080
;;; macro, then it is a good idea to do this.  This macro is wrapped around
 
1081
;;; request writing and reply reading to ensure that requests are atomically
 
1082
;;; written and replies are atomically read from the stream.
 
1083
 
 
1084
#-(or Genera excl lcl3.0)
 
1085
(defmacro without-aborts (&body body)
 
1086
  `(progn ,@body))
 
1087
 
 
1088
#+Genera
 
1089
(defmacro without-aborts (&body body)
 
1090
  `(sys:without-aborts (clx "CLX is in the middle of an operation that should be atomic.")
 
1091
     ,@body))
 
1092
 
 
1093
#+excl
 
1094
(defmacro without-aborts (&body body)
 
1095
  `(without-interrupts ,@body))
 
1096
    
 
1097
#+lcl3.0
 
1098
(defmacro without-aborts (&body body)
 
1099
  `(lcl:with-interruptions-inhibited ,@body))
 
1100
 
 
1101
;;; PROCESS-BLOCK: Wait until a given predicate returns a non-NIL value.
 
1102
;;; Caller guarantees that PROCESS-WAKEUP will be called after the predicate's
 
1103
;;; value changes.
 
1104
 
 
1105
#-(or lispm excl lcl3.0 Minima (and sb-thread sbcl) (and cmu mp))
 
1106
(defun process-block (whostate predicate &rest predicate-args)
 
1107
  (declare (ignore whostate))
 
1108
  (or (apply predicate predicate-args)
 
1109
      (error "Program tried to wait with no scheduler.")))
 
1110
 
 
1111
#+Genera
 
1112
(defun process-block (whostate predicate &rest predicate-args)
 
1113
  (declare (type function predicate)
 
1114
           #+clx-ansi-common-lisp
 
1115
           (dynamic-extent predicate)
 
1116
           #-clx-ansi-common-lisp
 
1117
           (sys:downward-funarg predicate))
 
1118
  (apply #'process:block-process whostate predicate predicate-args))
 
1119
 
 
1120
#+(and lispm (not Genera))
 
1121
(defun process-block (whostate predicate &rest predicate-args)
 
1122
  (declare (type function predicate)
 
1123
           #+clx-ansi-common-lisp
 
1124
           (dynamic-extent predicate)
 
1125
           #-clx-ansi-common-lisp 
 
1126
           (sys:downward-funarg predicate))
 
1127
  (apply #'global:process-wait whostate predicate predicate-args))
 
1128
 
 
1129
#+excl
 
1130
(defun process-block (whostate predicate &rest predicate-args)
 
1131
  (if mp::*scheduler-stack-group*
 
1132
      (apply #'mp::process-wait whostate predicate predicate-args)
 
1133
      (or (apply predicate predicate-args)
 
1134
          (error "Program tried to wait with no scheduler."))))
 
1135
 
 
1136
#+lcl3.0
 
1137
(defun process-block (whostate predicate &rest predicate-args)
 
1138
  (declare (dynamic-extent predicate-args))
 
1139
  (apply #'lcl:process-wait whostate predicate predicate-args))
 
1140
 
 
1141
#+Minima
 
1142
(defun process-block (whostate predicate &rest predicate-args)
 
1143
  (declare (type function predicate)
 
1144
           (dynamic-extent predicate))
 
1145
  (apply #'minima:process-wait whostate predicate predicate-args))
 
1146
 
 
1147
#+(and cmu mp)
 
1148
(defun process-block (whostate predicate &rest predicate-args)
 
1149
  (declare (type function predicate))
 
1150
  (mp:process-wait whostate #'(lambda ()
 
1151
                                (apply predicate predicate-args))))
 
1152
 
 
1153
#+(and sbcl sb-thread)
 
1154
(progn
 
1155
  (declaim (inline yield))
 
1156
  (defun yield ()
 
1157
    (declare (optimize speed (safety 0)))
 
1158
    (sb-alien:alien-funcall
 
1159
     (sb-alien:extern-alien "sched_yield" (function sb-alien:int)))
 
1160
    (values)))
 
1161
 
 
1162
#+(and sbcl sb-thread)
 
1163
(defun process-block (whostate predicate &rest predicate-args)
 
1164
  (declare (ignore whostate))
 
1165
  (declare (type function predicate))
 
1166
  (loop
 
1167
   (when (apply predicate predicate-args)
 
1168
     (return))
 
1169
   (yield)))
 
1170
 
 
1171
;;; FIXME: the below implementation for threaded PROCESS-BLOCK using
 
1172
;;; queues and condition variables might seem better, but in fact it
 
1173
;;; turns out to make performance extremely suboptimal, at least as
 
1174
;;; measured by McCLIM on linux 2.4 kernels.  -- CSR, 2003-11-10
 
1175
#+(or)
 
1176
(defvar *process-conditions* (make-hash-table))
 
1177
 
 
1178
#+(or)
 
1179
(defun process-block (whostate predicate &rest predicate-args)
 
1180
  (declare (ignore whostate))
 
1181
  (declare (type function predicate))
 
1182
  (let* ((pid (sb-thread:current-thread-id))
 
1183
         (last (gethash  pid *process-conditions*))
 
1184
         (lock
 
1185
          (or (car last)
 
1186
              (sb-thread:make-mutex :name (format nil "lock ~A" pid))))
 
1187
         (queue
 
1188
          (or (cdr last)
 
1189
              (sb-thread:make-waitqueue :name (format nil "queue ~A" pid)))))
 
1190
    (unless last
 
1191
      (setf (gethash pid *process-conditions*) (cons lock queue)))
 
1192
    (sb-thread:with-mutex (lock)
 
1193
      (loop
 
1194
       (when (apply predicate predicate-args) (return))
 
1195
       (handler-case
 
1196
           (sb-ext:with-timeout .5
 
1197
             (sb-thread:condition-wait queue lock))
 
1198
         (sb-ext:timeout ()
 
1199
           (format *trace-output* "thread ~A, process-block timed out~%"
 
1200
                   (sb-thread:current-thread-id) )))))))
 
1201
 
 
1202
;;; PROCESS-WAKEUP: Check some other process' wait function.
 
1203
 
 
1204
(declaim (inline process-wakeup))
 
1205
 
 
1206
#-(or excl Genera Minima (and sbcl sb-thread) (and cmu mp))
 
1207
(defun process-wakeup (process)
 
1208
  (declare (ignore process))
 
1209
  nil)
 
1210
 
 
1211
#+excl
 
1212
(defun process-wakeup (process)
 
1213
  (let ((curproc mp::*current-process*))
 
1214
    (when (and curproc process)
 
1215
      (unless (mp::process-p curproc)
 
1216
        (error "~s is not a process" curproc))
 
1217
      (unless (mp::process-p process)
 
1218
        (error "~s is not a process" process))
 
1219
      (if (> (mp::process-priority process) (mp::process-priority curproc))
 
1220
          (mp::process-allow-schedule process)))))
 
1221
 
 
1222
#+Genera
 
1223
(defun process-wakeup (process)
 
1224
  (process:wakeup process))
 
1225
 
 
1226
#+Minima
 
1227
(defun process-wakeup (process)
 
1228
  (when process
 
1229
    (minima:process-wakeup process)))
 
1230
 
 
1231
#+(and cmu mp)
 
1232
(defun process-wakeup (process)
 
1233
  (declare (ignore process))
 
1234
  (mp:process-yield))
 
1235
 
 
1236
#+(and sb-thread sbcl)
 
1237
(defun process-wakeup (process)
 
1238
  (declare (ignore process))
 
1239
  (yield))
 
1240
#+(or)
 
1241
(defun process-wakeup (process)
 
1242
  (declare (ignore process))
 
1243
  (destructuring-bind (lock . queue)
 
1244
      (gethash (sb-thread:current-thread-id) *process-conditions*
 
1245
               (cons nil nil))
 
1246
    (declare (ignore lock))
 
1247
    (when queue
 
1248
      (sb-thread:condition-notify queue))))
 
1249
 
 
1250
 
 
1251
;;; CURRENT-PROCESS: Return the current process object for input locking and
 
1252
;;; for calling PROCESS-WAKEUP.
 
1253
 
 
1254
(declaim (inline current-process))
 
1255
 
 
1256
;;; Default return NIL, which is acceptable even if there is a scheduler.
 
1257
 
 
1258
#-(or lispm excl lcl3.0 sbcl Minima (and cmu mp))
 
1259
(defun current-process ()
 
1260
  nil)
 
1261
 
 
1262
#+lispm
 
1263
(defun current-process ()
 
1264
  sys:current-process)
 
1265
 
 
1266
#+excl
 
1267
(defun current-process ()
 
1268
  (and mp::*scheduler-stack-group*
 
1269
       mp::*current-process*))
 
1270
 
 
1271
#+lcl3.0
 
1272
(defun current-process ()
 
1273
  lcl:*current-process*)
 
1274
 
 
1275
#+Minima
 
1276
(defun current-process ()
 
1277
  (minima:current-process))
 
1278
 
 
1279
#+(and cmu mp)
 
1280
(defun current-process ()
 
1281
  mp:*current-process*)
 
1282
 
 
1283
#+sbcl
 
1284
(defun current-process ()
 
1285
  (sb-thread:current-thread-id))
 
1286
 
 
1287
;;; WITHOUT-INTERRUPTS -- provide for atomic operations.
 
1288
 
 
1289
#-(or lispm excl lcl3.0 Minima cmu)
 
1290
(defmacro without-interrupts (&body body)
 
1291
  `(progn ,@body))
 
1292
 
 
1293
#+(and lispm (not Genera))
 
1294
(defmacro without-interrupts (&body body)
 
1295
  `(sys:without-interrupts ,@body))
 
1296
 
 
1297
#+Genera
 
1298
(defmacro without-interrupts (&body body)
 
1299
  `(process:with-no-other-processes ,@body))
 
1300
 
 
1301
#+LCL3.0
 
1302
(defmacro without-interrupts (&body body)
 
1303
  `(lcl:with-scheduling-inhibited ,@body))
 
1304
 
 
1305
#+Minima
 
1306
(defmacro without-interrupts (&body body)
 
1307
  `(minima:with-no-other-processes ,@body))
 
1308
 
 
1309
#+cmu
 
1310
(defmacro without-interrupts (&body body)
 
1311
  `(system:without-interrupts ,@body))
 
1312
 
 
1313
#+sbcl
 
1314
(defvar *without-interrupts-sic-lock*
 
1315
  (sb-thread:make-mutex :name "lock simulating *without-interrupts*"))
 
1316
#+sbcl
 
1317
(defmacro without-interrupts (&body body)
 
1318
  `(sb-thread:with-recursive-lock (*without-interrupts-sic-lock*)
 
1319
    ,@body))
 
1320
 
 
1321
;;; CONDITIONAL-STORE:
 
1322
 
 
1323
;; This should use GET-SETF-METHOD to avoid evaluating subforms multiple times.
 
1324
;; It doesn't because CLtL doesn't pass the environment to GET-SETF-METHOD.
 
1325
#-sbcl
 
1326
(defmacro conditional-store (place old-value new-value)
 
1327
  `(without-interrupts
 
1328
     (cond ((eq ,place ,old-value)
 
1329
            (setf ,place ,new-value)
 
1330
            t))))
 
1331
 
 
1332
;;; we only use this queue for the spinlock word, in fact
 
1333
#+sbcl
 
1334
(defvar *conditional-store-queue*
 
1335
  (sb-thread:make-waitqueue :name "conditional store"))
 
1336
 
 
1337
#+sbcl
 
1338
(defmacro conditional-store (place old-value new-value)
 
1339
  `(sb-thread::with-spinlock (*conditional-store-queue*)
 
1340
     (cond ((eq ,place ,old-value)
 
1341
            (setf ,place ,new-value)
 
1342
            t))))
 
1343
 
 
1344
;;;----------------------------------------------------------------------------
 
1345
;;; IO Error Recovery
 
1346
;;;     All I/O operations are done within a WRAP-BUF-OUTPUT macro.
 
1347
;;;     It prevents multiple mindless errors when the network craters.
 
1348
;;;
 
1349
;;;----------------------------------------------------------------------------
 
1350
 
 
1351
#-Genera
 
1352
(defmacro wrap-buf-output ((buffer) &body body)
 
1353
  ;; Error recovery wrapper
 
1354
  `(unless (buffer-dead ,buffer)
 
1355
     ,@body))
 
1356
 
 
1357
#+Genera
 
1358
(defmacro wrap-buf-output ((buffer) &body body)
 
1359
  ;; Error recovery wrapper
 
1360
  `(let ((.buffer. ,buffer))
 
1361
     (unless (buffer-dead .buffer.)
 
1362
       (scl:condition-bind
 
1363
         (((sys:network-error)
 
1364
           #'(lambda (error)
 
1365
               (scl:condition-case () 
 
1366
                    (funcall (buffer-close-function .buffer.) .buffer. :abort t)
 
1367
                  (sys:network-error))
 
1368
               (setf (buffer-dead .buffer.) error)
 
1369
               (setf (buffer-output-stream .buffer.) nil)
 
1370
               (setf (buffer-input-stream .buffer.) nil)
 
1371
               nil)))
 
1372
         ,@body))))
 
1373
 
 
1374
#-Genera
 
1375
(defmacro wrap-buf-input ((buffer) &body body)
 
1376
  (declare (ignore buffer))
 
1377
  ;; Error recovery wrapper
 
1378
  `(progn ,@body))
 
1379
 
 
1380
#+Genera
 
1381
(defmacro wrap-buf-input ((buffer) &body body)
 
1382
  ;; Error recovery wrapper
 
1383
  `(let ((.buffer. ,buffer))
 
1384
     (scl:condition-bind
 
1385
       (((sys:network-error)
 
1386
         #'(lambda (error)
 
1387
             (scl:condition-case () 
 
1388
                  (funcall (buffer-close-function .buffer.) .buffer. :abort t)
 
1389
                (sys:network-error))
 
1390
             (setf (buffer-dead .buffer.) error)
 
1391
             (setf (buffer-output-stream .buffer.) nil)
 
1392
             (setf (buffer-input-stream .buffer.) nil)
 
1393
             nil)))
 
1394
       ,@body)))
 
1395
 
 
1396
 
 
1397
;;;----------------------------------------------------------------------------
 
1398
;;; System dependent IO primitives
 
1399
;;;     Functions for opening, reading writing forcing-output and closing 
 
1400
;;;     the stream to the server.
 
1401
;;;----------------------------------------------------------------------------
 
1402
 
 
1403
;;; OPEN-X-STREAM - create a stream for communicating to the appropriate X
 
1404
;;; server
 
1405
 
 
1406
#-(or explorer Genera lucid kcl ibcl excl Minima CMU sbcl ecl)
 
1407
(defun open-x-stream (host display protocol)
 
1408
  host display protocol ;; unused
 
1409
  (error "OPEN-X-STREAM not implemented yet."))
 
1410
 
 
1411
;;; Genera:
 
1412
 
 
1413
;;; TCP and DNA are both layered products, so try to work with either one.
 
1414
 
 
1415
#+Genera
 
1416
(when (fboundp 'tcp:add-tcp-port-for-protocol)
 
1417
  (tcp:add-tcp-port-for-protocol :x-window-system 6000))
 
1418
 
 
1419
#+Genera
 
1420
(when (fboundp 'dna:add-dna-contact-id-for-protocol)
 
1421
  (dna:add-dna-contact-id-for-protocol :x-window-system "X$X0"))
 
1422
 
 
1423
#+Genera
 
1424
(net:define-protocol :x-window-system (:x-window-system :byte-stream)
 
1425
  (:invoke-with-stream ((stream :characters nil :ascii-translation nil))
 
1426
    stream))
 
1427
 
 
1428
#+Genera
 
1429
(eval-when (compile)
 
1430
  (compiler:function-defined 'tcp:open-tcp-stream)
 
1431
  (compiler:function-defined 'dna:open-dna-bidirectional-stream))
 
1432
 
 
1433
#+Genera
 
1434
(defun open-x-stream (host display protocol)
 
1435
  (let ((host (net:parse-host host)))
 
1436
    (if (or protocol (plusp display))
 
1437
        ;; The protocol was specified or the display isn't 0, so we
 
1438
        ;; can't use the Generic Network System.  If the protocol was
 
1439
        ;; specified, then use that protocol, otherwise, blindly use
 
1440
        ;; TCP.
 
1441
        (ccase protocol
 
1442
          ((:tcp nil)
 
1443
           (tcp:open-tcp-stream
 
1444
             host (+ *x-tcp-port* display) nil
 
1445
             :direction :io
 
1446
             :characters nil
 
1447
             :ascii-translation nil))
 
1448
          ((:dna)
 
1449
           (dna:open-dna-bidirectional-stream
 
1450
             host (format nil "X$X~D" display)
 
1451
             :characters nil
 
1452
             :ascii-translation nil)))
 
1453
      (let ((neti:*invoke-service-automatic-retry* t))
 
1454
        (net:invoke-service-on-host :x-window-system host)))))
 
1455
 
 
1456
#+explorer
 
1457
(defun open-x-stream (host display protocol)
 
1458
  (declare (ignore protocol))
 
1459
  (net:open-connection-on-medium
 
1460
    (net:parse-host host)                       ;Host
 
1461
    :byte-stream                                ;Medium
 
1462
    "X11"                                       ;Logical contact name
 
1463
    :stream-type :character-stream
 
1464
    :direction :bidirectional
 
1465
    :timeout-after-open nil
 
1466
    :remote-port (+ *x-tcp-port* display)))
 
1467
 
 
1468
#+explorer
 
1469
(net:define-logical-contact-name
 
1470
  "X11"
 
1471
  `((:local "X11")
 
1472
    (:chaos "X11")
 
1473
    (:nsp-stream "X11")
 
1474
    (:tcp ,*x-tcp-port*)))
 
1475
 
 
1476
#+lucid
 
1477
(defun open-x-stream (host display protocol)
 
1478
  protocol ;; unused
 
1479
  (let ((fd (connect-to-server host display)))
 
1480
    (when (minusp fd)
 
1481
      (error "Failed to connect to server: ~A ~D" host display))
 
1482
    (user::make-lisp-stream :input-handle fd
 
1483
                            :output-handle fd
 
1484
                            :element-type 'unsigned-byte
 
1485
                            #-lcl3.0 :stream-type #-lcl3.0 :ephemeral)))
 
1486
 
 
1487
#+(or kcl ibcl)
 
1488
(defun open-x-stream (host display protocol)
 
1489
  protocol ;; unused
 
1490
  (let ((stream (open-socket-stream host display)))
 
1491
    (if (streamp stream)
 
1492
        stream
 
1493
      (error "Cannot connect to server: ~A:~D" host display))))
 
1494
 
 
1495
#+excl
 
1496
;;
 
1497
;; Note that since we don't use the CL i/o facilities to do i/o, the display
 
1498
;; input and output "stream" is really a file descriptor (fixnum).
 
1499
;;
 
1500
(defun open-x-stream (host display protocol)
 
1501
  (declare (ignore protocol));; unused
 
1502
  (let ((fd (connect-to-server (string host) display)))
 
1503
    (when (minusp fd)
 
1504
      (error "Failed to connect to server: ~A ~D" host display))
 
1505
    fd))
 
1506
 
 
1507
#+Minima
 
1508
(defun open-x-stream (host display protocol)
 
1509
  (declare (ignore protocol));; unused
 
1510
  (minima:open-tcp-stream :foreign-address (apply #'minima:make-ip-address
 
1511
                                                  (cdr (host-address host)))
 
1512
                          :foreign-port (+ *x-tcp-port* display)))
 
1513
 
 
1514
#+(or sbcl ecl)
 
1515
(defconstant +X-unix-socket-path+
 
1516
  "/tmp/.X11-unix/X"
 
1517
  "The location of the X socket")
 
1518
 
 
1519
#+sbcl
 
1520
(defun open-x-stream (host display protocol)  
 
1521
  (declare (ignore protocol)
 
1522
           (type (integer 0) display))
 
1523
  (socket-make-stream 
 
1524
   (if (or (string= host "") (string= host "unix")) ; AF_LOCAL domain socket
 
1525
       (let ((s (make-instance 'local-socket :type :stream)))
 
1526
         (socket-connect s (format nil "~A~D" +X-unix-socket-path+ display))
 
1527
         s)
 
1528
       (let ((host (car (host-ent-addresses (get-host-by-name host)))))
 
1529
         (when host
 
1530
           (let ((s (make-instance 'inet-socket :type :stream :protocol :tcp)))
 
1531
             (socket-connect s host (+ 6000 display))
 
1532
             s))))
 
1533
   :element-type '(unsigned-byte 8)
 
1534
   :input t :output t :buffering :none))
 
1535
 
 
1536
#+ecl
 
1537
(defun open-x-stream (host display protocol)
 
1538
  (declare (ignore protocol)
 
1539
           (type (integer 0) display))
 
1540
  (let (socket)
 
1541
    (if (or (string= host "") (string= host "unix")) ; AF_UNIX doamin socket
 
1542
        (sys::open-unix-socket-stream
 
1543
         (format nil "~A~D" +X-unix-socket-path+ display))
 
1544
        (si::open-client-stream host (+ 6000 display)))))
 
1545
 
 
1546
;;; BUFFER-READ-DEFAULT - read data from the X stream
 
1547
 
 
1548
#+(or Genera explorer)
 
1549
(defun buffer-read-default (display vector start end timeout)
 
1550
  ;; returns non-NIL if EOF encountered
 
1551
  ;; Returns :TIMEOUT when timeout exceeded
 
1552
  (declare (type display display)
 
1553
           (type buffer-bytes vector)
 
1554
           (type array-index start end)
 
1555
           (type (or null (real 0 *)) timeout))
 
1556
  #.(declare-buffun)
 
1557
  (let ((stream (display-input-stream display)))
 
1558
    (or (cond ((null stream))
 
1559
              ((funcall stream :listen) nil)
 
1560
              ((and timeout (= timeout 0)) :timeout)
 
1561
              ((buffer-input-wait-default display timeout)))
 
1562
        (multiple-value-bind (ignore eofp)
 
1563
            (funcall stream :string-in nil vector start end)
 
1564
          eofp))))
 
1565
 
 
1566
 
 
1567
#+excl
 
1568
;;
 
1569
;; Rewritten 10/89 to not use foreign function interface to do I/O.
 
1570
;;
 
1571
(defun buffer-read-default (display vector start end timeout)
 
1572
  (declare (type display display)
 
1573
           (type buffer-bytes vector)
 
1574
           (type array-index start end)
 
1575
           (type (or null (real 0 *)) timeout))
 
1576
  #.(declare-buffun)
 
1577
    
 
1578
  (let* ((howmany (- end start))
 
1579
         (fd (display-input-stream display)))
 
1580
    (declare (type array-index howmany)
 
1581
             (fixnum fd))
 
1582
    (or (cond ((fd-char-avail-p fd) nil)
 
1583
              ((and timeout (= timeout 0)) :timeout)
 
1584
              ((buffer-input-wait-default display timeout)))
 
1585
        (fd-read-bytes fd vector start howmany))))
 
1586
 
 
1587
 
 
1588
#+lcl3.0
 
1589
(defmacro with-underlying-stream ((variable stream display direction) &body body)
 
1590
  `(let ((,variable
 
1591
          (or (getf (display-plist ,display) ',direction)
 
1592
              (setf (getf (display-plist ,display) ',direction)
 
1593
                    (lucid::underlying-stream
 
1594
                      ,stream ,(if (eq direction 'input) :input :output))))))
 
1595
     ,@body))
 
1596
 
 
1597
#+lcl3.0
 
1598
(defun buffer-read-default (display vector start end timeout)
 
1599
  ;;Note that LISTEN must still be done on "slow stream" or the I/O system
 
1600
  ;;gets confused.  But reading should be done from "fast stream" for speed.
 
1601
  ;;We used to inhibit scheduling because there were races in Lucid's
 
1602
  ;;multitasking system.  Empirical evidence suggests they may be gone now.
 
1603
  ;;Should you decide you need to inhibit scheduling, do it around the
 
1604
  ;;lcl:read-array.
 
1605
  (declare (type display display)
 
1606
           (type buffer-bytes vector)
 
1607
           (type array-index start end)
 
1608
           (type (or null (real 0 *)) timeout))
 
1609
  #.(declare-buffun)
 
1610
  (let ((stream (display-input-stream display)))
 
1611
    (declare (type (or null stream) stream))
 
1612
    (or (cond ((null stream))
 
1613
              ((listen stream) nil)
 
1614
              ((and timeout (= timeout 0)) :timeout)
 
1615
              ((buffer-input-wait-default display timeout)))
 
1616
        (with-underlying-stream (stream stream display input)
 
1617
          (eq (lcl:read-array stream vector start end nil :eof) :eof)))))
 
1618
 
 
1619
#+Minima
 
1620
(defun buffer-read-default (display vector start end timeout)
 
1621
  ;; returns non-NIL if EOF encountered
 
1622
  ;; Returns :TIMEOUT when timeout exceeded
 
1623
  (declare (type display display)
 
1624
           (type buffer-bytes vector)
 
1625
           (type array-index start end)
 
1626
           (type (or null (real 0 *)) timeout))
 
1627
  #.(declare-buffun)
 
1628
  (let ((stream (display-input-stream display)))
 
1629
    (or (cond ((null stream))
 
1630
              ((listen stream) nil)
 
1631
              ((and timeout (= timeout 0)) :timeout)
 
1632
              ((buffer-input-wait-default display timeout)))
 
1633
        (eq :eof (minima:read-vector vector stream nil start end)))))
 
1634
 
 
1635
;;; BUFFER-READ-DEFAULT for CMU Common Lisp.
 
1636
;;;
 
1637
;;;    If timeout is 0, then we call LISTEN to see if there is any input.
 
1638
;;; Timeout 0 is the only case where READ-INPUT dives into BUFFER-READ without
 
1639
;;; first calling BUFFER-INPUT-WAIT-DEFAULT.
 
1640
;;;
 
1641
#+(or CMU sbcl)
 
1642
(defun buffer-read-default (display vector start end timeout)
 
1643
  (declare (type display display)
 
1644
           (type buffer-bytes vector)
 
1645
           (type array-index start end)
 
1646
           (type (or null fixnum) timeout))
 
1647
  #.(declare-buffun)
 
1648
  (cond ((and (eql timeout 0)
 
1649
              (not (listen (display-input-stream display))))
 
1650
         :timeout)
 
1651
        (t
 
1652
         (#+cmu system:read-n-bytes
 
1653
          #+sbcl sb-sys:read-n-bytes
 
1654
          (display-input-stream display)
 
1655
          vector start (- end start))
 
1656
         nil)))
 
1657
 
 
1658
#+ecl
 
1659
(defun buffer-read-default (display vector start end timeout)
 
1660
  (declare (type display display)
 
1661
           (type buffer-bytes vector)
 
1662
           (type array-index start end)
 
1663
           (type (or null fixnum) timeout))
 
1664
  #.(declare-buffun)
 
1665
  (cond ((and (eql timeout 0)
 
1666
              (not (listen (display-input-stream display))))
 
1667
         :timeout)
 
1668
        (t
 
1669
         (read-sequence vector
 
1670
                        (display-input-stream display)
 
1671
                        :start start
 
1672
                        :end end)
 
1673
         nil)))
 
1674
 
 
1675
;;; WARNING:
 
1676
;;;     CLX performance will suffer if your lisp uses read-byte for
 
1677
;;;     receiving all data from the X Window System server.
 
1678
;;;     You are encouraged to write a specialized version of
 
1679
;;;     buffer-read-default that does block transfers.
 
1680
#-(or Genera explorer excl lcl3.0 Minima CMU sbcl ecl)
 
1681
(defun buffer-read-default (display vector start end timeout)
 
1682
  (declare (type display display)
 
1683
           (type buffer-bytes vector)
 
1684
           (type array-index start end)
 
1685
           (type (or null (real 0 *)) timeout))
 
1686
  #.(declare-buffun)
 
1687
  (let ((stream (display-input-stream display)))
 
1688
    (declare (type (or null stream) stream))
 
1689
    (or (cond ((null stream))
 
1690
              ((listen stream) nil)
 
1691
              ((and timeout (= timeout 0)) :timeout)
 
1692
              ((buffer-input-wait-default display timeout)))
 
1693
        (do* ((index start (index1+ index)))
 
1694
             ((index>= index end) nil)
 
1695
          (declare (type array-index index))
 
1696
          (let ((c (read-byte stream nil nil)))
 
1697
            (declare (type (or null card8) c))
 
1698
            (if (null c)
 
1699
                (return t)
 
1700
              (setf (aref vector index) (the card8 c))))))))
 
1701
 
 
1702
;;; BUFFER-WRITE-DEFAULT - write data to the X stream
 
1703
 
 
1704
#+(or Genera explorer)
 
1705
(defun buffer-write-default (vector display start end)
 
1706
  ;; The default buffer write function for use with common-lisp streams
 
1707
  (declare (type buffer-bytes vector)
 
1708
           (type display display)
 
1709
           (type array-index start end))
 
1710
  #.(declare-buffun)
 
1711
  (let ((stream (display-output-stream display)))
 
1712
    (declare (type (or null stream) stream))
 
1713
    (unless (null stream) 
 
1714
      (write-string vector stream :start start :end end))))
 
1715
 
 
1716
#+excl
 
1717
(defun buffer-write-default (vector display start end)
 
1718
  (declare (type buffer-bytes vector)
 
1719
           (type display display)
 
1720
           (type array-index start end))
 
1721
  #.(declare-buffun)
 
1722
  (excl::filesys-write-bytes (display-output-stream display) vector start
 
1723
                             (- end start)))
 
1724
  
 
1725
#+lcl3.0
 
1726
(defun buffer-write-default (vector display start end)
 
1727
  ;;We used to inhibit scheduling because there were races in Lucid's
 
1728
  ;;multitasking system.  Empirical evidence suggests they may be gone now.
 
1729
  ;;Should you decide you need to inhibit scheduling, do it around the
 
1730
  ;;lcl:write-array.
 
1731
  (declare (type display display)
 
1732
           (type buffer-bytes vector)
 
1733
           (type array-index start end))
 
1734
  #.(declare-buffun)
 
1735
  (let ((stream (display-output-stream display)))
 
1736
    (declare (type (or null stream) stream))
 
1737
    (unless (null stream) 
 
1738
      (with-underlying-stream (stream stream display output)
 
1739
        (lcl:write-array stream vector start end)))))
 
1740
 
 
1741
#+Minima
 
1742
(defun buffer-write-default (vector display start end)
 
1743
  ;; The default buffer write function for use with common-lisp streams
 
1744
  (declare (type buffer-bytes vector)
 
1745
           (type display display)
 
1746
           (type array-index start end))
 
1747
  #.(declare-buffun)
 
1748
  (let ((stream (display-output-stream display)))
 
1749
    (declare (type (or null stream) stream))
 
1750
    (unless (null stream) 
 
1751
      (minima:write-vector vector stream start end))))
 
1752
 
 
1753
#+CMU
 
1754
(defun buffer-write-default (vector display start end)
 
1755
  (declare (type buffer-bytes vector)
 
1756
           (type display display)
 
1757
           (type array-index start end))
 
1758
  #.(declare-buffun)
 
1759
  (system:output-raw-bytes (display-output-stream display) vector start end)
 
1760
  nil)
 
1761
 
 
1762
#+sbcl
 
1763
(defun buffer-write-default (vector display start end)
 
1764
  (declare (type buffer-bytes vector)
 
1765
           (type display display)
 
1766
           (type array-index start end))
 
1767
  #.(declare-buffun)
 
1768
  (sb-impl::output-raw-bytes (display-output-stream display) vector start end)
 
1769
  nil)
 
1770
 
 
1771
#+ecl
 
1772
(defun buffer-write-default (vector display start end)
 
1773
  (declare (type buffer-bytes vector)
 
1774
           (type display display)
 
1775
           (type array-index start end))
 
1776
  #.(declare-buffun)
 
1777
  (write-sequence vector
 
1778
                  (display-output-stream display)
 
1779
                  :start start
 
1780
                  :end end)
 
1781
  nil)
 
1782
 
 
1783
;;; WARNING:
 
1784
;;;     CLX performance will be severely degraded if your lisp uses
 
1785
;;;     write-byte to send all data to the X Window System server.
 
1786
;;;     You are STRONGLY encouraged to write a specialized version
 
1787
;;;     of buffer-write-default that does block transfers.
 
1788
 
 
1789
#-(or Genera explorer excl lcl3.0 Minima CMU sbcl)
 
1790
(defun buffer-write-default (vector display start end)
 
1791
  ;; The default buffer write function for use with common-lisp streams
 
1792
  (declare (type buffer-bytes vector)
 
1793
           (type display display)
 
1794
           (type array-index start end))
 
1795
  #.(declare-buffun)
 
1796
  (let ((stream (display-output-stream display)))
 
1797
    (declare (type (or null stream) stream))
 
1798
    (unless (null stream)
 
1799
      (with-vector (vector buffer-bytes)
 
1800
        (do ((index start (index1+ index)))
 
1801
            ((index>= index end))
 
1802
          (declare (type array-index index))
 
1803
          (write-byte (aref vector index) stream))))))
 
1804
 
 
1805
;;; buffer-force-output-default - force output to the X stream
 
1806
 
 
1807
#+excl
 
1808
(defun buffer-force-output-default (display)
 
1809
  ;; buffer-write-default does the actual writing.
 
1810
  (declare (ignore display)))
 
1811
 
 
1812
#-(or excl)
 
1813
(defun buffer-force-output-default (display)
 
1814
  ;; The default buffer force-output function for use with common-lisp streams
 
1815
  (declare (type display display))
 
1816
  (let ((stream (display-output-stream display)))
 
1817
    (declare (type (or null stream) stream))
 
1818
    (unless (null stream)
 
1819
      (force-output stream))))
 
1820
 
 
1821
;;; BUFFER-CLOSE-DEFAULT - close the X stream
 
1822
 
 
1823
#+excl
 
1824
(defun buffer-close-default (display &key abort)
 
1825
  ;; The default buffer close function for use with common-lisp streams
 
1826
  (declare (type display display)
 
1827
           (ignore abort))
 
1828
  #.(declare-buffun)
 
1829
  (excl::filesys-checking-close (display-output-stream display)))
 
1830
 
 
1831
#-(or excl)
 
1832
(defun buffer-close-default (display &key abort)
 
1833
  ;; The default buffer close function for use with common-lisp streams
 
1834
  (declare (type display display))
 
1835
  #.(declare-buffun)
 
1836
  (let ((stream (display-output-stream display)))
 
1837
    (declare (type (or null stream) stream))
 
1838
    (unless (null stream)
 
1839
      (close stream :abort abort))))
 
1840
 
 
1841
;;; BUFFER-INPUT-WAIT-DEFAULT - wait for for input to be available for the
 
1842
;;; buffer.  This is called in read-input between requests, so that a process
 
1843
;;; waiting for input is abortable when between requests.  Should return
 
1844
;;; :TIMEOUT if it times out, NIL otherwise.
 
1845
 
 
1846
;;; The default implementation
 
1847
 
 
1848
;; Poll for input every *buffer-read-polling-time* SECONDS.
 
1849
#-(or Genera explorer excl lcl3.0 CMU sbcl)
 
1850
(defparameter *buffer-read-polling-time* 0.5)
 
1851
 
 
1852
#-(or Genera explorer excl lcl3.0 CMU sbcl)
 
1853
(defun buffer-input-wait-default (display timeout)
 
1854
  (declare (type display display)
 
1855
           (type (or null (real 0 *)) timeout))
 
1856
  (declare (clx-values timeout))
 
1857
  
 
1858
  (let ((stream (display-input-stream display)))
 
1859
    (declare (type (or null stream) stream))
 
1860
    (cond ((null stream))
 
1861
          ((listen stream) nil)
 
1862
          ((and timeout (= timeout 0)) :timeout)
 
1863
          ((not (null timeout))
 
1864
           (multiple-value-bind (npoll fraction)
 
1865
               (truncate timeout *buffer-read-polling-time*)
 
1866
             (dotimes (i npoll)                 ; Sleep for a time, then listen again
 
1867
               (sleep *buffer-read-polling-time*)
 
1868
               (when (listen stream)
 
1869
                 (return-from buffer-input-wait-default nil)))
 
1870
             (when (plusp fraction)
 
1871
               (sleep fraction)                 ; Sleep a fraction of a second
 
1872
               (when (listen stream)            ; and listen one last time
 
1873
                 (return-from buffer-input-wait-default nil)))
 
1874
             :timeout)))))
 
1875
 
 
1876
#+(or CMU sbcl)
 
1877
(defun buffer-input-wait-default (display timeout)
 
1878
  (declare (type display display)
 
1879
           (type (or null number) timeout))
 
1880
  (let ((stream (display-input-stream display)))
 
1881
    (declare (type (or null stream) stream))
 
1882
    (cond ((null stream))
 
1883
          ((listen stream) nil)
 
1884
          ((eql timeout 0) :timeout)
 
1885
          (t
 
1886
           (if #+sbcl (sb-sys:wait-until-fd-usable (sb-sys:fd-stream-fd stream)
 
1887
                                                   :input timeout)
 
1888
               #+mp (mp:process-wait-until-fd-usable
 
1889
                     (system:fd-stream-fd stream) :input timeout)
 
1890
               #-(or sbcl mp) (system:wait-until-fd-usable
 
1891
                               (system:fd-stream-fd stream) :input timeout)
 
1892
               nil
 
1893
               :timeout)))))
 
1894
 
 
1895
#+Genera
 
1896
(defun buffer-input-wait-default (display timeout)
 
1897
  (declare (type display display)
 
1898
           (type (or null (real 0 *)) timeout))
 
1899
  (declare (clx-values timeout))
 
1900
  (let ((stream (display-input-stream display)))
 
1901
    (declare (type (or null stream) stream))
 
1902
    (cond ((null stream))
 
1903
          ((scl:send stream :listen) nil)
 
1904
          ((and timeout (= timeout 0)) :timeout)
 
1905
          ((null timeout) (si:stream-input-block stream "CLX Input"))
 
1906
          (t
 
1907
           (scl:condition-bind ((neti:protocol-timeout
 
1908
                                  #'(lambda (error)
 
1909
                                      (when (eq stream (scl:send error :stream))
 
1910
                                        (return-from buffer-input-wait-default :timeout)))))
 
1911
             (neti:with-stream-timeout (stream :input timeout)
 
1912
               (si:stream-input-block stream "CLX Input")))))
 
1913
    nil))
 
1914
 
 
1915
#+explorer
 
1916
(defun buffer-input-wait-default (display timeout)
 
1917
  (declare (type display display)
 
1918
           (type (or null (real 0 *)) timeout))
 
1919
  (declare (clx-values timeout))
 
1920
  (let ((stream (display-input-stream display)))
 
1921
    (declare (type (or null stream) stream))
 
1922
    (cond ((null stream))
 
1923
          ((zl:send stream :listen) nil)
 
1924
          ((and timeout (= timeout 0)) :timeout)
 
1925
          ((null timeout)
 
1926
           (si:process-wait "CLX Input" stream :listen))
 
1927
          (t
 
1928
           (unless (si:process-wait-with-timeout
 
1929
                       "CLX Input" (round (* timeout 60.)) stream :listen)
 
1930
             (return-from buffer-input-wait-default :timeout))))
 
1931
    nil))
 
1932
 
 
1933
#+excl
 
1934
;;
 
1935
;; This is used so an 'eq' test may be used to find out whether or not we can
 
1936
;; safely throw this process out of the CLX read loop.
 
1937
;;
 
1938
(defparameter *read-whostate* "waiting for input from X server")
 
1939
 
 
1940
;;
 
1941
;; Note that this function returns nil on error if the scheduler is running,
 
1942
;; t on error if not.  This is ok since buffer-read will detect the error.
 
1943
;;
 
1944
#+excl
 
1945
(defun buffer-input-wait-default (display timeout)
 
1946
  (declare (type display display)
 
1947
           (type (or null (real 0 *)) timeout))
 
1948
  (declare (clx-values timeout))
 
1949
  (let ((fd (display-input-stream display)))
 
1950
    (declare (fixnum fd))
 
1951
    (when (>= fd 0)
 
1952
      (cond ((fd-char-avail-p fd)
 
1953
             nil)
 
1954
            
 
1955
            ;; Otherwise no bytes were available on the socket
 
1956
            ((and timeout (= timeout 0))
 
1957
             ;; If there aren't enough and timeout == 0, timeout.
 
1958
             :timeout)
 
1959
          
 
1960
            ;; If the scheduler is running let it do timeouts.
 
1961
            (mp::*scheduler-stack-group*
 
1962
             #+allegro
 
1963
             (if (not
 
1964
                  (mp:wait-for-input-available fd :whostate *read-whostate*
 
1965
                                               :wait-function #'fd-char-avail-p
 
1966
                                               :timeout timeout))
 
1967
                 (return-from buffer-input-wait-default :timeout))
 
1968
             #-allegro
 
1969
             (mp::wait-for-input-available fd :whostate *read-whostate*
 
1970
                                           :wait-function #'fd-char-avail-p))
 
1971
            
 
1972
            ;; Otherwise we have to handle timeouts by hand, and call select()
 
1973
            ;; to block until input is available.  Note we don't really handle
 
1974
            ;; the interaction of interrupts and (numberp timeout) here.  XX
 
1975
            (t
 
1976
             (let ((res 0))
 
1977
               (declare (fixnum res))
 
1978
               (with-interrupt-checking-on
 
1979
                (loop
 
1980
                  (setq res (fd-wait-for-input fd (if (null timeout) 0
 
1981
                                                    (truncate timeout))))
 
1982
                  (cond ((plusp res)    ; success
 
1983
                         (return nil))
 
1984
                        ((eq res 0)     ; timeout
 
1985
                         (return :timeout))
 
1986
                        ((eq res -1)    ; error
 
1987
                         (return t))
 
1988
                        ;; Otherwise we got an interrupt -- go around again.
 
1989
                        )))))))))
 
1990
 
 
1991
           
 
1992
#+lcl3.0
 
1993
(defun buffer-input-wait-default (display timeout)
 
1994
  (declare (type display display)
 
1995
           (type (or null (real 0 *)) timeout)
 
1996
           (clx-values timeout))
 
1997
  #.(declare-buffun)
 
1998
  (let ((stream (display-input-stream display)))
 
1999
    (declare (type (or null stream) stream))
 
2000
    (cond ((null stream))
 
2001
          ((listen stream) nil)
 
2002
          ((and timeout (= timeout 0)) :timeout)
 
2003
          ((with-underlying-stream (stream stream display input)
 
2004
             (lucid::waiting-for-input-from-stream stream
 
2005
               (lucid::with-io-unlocked
 
2006
                 (if (null timeout)
 
2007
                     (lcl:process-wait "CLX Input" #'listen stream)
 
2008
                   (lcl:process-wait-with-timeout
 
2009
                     "CLX Input" timeout #'listen stream)))))
 
2010
           nil)
 
2011
          (:timeout))))
 
2012
 
 
2013
 
 
2014
;;; BUFFER-LISTEN-DEFAULT - returns T if there is input available for the
 
2015
;;; buffer. This should never block, so it can be called from the scheduler.
 
2016
 
 
2017
;;; The default implementation is to just use listen.
 
2018
#-(or excl)
 
2019
(defun buffer-listen-default (display)
 
2020
  (declare (type display display))
 
2021
  (let ((stream (display-input-stream display)))
 
2022
    (declare (type (or null stream) stream))
 
2023
    (if (null stream)
 
2024
        t
 
2025
      (listen stream))))
 
2026
 
 
2027
#+excl 
 
2028
(defun buffer-listen-default (display)
 
2029
  (declare (type display display))
 
2030
  (let ((fd (display-input-stream display)))
 
2031
    (declare (type fixnum fd))
 
2032
    (if (= fd -1)
 
2033
        t
 
2034
      (fd-char-avail-p fd))))
 
2035
 
 
2036
 
 
2037
;;;----------------------------------------------------------------------------
 
2038
;;; System dependent speed hacks
 
2039
;;;----------------------------------------------------------------------------
 
2040
 
 
2041
;;
 
2042
;; WITH-STACK-LIST is used by WITH-STATE as a memory saving feature.
 
2043
;; If your lisp doesn't have stack-lists, and you're worried about
 
2044
;; consing garbage, you may want to re-write this to allocate and
 
2045
;; initialize lists from a resource.
 
2046
;;
 
2047
#-lispm
 
2048
(defmacro with-stack-list ((var &rest elements) &body body)
 
2049
  ;; SYNTAX: (WITH-STACK-LIST (var exp1 ... expN) body)
 
2050
  ;; Equivalent to (LET ((var (MAPCAR #'EVAL '(exp1 ... expN)))) body)
 
2051
  ;; except that the list produced by MAPCAR resides on the stack and
 
2052
  ;; therefore DISAPPEARS when WITH-STACK-LIST is exited.
 
2053
  `(let ((,var (list ,@elements)))
 
2054
     (declare (type cons ,var)
 
2055
              #+clx-ansi-common-lisp (dynamic-extent ,var))
 
2056
     ,@body))
 
2057
 
 
2058
#-lispm
 
2059
(defmacro with-stack-list* ((var &rest elements) &body body)
 
2060
  ;; SYNTAX: (WITH-STACK-LIST* (var exp1 ... expN) body)
 
2061
  ;; Equivalent to (LET ((var (APPLY #'LIST* (MAPCAR #'EVAL '(exp1 ... expN))))) body)
 
2062
  ;; except that the list produced by MAPCAR resides on the stack and
 
2063
  ;; therefore DISAPPEARS when WITH-STACK-LIST is exited.
 
2064
  `(let ((,var (list* ,@elements)))
 
2065
     (declare (type cons ,var)
 
2066
              #+clx-ansi-common-lisp (dynamic-extent ,var))
 
2067
     ,@body))
 
2068
 
 
2069
(declaim (inline buffer-replace))
 
2070
 
 
2071
#+lispm
 
2072
(defun buffer-replace (buf1 buf2 start1 end1 &optional (start2 0))
 
2073
  (declare (type vector buf1 buf2)
 
2074
           (type array-index start1 end1 start2))
 
2075
  (sys:copy-array-portion buf2 start2 (length buf2) buf1 start1 end1))
 
2076
 
 
2077
#+excl
 
2078
(defun buffer-replace (target-sequence source-sequence target-start
 
2079
                                       target-end &optional (source-start 0))
 
2080
  (declare (type buffer-bytes target-sequence source-sequence)
 
2081
           (type array-index target-start target-end source-start)
 
2082
           (optimize (speed 3) (safety 0)))
 
2083
  
 
2084
  (let ((source-end (length source-sequence)))
 
2085
    (declare (type array-index source-end))
 
2086
    
 
2087
    (excl:if* (and (eq target-sequence source-sequence)
 
2088
                   (> target-start source-start))
 
2089
       then (let ((nelts (min (- target-end target-start)
 
2090
                              (- source-end source-start))))
 
2091
              (do ((target-index (+ target-start nelts -1) (1- target-index))
 
2092
                   (source-index (+ source-start nelts -1) (1- source-index)))
 
2093
                  ((= target-index (1- target-start)) target-sequence)
 
2094
                (declare (type array-index target-index source-index))
 
2095
                
 
2096
                (setf (aref target-sequence target-index)
 
2097
                  (aref source-sequence source-index))))
 
2098
       else (do ((target-index target-start (1+ target-index))
 
2099
                 (source-index source-start (1+ source-index)))
 
2100
                ((or (= target-index target-end) (= source-index source-end))
 
2101
                 target-sequence)
 
2102
              (declare (type array-index target-index source-index))
 
2103
 
 
2104
              (setf (aref target-sequence target-index)
 
2105
                (aref source-sequence source-index))))))
 
2106
 
 
2107
#+cmu 
 
2108
(defun buffer-replace (buf1 buf2 start1 end1 &optional (start2 0))
 
2109
  (declare (type buffer-bytes buf1 buf2)
 
2110
           (type array-index start1 end1 start2))
 
2111
  #.(declare-buffun)
 
2112
  (kernel:bit-bash-copy
 
2113
   buf2 (+ (* start2 #+cmu vm:byte-bits #+sbcl sb-vm:n-byte-bits)
 
2114
           (* vm:vector-data-offset #+cmu vm:word-bits #+sbcl sb-vm:n-word-bits))
 
2115
   buf1 (+ (* start1 #+cmu vm:byte-bits #+sbcl sb-vm:n-byte-bits)
 
2116
           (* vm:vector-data-offset #+cmu vm:word-bits #+sbcl sb-vm:n-word-bits))
 
2117
   (* (- end1 start1) #+cmu vm:byte-bits #+sbcl sb-vm:n-byte-bits)))
 
2118
 
 
2119
#+lucid
 
2120
;;;The compiler is *supposed* to optimize calls to replace, but in actual
 
2121
;;;fact it does not.
 
2122
(defun buffer-replace (buf1 buf2 start1 end1 &optional (start2 0))
 
2123
  (declare (type buffer-bytes buf1 buf2)
 
2124
           (type array-index start1 end1 start2))
 
2125
  #.(declare-buffun)
 
2126
  (let ((end2 (lucid::%simple-8bit-vector-length buf2)))
 
2127
    (declare (type array-index end2))
 
2128
    (lucid::simple-8bit-vector-replace-internal
 
2129
      buf1 buf2 start1 end1 start2 end2)))
 
2130
 
 
2131
#+(and clx-overlapping-arrays (not (or lispm excl)))
 
2132
(defun buffer-replace (buf1 buf2 start1 end1 &optional (start2 0))
 
2133
  (declare (type vector buf1 buf2)
 
2134
           (type array-index start1 end1 start2))
 
2135
  (replace buf1 buf2 :start1 start1 :end1 end1 :start2 start2))
 
2136
 
 
2137
#-(or lispm lucid excl CMU clx-overlapping-arrays)
 
2138
(defun buffer-replace (buf1 buf2 start1 end1 &optional (start2 0))
 
2139
  (declare (type buffer-bytes buf1 buf2)
 
2140
           (type array-index start1 end1 start2))
 
2141
  (replace buf1 buf2 :start1 start1 :end1 end1 :start2 start2))
 
2142
 
 
2143
#+ti
 
2144
(defun with-location-bindings (sys:&quote bindings &rest body)
 
2145
  (do ((bindings bindings (cdr bindings)))
 
2146
      ((null bindings)
 
2147
       (sys:eval-body-as-progn body))
 
2148
    (sys:bind (sys:*eval `(sys:locf ,(caar bindings)))
 
2149
              (sys:*eval (cadar bindings)))))
 
2150
 
 
2151
#+ti
 
2152
(compiler:defoptimizer with-location-bindings with-l-b-compiler nil (form)
 
2153
  (let ((bindings (cadr form))
 
2154
        (body (cddr form)))
 
2155
    `(let ()
 
2156
       ,@(loop for (accessor value) in bindings
 
2157
               collect `(si:bind (si:locf ,accessor) ,value))
 
2158
       ,@body)))
 
2159
 
 
2160
#+ti
 
2161
(defun (:property with-location-bindings compiler::cw-handler) (exp)
 
2162
  (let* ((bindlist (mapcar #'compiler::cw-clause (second exp)))
 
2163
         (body (compiler::cw-clause (cddr exp))))
 
2164
    (and compiler::cw-return-expansion-flag
 
2165
         (list* (first exp) bindlist body))))
 
2166
 
 
2167
#+(and lispm (not ti))
 
2168
(defmacro with-location-bindings (bindings &body body)
 
2169
  `(sys:letf* ,bindings ,@body))
 
2170
 
 
2171
#+lispm
 
2172
(defmacro with-gcontext-bindings ((gc saved-state indexes ts-index temp-mask temp-gc)
 
2173
                                  &body body)
 
2174
  ;; don't use svref on LHS because Symbolics didn't define locf for it
 
2175
  (let* ((local-state (gensym))
 
2176
         (bindings `(((aref ,local-state ,ts-index) 0))))       ; will become zero anyway
 
2177
    (dolist (index indexes)
 
2178
      (push `((aref ,local-state ,index) (svref ,saved-state ,index))
 
2179
            bindings))
 
2180
    `(let ((,local-state (gcontext-local-state ,gc)))
 
2181
       (declare (type gcontext-state ,local-state))
 
2182
       (unwind-protect
 
2183
           (with-location-bindings ,bindings
 
2184
             ,@body)
 
2185
         (setf (svref ,local-state ,ts-index) 0)
 
2186
         (when ,temp-gc
 
2187
           (restore-gcontext-temp-state ,gc ,temp-mask ,temp-gc))
 
2188
         (deallocate-gcontext-state ,saved-state)))))
 
2189
 
 
2190
#-lispm
 
2191
(defmacro with-gcontext-bindings ((gc saved-state indexes ts-index temp-mask temp-gc)
 
2192
                                  &body body)
 
2193
  (let ((local-state (gensym))
 
2194
        (resets nil))
 
2195
    (dolist (index indexes)
 
2196
      (push `(setf (svref ,local-state ,index) (svref ,saved-state ,index))
 
2197
            resets))
 
2198
    `(unwind-protect
 
2199
         (progn
 
2200
           ,@body)
 
2201
       (let ((,local-state (gcontext-local-state ,gc)))
 
2202
         (declare (type gcontext-state ,local-state))
 
2203
         ,@resets
 
2204
         (setf (svref ,local-state ,ts-index) 0))
 
2205
       (when ,temp-gc
 
2206
         (restore-gcontext-temp-state ,gc ,temp-mask ,temp-gc))
 
2207
       (deallocate-gcontext-state ,saved-state))))
 
2208
 
 
2209
;;;----------------------------------------------------------------------------
 
2210
;;; How much error detection should CLX do?
 
2211
;;; Several levels are possible:
 
2212
;;;
 
2213
;;; 1. Do the equivalent of check-type on every argument.
 
2214
;;; 
 
2215
;;; 2. Simply report TYPE-ERROR.  This eliminates overhead of all the format
 
2216
;;;    strings generated by check-type.
 
2217
;;; 
 
2218
;;; 3. Do error checking only on arguments that are likely to have errors
 
2219
;;;    (like keyword names)
 
2220
;;; 
 
2221
;;; 4. Do error checking only where not doing so may dammage the envirnment
 
2222
;;;    on a non-tagged machine (i.e. when storing into a structure that has
 
2223
;;;    been passed in)
 
2224
;;; 
 
2225
;;; 5. No extra error detection code.  On lispm's, ASET may barf trying to
 
2226
;;;    store a non-integer into a number array. 
 
2227
;;; 
 
2228
;;; How extensive should the error checking be?  For example, if the server
 
2229
;;; expects a CARD16, is is sufficient for CLX to check for integer, or
 
2230
;;; should it also check for non-negative and less than 65536?
 
2231
;;;----------------------------------------------------------------------------
 
2232
 
 
2233
;; The +TYPE-CHECK?+ constant controls how much error checking is done.
 
2234
;; Possible values are:
 
2235
;;    NIL      - Don't do any error checking
 
2236
;;    t        - Do the equivalent of checktype on every argument
 
2237
;;    :minimal - Do error checking only where errors are likely
 
2238
 
 
2239
;;; This controls macro expansion, and isn't changable at run-time You will
 
2240
;;; probably want to set this to nil if you want good performance at
 
2241
;;; production time.
 
2242
(defconstant +type-check?+
 
2243
  #+(or Genera Minima CMU sbcl) nil
 
2244
  #-(or Genera Minima CMU sbcl) t)
 
2245
 
 
2246
;; TYPE? is used to allow the code to do error checking at a different level from
 
2247
;; the declarations.  It also does some optimizations for systems that don't have
 
2248
;; good compiler support for TYPEP.  The definitions for CARD32, CARD16, INT16, etc.
 
2249
;; include range checks.  You can modify TYPE? to do less extensive checking
 
2250
;; for these types if you desire.
 
2251
 
 
2252
;;
 
2253
;; ### This comment is a lie!  TYPE? is really also used for run-time type
 
2254
;; dispatching, not just type checking.  -- Ram.
 
2255
 
 
2256
(defmacro type? (object type)
 
2257
  #+(or cmu sbcl)
 
2258
  `(typep ,object ,type)
 
2259
  #-(or cmu sbcl)
 
2260
  (if (not (constantp type))
 
2261
      `(typep ,object ,type)
 
2262
    (progn
 
2263
      (setq type (eval type))
 
2264
      #+(or Genera explorer Minima)
 
2265
      (if +type-check?+
 
2266
          `(locally (declare (optimize safety)) (typep ,object ',type))
 
2267
        `(typep ,object ',type))
 
2268
      #-(or Genera explorer Minima)
 
2269
      (let ((predicate (assoc type
 
2270
                              '((drawable drawable-p) (window window-p)
 
2271
                                (pixmap pixmap-p) (cursor cursor-p)
 
2272
                                (font font-p) (gcontext gcontext-p)
 
2273
                                (colormap colormap-p) (null null)
 
2274
                                (integer integerp)))))
 
2275
        (cond (predicate
 
2276
               `(,(second predicate) ,object))
 
2277
              ((eq type 'generalized-boolean)
 
2278
               't)                      ; Everything is a generalized-boolean.
 
2279
              (+type-check?+
 
2280
               `(locally (declare (optimize safety)) (typep ,object ',type)))
 
2281
              (t
 
2282
               `(typep ,object ',type)))))))
 
2283
 
 
2284
;; X-TYPE-ERROR is the function called for type errors.
 
2285
;; If you want lots of checking, but are concerned about code size,
 
2286
;; this can be made into a macro that ignores some parameters.
 
2287
 
 
2288
(defun x-type-error (object type &optional error-string)
 
2289
  (x-error 'x-type-error
 
2290
           :datum object
 
2291
           :expected-type type
 
2292
           :type-string error-string))
 
2293
 
 
2294
 
 
2295
;;-----------------------------------------------------------------------------
 
2296
;; Error handlers
 
2297
;;    Hack up KMP error signaling using zetalisp until the real thing comes 
 
2298
;;    along
 
2299
;;-----------------------------------------------------------------------------
 
2300
 
 
2301
(defun default-error-handler (display error-key &rest key-vals
 
2302
                              &key asynchronous &allow-other-keys)
 
2303
  (declare (type generalized-boolean asynchronous)
 
2304
           (dynamic-extent key-vals))
 
2305
  ;; The default display-error-handler.
 
2306
  ;; It signals the conditions listed in the DISPLAY file.
 
2307
  (if asynchronous
 
2308
      (apply #'x-cerror "Ignore" error-key :display display :error-key error-key key-vals)
 
2309
      (apply #'x-error error-key :display display :error-key error-key key-vals)))
 
2310
 
 
2311
#+(and lispm (not Genera) (not clx-ansi-common-lisp))
 
2312
(defun x-error (condition &rest keyargs)
 
2313
  (apply #'sys:signal condition keyargs))
 
2314
 
 
2315
#+(and lispm (not Genera) (not clx-ansi-common-lisp))
 
2316
(defun x-cerror (proceed-format-string condition &rest keyargs)
 
2317
  (sys:signal (apply #'zl:make-condition condition keyargs)
 
2318
              :proceed-types proceed-format-string))
 
2319
 
 
2320
#+(and Genera (not clx-ansi-common-lisp))
 
2321
(defun x-error (condition &rest keyargs)
 
2322
  (declare (dbg:error-reporter))
 
2323
  (apply #'sys:signal condition keyargs))
 
2324
 
 
2325
#+(and Genera (not clx-ansi-common-lisp))
 
2326
(defun x-cerror (proceed-format-string condition &rest keyargs)
 
2327
  (declare (dbg:error-reporter))
 
2328
  (apply #'sys:signal condition :continue-format-string proceed-format-string keyargs))
 
2329
 
 
2330
#+(or clx-ansi-common-lisp excl lcl3.0 (and CMU mp))
 
2331
(defun x-error (condition &rest keyargs)
 
2332
  (declare (dynamic-extent keyargs))
 
2333
  (apply #'error condition keyargs))
 
2334
 
 
2335
#+(or clx-ansi-common-lisp excl lcl3.0 CMU)
 
2336
(defun x-cerror (proceed-format-string condition &rest keyargs)
 
2337
  (declare (dynamic-extent keyargs))
 
2338
  (apply #'cerror proceed-format-string condition keyargs))
 
2339
 
 
2340
;;; X-ERROR for CMU Common Lisp
 
2341
;;;
 
2342
;;; We detect a couple condition types for which we disable event handling in
 
2343
;;; our system.  This prevents going into the debugger or returning to a
 
2344
;;; command prompt with CLX repeatedly seeing the same condition.  This occurs
 
2345
;;; because CMU Common Lisp provides for all events (that is, X, input on file
 
2346
;;; descriptors, Mach messages, etc.) to come through one routine anyone can
 
2347
;;; use to wait for input.
 
2348
;;;
 
2349
#+(and CMU (not mp)) 
 
2350
(defun x-error (condition &rest keyargs)
 
2351
  (let ((condx (apply #'make-condition condition keyargs)))
 
2352
    (when (eq condition 'closed-display)
 
2353
      (let ((disp (closed-display-display condx)))
 
2354
        (warn "Disabled event handling on ~S." disp)
 
2355
        (ext::disable-clx-event-handling disp)))
 
2356
    (error condx)))
 
2357
 
 
2358
#-(or lispm ansi-common-lisp excl lcl3.0 CMU sbcl)
 
2359
(defun x-error (condition &rest keyargs)
 
2360
  (error "X-Error: ~a"
 
2361
         (princ-to-string (apply #'make-condition condition keyargs))))
 
2362
 
 
2363
#-(or lispm clx-ansi-common-lisp excl lcl3.0 CMU sbcl)
 
2364
(defun x-cerror (proceed-format-string condition &rest keyargs)
 
2365
  (cerror proceed-format-string "X-Error: ~a"
 
2366
         (princ-to-string (apply #'make-condition condition keyargs))))
 
2367
 
 
2368
;; version 15 of Pitman error handling defines the syntax for define-condition to be:
 
2369
;; DEFINE-CONDITION name (parent-type) [({slot}*) {option}*]
 
2370
;; Where option is one of: (:documentation doc-string) (:conc-name symbol-or-string)
 
2371
;; or (:report exp)
 
2372
 
 
2373
#+lcl3.0 
 
2374
(defmacro define-condition (name parent-types &optional slots &rest args)
 
2375
  `(lcl:define-condition
 
2376
     ,name (,(first parent-types))
 
2377
     ,(mapcar #'(lambda (slot) (if (consp slot) (car slot) slot))
 
2378
              slots)
 
2379
     ,@args))
 
2380
 
 
2381
#+(and excl (not clx-ansi-common-lisp))
 
2382
(defmacro define-condition (name parent-types &optional slots &rest args)
 
2383
  `(excl::define-condition
 
2384
     ,name (,(first parent-types))
 
2385
     ,(mapcar #'(lambda (slot) (if (consp slot) (car slot) slot))
 
2386
              slots)
 
2387
     ,@args))
 
2388
 
 
2389
#+(and CMU (not clx-ansi-common-lisp))
 
2390
(defmacro define-condition (name parent-types &optional slots &rest args)
 
2391
  `(common-lisp:define-condition
 
2392
     ,name (,(first parent-types))
 
2393
     ,(mapcar #'(lambda (slot) (if (consp slot) (car slot) slot))
 
2394
              slots)
 
2395
     ,@args))
 
2396
 
 
2397
#+(and lispm (not clx-ansi-common-lisp))
 
2398
(defmacro define-condition (name parent-types &body options)
 
2399
  (let ((slot-names
 
2400
          (mapcar #'(lambda (slot) (if (consp slot) (car slot) slot))
 
2401
                  (pop options)))
 
2402
        (documentation nil)
 
2403
        (conc-name (concatenate 'string (string name) "-"))            
 
2404
        (reporter nil))
 
2405
    (dolist (item options)
 
2406
      (ecase (first item)
 
2407
        (:documentation (setq documentation (second item)))
 
2408
        (:conc-name (setq conc-name (string (second item))))
 
2409
        (:report (setq reporter (second item)))))
 
2410
    `(within-definition (,name define-condition)
 
2411
       (zl:defflavor ,name ,slot-names ,parent-types
 
2412
         :initable-instance-variables
 
2413
         #-Genera
 
2414
         (:accessor-prefix ,conc-name)
 
2415
         #+Genera
 
2416
         (:conc-name ,conc-name)
 
2417
         #-Genera
 
2418
         (:outside-accessible-instance-variables ,@slot-names)
 
2419
         #+Genera
 
2420
         (:readable-instance-variables ,@slot-names))
 
2421
       ,(when reporter ;; when no reporter, parent's is inherited
 
2422
          `(zl:defmethod #-Genera (,name :report)
 
2423
                         #+Genera (dbg:report ,name) (stream)
 
2424
              ,(if (stringp reporter)
 
2425
                   `(write-string ,reporter stream)
 
2426
                 `(,reporter global:self stream))
 
2427
              global:self))
 
2428
       (zl:compile-flavor-methods ,name)
 
2429
       ,(when documentation
 
2430
          `(setf (documentation name 'type) ,documentation))
 
2431
       ',name)))
 
2432
 
 
2433
#+(and lispm (not Genera) (not clx-ansi-common-lisp))
 
2434
(zl:defflavor x-error () (global:error))
 
2435
 
 
2436
#+(and Genera (not clx-ansi-common-lisp))
 
2437
(scl:defflavor x-error
 
2438
        ((dbg:proceed-types '(:continue))       ;
 
2439
         continue-format-string)
 
2440
        (sys:error)
 
2441
  (:initable-instance-variables continue-format-string))
 
2442
 
 
2443
#+(and Genera (not clx-ansi-common-lisp))
 
2444
(scl:defmethod (scl:make-instance x-error) (&rest ignore)
 
2445
  (when (not (sys:variable-boundp continue-format-string))
 
2446
    (setf dbg:proceed-types (remove :continue dbg:proceed-types))))
 
2447
 
 
2448
#+(and Genera (not clx-ansi-common-lisp))
 
2449
(scl:defmethod (dbg:proceed x-error :continue) ()
 
2450
  :continue)
 
2451
 
 
2452
#+(and Genera (not clx-ansi-common-lisp))
 
2453
(sys:defmethod (dbg:document-proceed-type x-error :continue) (stream)
 
2454
  (format stream continue-format-string))
 
2455
 
 
2456
#+(or clx-ansi-common-lisp excl lcl3.0 CMU sbcl)
 
2457
(define-condition x-error (error) ())
 
2458
 
 
2459
#-(or lispm clx-ansi-common-lisp excl lcl3.0 CMU sbcl)
 
2460
(defstruct x-error
 
2461
  report-function)
 
2462
 
 
2463
#-(or lispm clx-ansi-common-lisp excl lcl3.0 CMU sbcl)
 
2464
(defmacro define-condition (name parent-types &body options)
 
2465
  ;; Define a structure that when printed displays an error message
 
2466
  (flet ((reporter-for-condition (name)
 
2467
           (xintern "." name '-reporter.)))
 
2468
    (let ((slot-names
 
2469
            (mapcar #'(lambda (slot) (if (consp slot) (car slot) slot))
 
2470
                    (pop options)))
 
2471
          (documentation nil)
 
2472
          (conc-name (concatenate 'string (string name) "-"))          
 
2473
          (reporter nil)
 
2474
          (condition (gensym))
 
2475
          (stream (gensym))
 
2476
          (report-function (reporter-for-condition name)))
 
2477
      (dolist (item options)
 
2478
        (ecase (first item)
 
2479
          (:documentation (setq documentation (second item)))
 
2480
          (:conc-name (setq conc-name (string (second item))))
 
2481
          (:report (setq reporter (second item)))))
 
2482
      (unless reporter
 
2483
        (setq report-function (reporter-for-condition (first parent-types))))
 
2484
      `(within-definition (,name define-condition)
 
2485
         (defstruct (,name (:conc-name ,(intern conc-name))
 
2486
                     (:print-function condition-print)
 
2487
                     (:include ,(first parent-types)
 
2488
                      (report-function ',report-function)))
 
2489
           ,@slot-names)
 
2490
         ,(when documentation
 
2491
            `(setf (documentation name 'type) ,documentation))
 
2492
         ,(when reporter
 
2493
            `(defun ,report-function (,condition ,stream)
 
2494
               ,(if (stringp reporter)
 
2495
                    `(write-string ,reporter ,stream)
 
2496
                  `(,reporter ,condition ,stream))
 
2497
               ,condition))
 
2498
         ',name))))
 
2499
 
 
2500
#-(or lispm clx-ansi-common-lisp excl lcl3.0 CMU sbcl)
 
2501
(defun condition-print (condition stream depth)
 
2502
  (declare (type x-error condition)
 
2503
           (type stream stream)
 
2504
           (ignore depth))
 
2505
  (if *print-escape*
 
2506
      (print-unreadable-object (condition stream :type t))
 
2507
    (funcall (x-error-report-function condition) condition stream))
 
2508
  condition)
 
2509
  
 
2510
#-(or lispm clx-ansi-common-lisp excl lcl3.0 CMU sbcl)
 
2511
(defun make-condition (type &rest slot-initializations)
 
2512
  (declare (dynamic-extent slot-initializations))
 
2513
  (let ((make-function (intern (concatenate 'string (string 'make-) (string type))
 
2514
                               (symbol-package type))))
 
2515
    (apply make-function slot-initializations)))
 
2516
 
 
2517
#-(or clx-ansi-common-lisp excl lcl3.0 CMU sbcl)
 
2518
(define-condition type-error (x-error)
 
2519
  ((datum :reader type-error-datum :initarg :datum)
 
2520
   (expected-type :reader type-error-expected-type :initarg :expected-type))
 
2521
  (:report
 
2522
    (lambda (condition stream)
 
2523
      (format stream "~s isn't a ~a"
 
2524
              (type-error-datum condition)
 
2525
              (type-error-expected-type condition)))))
 
2526
 
 
2527
 
 
2528
;;-----------------------------------------------------------------------------
 
2529
;;  HOST hacking
 
2530
;;-----------------------------------------------------------------------------
 
2531
 
 
2532
#-(or explorer Genera Minima Allegro CMU sbcl ecl)
 
2533
(defun host-address (host &optional (family :internet))
 
2534
  ;; Return a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2535
  ;; and cdr is a list of network address bytes.
 
2536
  (declare (type stringable host)
 
2537
           (type (or null (member :internet :decnet :chaos) card8) family))
 
2538
  (declare (clx-values list))
 
2539
  host family
 
2540
  (error "HOST-ADDRESS not implemented yet."))
 
2541
 
 
2542
#+explorer
 
2543
(defun host-address (host &optional (family :internet))
 
2544
  ;; Return a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2545
  ;; and cdr is a list of network address bytes.
 
2546
  (declare (type stringable host)
 
2547
           (type (or null (member :internet :decnet :chaos) card8) family))
 
2548
  (declare (clx-values list))
 
2549
  (ecase family
 
2550
    ((:internet nil 0)
 
2551
     (let ((addr (ip:get-ip-address host)))
 
2552
       (unless addr (error "~s isn't an internet host name" host))
 
2553
       (list :internet
 
2554
             (ldb (byte 8 24) addr)
 
2555
             (ldb (byte 8 16) addr)
 
2556
             (ldb (byte 8 8) addr)
 
2557
             (ldb (byte 8 0) addr))))
 
2558
    ((:chaos 2)
 
2559
     (let ((addr (first (chaos:chaos-addresses host))))
 
2560
       (unless addr (error "~s isn't a chaos host name" host))
 
2561
       (list :chaos
 
2562
             (ldb (byte 8 0) addr)
 
2563
             (ldb (byte 8 8) addr))))))
 
2564
 
 
2565
#+Genera
 
2566
(defun host-address (host &optional (family :internet))
 
2567
  ;; Return a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2568
  ;; and cdr is a list of network address bytes.
 
2569
  (declare (type stringable host)
 
2570
           (type (or null (member :internet :decnet :chaos) card8) family))
 
2571
  (declare (clx-values list))
 
2572
  (setf host (string host))
 
2573
  (let ((net-type (ecase family
 
2574
                    ((:internet nil 0) :internet)
 
2575
                    ((:DECnet 1) :dna)
 
2576
                    ((:chaos 2) :chaos))))
 
2577
    (dolist (addr
 
2578
              (sys:send (net:parse-host host) :network-addresses)
 
2579
              (error "~S isn't a valid ~(~A~) host name" host family))
 
2580
      (let ((network (car addr))
 
2581
            (address (cadr addr)))
 
2582
        (when (sys:send network :network-typep net-type)
 
2583
          (return (ecase family
 
2584
                    ((:internet nil 0)
 
2585
                     (multiple-value-bind (a b c d) (tcp:explode-internet-address address)
 
2586
                       (list :internet a b c d)))
 
2587
                    ((:DECnet 1)
 
2588
                     (list :DECnet (ldb (byte 8 0) address) (ldb (byte 8 8) address)))
 
2589
                    ((:chaos 2)
 
2590
                     (list :chaos (ldb (byte 8 0) address) (ldb (byte 8 8) address))))))))))
 
2591
 
 
2592
#+Minima
 
2593
(defun host-address (host &optional (family :internet))
 
2594
  ;; Return a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2595
  ;; and cdr is a list of network address bytes.
 
2596
  (declare (type stringable host)
 
2597
           (type (or null (member :internet :decnet :chaos) card8) family))
 
2598
  (declare (clx-values list))
 
2599
  (etypecase family
 
2600
    ((:internet nil 0)
 
2601
      (list* :internet
 
2602
             (multiple-value-list
 
2603
               (minima:ip-address-components (minima:parse-ip-address (string host))))))))
 
2604
 
 
2605
#+Allegro
 
2606
(defun host-address (host &optional (family :internet))
 
2607
  ;; Return a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2608
  ;; and cdr is a list of network address bytes.
 
2609
  (declare (type stringable host)
 
2610
           (type (or null (member :internet :decnet :chaos) card8) family))
 
2611
  (declare (clx-values list))
 
2612
  (labels ((no-host-error ()
 
2613
             (error "Unknown host ~S" host))
 
2614
           (no-address-error ()
 
2615
             (error "Host ~S has no ~S address" host family)))
 
2616
    (let ((hostent 0))
 
2617
      (unwind-protect
 
2618
           (progn
 
2619
             (setf hostent (ipc::gethostbyname (string host)))
 
2620
             (when (zerop hostent)
 
2621
               (no-host-error))
 
2622
             (ecase family
 
2623
               ((:internet nil 0)
 
2624
                (unless (= (ipc::hostent-addrtype hostent) 2)
 
2625
                  (no-address-error))
 
2626
                (assert (= (ipc::hostent-length hostent) 4))
 
2627
                (let ((addr (ipc::hostent-addr hostent)))
 
2628
                   (when (or (member comp::.target.
 
2629
                                     '(:hp :sgi4d :sony :dec3100)
 
2630
                                     :test #'eq)
 
2631
                             (probe-file "/lib/ld.so"))
 
2632
                     ;; BSD 4.3 based systems require an extra indirection
 
2633
                     (setq addr (si:memref-int addr 0 0 :unsigned-long)))
 
2634
                  (list :internet
 
2635
                        (si:memref-int addr 0 0 :unsigned-byte)
 
2636
                        (si:memref-int addr 1 0 :unsigned-byte)
 
2637
                        (si:memref-int addr 2 0 :unsigned-byte)
 
2638
                        (si:memref-int addr 3 0 :unsigned-byte))))))
 
2639
        (ff:free-cstruct hostent)))))
 
2640
 
 
2641
;#+sbcl
 
2642
;(require :sockets)
 
2643
 
 
2644
#+CMU
 
2645
(defun host-address (host &optional (family :internet))
 
2646
  ;; Return a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2647
  ;; and cdr is a list of network address bytes.
 
2648
  (declare (type stringable host)
 
2649
           (type (or null (member :internet :decnet :chaos) card8) family))
 
2650
  (declare (clx-values list))
 
2651
  (labels ((no-host-error ()
 
2652
             (error "Unknown host ~S" host))
 
2653
           (no-address-error ()
 
2654
             (error "Host ~S has no ~S address" host family)))
 
2655
    (let ((hostent #+rwi-sockets(ext:lookup-host-entry (string host))
 
2656
                   #+mna-sockets(net.sbcl.sockets:look-up-host-entry
 
2657
                                 (string host)) 
 
2658
                   #+db-sockets(sockets:get-host-by-name (string host))))
 
2659
      (when (not hostent)
 
2660
        (no-host-error))
 
2661
      (ecase family
 
2662
        ((:internet nil 0)
 
2663
         #+rwi-sockets(unless (= (ext::host-entry-addr-type hostent) 2)
 
2664
                        (no-address-error))
 
2665
         #+mna-sockets(unless (= (net.sbcl.sockets::host-entry-addr-type hostent) 2)
 
2666
                        (no-address-error))
 
2667
         ;; the following form is for use with SBCL and Daniel
 
2668
         ;; Barlow's socket package
 
2669
         #+db-sockets(unless (sockets:host-ent-address hostent)
 
2670
           (no-address-error))
 
2671
         (append (list :internet)
 
2672
                 #+rwi-sockets
 
2673
                 (let ((addr (first (ext::host-entry-addr-list hostent))))
 
2674
                        (list (ldb (byte 8 24) addr)
 
2675
                              (ldb (byte 8 16) addr)
 
2676
                              (ldb (byte 8  8) addr)
 
2677
                              (ldb (byte 8  0) addr)))
 
2678
                 #+mna-sockets
 
2679
                 (let ((addr (first (net.sbcl.sockets::host-entry-addr-list hostent))))
 
2680
                                (list (ldb (byte 8 24) addr)
 
2681
                                      (ldb (byte 8 16) addr)
 
2682
                                      (ldb (byte 8  8) addr)
 
2683
                                      (ldb (byte 8  0) addr)))
 
2684
                 ;; the following form is for use with SBCL and Daniel
 
2685
                 ;; Barlow's socket package
 
2686
                 #+db-sockets(coerce (sockets:host-ent-address hostent)
 
2687
                                     'list)))))))
 
2688
 
 
2689
#+sbcl
 
2690
(defun host-address (host &optional (family :internet))
 
2691
  ;; Return a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2692
  ;; and cdr is a list of network address bytes.
 
2693
  (declare (type stringable host)
 
2694
           (type (or null (member :internet :decnet :chaos) card8) family))
 
2695
  (declare (clx-values list))
 
2696
  (let ((hostent (get-host-by-name (string host))))
 
2697
    (ecase family
 
2698
      ((:internet nil 0)
 
2699
       (cons :internet (coerce (host-ent-address hostent) 'list))))))
 
2700
 
 
2701
#+ecl
 
2702
(defun host-address (host &optional (family :internet))
 
2703
  ;; Return a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2704
  ;; and cdr is a list of network address bytes.
 
2705
  (declare (type stringable host)
 
2706
           (type (or null (member :internet :decnet :chaos) card8) family))
 
2707
  (declare (clx-values list))
 
2708
  (labels ((no-host-error ()
 
2709
             (error "Unknown host ~S" host)))
 
2710
    (let ((addr (first (nth-value 3 (si::lookup-host-entry (string host))))))
 
2711
      (unless addr
 
2712
        (no-host-error))
 
2713
      (list :internet
 
2714
            (ldb (byte 8 24) addr)
 
2715
            (ldb (byte 8 16) addr)
 
2716
            (ldb (byte 8  8) addr)
 
2717
            (ldb (byte 8  0) addr)))))
 
2718
 
 
2719
#+explorer ;; This isn't required, but it helps make sense of the results from access-hosts
 
2720
(defun get-host (host-object)
 
2721
  ;; host-object is a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2722
  ;; and cdr is a list of network address bytes.
 
2723
  (declare (type list host-object))
 
2724
  (declare (clx-values string family))
 
2725
  (let* ((family (first host-object))
 
2726
         (address (ecase family
 
2727
                    (:internet
 
2728
                     (dpb (second host-object)
 
2729
                          (byte 8 24)
 
2730
                          (dpb (third host-object)
 
2731
                               (byte 8 16)
 
2732
                               (dpb (fourth host-object)
 
2733
                                    (byte 8 8)
 
2734
                                    (fifth host-object)))))
 
2735
                    (:chaos
 
2736
                     (dpb (third host-object) (byte 8 8) (second host-object))))))
 
2737
    (when (eq family :internet) (setq family :ip))
 
2738
    (let ((host (si:get-host-from-address address family)))
 
2739
      (values (and host (funcall host :name)) family))))
 
2740
 
 
2741
;;; This isn't required, but it helps make sense of the results from access-hosts
 
2742
#+Genera
 
2743
(defun get-host (host-object)
 
2744
  ;; host-object is a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2745
  ;; and cdr is a list of network address bytes.
 
2746
  (declare (type list host-object))
 
2747
  (declare (clx-values string family))
 
2748
  (let ((family (first host-object)))
 
2749
    (values (sys:send (net:get-host-from-address 
 
2750
                        (ecase family
 
2751
                          (:internet
 
2752
                            (apply #'tcp:build-internet-address (rest host-object)))
 
2753
                          ((:chaos :DECnet)
 
2754
                           (dpb (third host-object) (byte 8 8) (second host-object))))
 
2755
                        (net:local-network-of-type (if (eq family :DECnet)
 
2756
                                                       :DNA
 
2757
                                                       family)))
 
2758
                      :name)
 
2759
            family)))
 
2760
 
 
2761
;;; This isn't required, but it helps make sense of the results from access-hosts
 
2762
#+Minima
 
2763
(defun get-host (host-object)
 
2764
  ;; host-object is a list whose car is the family keyword (:internet :DECnet :Chaos)
 
2765
  ;; and cdr is a list of network address bytes.
 
2766
  (declare (type list host-object))
 
2767
  (declare (clx-values string family))
 
2768
  (let ((family (first host-object)))
 
2769
    (values (ecase family
 
2770
              (:internet
 
2771
                (minima:ip-address-string
 
2772
                  (apply #'minima:make-ip-address (rest host-object)))))
 
2773
            family)))
 
2774
 
 
2775
 
 
2776
;;-----------------------------------------------------------------------------
 
2777
;; Whether to use closures for requests or not.
 
2778
;;-----------------------------------------------------------------------------
 
2779
 
 
2780
;;; If this macro expands to non-NIL, then request and locking code is
 
2781
;;; compiled in a much more compact format, as the common code is shared, and
 
2782
;;; the specific code is built into a closure that is funcalled by the shared
 
2783
;;; code.  If your compiler makes efficient use of closures then you probably
 
2784
;;; want to make this expand to T, as it makes the code more compact.
 
2785
 
 
2786
(defmacro use-closures ()
 
2787
  #+(or lispm Minima) t
 
2788
  #-(or lispm Minima) nil)
 
2789
 
 
2790
#+(or Genera Minima)
 
2791
(defun clx-macroexpand (form env)
 
2792
  (declare (ignore env))
 
2793
  form)
 
2794
 
 
2795
#-(or Genera Minima)
 
2796
(defun clx-macroexpand (form env)
 
2797
  (macroexpand form env))
 
2798
 
 
2799
 
 
2800
;;-----------------------------------------------------------------------------
 
2801
;; Resource stuff
 
2802
;;-----------------------------------------------------------------------------
 
2803
 
 
2804
 
 
2805
;;; Utilities 
 
2806
 
 
2807
(defun getenv (name)
 
2808
  #+excl (sys:getenv name)
 
2809
  #+lcl3.0 (lcl:environment-variable name)
 
2810
  #+CMU (cdr (assoc name ext:*environment-list* :test #'string=))
 
2811
  #+sbcl (sb-ext:posix-getenv name)
 
2812
  #+ecl (si:getenv name)
 
2813
  #-(or sbcl excl lcl3.0 CMU ecl) (progn name nil))
 
2814
 
 
2815
(defun get-host-name ()
 
2816
  "Return the same hostname as gethostname(3) would"
 
2817
  ;; machine-instance probably works on a lot of lisps, but clisp is not
 
2818
  ;; one of them
 
2819
  #+(or cmu sbcl) (machine-instance)
 
2820
  ;; resources-pathname was using short-site-name for this purpose
 
2821
  #+excl (short-site-name)
 
2822
  #+ecl (si:getenv "HOST")
 
2823
  #-(or excl cmu sbcl ecl) (error "get-host-name not implemented"))
 
2824
 
 
2825
(defun homedir-file-pathname (name)
 
2826
  (and #-(or unix mach) (search "Unix" (software-type) :test #'char-equal)
 
2827
       (merge-pathnames (user-homedir-pathname) (pathname name))))
 
2828
 
 
2829
;;; DEFAULT-RESOURCES-PATHNAME - The pathname of the resources file to load if
 
2830
;;; a resource manager isn't running.
 
2831
 
 
2832
(defun default-resources-pathname ()
 
2833
  (homedir-file-pathname ".Xdefaults"))
 
2834
 
 
2835
;;; RESOURCES-PATHNAME - The pathname of the resources file to load after the
 
2836
;;; defaults have been loaded.
 
2837
 
 
2838
(defun resources-pathname ()
 
2839
  (or (let ((string (getenv "XENVIRONMENT")))
 
2840
        (and string
 
2841
             (pathname string)))
 
2842
      (homedir-file-pathname
 
2843
       (concatenate 'string ".Xdefaults-" (get-host-name)))))
 
2844
 
 
2845
;;; AUTHORITY-PATHNAME - The pathname of the authority file.
 
2846
 
 
2847
(defun authority-pathname ()
 
2848
  (or (let ((xauthority (getenv "XAUTHORITY")))
 
2849
        (and xauthority
 
2850
             (pathname xauthority)))
 
2851
      (homedir-file-pathname ".Xauthority")))
 
2852
 
 
2853
;;; this particular defaulting behaviour is typical to most Unices, I think
 
2854
#+unix
 
2855
(defun get-default-display (&optional display-name)
 
2856
  "Parse the argument DISPLAY-NAME, or the environment variable $DISPLAY
 
2857
if it is NIL.  Display names have the format
 
2858
 
 
2859
  [protocol/] [hostname] : [:] displaynumber [.screennumber]
 
2860
 
 
2861
There are two special cases in parsing, to match that done in the Xlib
 
2862
C language bindings
 
2863
 
 
2864
 - If the hostname is ``unix'' or the empty string, any supplied
 
2865
   protocol is ignored and a connection is made using the :local
 
2866
   transport.
 
2867
 
 
2868
 - If a double colon separates hostname from displaynumber, the
 
2869
   protocol is assumed to be decnet.
 
2870
 
 
2871
Returns a list of (host display-number screen protocol)."
 
2872
  (let* ((name (or display-name
 
2873
                   (getenv "DISPLAY")
 
2874
                   (error "DISPLAY environment variable is not set")))
 
2875
         (slash-i (or (position #\/ name) -1))
 
2876
         (colon-i (position #\: name :start (1+ slash-i)))
 
2877
         (decnet-colon-p (eql (elt name (1+ colon-i)) #\:))
 
2878
         (host (subseq name (1+ slash-i) colon-i))
 
2879
         (dot-i (and colon-i (position #\. name :start colon-i)))
 
2880
         (display (when colon-i
 
2881
                    (parse-integer name
 
2882
                                   :start (if decnet-colon-p
 
2883
                                              (+ colon-i 2)
 
2884
                                              (1+ colon-i))
 
2885
                                   :end dot-i)))
 
2886
         (screen (when dot-i
 
2887
                   (parse-integer name :start (1+ dot-i))))
 
2888
         (protocol
 
2889
          (cond ((or (string= host "") (string-equal host "unix")) :local)
 
2890
                (decnet-colon-p :decnet)
 
2891
                ((> slash-i -1) (intern
 
2892
                                 (string-upcase (subseq name 0 slash-i))
 
2893
                                 :keyword))
 
2894
                (t :internet))))
 
2895
    (list host (or display 0) (or screen 0) protocol)))
 
2896
 
 
2897
#+win32
 
2898
(defun get-default-display (&optional display-name)
 
2899
  (declare (ignore display-name))
 
2900
  (list "127.0.0.1" 0 0 :internet))
 
2901
 
 
2902
 
 
2903
;;-----------------------------------------------------------------------------
 
2904
;; GC stuff
 
2905
;;-----------------------------------------------------------------------------
 
2906
 
 
2907
(defun gc-cleanup ()
 
2908
  (declare (special *event-free-list*
 
2909
                    *pending-command-free-list*
 
2910
                    *reply-buffer-free-lists*
 
2911
                    *gcontext-local-state-cache*
 
2912
                    *temp-gcontext-cache*))
 
2913
  (setq *event-free-list* nil)
 
2914
  (setq *pending-command-free-list* nil)
 
2915
  (when (boundp '*reply-buffer-free-lists*)
 
2916
    (fill *reply-buffer-free-lists* nil))
 
2917
  (setq *gcontext-local-state-cache* nil)
 
2918
  (setq *temp-gcontext-cache* nil)
 
2919
  nil)
 
2920
 
 
2921
#+Genera
 
2922
(si:define-gc-cleanup clx-cleanup ("CLX Cleanup")
 
2923
  (gc-cleanup))
 
2924
 
 
2925
 
 
2926
;;-----------------------------------------------------------------------------
 
2927
;; WITH-STANDARD-IO-SYNTAX equivalent, used in (SETF WM-COMMAND)
 
2928
;;-----------------------------------------------------------------------------
 
2929
 
 
2930
#-(or clx-ansi-common-lisp Genera CMU sbcl)
 
2931
(defun with-standard-io-syntax-function (function)
 
2932
  (declare #+lispm
 
2933
           (sys:downward-funarg function))
 
2934
  (let ((*package* (find-package :user))
 
2935
        (*print-array* t)
 
2936
        (*print-base* 10)
 
2937
        (*print-case* :upcase)
 
2938
        (*print-circle* nil)
 
2939
        (*print-escape* t)
 
2940
        (*print-gensym* t)
 
2941
        (*print-length* nil)
 
2942
        (*print-level* nil)
 
2943
        (*print-pretty* nil)
 
2944
        (*print-radix* nil)
 
2945
        (*read-base* 10)
 
2946
        (*read-default-float-format* 'single-float)
 
2947
        (*read-suppress* nil)
 
2948
        #+ticl (ticl:*print-structure* t)
 
2949
        #+lucid (lucid::*print-structure* t))
 
2950
    (funcall function)))
 
2951
 
 
2952
#-(or clx-ansi-common-lisp Genera CMU sbcl)
 
2953
(defmacro with-standard-io-syntax (&body body)
 
2954
  `(flet ((.with-standard-io-syntax-body. () ,@body))
 
2955
     (with-standard-io-syntax-function #'.with-standard-io-syntax-body.)))
 
2956
 
 
2957
 
 
2958
;;-----------------------------------------------------------------------------
 
2959
;; DEFAULT-KEYSYM-TRANSLATE
 
2960
;;-----------------------------------------------------------------------------
 
2961
 
 
2962
;;; If object is a character, char-bits are set from state.
 
2963
;;;
 
2964
;;; [the following isn't implemented (should it be?)]
 
2965
;;; If object is a list, it is an alist with entries:
 
2966
;;; (base-char [modifiers] [mask-modifiers])
 
2967
;;; When MODIFIERS are specified, this character translation
 
2968
;;; will only take effect when the specified modifiers are pressed.
 
2969
;;; MASK-MODIFIERS can be used to specify a set of modifiers to ignore.
 
2970
;;; When MASK-MODIFIERS is missing, all other modifiers are ignored.
 
2971
;;; In ambiguous cases, the most specific translation is used.
 
2972
 
 
2973
#-(or (and clx-ansi-common-lisp (not lispm) (not allegro)) CMU sbcl)
 
2974
(defun default-keysym-translate (display state object)
 
2975
  (declare (type display display)
 
2976
           (type card16 state)
 
2977
           (type t object)
 
2978
           (clx-values t)
 
2979
           (special left-meta-keysym right-meta-keysym
 
2980
                    left-super-keysym right-super-keysym
 
2981
                    left-hyper-keysym right-hyper-keysym))
 
2982
  (when (characterp object)
 
2983
    (when (logbitp (position :control +state-mask-vector+) state)
 
2984
      (setf (char-bit object :control) 1))
 
2985
    (when (or (state-keysymp display state left-meta-keysym)
 
2986
              (state-keysymp display state right-meta-keysym))
 
2987
      (setf (char-bit object :meta) 1))
 
2988
    (when (or (state-keysymp display state left-super-keysym)
 
2989
              (state-keysymp display state right-super-keysym))
 
2990
      (setf (char-bit object :super) 1))
 
2991
    (when (or (state-keysymp display state left-hyper-keysym)
 
2992
              (state-keysymp display state right-hyper-keysym))
 
2993
      (setf (char-bit object :hyper) 1)))
 
2994
  object)
 
2995
 
 
2996
#+(or (and clx-ansi-common-lisp (not lispm) (not allegro)) CMU sbcl)
 
2997
(defun default-keysym-translate (display state object)
 
2998
  (declare (type display display)
 
2999
           (type card16 state)
 
3000
           (type t object)
 
3001
           (ignore display state)
 
3002
           (clx-values t))
 
3003
  object)
 
3004
 
 
3005
 
 
3006
;;-----------------------------------------------------------------------------
 
3007
;; Image stuff
 
3008
;;-----------------------------------------------------------------------------
 
3009
 
 
3010
;;; Types
 
3011
 
 
3012
(deftype pixarray-1-element-type ()
 
3013
  'bit)
 
3014
 
 
3015
(deftype pixarray-4-element-type ()
 
3016
  '(unsigned-byte 4))
 
3017
 
 
3018
(deftype pixarray-8-element-type ()
 
3019
  '(unsigned-byte 8))
 
3020
 
 
3021
(deftype pixarray-16-element-type ()
 
3022
  '(unsigned-byte 16))
 
3023
 
 
3024
(deftype pixarray-24-element-type ()
 
3025
  '(unsigned-byte 24))
 
3026
 
 
3027
(deftype pixarray-32-element-type ()
 
3028
  #-(or Genera Minima) '(unsigned-byte 32)
 
3029
  #+(or Genera Minima) 'fixnum)
 
3030
 
 
3031
(deftype pixarray-1  ()
 
3032
  '(#+(or cmu sbcl) simple-array
 
3033
    #-(or cmu sbcl) array pixarray-1-element-type (* *)))
 
3034
 
 
3035
(deftype pixarray-4  ()
 
3036
  '(#+(or cmu sbcl) simple-array
 
3037
    #-(or cmu sbcl) array pixarray-4-element-type (* *)))
 
3038
 
 
3039
(deftype pixarray-8  ()
 
3040
  '(#+(or cmu sbcl) simple-array
 
3041
    #-(or cmu sbcl) array pixarray-8-element-type (* *)))
 
3042
 
 
3043
(deftype pixarray-16 ()
 
3044
  '(#+(or cmu sbcl) simple-array
 
3045
    #-(or cmu sbcl) array pixarray-16-element-type (* *)))
 
3046
 
 
3047
(deftype pixarray-24 ()
 
3048
  '(#+(or cmu sbcl) simple-array
 
3049
    #-(or cmu sbcl) array pixarray-24-element-type (* *)))
 
3050
 
 
3051
(deftype pixarray-32 ()
 
3052
  '(#+(or cmu sbcl) simple-array #-(or cmu sbcl) array pixarray-32-element-type (* *)))
 
3053
 
 
3054
(deftype pixarray ()
 
3055
  '(or pixarray-1 pixarray-4 pixarray-8 pixarray-16 pixarray-24 pixarray-32))
 
3056
 
 
3057
(deftype bitmap ()
 
3058
  'pixarray-1)
 
3059
 
 
3060
;;; WITH-UNDERLYING-SIMPLE-VECTOR 
 
3061
 
 
3062
#+Genera
 
3063
(defmacro with-underlying-simple-vector
 
3064
          ((variable element-type pixarray) &body body)
 
3065
  (let ((bits-per-element
 
3066
          (sys:array-bits-per-element
 
3067
            (symbol-value (sys:type-array-element-type element-type)))))
 
3068
    `(scl:stack-let ((,variable
 
3069
                      (make-array
 
3070
                        (index-ceiling
 
3071
                          (index* (array-total-size ,pixarray)
 
3072
                                  (sys:array-element-size ,pixarray))
 
3073
                          ,bits-per-element)
 
3074
                        :element-type ',element-type
 
3075
                        :displaced-to ,pixarray)))
 
3076
       (declare (type (vector ,element-type) ,variable))
 
3077
       ,@body)))
 
3078
 
 
3079
#+lcl3.0
 
3080
(defmacro with-underlying-simple-vector
 
3081
          ((variable element-type pixarray) &body body)
 
3082
  `(let ((,variable (sys:underlying-simple-vector ,pixarray)))
 
3083
     (declare (type (simple-array ,element-type (*)) ,variable))
 
3084
     ,@body))
 
3085
 
 
3086
#+excl
 
3087
(defmacro with-underlying-simple-vector
 
3088
          ((variable element-type pixarray) &body body)
 
3089
  `(let ((,variable (cdr (excl::ah_data ,pixarray))))
 
3090
     (declare (type (simple-array ,element-type (*)) ,variable))
 
3091
     ,@body))
 
3092
 
 
3093
#+(or CMU sbcl)
 
3094
;;; We do *NOT* support viewing an array as having a different element type.
 
3095
;;; Element-type is ignored.
 
3096
;;;
 
3097
(defmacro with-underlying-simple-vector 
 
3098
    ((variable element-type pixarray) &body body)
 
3099
  (declare (ignore element-type))
 
3100
  `(#+cmu kernel::with-array-data #+sbcl sb-kernel:with-array-data
 
3101
    ((,variable ,pixarray) (start) (end))
 
3102
    (declare (ignore start end))
 
3103
    ,@body))
 
3104
 
 
3105
;;; These are used to read and write pixels from and to CARD8s.
 
3106
 
 
3107
;;; READ-IMAGE-LOAD-BYTE is used to extract 1 and 4 bit pixels from CARD8s.
 
3108
 
 
3109
(defmacro read-image-load-byte (size position integer)
 
3110
  (unless +image-bit-lsb-first-p+ (setq position (- 7 position)))
 
3111
  `(the (unsigned-byte ,size)
 
3112
        (#-Genera ldb #+Genera sys:%logldb
 
3113
         (byte ,size ,position)
 
3114
         (the card8 ,integer))))
 
3115
 
 
3116
;;; READ-IMAGE-ASSEMBLE-BYTES is used to build 16, 24 and 32 bit pixels from
 
3117
;;; the appropriate number of CARD8s.
 
3118
 
 
3119
(defmacro read-image-assemble-bytes (&rest bytes)
 
3120
  (unless +image-byte-lsb-first-p+ (setq bytes (reverse bytes)))
 
3121
  (let ((it (first bytes))
 
3122
        (count 0))
 
3123
    (dolist (byte (rest bytes))
 
3124
      (setq it
 
3125
            `(#-Genera dpb #+Genera sys:%logdpb 
 
3126
              (the card8 ,byte)
 
3127
              (byte 8 ,(incf count 8))
 
3128
              (the (unsigned-byte ,count) ,it))))
 
3129
    #-Genera `(the (unsigned-byte ,(* (length bytes) 8)) ,it)
 
3130
    #+Genera it))
 
3131
 
 
3132
;;; WRITE-IMAGE-LOAD-BYTE is used to extract a CARD8 from a 16, 24 or 32 bit
 
3133
;;; pixel.
 
3134
 
 
3135
(defmacro write-image-load-byte (position integer integer-size)
 
3136
  integer-size
 
3137
  (unless +image-byte-lsb-first-p+ (setq position (- integer-size 8 position)))
 
3138
  `(the card8
 
3139
        (#-Genera ldb #+Genera sys:%logldb
 
3140
         (byte 8 ,position)
 
3141
         #-Genera (the (unsigned-byte ,integer-size) ,integer)
 
3142
         #+Genera ,integer
 
3143
         )))
 
3144
 
 
3145
;;; WRITE-IMAGE-ASSEMBLE-BYTES is used to build a CARD8 from 1 or 4 bit
 
3146
;;; pixels.
 
3147
 
 
3148
(defmacro write-image-assemble-bytes (&rest bytes)
 
3149
  (unless +image-bit-lsb-first-p+ (setq bytes (reverse bytes)))
 
3150
  (let ((size (floor 8 (length bytes)))
 
3151
        (it (first bytes))
 
3152
        (count 0))
 
3153
    (dolist (byte (rest bytes))
 
3154
      (setq it `(#-Genera dpb #+Genera sys:%logdpb
 
3155
                 (the (unsigned-byte ,size) ,byte)
 
3156
                 (byte ,size ,(incf count size))
 
3157
                 (the (unsigned-byte ,count) ,it))))
 
3158
    `(the card8 ,it)))
 
3159
 
 
3160
#+(or Genera lcl3.0 excl)
 
3161
(defvar *computed-image-byte-lsb-first-p* +image-byte-lsb-first-p+)
 
3162
 
 
3163
#+(or Genera lcl3.0 excl)
 
3164
(defvar *computed-image-bit-lsb-first-p* +image-bit-lsb-first-p+)
 
3165
 
 
3166
;;; The following table gives the bit ordering within bytes (when accessed
 
3167
;;; sequentially) for a scanline containing 32 bits, with bits numbered 0 to
 
3168
;;; 31, where bit 0 should be leftmost on the display.  For a given byte
 
3169
;;; labelled A-B, A is for the most significant bit of the byte, and B is
 
3170
;;; for the least significant bit.
 
3171
;;; 
 
3172
;;; legend:
 
3173
;;;     1   scanline-unit = 8
 
3174
;;;     2   scanline-unit = 16
 
3175
;;;     4   scanline-unit = 32
 
3176
;;;     M   byte-order = MostSignificant
 
3177
;;;     L   byte-order = LeastSignificant
 
3178
;;;     m   bit-order = MostSignificant
 
3179
;;;     l   bit-order = LeastSignificant
 
3180
;;; 
 
3181
;;; 
 
3182
;;; format      ordering
 
3183
;;; 
 
3184
;;; 1Mm 00-07 08-15 16-23 24-31
 
3185
;;; 2Mm 00-07 08-15 16-23 24-31
 
3186
;;; 4Mm 00-07 08-15 16-23 24-31
 
3187
;;; 1Ml 07-00 15-08 23-16 31-24
 
3188
;;; 2Ml 15-08 07-00 31-24 23-16
 
3189
;;; 4Ml 31-24 23-16 15-08 07-00
 
3190
;;; 1Lm 00-07 08-15 16-23 24-31
 
3191
;;; 2Lm 08-15 00-07 24-31 16-23
 
3192
;;; 4Lm 24-31 16-23 08-15 00-07
 
3193
;;; 1Ll 07-00 15-08 23-16 31-24
 
3194
;;; 2Ll 07-00 15-08 23-16 31-24
 
3195
;;; 4Ll 07-00 15-08 23-16 31-24
 
3196
 
 
3197
#+(or Genera lcl3.0 excl) 
 
3198
(defconstant
 
3199
  *image-bit-ordering-table*
 
3200
  '(((1 (00 07) (08 15) (16 23) (24 31)) (nil nil))
 
3201
    ((2 (00 07) (08 15) (16 23) (24 31)) (nil nil))
 
3202
    ((4 (00 07) (08 15) (16 23) (24 31)) (nil nil))
 
3203
    ((1 (07 00) (15 08) (23 16) (31 24)) (nil t))
 
3204
    ((2 (15 08) (07 00) (31 24) (23 16)) (nil t))
 
3205
    ((4 (31 24) (23 16) (15 08) (07 00)) (nil t))
 
3206
    ((1 (00 07) (08 15) (16 23) (24 31)) (t   nil))
 
3207
    ((2 (08 15) (00 07) (24 31) (16 23)) (t   nil))
 
3208
    ((4 (24 31) (16 23) (08 15) (00 07)) (t   nil))
 
3209
    ((1 (07 00) (15 08) (23 16) (31 24)) (t   t))
 
3210
    ((2 (07 00) (15 08) (23 16) (31 24)) (t   t))
 
3211
    ((4 (07 00) (15 08) (23 16) (31 24)) (t   t))))
 
3212
  
 
3213
#+(or Genera lcl3.0 excl) 
 
3214
(defun compute-image-byte-and-bit-ordering ()
 
3215
  (declare (clx-values image-byte-lsb-first-p image-bit-lsb-first-p))
 
3216
  ;; First compute the ordering 
 
3217
  (let ((ordering nil)
 
3218
        (a (make-array '(1 32) :element-type 'bit :initial-element 0)))
 
3219
    (dotimes (i 4)
 
3220
      (push (flet ((bitpos (a i n)
 
3221
                     (declare (optimize (speed 3) (safety 0) (space 0)))
 
3222
                     (declare (type (simple-array bit (* *)) a)
 
3223
                              (type fixnum i n))
 
3224
                     (with-underlying-simple-vector (v (unsigned-byte 8) a)
 
3225
                       (prog2
 
3226
                         (setf (aref v i) n)
 
3227
                         (dotimes (i 32)
 
3228
                           (unless (zerop (aref a 0 i))
 
3229
                             (return i)))
 
3230
                         (setf (aref v i) 0)))))
 
3231
              (list (bitpos a i #b10000000)
 
3232
                    (bitpos a i #b00000001)))
 
3233
            ordering))
 
3234
    (setq ordering (cons (floor +image-unit+ 8) (nreverse ordering)))
 
3235
    ;; Now from the ordering, compute byte-lsb-first-p and bit-lsb-first-p
 
3236
    (let ((byte-and-bit-ordering
 
3237
            (second (assoc ordering *image-bit-ordering-table*
 
3238
                           :test #'equal))))
 
3239
      (unless byte-and-bit-ordering
 
3240
        (error "Couldn't determine image byte and bit ordering~@
 
3241
                measured image ordering = ~A"
 
3242
               ordering))
 
3243
      (values-list byte-and-bit-ordering))))
 
3244
 
 
3245
#+(or Genera lcl3.0 excl) 
 
3246
(multiple-value-setq
 
3247
  (*computed-image-byte-lsb-first-p* *computed-image-bit-lsb-first-p*)
 
3248
  (compute-image-byte-and-bit-ordering))
 
3249
 
 
3250
;;; If you can write fast routines that can read and write pixarrays out of a
 
3251
;;; buffer-bytes, do it!  It makes the image code a lot faster.  The
 
3252
;;; FAST-READ-PIXARRAY, FAST-WRITE-PIXARRAY and FAST-COPY-PIXARRAY routines
 
3253
;;; return T if they can do it, NIL if they can't.
 
3254
 
 
3255
;;; FIXME: though we have some #+sbcl -conditionalized routines in
 
3256
;;; here, they would appear not to work, and so are commented out in
 
3257
;;; the the FAST-xxx-PIXARRAY routines themseleves.  Investigate
 
3258
;;; whether the unoptimized routines are often used, and also whether
 
3259
;;; speeding them up while maintaining correctness is possible.
 
3260
 
 
3261
;;; FAST-READ-PIXARRAY - fill part of a pixarray from a buffer of card8s
 
3262
 
 
3263
#+(or lcl3.0 excl)
 
3264
(defun fast-read-pixarray-1 (buffer-bbuf index array x y width height  
 
3265
                             padded-bytes-per-line bits-per-pixel)
 
3266
  (declare (type buffer-bytes buffer-bbuf)
 
3267
           (type pixarray-1 array)
 
3268
           (type card16 x y width height)
 
3269
           (type array-index index padded-bytes-per-line)
 
3270
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3271
           (ignore bits-per-pixel))
 
3272
  #.(declare-buffun)
 
3273
  (with-vector (buffer-bbuf buffer-bytes)
 
3274
    (with-underlying-simple-vector (vector pixarray-1-element-type array)
 
3275
      (do* ((start (index+ index
 
3276
                           (index* y padded-bytes-per-line)
 
3277
                           (index-ceiling x 8))
 
3278
                   (index+ start padded-bytes-per-line))
 
3279
            (y 0 (index1+ y))
 
3280
            (left-bits (the array-index (mod (the fixnum (- x)) 8)))
 
3281
            (right-bits (index-mod (index- width left-bits) 8))
 
3282
            (middle-bits (the fixnum (- (the fixnum (- width left-bits))
 
3283
                                        right-bits)))
 
3284
            (middle-bytes (index-floor middle-bits 8)))
 
3285
           ((index>= y height))
 
3286
        (declare (type array-index start y
 
3287
                       left-bits right-bits middle-bytes)
 
3288
                 (fixnum middle-bits))
 
3289
        (cond ((< middle-bits 0)
 
3290
               (let ((byte (aref buffer-bbuf (index1- start)))
 
3291
                     (x (array-row-major-index array y left-bits)))
 
3292
                 (declare (type card8 byte)
 
3293
                          (type array-index x))
 
3294
                 (when (index> right-bits 6)
 
3295
                   (setf (aref vector (index- x 1))
 
3296
                         (read-image-load-byte 1 7 byte)))
 
3297
                 (when (and (index> left-bits 1)
 
3298
                            (index> right-bits 5))
 
3299
                   (setf (aref vector (index- x 2))
 
3300
                         (read-image-load-byte 1 6 byte)))
 
3301
                 (when (and (index> left-bits 2)
 
3302
                            (index> right-bits 4))
 
3303
                   (setf (aref vector (index- x 3))
 
3304
                         (read-image-load-byte 1 5 byte)))
 
3305
                 (when (and (index> left-bits 3)
 
3306
                            (index> right-bits 3))
 
3307
                   (setf (aref vector (index- x 4))
 
3308
                         (read-image-load-byte 1 4 byte)))
 
3309
                 (when (and (index> left-bits 4)
 
3310
                            (index> right-bits 2))
 
3311
                   (setf (aref vector (index- x 5))
 
3312
                         (read-image-load-byte 1 3 byte)))
 
3313
                 (when (and (index> left-bits 5)
 
3314
                            (index> right-bits 1))
 
3315
                   (setf (aref vector (index- x 6))
 
3316
                         (read-image-load-byte 1 2 byte)))
 
3317
                 (when (index> left-bits 6)
 
3318
                   (setf (aref vector (index- x 7))
 
3319
                         (read-image-load-byte 1 1 byte)))))
 
3320
              (t
 
3321
               (unless (index-zerop left-bits)
 
3322
                 (let ((byte (aref buffer-bbuf (index1- start)))
 
3323
                       (x (array-row-major-index array y left-bits)))
 
3324
                   (declare (type card8 byte)
 
3325
                            (type array-index x))
 
3326
                   (setf (aref vector (index- x 1))
 
3327
                         (read-image-load-byte 1 7 byte))
 
3328
                   (when (index> left-bits 1)
 
3329
                     (setf (aref vector (index- x 2))
 
3330
                           (read-image-load-byte 1 6 byte))
 
3331
                     (when (index> left-bits 2)
 
3332
                       (setf (aref vector (index- x 3))
 
3333
                             (read-image-load-byte 1 5 byte))
 
3334
                       (when (index> left-bits 3)
 
3335
                         (setf (aref vector (index- x 4))
 
3336
                               (read-image-load-byte 1 4 byte))
 
3337
                         (when (index> left-bits 4)
 
3338
                           (setf (aref vector (index- x 5))
 
3339
                                 (read-image-load-byte 1 3 byte))
 
3340
                           (when (index> left-bits 5)
 
3341
                             (setf (aref vector (index- x 6))
 
3342
                                   (read-image-load-byte 1 2 byte))
 
3343
                             (when (index> left-bits 6)
 
3344
                               (setf (aref vector (index- x 7))
 
3345
                                     (read-image-load-byte 1 1 byte))
 
3346
                               ))))))))
 
3347
               (do* ((end (index+ start middle-bytes))
 
3348
                     (i start (index1+ i))
 
3349
                     (x (array-row-major-index array y left-bits) (index+ x 8)))
 
3350
                    ((index>= i end)
 
3351
                     (unless (index-zerop right-bits)
 
3352
                       (let ((byte (aref buffer-bbuf end))
 
3353
                             (x (array-row-major-index
 
3354
                                 array y (index+ left-bits middle-bits))))
 
3355
                         (declare (type card8 byte)
 
3356
                                  (type array-index x))
 
3357
                         (setf (aref vector (index+ x 0))
 
3358
                               (read-image-load-byte 1 0 byte))
 
3359
                         (when (index> right-bits 1)
 
3360
                           (setf (aref vector (index+ x 1))
 
3361
                                 (read-image-load-byte 1 1 byte))
 
3362
                           (when (index> right-bits 2)
 
3363
                             (setf (aref vector (index+ x 2))
 
3364
                                   (read-image-load-byte 1 2 byte))
 
3365
                             (when (index> right-bits 3)
 
3366
                               (setf (aref vector (index+ x 3))
 
3367
                                     (read-image-load-byte 1 3 byte))
 
3368
                               (when (index> right-bits 4)
 
3369
                                 (setf (aref vector (index+ x 4))
 
3370
                                       (read-image-load-byte 1 4 byte))
 
3371
                                 (when (index> right-bits 5)
 
3372
                                   (setf (aref vector (index+ x 5))
 
3373
                                         (read-image-load-byte 1 5 byte))
 
3374
                                   (when (index> right-bits 6)
 
3375
                                     (setf (aref vector (index+ x 6))
 
3376
                                           (read-image-load-byte 1 6 byte))
 
3377
                                     )))))))))
 
3378
                 (declare (type array-index end i x))
 
3379
                 (let ((byte (aref buffer-bbuf i)))
 
3380
                   (declare (type card8 byte))
 
3381
                   (setf (aref vector (index+ x 0))
 
3382
                         (read-image-load-byte 1 0 byte))
 
3383
                   (setf (aref vector (index+ x 1))
 
3384
                         (read-image-load-byte 1 1 byte))
 
3385
                   (setf (aref vector (index+ x 2))
 
3386
                         (read-image-load-byte 1 2 byte))
 
3387
                   (setf (aref vector (index+ x 3))
 
3388
                         (read-image-load-byte 1 3 byte))
 
3389
                   (setf (aref vector (index+ x 4))
 
3390
                         (read-image-load-byte 1 4 byte))
 
3391
                   (setf (aref vector (index+ x 5))
 
3392
                         (read-image-load-byte 1 5 byte))
 
3393
                   (setf (aref vector (index+ x 6))
 
3394
                         (read-image-load-byte 1 6 byte))
 
3395
                   (setf (aref vector (index+ x 7))
 
3396
                         (read-image-load-byte 1 7 byte))))
 
3397
               )))))
 
3398
    t)
 
3399
 
 
3400
#+(or lcl3.0 excl)
 
3401
(defun fast-read-pixarray-4 (buffer-bbuf index array x y width height 
 
3402
                             padded-bytes-per-line bits-per-pixel)
 
3403
  (declare (type buffer-bytes buffer-bbuf)
 
3404
           (type pixarray-4 array)
 
3405
           (type card16 x y width height)
 
3406
           (type array-index index padded-bytes-per-line)
 
3407
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3408
           (ignore bits-per-pixel))
 
3409
  #.(declare-buffun)
 
3410
  (with-vector (buffer-bbuf buffer-bytes)
 
3411
    (with-underlying-simple-vector (vector pixarray-4-element-type array)
 
3412
      (do* ((start (index+ index
 
3413
                           (index* y padded-bytes-per-line)
 
3414
                           (index-ceiling x 2))
 
3415
                   (index+ start padded-bytes-per-line))
 
3416
            (y 0 (index1+ y))
 
3417
            (left-nibbles (the array-index (mod (the fixnum (- (the fixnum x)))
 
3418
                                                2)))
 
3419
            (right-nibbles (index-mod (index- width left-nibbles) 2))
 
3420
            (middle-nibbles (index- width left-nibbles right-nibbles))
 
3421
            (middle-bytes (index-floor middle-nibbles 2)))
 
3422
           ((index>= y height))
 
3423
        (declare (type array-index start y
 
3424
                       left-nibbles right-nibbles middle-nibbles middle-bytes))
 
3425
        (unless (index-zerop left-nibbles)
 
3426
          (setf (aref array y 0)
 
3427
                (read-image-load-byte
 
3428
                  4 4 (aref buffer-bbuf (index1- start)))))
 
3429
        (do* ((end (index+ start middle-bytes))
 
3430
              (i start (index1+ i))
 
3431
              (x (array-row-major-index array y left-nibbles) (index+ x 2)))
 
3432
             ((index>= i end)
 
3433
              (unless (index-zerop right-nibbles)
 
3434
                (setf (aref array y (index+ left-nibbles middle-nibbles))
 
3435
                      (read-image-load-byte 4 0 (aref buffer-bbuf end)))))
 
3436
          (declare (type array-index end i x))
 
3437
          (let ((byte (aref buffer-bbuf i)))
 
3438
            (declare (type card8 byte))
 
3439
            (setf (aref vector (index+ x 0))
 
3440
                  (read-image-load-byte 4 0 byte))
 
3441
            (setf (aref vector (index+ x 1))
 
3442
                  (read-image-load-byte 4 4 byte))))
 
3443
        )))
 
3444
  t)
 
3445
 
 
3446
#+(or Genera lcl3.0 excl CMU sbcl)
 
3447
(defun fast-read-pixarray-24 (buffer-bbuf index array x y width height 
 
3448
                              padded-bytes-per-line bits-per-pixel)
 
3449
  (declare (type buffer-bytes buffer-bbuf)
 
3450
           (type pixarray-24 array)
 
3451
           (type card16 width height)
 
3452
           (type array-index index padded-bytes-per-line)
 
3453
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3454
           (ignore bits-per-pixel))
 
3455
  #.(declare-buffun)
 
3456
  (with-vector (buffer-bbuf buffer-bytes)
 
3457
    (with-underlying-simple-vector (vector pixarray-24-element-type array)
 
3458
      (do* ((start (index+ index
 
3459
                           (index* y padded-bytes-per-line)
 
3460
                           (index* x 3))
 
3461
                   (index+ start padded-bytes-per-line))
 
3462
            (y 0 (index1+ y)))
 
3463
           ((index>= y height))
 
3464
        (declare (type array-index start y))
 
3465
        (do* ((end (index+ start (index* width 3)))
 
3466
              (i start (index+ i 3))
 
3467
              (x (array-row-major-index array y 0) (index1+ x)))
 
3468
             ((index>= i end))
 
3469
          (declare (type array-index end i x))
 
3470
          (setf (aref vector x)
 
3471
                (read-image-assemble-bytes
 
3472
                  (aref buffer-bbuf (index+ i 0))
 
3473
                  (aref buffer-bbuf (index+ i 1))
 
3474
                  (aref buffer-bbuf (index+ i 2))))))))
 
3475
  t)
 
3476
 
 
3477
#+lispm
 
3478
(defun fast-read-pixarray-using-bitblt
 
3479
       (bbuf boffset pixarray x y width height padded-bytes-per-line
 
3480
        bits-per-pixel)
 
3481
  (#+Genera sys:stack-let* #-Genera let*
 
3482
   ((dimensions (list (+ y height)
 
3483
                      (floor (* padded-bytes-per-line 8) bits-per-pixel)))
 
3484
    (a (make-array
 
3485
         dimensions
 
3486
         :element-type (array-element-type pixarray)
 
3487
         :displaced-to bbuf
 
3488
         :displaced-index-offset (floor (* boffset 8) bits-per-pixel))))
 
3489
   (sys:bitblt boole-1 width height a x y pixarray 0 0))
 
3490
  t)
 
3491
 
 
3492
#+(or CMU sbcl)
 
3493
(defun pixarray-element-size (pixarray)
 
3494
  (let ((eltype (array-element-type pixarray)))
 
3495
    (cond ((eq eltype 'bit) 1)
 
3496
          ((and (consp eltype) (eq (first eltype) 'unsigned-byte))
 
3497
           (second eltype))
 
3498
          (t
 
3499
           (error "Invalid pixarray: ~S." pixarray)))))
 
3500
 
 
3501
#+CMU
 
3502
;;; COPY-BIT-RECT  --  Internal
 
3503
;;;
 
3504
;;;    This is the classic BITBLT operation, copying a rectangular subarray
 
3505
;;; from one array to another (but source and destination must not overlap.)
 
3506
;;; Widths are specified in bits.  Neither array can have a non-zero
 
3507
;;; displacement.  We allow extra random bit-offset to be thrown into the X.
 
3508
;;;
 
3509
(defun copy-bit-rect (source source-width sx sy dest dest-width dx dy
 
3510
                             height width)
 
3511
  (declare (type array-index source-width sx sy dest-width dx dy height width))
 
3512
  #.(declare-buffun)
 
3513
  (kernel::with-array-data ((sdata source)
 
3514
                                 (sstart)
 
3515
                                 (send))
 
3516
    (declare (ignore send))
 
3517
    (kernel::with-array-data ((ddata dest)
 
3518
                                   (dstart)
 
3519
                                   (dend))
 
3520
      (declare (ignore dend))
 
3521
      (assert (and (zerop sstart) (zerop dstart)))
 
3522
      (do ((src-idx (index+ (* vm:vector-data-offset #+cmu vm:word-bits #+sbcl sb-vm:n-word-bits)
 
3523
                            sx (index* sy source-width))
 
3524
                    (index+ src-idx source-width))
 
3525
           (dest-idx (index+ (* vm:vector-data-offset #+cmu vm:word-bits #+sbcl sb-vm:n-word-bits)
 
3526
                             dx (index* dy dest-width))
 
3527
                     (index+ dest-idx dest-width))
 
3528
           (count height (1- count)))
 
3529
          ((zerop count))
 
3530
        (declare (type array-index src-idx dest-idx count))
 
3531
        (kernel:bit-bash-copy sdata src-idx ddata dest-idx width)))))
 
3532
 
 
3533
 
 
3534
#+sbcl
 
3535
(defun copy-bit-rect (source source-width sx sy dest dest-width dx dy
 
3536
                             height width)
 
3537
  (declare (type array-index source-width sx sy dest-width dx dy height width))
 
3538
  #.(declare-buffun)
 
3539
  (sb-kernel:with-array-data ((sdata source) (sstart) (send))
 
3540
    (declare (ignore send))
 
3541
    (sb-kernel:with-array-data ((ddata dest) (dstart) (dend))
 
3542
      (declare (ignore dend))
 
3543
      (assert (and (zerop sstart) (zerop dstart)))
 
3544
      (do ((src-idx (index+ (* sb-vm:vector-data-offset sb-vm:n-word-bits)
 
3545
                            sx (index* sy source-width))
 
3546
                    (index+ src-idx source-width))
 
3547
           (dest-idx (index+ (* sb-vm:vector-data-offset sb-vm:n-word-bits)
 
3548
                             dx (index* dy dest-width))
 
3549
                     (index+ dest-idx dest-width))
 
3550
           (count height (1- count)))
 
3551
          ((zerop count))
 
3552
        (declare (type array-index src-idx dest-idx count))
 
3553
        (sb-kernel:bit-bash-copy sdata src-idx ddata dest-idx width)))))
 
3554
 
 
3555
#+(or CMU sbcl)
 
3556
(defun fast-read-pixarray-using-bitblt
 
3557
       (bbuf boffset pixarray x y width height padded-bytes-per-line
 
3558
        bits-per-pixel)
 
3559
  (declare (type (array * 2) pixarray))
 
3560
  #.(declare-buffun)
 
3561
  (copy-bit-rect bbuf
 
3562
                 (index* padded-bytes-per-line #+cmu vm:byte-bits #+sbcl sb-vm:n-byte-bits)
 
3563
                 (index* boffset #+cmu vm:byte-bits #+sbcl sb-vm:n-byte-bits) 0
 
3564
                 pixarray
 
3565
                 (index* (array-dimension pixarray 1) bits-per-pixel)
 
3566
                 x y
 
3567
                 height
 
3568
                 (index* width bits-per-pixel))
 
3569
  t)
 
3570
 
 
3571
#+(or Genera lcl3.0 excl)
 
3572
(defun fast-read-pixarray-with-swap
 
3573
       (bbuf boffset pixarray x y width height padded-bytes-per-line
 
3574
        bits-per-pixel unit byte-lsb-first-p bit-lsb-first-p)
 
3575
  (declare (type buffer-bytes bbuf)
 
3576
           (type array-index boffset
 
3577
                 padded-bytes-per-line)
 
3578
           (type pixarray pixarray)
 
3579
           (type card16 x y width height)
 
3580
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3581
           (type (member 8 16 32) unit)
 
3582
           (type generalized-boolean byte-lsb-first-p bit-lsb-first-p))
 
3583
  (unless (index= bits-per-pixel 24)
 
3584
    (let ((pixarray-padded-bits-per-line
 
3585
            (if (index= height 1) 0
 
3586
              (index* (index- (array-row-major-index pixarray 1 0)
 
3587
                              (array-row-major-index pixarray 0 0))
 
3588
                      bits-per-pixel)))
 
3589
          (x-bits (index* x bits-per-pixel)))
 
3590
      (declare (type array-index pixarray-padded-bits-per-line x-bits))
 
3591
      (when (if (eq *computed-image-byte-lsb-first-p* *computed-image-bit-lsb-first-p*)
 
3592
                (and (index-zerop (index-mod pixarray-padded-bits-per-line 8))
 
3593
                     (index-zerop (index-mod x-bits 8)))
 
3594
              (and (index-zerop (index-mod pixarray-padded-bits-per-line +image-unit+))
 
3595
                   (index-zerop (index-mod x-bits +image-unit+))))
 
3596
        (multiple-value-bind (image-swap-function image-swap-lsb-first-p)
 
3597
            (image-swap-function
 
3598
              bits-per-pixel 
 
3599
              unit byte-lsb-first-p bit-lsb-first-p
 
3600
              +image-unit+ *computed-image-byte-lsb-first-p*
 
3601
              *computed-image-bit-lsb-first-p*)
 
3602
          (declare (type symbol image-swap-function)
 
3603
                   (type generalized-boolean image-swap-lsb-first-p))
 
3604
          (with-underlying-simple-vector (dst card8 pixarray)
 
3605
            (funcall
 
3606
              (symbol-function image-swap-function) bbuf dst
 
3607
              (index+ boffset
 
3608
                      (index* y padded-bytes-per-line)
 
3609
                      (index-floor x-bits 8))
 
3610
              0 (index-ceiling (index* width bits-per-pixel) 8)
 
3611
              padded-bytes-per-line
 
3612
              (index-floor pixarray-padded-bits-per-line 8)
 
3613
              height image-swap-lsb-first-p)))
 
3614
        t))))
 
3615
 
 
3616
(defun fast-read-pixarray (bbuf boffset pixarray
 
3617
                           x y width height padded-bytes-per-line
 
3618
                           bits-per-pixel
 
3619
                           unit byte-lsb-first-p bit-lsb-first-p)
 
3620
  (declare (type buffer-bytes bbuf)
 
3621
           (type array-index boffset
 
3622
                 padded-bytes-per-line)
 
3623
           (type pixarray pixarray)
 
3624
           (type card16 x y width height)
 
3625
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3626
           (type (member 8 16 32) unit)
 
3627
           (type generalized-boolean byte-lsb-first-p bit-lsb-first-p))
 
3628
  (progn bbuf boffset pixarray x y width height padded-bytes-per-line
 
3629
         bits-per-pixel unit byte-lsb-first-p bit-lsb-first-p)
 
3630
  (or
 
3631
    #+(or Genera lcl3.0 excl)
 
3632
    (fast-read-pixarray-with-swap
 
3633
      bbuf boffset pixarray x y width height padded-bytes-per-line
 
3634
      bits-per-pixel unit byte-lsb-first-p bit-lsb-first-p)
 
3635
    (let ((function
 
3636
            (or #+lispm
 
3637
                (and (= (sys:array-element-size pixarray) bits-per-pixel)
 
3638
                     (zerop (index-mod padded-bytes-per-line 4))
 
3639
                     (zerop (index-mod
 
3640
                              (* #+Genera (sys:array-row-span pixarray)
 
3641
                                 #-Genera (array-dimension pixarray 1)
 
3642
                                 bits-per-pixel)
 
3643
                              32))
 
3644
                     #'fast-read-pixarray-using-bitblt)
 
3645
                #+(or CMU)
 
3646
                (and (index= (pixarray-element-size pixarray) bits-per-pixel)
 
3647
                     #'fast-read-pixarray-using-bitblt)
 
3648
                #+(or lcl3.0 excl)
 
3649
                (and (index= bits-per-pixel 1)
 
3650
                     #'fast-read-pixarray-1)
 
3651
                #+(or lcl3.0 excl)
 
3652
                (and (index= bits-per-pixel 4)
 
3653
                     #'fast-read-pixarray-4)
 
3654
                #+(or Genera lcl3.0 excl CMU)
 
3655
                (and (index= bits-per-pixel 24)
 
3656
                     #'fast-read-pixarray-24))))
 
3657
      (when function
 
3658
        (read-pixarray-internal
 
3659
          bbuf boffset pixarray x y width height padded-bytes-per-line
 
3660
          bits-per-pixel function
 
3661
          unit byte-lsb-first-p bit-lsb-first-p
 
3662
          +image-unit+ +image-byte-lsb-first-p+ +image-bit-lsb-first-p+)))))
 
3663
 
 
3664
;;; FAST-WRITE-PIXARRAY - copy part of a pixarray into an array of CARD8s
 
3665
 
 
3666
#+(or lcl3.0 excl)
 
3667
(defun fast-write-pixarray-1 (buffer-bbuf index array x y width height
 
3668
                              padded-bytes-per-line bits-per-pixel)
 
3669
  (declare (type buffer-bytes buffer-bbuf)
 
3670
           (type pixarray-1 array)
 
3671
           (type card16 x y width height)
 
3672
           (type array-index index padded-bytes-per-line)
 
3673
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3674
           (ignore bits-per-pixel))
 
3675
  #.(declare-buffun)
 
3676
  (with-vector (buffer-bbuf buffer-bytes)
 
3677
    (with-underlying-simple-vector (vector pixarray-1-element-type array)
 
3678
      (do* ((h 0 (index1+ h))
 
3679
            (y y (index1+ y))
 
3680
            (right-bits (index-mod width 8))
 
3681
            (middle-bits (index- width right-bits))
 
3682
            (middle-bytes (index-ceiling middle-bits 8))
 
3683
            (start index (index+ start padded-bytes-per-line)))
 
3684
           ((index>= h height))
 
3685
        (declare (type array-index h y right-bits middle-bits
 
3686
                       middle-bytes start))
 
3687
        (do* ((end (index+ start middle-bytes))
 
3688
              (i start (index1+ i))
 
3689
              (start-x x)
 
3690
              (x (array-row-major-index array y start-x) (index+ x 8)))
 
3691
             ((index>= i end)
 
3692
              (unless (index-zerop right-bits)
 
3693
                (let ((x (array-row-major-index
 
3694
                           array y (index+ start-x middle-bits))))
 
3695
                  (declare (type array-index x))
 
3696
                  (setf (aref buffer-bbuf end)
 
3697
                        (write-image-assemble-bytes
 
3698
                          (aref vector (index+ x 0))
 
3699
                          (if (index> right-bits 1)
 
3700
                              (aref vector (index+ x 1))
 
3701
                            0)
 
3702
                          (if (index> right-bits 2)
 
3703
                              (aref vector (index+ x 2))
 
3704
                            0)
 
3705
                          (if (index> right-bits 3)
 
3706
                              (aref vector (index+ x 3))
 
3707
                            0)
 
3708
                          (if (index> right-bits 4)
 
3709
                              (aref vector (index+ x 4))
 
3710
                            0)
 
3711
                          (if (index> right-bits 5)
 
3712
                              (aref vector (index+ x 5))
 
3713
                            0)
 
3714
                          (if (index> right-bits 6)
 
3715
                              (aref vector (index+ x 6))
 
3716
                            0)
 
3717
                          0)))))
 
3718
          (declare (type array-index end i start-x x))
 
3719
          (setf (aref buffer-bbuf i)
 
3720
                (write-image-assemble-bytes
 
3721
                  (aref vector (index+ x 0))
 
3722
                  (aref vector (index+ x 1))
 
3723
                  (aref vector (index+ x 2))
 
3724
                  (aref vector (index+ x 3))
 
3725
                  (aref vector (index+ x 4))
 
3726
                  (aref vector (index+ x 5))
 
3727
                  (aref vector (index+ x 6))
 
3728
                  (aref vector (index+ x 7))))))))
 
3729
  t)
 
3730
 
 
3731
#+(or lcl3.0 excl)
 
3732
(defun fast-write-pixarray-4 (buffer-bbuf index array x y width height
 
3733
                              padded-bytes-per-line bits-per-pixel)
 
3734
  (declare (type buffer-bytes buffer-bbuf)
 
3735
           (type pixarray-4 array)
 
3736
           (type int16 x y)
 
3737
           (type card16 width height)
 
3738
           (type array-index index padded-bytes-per-line)
 
3739
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3740
           (ignore bits-per-pixel))
 
3741
  #.(declare-buffun)
 
3742
  (with-vector (buffer-bbuf buffer-bytes)
 
3743
    (with-underlying-simple-vector (vector pixarray-4-element-type array)
 
3744
      (do* ((h 0 (index1+ h))
 
3745
            (y y (index1+ y))
 
3746
            (right-nibbles (index-mod width 2))
 
3747
            (middle-nibbles (index- width right-nibbles))
 
3748
            (middle-bytes (index-ceiling middle-nibbles 2))
 
3749
            (start index (index+ start padded-bytes-per-line)))
 
3750
           ((index>= h height))
 
3751
        (declare (type array-index h y right-nibbles middle-nibbles
 
3752
                       middle-bytes start))
 
3753
        (do* ((end (index+ start middle-bytes))
 
3754
              (i start (index1+ i))
 
3755
              (start-x x)
 
3756
              (x (array-row-major-index array y start-x) (index+ x 2)))
 
3757
             ((index>= i end)
 
3758
              (unless (index-zerop right-nibbles)
 
3759
                (setf (aref buffer-bbuf end)
 
3760
                      (write-image-assemble-bytes
 
3761
                        (aref array y (index+ start-x middle-nibbles))
 
3762
                        0))))
 
3763
          (declare (type array-index end i start-x x))
 
3764
          (setf (aref buffer-bbuf i)
 
3765
                (write-image-assemble-bytes
 
3766
                  (aref vector (index+ x 0))
 
3767
                  (aref vector (index+ x 1))))))))
 
3768
  t)
 
3769
 
 
3770
#+(or Genera lcl3.0 excl CMU sbcl)
 
3771
(defun fast-write-pixarray-24 (buffer-bbuf index array x y width height
 
3772
                               padded-bytes-per-line bits-per-pixel)
 
3773
  (declare (type buffer-bytes buffer-bbuf)
 
3774
           (type pixarray-24 array)
 
3775
           (type int16 x y)
 
3776
           (type card16 width height)
 
3777
           (type array-index index padded-bytes-per-line)
 
3778
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3779
           (ignore bits-per-pixel))
 
3780
  #.(declare-buffun)
 
3781
  (with-vector (buffer-bbuf buffer-bytes)
 
3782
    (with-underlying-simple-vector (vector pixarray-24-element-type array)
 
3783
      (do* ((h 0 (index1+ h))
 
3784
            (y y (index1+ y))
 
3785
            (start index (index+ start padded-bytes-per-line)))
 
3786
           ((index>= h height))
 
3787
        (declare (type array-index y start))
 
3788
        (do* ((end (index+ start (index* width 3)))
 
3789
              (i start (index+ i 3))
 
3790
              (x (array-row-major-index array y x) (index1+ x)))
 
3791
             ((index>= i end))
 
3792
          (declare (type array-index end i x))
 
3793
          (let ((pixel (aref vector x)))
 
3794
            (declare (type pixarray-24-element-type pixel))
 
3795
            (setf (aref buffer-bbuf (index+ i 0))
 
3796
                  (write-image-load-byte 0 pixel 24))
 
3797
            (setf (aref buffer-bbuf (index+ i 1))
 
3798
                  (write-image-load-byte 8 pixel 24))
 
3799
            (setf (aref buffer-bbuf (index+ i 2))
 
3800
                  (write-image-load-byte 16 pixel 24)))))))
 
3801
  t)
 
3802
 
 
3803
#+lispm
 
3804
(defun fast-write-pixarray-using-bitblt
 
3805
       (bbuf boffset pixarray x y width height padded-bytes-per-line
 
3806
        bits-per-pixel)
 
3807
  (#+Genera sys:stack-let* #-Genera let*
 
3808
   ((dimensions (list (+ y height)
 
3809
                      (floor (* padded-bytes-per-line 8) bits-per-pixel)))
 
3810
    (a (make-array
 
3811
         dimensions
 
3812
         :element-type (array-element-type pixarray)
 
3813
         :displaced-to bbuf
 
3814
         :displaced-index-offset (floor (* boffset 8) bits-per-pixel))))
 
3815
   (sys:bitblt boole-1 width height pixarray x y a 0 0))
 
3816
  t)
 
3817
 
 
3818
#+(or CMU sbcl)
 
3819
(defun fast-write-pixarray-using-bitblt
 
3820
       (bbuf boffset pixarray x y width height padded-bytes-per-line
 
3821
        bits-per-pixel)
 
3822
  #.(declare-buffun)
 
3823
  (copy-bit-rect pixarray
 
3824
                 (index* (array-dimension pixarray 1) bits-per-pixel)
 
3825
                 x y
 
3826
                 bbuf
 
3827
                 (index* padded-bytes-per-line #+cmu vm:byte-bits #+sbcl sb-vm:n-byte-bits)
 
3828
                 (index* boffset #+cmu vm:byte-bits #+sbcl sb-vm:n-byte-bits) 0
 
3829
                 height
 
3830
                 (index* width bits-per-pixel))
 
3831
  t)
 
3832
 
 
3833
#+(or Genera lcl3.0 excl)
 
3834
(defun fast-write-pixarray-with-swap
 
3835
       (bbuf boffset pixarray x y width height padded-bytes-per-line
 
3836
        bits-per-pixel unit byte-lsb-first-p bit-lsb-first-p)
 
3837
  (declare (type buffer-bytes bbuf)
 
3838
           (type pixarray pixarray)
 
3839
           (type card16 x y width height)
 
3840
           (type array-index boffset padded-bytes-per-line)
 
3841
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3842
           (type (member 8 16 32) unit)
 
3843
           (type generalized-boolean byte-lsb-first-p bit-lsb-first-p))
 
3844
  (unless (index= bits-per-pixel 24)
 
3845
    (let ((pixarray-padded-bits-per-line
 
3846
            (if (index= height 1) 0
 
3847
              (index* (index- (array-row-major-index pixarray 1 0)
 
3848
                              (array-row-major-index pixarray 0 0))
 
3849
                      bits-per-pixel)))
 
3850
          (pixarray-start-bit-offset
 
3851
            (index* (array-row-major-index pixarray y x)
 
3852
                    bits-per-pixel)))
 
3853
      (declare (type array-index pixarray-padded-bits-per-line
 
3854
                     pixarray-start-bit-offset))
 
3855
      (when (if (eq *computed-image-byte-lsb-first-p* *computed-image-bit-lsb-first-p*)
 
3856
                (and (index-zerop (index-mod pixarray-padded-bits-per-line 8))
 
3857
                     (index-zerop (index-mod pixarray-start-bit-offset 8)))
 
3858
              (and (index-zerop (index-mod pixarray-padded-bits-per-line +image-unit+))
 
3859
                   (index-zerop (index-mod pixarray-start-bit-offset +image-unit+))))
 
3860
        (multiple-value-bind (image-swap-function image-swap-lsb-first-p)
 
3861
            (image-swap-function
 
3862
              bits-per-pixel
 
3863
              +image-unit+ *computed-image-byte-lsb-first-p*
 
3864
              *computed-image-bit-lsb-first-p*
 
3865
              unit byte-lsb-first-p bit-lsb-first-p)
 
3866
          (declare (type symbol image-swap-function)
 
3867
                   (type generalized-boolean image-swap-lsb-first-p))
 
3868
          (with-underlying-simple-vector (src card8 pixarray)
 
3869
            (funcall
 
3870
              (symbol-function image-swap-function)
 
3871
              src bbuf (index-floor pixarray-start-bit-offset 8) boffset
 
3872
              (index-ceiling (index* width bits-per-pixel) 8)
 
3873
              (index-floor pixarray-padded-bits-per-line 8)
 
3874
              padded-bytes-per-line height image-swap-lsb-first-p))
 
3875
          t)))))
 
3876
 
 
3877
(defun fast-write-pixarray (bbuf boffset pixarray x y width height
 
3878
                            padded-bytes-per-line bits-per-pixel
 
3879
                            unit byte-lsb-first-p bit-lsb-first-p)
 
3880
  (declare (type buffer-bytes bbuf)
 
3881
           (type pixarray pixarray)
 
3882
           (type card16 x y width height)
 
3883
           (type array-index boffset padded-bytes-per-line)
 
3884
           (type (member 1 4 8 16 24 32) bits-per-pixel)
 
3885
           (type (member 8 16 32) unit)
 
3886
           (type generalized-boolean byte-lsb-first-p bit-lsb-first-p))
 
3887
  (progn bbuf boffset pixarray x y width height padded-bytes-per-line
 
3888
         bits-per-pixel unit byte-lsb-first-p bit-lsb-first-p)
 
3889
  (or
 
3890
    #+(or Genera lcl3.0 excl)
 
3891
    (fast-write-pixarray-with-swap
 
3892
      bbuf boffset pixarray x y width height padded-bytes-per-line
 
3893
      bits-per-pixel unit byte-lsb-first-p bit-lsb-first-p)
 
3894
    (let ((function
 
3895
            (or #+lispm
 
3896
                (and (= (sys:array-element-size pixarray) bits-per-pixel)
 
3897
                     (zerop (index-mod padded-bytes-per-line 4))
 
3898
                     (zerop (index-mod
 
3899
                              (* #+Genera (sys:array-row-span pixarray)
 
3900
                                 #-Genera (array-dimension pixarray 1)
 
3901
                                 bits-per-pixel)
 
3902
                              32))
 
3903
                     #'fast-write-pixarray-using-bitblt)
 
3904
                #+(or CMU)
 
3905
                (and (index= (pixarray-element-size pixarray) bits-per-pixel)
 
3906
                     #'fast-write-pixarray-using-bitblt)
 
3907
                #+(or lcl3.0 excl)
 
3908
                (and (index= bits-per-pixel 1)
 
3909
                     #'fast-write-pixarray-1)
 
3910
                #+(or lcl3.0 excl)
 
3911
                (and (index= bits-per-pixel 4)
 
3912
                     #'fast-write-pixarray-4)
 
3913
                #+(or Genera lcl3.0 excl CMU)
 
3914
                (and (index= bits-per-pixel 24)
 
3915
                     #'fast-write-pixarray-24))))
 
3916
      (when function
 
3917
        (write-pixarray-internal
 
3918
          bbuf boffset pixarray x y width height padded-bytes-per-line
 
3919
          bits-per-pixel function
 
3920
          +image-unit+ +image-byte-lsb-first-p+ +image-bit-lsb-first-p+
 
3921
          unit byte-lsb-first-p bit-lsb-first-p)))))
 
3922
 
 
3923
;;; FAST-COPY-PIXARRAY - copy part of a pixarray into another
 
3924
 
 
3925
(defun fast-copy-pixarray (pixarray copy x y width height bits-per-pixel)
 
3926
  (declare (type pixarray pixarray copy)
 
3927
           (type card16 x y width height)
 
3928
           (type (member 1 4 8 16 24 32) bits-per-pixel))
 
3929
  (progn pixarray copy x y width height bits-per-pixel nil)
 
3930
  (or
 
3931
    #+(or lispm CMU)
 
3932
    (let* ((pixarray-padded-pixels-per-line
 
3933
             #+Genera (sys:array-row-span pixarray)
 
3934
             #-Genera (array-dimension pixarray 1))
 
3935
           (pixarray-padded-bits-per-line
 
3936
             (* pixarray-padded-pixels-per-line bits-per-pixel))
 
3937
           (copy-padded-pixels-per-line
 
3938
             #+Genera (sys:array-row-span copy)
 
3939
             #-Genera (array-dimension copy 1))
 
3940
           (copy-padded-bits-per-line
 
3941
             (* copy-padded-pixels-per-line bits-per-pixel)))
 
3942
      #-(or CMU)
 
3943
      (when (and (= (sys:array-element-size pixarray) bits-per-pixel)
 
3944
                 (zerop (index-mod pixarray-padded-bits-per-line 32))
 
3945
                 (zerop (index-mod copy-padded-bits-per-line 32)))
 
3946
        (sys:bitblt boole-1 width height pixarray x y copy 0 0)
 
3947
        t)
 
3948
      #+(or CMU)
 
3949
      (when (index= (pixarray-element-size pixarray)
 
3950
                    (pixarray-element-size copy)
 
3951
                    bits-per-pixel)
 
3952
        (copy-bit-rect pixarray pixarray-padded-bits-per-line x y
 
3953
                       copy copy-padded-bits-per-line 0 0
 
3954
                       height
 
3955
                       (index* width bits-per-pixel))
 
3956
        t))
 
3957
        
 
3958
    #+(or lcl3.0 excl)
 
3959
    (unless (index= bits-per-pixel 24)
 
3960
      (let ((pixarray-padded-bits-per-line
 
3961
              (if (index= height 1) 0
 
3962
                (index* (index- (array-row-major-index pixarray 1 0)
 
3963
                                (array-row-major-index pixarray 0 0))
 
3964
                        bits-per-pixel)))
 
3965
            (copy-padded-bits-per-line
 
3966
              (if (index= height 1) 0
 
3967
                (index* (index- (array-row-major-index copy 1 0)
 
3968
                                (array-row-major-index copy 0 0))
 
3969
                        bits-per-pixel)))
 
3970
            (pixarray-start-bit-offset
 
3971
              (index* (array-row-major-index pixarray y x)
 
3972
                      bits-per-pixel)))
 
3973
        (declare (type array-index pixarray-padded-bits-per-line
 
3974
                       copy-padded-bits-per-line pixarray-start-bit-offset))
 
3975
        (when (if (eq *computed-image-byte-lsb-first-p* *computed-image-bit-lsb-first-p*)
 
3976
                  (and (index-zerop (index-mod pixarray-padded-bits-per-line 8))
 
3977
                       (index-zerop (index-mod copy-padded-bits-per-line 8))
 
3978
                       (index-zerop (index-mod pixarray-start-bit-offset 8)))
 
3979
                (and (index-zerop (index-mod pixarray-padded-bits-per-line +image-unit+))
 
3980
                     (index-zerop (index-mod copy-padded-bits-per-line +image-unit+))
 
3981
                     (index-zerop (index-mod pixarray-start-bit-offset +image-unit+))))
 
3982
          (with-underlying-simple-vector (src card8 pixarray)
 
3983
            (with-underlying-simple-vector (dst card8 copy)
 
3984
              (image-noswap
 
3985
                src dst
 
3986
                (index-floor pixarray-start-bit-offset 8) 0
 
3987
                (index-ceiling (index* width bits-per-pixel) 8)
 
3988
                (index-floor pixarray-padded-bits-per-line 8)
 
3989
                (index-floor copy-padded-bits-per-line 8)
 
3990
                height nil)))
 
3991
          t)))
 
3992
    #+(or lcl3.0 excl)
 
3993
    (macrolet
 
3994
      ((copy (type element-type)
 
3995
         `(let ((pixarray pixarray)
 
3996
                (copy copy))
 
3997
            (declare (type ,type pixarray copy))
 
3998
            #.(declare-buffun)
 
3999
            (with-underlying-simple-vector (src ,element-type pixarray)
 
4000
              (with-underlying-simple-vector (dst ,element-type copy)
 
4001
                (do* ((dst-y 0 (index1+ dst-y))
 
4002
                      (src-y y (index1+ src-y)))
 
4003
                     ((index>= dst-y height))
 
4004
                  (declare (type card16 dst-y src-y))
 
4005
                  (do* ((dst-idx (array-row-major-index copy dst-y 0)
 
4006
                                 (index1+ dst-idx))
 
4007
                        (dst-end (index+ dst-idx width))
 
4008
                        (src-idx (array-row-major-index pixarray src-y x)
 
4009
                                 (index1+ src-idx)))
 
4010
                       ((index>= dst-idx dst-end))
 
4011
                    (declare (type array-index dst-idx src-idx dst-end))
 
4012
                    (setf (aref dst dst-idx)
 
4013
                          (the ,element-type (aref src src-idx))))))))))
 
4014
      (ecase bits-per-pixel
 
4015
        (1  (copy pixarray-1  pixarray-1-element-type))
 
4016
        (4  (copy pixarray-4  pixarray-4-element-type))
 
4017
        (8  (copy pixarray-8  pixarray-8-element-type))
 
4018
        (16 (copy pixarray-16 pixarray-16-element-type))
 
4019
        (24 (copy pixarray-24 pixarray-24-element-type))
 
4020
        (32 (copy pixarray-32 pixarray-32-element-type)))
 
4021
      t)))