// P A R T S // errors 300 // //Stuff for dealing with "parts" of windows. // // SetPartBounds(window,frec,nrecs) // Sets bounds on "window" starting at Press record # frec, // and going for nrecs. // GetPositioninPart(window,dp) // Returns dp position within bounds. // SetPositioninPart(window,dp) // Sets position relative to bounds. // SetBytePositioninPart(window,bdp) // bdp is BYTE position relative to bounds. // CheckAvailinPart(window,how,n) // Checks availablity of n "things" in bounds. // h=0 n in bytes // h=1 n in words // h=2 n is dp word count // h=3 n is dp byte count // SkipinPart(window,how,n) // Skips n "things" -- how as above. // get "PressInternals.df" get "PressParams.df" // outgoing procedures external [ SetPartBounds GetPositioninPart SetPositioninPart SetBytePositioninPart CheckAvailinPart SkipinPart ] // outgoing statics //external // [ // ] //static // [ // ] // incoming procedures external [ //PRESS PressError //WINDOW,FILES WindowInit WindowClose WindowGetPosition WindowSetPosition WindowReadBlock WindowReadByte WindowFlush FileStuff FileWritePage //PRESS DblShift //OS MoveBlock //PRESSML MulDiv DoubleAdd; DoubleSub; DoubleCop ] // incoming statics //external // [ // ] // internal statics //static // [ // ] // File-wide structure and manifest declarations. structure WP: //"Window Part" [ RPos word 2 //Relocation position Len word 2 //Length of part Base word //Lines up with W ] // Procedures //"Part" functions let SetPartBounds(w,frec,nrecs) be [ compileif offset WP.Base ne offset W.Base then [ foo=0 ] //Get file size let f=w>>W.File let fsiz=vec 1 FileStuff(f,fsiz) //Get file size //Now convert to Press records DblShift(fsiz,LogPressRecordSize) if fsiz!0 then PressError(300) //Too big let nPressRecs=fsiz!1 //All for this if frec ls 0 % nrecs ls 1 % frec+nrecs-1 ge nPressRecs then PressError(301) //Part bounds wrong //Record part length fsiz!1=nrecs DblShift(fsiz,-LogPressRecordSize) DoubleCop(lv w>>WP.Len,fsiz) //Length of area. //Record part starting position fsiz!0=0 fsiz!1=frec DblShift(fsiz,-LogPressRecordSize) DoubleCop(lv w>>WP.RPos,fsiz) ] and GetPositioninPart(w,p) be [ WindowGetPosition(w,p) DoubleSub(p,lv w>>WP.RPos) ] and SetPositioninPart(w,p) be [ let t=vec 1 //Condition is: len-position => 0 DoubleCop(t,lv w>>WP.Len); DoubleSub(t,p); if p!0 ls 0 % t!0 ls 0 then PressError(302) DoubleCop(t,p); DoubleAdd(t,lv w>>WP.RPos) WindowSetPosition(w,t) ] and SetBytePositioninPart(w,p) be [ let b=(p!1)&1 //Byte odd let t=vec 1 DoubleCop(t,p); DblShift(t,1); SetPositioninPart(w,t) if b then WindowReadByte(w) ] and CheckAvailinPart(w,how,n) be [ if how gr 1 & n!0 eq 0 then [ n=n!1; how=1 ] if how eq 0 then [ if w>>W.WhichByte then n=n-1 //A byte there already n=(n+1)/2 ] //Following is a quick check so that ordinary things work fast, // but is not strictly speaking correct. The reason is that if several // Press records will fit in one window buffer, then the check could // allow a check to succeed even though the range is outside the // specified number of Press records. if how le 1 & n le -w>>W.Offset then return //Enuf in this buffer //Condition is position+needed <= length let t=vec 1 t!0=0;t!1=n if how gr 1 then DoubleCop(t,n) let s=vec 1 GetPositioninPart(w,s) DoubleAdd(s,t) //s=pos+needed DoubleCop(t,lv w>>WP.Len) DoubleSub(t,s) //t=len-(pos+needed) if t!0 ls 0 then PressError(303) ] and SkipinPart(w,how,n) be [ //Get current byte pos. let t=vec 1 GetPositioninPart(w,t) DblShift(t,-1) if w>>W.WhichByte then DoubleAdd(t,table [ 0;1 ]) //Convert n to bytes let s=vec 1 s!0=0; s!1=n if how ne 0 then [ if how ge 2 then DoubleCop(s,n) unless how eq 3 do DblShift(s,-1) ] //Now set position to pos+n DoubleAdd(s,t) SetBytePositioninPart(w,s) ]