CtFileImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Plass and Bloomenthal, July 4, 1992 11:21 am PDT
Glassner, July 9, 1991 2:10 pm PDT
DIRECTORY AISFileFormat, AISIO, Basics, CtBasic, CtFile, Commander, FileNames, FS, Imager, ImagerBackdoor, ImagerBox, ImagerColor, ImagerPixel, ImagerPixelArray, ImagerSample, ImagerTransformation, InterpressInterpreter, IO, MessageWindow, Process, RefText, Rope, SF;
CtFileImpl: CEDAR PROGRAM
IMPORTS AISIO, Basics, CtBasic, FileNames, FS, ImagerSample, IO, MessageWindow, Process, RefText, Rope, SF
EXPORTS CtFile
~ BEGIN
SampleMap:   TYPE ~ CtBasic.SampleMap;
SampleMaps:   TYPE ~ CtBasic.SampleMaps;
PixelArray:   TYPE ~ CtBasic.PixelArray;
RealPair:    TYPE ~ CtBasic.RealPair;
FileInfo:     TYPE ~ CtFile.FileInfo;
FileType:    TYPE ~ CtFile.FileType;
Context:    TYPE ~ Imager.Context;
Box:     TYPE ~ ImagerSample.Box;
Vec:     TYPE ~ ImagerSample.Vec;
SampleBuffer:  TYPE ~ ImagerSample.SampleBuffer;
RasterSampleMap: TYPE ~ ImagerSample.RasterSampleMap;
STREAM:    TYPE ~ IO.STREAM;
ROPE:     TYPE ~ Rope.ROPE;
File Write Operations
WriteMapsToAIS: PUBLIC PROC [maps: SampleMaps, name: ROPE, stream: STREAM ¬ NIL] ~ {
saving: ROPE ¬ IO.PutFLR["Saving (%g %g %g %g) ",
LIST[IO.int[maps.x], IO.int[maps.y], IO.int[maps.w], IO.int[maps.h]]];
SELECT maps.bpp FROM
1, 8 => {
IF stream # NIL THEN IO.PutF[stream, "%g%g . . . ", IO.rope[saving], IO.rope[name]];
SaveSampleMapToFile[maps[0].map, name];
IF stream # NIL THEN IO.PutRope[stream, "done\n"];
};
24 => {
IF stream # NIL THEN IO.PutRope[stream, saving];
IF stream # NIL THEN IO.PutF1[stream, "%g-red.ais . . . ", IO.rope[name]];
SaveSampleMapToFile[maps[0].map, Rope.Concat[name, "-red.ais"]];
IF stream # NIL THEN IO.PutF1[stream, "%g-grn.ais . . . ", IO.rope[name]];
SaveSampleMapToFile[maps[1].map, Rope.Concat[name, "-grn.ais"]];
IF stream # NIL THEN IO.PutF1[stream, "%g-blu.ais . . . ", IO.rope[name]];
SaveSampleMapToFile[maps[2].map, Rope.Concat[name, "-blu.ais"]];
IF stream # NIL THEN IO.PutRope[stream, "done\n"];
};
ENDCASE => NULL;
};
SaveSampleMapToFile: PUBLIC PROC [
source: SampleMap,
aisFileName: ROPE,
comment: ROPE ¬ NIL]
~ {
AISIO.Write[aisFileName, source, NIL, NIL, LIST[comment]];
};
File Read Operations
Error: PUBLIC ERROR [reason: ROPE] = CODE;
ReadFile: PUBLIC PROC [
baseName: ROPE,
aisX, aisY: CARDINAL ¬ 0,
aisW, aisH: CARDINAL ¬ LAST[CARDINAL],
maps: SampleMaps ¬ NIL]
RETURNS [ret: SampleMaps]
~ {
i: FileInfo ¬ Parse[baseName];
ret ¬ SELECT i.type FROM
bw => Read8BitFile[i.names[0], aisX, aisY, aisW, aisH, maps],
color => Read24BitFile[i.names[0], i.names[1], i.names[2], aisX, aisY, aisW, aisH, maps],
ENDCASE => NIL;
};
ReadFileAndClip: PROC [name: ROPE, x, y, w, h: CARDINAL] RETURNS [map: SampleMap] ~ {
V: PROC [c: AISFileFormat.Card16] RETURNS [CARD] ~ {RETURN[Basics.Card16FromH[c]]};
i: AISIO.Info ¬ AISIO.ReadInfo[name];
w ¬ MIN[w, V[i.raster.scanLength]];
h ¬ MIN[h, V[i.raster.scanCount]];
map ¬ ImagerSample.ZeroOrigin[ImagerSample.Clip[AISIO.Read[name], [[y, x], [y+h, x+w]]]];
};
Read8BitFile: PUBLIC PROC [
name: ROPE,
aisX, aisY: CARDINAL ¬ 0,
aisW, aisH: CARDINAL ¬ LAST[CARDINAL],
maps: SampleMaps ¬ NIL]
RETURNS [ret: SampleMaps]
~ {
bw: SampleMap ¬ ReadFileAndClip[name, aisX, aisY, aisW, aisH];
size: SF.Vec ¬ ImagerSample.GetSize[bw];
IF (ret ¬ maps) = NIL OR maps.w < size.f OR maps.h < size.s
THEN ret ¬ CtBasic.CreateMaps[8, 0, 0, size.f, size.s];
ImagerSample.BasicTransfer[ret[0].map, bw, ret.box.min,, size];
};
Read24BitFile: PUBLIC PROC [
rName, gName, bName: ROPE,
aisX, aisY: CARDINAL ¬ 0,
aisW, aisH: CARDINAL ¬ LAST[CARDINAL],
maps: SampleMaps ¬ NIL]
RETURNS [ret: SampleMaps]
~ {
Union: PROC [box1, box2: Box] RETURNS [u: Box] ~ {
u ¬ [SF.Min[box1.min, box2.min], SF.Max[box1.max, box2.max]];
};
GetBox: PROC [m: SampleMap] RETURNS [b: Box] ~ {b ¬ ImagerSample.GetBox[m]};
red: SampleMap ¬ ReadFileAndClip[rName, aisX, aisY, aisW, aisH];
grn: SampleMap ¬ ReadFileAndClip[gName, aisX, aisY, aisW, aisH];
blu: SampleMap ¬ ReadFileAndClip[bName, aisX, aisY, aisW, aisH];
size: SF.Vec ¬ SF.Size[Union[GetBox[red], Union[GetBox[grn], GetBox[blu]]]];
IF (ret ¬ maps) = NIL OR maps.bpp # 24 OR maps.w < size.f OR maps.h < size.s
THEN ret ¬ CtBasic.CreateMaps[24, 0, 0, size.f, size.s];
ImagerSample.BasicTransfer[ret[0].map, red, ret.box.min,, size];
ImagerSample.BasicTransfer[ret[1].map, grn, ret.box.min,, size];
ImagerSample.BasicTransfer[ret[2].map, blu, ret.box.min,, size];
};
ReadPixelArray: PUBLIC PROC [aisFileName: ROPE] RETURNS [pa: PixelArray] ~ {
pa ¬ CtBasic.PixelArrayFromSampleMap[AISIO.Read[aisFileName]];
};
Dump File Operations
ReadDumpFile: PUBLIC PROC [
fileName: ROPE,
maps: SampleMaps ¬ NIL,
ascii: BOOL ¬ FALSE,
nChannels: NAT ¬ 0,
width, height: NAT ¬ 0,
contiguous: BOOL ¬ TRUE]
RETURNS [SampleMaps]
~ {
LineStatus: PROC [y: NAT] ~ {
Process.CheckForAbort[];
IF y MOD 10 = 0 OR y = height-1 THEN
MessageWindow.Append[IO.PutFR["line %g/%g", IO.int[y], IO.int[height-1]], TRUE];
};
ReadLine: PROC [y: NAT, b: SampleBuffer, m: SampleMap] ~ {
LineStatus[y];
IF ascii
THEN FOR x: NAT IN [0..width) DO b[x] ¬ IO.GetInt[s]; ENDLOOP
ELSE FOR x: NAT IN [0..width) DO b[x] ¬ IO.GetByte[s]; ENDLOOP;
ImagerSample.PutSamples[m, [y, 0],, b,, width];
};
box: SF.Box;
bw, r, g, b: SampleBuffer;
bwMap, rMap, gMap, bMap: SampleMap;
s: STREAM ¬ FS.StreamOpen[fileName ! FS.Error => Error["Can't open file."]];
IF s = NIL THEN Error["Can't open file."];
IF nChannels = 0 OR width = 0 OR height = 0 THEN {
IF ascii
THEN {
nChannels ¬ IO.GetInt[s];
width ¬ IO.GetInt[s];
height ¬ IO.GetInt[s];
}
ELSE {
nChannels ¬ INT[Basics.Card16FromH[IO.GetHWord[s]]];
width ¬ INT[Basics.Card16FromH[IO.GetHWord[s]]];
height ¬ INT[Basics.Card16FromH[IO.GetHWord[s]]];
};
};
box ¬ [[0, 0], [height, width]];
IF maps = NIL OR maps.w < width OR maps.h < height OR maps.nChannels # nChannels
THEN maps ¬ CtBasic.CreateMaps[nChannels*8, 0, 0, width, height];
IF nChannels = 1
THEN {
bwMap ¬ ImagerSample.ObtainScratchMap[box, 8];
bw ¬ ImagerSample.NewSamples[width];
}
ELSE {
rMap ¬ ImagerSample.ObtainScratchMap[box, 8];
gMap ¬ ImagerSample.ObtainScratchMap[box, 8];
bMap ¬ ImagerSample.ObtainScratchMap[box, 8];
r ¬ ImagerSample.NewSamples[width];
b ¬ ImagerSample.NewSamples[width];
g ¬ ImagerSample.NewSamples[width];
};
SELECT TRUE FROM
nChannels = 1 =>
FOR y: NAT IN [0..height) DO ReadLine[y, bw, bwMap]; ENDLOOP;
nChannels = 3 AND contiguous =>
FOR y: NAT IN [0..height) DO
LineStatus[y];
IF ascii
THEN
FOR x: NAT IN [0..width) DO
r[x] ¬ IO.GetInt[s];
g[x] ¬ IO.GetInt[s];
b[x] ¬ IO.GetInt[s]; 
ENDLOOP
ELSE
FOR x: NAT IN [0..width) DO
r[x] ¬ IO.GetByte[s];
g[x] ¬ IO.GetByte[s];
b[x] ¬ IO.GetByte[s]; 
ENDLOOP;
ImagerSample.PutSamples[rMap, [y, 0],, r,, width];
ImagerSample.PutSamples[gMap, [y, 0],, g,, width];
ImagerSample.PutSamples[bMap, [y, 0],, b,, width];
ENDLOOP;
nChannels = 3 AND NOT contiguous => {
FOR y: NAT IN [0..height) DO ReadLine[y, r, rMap]; ENDLOOP;
FOR y: NAT IN [0..height) DO ReadLine[y, g, gMap]; ENDLOOP;
FOR y: NAT IN [0..height) DO ReadLine[y, b, bMap]; ENDLOOP;
};
ENDCASE;
IF nChannels = 1
THEN {
ImagerSample.Transfer[dst: maps[0].map, src: bwMap];
ImagerSample.ReleaseScratchMap[bwMap];
}
ELSE {
pm: ImagerPixel.PixelMap ← ImagerPixel.MakePixelMap[rMap, gMap, gMap];
pa: ImagerPixelArray.PixelArray←ImagerPixelArray.FromPixelMap[pm,box,[right,down]];
ImagerPixelArray.Transfer[pa: pa, dst: maps[0].map];
ImagerSample.Transfer[maps[0].map, rMap];
ImagerSample.Transfer[maps[1].map, gMap];
ImagerSample.Transfer[maps[2].map, bMap];
ImagerSample.ReleaseScratchMap[rMap];
ImagerSample.ReleaseScratchMap[gMap];
ImagerSample.ReleaseScratchMap[bMap];
};
RETURN[maps];
};
Display Operations
ViewFile: PUBLIC PROC [
maps: SampleMaps,
baseName: ROPE,
center, noPlace: BOOL ¬ FALSE,
aisX, aisY: CARDINAL ¬ 0,
aisW, aisH: CARDINAL ¬ LAST[CARDINAL]]
RETURNS [error: ROPE ¬ NIL] ~ {
Action: PROC ~ {
r, g, b: ROPE;
type: FileType;
[type, r, g, b] ← Parse[baseName];
error ← SELECT type FROM
ip => ViewIpFile[r],
bw => IF maps.bpp = 24
THEN View24BitFile[maps, r, r, r, center, noPlace, aisX, aisY, aisW, aisH]
ELSE View8BitFile[maps[0].map, r, center, noPlace, aisX, aisY, aisW, aisH],
color => IF maps.bpp = 24
THEN View24BitFile[maps, r, g, b, center, noPlace, aisX, aisY, aisW, aisH]
ELSE ViewColorFiles[r, g, b],
ENDCASE => Rope.Cat["Bad name: ", baseName];
};
Terminal.ModifyColorFrame[Terminal.Current[], Action]
};
View8BitFile: PUBLIC PROC [
maps: SampleMaps,
name: ROPE,
center, noPlace: BOOL ¬ FALSE,
aisX, aisY: CARDINAL ¬ 0,
aisW, aisH: CARDINAL ¬ LAST[CARDINAL]]
RETURNS [error: ROPE ¬ NIL]
~ {
box: Box ← ImagerSample.GetBox[map];
size: SF.Vec ← SF.Size[box];
ais: AIS.FRef ← AISOpenFile[name ! Error => {error ← reason; GOTO Bad}];
bpp: NATAIS.ReadRaster[ais].bitsPerPixel;
place: AIS.Placement ← AIS.ReadPlacement[ais];
IF noPlace THEN place ← NIL;
SELECT bpp FROM
1, 8 => {
ENABLE AIS.Error => {error ← "Error opening file."; GOTO Bad};
wRef: AIS.WRef ← AIS.OpenWindow[ais, aisY, aisY+aisH-1, aisX, aisX+aisW-1];
w: INTEGER ← wRef.lastPixel-wRef.firstPixel+1;
h: INTEGER ← wRef.lastScan-wRef.firstScan+1;
lineMap: RasterSampleMap ← ImagerSample.NewSampleMap[[[0, 0], [1, w]], bpp, bpp*w];
lineBuf: AIS.Buffer ← LineBufferFromRasterSampleMap[lineMap];
shift: Vec ← [0, 0];
SELECT TRUE FROM
center => shift ← [(h-size.s)/2, (w-size.f)/2];
place # NIL => map ← ImagerSample.Shift[map, [-place.yBottom, -place.xLeft]];
ENDCASE;
IF shift.f < 0 THEN {map ← ImagerSample.Shift[map, [0, shift.f]]; shift.f ← 0};
IF shift.s < 0 THEN {map ← ImagerSample.Shift[map, [shift.s, 0]]; shift.s ← 0};
FOR i: INT IN [0..h) WHILE i <= size.s DO
TRUSTED {AIS.UnsafeReadLine[wRef, lineBuf, i+shift.s]};
ImagerSample.Transfer[map,ImagerSample.Shift[lineMap,[box.min.s+i,box.min.f-shift.f]]];
Process.CheckForAbort[];
ENDLOOP;
AIS.CloseWindow[wRef];
};
ENDCASE => error ← "File isn't 1 or 8 bits per pixel.";
AIS.CloseFile[ais];
EXITS Bad => NULL;
};
View24BitFile: PUBLIC PROC [
maps: SampleMaps,
rName, gName, bName: ROPE,
center, noPlace: BOOL ¬ FALSE,
aisX, aisY: CARDINAL ¬ 0,
aisW, aisH: CARDINAL ¬ LAST[CARDINAL]]
RETURNS [error: ROPE ¬ NIL]
~ {
For 512 by 480 image, Preview and ViewColorFiles[] take ~ 23 secs.
The previous method of separating 16 bpp red/green (see bottom of this file) took ~ 14.3 secs.
The current method (using delta of [0, 2]) takes ~ 10.3 secs.
ENABLE Error => {error ← reason; GOTO Bad};
rAis: AIS.FRef ← AISOpenFile[rName];
gAis: AIS.FRef ← AISOpenFile[gName];
bAis: AIS.FRef ← AISOpenFile[bName];
placement: AIS.Placement ← AIS.ReadPlacement[rAis];
r: AIS.Raster ← AIS.ReadRaster[rAis];
IF noPlace THEN placement ← NIL;
IF r.bitsPerPixel = 8 AND r^ = AIS.ReadRaster[gAis]^ AND r^ = AIS.ReadRaster[bAis]^
THEN {
rWRef: AIS.WRef ← AIS.OpenWindow[rAis, aisY, aisY+aisH-1, aisX, aisX+aisW-1];
gWRef: AIS.WRef ← AIS.OpenWindow[gAis, aisY, aisY+aisH-1, aisX, aisX+aisW-1];
bWRef: AIS.WRef ← AIS.OpenWindow[bAis, aisY, aisY+aisH-1, aisX, aisX+aisW-1];
w: INTEGER ← rWRef.lastPixel-rWRef.firstPixel+1;
h: INTEGER ← rWRef.lastScan-rWRef.firstScan+1;
rSampleBuf: SampleBuffer ← ImagerSample.ObtainScratchSamples[w];
gSampleBuf: SampleBuffer ← ImagerSample.ObtainScratchSamples[w];
bSampleBuf: SampleBuffer ← ImagerSample.ObtainScratchSamples[w];
rMap: RasterSampleMap ← ImagerSample.NewSampleMap[[[0, 0], [1, w]], 8, 8*w];
gMap: RasterSampleMap ← ImagerSample.NewSampleMap[[[0, 0], [1, w]], 8, 8*w];
bMap: RasterSampleMap ← ImagerSample.NewSampleMap[[[0, 0], [1, w]], 8, 8*w];
rgMap: SampleMap ← CtBasic.GetRedGrn[maps[0].map];
rAISBuf: AIS.Buffer ← LineBufferFromRasterSampleMap[rMap];
gAISBuf: AIS.Buffer ← LineBufferFromRasterSampleMap[gMap];
bAISBuf: AIS.Buffer ← LineBufferFromRasterSampleMap[bMap];
shift: Vec ← [0, 0];
SELECT TRUE FROM
center => shift ← [(h-maps.size.s)/2, (w-maps.size.f)/2];
placement # NIL => {
rgMap ← ImagerSample.Shift[rgMap, [-placement.yBottom, -2*placement.xLeft]];
maps[1].map←ImagerSample.Shift[maps[1].map,[-placement.yBottom,-placement.xLeft]];
};
ENDCASE;
IF shift.f < 0 THEN {
rgMap ← ImagerSample.Shift[rgMap, [0, 2*shift.f]];
maps[1].map ← ImagerSample.Shift[maps[1].map, [0, shift.f]];
shift.f ← 0;
};
IF shift.s < 0 THEN {
rgMap ← ImagerSample.Shift[rgMap, [shift.s, 0]];
maps[1].map ← ImagerSample.Shift[maps[1].map, [shift.s, 0]];
shift.s ← 0;
};
FOR i: INT IN [0..MIN[h, maps.size.s]) DO
y: NAT ← i+shift.s;
TRUSTED {AIS.UnsafeReadLine[rWRef, rAISBuf, y]}; -- file to rMap (rAISBuf)
TRUSTED {AIS.UnsafeReadLine[gWRef, gAISBuf, y]}; -- file to gMap (gAISBuf)
TRUSTED {AIS.UnsafeReadLine[bWRef, bAISBuf, y]}; -- file to bMap (bAISBuf)
ImagerSample.GetSamples[rMap, [0, shift.f],, rSampleBuf, 0, maps.size.f]; -- rSampleBuf
ImagerSample.GetSamples[gMap, [0, shift.f],, gSampleBuf, 0, maps.size.f]; -- gSampleBuf
ImagerSample.GetSamples[bMap, [0, shift.f],, bSampleBuf, 0, maps.size.f]; -- bSampleBuf
Write the red, starting at 0, with delta.f = 2, thus writing the even bytes:
ImagerSample.PutSamples[rgMap, [i+maps.y, 2*maps.x], [0, 2], rSampleBuf, 0, maps.w];
Write the green, starting at 1, with delta.f = 2, thus writing the odd bytes:
ImagerSample.PutSamples[rgMap, [i+maps.y, 1+2*maps.x], [0, 2], gSampleBuf, 0, maps.w];
Write the blue:
ImagerSample.Transfer[maps[1].map, ImagerSample.Shift[bMap, [maps.y+i, maps.x+-shift.f]]];
Process.CheckForAbort[];
ENDLOOP;
AIS.CloseWindow[rWRef];
AIS.CloseWindow[gWRef];
AIS.CloseWindow[bWRef];
ImagerSample.ReleaseScratchSamples[rSampleBuf];
ImagerSample.ReleaseScratchSamples[gSampleBuf];
ImagerSample.ReleaseScratchSamples[bSampleBuf];
TRUSTED {
ImagerSample.ReleaseDescriptor[rMap];
ImagerSample.ReleaseDescriptor[gMap];
ImagerSample.ReleaseDescriptor[bMap];
ImagerSample.ReleaseDescriptor[rgMap];
};
}
ELSE error ← "Error in viewing file.";
AIS.CloseFile[rAis];
AIS.CloseFile[gAis];
AIS.CloseFile[bAis];
EXITS Bad => NULL;
};
Display: PUBLIC PROC [
context: Context,
pa: ImagerPixelArray.PixelArray,
op: ImagerColor.ColorOperator,
center: BOOL ¬ TRUE]
~ {
r1: ImagerBox.Rectangle ← ViewRectangle[pa];
r2: ImagerBox.Rectangle ← ImagerBackdoor.GetBounds[context];
Inner: PROC ~ {
IF center
THEN Imager.TranslateT[context, [(r2.w-r1.w)/2, (r2.h-r1.h)/2]]
ELSE Imager.TranslateT[context, [0.0, r2.h-r1.h]];
Imager.SetSampledColor[context, pa, ViewPort[], op];
Imager.MaskRectangle[context, ViewRectangle[pa]];       
};
Process.CheckForAbort[];
Imager.DoSave[context, Inner];
};
ViewRectangle: PROC [pa: ImagerPixelArray.PixelArray]
RETURNS [rect: ImagerBox.Rectangle] ~ {
rect ← ImagerTransformation.TransformRectangle[pa.m, [0, 0, pa.sSize, pa.fSize]];
};
ViewPort: PROC RETURNS [ImagerTransformation.Transformation] ~ {
RETURN[ImagerTransformation.Scale[1]];
};
ViewDitherFile: PUBLIC PROC [
fileName: ROPE,
context: Context ¬ NIL,
center, cmapInit: BOOL]
RETURNS [error: ROPE ¬ NIL] ~ {
pa: ImagerPixelArray.PixelArray;
pa ← ImagerPixelArray.FromAIS[fileName !
FS.Error, ImagerPixelArray.Error => {error ← "Couldn't make dither array"; CONTINUE}];
IF error # NIL THEN RETURN;
IF context = NIL THEN context ← CtBasic.InitCd[gray, TRUE, TRUE, cmapInit];
Display[context, pa, ImagerColor.NewColorOperatorGrayLinear[255, 0], center];
};
ViewGrayFile: PUBLIC PROC [fileName: ROPE, context: Context ¬ NIL, center, cmapInit: BOOL]
RETURNS [error: ROPE ¬ NIL] ~ {
pa: ImagerPixelArray.PixelArray;
pa ← ImagerPixelArray.FromAIS[fileName !
FS.Error, ImagerPixelArray.Error => {error ← "Couldn't make gray array"; CONTINUE}];
IF error # NIL THEN RETURN;
IF context = NIL THEN context ← CtBasic.InitCd[gray, TRUE, TRUE, cmapInit];
Display[context, pa, ImagerColor.NewColorOperatorGrayLinear[255, 0], center];
};
ViewColorFiles: PUBLIC PROC [r, g, b: ROPE, center, cmapInit: BOOL ¬ TRUE]
RETURNS [error: ROPE ¬ NIL]
~ {
type: ATOM ← ColorDisplayManager.NextState[].type;
pa: ImagerPixelArray.PixelArray;
IF type # $Dither8 AND type # $FullColor THEN
RETURN["To view color files, set display mode (using 'Ct On') to 24 or Dither"];
pa ← ImagerPixelArray.Join3AIS[r, g, b !
FS.Error, ImagerPixelArray.Error => {error ← "Couldn't make color array"; CONTINUE}];
IF error = NIL THEN Display[
CtBasic.InitCd[color, TRUE, TRUE, cmapInit],
pa,
ImagerColor.NewColorOperatorRGB[255],
center];
};
Interpress Operations
IpOpenFailed: ERROR = CODE;
LogError: PUBLIC InterpressInterpreter.LogProc ~ {
WITH ProcessProps.GetProp[$CommanderHandle] SELECT FROM
cmd: Commander.Handle =>
IO.PutRope[cmd.err, Rope.Concat["\n Interpress error: ", explanation]];
ENDCASE => NULL;
IF class = 0 THEN ERROR IpOpenFailed;
};
OpenInterpress: PUBLIC PROC [name: ROPE] RETURNS [master: InterpressInterpreter.Master] ~ {
master ← InterpressInterpreter.Open[name, LogError
! IpOpenFailed => {master ← NIL; CONTINUE}];
};
ViewIpFile: PUBLIC PROC [
name: ROPE,
scale: RealPair ¬ [1.0, 1.0],
shift: RealPair ¬ [0.0, 0.0],
cmapInit: BOOL ¬ TRUE]
RETURNS [error: ROPE ¬ NIL]
~ {
type: CtBasic.CdType ~
IF CtBasic.GetColorDisplayBpp[] = 24 THEN smooth ELSE color;
context: Context ~ CtBasic.InitCd[type, FALSE, FALSE, cmapInit];
master: InterpressInterrpeter.Master ~ OpenInterpress[name];
IF master = NIL THEN error ← "Nil interpress master";
IF error # NIL THEN RETURN;
Imager.Scale2T[context, scale];
Imager.TranslateT[context, shift];
FOR page: INT IN [1..master.pages] DO
Action1: PROC ~ {
Imager.SetColor[context, Imager.white];
Imager.MaskRectangle[context, ImagerBackdoor.GetBounds[context]];
};
Action2: PROC ~ {InterpressInterpreter.DoPage[master, page, context, LogError]};
Process.CheckForAbort[];
Imager.DoSaveAll[context, Action1];
Imager.DoSaveAll[context, Action2];
ENDLOOP;
InterpressInterpreter.Close[master];
};
Parsing Procedures
Parse: PUBLIC PROC [fileName: ROPE] RETURNS [i: FileInfo] ~ {
SuffixIs: PROC [r: ROPE] RETURNS [BOOL] ~ {RETURN[Rope.Equal[suffix, r, FALSE]]};
name: ROPE ¬ FileNames.ResolveRelativePath[fileName];
suffix: ROPE ¬ FileNames.Tail[FileNames.StripVersionNumber[name], '.];
IF (SuffixIs["ip"] OR SuffixIs["interpress"]) AND TestIpName[name]
THEN {i.type ¬ ip; i.names[0] ¬ name; RETURN};
IF SuffixIs["ais"] AND FileExists[name] THEN {i.type ¬ bw; i.names[0] ¬ name; RETURN};
i.names ¬ GetColorAISNames[name];
IF i.names[0] # NIL AND i.names[1] # NIL AND i.names[2] # NIL THEN {
i.type ¬ color;
RETURN;
};
IF FileExists[Rope.Concat[name, ".ais"]]
THEN {i.type ¬ bw; i.names[0] ¬ Rope.Concat[name, ".ais"]; RETURN};
IF TestIpName[Rope.Concat[name, ".ip"]]
THEN {i.type ¬ ip; i.names[0] ¬ Rope.Concat[name, ".ip"]; RETURN};
IF TestIpName[Rope.Concat[name, ".interpress"]]
THEN {i.type ¬ bw; i.names[0] ¬ Rope.Concat[name, ".interpress"]; RETURN};
IF FileExists[name] THEN {i.type ¬ bw; i.names[0] ¬ name};
};
TestIpName: PROC [name: ROPE] RETURNS [ok: BOOL ¬ FALSE] ~ {
IF FileExists[name] THEN {
ipText: REF TEXT ~ "Interpress/";
text: REF TEXT ¬ NEW[TEXT[ipText.length]];
s: FS.STREAM ¬ FS.StreamOpen[name ! FS.Error => GOTO BadFile];
[] ¬ IO.GetBlock[s, text];
ok ¬ RefText.Equal[ipText, text, FALSE];
IO.Close[s];
};
EXITS BadFile => RETURN[FALSE];
};
FileExists: PROC [name: ROPE] RETURNS [ok: BOOL ¬ TRUE] ~ {
[] ¬ FS.FileInfo[name ! FS.Error => {ok ¬ FALSE; CONTINUE}];
};
AisSuffix: PROC [base, suffix: ROPE] RETURNS [name: ROPE] ~ {
name ¬ IO.PutFR["%g-%g.ais", IO.rope[base], IO.rope[suffix]];
};
FileChoice: PROC [r: ROPE, a: ROPE ¬ NIL, b: ROPE ¬ NIL, c: ROPE ¬ NIL]
RETURNS [result: ROPE] ~ {
IF FileExists[result ¬ AisSuffix[r, a]] THEN RETURN;
IF b = NIL THEN RETURN[NIL];
IF FileExists[result ¬ AisSuffix[r, b]] THEN RETURN;
IF c = NIL THEN RETURN[NIL];
IF NOT FileExists[result ¬ AisSuffix[r, c]] THEN RETURN[NIL];
};
GetColorAISNames: PUBLIC PROC [name: ROPE] RETURNS [names: ARRAY [0..3) OF ROPE] ~ {
names[0] ¬ FileChoice[name, "red", "r"];
names[1] ¬ FileChoice[name, "grn", "green", "g"];
names[2] ¬ FileChoice[name, "blu", "blue", "b"];
};
END.