-- AISImpl.mesa -- Last changed by John Warnock, 23-Nov-81 16:21:11 -- Last Edited by: Stone, August 11, 1983 2:50 pm DIRECTORY AIS, AISFormat, DCSFileTypes, Directory, File, Heap, Inline, Space, Volume, BitBlt, Environment; AISImpl: PROGRAM IMPORTS Directory, File, Heap, Inline, Space, Volume,BitBlt EXPORTS AIS = {OPEN AIS; zone: UNCOUNTED ZONE = Heap.systemZone; Error: PUBLIC SIGNAL[type: ErrorType] = CODE; catch: BOOLEAN = TRUE; wordsPerPage: CARDINAL = Space.wordsPerPage; aisWordsPerPage: CARDINAL = AISFormat.aisWordsPerPage; pagesPerAISPage: CARDINAL = aisWordsPerPage/wordsPerPage; defaultBSize: CARDINAL _ 4*pagesPerAISPage; bbspace: BitBlt.BBTableSpace; bbptr: BitBlt.BBptr _ BitBlt.AlignedBBTable[@bbspace]; bbflags: BitBlt.BitBltFlags _ [direction: forward, disjoint: TRUE, disjointItems: FALSE, gray: FALSE, srcFunc: null, dstFunc: null]; ARef: TYPE = LONG POINTER TO ARep; ARep: TYPE = RECORD [ fref: FRef _ NIL, space: Space.Handle _ Space.nullHandle, --attributes space header: LONG POINTER TO AISFormat.Header _ NIL, raster: LONG POINTER TO uca AISFormat.RasterPart _ NIL, placement: LONG POINTER TO AISFormat.PlacementPart _ NIL, photometry: LONG POINTER TO AISFormat.PhotometryPart _ NIL, comment: LONG POINTER TO AISFormat.CommentPart _ NIL ]; lastARep: ARep _ [NIL,Space.Create[size: defaultBSize, parent: Space.virtualMemory],NIL,NIL,NIL,NIL]; lastARef: ARef _ @lastARep; DivUp: PROC[n: LONG CARDINAL, d: CARDINAL] RETURNS[CARDINAL] = INLINE { q,r: CARDINAL; [q,r] _ Inline.LongDivMod[n,d]; RETURN[IF r>0 THEN q+1 ELSE q] }; LongCopy: PROC[from: LONG POINTER, to: LONG POINTER, nwords: LONG CARDINAL] = INLINE { wpb: CARDINAL _ 177777B; q,r: CARDINAL; [q,r] _ Inline.LongDivMod[num: nwords,den: wpb]; FOR i: CARDINAL IN [0..q) DO Inline.LongCOPY[from: from, to: to, nwords: wpb]; from _ from+wpb; ENDLOOP; Inline.LongCOPY[from: from, to: to, nwords: r]; }; CreateFile: PUBLIC PROC[name: LONG STRING, raster: Raster, overwrite: BOOLEAN, attributeLength: CARDINAL] RETURNS[f: FRef] = { file: File.Capability _ File.nullCapability; filesize: File.PageCount _ 0; bpp: CARDINAL _ 0; -- bits per pixel ppw: CARDINAL _ 0; -- pixels per word wpl: CARDINAL _ 0; -- words per scan line lines: CARDINAL _ 0; -- raster.scanLength pixels: CARDINAL _ 0; -- raster.scanCount apages,rpages,bpages: CARDINAL _ 0; -- AIS pages in attribute, raster, and block abase,rbase: File.PageNumber; -- starting file pages -- Check for reasonable parameters SELECT raster.bitsPerPixel FROM 0 => { bpp _ 1; ppw _ 16 }; 1,2,4,8,16 => { bpp _ raster.bitsPerPixel; ppw _ 16/bpp }; 3,5,6,7,IN[9..15] => Error[notImplemented]; -- not expected ENDCASE => Error[invalidParameter]; -- 0 or out of range IF raster.scanCount>0 AND raster.scanLength>0 THEN { lines _ raster.scanCount; pixels _ raster.scanLength; wpl _ DivUp[pixels,ppw]; } ELSE Error[invalidParameter]; -- bad scanCount or scanLength apages _ (IF attributeLength=0 THEN 1 ELSE DivUp[attributeLength,aisWordsPerPage]); attributeLength _ aisWordsPerPage*apages; --compute the number of pages to hold the raster IF raster.linesPerBlock>0 THEN { blocks: CARDINAL _ DivUp[lines,raster.linesPerBlock]; -- number of blocks bwords: LONG CARDINAL _ Inline.LongMult[wpl,raster.linesPerBlock]; bpages _ DivUp[bwords,aisWordsPerPage]; -- ais pages per block rpages _ blocks*bpages; --total ais pages in raster part } ELSE { rwords: LONG CARDINAL _ Inline.LongMult[wpl,lines]; rpages _ DivUp[rwords,aisWordsPerPage] --total ais pages in raster part }; abase _ 1; -- attributes follow leader page rbase _ abase + pagesPerAISPage*apages; filesize _ rbase + pagesPerAISPage*rpages; IF overwrite THEN Directory.DeleteFile[fileName: name ! Directory.Error => SELECT type FROM fileNotFound => CONTINUE; invalidFileName => IF catch THEN GOTO BadName; ENDCASE; ]; file _ Directory.CreateFile[fileName: name, fileType: DCSFileTypes.tLeaderPage, size: filesize ! Directory.Error => SELECT type FROM fileAlreadyExists => IF catch THEN GOTO OldFile; invalidFileName => IF catch THEN GOTO BadName; ENDCASE; Volume.InsufficientSpace => IF catch THEN GOTO NoRoom; ]; file _ File.LimitPermissions[file, File.read + File.write]; f _ zone.NEW[FRep _ [file: file, write: TRUE, abase: abase, rbase: rbase, raster: raster, wordsPerLine: wpl, buffersize: 0]]; IF raster.linesPerBlock>0 THEN f.buffersize _ bpages*pagesPerAISPage ELSE SetBufferSize[f]; IF lastARef.fref#NIL THEN DeleteLastARef[]; lastARef.fref _ f; lastARef.header _ zone.NEW[AISFormat.Header _ [password: AISFormat.aisPassword, attributeLength: attributeLength]]; Space.Map[space: lastARef.space, window: [file: f.file, base: abase]]; lastARef.raster _ zone.NEW[uca AISFormat.RasterPart _ [ part: AISFormat.PartHeader[type: raster, length: SIZE[uca AISFormat.RasterPart]], scanCount: raster.scanCount, scanLength: raster.scanLength, scanDir: (SELECT raster.scanMode FROM ru => 2, rd => 3, lu => 6, ld => 7, ul => 9, ur => 8, dl => 13, dr => 12, ENDCASE => ERROR), samplesPerPixel: 1, coding: uca[bitsPerSample: raster.bitsPerPixel, wordsPerScanLine: wpl, scanLinesPerBlock: raster.linesPerBlock, paddingPerBlock: raster.paddingPerBlock] ]]; RETURN[f]; EXITS BadName => Error[invalidFileName]; OldFile => Error[fileAlreadyExists]; NoRoom => Error[volumeFull]; }; DeleteFile: PUBLIC PROC[name: LONG STRING] RETURNS[success: BOOLEAN] = { success _ TRUE; Directory.DeleteFile[name ! Directory.Error => SELECT type FROM fileNotFound => { success _ FALSE; CONTINUE }; ENDCASE]; RETURN[success]; }; OpenFile: PUBLIC PROC[name: LONG STRING, write: BOOLEAN _ FALSE] RETURNS[f: FRef] = { file: File.Capability _ Directory.Lookup[ fileName: name, permissions: (IF write THEN File.read + File.write ELSE File.read) ! Directory.Error =>SELECT type FROM fileNotFound => IF catch THEN GOTO NotFound; invalidFileName => IF catch THEN GOTO BadName; ENDCASE; ]; scanmode: ScanMode _ ru; apages: Space.PageCount; f _ zone.NEW[FRep]; f.file _ file; f.abase _ FirstPage[f.file]; ReadAttributes[f]; --sets up lastARef, and maps the file apages _ lastARef.header.attributeLength/wordsPerPage; f.rbase _ f.abase + apages; scanmode _ SELECT lastARef.raster.scanDir FROM 2 => ru, 3 => rd, 6 => lu, 7 => ld, 9 => ul, 8 => ur, 13 => dl, 12 => dr, ENDCASE => rd; f.raster _ zone.NEW[AIS.RasterPart _ [scanCount: lastARef.raster.scanCount, scanLength: lastARef.raster.scanLength, scanMode: scanmode, bitsPerPixel: lastARef.raster.bitsPerSample, linesPerBlock: lastARef.raster.scanLinesPerBlock, paddingPerBlock: lastARef.raster.paddingPerBlock]]; f.wordsPerLine _ lastARef.raster.wordsPerScanLine; f.write _ write; IF lastARef.raster.scanLinesPerBlock>0 THEN { bwords: LONG CARDINAL _ Inline.LongMult[lastARef.raster.wordsPerScanLine,lastARef.raster.scanLinesPerBlock]; bpages: LONG CARDINAL _ DivUp[bwords,aisWordsPerPage]; -- ais pages per block temp: LONG CARDINAL _ bpages*pagesPerAISPage; IF Inline.HighHalf[temp]=0 THEN f.buffersize _ Inline.LowHalf[temp] ELSE ERROR; } ELSE SetBufferSize[f]; RETURN[f]; EXITS BadName => Error[invalidFileName]; NotFound => Error[fileNotFound]; }; CloseFile: PUBLIC PROC[f: FRef] = { --If the file is mapped, writes out the file and cleans up the local data structures IF f=lastARef.fref THEN DeleteLastARef[]; zone.FREE[@f]; --dangle, dangle... }; SetBufferSize: PROC[f: FRef] = { rsize: CARDINAL _ DivUp[Inline.LongMult[f.wordsPerLine,f.raster.scanCount],wordsPerPage]; f.buffersize _ IF rsize0 THEN ERROR; --allocate the lastARef fields according to the length IF lastARef.photometry#NIL THEN zone.FREE[@lastARef.photometry]; lastARef.photometry _ zone.NEW[AISFormat.PhotometryPart[len]]; lastARef.photometry.part _ [type: photometry, length: SIZE[AISFormat.PhotometryPart[len]]]; lastARef.photometry.signal _ photometry.signal; lastARef.photometry.sense _ photometry.sense; lastARef.photometry.scaleType _ photometry.scaleType; lastARef.photometry.pointA _ photometry.pointA; lastARef.photometry.pointB _ photometry.pointB; lastARef.photometry.pointC _ photometry.pointC; lastARef.photometry.spotType _ photometry.spotType; lastARef.photometry.spotWidth _ photometry.spotWidth; lastARef.photometry.spotLength _ photometry.spotLength; lastARef.photometry.sampleMin _ photometry.sampleMin; lastARef.photometry.sampleMax _ photometry.sampleMax; lastARef.photometry.histogramLength _ photometry.histogramLength; IF histogram#NIL THEN FOR i: INTEGER IN [0..len] DO lastARef.photometry.histogram[i] _ histogram[i]; ENDLOOP; }; -- Window operations -- OpenWindow: PUBLIC PROC[f: FRef, firstScan: CARDINAL _ 0, lastScan: CARDINAL _ LAST[CARDINAL], firstPixel: CARDINAL _ 0, lastPixel: CARDINAL _ LAST[CARDINAL]] RETURNS[w: WRef] = { bref: BRef; wpl,ppw: CARDINAL; bref _ zone.NEW[BRep]; IF lastScan=LAST[CARDINAL] THEN lastScan _ f.raster.scanCount; IF lastPixel=LAST[CARDINAL] THEN lastPixel _ f.raster.scanLength; lastScan _ MIN[f.raster.scanCount-1,lastScan]; lastPixel _ MIN[f.raster.scanLength-1,lastPixel]; IF firstScan>lastScan THEN Error[badWindow]; IF firstPixel>lastPixel THEN Error[badWindow]; bref^ _ [space: Space.Create[f.buffersize,Space.virtualMemory], addr: NIL, first: 0, last: 0]; ppw _ IF f.raster.bitsPerPixel=0 THEN 16 ELSE 16/f.raster.bitsPerPixel; wpl _ DivUp[lastPixel-firstPixel+1,ppw]; w _ zone.NEW[WRep _ [fref: f, bref: bref, firstScan: firstScan, lastScan: lastScan, firstPixel: firstPixel, lastPixel: lastPixel, wordsPerLine: wpl, pixelsPerWord: ppw]]; MapBuffer[w,w.firstScan]; }; CloseWindow: PUBLIC PROC[w: WRef] = { Space.Delete[w.bref.space]; zone.FREE[@w.bref]; zone.FREE[@w]; --dangle, dangle }; --scan is absolute scan number MapBuffer: PROC[w: WRef, scan: CARDINAL _ 0] = INLINE {IF scan>w.lastScan THEN Error[outOfRange]; IF w.bref.addr#NIL AND scan IN [w.bref.first..w.bref.last] THEN RETURN; --already mapped in GMBuff[w,scan];}; GMBuff:PROC [w: WRef, scan: CARDINAL _ 0] = {page,offset,lnum,loff: CARDINAL; --compute which file page [page,offset] _ Inline.LongDivMod[num: Inline.LongMult[scan,w.fref.wordsPerLine], den: wordsPerPage]; IF w.bref.addr#NIL THEN Space.Unmap[w.bref.space]; --first time, isn't mapped Space.Map[w.bref.space,[w.fref.file,w.fref.rbase+page]]; --compute the number of the first scanline in the buffer [lnum,loff] _ Inline.LongDivMod[num: offset, den: w.fref.wordsPerLine]; w.bref.addr _ Space.LongPointer[w.bref.space]+loff; w.bref.first _ scan-lnum; w.bref.last _ w.bref.first + Inline.LongDiv[num: Inline.LongMult[w.fref.buffersize,wordsPerPage]-loff, den: w.fref.wordsPerLine] - 1; }; GetWindowParams: PUBLIC PROC[w: WRef] RETURNS[firstScan: CARDINAL, lastScan: CARDINAL, firstPixel: CARDINAL, lastPixel: CARDINAL] = { firstScan _ w.firstScan; lastScan _ w.lastScan; firstPixel _ w.firstPixel; lastPixel _ w.lastPixel; }; MinBufferSize: PUBLIC PROC[w: WRef] RETURNS[length: CARDINAL] = {RETURN[w.wordsPerLine]}; EndOfWindow: PUBLIC PROC[w: WRef] RETURNS[BOOLEAN] = {RETURN[w.nextScanLine=(w.lastScan-w.firstScan)]}; --Buffer: TYPE = LONG DESCRIPTOR FOR ARRAY OF WORD; ReadLine: PUBLIC PROC[w: WRef, buffer: Buffer, line: INTEGER _ -1] = { XFerLine[w,buffer,line,TRUE]; }; WriteLine: PUBLIC PROC[w: WRef, buffer: Buffer, line: INTEGER _ -1] = { XFerLine[w,buffer,line,FALSE]; }; XFerLine: PROC[w: WRef, buffer: Buffer, line: INTEGER _ -1, read: BOOLEAN] = { woff,poff,absline: CARDINAL; word: LONG POINTER; IF w.wordsPerLine>buffer.length THEN Error[bufferTooSmall]; IF line=-1 THEN line _ w.nextScanLine; absline _ CARDINAL[line]+w.firstScan; IF absline > w.lastScan THEN Error[outOfRange]; MapBuffer[w,absline]; [woff,poff] _ Inline.LongDivMod[num:w.firstPixel,den: w.pixelsPerWord]; word _ w.bref.addr+Inline.LongMult[w.fref.wordsPerLine,(absline-w.bref.first)]+woff; IF poff=0 THEN { IF read THEN LongCopy[from: word, to: buffer.addr, nwords: w.wordsPerLine] ELSE LongCopy[from: buffer.addr, to: word, nwords: w.wordsPerLine] } ELSE { src,dst: BitBlt.BitAddress; bit: CARDINAL _ IF w.fref.raster.bitsPerPixel=0 THEN poff ELSE poff*w.fref.raster.bitsPerPixel; bufferwidth: CARDINAL _ w.wordsPerLine*16; filebpl: CARDINAL _ w.fref.wordsPerLine*16; IF read THEN { src _ [word: word, bit: bit]; dst _ [word: buffer.addr, bit: 0]; bbptr^ _ [dst: dst, dstBpl: bufferwidth, src: src, srcDesc: [srcBpl[srcBpl: filebpl]], width: bufferwidth, height: 1, flags: bbflags]; } ELSE { dst _ [word: word, bit: bit]; src _ [word: buffer.addr, bit: 0]; bbptr^ _ [dst: dst, dstBpl: filebpl, src: src, srcDesc: [srcBpl[srcBpl: bufferwidth]], width: bufferwidth, height: 1, flags: bbflags]; }; BitBlt.BITBLT[bbptr]; }; w.nextScanLine _ MIN[line+1,w.lastScan]; }; ReadLines: PUBLIC PROC[w: WRef, buffer: Buffer, line: INTEGER _ -1, count: CARDINAL _ 1] RETURNS[numberRead: CARDINAL] = { RETURN[XFerLines[w,buffer,line,count,TRUE]]; }; WriteLines: PUBLIC PROC[w: WRef, buffer: Buffer, line: INTEGER _ -1, count: CARDINAL _ 1] RETURNS[numberWritten: CARDINAL] = { RETURN[XFerLines[w,buffer,line,count,FALSE]]; }; XFerLines: PROC[w: WRef, buffer: Buffer, line: INTEGER _ -1, count: CARDINAL _ 1, read: BOOLEAN] RETURNS[numberRead: CARDINAL] = { temp: LONG CARDINAL; maxline: LONG CARDINAL _ 0; numberRead _ 0; temp_Inline.LongMult[w.wordsPerLine,count]; IF buffer.addr=NIL OR temp>buffer.length THEN Error[bufferTooSmall]; IF line=-1 THEN line _ w.nextScanLine; IF CARDINAL[line]+w.firstScan > w.lastScan THEN Error[outOfRange]; maxline _ w.firstScan+(buffer.length/w.wordsPerLine)-1; IF w.wordsPerLine=w.fref.wordsPerLine THEN { first: CARDINAL _ line+w.firstScan; lastscan,last: CARDINAL _ first+count-1; to: LONG POINTER _ buffer.addr; from: LONG POINTER _ NIL; nlines,nwords: CARDINAL _ 0; lastscan _ MIN[lastscan,w.lastScan]; IF lastscan>maxline THEN Error[bufferTooSmall]; UNTIL numberRead>= count DO MapBuffer[w,first]; last _ MIN[lastscan,w.bref.last]; nlines _ last-first+1; nwords _ nlines*w.wordsPerLine; from _ w.bref.addr+Inline.LongMult[(first-w.bref.first),w.wordsPerLine]; IF read THEN LongCopy[from: from, to: to, nwords: nwords] ELSE LongCopy[from: to, to: from, nwords: nwords]; numberRead _ numberRead+nlines; first _ last+1; to _ to+nwords; ENDLOOP; } ELSE { tbuffer: Buffer _ [w.wordsPerLine, Heap.MakeNode[zone, w.wordsPerLine]]; to: LONG POINTER _ buffer.addr; tbuffer.length _ w.wordsPerLine; FOR i: CARDINAL IN[0..count) DO IF CARDINAL[line]+w.firstScan>maxline THEN Error[bufferTooSmall]; IF read THEN { ReadLine[w,tbuffer,line ! Error => IF type=outOfRange THEN EXIT ELSE ERROR]; LongCopy[from: tbuffer.addr, to: to, nwords: tbuffer.length]; } ELSE { LongCopy[from: to, to: tbuffer.addr, nwords: tbuffer.length]; WriteLine[w,tbuffer,line ! Error => IF type=outOfRange THEN EXIT ELSE ERROR]; }; line _ line+1; to _ to+w.wordsPerLine; numberRead _ numberRead+1; ENDLOOP; }; w.nextScanLine _ MIN[line+numberRead,w.lastScan]; }; Line1: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..1B]]; Line2: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..3B]]; Line4: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..17B]]; Line8: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..377B]]; Line16: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF WORD]; ReadSample: PUBLIC PROC[w: WRef, line,pixel: CARDINAL] RETURNS[value: CARDINAL] = { lineaddr: LONG POINTER; absline: CARDINAL _ line+w.firstScan; IF absline # w.currline THEN {IF absline > w.lastScan THEN Error[outOfRange]; MapBuffer[w,absline]; w.currline_absline; w.clineaddr _ w.bref.addr+Inline.LongMult[(absline-w.bref.first),w.fref.wordsPerLine]; } ELSE {IF pixel+ w.firstPixel > w.lastPixel THEN Error[outOfRange];}; lineaddr_w.clineaddr; SELECT w.fref.raster.bitsPerPixel FROM 0,1 => RETURN[LOOPHOLE[lineaddr,LONG POINTER TO Line1][pixel]]; 2 => RETURN[LOOPHOLE[lineaddr,LONG POINTER TO Line2][pixel]]; 4 => RETURN[LOOPHOLE[lineaddr,LONG POINTER TO Line4][pixel]]; 8 => RETURN[LOOPHOLE[lineaddr,LONG POINTER TO Line8][pixel]]; 16 => RETURN[LOOPHOLE[lineaddr,LONG POINTER TO Line16][pixel]]; ENDCASE => Error[notImplemented]; w.nextScanLine _ MIN[line+1,w.lastScan]; }; WriteSample: PUBLIC PROC[w: WRef, value: CARDINAL, line,pixel: CARDINAL] = { lineaddr: LONG POINTER; absline: CARDINAL _ line+w.firstScan; IF absline # w.currline THEN {IF absline > w.lastScan THEN Error[outOfRange]; MapBuffer[w,absline]; w.currline_absline; w.clineaddr _ w.bref.addr+Inline.LongMult[(absline-w.bref.first),w.fref.wordsPerLine]; } ELSE {IF pixel+ w.firstPixel > w.lastPixel THEN Error[outOfRange];}; lineaddr_w.clineaddr; SELECT w.fref.raster.bitsPerPixel FROM 0,1 => LOOPHOLE[lineaddr,LONG POINTER TO Line1][pixel] _ value; 2 => LOOPHOLE[lineaddr,LONG POINTER TO Line2][pixel] _ value; 4 => LOOPHOLE[lineaddr,LONG POINTER TO Line4][pixel] _ value; 8 => LOOPHOLE[lineaddr,LONG POINTER TO Line8][pixel] _ value; 16 => LOOPHOLE[lineaddr,LONG POINTER TO Line16][pixel] _ value; ENDCASE => Error[notImplemented]; w.nextScanLine _ MIN[line+1,w.lastScan]; }; ReadAttributes: PROC[f:FRef] = {OPEN AISFormat; addr: LONG POINTER _ NIL; -- address of first word of attributes words: CARDINAL _ 0; -- number of words read from attributes awords: CARDINAL _ apages*Environment.wordsPerPage; header: LONG POINTER TO AISFormat.Header _ NIL; part: LONG POINTER TO AISFormat.PartHeader _ NIL; raster: LONG POINTER TO uca AISFormat.RasterPart _ NIL; placement: LONG POINTER TO AISFormat.PlacementPart _ NIL; photometry: LONG POINTER TO AISFormat.PhotometryPart _ NIL; comment: LONG POINTER TO AISFormat.CommentPart _ NIL; string: LONG STRING _ NIL; apages: Space.PageCount; IF lastARef.fref#NIL THEN IF f.file = lastARef.fref.file THEN RETURN --we just did the read ELSE DeleteLastARef[]; lastARef.fref _ f; Space.Map[space: lastARef.space, window: [file: f.file, base: f.abase]]; addr _ Space.LongPointer[lastARef.space]; header _ addr; IF header.password#AISFormat.aisPassword THEN Error[invalidFile]; -- wrong password IF (header.attributeLength MOD AISFormat.aisWordsPerPage)=0 THEN { apages _ header.attributeLength/wordsPerPage; IF apages > Space.GetAttributes[lastARef.space].size THEN { Space.Delete[lastARef.space]; lastARef.space _ Space.Create[size: apages, parent: Space.virtualMemory]; Space.Map[space: lastARef.space, window: [file: f.file, base: f.abase]]; }; } ELSE Error[invalidFile]; -- illegal attribute length lastARef.header _ zone.NEW[Header _ header^]; words _ SIZE[AISFormat.Header]; DO -- read the parts part _ addr + words; words _ words + part.length; IF words>header.attributeLength THEN Error[invalidFile]; -- part overflows end of attribute section SELECT part.type FROM nil => EXIT; -- no more parts raster => IF raster=NIL THEN {raster _ LOOPHOLE[part]; lastARef.raster _ zone.NEW[uca RasterPart _ raster^]} ELSE Error[invalidFile]; -- multiple raster parts placement => IF placement=NIL THEN {placement _ LOOPHOLE[part]; lastARef.placement _ zone.NEW[PlacementPart _ placement^]} ELSE Error[invalidFile]; -- multiple placement parts photometry => IF photometry=NIL THEN { hlen: INTEGER; photometry _ LOOPHOLE[part]; hlen _ photometry.histogramLength; IF hlen<0 THEN hlen _ 0; lastARef.photometry _ zone.NEW[PhotometryPart[hlen] _ photometry^]; } ELSE Error[invalidFile]; -- multiple photometry parts comment => IF comment=NIL THEN {comment _ LOOPHOLE[part]; lastARef.comment _ zone.NEW[CommentPart _ comment^]} ELSE Error[invalidFile]; -- multiple comment parts ENDCASE => Error[invalidFile]; -- unknown part type ENDLOOP; IF raster=NIL THEN Error[invalidFile]; -- raster part missing IF raster.samplesPerPixel#1 THEN ERROR; -- Can't handle multiple samples per pixel IF raster.codingType#uca THEN ERROR; -- Coding type not UCA }; FirstPage: PROC[file: File.Capability] RETURNS[File.PageNumber] = { RETURN[1]; --should check with the Directory stuff }; DeleteLastARef: PROC = {OPEN lastARef; --using: fref,header,space,raster,placement,photometry,comment IF fref=NIL THEN ERROR; IF fref.write THEN WriteLastARef[]; --don't free the FRef. Someone has a hold of it! IF header#NIL THEN {zone.FREE[@header]; header _ NIL}; IF raster#NIL THEN {zone.FREE[@raster]; raster _ NIL}; IF placement#NIL THEN {zone.FREE[@placement]; placement _ NIL}; IF photometry#NIL THEN {zone.FREE[@photometry]; photometry _ NIL}; IF comment#NIL THEN {zone.FREE[@comment]; comment _ NIL}; Space.Unmap[space]; lastARef.fref _ NIL; }; WriteLastARef: PROC = {OPEN Inline,lastARef; --using: header,space,raster,placement,photometry,comment --assumes the file is mapped to lastARef.space --if all elements are NIL, this is a NOOP to: LONG POINTER _ Space.LongPointer[space]; IF header#NIL THEN {LongCOPY[from: header, to: to, nwords: SIZE[AISFormat.Header]]; to _ to+SIZE[AISFormat.Header]}; IF raster#NIL THEN {LongCOPY[from: raster, to: to, nwords: raster.part.length]; to _ to+raster.part.length}; IF placement#NIL THEN {LongCOPY[from: placement, to: to, nwords: placement.part.length]; to _ to+placement.part.length}; IF photometry#NIL THEN {LongCOPY[from: photometry, to: to, nwords: photometry.part.length]; to _ to+photometry.part.length}; IF comment#NIL THEN {LongCOPY[from: comment, to: to, nwords: comment.part.length]; to _ to+raster.part.length}; }; -- Initialization bbptr^ _ [dst: [word: NIL,bit:0], dstBpl: 0, src: [word: NIL,bit: 0], srcDesc: [srcBpl[srcBpl: 0]], width: 0, height: 0, flags: bbflags] }. -- Last changed by Maureen Stone, 17-Nov-81 17:32:46 fixed overwrite in CreateFile -- Last changed by Maureen Stone, 17-Nov-81 13:59:17 fixed write header in DeleteLastARef, and changed linesPerBlock in CreateFile -- Last changed by Gordon Hamachi, 5-Nov-81 18:47:08, to fix overflow on first check in XferLines -- Last changed by Gordon Hamachi, 5-Nov-81 18:38:18, to fix the computation of rsize in SetBufferSize -- Last changed by Maureen Stone, 5-Nov-81 17:26:28 -- Last changed by John Warnock, 23-Nov-81 16:20:02, changed MapBuffer,ReadSample, and WriteSample