// GPARA.SR Paragraphs get "BRAVO.DF" get "CHAR.DF" get "GINN.DF" // Incoming procedures external [ cppara parabounds paradetails macpara gotparaspec setparaspec paracp paraspec setparacp getint binsearcha hpfree getvch putvch mapscrcp errhlt insertstring deletea hpalloca hpalloc move movec enww readsel stequal invalidatedisplay receivechange parsespec unparsespec min cpc makelist bubblesegs setpagenum setpagecp growlist updateofs inheap createdocm ckhp newsphp // %% freesphp // %% ] // Incoming statics external [ widthblave // $$ xleftmargstd // $$ xrightmargstd // $$ rgdllast // %% some names taken out to allow compilation vdoc vcp vchremain rgmaccp rgcpfdispl rgcplast vxleftmarg vxrightmarg vinsertk mdoc vlooktrailer rgpage rgpagenum rgreadonly rgchoppage rgupdate rgpctb rgsfile hdebug ] // Outgoing procedures external [ specstate nextspecstate enpspecs gcspecs freespec ckspecs wipedoc createdocp discardspecs acquirespecs replacespec forgetspec nulltrailer specdetails makespec discard bsearch ckspec trycpspec ] // Outgoing statics external [ vpara rgpara rgspec vlook vlookctrl vquad vchangemarker currentspec otherspec mphd rgprogram fdebug speclist vmakelock ] // Local statics static [ vpara rgpara rgspec vlook vlookctrl // strange-- maps chars gr #200 and ls #40 vquad vchangemarker zcpfirst zcplast zspecinuse currentdoc currententry currentstart currentpara currentspec otherspec mphd rgprogram fdebug speclist cspecs vmakelock ] // Data Structures: // For each doc: rgpara!doc and rgspec!doc are "lists" // Each list has a prelude "listbase" words long with a "max" size // and a current "siz" // Then there is an entry for each paragraph, plus an entry for the // end-of-document paragraph (at !(siz-2)) and an entry // to stop the binary search (at !(siz-1)) // rgpara has start cp's of each paragraph // rgspec has for each paragraph one of: // an even number -- ptr to heap structure for a "spec" // an odd number -- ptr to SCRATCH.TX mail for the para // zero -- neither of the above // each spec is a "list" with four parts after the prelude: // dirty bit, trailer length // paragraph wide format ("measures and quads") // local format changes ("looks") // relative cp's where looks occur ("changes") let bsearch(list, key) = valof [ let siz = list >> LIST.siz - 1 let i = binsearcha(list+listbase, siz, key) unless 0 le i & i ls siz do errhlt("NSK") resultis i ] and specdetails(spec, vector) = valof [ // To use: // let siz,looks,changes = nil,nil,nil // specdetails(spec, lv siz) let siz = spec >> SPEC.siz vector ! 0 = siz vector ! 1 = spec + specbase // looks vector ! 2 = vector ! 1 + spec >> SPEC.max // changes resultis siz ] and trycpspec(doc, cp) = valof [ let para = cppara(doc, cp) let w = (rgspec!doc) ! (para+listbase) if w & not w << odd then resultis true vmakelock = true let spec = parsespec(doc, para, w) vmakelock = false resultis spec ne -1 ] and specstate(doc, cp, para) = valof [ // Returns cp unless in hidden trailer, then returns beg of trailer cp let tex, b, e = nil, nil, nil parabounds(doc, para, lv tex, lv b, lv e) let spec,siz,looks,changes,rcp,r = nil,nil,nil,nil,nil,nil paradetails(doc, para, lv spec, cp) currentpara = para currentspec = spec currententry = r currentstart = tex currentdoc = doc // $$ vchangemarker = spec >> SPEC.dirty? 2, spec >> SPEC.marker? 1, 0 vchangemarker = spec >> SPEC.marker? 1, 0 vquad = spec >> SPEC.quad let intrailer = r ge siz-2 & not vlooktrailer// %% // $$ vxleftmarg = rcp? spec >> SPEC.lmarg, spec >> SPEC.dent vxleftmarg = xleftmargstd + spec >> SPEC.lmarg * widthblave vxrightmarg = xrightmargstd - spec >> SPEC.rmarg * widthblave // $$[ if vxleftmarg eq xleftmargstd & vxrightmarg eq xrightmargstd then resultis intrailer? b, cp // %% vxleftmarg = vxleftmarg gr xrightmargstd? xrightmargstd, vxleftmarg ls xleftmargstd? xleftmargstd, vxleftmarg vxrightmarg = vxrightmarg ls xleftmargstd? xleftmargstd, vxrightmarg gr xrightmargstd? xrightmargstd, vxrightmarg if vxleftmarg gr vxrightmarg then [ vxleftmarg = (vxleftmarg+vxrightmarg)/2 vxrightmarg = vxleftmarg ] if (vxrightmarg-vxleftmarg) ls (minline*widthblave) then [ let adjust = ((minline*widthblave)-(vxrightmarg-vxleftmarg))/2 vxleftmarg = vxleftmarg-adjust vxrightmarg = vxrightmarg+adjust if vxrightmarg gr xrightmargstd then [ vxleftmarg = vxleftmarg - (vxrightmarg-xrightmargstd) vxrightmarg = xrightmargstd ] if vxleftmarg ls xleftmargstd then [ vxrightmarg = vxrightmarg + (xleftmargstd-vxleftmarg) vxleftmarg = xleftmargstd ] ] // $$] resultis intrailer? b, cp // %% ] and nextspecstate() = valof [ // Be sure specstate has been called to initiallize ! // Computes the format state and assigns it to statics such as vlook // Returns the cp at which the next format changes occurs // If encountered a trailer to be skipped, returns -1 & vcp -> CR let siz,looks,changes = nil,nil,nil specdetails(currentspec, lv siz) vlook = looks ! currententry if currententry ge siz-2 then [ // %% vxleftmarg = xleftmargstd // %% vxrightmarg = xrightmargstd unless vlooktrailer do [ vcp = currentstart + changes ! (siz-1) - 1 resultis -1 ] ] currententry = currententry + 1 resultis currentstart + changes ! currententry ] and enpspecs(proc, doconly ; numargs N) be [ // enpspecs(proc) calls proc(lv pspec) for all specs in all docs // TWICE -- once for speclist ptr and once for rgspec ptr // enpspecs(proc, doc) calls proc(doc, para, spec) for all specs in // doconly (or in all docs if doc=-1) ONCE // proc is not allowed to destroy specs or add new ones ! // to do this use slowenpspecs let p = lv speclist let spec = speclist let tsphp = newsphp(lv spec) // %% while spec do [ let doc = spec >> SPEC.doc let para = spec >> SPEC.para test N eq 1 ifso [ let s = @p proc(p) if doc ne abandon then [ let pp = (rgspec!doc)+(para+listbase) if @pp then [ if s ne @pp then errhlt("ENP") proc(pp) ] ] ] ifnot if doc ne abandon & (doc eq doconly % doconly eq -1) then proc(doc, para, spec) p = lv spec >> SPEC.link spec = @p ] freesphp(tsphp) // %% ] and slowenpspecs(proc, doconly ; numargs N) be [ // discard after ckspecs doesn't need it any more // enpspecs(proc) calls proc(lv pspec) for all specs in all docs // enpspecs(proc, doc) calls proc(doc, para, spec) for all specs in // doconly (or in all docs if doc=-1) // proc is allowed to destroy specs or add new ones // if it doesn't need to, then use enpspecs instead for doc = 0 to maxdoc-1 do if rgpara ! doc then if (N eq 1 % doc eq doconly % doconly eq -1) then for para = 0 to macpara(doc) - 2 do [ let spec = gotparaspec(doc, para) unless spec & not spec << odd do loop test N eq 2 ifso proc(doc, para, spec) ifnot proc((rgspec!doc)+(para+listbase)) ] ] and gcspecs() be unless vinsertk do [ if hdebug then ckhp() currentspec = speclist otherspec = 0 while currentspec do [ let doc = currentspec >> SPEC.doc let para = currentspec >> SPEC.para if fdebug & doc ne abandon then ckspec(doc, para, currentspec) let junk = doc eq abandon? true, gcspec(doc, para, currentspec) let nextspec = currentspec >> SPEC.link test junk ifso [ test otherspec ifso otherspec >> SPEC.link = nextspec ifnot speclist = nextspec if doc ne abandon then setparaspec(doc, para, 0) hpfree(currentspec) if hdebug then ckhp() ] ifnot otherspec = currentspec currentspec = nextspec ] if fdebug then ckspecs() ] and gcspec(doc, para, spec) = valof [ if para eq 0 % doc eq docsys % doc eq mdoc then resultis false zspecinuse = false ; zcpfirst = paracp(doc, para) zcplast = paracp(doc, para+1) - 1 enww(isspecinuse, doc) unless zspecinuse do [ unparsespec(doc, para, spec) resultis true ] resultis false ] and isspecinuse(ww) be [ if cpc(zcplast, rgcpfdispl ! ww) ls 0 % (not rgupdate ! ww & cpc(zcpfirst, rgcplast ! (rgdllast ! ww)) gr 0) then return ; zspecinuse = true ; ] and freespec(doc, para, spec) be [ spec >> SPEC.doc = abandon setparaspec(doc, para, 0) currentspec = 0 ] and wipefree(p, nilval; numargs N) be [ if N eq 1 then nilval = 0 if @p ne nilval then [ if inheap(@p) then hpfree(@p) @p = nilval ] ] and wipedoc(doc) be [ enpspecs(freespec, doc) wipefree(rgreadonly + doc) wipefree(rgsfile + doc) wipefree(rgpara + doc) wipefree(rgspec + doc) wipefree(rgpage + doc) wipefree(rgpagenum + doc) wipefree(rgpctb + doc, -1) rgmaccp ! doc = 0; updateofs() createdocm(doc) ] and ckspecs() be [ cspecs = 0 enpspecs(ckspec, -1) let tcspecs = cspecs cspecs = 0 slowenpspecs(ckspec, -1) if cspecs ne tcspecs then errhlt("SPL") for doc = 0 to maxdoc-1 do if rgpara ! doc then [ vdoc = doc for para = 1 to macpara(doc) - 2 do [ vcp = paracp(doc, para)-1 if cpc(vcp-paracp(doc,para-1), 1) ls 0 then errhlt("YIK") vchremain = 0 if getvch() ne chcr then errhlt("MCR") ] if rgprogram ! doc then unless (rgpara ! doc) >> LIST.siz le 3 & paraspec(doc, 0) >> SPEC.trailerlength eq 2 do errhlt("fpr") ] ] and ckspec(doc, para, spec) be [ cspecs = cspecs + 1 if spec >> SPEC.doc ne doc % spec >> SPEC.para ne para then errhlt("DPS") let v = rgpara ! doc unless 0 le para & para ls v >> LIST.siz do errhlt("CSP") let siz, looks, changes = nil, nil, nil specdetails(spec, lv siz) unless changes ! 0 eq 0 do errhlt("CS0") for i = 1 to siz - 1 do if cpc(changes ! (i-1), changes ! i) ge 0 then errhlt("CSB") if changes ! (siz-1) ne paracp(doc, para+1) - paracp(doc, para) % spec >> SPEC.trailerlength + changes ! (siz-2) ne changes ! (siz-1) then errhlt("PBE") ] and createdocp(doc) be [ rgpara ! doc = makelist(2, 1, listbase, false) rgspec ! doc = makelist(2, 1, listbase, false) rgpage ! doc = makelist(2, 1, listbase, false) rgpagenum ! doc = makelist(2, 1, listbase, false) rgreadonly ! doc = 0 rgprogram ! doc = false rgchoppage ! doc = false insertstring(doc, 0, "*032*N") setparacp(doc, 1, rgmaccp ! doc) setpagecp(doc, 1, rgmaccp ! doc) setpagenum(doc, 1, 1) ] and fixspecparas(doc, para1, para2) be for para = para1 to para2 do [ let spec = gotparaspec(doc, para) if spec & not spec << odd then spec >> SPEC.para = para ] and discard(mac, p1, p2, rg1, rg2) be [ let siz = bubblesegs(mac, p1-p2-1, p2+1, rg1 + listbase, rg2 + listbase) rg1 >> LIST.siz = siz rg2 >> LIST.siz = siz ] and discardspecs(doc, para1, para2) be [ discard(macpara(doc), para1, para2, rgpara!doc, rgspec!doc) fixspecparas(doc, para1, macpara(doc)-2) ] and acquirespecs(doc, para, nparas) be [ growlist(rgpara+doc, nparas, 10, 1, listbase) growlist(rgspec+doc, nparas, 10, 1, listbase) bubblesegs(macpara(doc) - nparas, nparas, para, rgpara!doc + listbase, rgspec!doc + listbase) fixspecparas(doc, para+nparas, macpara(doc)-2) ] and replacespec(doc, para, spec) be [ currentspec = 0 let oldspec = paraspec(doc, para) if oldspec then [ spec >> SPEC.trailerlength = oldspec >> SPEC.trailerlength let siz, looks, changes = nil, nil, nil specdetails(spec, lv siz) changes ! (siz-1) = changes ! (siz-2) + spec >> SPEC.trailerlength oldspec >> SPEC.doc = abandon ] setparaspec(doc, para, spec) ] and forgetspec(doc, para) be [ let spec = (rgspec!doc)!(para+listbase) if spec & not spec << odd then spec >> SPEC.doc = abandon (rgspec!doc)!(para+listbase) = 0 currentspec = 0 ] and makespec(lim, okrobdisplay; numargs N) = valof [ // okrobdisplay defaults to true let spec = makelist(lim, 2, specbase, N eq 1 % okrobdisplay) if spec eq 0 then errhlt("SPZ") spec >> SPEC.doc = abandon spec >> SPEC.link = speclist speclist = spec resultis spec ]