home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / MacPerl / MPEditions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-09  |  38.9 KB  |  1,426 lines

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPEditions.c    -
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPEditions.c,v $
  12. Revision 1.2  1994/05/04  02:50:54  neeri
  13. Fix segment names.
  14.  
  15. Revision 1.1  1994/02/27  23:00:31  neeri
  16. Initial revision
  17.  
  18. Revision 0.3  1993/09/18  00:00:00  neeri
  19. Runtime
  20.  
  21. Revision 0.2  1993/05/30  00:00:00  neeri
  22. Support Console Windows
  23.  
  24. Revision 0.1  1993/05/29  00:00:00  neeri
  25. Compiles correctly
  26.  
  27. *********************************************************************/
  28.  
  29. #include <OSUtils.h>
  30. #include <Resources.h>
  31. #include <Errors.h>
  32. #include <AppleEvents.h>
  33.  
  34. #include "MPEditions.h"
  35.  
  36. #ifndef RUNTIME
  37.  
  38. /**-----------------------------------------------------------------------
  39.         Name:         GetERefCon
  40.         Purpose:        Return the sectHandle (our own type) stored in
  41.                         the refcon of the SectionRecord.
  42.     -----------------------------------------------------------------------**/
  43.  
  44. #if !defined(powerc) && !defined(__powerc)
  45. #pragma segment Editions
  46. #endif
  47.  
  48. pascal SectHandle GetERefCon(SectionHandle EMSection)
  49. {
  50.     SectHandle aSectHandle;
  51.  
  52.     aSectHandle = (SectHandle)(*EMSection)->refCon;
  53.     return(aSectHandle);
  54. }
  55.  
  56. /**-----------------------------------------------------------------------
  57. Name:         SetERefCon
  58. Purpose:        Store a handle to our own SectRecord in the refcon
  59.                 field of the SectionRecord.
  60. -----------------------------------------------------------------------**/
  61.  
  62. #if !defined(powerc) && !defined(__powerc)
  63. #pragma segment Editions
  64. #endif
  65.  
  66. pascal void SetERefCon(SectionHandle EMSection, SectHandle aSectHandle)
  67. {
  68.     (*EMSection)->refCon = (long)aSectHandle;
  69. }
  70.  
  71. /**-----------------------------------------------------------------------
  72.         Name:         AddSection
  73.         Purpose:        Add our own section record to the document linked
  74.                         list.  Set up the first and last section variables.
  75.     -----------------------------------------------------------------------**/
  76.  
  77. #if !defined(powerc) && !defined(__powerc)
  78. #pragma segment Editions
  79. #endif
  80.  
  81. pascal void AddSection(SectHandle newSection, DPtr aDocument)
  82. {
  83.     if (aDocument->kind != kDocumentWindow)
  84.         return;
  85.         
  86.     /*
  87.         add the section to the document
  88.     */
  89.     aDocument->u.reg.numSections += 1;
  90.  
  91.     /*
  92.         if not NIL, add the new section to the list after the last element
  93.     */
  94.  
  95.     if (aDocument->u.reg.lastSection)
  96.         (*(aDocument->u.reg.lastSection))->fNextSection = newSection;
  97.     else
  98.         aDocument->u.reg.firstSection = newSection;
  99.  
  100.     aDocument->u.reg.lastSection = newSection;
  101.     (*newSection)->fNextSection  = nil;
  102. }
  103.  
  104. /**-----------------------------------------------------------------------
  105.         Name:         CreateSection
  106.         Purpose:        Create a new section record to hold a Publisher or
  107.                         Subscriber. Link this to the SectionRecord.
  108.     -----------------------------------------------------------------------**/
  109.  
  110. #if !defined(powerc) && !defined(__powerc)
  111. #pragma segment Editions
  112. #endif
  113.  
  114. pascal void CreateSection(SectionHandle   EMSection,
  115.                                   short           sectionID,
  116.                                   short           theStart,
  117.                                   short           theEnd,
  118.                                   DPtr            aDocument,
  119.                                   RgnHandle       theBorder)
  120.  
  121. {
  122.     SectHandle    newSection;
  123.  
  124.     if (aDocument->kind != kDocumentWindow)
  125.         return;
  126.         
  127.     /*
  128.         create a section and call AddSection to add it to the list
  129.     */
  130.     newSection = (SectHandle)NewHandle(sizeof(SectRec));
  131.  
  132.     if (newSection) {
  133.         (*newSection)->fSectionID   = sectionID;
  134.         (*newSection)->fNextSection = nil;
  135.         (*newSection)->fSectHandle  = EMSection;
  136.         (*newSection)->fStart       = theStart;
  137.         (*newSection)->fEnd         = theEnd;
  138.         (*newSection)->fCount       = theEnd - theStart;
  139.         (*newSection)->fBorderRgn   = theBorder;
  140.         (*newSection)->fDocument    = aDocument;
  141.  
  142.         /*
  143.             put a reference to our section record in the section's refCon field
  144.         */
  145.  
  146.         SetERefCon(EMSection, newSection);
  147.         AddSection(newSection, aDocument);
  148.     }
  149. }
  150.  
  151.  /**-----------------------------------------------------------------------
  152.         Name:         DeleteASection
  153.         Purpose:        Delete the section from the list.
  154.                         Called when 'Cancel Publisher/Subscriber is chosen in
  155.                         the 'Section Options' dialog.
  156.     -----------------------------------------------------------------------**/
  157.  
  158. #if !defined(powerc) && !defined(__powerc)
  159.     #pragma segment Editions
  160. #endif
  161.  
  162. pascal void DeleteASection(SectHandle sectToDelete, DPtr theDoc)
  163. {
  164.     SectHandle    currSect;
  165.     SectHandle    prevSect;
  166.  
  167.     if (theDoc->kind != kDocumentWindow)
  168.         return;
  169.  
  170.     currSect = theDoc->u.reg.firstSection;
  171.     prevSect = nil;
  172.  
  173.     while (currSect) {
  174.         if (currSect == sectToDelete) {
  175.             /*
  176.                 unlink the section from the list
  177.             */
  178.             if (prevSect)
  179.                 (*prevSect)->fNextSection = (*currSect)->fNextSection;
  180.  
  181.             if (currSect == theDoc->u.reg.firstSection)
  182.                 theDoc->u.reg.firstSection = nil;
  183.  
  184.             if (currSect == theDoc->u.reg.lastSection)
  185.                 theDoc->u.reg.lastSection = nil;
  186.         }
  187.         prevSect = currSect;
  188.         currSect = (*currSect)->fNextSection;
  189.     }
  190. }
  191.  
  192. /**-----------------------------------------------------------------------
  193.         Name:         ReadASection
  194.         Purpose:        Read in a section from disk
  195.                         Read in the rAliasType and rsectionType resources and register
  196.                         the section with the document.
  197.     -----------------------------------------------------------------------**/
  198.  
  199. #if !defined(powerc) && !defined(__powerc)
  200. #pragma segment Editions
  201. #endif
  202.  
  203. pascal void ReadASection(SectHandle aSectHandle)
  204. {
  205.     SectionHandle     aSectionHandle;
  206.     AliasHandle         anAlias;
  207.     OSErr               err;
  208.     FSSpec            myFSSpec;
  209.     Boolean            ignore;
  210.  
  211.     /*read in the rAliasType and rSectionType resources*/
  212.  
  213.     aSectionHandle = (SectionHandle)Get1Resource(rSectionType, (*aSectHandle)->fSectionID);
  214.     err            = HandToHand((Handle *)&aSectionHandle);
  215.     (*aSectHandle)->fSectHandle = aSectionHandle;
  216.     SetERefCon(aSectionHandle, aSectHandle);
  217.  
  218.     anAlias = (AliasHandle)Get1Resource(rAliasType, (*aSectHandle)->fSectionID);
  219.     err     = HandToHand((Handle *)&anAlias);
  220.     (*aSectionHandle)->alias = anAlias;
  221.  
  222.     /*now register the section*/
  223.  
  224.     err = ResolveAlias(nil, (*aSectionHandle)->alias, &myFSSpec, &ignore);
  225.     if (err) {
  226.         ShowError((StringPtr) "\pResolve Alias", err);
  227.         return;
  228.     }
  229.  
  230.     err = RegisterSection(&myFSSpec, aSectionHandle, &ignore);
  231.  
  232.     if ((err) && (err != notThePublisherWrn) && (err != multiplePublisherWrn)) {
  233.         ShowError((StringPtr) "\pRegisterSection", err);
  234.         return;
  235.     }
  236.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText,
  237.                          (*aSectHandle)->fStart,
  238.                                     (*aSectHandle)->fEnd,
  239.                                     &(*aSectHandle)->fBorderRgn);
  240.     InvalRgn((*aSectHandle)->fBorderRgn);
  241. }
  242.  
  243. /**-----------------------------------------------------------------------
  244. Name:         ReadAllSectionResources
  245. Purpose:        Call the above routine to read in the resources for
  246.                 each section in the document.
  247. -----------------------------------------------------------------------**/
  248. #if !defined(powerc) && !defined(__powerc)
  249. #pragma segment Editions
  250. #endif
  251.  
  252. pascal void ReadAllSectionResources(DPtr aDoc)
  253. {
  254.     SectHandle  theSection;
  255.  
  256.     if (aDoc->kind != kDocumentWindow)
  257.         return;
  258.         
  259.     /*read in each section resource*/
  260.  
  261.     theSection = aDoc->u.reg.firstSection;
  262.     while (theSection) {
  263.         ReadASection(theSection);
  264.         theSection = (*theSection)->fNextSection;
  265.     }
  266. }
  267.  
  268. /**-----------------------------------------------------------------------
  269. Name:         ReadSectionRecords
  270. Purpose:        Read in all the 'sect' resources and form list
  271.                 of sections in the document.    This is called from the
  272.                 main read document routine.
  273. -----------------------------------------------------------------------**/
  274. #if !defined(powerc) && !defined(__powerc)
  275. #pragma segment Editions
  276. #endif
  277.  
  278. pascal void ReadSectionRecords(DPtr aDoc)
  279. {
  280.     short         theID;
  281.     SectHandle    aSectHandle;
  282.     OSErr         err;
  283.     short         theCount;
  284.  
  285.     /*read in all the 'sect' resources for our document's sections*/
  286.  
  287.     if (aDoc->kind != kDocumentWindow)
  288.         return;
  289.         
  290.     theCount = aDoc->u.reg.numSections;
  291.     if (theCount == 0)
  292.         return;
  293.  
  294.     aDoc->u.reg.numSections = 0;
  295.     for (theID = 1; theID <= theCount; theID++) {
  296.         aSectHandle = (SectHandle)Get1Resource('SECT', theID);
  297.         err = HandToHand((Handle *)&aSectHandle);
  298.  
  299.         /*now add it to the list*/
  300.  
  301.         if (aSectHandle)
  302.             AddSection(aSectHandle, aDoc);
  303.  
  304.         /*here we should recalculate the region for the bounds*/
  305.  
  306.         (*aSectHandle)->fBorderRgn = NewRgn();
  307.  
  308.         (*aSectHandle)->fDocument  = aDoc;
  309.     }
  310. }
  311.  
  312. /**-----------------------------------------------------------------------
  313.         Name:             SaveASection
  314.         Purpose:        Write out the 'sect', rAliasType and rSectionType resources
  315.                                 to file.    Called when the document is saved.
  316.     -----------------------------------------------------------------------**/
  317.  
  318. #if !defined(powerc) && !defined(__powerc)
  319. #pragma segment Editions
  320. #endif
  321.  
  322. pascal void SaveASection(SectHandle aSection, short count)
  323. {
  324.     SectionHandle  EMSection;
  325.     OSErr          err;
  326.     Handle         tempHandle;
  327.  
  328.     HLock((Handle)aSection);
  329.  
  330.     /*save this section as its component rAliasType and rSectionType resource*/
  331.     /*also save as our own section record as a 'sect' resource*/
  332.  
  333.     EMSection  = (*aSection)->fSectHandle;
  334.     tempHandle = (Handle)EMSection;
  335.     err        = HandToHand(&tempHandle);
  336.  
  337.     HLock((Handle)EMSection);
  338.     AddResource(tempHandle, rSectionType, (*EMSection)->sectionID, (StringPtr) "\p");
  339.     err = ResError();
  340.     if (err) {
  341.         ShowError((StringPtr) "\pAddResource- rSectionType", err);
  342.         return;
  343.     }
  344.  
  345.     /*now add the alias resource*/
  346.     tempHandle = (Handle)(*EMSection)->alias;
  347.     err = HandToHand(&tempHandle);
  348.     AddResource(tempHandle, rAliasType, (*EMSection)->sectionID, (StringPtr) "\p");
  349.     if (err) {
  350.         ShowError((StringPtr) "\pAddResource- rAliasType", err);
  351.         return;
  352.     }
  353.  
  354.     /*now add our own resource- for now all the record, although we only need a few fields*/
  355.     tempHandle = (Handle)aSection;
  356.     err  = HandToHand(&tempHandle);
  357.     AddResource(tempHandle, 'SECT', count, (StringPtr) "\p");
  358.     if (err) {
  359.         ShowError((StringPtr) "\pAddResource- SECT", err);
  360.         return;
  361.     }
  362.  
  363.     HUnlock((Handle)aSection);
  364.     HUnlock((Handle)EMSection);
  365. }
  366.  
  367.  /**-----------------------------------------------------------------------
  368.         Name:         SaveSections
  369.         Purpose:        Called to go down to the section list and call SaveASection
  370.                         for each one.
  371.     -----------------------------------------------------------------------**/
  372.  
  373. #if !defined(powerc) && !defined(__powerc)
  374. #pragma segment Editions
  375. #endif
  376.  
  377. pascal void SaveSections(DPtr aDocument)
  378. {
  379.     OSErr          err;
  380.     SectHandle     currSection;
  381.     short          count;
  382.  
  383.     if (aDocument->kind != kDocumentWindow)
  384.         return;
  385.  
  386.     /*go down the list and save each of the sections*/
  387.     /*the resource file is already open for writing*/
  388.  
  389.     count = 1;
  390.     err = ResError();
  391.     if (err) {
  392.         ShowError((StringPtr) "\pHOpenResFile", err);
  393.         return;
  394.     }
  395.  
  396.     /*now go down the list*/
  397.     currSection = aDocument->u.reg.firstSection;
  398.     while (currSection) {
  399.         SaveASection(currSection, count);
  400.         currSection = (*currSection)->fNextSection;
  401.         count ++;
  402.     }
  403. }
  404.  
  405. /**-----------------------------------------------------------------------
  406.     Name:         AssocAllSections
  407.     Purpose:        Associate all the sections in a document with the document.
  408.                     Called on a SaveAs.
  409. -----------------------------------------------------------------------**/
  410.  
  411. #if !defined(powerc) && !defined(__powerc)
  412. #pragma segment Editions
  413. #endif
  414.  
  415. pascal void AssocAllSections(DPtr theDoc)
  416. {
  417.     SectHandle    aSection;
  418.     SectionHandle EMSection;
  419.     OSErr         err;
  420.  
  421.     if (theDoc->kind != kDocumentWindow)
  422.         return;
  423.  
  424.     /*called by DoSaveAs.    Make sure sections are registered with this document*/
  425.     aSection = theDoc->u.reg.firstSection;
  426.     while (aSection) {
  427.         EMSection = (*aSection)->fSectHandle;
  428.         err = AssociateSection(EMSection, &theDoc->theFSSpec);
  429.         aSection  = (*aSection)->fNextSection;
  430.     }
  431. }
  432. #endif
  433.  
  434. /**-----------------------------------------------------------------------
  435.         Name:         KeyOKinSubscriber
  436.         Purpose:        Detects arrow keys.
  437.  -----------------------------------------------------------------------**/
  438. #define kChLeft    28
  439. #define kChRight    29
  440. #define kChUp        30
  441. #define kChDown    31
  442.  
  443. #if !defined(powerc) && !defined(__powerc)
  444. #pragma segment Editions
  445. #endif
  446.  
  447. pascal Boolean KeyOKinSubscriber(char whatKey)
  448. {
  449.     return( (whatKey==kChUp) || (whatKey==kChDown) || (whatKey==kChLeft) || (whatKey==kChRight));
  450. } /*KeyOKinSubscriber*/
  451.  
  452. #ifndef RUNTIME
  453.  
  454. /**-----------------------------------------------------------------------
  455.         Name:         ShiftSection
  456.         Purpose:        Moves a section by howMany characters.
  457.  -----------------------------------------------------------------------**/
  458.  
  459. pascal void ShiftSection(SectHandle whichSection, short howMany)
  460. {
  461.     (*whichSection)->fStart += howMany;
  462.     (*whichSection)->fEnd   += howMany;
  463. }  /* ShiftSection */
  464.  
  465. /**-----------------------------------------------------------------------
  466. Name:         DoSectionRecalc
  467. Purpose:        Keeps track of the positions of the sections.
  468. -----------------------------------------------------------------------**/
  469.  
  470. #if !defined(powerc) && !defined(__powerc)
  471. #pragma segment Editions
  472. #endif
  473.  
  474. pascal void DoSectionRecalc(DPtr theDoc, short toAdd)
  475. {
  476.     short        theStartPos;
  477.     short        theEndPos;
  478.     short        oldSectionStart;
  479.     short        oldSectionEnd;
  480.     SectHandle   aSection;
  481.     Boolean      wasChanged;
  482.     GrafPtr      oldPort;
  483.  
  484.     if (theDoc->kind != kDocumentWindow)
  485.         return;
  486.  
  487.     /*
  488.         Work thru all sections -
  489.         1) Those spanning area of modification get modified or zapped
  490.         2) Those after get shifted back or forwards.
  491.  
  492.         Sorry it is so complicated - there's a lot of possibilities
  493.     */
  494.     theStartPos = (*(theDoc->theText))->selStart;
  495.     theEndPos   = (*(theDoc->theText))->selEnd;
  496.  
  497.     aSection = theDoc->u.reg.firstSection;
  498.     while (aSection) {
  499.         wasChanged = true;
  500.  
  501.         oldSectionEnd   = (*aSection)->fEnd;
  502.         oldSectionStart = (*aSection)->fStart;
  503.  
  504.         if (theEndPos < (*aSection)->fStart)
  505.             ShiftSection(aSection, toAdd - (theEndPos-theStartPos));
  506.         else if (theStartPos == (*aSection)->fStart)
  507.             if (theEndPos == (*aSection)->fStart)
  508.                 ShiftSection(aSection, toAdd - (theEndPos-theStartPos));
  509.             else if (theEndPos >= (*aSection)->fEnd) /* section becomes pasted text */
  510.                 (*aSection)->fEnd = (*aSection)->fStart + toAdd;
  511.             else                                                                    /* insert pasted text */
  512.                 (*aSection)->fEnd = (*aSection)->fEnd + toAdd - (theEndPos-theStartPos);
  513.         else if (theStartPos< (*aSection)->fStart)
  514.             (*aSection)->fStart = theStartPos + toAdd; /* move start to end of pasted text */
  515.         else if (theStartPos <= (*aSection)->fEnd)
  516.             if (theEndPos >= (*aSection)->fEnd) /* end of section becomes pasted text */
  517.                 (*aSection)->fEnd = theStartPos + toAdd ;
  518.             else                                                                    /* insert pasted text into section */
  519.                 (*aSection)->fEnd = (*aSection)->fEnd + toAdd - (theEndPos-theStartPos);
  520.         else
  521.             wasChanged = false;
  522.  
  523.         if (wasChanged) {
  524.             (*aSection)->fCount = (*aSection)->fEnd - (*aSection)->fStart;
  525.  
  526.             if (theDoc->u.reg.showBorders) { /* Force an update of the borders - later*/
  527.                 GetPort(&oldPort);
  528.                 SetPort(theDoc->theWindow);
  529.  
  530.                 SetSelectionRgn(theDoc->theText,
  531.                                      oldSectionStart,
  532.                                      oldSectionEnd,
  533.                                      &(*aSection)->fBorderRgn);
  534.                 InvalRgn((*aSection)->fBorderRgn);
  535.  
  536.                 SetPort(oldPort);
  537.             }
  538.         }
  539.  
  540.         aSection = (*aSection)->fNextSection;
  541.     }
  542. }  /* DoSectionRecalc */
  543.  
  544. /**-----------------------------------------------------------------------
  545. Name:         ReadAnEdition
  546. Purpose:        Read the latest version of an edition from disk.
  547. -----------------------------------------------------------------------**/
  548.  
  549. #if !defined(powerc) && !defined(__powerc)
  550. #pragma segment Editions
  551. #endif
  552.  
  553. pascal void ReadAnEdition(SectionHandle mySectHdl)
  554. {
  555.     SectHandle    aSectHandle;
  556.     EditionRefNum theRefNum;
  557.     OSErr         err;
  558.     Ptr           p;
  559.     Size          cutSize;
  560.  
  561.     p = nil;
  562.  
  563.     if (!mySectHdl) {
  564.         ShowError((StringPtr) "\pmySectHdl is NIL", 0);
  565.         return;
  566.     }
  567.  
  568.     aSectHandle = (SectHandle)GetERefCon(mySectHdl);
  569.     if (!aSectHandle) {
  570.         ShowError((StringPtr) "\paSectHandle is NIL", 0);
  571.         return;
  572.     }
  573.  
  574.     GetDateTime(&(*mySectHdl)->mdDate);
  575.  
  576.     /*read a subscriber in from disk.    Usually in response to a sectionread event*/
  577.  
  578.     if (err = OpenEdition(mySectHdl, &theRefNum)) {
  579.         ShowError((StringPtr) "\pOpenEdition in ReadAnEdition", err);
  580.         return;
  581.     }
  582.  
  583.     if (err = EditionHasFormat(theRefNum, 'TEXT', &cutSize)) {
  584.         ShowError((StringPtr) "\pEditionHasFormat in ReadAnEdition", err);
  585.         return;
  586.     }
  587.  
  588.     if (err = SetEditionFormatMark(theRefNum, 'TEXT', 0)) {
  589.         ShowError((StringPtr) "\pSetEditionFormatMark in ReadAnEdition", err);
  590.         return;
  591.     }
  592.  
  593.     /*set up a buffer for the text we're going to read in*/
  594.     p = NewPtr(cutSize);
  595.     if (!p) {
  596.         ShowError((StringPtr) "\pInsufficient memory to read edition", MemError());
  597.         return;
  598.     }
  599.  
  600.     if (err = ReadEdition(theRefNum, 'TEXT', p, &cutSize)) {
  601.         ShowError((StringPtr) "\pReadEdition", err);
  602.         return;
  603.     }
  604.  
  605.     if (err = CloseEdition(theRefNum, true)) {
  606.         ShowError((StringPtr) "\pCloseEdition", err);
  607.         return;
  608.     }
  609.  
  610.     /*
  611.         Ensure this section has a region and invalidate the old region
  612.     */
  613.  
  614.     if ((*aSectHandle)->fBorderRgn == nil)
  615.         (*aSectHandle)->fBorderRgn = NewRgn();
  616.  
  617.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText,
  618.                          (*aSectHandle)->fStart,
  619.                          (*aSectHandle)->fEnd,
  620.                          &(*aSectHandle)->fBorderRgn);
  621.  
  622.     InvalRgn((*aSectHandle)->fBorderRgn);
  623.  
  624.     /*now insert the text in the right place by setting the selection range*/
  625.     /*we want this to act like paste, but without putting the contents on the clipboard*/
  626.     /*so we have to delete the current selection range and then insert our new text*/
  627.  
  628.     /*
  629.         Also fixup section info. for other moved sections
  630.     */
  631.  
  632.     TESetSelect((*aSectHandle)->fStart, (*aSectHandle)->fEnd, ((*aSectHandle)->fDocument)->theText);
  633.     DoSectionRecalc((*aSectHandle)->fDocument, cutSize);
  634.  
  635.     TEDelete(((*aSectHandle)->fDocument)->theText);
  636.     TEInsert(p, cutSize, ((*aSectHandle)->fDocument)->theText);
  637.  
  638.     /*
  639.         Now a little fix up - if the section was previously empty the
  640.         DoSectionRecalc will have put the text in before the section.
  641.         It's like that so you can type in before a subscriber in an
  642.         otherwise empty document. So now pull the start of this section
  643.         back to include the text we just added.
  644.     */
  645.  
  646.     (*aSectHandle)->fStart = (*aSectHandle)->fEnd - cutSize;
  647.  
  648.     /*
  649.         Force redraw of this region
  650.     */
  651.  
  652.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText, 
  653.                          (*aSectHandle)->fStart,
  654.                          (*aSectHandle)->fEnd,
  655.                          &(*aSectHandle)->fBorderRgn);
  656.  
  657.     InvalRgn((*aSectHandle)->fBorderRgn);
  658.  
  659.     DisposPtr(p);
  660. }
  661.  
  662. /**-----------------------------------------------------------------------
  663. Name:         WriteAnEdition
  664. Purpose:        Write out the latest version of an Edition.
  665.                 Called on a Save and on selecting WriteEdition now from
  666.                 the Publisher Options dialog.
  667. -----------------------------------------------------------------------**/
  668.  
  669. #if !defined(powerc) && !defined(__powerc)
  670. #pragma segment Editions
  671. #endif
  672.  
  673. pascal void WriteAnEdition(SectionHandle mySectHdl)
  674. {
  675.     OSErr           err;
  676.     SectHandle      aSectHandle;
  677.     EditionRefNum   theRefNum;
  678.     Handle          aHandle;
  679.     FSSpecPtr       theFSSpecPtr;
  680.  
  681.     aSectHandle = (SectHandle)GetERefCon(mySectHdl);
  682.     /*alter the modification date for the section*/
  683.     GetDateTime(&(*mySectHdl)->mdDate);
  684.     /*write out the edition.  Assume that it is a publisher for now*/
  685.     /*subscribers will be opened for writing with OpenEdition*/
  686.  
  687.     if (((*aSectHandle)->fDocument)->u.reg.everSaved == false)
  688.         theFSSpecPtr = nil;
  689.     else
  690.         theFSSpecPtr = &((*aSectHandle)->fDocument)->theFSSpec;
  691.  
  692.     if (err = OpenNewEdition(mySectHdl, MPAppSig, theFSSpecPtr, &theRefNum)) {
  693.         ShowError((StringPtr) "\pOpenNewEdition", err);
  694.         return;
  695.     }
  696.  
  697.     if (err = SetEditionFormatMark(theRefNum, 'TEXT', 0)) {
  698.         ShowError((StringPtr) "\pSetEditionFormatMark", err);
  699.         return;
  700.     }
  701.  
  702.     /*now get a handle to the text to be written out*/
  703.     /*use the same start and end positions for now, increasing and decreasing*/
  704.     /*the selection will be implemented later*/
  705.  
  706.     aHandle = GetHandleToText(((*aSectHandle)->fDocument)->theText,
  707.                                       (*aSectHandle)->fStart,
  708.                                       (*aSectHandle)->fEnd);
  709.     HLock(aHandle);
  710.  
  711.     /*make sure the count is up to date*/
  712.     (*aSectHandle)->fCount = (*aSectHandle)->fEnd - (*aSectHandle)->fStart;
  713.  
  714.     if (err = WriteEdition(theRefNum, 'TEXT', *aHandle, (*aSectHandle)->fCount)) {
  715.         ShowError((StringPtr) "\pWriteEdition", err);
  716.         return;
  717.     }
  718.     HUnlock(aHandle);
  719.  
  720.     /*remember to save the section and alias records as resources later*/
  721.  
  722.     /*now close the edition*/
  723.  
  724.     if (err = CloseEdition(theRefNum, true)) {
  725.         ShowError((StringPtr) "\pCloseEdition", err);
  726.         return;
  727.     }
  728.  
  729.     /*
  730.         Clean Up
  731.     */
  732.  
  733.     DisposHandle(aHandle);
  734. }     /*WriteAnEdition*/
  735.  
  736. /**-----------------------------------------------------------------------
  737.     Name:         WriteAllEditions
  738.     Purpose:        Go down the list and call WriteAnEdition
  739. -----------------------------------------------------------------------**/
  740.  
  741. #if !defined(powerc) && !defined(__powerc)
  742. #pragma segment Editions
  743. #endif
  744.  
  745. pascal void WriteAllEditions(DPtr aDocument)
  746. {
  747.     SectHandle      aSection;
  748.     SectionHandle   EMSection;
  749.  
  750.     if (aDocument->kind != kDocumentWindow)
  751.         return;
  752.         
  753.     /*called on a Save, to write out all editions*/
  754.     aSection = aDocument->u.reg.firstSection;
  755.  
  756.     while (aSection) {
  757.         EMSection = (*aSection)->fSectHandle;
  758.         if ((*EMSection)->kind == stPublisher)
  759.             WriteAnEdition(EMSection);
  760.         aSection = (*aSection)->fNextSection;
  761.     }
  762. }
  763.  
  764. /**-----------------------------------------------------------------------
  765. Name:         DeRegisterAllSections
  766. Purpose:        Called on cancel Publisher/Subscriber and on a close.
  767. -----------------------------------------------------------------------**/
  768.  
  769. #if !defined(powerc) && !defined(__powerc)
  770. #pragma segment Editions
  771. #endif
  772.  
  773. pascal void DeRegisterAllSections(DPtr aDoc)
  774.   {
  775.         SectHandle      aSection;
  776.         SectionHandle   EMSection;
  777.         OSErr           err;
  778.  
  779.         aSection = aDoc->u.reg.firstSection;
  780.         while (aSection)
  781.             {
  782.                 EMSection = (*aSection)->fSectHandle;
  783.                 err = UnRegisterSection(EMSection);
  784.                 aSection = (*aSection)->fNextSection;
  785.             }
  786.     }
  787.  
  788. /**-----------------------------------------------------------------------
  789. Name:         GetHandleToText
  790. Purpose:        Get a handle to the current text selection.
  791.                 Used to provide a preview on Create Publisher...
  792. -----------------------------------------------------------------------**/
  793.  
  794. #if !defined(powerc) && !defined(__powerc)
  795. #pragma segment Editions
  796. #endif
  797.  
  798. pascal Handle GetHandleToText(TEHandle aTEHandle, short theStart, short theEnd)
  799. {
  800.     OSErr     err;
  801.     Handle    myHandle;
  802.     Ptr       p;
  803.  
  804.     HLock((*aTEHandle)->hText);
  805.     p  = *((*aTEHandle)->hText);
  806.     p  += theStart;
  807.     err = PtrToHand(p, &myHandle, (theEnd - theStart));
  808.     HUnlock((*aTEHandle)->hText);
  809.     return(myHandle);
  810. } /* GetHandleToText */
  811.  
  812. /**-----------------------------------------------------------------------
  813.         Name:         FindLine
  814.         Purpose:        Find the line a character is in.
  815.                         Used to find to calculate the region to use for the Publisher/
  816.                         Subscriber borders.
  817.     -----------------------------------------------------------------------**/
  818.  
  819. #if !defined(powerc) && !defined(__powerc)
  820. #pragma segment Editions
  821. #endif
  822.  
  823. pascal short FindLine(short thePos,TEHandle theTEHandle)
  824. {
  825.     short    index;
  826.     short    theFirstPos;
  827.     short    theNextPos;
  828.  
  829.     index = 0;
  830.  
  831.     do {
  832.         theFirstPos = (*theTEHandle)->lineStarts[index];
  833.         theNextPos  = (*theTEHandle)->lineStarts[index + 1];
  834.         index++;
  835.     } while (! (((thePos >= theFirstPos) && (thePos < theNextPos)) ||
  836.                     (index > (*theTEHandle)->nLines)));
  837.  
  838.     return(index);
  839. }
  840.  
  841. /**-----------------------------------------------------------------------
  842.         Name:         DrawSelectionRgn
  843.         Purpose:        Given a text handle and a start and end position this routine
  844.                         will draw a section border around the selected text.
  845.                         Must allow for the case when the section has no text in it-
  846.                         but we still want to show it as a published section
  847.  -----------------------------------------------------------------------**/
  848.  
  849. pascal void DrawSelectionRegion(TEHandle theTEHandle, short posStart, short posEnd)
  850. {
  851.     RgnHandle  theSelRgn;
  852.     
  853.     theSelRgn = NewRgn();
  854.     
  855.     SetSelectionRgn(theTEHandle, posStart, posEnd,&theSelRgn);
  856.     FrameRgn(theSelRgn);
  857.     
  858.     DisposeRgn(theSelRgn);
  859. } /* DrawSelectionRegion */
  860.  
  861. /**-----------------------------------------------------------------------
  862.         Name:         SetSelectionRgn
  863.         Purpose:        Given a text handle and a start and end position this routine
  864.                         will return the region which is necessary to draw a section
  865.                         border around the selected text.
  866.                         Must allow for the case when the section has no text in it-
  867.                         but we still want to show it as a published section
  868.  -----------------------------------------------------------------------**/
  869.  
  870. #if !defined(powerc) && !defined(__powerc)
  871. #pragma segment Editions
  872. #endif
  873.  
  874. pascal void SetSelectionRgn(TEHandle theTEHandle, short posStart, short posEnd, RgnHandle *theSelRgn)
  875. {
  876.     Point           theStart;
  877.     Point           theEnd;
  878.     short           startLine;
  879.     short           endLine;
  880.     Rect            theRect;
  881.     short           theLeft;
  882.     short           theRight;
  883.     short           theBottom;
  884.     short           theTop;
  885.     short           slineHeight;
  886.     short           elineHeight;
  887.     short           fontAscent;
  888.     TextStyle       theTStyle;
  889.  
  890.     /*first of all find out if the text is on the same line*/
  891.     startLine = FindLine(posStart, theTEHandle);
  892.     endLine   = FindLine(posEnd, theTEHandle);
  893.  
  894.     theStart = TEGetPoint(posStart, theTEHandle);
  895.     theEnd   = TEGetPoint(posEnd, theTEHandle);
  896.  
  897. /*
  898. Get the line height info
  899. */
  900.     TEGetStyle(posStart, &theTStyle, &slineHeight, &fontAscent, theTEHandle);
  901.     TEGetStyle(posEnd,   &theTStyle, &elineHeight, &fontAscent, theTEHandle);
  902.  
  903.     if (startLine == endLine) {
  904.         /*use the start and end points to form the rectangle and draw this into the region*/
  905.         theStart.v -= slineHeight;
  906.         Pt2Rect(theStart, theEnd, &theRect);
  907.         InsetRect(&theRect, - 1, - 1);
  908.         RectRgn(*theSelRgn, &theRect);
  909.     } else {
  910.         theLeft  = (*theTEHandle)->destRect.left;
  911.         theRight = (*theTEHandle)->destRect.right;
  912.         theTop   = theStart.v - slineHeight;
  913.         theBottom  = theEnd.v;
  914.         OpenRgn();
  915.         MoveTo(theStart.h, theStart.v - slineHeight);
  916.         LineTo(theRight, theStart.v - slineHeight);
  917.         LineTo(theRight, theEnd.v - elineHeight);
  918.         LineTo(theEnd.h, theEnd.v - elineHeight);
  919.         LineTo(theEnd.h, theEnd.v);
  920.         LineTo(theLeft, theEnd.v);
  921.         LineTo(theLeft, theStart.v);
  922.         LineTo(theStart.h, theStart.v);
  923.         LineTo(theStart.h, theStart.v - slineHeight);
  924.         CloseRgn(*theSelRgn);
  925.     }
  926.  
  927.     InsetRgn(*theSelRgn, - 2, - 2);
  928. }
  929.  
  930. /**-----------------------------------------------------------------------
  931.         Name:         ShowSectionBorders
  932.         Purpose:        Show the borders for all the sections in a document.
  933.                         Show a Publisher border in 50% gray, a subscriber in 75% gray
  934.  -----------------------------------------------------------------------**/
  935.  
  936. #if !defined(powerc) && !defined(__powerc)
  937. #pragma segment Editions
  938. #endif
  939.  
  940. pascal void ShowSectionBorders(DPtr aDoc)
  941. {
  942.     SectHandle aSection;
  943.  
  944.     if (aDoc->kind != kDocumentWindow)
  945.         return;
  946.         
  947.     PenNormal();
  948.     PenSize(3, 3);
  949.     PenPat(&qd.gray);
  950.     aSection = aDoc->u.reg.firstSection;
  951.     while (aSection) {
  952.         if ((*aSection)->fBorderRgn) {
  953.             SetSelectionRgn(((*aSection)->fDocument)->theText,
  954.                                  (*aSection)->fStart,
  955.                                  (*aSection)->fEnd,
  956.                                  &(*aSection)->fBorderRgn);
  957.  
  958.             if ((*(*aSection)->fSectHandle)->kind == stPublisher)
  959.                 PenPat(&qd.gray);
  960.             else
  961.                 PenPat(&qd.dkGray);
  962.  
  963.             FrameRgn((*aSection)->fBorderRgn);
  964.             PenNormal();
  965.         }
  966.         aSection = (*aSection)->fNextSection;
  967.     }
  968.     PenNormal();
  969. }
  970.  
  971. /**-----------------------------------------------------------------------
  972.         Name:         RecalcBorders
  973.         Purpose:        Recalculate all the borders for the sections in a document.
  974.  -----------------------------------------------------------------------**/
  975.  
  976. #if !defined(powerc) && !defined(__powerc)
  977. #pragma segment Editions
  978. #endif
  979.  
  980. pascal void RecalcBorders(DPtr aDoc, Boolean invalidate)
  981. {
  982.     SectHandle  aSection;
  983.  
  984.     if (aDoc->kind != kDocumentWindow)
  985.         return;
  986.         
  987.     /*go down the section list and recalculate all the borders*/
  988.     aSection = aDoc->u.reg.firstSection;
  989.     while (aSection) {
  990.         if ((*aSection)->fBorderRgn) {
  991.             if (invalidate)
  992.                 InvalRgn((*aSection)->fBorderRgn);
  993.  
  994.             SetSelectionRgn(((*aSection)->fDocument)->theText,
  995.                                  (*aSection)->fStart,
  996.                                  (*aSection)->fEnd,
  997.                                  &(*aSection)->fBorderRgn);
  998.  
  999.             if (invalidate)
  1000.                 InvalRgn((*aSection)->fBorderRgn);
  1001.         }
  1002.         aSection = (*aSection)->fNextSection;
  1003.     }
  1004. }
  1005.  
  1006. /**-----------------------------------------------------------------------
  1007.         Name:         GetSection
  1008.         Purpose:        Given a start and end of a selection- return the section
  1009.                         handle if it is in a Publisher or Subscriber.
  1010.  -----------------------------------------------------------------------**/
  1011.  
  1012. #if !defined(powerc) && !defined(__powerc)
  1013. #pragma segment Editions
  1014. #endif
  1015.  
  1016. pascal SectHandle GetSection(short theStartPos, short theEndPos, DPtr aDoc)
  1017. {
  1018.     SectHandle   foundSection;
  1019.     SectHandle   aSection;
  1020.  
  1021.     /*returns the section handle for the section between theStartPos and theEndPos*/
  1022.  
  1023.     if (aDoc->kind != kDocumentWindow)
  1024.         return nil;
  1025.         
  1026.     foundSection = nil;
  1027.  
  1028.     aSection = aDoc->u.reg.firstSection;
  1029.     while (aSection) {
  1030.         if ((theStartPos >= (*aSection)->fStart) && (theEndPos <= (*aSection)->fEnd))
  1031.             foundSection = aSection;
  1032.         aSection = (*aSection)->fNextSection;
  1033.     }
  1034.  
  1035.     return foundSection;
  1036. }
  1037.  
  1038. /**-----------------------------------------------------------------------
  1039.         Name:         DoTEPasteSectionRecalc
  1040.         Purpose:        Keeps track of the positions of the sections call before a
  1041.                     TEPaste or TEStylPaste.
  1042.  -----------------------------------------------------------------------**/
  1043.  
  1044. pascal void DoTEPasteSectionRecalc(DPtr theDoc)
  1045. {
  1046.     short toAdd;
  1047.  
  1048.     if (theDoc->kind != kDocumentWindow)
  1049.         return;
  1050.         
  1051.     toAdd = TEGetScrapLen();
  1052.     DoSectionRecalc(theDoc, toAdd);
  1053. }  /* DoTEPasteSectionRecalc */
  1054.  
  1055. /**-----------------------------------------------------------------------
  1056.         Name:         DoTEDeleteSectionRecalc
  1057.         Purpose:        Keeps track of the positions of the sections call before a
  1058.                     TEDelete.
  1059.  -----------------------------------------------------------------------**/
  1060.  
  1061. pascal void DoTEDeleteSectionRecalc(DPtr theDoc)
  1062. {
  1063.     if (theDoc->kind != kDocumentWindow)
  1064.         return;
  1065.         
  1066.     DoSectionRecalc(theDoc, 0);
  1067. }  /* DoTEDeleteSectionRecalc */
  1068.  
  1069. /**-----------------------------------------------------------------------
  1070.         Name:         DoTECutSectionRecalc
  1071.         Purpose:        Keeps track of the positions of the sections call before a
  1072.                     TECut.
  1073.  -----------------------------------------------------------------------**/
  1074.  
  1075. pascal void DoTECutSectionRecalc(DPtr theDoc)
  1076. {
  1077.     if (theDoc->kind != kDocumentWindow)
  1078.         return;
  1079.         
  1080.     DoSectionRecalc(theDoc, 0);
  1081. }  /* DoTEDeleteSectionRecalc */
  1082.  
  1083. /**-----------------------------------------------------------------------
  1084.         Name:         DoTEKeySectionRecalc
  1085.         Purpose:        Keeps track of the positions of the sections call before a
  1086.                     TECut.
  1087.  -----------------------------------------------------------------------**/
  1088.  
  1089. pascal void DoTEKeySectionRecalc(DPtr theDoc,char theChar)
  1090. {
  1091.     short     toAdd;
  1092.     short     oldStart;
  1093.  
  1094.     if (theDoc->kind != kDocumentWindow)
  1095.         return;
  1096.         
  1097.     if (!KeyOKinSubscriber(theChar)) /* is it a cursor motion key? - yes = ignore */ {
  1098.         if (theChar==8)
  1099.             if ((*(theDoc->theText))->selStart<(*(theDoc->theText))->selEnd)
  1100.                 toAdd = 0;
  1101.             else {
  1102.                 toAdd = -1;
  1103.                 oldStart = (*(theDoc->theText))->selStart;
  1104.  
  1105.                 (*(theDoc->theText))->selStart = GreaterOf(oldStart-1,0);
  1106.                 DoSectionRecalc(theDoc, 0);
  1107.                 (*(theDoc->theText))->selStart = oldStart;
  1108.             }
  1109.         else
  1110.             toAdd = 1;
  1111.  
  1112.         if (toAdd!=-1)
  1113.             DoSectionRecalc(theDoc, toAdd);
  1114.     }
  1115. }  /* DoTEKeySectionRecalc */
  1116.  
  1117. /**-----------------------------------------------------------------------
  1118.         Name:         GetEditionContainer
  1119.         Purpose:        Gets the Edition Container to put the edition into.
  1120.                         The main user interface stuff.
  1121.                         Puts up the new publisher dialog.
  1122.                         Should check kAEInteractWithUser etc.
  1123.  -----------------------------------------------------------------------**/
  1124.  
  1125. #if !defined(powerc) && !defined(__powerc)
  1126. #pragma segment Main
  1127. #endif
  1128.  
  1129. pascal OSErr GetEditionContainer(DPtr theDoc, FSSpec *theFSSpec)
  1130. {
  1131.     OSErr             err;
  1132.     NewPublisherReply myReply;
  1133.     short             theStart;
  1134.     short             theEnd;
  1135.     Handle            myHandle;
  1136.     TEHandle          myText;
  1137.  
  1138.     if (theDoc->kind != kDocumentWindow)
  1139.         return noErr;
  1140.         
  1141.     err = noErr;
  1142.  
  1143.     /*get default editionContainer to use, using last volume and folder*/
  1144.  
  1145.     myReply.container.thePart = kPartsNotUsed;
  1146.  
  1147.     err = GetLastEditionContainerUsed(&myReply.container);
  1148.  
  1149.     if (err==fnfErr)
  1150.         err = noErr;
  1151.  
  1152.     myText = theDoc->theText;
  1153.  
  1154.     theStart = (*myText)->selStart;
  1155.     theEnd   = (*myText)->selEnd;
  1156.  
  1157.     if (err==noErr) {
  1158.         /*
  1159.             Create a handle containing the text to be published for previewing -
  1160.             need to ask the user where to put the data
  1161.         */
  1162.         myHandle = GetHandleToText(myText, theStart, theEnd);
  1163.  
  1164.         myReply.usePart       = false;
  1165.         myReply.preview       = myHandle;
  1166.         myReply.previewFormat = 'TEXT';
  1167.         myReply.container.theFile.name[0] = 0; /* Want a proper prompted name here */
  1168.         HLock(myHandle);
  1169.  
  1170.         /* Should take suggested name and avoid dialog if no user interaction */
  1171.  
  1172.         err = AEInteractWithUser(kAEDefaultTimeout, nil, nil);
  1173.  
  1174.         err = NewPublisherDialog(&myReply);
  1175.         HUnlock(myHandle);
  1176.         DisposHandle(myHandle);
  1177.     }
  1178.  
  1179.     /*IF user cancelled, THEN exit from this routine*/
  1180.  
  1181.     if (err==noErr)
  1182.         if (myReply.canceled)
  1183.             err = userCanceledErr; /* User cancelled marker - replace later */
  1184.  
  1185.     if (err==noErr)
  1186.         if (myReply.replacing)
  1187.             err = FSpDelete(&myReply.container.theFile);
  1188.  
  1189.     if (err == noErr)
  1190.         *theFSSpec = myReply.container.theFile;
  1191.  
  1192.     return(err);
  1193. } /*GetEditionContainer*/
  1194.  
  1195.  
  1196. /**-----------------------------------------------------------------------
  1197.         Name:             PublishText
  1198.         Purpose:        Publishes the current selection of theDoc.
  1199.                                 The main user interface stuff.
  1200.                                 Puts up the new publisher dialog - if theFSSpec=NIL
  1201.                                 Writes the new edition out to disk.
  1202.  -----------------------------------------------------------------------**/
  1203.  
  1204. #if !defined(powerc) && !defined(__powerc)
  1205. #pragma segment Main
  1206. #endif
  1207.  
  1208. pascal OSErr PublishText(DPtr theDoc, FSSpecPtr theFSSpec)
  1209. {
  1210.     NewPublisherReply myReply;
  1211.     SectionHandle        mySectHdl;
  1212.     OSErr                 err;
  1213.     long               mysectionID;
  1214.     FSSpecPtr             pubFSSpec;
  1215.     short                 theStart;
  1216.     short                 theEnd;
  1217.     RgnHandle             theRgnHandle;
  1218.  
  1219.     if (theDoc->kind != kDocumentWindow)
  1220.         return noErr;
  1221.         
  1222.     mysectionID            = theDoc->u.reg.lastID + 1;
  1223.     theDoc->u.reg.lastID = mysectionID;
  1224.  
  1225.     /*get default editionContainer to use, using last volume and folder*/
  1226.  
  1227.     myReply.container.thePart = kPartsNotUsed;
  1228.  
  1229.     err = GetLastEditionContainerUsed(&myReply.container);
  1230.  
  1231.     if (err==fnfErr)
  1232.         err = noErr;
  1233.  
  1234.     theStart = (*theDoc->theText)->selStart;
  1235.     theEnd   = (*theDoc->theText)->selEnd;
  1236.  
  1237.     /*don't want to publish an empty section*/
  1238.  
  1239.     if (theEnd - theStart == 0)
  1240.         err = userCanceledErr;
  1241.  
  1242.     myReply.container.theFile = *theFSSpec;
  1243.  
  1244.     /*now publish this section*/
  1245.  
  1246.     if (err == noErr)
  1247.         err = CreateEditionContainerFile(&myReply.container.theFile, MPAppSig, 0);
  1248.  
  1249.     /*check IF the file has been saved, IF not set pubCFS to NIL*/
  1250.  
  1251.     if (theDoc->u.reg.everSaved == false)
  1252.         pubFSSpec = nil;
  1253.     else
  1254.         pubFSSpec = &theDoc->theFSSpec;
  1255.  
  1256.     /*get the region to encompass the selection*/
  1257.  
  1258.     theRgnHandle = NewRgn();
  1259.     SetSelectionRgn(theDoc->theText,
  1260.                          (*theDoc->theText)->selStart,
  1261.                                     (*theDoc->theText)->selEnd,
  1262.                                     &theRgnHandle);
  1263.  
  1264.     InvalRgn(theRgnHandle);
  1265.  
  1266.     /*create a publisher section*/
  1267.     if (err==noErr) {
  1268.         err = NewSection(&myReply.container,
  1269.                               pubFSSpec,
  1270.                               stPublisher,
  1271.                               mysectionID,
  1272.                               pumOnSave,
  1273.                               &mySectHdl);
  1274.  
  1275.         /*now add this section to our document list*/
  1276.  
  1277.         if (err == noErr)
  1278.             CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, theRgnHandle);
  1279.     }
  1280.  
  1281.     /*now write out the edition to file*/
  1282.  
  1283.     if (err==noErr)
  1284.         WriteAnEdition(mySectHdl);
  1285.  
  1286.     return(err);
  1287. } /*PublishText*/
  1288.  
  1289. /**-----------------------------------------------------------------------
  1290.         Name:         DoSubscribe
  1291.         Purpose:        Subscribe to a published section. Puts up the subscriber
  1292.                         dialog, creates and adds the new section.
  1293.  -----------------------------------------------------------------------**/
  1294.  
  1295. #if !defined(powerc) && !defined(__powerc)
  1296. #pragma segment Main
  1297. #endif
  1298.  
  1299. pascal void DoSubscribe(DPtr theDoc)
  1300. {
  1301.     NewSubscriberReply myReply;
  1302.     SectionHandle      mySectHdl;
  1303.     long               mysectionID;
  1304.     FSSpecPtr          subFSSpec; /*the fsspec for the subscriber file*/
  1305.     OSErr              err;
  1306.     short              theStart;
  1307.     short              theEnd;
  1308.  
  1309.     if (theDoc->kind != kDocumentWindow)
  1310.         return;
  1311.         
  1312.     mysectionID = theDoc->u.reg.lastID + 1;
  1313.     theDoc->u.reg.lastID = mysectionID;
  1314.     err = noErr;
  1315.  
  1316.     /*get default editionContainer to use, using last volume and folder*/
  1317.     /*  myreply.container.thePart := kPartNumberUnknown;*/
  1318.     myReply.formatsMask = kTEXTformatMask;
  1319.  
  1320.     err = GetLastEditionContainerUsed(&myReply.container);
  1321.     if (err && (err !=fnfErr)) {
  1322.         ShowError((StringPtr) "\pGetLastEditionContainerUsed", err);
  1323.         return;
  1324.     }
  1325.  
  1326.     /*put up the subscriber dialog*/
  1327.     err = NewSubscriberDialog(&myReply);
  1328.     if (err && (err !=fnfErr)) {
  1329.         ShowError((StringPtr) "\pNewSubscriberDialog", err);
  1330.         return;
  1331.     }
  1332.  
  1333.     if (myReply.canceled)
  1334.         return;
  1335.  
  1336.     /*check IF the file has been saved, IF not set pubCFS to NIL*/
  1337.     if (theDoc->u.reg.everSaved == false)
  1338.         subFSSpec = nil;
  1339.     else
  1340.         subFSSpec = &theDoc->theFSSpec;
  1341.  
  1342.     /*create a publisher section*/
  1343.     err = NewSection(&myReply.container,
  1344.                           subFSSpec,
  1345.                           stSubscriber,
  1346.                           mysectionID,
  1347.                           sumAutomatic,
  1348.                           &mySectHdl);
  1349.  
  1350.     if (err) {
  1351.         ShowError((StringPtr) "\pNewSection", err);
  1352.         return;
  1353.     }
  1354.  
  1355.     theStart = (*theDoc->theText)->selStart;
  1356.     theEnd   = (*theDoc->theText)->selEnd;
  1357.  
  1358.     /*now add this section to our document list*/
  1359.  
  1360.     CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, nil);
  1361.  
  1362.     /*read the subscriber in from disk*/
  1363.  
  1364.     ReadAnEdition(mySectHdl);
  1365.  
  1366. }  /*DoSubscribe*/
  1367.  
  1368. /**-----------------------------------------------------------------------
  1369.         Name:         DoSectionOptions
  1370.         Purpose:        Put up the section option dialogs for a publisher
  1371.                         or subscriber.    Handle all the various options.
  1372.                         Note that 'Find Publisher' doesn't work yet.
  1373.  -----------------------------------------------------------------------**/
  1374.  
  1375. #if !defined(powerc) && !defined(__powerc)
  1376. #pragma segment Main
  1377. #endif
  1378.  
  1379. pascal void DoSectionOptions(DPtr theDoc)
  1380. {
  1381.     OSErr               err;
  1382.     SectionOptionsReply reply;
  1383.     EditionInfoRecord   theInfo;
  1384.     SectHandle          currSection;
  1385.  
  1386.     if (theDoc->kind != kDocumentWindow)
  1387.         return;
  1388.         
  1389.     currSection = GetSection((*theDoc->theText)->selStart,
  1390.                                                      (*theDoc->theText)->selEnd,
  1391.                                                      theDoc);
  1392.  
  1393.     reply.sectionH = (*currSection)->fSectHandle;
  1394.     err = SectionOptionsDialog(&reply);
  1395.     if (!reply.canceled) {
  1396.         /*find out IF there is any action needed*/
  1397.         if (reply.action == 'read')
  1398.         /*read the latest version of a subscriber*/
  1399.             ReadAnEdition((*currSection)->fSectHandle);
  1400.         else if (reply.action == 'writ')
  1401.         /*write out the latest version of a publisher to disk*/
  1402.             WriteAnEdition((*currSection)->fSectHandle);
  1403.         else if (reply.action == 'goto') /*goto a published section*/ {
  1404.             err = GetEditionInfo((*currSection)->fSectHandle, &theInfo);
  1405.  
  1406.             if (err)
  1407.                 ShowError((StringPtr) "\pGetEditionInfo", err);
  1408.  
  1409.             err = GoToPublisherSection(&theInfo.container);
  1410.  
  1411.             if (err)
  1412.                 ShowError((StringPtr) "\pGotoPublisherSection", err);
  1413.         } else if (reply.action == 'cncl') /*cancel a publisher or subscriber*/ {
  1414.             /*unRegister the section and delete from our own list*/
  1415.             /*should have a free PROCEDURE which frees the structures*/
  1416.             /*associated with a section*/
  1417.             err = UnRegisterSection((*currSection)->fSectHandle);
  1418.             DeleteASection(currSection, theDoc);
  1419.  
  1420.             /*IF this is the ONLY publisher writing data to this edition*/
  1421.             /*we should delete the container file as well*/
  1422.         }
  1423.     }
  1424. }
  1425.  
  1426. #endif