[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: MCL - Publish & Subscribe

>We previously sent the message below to info-mcl.  The code results with a "not
>a valid section type" error, which we cannot get around.  Ideally, we are
>looking for a working example of publish and subscribe using MCL.  If we cannot
>get this resolved in the next few weeks, the first release of our product will
>not have Publish and Subscribe.  After our info-mcl message, we received
>requests from other MCL customers for a working example.  Please help!  Thank
>;;;  Are there any examples of using publish and subscribe in MCL?
>;;;  The following piece of code always gets error code -451 when
>;;;  trying to create a new section.  I've tried to subscribe to Excel and
>;;;  Word editions with the same result.  Can anyone tell me what's
>;;;  wrong with it?
>  (require-interface :appleevents)
>  (require-interface :editions)
>  (traps::_initeditionpack)  ;; only run once
>  (setf reply (make-record (:newsubscriberreply :storage :pointer)))
>  (rset reply :newsubscriberreply.formatsmask  (+ #$kpictformatmask
>  (traps::_getlasteditioncontainerused (rref reply
>  (traps::_newsubscriberdialog reply)
>  (rlet ((kind :signed-byte)
>         (mode :signed-integer)
>         (id :signed-long)
>         (section (:pointer (make-record section (:sectionrecord :storage
>    (%put-byte kind  #$stpublisher 0)
>    (%put-long id 177 0)
>    (%put-word mode #$sumautomatic 0)
>    (let* ((code (traps::_newsection
>                  (rref reply :newsubscriberreply.container)
>                  (%null-ptr) ;;this document
>                  kind
>                  177
>                  mode
>                  section)))
>      (format t "~%code=~a" code)
>      (with-dereferenced-handles
>        ((ctlh (%get-ptr section)))
>        (if (%null-ptr-p ctlh)
>          (format t "~%have a null pointer")
>          (format t "~%BINGO!"))
>        )
>      )
>    )
>  )

There are a couple of problems.

1) You need to use gestalt to check for the existence of the Edition
   Manager before calling #_InitEditionPack. You should also check the
   result of (#_InitEditionPack) to make sure that there was room in
   the System heap for the Edition Manager to load.

2) I prefer the style of letting traps autoload to the style of
   using require-interface and traps::_xxx. You use #$xxx for constants,
   why not #_xxx for traps.

3) The "kind", "sectionID", and "initalMode" args to #_NewSection are
   not VAR parameters. They should be passed directly as integers.

4) You allocated REPLY from the Mac heap with MAKE-RECORD, but never
   freed that storage. Better to use RLET.

5) MCL has a bug that it passes byte parameters to stack traps
   incorrectly. I am considering a patch for this, but in the meantime
   you need to left shift such parameters 8 bits (the "kind" parameter
   to #_NewSection is :signed-byte. _CallEditionOpenerProc & _CallFormatIOProc
   also take a "selector" arg which is :unsigned-byte). This is probably
   what confused you most.

I managed to create a new section to an edition that I created with
MicroSoft Word with the following code:


; Set true if the edition manager is loaded
(defvar *edition-manager-present*)

; DEF-LOAD-POINTERS will make sure you check for and initialize
; the Edition Manager whenever your (saved) application opens.
(def-load-pointers *edition-manager-present* ()
  (let ((res (ccl::gestalt #$gestaltEditionMgrAttr)))
    (setq *edition-manager-present*
          (and res
               (logbitp #$gestaltEditionMgrPresent res)
               (eql 0 (#_InitEditionPack))))))

; Here's your code, prettied up a bit.
; I also changed the mode arg for #_NewSection to #$sumManual.
; To use #$sumAutomatic, you need to be prepared to process the
; "Section Read" AppleEvent (though it may not be sent until you
; #_AddSectionAliasPair. I don't know).
(defun new-subscriber-section ()
  (unless *edition-manager-present*
    (error "There is no edition manager"))
  (rlet ((reply :NewSubscriberReply
                :formatsMask (+ #$kpictformatmask #$ktextformatmask))
         (section :pointer))
    (#_GetLastEditionContainerUsed (pref reply :newsubscriberreply.container))
    (let ((code (#_newsubscriberdialog reply)))
      (unless (eql 0 code) (ccl::%err-disp code))
      (when (pref reply :newSubscriberReply.canceled)
        (return-from new-subscriber-section nil))
      (setq code (#_NewSection
                  (pref reply :newsubscriberreply.container)
                  (%null-ptr)             ; no document
                  (ash #$stSubscriber 8)  ; kind (left shifted for MCL bug)
                  177                     ; id
                  #$sumManual             ; mode
      (unless (eql code 0)
        (ccl::%err-disp code))
      (let ((result (%get-ptr section)))
        (if (%null-ptr-p result)
            (format t "~%have a null pointer")
            (format t "~%BINGO!")