Changeset 6687
- Timestamp:
- Jun 8, 2007, 3:20:58 PM (17 years ago)
- File:
-
- 1 edited
-
branches/ide-1.0/ccl/examples/cocoa-editor.lisp (modified) (54 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/ide-1.0/ccl/examples/cocoa-editor.lisp
r6668 r6687 354 354 355 355 356 ;;; Return an NSData object representing the bytes in the string. If 357 ;;; the underlying buffer uses #\linefeed as a line terminator, we can 358 ;;; let the superclass method do the work; otherwise, we have to 359 ;;; ensure that each line is terminated according to the buffer's 360 ;;; conventions. 361 (objc:defmethod #/dataUsingEncoding:allowLossyConversion: 362 ((self hemlock-buffer-string) 363 (encoding :<NSS>tring<E>ncoding) 364 (flag :<BOOL>)) 365 (let* ((buffer (buffer-cache-buffer (hemlock-buffer-string-cache self))) 366 (hi::*buffer-gap-context* (hi::buffer-gap-context buffer)) 367 (external-format (if buffer (hi::buffer-external-format buffer ))) 368 (raw-length (if buffer (hemlock-buffer-length buffer) 0))) 369 (hi::%set-buffer-modified buffer nil) 370 (if (eql 0 raw-length) 371 (make-instance 'ns:ns-mutable-data :with-length 0) 372 (case external-format 373 ((:unix nil) 374 (call-next-method encoding flag)) 375 ((:macos :cp/m) 376 (let* ((cp/m-p (eq external-format :cp/m))) 377 (when cp/m-p 378 ;; This may seem like lot of fuss about an ancient OS and its 379 ;; odd line-termination conventions. Of course, I'm actually 380 ;; referring to CP/M-86. 381 (do* ((line (hi::mark-line (hi::buffer-start-mark buffer)) 382 next) 383 (next (hi::line-next line) (hi::line-next line))) 384 ((null line)) 385 (when next (incf raw-length)))) 386 (let* ((pos 0) 387 (data (make-instance 'ns:ns-mutable-data 388 :with-length raw-length)) 389 (bytes (#/mutableBytes data))) 390 (do* ((line (hi::mark-line (hi::buffer-start-mark buffer)) 391 next) 392 (next (hi::line-next line) (hi::line-next line))) 393 ((null line) data) 394 (let* ((chars (hi::line-chars line)) 395 (len (length chars))) 396 (unless (zerop len) 397 (%cstr-pointer chars (%inc-ptr bytes pos) nil) 398 (incf pos len)) 399 (when next 400 (when cp/m-p 401 (setf (%get-byte bytes pos) (char-code #\return)) 402 (incf pos) 403 (setf (%get-byte bytes pos) (char-code #\linefeed)) 404 (incf pos)))))))))))) 356 405 357 406 358 … … 419 371 (defclass hemlock-text-storage (ns:ns-text-storage) 420 372 ((string :foreign-type :id) 373 (hemlock-string :foreign-type :id) 421 374 (edit-count :foreign-type :int) 422 375 (append-edits :foreign-type :int) … … 438 391 439 392 393 440 394 ;;; Return true iff we're inside a "beginEditing/endEditing" pair 441 395 (objc:defmethod (#/editingInProgress :<BOOL>) ((self hemlock-text-storage)) … … 457 411 (n (#/longValue (#/objectAtIndex: params 1)))) 458 412 (#/edited:range:changeInLength: self #$NSTextStorageEditedCharacters (ns:make-ns-range pos n) (- n)) 459 (let* ((display (hemlock-buffer-string-cache (#/ string self))))413 (let* ((display (hemlock-buffer-string-cache (#/hemlockString self)))) 460 414 (reset-buffer-cache display) 461 415 (update-line-cache-for-index display pos)))) … … 499 453 ;;; Access the string. It'd be nice if this was a generic function; 500 454 ;;; we could have just made a reader method in the class definition. 455 456 457 501 458 (objc:defmethod #/string ((self hemlock-text-storage)) 502 459 (slot-value self 'string)) … … 505 462 (slot-value self 'cache)) 506 463 464 (objc:defmethod #/hemlockString ((self hemlock-text-storage)) 465 (slot-value self 'hemlock-string)) 466 507 467 (objc:defmethod #/initWithString: ((self hemlock-text-storage) s) 508 (let* ((newself (#/init self))) 509 (setf (slot-value newself 'string) s) 510 (setf (slot-value newself 'cache) 511 (#/retain (make-instance ns:ns-mutable-attributed-string 468 (setq s (%inc-ptr s 0)) 469 (let* ((newself (#/init self)) 470 (cache (#/retain (make-instance ns:ns-mutable-attributed-string 512 471 :with-string s 513 :attributes (svref *styles* 0)))) 472 :attributes (svref *styles* 0))))) 473 (declare (type hemlock-text-storage newself)) 474 (setf (slot-value newself 'hemlock-string) s) 475 (setf (slot-value newself 'cache) cache) 476 (setf (slot-value newself 'string) (#/retain (#/string cache))) 514 477 newself)) 515 478 516 479 ;;; Should generally only be called after open/revert. 517 480 (objc:defmethod (#/updateCache :void) ((self hemlock-text-storage)) 518 (with-slots (string cache) self 519 (#/replaceCharactersInRange:withString: cache (ns:make-ns-range 0 (#/length cache)) string))) 481 (with-slots (hemlock-string cache) self 482 (#/replaceCharactersInRange:withString: cache (ns:make-ns-range 0 (#/length cache)) hemlock-string) 483 (#/setAttributes:range: cache (svref *styles* 0) (ns:make-ns-range 0 (#/length cache))))) 520 484 521 485 ;;; This is the only thing that's actually called to create a … … 536 500 #+debug 537 501 (#_NSLog #@"Attributes at index: %d" :unsigned index) 538 #+no539 (let* ((buffer-cache (hemlock-buffer-string-cache (slot-value self 'string)))540 (buffer (buffer-cache-buffer buffer-cache))541 (hi::*buffer-gap-context* (hi::buffer-gap-context buffer)))542 (update-line-cache-for-index buffer-cache index)543 (multiple-value-bind (start len style)544 (ccl::do-dll-nodes (node545 (hi::buffer-font-regions buffer)546 (values 0 (buffer-cache-buflen buffer-cache) 0))547 (let* ((region (hi::font-region-node-region node))548 (start (hi::region-start region))549 (end (hi::region-end region))550 (startpos (mark-absolute-position start))551 (endpos (mark-absolute-position end)))552 (when (and (>= index startpos)553 (< index endpos))554 (return (values startpos555 (- endpos startpos)556 (hi::font-mark-font start))))))557 #+debug558 (#_NSLog #@"Start = %d, len = %d, style = %d"559 :int start :int len :int style)560 (unless (%null-ptr-p rangeptr)561 (setf (pref rangeptr :<NSR>ange.location) start562 (pref rangeptr :<NSR>ange.length) len))563 (svref *styles* style)))564 #-no565 502 (with-slots (cache) self 566 503 (let* ((attrs (#/attributesAtIndex:effectiveRange: cache index rangeptr))) 567 504 (when (eql 0 (#/count attrs)) 505 (#_NSLog #@"No attributes ?") 568 506 (ns:with-ns-range (r) 569 507 (#/attributesAtIndex:longestEffectiveRange:inRange: … … 575 513 (objc:defmethod (#/replaceCharactersInRange:withString: :void) 576 514 ((self hemlock-text-storage) (r :<NSR>ange) string) 577 #+debug 0(#_NSLog #@"Replace in range %ld/%ld with %@"578 :<NSI>nteger (pref r :<NSR>ange.location)579 :<NSI>nteger (pref r :<NSR>ange.length)580 :id string)581 (let* ((cache (hemlock-buffer-string-cache (#/ string self)))515 #+debug (#_NSLog #@"Replace in range %ld/%ld with %@" 516 :<NSI>nteger (pref r :<NSR>ange.location) 517 :<NSI>nteger (pref r :<NSR>ange.length) 518 :id string) 519 (let* ((cache (hemlock-buffer-string-cache (#/hemlockString self))) 582 520 (buffer (if cache (buffer-cache-buffer cache))) 583 521 (hi::*buffer-gap-context* (hi::buffer-gap-context buffer)) 584 522 (location (pref r :<NSR>ange.location)) 585 523 (length (pref r :<NSR>ange.length)) 586 (mark (hi::buffer-%mark buffer)) 587 (point (hi::buffer-point buffer)) 588 input-mark) 589 ;; 590 ;; special behavior for listener windows. 591 ;; 592 (if (and (> (slot-value self 'append-edits) 0) 593 (progn 594 (setf input-mark (hi::variable-value 'hemlock::buffer-input-mark :buffer buffer)) 595 (not (hi::same-line-p point input-mark)))) 596 (progn 597 ;; 598 ;; move the point to the end of the buffer 599 ;; 600 (setf (hi::buffer-region-active buffer) nil) 601 (move-hemlock-mark-to-absolute-position point cache (hemlock-buffer-length buffer))) 602 (cond ((> length 0) 603 (move-hemlock-mark-to-absolute-position mark cache location) 604 (move-hemlock-mark-to-absolute-position point cache (+ location length)) 605 (hemlock::%buffer-activate-region buffer)) 606 (t 607 (move-hemlock-mark-to-absolute-position point cache location)))) 608 (let* ((lisp-string (lisp-string-from-nsstring string))) 609 (hi::enqueue-buffer-operation 610 buffer 611 #'(lambda () 612 (unwind-protect 613 (progn 614 (hi::buffer-document-begin-editing buffer) 615 (hi::insert-string point lisp-string)) 616 (hi::buffer-document-end-editing buffer))))))) 524 (point (hi::buffer-point buffer))) 525 (let* ((lisp-string (lisp-string-from-nsstring string)) 526 (document (if buffer (hi::buffer-document buffer))) 527 (textstorage (if document (slot-value document 'textstorage)))) 528 (when textstorage (#/beginEditing textstorage)) 529 (setf (hi::buffer-region-active buffer) nil) 530 (unless (zerop length) 531 (hi::with-mark ((start point) 532 (end point)) 533 (move-hemlock-mark-to-absolute-position start cache location) 534 (move-hemlock-mark-to-absolute-position end cache (+ location length)) 535 (hi::delete-region (hi::region start end)))) 536 (hi::insert-string point lisp-string) 537 (when textstorage 538 (#/endEditing textstorage) 539 (for-each-textview-using-storage textstorage (lambda (tv) 540 (hi::disable-self-insert (hemlock-frame-event-queue (#/window tv))))) 541 (#/ensureSelectionVisible textstorage))))) 617 542 618 543 … … 624 549 (with-slots (cache) self 625 550 (#/setAttributes:range: cache attributes r) 626 #+debug 627 (#_NSLog #@"Assigned attributes = %@" :id (#/attributesAtIndex:effectiveRange: cache (pref r :<NSR>ange.location) +null-ptr+)) 628 )) 551 #+debug 552 (#_NSLog #@"Assigned attributes = %@" :id (#/attributesAtIndex:effectiveRange: cache (pref r :<NSR>ange.location) +null-ptr+)))) 629 553 630 554 (defun for-each-textview-using-storage (textstorage f) … … 642 566 ;;; Again, it's helpful to see the buffer name when debugging. 643 567 (objc:defmethod #/description ((self hemlock-text-storage)) 644 (#/stringWithFormat: ns:ns-string #@"%s : string %@" (#_object_getClassName self) (slot-value self ' string)))568 (#/stringWithFormat: ns:ns-string #@"%s : string %@" (#_object_getClassName self) (slot-value self 'hemlock-string))) 645 569 646 570 ;;; This needs to happen on the main thread. … … 653 577 654 578 (defun close-hemlock-textstorage (ts) 655 (let* (( string (slot-value ts 'string)))656 (setf (slot-value ts ' string) (%null-ptr))657 (unless (%null-ptr-p string)658 (let* ((cache (hemlock-buffer-string-cache string))659 (buffer (if cache (buffer-cache-buffer cache))))660 (when buffer661 (setf (buffer-cache-buffer cache) nil662 (slot-valuestring 'cache) nil663 (hi::buffer-document buffer) nil)664 (let* ((p (hi::buffer-process buffer)))665 (when p666 (setf (hi::buffer-process buffer) nil)667 (process-kill p)))668 (when (eq buffer hi::*current-buffer*)669 (setf (hi::current-buffer)670 (car (last hi::*buffer-list*))))671 (hi::invoke-hook (hi::buffer-delete-hook buffer) buffer)672 (hi::invoke-hook hemlock::delete-buffer-hook buffer)673 (setq hi::*buffer-list* (delq buffer hi::*buffer-list*))674 (hi::delete-string (hi::buffer-name buffer) hi::*buffer-names*))))))579 (let* ((hemlock-string (slot-value ts 'hemlock-string))) 580 (setf (slot-value ts 'hemlock-string) +null-ptr+) 581 (unless (%null-ptr-p hemlock-string) 582 (let* ((cache (hemlock-buffer-string-cache hemlock-string)) 583 (buffer (if cache (buffer-cache-buffer cache)))) 584 (when buffer 585 (setf (buffer-cache-buffer cache) nil 586 (slot-value hemlock-string 'cache) nil 587 (hi::buffer-document buffer) nil) 588 (let* ((p (hi::buffer-process buffer))) 589 (when p 590 (setf (hi::buffer-process buffer) nil) 591 (process-kill p))) 592 (when (eq buffer hi::*current-buffer*) 593 (setf (hi::current-buffer) 594 (car (last hi::*buffer-list*)))) 595 (hi::invoke-hook (hi::buffer-delete-hook buffer) buffer) 596 (hi::invoke-hook hemlock::delete-buffer-hook buffer) 597 (setq hi::*buffer-list* (delq buffer hi::*buffer-list*)) 598 (hi::delete-string (hi::buffer-name buffer) hi::*buffer-names*)))))) 675 599 676 600 … … 691 615 ((self hemlock-textstorage-text-view) layout cont (flag :<BOOL>)) 692 616 (declare (ignorable cont flag)) 617 #+debug (#_NSLog #@"layout complete: container = %@, atend = %d" :id cont :int (if flag 1 0)) 693 618 (when (zerop *layout-text-in-background*) 694 619 (#/setDelegate: layout +null-ptr+) … … 744 669 (defmethod update-blink ((self hemlock-textstorage-text-view)) 745 670 (disable-blink self) 746 (let* ((d (hemlock-buffer-string-cache (#/ string self)))671 (let* ((d (hemlock-buffer-string-cache (#/hemlockString (#/textStorage self)))) 747 672 (buffer (buffer-cache-buffer d))) 748 673 (when (and buffer (string= (hi::buffer-major-mode buffer) "Lisp")) … … 794 719 ;;; object that displays buffers. 795 720 (defclass hemlock-text-view (hemlock-textstorage-text-view) 796 ((pane :foreign-type :id :accessor text-view-pane)) 721 ((pane :foreign-type :id :accessor text-view-pane) 722 (char-width :foreign-type :<CGF>loat :accessor text-view-char-width) 723 (char-height :foreign-type :<CGF>loat :accessor text-view-char-height)) 797 724 (:metaclass ns:+ns-object)) 798 725 … … 803 730 ;;; Access the underlying buffer in one swell foop. 804 731 (defmethod text-view-buffer ((self hemlock-text-view)) 805 (buffer-cache-buffer (hemlock-buffer-string-cache (#/string (#/textStorage self))))) 806 807 (objc:defmethod (#/setString: :void) ((self hemlock-textstorage-text-view) s) 808 #+debug 809 (#_NSLog #@"hemlock-text-view %@ string set to %@" :id self :id s) 810 (call-next-method) s) 732 (buffer-cache-buffer (hemlock-buffer-string-cache (#/hemlockString (#/textStorage self))))) 733 734 811 735 812 736 (objc:defmethod (#/selectionRangeForProposedRange:granularity: :ns-range) … … 817 741 (#_NSLog #@"Granularity = %d" :int g) 818 742 (objc:returning-foreign-struct (r) 819 (block HANDLED 820 (let* ((index (ns:ns-range-location proposed)) 821 (length (ns:ns-range-length proposed))) 822 (when (and (eql 0 length) ; not extending existing selection 823 (not (eql g #$NSSelectByCharacter))) 824 (let* ((textstorage (#/textStorage self)) 825 (cache (hemlock-buffer-string-cache (#/string textstorage))) 826 (buffer (if cache (buffer-cache-buffer cache)))) 827 (when (and buffer (string= (hi::buffer-major-mode buffer) "Lisp")) 828 (let* ((hi::*buffer-gap-context* (hi::buffer-gap-context buffer))) 829 (hi::with-mark ((m1 (hi::buffer-point buffer))) 830 (move-hemlock-mark-to-absolute-position m1 cache index) 831 (hemlock::pre-command-parse-check m1) 832 (when (hemlock::valid-spot m1 nil) 833 (cond ((eql (hi::next-character m1) #\() 834 (hi::with-mark ((m2 m1)) 835 (when (hemlock::list-offset m2 1) 836 (ns:init-ns-range r index (- (mark-absolute-position m2) index)) 837 (return-from HANDLED r)))) 838 ((eql (hi::previous-character m1) #\)) 839 (hi::with-mark ((m2 m1)) 840 (when (hemlock::list-offset m2 -1) 841 (ns:init-ns-range r (mark-absolute-position m2) (- index (mark-absolute-position m2))) 842 (return-from HANDLED r)))))))))))) 843 (call-next-method proposed g) 844 #+debug 845 (#_NSLog #@"range = %@, proposed = %@, granularity = %d" 846 :address (#_NSStringFromRange r) 847 :address (#_NSStringFromRange proposed) 848 :<NSS>election<G>ranularity g)))) 743 (block HANDLED 744 (let* ((index (ns:ns-range-location proposed)) 745 (length (ns:ns-range-length proposed))) 746 (when (and (eql 0 length) ; not extending existing selection 747 (not (eql g #$NSSelectByCharacter))) 748 (let* ((textstorage (#/textStorage self)) 749 (cache (hemlock-buffer-string-cache (#/hemlockString textstorage))) 750 (buffer (if cache (buffer-cache-buffer cache)))) 751 (when (and buffer (string= (hi::buffer-major-mode buffer) "Lisp")) 752 (let* ((hi::*buffer-gap-context* (hi::buffer-gap-context buffer))) 753 (hi::with-mark ((m1 (hi::buffer-point buffer))) 754 (move-hemlock-mark-to-absolute-position m1 cache index) 755 (hemlock::pre-command-parse-check m1) 756 (when (hemlock::valid-spot m1 nil) 757 (cond ((eql (hi::next-character m1) #\() 758 (hi::with-mark ((m2 m1)) 759 (when (hemlock::list-offset m2 1) 760 (ns:init-ns-range r index (- (mark-absolute-position m2) index)) 761 (return-from HANDLED r)))) 762 ((eql (hi::previous-character m1) #\)) 763 (hi::with-mark ((m2 m1)) 764 (when (hemlock::list-offset m2 -1) 765 (ns:init-ns-range r (mark-absolute-position m2) (- index (mark-absolute-position m2))) 766 (return-from HANDLED r)))))))))))) 767 (call-next-method proposed g) 768 #+debug 769 (#_NSLog #@"range = %@, proposed = %@, granularity = %d" 770 :address (#_NSStringFromRange r) 771 :address (#_NSStringFromRange proposed) 772 :<NSS>election<G>ranularity g)))) 773 774 849 775 850 776 … … 852 778 853 779 ;;; Translate a keyDown NSEvent to a Hemlock key-event. 854 (defun nsevent-to-key-event (nsevent )780 (defun nsevent-to-key-event (nsevent &optional quoted) 855 781 (let* ((modifiers (#/modifierFlags nsevent))) 856 782 (unless (logtest #$NSCommandKeyMask modifiers) 857 (let* ((unmodchars (#/charactersIgnoringModifiers nsevent)) 858 (n (if (%null-ptr-p unmodchars) 783 (let* ((chars (if quoted 784 (#/characters nsevent) 785 (#/charactersIgnoringModifiers nsevent))) 786 (n (if (%null-ptr-p chars) 859 787 0 860 (#/length unmodchars)))788 (#/length chars))) 861 789 (c (if (eql n 1) 862 (#/characterAtIndex: unmodchars 0))))790 (#/characterAtIndex: chars 0)))) 863 791 (when c 864 792 (let* ((bits 0) … … 866 794 (logior #$NSShiftKeyMask 867 795 #$NSAlphaShiftKeyMask)))) 868 (dolist (map hemlock-ext::*modifier-translations*) 869 (when (logtest useful-modifiers (car map)) 870 (setq bits (logior bits (hemlock-ext::key-event-modifier-mask 871 (cdr map)))))) 796 (unless quoted 797 (dolist (map hemlock-ext::*modifier-translations*) 798 (when (logtest useful-modifiers (car map)) 799 (setq bits (logior bits (hemlock-ext::key-event-modifier-mask 800 (cdr map))))))) 872 801 (hemlock-ext::make-key-event c bits))))))) 873 802 874 (defun pass-key-down-event-to-hemlock (self event )803 (defun pass-key-down-event-to-hemlock (self event q) 875 804 #+debug 876 805 (#_NSLog #@"Key down event = %@" :address event) 877 806 (let* ((buffer (text-view-buffer self))) 878 807 (when buffer 879 (let* ((hemlock-event (nsevent-to-key-event event )))808 (let* ((hemlock-event (nsevent-to-key-event event (hi::frame-event-queue-quoted-insert q )))) 880 809 (when hemlock-event 881 (let* ((q (hemlock-frame-event-queue (#/window self)))) 882 (hi::enqueue-key-event q hemlock-event))))))) 810 (hi::enqueue-key-event q hemlock-event)))))) 883 811 884 812 (defun hi::enqueue-buffer-operation (buffer thunk) … … 893 821 ;;; interpreter. 894 822 823 (defun handle-key-down (self event) 824 (let* ((q (hemlock-frame-event-queue (#/window self)))) 825 (if (or (and (zerop (#/length (#/characters event))) 826 (hi::frame-event-queue-quoted-insert q)) 827 (#/hasMarkedText self)) 828 nil 829 (progn 830 (pass-key-down-event-to-hemlock self event q) 831 t)))) 832 833 895 834 (objc:defmethod (#/keyDown: :void) ((self hemlock-text-view) event) 896 (pass-key-down-event-to-hemlock self event)) 835 (or (handle-key-down self event) 836 (call-next-method event))) 897 837 898 838 ;;; Update the underlying buffer's point (and "active region", if appropriate. … … 916 856 :id (#/string (#/textStorage self))) 917 857 (unless (#/editingInProgress (#/textStorage self)) 918 (let* ((d (hemlock-buffer-string-cache (#/ string self)))858 (let* ((d (hemlock-buffer-string-cache (#/hemlockString (#/textStorage self)))) 919 859 (buffer (buffer-cache-buffer d)) 920 860 (hi::*buffer-gap-context* (hi::buffer-gap-context buffer)) … … 1155 1095 1156 1096 1157 (defun make-scrolling-text-view-for-textstorage (textstorage x y width height tracks-width color )1097 (defun make-scrolling-text-view-for-textstorage (textstorage x y width height tracks-width color style) 1158 1098 (let* ((scrollview (#/autorelease 1159 1099 (make-instance … … 1170 1110 (let* ((layout (make-instance 'ns:ns-layout-manager))) 1171 1111 (#/addLayoutManager: textstorage layout) 1112 (#/setUsesScreenFonts: layout t) 1172 1113 (#/release layout) 1173 1114 (let* ((contentsize (#/contentSize scrollview))) … … 1191 1132 (#/setAutoresizingMask: tv #$NSViewWidthSizable) 1192 1133 (#/setBackgroundColor: tv color) 1134 (#/setTypingAttributes: tv (aref *styles* style)) 1193 1135 (#/setSmartInsertDeleteEnabled: tv nil) 1194 1136 (#/setAllowsUndo: tv t) … … 1199 1141 (values tv scrollview))))))))) 1200 1142 1201 (defun make-scrolling-textview-for-pane (pane textstorage track-width color )1143 (defun make-scrolling-textview-for-pane (pane textstorage track-width color style) 1202 1144 (let* ((contentrect (#/frame (#/contentView pane)))) 1203 1145 (multiple-value-bind (tv scrollview) … … 1209 1151 (ns:ns-rect-height contentrect) 1210 1152 track-width 1211 color) 1153 color 1154 style) 1212 1155 (#/setContentView: pane scrollview) 1213 1156 (setf (slot-value pane 'scroll-view) scrollview … … 1238 1181 1239 1182 (defmethod text-view-buffer ((self echo-area-view)) 1240 (buffer-cache-buffer (hemlock-buffer-string-cache (#/ string (#/textStorage self)))))1183 (buffer-cache-buffer (hemlock-buffer-string-cache (#/hemlockString (#/textStorage self))))) 1241 1184 1242 1185 ;;; The "document" for an echo-area isn't a real NSDocument. … … 1245 1188 (:metaclass ns:+ns-object)) 1246 1189 1247 ( define-objc-method ((:void close) echo-area-document)1190 (objc:defmethod (#/close :void) ((self echo-area-document)) 1248 1191 (let* ((ts (slot-value self 'textstorage))) 1249 1192 (unless (%null-ptr-p ts) … … 1251 1194 (close-hemlock-textstorage ts)))) 1252 1195 1253 (define-objc-method ((:void :update-change-count (:<NSD>ocument<C>hange<T>ype change)) echo-area-document) 1196 (objc:defmethod (#/updateChangeCount: :void) 1197 ((self echo-area-document) 1198 (change :<NSD>ocument<C>hange<T>ype)) 1254 1199 (declare (ignore change))) 1255 1200 1256 ( define-objc-method ((:void :key-downevent)1257 echo-area-view)1258 (pass-key-down-event-to-hemlock self event))1201 (objc:defmethod (#/keyDown: :void) ((self echo-area-view) event) 1202 (or (handle-key-down self event) 1203 (call-next-method event))) 1259 1204 1260 1205 … … 1474 1419 pane)))) 1475 1420 1476 (defun textpane-for-textstorage (ts ncols nrows container-tracks-text-view-width color )1421 (defun textpane-for-textstorage (ts ncols nrows container-tracks-text-view-width color style) 1477 1422 (let* ((pane (nth-value 1478 1423 1 1479 1424 (new-hemlock-document-window)))) 1480 (make-scrolling-textview-for-pane pane ts container-tracks-text-view-width color )1425 (make-scrolling-textview-for-pane pane ts container-tracks-text-view-width color style) 1481 1426 (multiple-value-bind (height width) 1482 1427 (size-of-char-in-font (default-font)) … … 1492 1437 1493 1438 (defun %nsstring-to-mark (nsstring mark) 1494 "returns external-format of string" 1495 (let* ((string-len (#/length nsstring)) 1496 (line-start 0) 1497 (first-line-terminator ()) 1498 (first-line (hi::mark-line mark)) 1499 (previous first-line) 1500 (buffer (hi::line-%buffer first-line)) 1501 (hi::*buffer-gap-context* 1502 (or 1503 (hi::buffer-gap-context buffer) 1504 (setf (hi::buffer-gap-context buffer) 1505 (hi::make-buffer-gap-context))))) 1506 (rlet ((remaining-range :ns-range :location 0 :length 1) 1507 (line-end-index :<NSUI>nteger) 1508 (contents-end-index :<NSUI>nteger)) 1509 (do* ((number (+ (hi::line-number first-line) hi::line-increment) 1510 (+ number hi::line-increment))) 1511 ((= line-start string-len) 1512 (let* ((line (hi::mark-line mark))) 1513 (hi::insert-string mark (make-string 0)) 1514 (setf (hi::line-next previous) line 1515 (hi::line-previous line) previous)) 1516 nil) 1517 (setf (pref remaining-range :<NSR>ange.location) line-start) 1518 (#/getLineStart:end:contentsEnd:forRange: 1519 nsstring 1520 +null-ptr+ 1521 line-end-index 1522 contents-end-index 1523 remaining-range) 1524 (let* ((contents-end (pref contents-end-index :<NSUI>nteger)) 1525 (line-end (pref line-end-index :<NSUI>nteger)) 1526 (chars (make-string (- contents-end line-start)))) 1527 (do* ((i line-start (1+ i)) 1528 (j 0 (1+ j))) 1529 ((= i contents-end)) 1530 (setf (schar chars j) (code-char (#/characterAtIndex: nsstring i)))) 1531 (unless first-line-terminator 1532 (let* ((terminator (code-char 1533 (#/characterAtIndex: nsstring contents-end)))) 1534 (setq first-line-terminator 1535 (case terminator 1536 (#\return (if (= line-end (+ contents-end 2)) 1537 :cp/m 1538 :macos)) 1539 (t :unix))))) 1540 (if (eq previous first-line) 1541 (progn 1542 (hi::insert-string mark chars) 1543 (hi::insert-character mark #\newline) 1544 (setq first-line nil)) 1545 (if (eq string-len contents-end) 1546 (hi::insert-string mark chars) 1547 (let* ((line (hi::make-line 1548 :previous previous 1549 :%buffer buffer 1550 :chars chars 1551 :number number))) 1552 (setf (hi::line-next previous) line) 1553 (setq previous line)))) 1554 (setq line-start line-end)))) 1555 first-line-terminator)) 1439 "returns line-termination of string" 1440 (let* ((string (lisp-string-from-nsstring nsstring)) 1441 (lfpos (position #\linefeed string)) 1442 (crpos (position #\return string)) 1443 (line-termination (if crpos 1444 (if (eql lfpos (1+ crpos)) 1445 :cp/m 1446 :macos) 1447 :unix))) 1448 (hi::insert-string mark 1449 (case line-termination 1450 (:cp/m (remove #\return string)) 1451 (:macos (nsubstitute #\linefeed #\return string)) 1452 (t string))) 1453 line-termination)) 1556 1454 1557 1455 (defun nsstring-to-buffer (nsstring buffer) … … 1563 1461 (progn 1564 1462 (hi::delete-region region) 1565 (hi::modifying-buffer buffer )1566 (hi::with-mark ((mark (hi::buffer-point buffer) :left-inserting))1567 (setf (hi::buffer-external-formatbuffer)1568 (%nsstring-to-mark nsstring mark)))1569 (setf (hi::buffer-modified buffer) nil)1570 (hi::buffer-start (hi::buffer-point buffer))1571 (hi::renumber-region region)1572 buffer)1463 (hi::modifying-buffer buffer 1464 (hi::with-mark ((mark (hi::buffer-point buffer) :left-inserting)) 1465 (setf (hi::buffer-line-termination buffer) 1466 (%nsstring-to-mark nsstring mark))) 1467 (setf (hi::buffer-modified buffer) nil) 1468 (hi::buffer-start (hi::buffer-point buffer)) 1469 (hi::renumber-region region) 1470 buffer)) 1573 1471 (setf (hi::buffer-document buffer) document)))) 1574 1575 ;;; This assumes that the buffer has no document and no textstorage (yet).1576 (defun hi::cocoa-read-file (lisp-pathname mark buffer)1577 (let* ((lisp-namestring (native-translated-namestring lisp-pathname))1578 (cocoa-pathname (%make-nsstring lisp-namestring))1579 (hi::*buffer-gap-context* (hi::buffer-gap-context buffer))1580 (data (make-instance 'ns:ns-data1581 :with-contents-of-file cocoa-pathname))1582 (string (make-instance 'ns:ns-string1583 :with-data data1584 :encoding #$NSASCIIStringEncoding))1585 (external-format (%nsstring-to-mark string mark)))1586 (unless (hi::buffer-external-format buffer)1587 (setf (hi::buffer-external-format buffer) external-format))1588 buffer))1589 1590 1472 1591 1473 … … 1597 1479 1598 1480 ;;; This function must run in the main event thread. 1599 (defun %hemlock-frame-for-textstorage (ts ncols nrows container-tracks-text-view-width color )1600 (let* ((pane (textpane-for-textstorage ts ncols nrows container-tracks-text-view-width color ))1481 (defun %hemlock-frame-for-textstorage (ts ncols nrows container-tracks-text-view-width color style) 1482 (let* ((pane (textpane-for-textstorage ts ncols nrows container-tracks-text-view-width color style)) 1601 1483 (frame (#/window pane)) 1602 1484 (buffer (text-view-buffer (text-pane-text-view pane)))) … … 1617 1499 1618 1500 1619 (defun hemlock-frame-for-textstorage (ts ncols nrows container-tracks-text-view-width color )1501 (defun hemlock-frame-for-textstorage (ts ncols nrows container-tracks-text-view-width color style) 1620 1502 (process-interrupt *cocoa-event-process* 1621 1503 #'%hemlock-frame-for-textstorage 1622 ts ncols nrows container-tracks-text-view-width color ))1504 ts ncols nrows container-tracks-text-view-width color style)) 1623 1505 1624 1506 … … 1717 1599 (let* ((pos (mark-absolute-position mark)) 1718 1600 (cache (#/cache textstorage)) 1719 (hemlock-string (#/ string textstorage))1601 (hemlock-string (#/hemlockString textstorage)) 1720 1602 (display (hemlock-buffer-string-cache hemlock-string)) 1721 1603 (buffer (buffer-cache-buffer display)) … … 1745 1627 (textstorage (if document (slot-value document 'textstorage)))) 1746 1628 (when textstorage 1747 (let* ((hemlock-string (#/ string textstorage))1629 (let* ((hemlock-string (#/hemlockString textstorage)) 1748 1630 (cache (#/cache textstorage)) 1749 1631 (pos (mark-absolute-position mark))) … … 1780 1662 (#/edited:range:changeInLength: 1781 1663 textstorage #$NSTextStorageEditedCharacters (ns:make-ns-range pos n) (- n)) 1782 (let* ((display (hemlock-buffer-string-cache (#/ string textstorage))))1664 (let* ((display (hemlock-buffer-string-cache (#/hemlockString textstorage)))) 1783 1665 (reset-buffer-cache display) 1784 1666 (update-line-cache-for-index display pos))) … … 1838 1720 (ns:ns-size-width margins)) 1839 1721 (#/setContentSize: window sv-size) 1722 (setf (slot-value tv 'char-width) char-width 1723 (slot-value tv 'char-height) char-height) 1840 1724 (#/setResizeIncrements: window 1841 1725 (ns:make-ns-size char-width char-height)))))) … … 1847 1731 1848 1732 1733 ;;; Map *default-file-character-encoding* to an :<NSS>tring<E>ncoding 1734 (defun get-default-encoding () 1735 (let* ((string (string (or *default-file-character-encoding* 1736 "ISO-8859-1"))) 1737 (len (length string))) 1738 (with-cstrs ((cstr string)) 1739 (with-nsstr (nsstr cstr len) 1740 (let* ((cf (#_CFStringConvertIANACharSetNameToEncoding nsstr))) 1741 (if (= cf #$kCFStringEncodingInvalidId) 1742 (setq cf (#_CFStringGetSystemEncoding))) 1743 (let* ((ns (#_CFStringConvertEncodingToNSStringEncoding cf))) 1744 (if (= ns #$kCFStringEncodingInvalidId) 1745 (#/defaultCStringEncoding ns:ns-string) 1746 ns))))))) 1849 1747 1850 1748 ;;; The HemlockEditorDocument class. … … 1855 1753 (encoding :foreign-type :<NSS>tring<E>ncoding)) 1856 1754 (:metaclass ns:+ns-object)) 1755 1756 1757 (defmethod user-input-style ((doc hemlock-editor-document)) 1758 0) 1759 1760 (defvar *encoding-name-hash* (make-hash-table)) 1761 1762 (defmethod hi::document-encoding-name ((doc hemlock-editor-document)) 1763 (with-slots (encoding) doc 1764 (if (eql encoding 0) 1765 "Automatic" 1766 (or (gethash encoding *encoding-name-hash*) 1767 (setf (gethash encoding *encoding-name-hash*) 1768 (lisp-string-from-nsstring (nsstring-for-nsstring-encoding encoding))))))) 1769 1857 1770 1858 1771 (defmethod textview-background-color ((doc hemlock-editor-document)) … … 1867 1780 (objc:defmethod (#/setTextStorage: :void) ((self hemlock-editor-document) ts) 1868 1781 (let* ((doc (%inc-ptr self 0)) ; workaround for stack-consed self 1869 (string (#/ string ts))1782 (string (#/hemlockString ts)) 1870 1783 (cache (hemlock-buffer-string-cache string)) 1871 1784 (buffer (buffer-cache-buffer cache))) … … 1899 1812 (#/edited:range:changeInLength: textstorage #$NSTextStorageEditedAttributes (ns:make-ns-range 0 0) newlen) 1900 1813 (#/edited:range:changeInLength: textstorage #$NSTextStorageEditedCharacters (ns:make-ns-range 0 newlen) 0) 1901 (let* ((ts-string (#/ string textstorage))1814 (let* ((ts-string (#/hemlockString textstorage)) 1902 1815 (display (hemlock-buffer-string-cache ts-string))) 1903 1816 (reset-buffer-cache display) … … 1955 1868 (when (%null-ptr-p string) 1956 1869 (if (zerop selected-encoding) 1957 (setq selected-encoding ( #/defaultCStringEncoding ns:ns-string)))1870 (setq selected-encoding (get-default-encoding))) 1958 1871 (setq string (#/stringWithContentsOfURL:encoding:error: 1959 1872 ns:ns-string … … 1963 1876 (unless (%null-ptr-p string) 1964 1877 (with-slots (encoding) self (setq encoding selected-encoding)) 1878 (hi::queue-buffer-change buffer) 1965 1879 (hi::document-begin-editing self) 1966 1880 (nsstring-to-buffer string buffer) 1967 1881 (let* ((textstorage (slot-value self 'textstorage)) 1968 (display (hemlock-buffer-string-cache (#/ string textstorage))))1882 (display (hemlock-buffer-string-cache (#/hemlockString textstorage)))) 1969 1883 (reset-buffer-cache display) 1970 1884 (#/updateCache textstorage) … … 1992 1906 1993 1907 (defmethod hemlock-document-buffer (document) 1994 (let* ((string (#/ string (slot-value document 'textstorage))))1908 (let* ((string (#/hemlockString (slot-value document 'textstorage)))) 1995 1909 (unless (%null-ptr-p string) 1996 1910 (let* ((cache (hemlock-buffer-string-cache string))) … … 2008 1922 panes)) 2009 1923 2010 1924 (objc:defmethod (#/noteEncodingChange: :void) ((self hemlock-editor-document) 1925 popup) 1926 (with-slots (encoding) self 1927 (setq encoding (#/selectedTag popup)) 1928 ;; Force modeline update. 1929 (hi::queue-buffer-change (hemlock-document-buffer self)))) 2011 1930 2012 1931 (objc:defmethod (#/prepareSavePanel: :<BOOL>) ((self hemlock-editor-document) 2013 1932 panel) 2014 1933 (with-slots (encoding) self 2015 (let* ((popup (build-encodings-popup (#/sharedDocumentController ns:ns-document-controller) encoding))) 1934 (let* ((popup (build-encodings-popup (#/sharedDocumentController ns:ns-document-controller) encoding))) 1935 (#/setAction: popup (@selector #/noteEncodingChange:)) 1936 (#/setTarget: popup self) 2016 1937 (#/setAccessoryView: panel popup))) 2017 1938 (#/setExtensionHidden: panel nil) … … 2030 1951 (let* ((string (#/string textstorage)) 2031 1952 (buffer (hemlock-document-buffer self))) 2032 (case (when buffer (hi::buffer- external-formatbuffer))1953 (case (when buffer (hi::buffer-line-termination buffer)) 2033 1954 (:cp/m (setq string (#/stringByReplacingOccurrencesOfString:withString: 2034 1955 string *ns-lf-string* *ns-crlf-string*))) … … 2056 1977 2057 1978 2058 (def-cocoa-default *initial-editor-x-pos* :float 20 0.0f0 "X position of upper-left corner of initial editor")2059 2060 (def-cocoa-default *initial-editor-y-pos* :float 400.0f0 "Y position of upper-left corner of initial editor")1979 (def-cocoa-default *initial-editor-x-pos* :float 20.0f0 "X position of upper-left corner of initial editor") 1980 1981 (def-cocoa-default *initial-editor-y-pos* :float -20.0f0 "Y position of upper-left corner of initial editor") 2061 1982 2062 1983 (defloadvar *next-editor-x-pos* nil) ; set after defaults initialized 2063 1984 (defloadvar *next-editor-y-pos* nil) 1985 1986 (defun x-pos-for-window (window x) 1987 (let* ((frame (#/frame window)) 1988 (screen (#/screen window))) 1989 (if (%null-ptr-p screen) (setq screen (#/mainScreen ns:ns-screen))) 1990 (let* ((screen-rect (#/visibleFrame screen))) 1991 (if (>= x 0) 1992 (+ x (ns:ns-rect-x screen-rect)) 1993 (- (+ (ns:ns-rect-width screen-rect) x) (ns:ns-rect-width frame)))))) 1994 1995 (defun y-pos-for-window (window y) 1996 (let* ((frame (#/frame window)) 1997 (screen (#/screen window))) 1998 (if (%null-ptr-p screen) (setq screen (#/mainScreen ns:ns-screen))) 1999 (let* ((screen-rect (#/visibleFrame screen))) 2000 (if (>= y 0) 2001 (+ y (ns:ns-rect-y screen-rect) (ns:ns-rect-height frame)) 2002 (+ (ns:ns-rect-height screen-rect) y))))) 2064 2003 2065 2004 (objc:defmethod (#/makeWindowControllers :void) ((self hemlock-editor-document)) 2066 2005 #+debug 2067 2006 (#_NSLog #@"Make window controllers") 2068 (let* ((window (%hemlock-frame-for-textstorage 2069 (slot-value self 'textstorage) 2070 *editor-columns* 2071 *editor-rows* 2072 nil 2073 (textview-background-color self))) 2007 (let* ((textstorage (slot-value self 'textstorage)) 2008 (window (%hemlock-frame-for-textstorage 2009 textstorage 2010 *editor-columns* 2011 *editor-rows* 2012 nil 2013 (textview-background-color self) 2014 (user-input-style self))) 2074 2015 (controller (make-instance 2075 2016 'hemlock-editor-window-controller … … 2079 2020 (ns:with-ns-point (current-point 2080 2021 (or *next-editor-x-pos* 2081 *initial-editor-x-pos*)2022 (x-pos-for-window window *initial-editor-x-pos*)) 2082 2023 (or *next-editor-y-pos* 2083 *initial-editor-y-pos*))2024 (y-pos-for-window window *initial-editor-y-pos*))) 2084 2025 (let* ((new-point (#/cascadeTopLeftFromPoint: window current-point))) 2085 2026 (setq *next-editor-x-pos* (ns:ns-point-x new-point) … … 2105 2046 2106 2047 (defun hi::scroll-window (textpane n) 2107 (declare (ignore textpane)) 2108 (let* ((point (hi::current-point))) 2109 (or (hi::line-offset point (if (and n (< n 0)) -24 24) 0)))) 2048 (let* ((n (or n 0)) 2049 (sv (text-pane-scroll-view textpane)) 2050 (tv (text-pane-text-view textpane)) 2051 (char-height (text-view-char-height tv)) 2052 (sv-height (ns:ns-size-height (#/contentSize sv))) 2053 (nlines (floor sv-height char-height)) 2054 (point (hi::current-point))) 2055 (or (hi::line-offset point (* n nlines)) 2056 (if (< n 0) 2057 (hi::buffer-start point) 2058 (hi::buffer-end point))))) 2110 2059 2111 2060 (defmethod hemlock::center-text-pane ((pane text-pane)) 2112 (#/centerSelectionInVisibleArea: (text-pane-text-view pane) +null-ptr+)) 2061 (#/performSelectorOnMainThread:withObject:waitUntilDone: 2062 (text-pane-text-view pane) 2063 (@selector #/centerSelectionInVisibleArea:) 2064 +null-ptr+ 2065 t)) 2113 2066 2114 2067 … … 2137 2090 2138 2091 2092 (defun nsstring-for-nsstring-encoding (ns) 2093 (let* ((iana (iana-charset-name-of-nsstringencoding ns))) 2094 (if (%null-ptr-p iana) 2095 (#/stringWithFormat: ns:ns-string #@"{%@}" 2096 (#/localizedNameOfStringEncoding: ns:ns-string ns)) 2097 iana))) 2098 2139 2099 ;;; Return a list of :<NSS>tring<E>ncodings, sorted by the 2140 2100 ;;; (localized) name of each encoding. … … 2151 2111 (= #$NSOrderedAscending 2152 2112 (#/localizedCompare: 2153 ( #/localizedNameOfStringEncoding: ns:ns-string x)2154 ( #/localizedNameOfStringEncoding: ns:ns-string y))))))2113 (nsstring-for-nsstring-encoding x) 2114 (nsstring-for-nsstring-encoding y)))))) 2155 2115 (ids id)))))))) 2156 2116 … … 2166 2126 (#/setTag: (#/itemAtIndex: popup 0) 0) 2167 2127 (dolist (id id-list) 2168 (#/addItemWithTitle: popup ( #/localizedNameOfStringEncoding: ns:ns-string id))2128 (#/addItemWithTitle: popup (nsstring-for-nsstring-encoding id)) 2169 2129 (#/setTag: (#/lastItem popup) id)) 2170 2130 (when preferred-encoding … … 2206 2166 ;;; This needs to run on the main thread. 2207 2167 (objc:defmethod (#/updateHemlockSelection :void) ((self hemlock-text-storage)) 2208 (let* ((string (#/ string self))2168 (let* ((string (#/hemlockString self)) 2209 2169 (buffer (buffer-cache-buffer (hemlock-buffer-string-cache string))) 2210 2170 (hi::*buffer-gap-context* (hi::buffer-gap-context buffer)) … … 2283 2243 (#/replaceCharactersInRange:withString: textstorage selectedrange string))))) 2284 2244 2285 2245 (defun hi::edit-definition (name) 2246 (let* ((info (get-source-files-with-types&classes name))) 2247 (if info 2248 (if (cdr info) 2249 (edit-definition-list name info) 2250 (edit-single-definition name (car info)))))) 2251 2252 2253 (defun find-definition-in-document (name indicator document) 2254 (let* ((buffer (hemlock-document-buffer document)) 2255 (hi::*buffer-gap-context* (hi::buffer-gap-context buffer))) 2256 (hemlock::find-definition-in-buffer buffer name indicator))) 2257 2258 2259 (defstatic *edit-definition-id-map* (make-id-map)) 2260 2261 ;;; Need to force things to happen on the main thread. 2262 (defclass cocoa-edit-definition-request (ns:ns-object) 2263 ((name-id :foreign-type :int) 2264 (info-id :foreign-type :int)) 2265 (:metaclass ns:+ns-object)) 2266 2267 (objc:defmethod #/initWithName:info: 2268 ((self cocoa-edit-definition-request) 2269 (name :int) (info :int)) 2270 (#/init self) 2271 (setf (slot-value self 'name-id) name 2272 (slot-value self 'info-id) info) 2273 self) 2274 2275 (objc:defmethod (#/editDefinition: :void) 2276 ((self hemlock-document-controller) request) 2277 (let* ((name (id-map-free-object *edit-definition-id-map* (slot-value request 'name-id))) 2278 (info (id-map-free-object *edit-definition-id-map* (slot-value request 'info-id)))) 2279 (destructuring-bind (indicator . pathname) info 2280 (let* ((namestring (native-translated-namestring pathname)) 2281 (url (#/initFileURLWithPath: 2282 (#/alloc ns:ns-url) 2283 (%make-nsstring namestring))) 2284 (document (#/openDocumentWithContentsOfURL:display:error: 2285 self 2286 url 2287 nil 2288 +null-ptr+))) 2289 (unless (%null-ptr-p document) 2290 (if (= (#/count (#/windowControllers document)) 0) 2291 (#/makeWindowControllers document)) 2292 (find-definition-in-document name indicator document) 2293 (#/updateHemlockSelection (slot-value document 'textstorage)) 2294 (#/showWindows document)))))) 2295 2296 (defun edit-single-definition (name info) 2297 (let* ((request (make-instance 'cocoa-edit-definition-request 2298 :with-name (assign-id-map-id *edit-definition-id-map* name) 2299 :info (assign-id-map-id *edit-definition-id-map* info)))) 2300 (#/performSelectorOnMainThread:withObject:waitUntilDone: 2301 (#/sharedDocumentController ns:ns-document-controller) 2302 (@selector #/editDefinition:) 2303 request 2304 t))) 2305 2306 2307 (defun edit-definition-list (name infolist) 2308 (make-instance 'sequence-window-controller 2309 :sequence infolist 2310 :result-callback #'(lambda (info) 2311 (edit-single-definition name info)) 2312 :key #'car 2313 :title (format nil "Definitions of ~s" name))) 2314 2315 2316 2286 2317 2287 2318
Note:
See TracChangeset
for help on using the changeset viewer.
