home *** CD-ROM | disk | FTP | other *** search
- -- $Source: /home/harp/1/proto/monoBANK/winnt/pcxops.adb,v $
- -- $Revision: 1.3 $ $Date: 95/12/15 16:49:39 $ $Author: mg $
- -- $Id: pcxops.adb 1.4 1995/02/08 18:30:50 mps Exp mps $
- --
- -- This package performs operations on PCX files.
- -- It uses 'use' clauses like the other package bodies. Only pcx main does
- -- not use 'use' clauses.
- --
-
- with PcxChild;
- with Win32.WinDef;
- with Win32.WinBase;
- with Win32.WinUser;
- with Win32.WinGdi;
- with Interfaces.C;
- with Unchecked_Conversion;
-
- use Win32;
- use Win32.WinDef;
-
-
- package body PcxOps is
-
- use type Win32.INT;
- use type Win32.LONG;
-
- --
- -- These are file operations performed with the PCX file.
- --
- rd_only : constant := 0;
- open_default : constant := 8#644#; -- -rw--r--r--
- seek_set : constant := 0; -- set file pointer = OFFSET bytes
- seek_cur : constant := 1; -- set file pointer = current + OFFSET
- seek_end : constant := 2; -- set file pointer = EOF + OFFSET
-
-
- function Open(PATH : LPCSTR;
- OFLAG : INT;
- MODE : INT:= open_default) return INT;
- pragma Interface(C, open);
- pragma Interface_Name(open, "_open");
-
- -- returns -1 if error
- function Close(FILE_DES : INT) return INT;
- pragma Interface(C, close);
- pragma Interface_Name(Close, "_close");
-
- -- returns number of bytes actually read
- function Read(FILE_DESC : INT;
- BUFFER : System.ADDRESS;
- BYTES_TO_READ : INT) return INT;
- pragma Interface(C, read);
- pragma Interface_Name(Read, "_read");
-
- -- returns file pointer value
- function Lseek(FILE_DESC : INT;
- OFFSET : INT;
- WHENCE : INT) return INT;
- pragma Interface(C, lseek);
- pragma Interface_Name(Lseek, "_lseek");
- --
- --
- -- This is the PCX header and associated types/constants for processing the
- -- file.
- --
- black : constant COLORREF := 0;
- repeat_signature : constant := 16#C0#;
- repeat_count_mask : constant := 16#3F#;
-
- type PALETTEYPE is array(0..47) of BYTE;
- type RESERVEDYPE is array(0..57) of BYTE;
-
- type PCX_HEADER_RECORD is record
- MANUFACTURER : BYTE;
- VERSION : BYTE;
- ENCODING : BYTE;
- BITS_PER_PIXEL : BYTE;
- XMIN : SHORT;
- YMIN : SHORT;
- XMAX : SHORT;
- YMAX : SHORT;
- HRES : SHORT;
- VRES : SHORT;
- PALETTE : PALETTEYPE;
- RESERVED_1 : BYTE;
- NUM_PLANES : BYTE;
- BYTES_PER_LINE : SHORT;
- TYPE_OF_PALETTE : SHORT;
- RESERVED_2 : RESERVEDYPE;
- end record;
-
- --
- -- This is for keeping the PCX file in memory. Note that it stays in compressed
- -- form.
- --
- max_pcx_file : constant := 500000;
- type PCX_BYTES_ARRAY is array(0..max_pcx_file) of BYTE;
-
- --
- -- This type is used to keep the level of zoom.
- --
- type ZOOM_TYPE is delta 2.0 ** (-16) range -32_767.0..32_767.0;
-
- --
- -- This type is used to keep a stack of the zoom levels. This allows easy
- -- zoom in/zoom out.
- --
- type STACK_ELEMENT is record
- X_OFFSET : INT;
- Y_OFFSET : INT;
- X_SIZE : INT;
- Y_SIZE : INT;
- end record;
- max_stack : constant := PcxChild.max_images;
- type STACK_TYPE is array(1..max_stack) of STACK_ELEMENT;
-
-
- --
- -- Keeps track of the various image display parameters.
- --
- type INSTANCE_RECORD is record
- CHILDHWND : HWND;
- PCX_BYTES : PCX_BYTES_ARRAY;
- PCX_HEADER : PCX_HEADER_RECORD;
- X_OFFSET : INT;
- Y_OFFSET : INT;
- X_SIZE : INT;
- Y_SIZE : INT;
- X_SCALE : ZOOM_TYPE;
- Y_SCALE : ZOOM_TYPE;
- STACK : STACK_TYPE;
- STACK_PTR : INTEGER;
- BITS_PER_LINE : INT;
- end record;
-
- type INSTANCE_ARRAY is array(1..PcxChild.max_images) of INSTANCE_RECORD;
-
- INSTANCE : INSTANCE_ARRAY;
- MAX_WINDOWS : INTEGER := 0;
-
- -- aliased for function Push
- --
- zoom_msg : aliased constant Win32.CHAR_Array := "Zoom stack full" & Nul;
- error_msg : aliased constant Win32.CHAR_Array := "Pcx Error" & Nul;
-
- -- aliased for function Pop
- zoom_msg2 : aliased constant Win32.CHAR_Array := "Zoomed all the way out" & Nul;
- info_msg2 : aliased constant Win32.CHAR_Array := "Pcx Information" & Nul;
-
- -- aliased for procedure Display
- CLIENT_RECT : aliased RECT;
-
- -- aliased for procedure Zoom_In
- info_msg3 : aliased constant Win32.CHAR_Array := "Pcx Information" & Nul;
- zoom_err : aliased constant Win32.CHAR_Array := "Zoom Scale Set to 1" & Nul;
-
- -- aliased for procedure Initial_Display
- error_msg2 : aliased constant Win32.CHAR_Array := "PCX file too big" & Nul;
- title_msg : aliased constant Win32.CHAR_Array := "Pcx Error" & Nul;
-
-
- function CP(S : Win32.CHAR_Array) return Win32.LPCSTR is
- function UC is new Ada.Unchecked_Conversion(System.Address,Win32.LPCSTR);
- begin
- return UC(S(S'First)'Address);
- end CP;
-
- --
- -- Unchecked_Conversions.
- -- This function translates from an HDC to a WPARAM for SendMessage.
- --
- function Hdc_To_Wparam is new Unchecked_Conversion(HDC, WPARAM);
-
- --
- -- Find_Instance returns the index of the array element associated with
- -- the HWND passed in.
- --
- function Find_Instance(HWND : HWND) return INTEGER is
-
- use type System.Address;
-
- INDEX : INTEGER;
-
- begin
- INDEX := 1;
- for I in 1..MAX_WINDOWS loop
- if HWND = INSTANCE(I).CHILDHWND then
- INDEX := I;
- exit;
- end if;
- end loop;
- return INDEX;
- end Find_Instance;
-
- --
- -- Saves the state of X_OFFSET, Y_OFFSET, X_SIZE and Y_SIZE.
- --
- function Push(INDEX : INTEGER) return BOOLEAN is
-
- STACK_PTR : INTEGER;
- IRESULT : INT;
-
- begin
- if INSTANCE(INDEX).STACK_PTR < max_stack then
- STACK_PTR := INSTANCE(INDEX).STACK_PTR;
- INSTANCE(INDEX).STACK(STACK_PTR).X_OFFSET := INSTANCE(INDEX).X_OFFSET;
- INSTANCE(INDEX).STACK(STACK_PTR).Y_OFFSET := INSTANCE(INDEX).Y_OFFSET;
- INSTANCE(INDEX).STACK(STACK_PTR).X_SIZE := INSTANCE(INDEX).X_SIZE;
- INSTANCE(INDEX).STACK(STACK_PTR).Y_SIZE := INSTANCE(INDEX).Y_SIZE;
- INSTANCE(INDEX).STACK_PTR := INSTANCE(INDEX).STACK_PTR + 1;
- return TRUE;
- else
- IRESULT := Win32.WinUser.MessageBox(Win32.WinUser.GetFocus,
- CP(zoom_msg),
- CP(error_msg),
- Win32.WinUser.MB_ICONSTOP);
- return FALSE;
- end if;
- end Push;
-
- --
- -- Restores the previous state of X_OFFSET, Y_OFFSET, X_SIZE and Y_SIZE.
- --
- function Pop(INDEX : INTEGER) return BOOLEAN is
-
- STACK_PTR : INTEGER;
- IRESULT : INT;
-
- begin
- if INSTANCE(INDEX).STACK_PTR > 1 then
- INSTANCE(INDEX).STACK_PTR := INSTANCE(INDEX).STACK_PTR - 1;
- STACK_PTR := INSTANCE(INDEX).STACK_PTR;
- INSTANCE(INDEX).X_OFFSET := INSTANCE(INDEX).STACK(STACK_PTR).X_OFFSET;
- INSTANCE(INDEX).Y_OFFSET := INSTANCE(INDEX).STACK(STACK_PTR).Y_OFFSET;
- INSTANCE(INDEX).X_SIZE := INSTANCE(INDEX).STACK(STACK_PTR).X_SIZE;
- INSTANCE(INDEX).Y_SIZE := INSTANCE(INDEX).STACK(STACK_PTR).Y_SIZE;
- return TRUE;
- else
- IRESULT := Win32.WinUser.MessageBox(Win32.WinUser.GetFocus,
- CP(zoom_msg),
- CP(info_msg2),
- Win32.WinUser.MB_ICONINFORMATION);
- return FALSE;
- end if;
- end Pop;
-
- --
- -- For speed, this function mulitplies a ZOOM_TYPE in assembly.
- --
- function Scale(NUM : INT;
- FACTOR : ZOOM_TYPE) return INT;
- pragma Import(C, Scale, "scale");
-
-
-
- bit_7 : constant := 2**7;
- bit_6 : constant := 2**6;
- bit_5 : constant := 2**5;
- bit_4 : constant := 2**4;
- bit_3 : constant := 2**3;
- bit_2 : constant := 2**2;
- bit_1 : constant := 2**1;
- bit_0 : constant := 2**0;
-
- R : BOOL;
-
- procedure Display_Byte(HDC : HDC;
- INSTANCE_INDEX : INTEGER;
- BITS : BYTE;
- X,Y : INT) is
-
- use type Interfaces.C.UNSIGNED_CHAR;
-
- WX : INT;
- X_SCALE : ZOOM_TYPE;
-
- begin
- X_SCALE := INSTANCE(INSTANCE_INDEX).X_SCALE;
- if (BITS and bit_7) =0 then
- WX := Scale(X, X_SCALE);
- R := Win32.WinGdi.SetPixelV(HDC,WX ,Y,black);
- end if;
-
- if (BITS and bit_3) = 0 then
- WX := Scale(X+4, X_SCALE);
- R := Win32.WinGdi.SetPixelV(HDC,WX,Y,black);
- end if;
-
- if X_SCALE < 0.3 then return; end if;
-
- if (BITS and bit_6) =0 then
- WX := Scale(X+1, X_SCALE);
- R := Win32.WinGdi.SetPixelV(HDC,WX,Y,black);
- end if;
- if (BITS and bit_5) =0 then
- WX := Scale(X+2, X_SCALE);
- R := Win32.WinGdi.SetPixelV(HDC,WX,Y,black);
- end if;
- if (BITS and bit_4) =0 then
- WX := Scale(X+3, X_SCALE);
- R := Win32.WinGdi.SetPixelV(HDC,WX,Y,black);
- end if;
-
- if (BITS and bit_2) =0 then
- WX := Scale(X+5, X_SCALE);
- R := Win32.WinGdi.SetPixelV(HDC,WX,Y,black);
- end if;
- if (BITS and bit_1) =0 then
- WX := Scale(X+6, X_SCALE);
- R := Win32.WinGdi.SetPixelV(HDC,WX,Y,black);
- end if;
- if (BITS and bit_0) =0 then
- WX := Scale(X+7, X_SCALE);
- R := Win32.WinGdi.SetPixelV(HDC,WX,Y,black);
- end if;
- end Display_Byte;
- pragma Inline(Display_Byte);
-
- --
- -- This procedure displays the PCX file according to the current x and y
- -- offsets and scales.
- --
- procedure Display(HWND : HWND) is
-
- use type Interfaces.C.UNSIGNED_CHAR;
-
- DISPLAY_HDC : HDC;
- BRESULT : BOOL;
- IRESULT : INT;
- LRESULT : LONG;
- WY : INT;
- INDEX : INTEGER;
- X : INT;
- VALUE : BYTE;
- COUNT : BYTE;
- X_LIMIT : INT;
- Y_LIMIT : INT;
- INSTANCE_INDEX : INTEGER;
-
- begin
- null;
- --
- -- Find the occurence of this image.
- --
- INSTANCE_INDEX := Find_Instance(HWND);
- --
- -- Erase the previous image.
- --
- DISPLAY_HDC := Win32.WinUser.GetDC(HWND);
- LRESULT := Win32.WinUser.SendMessage(HWND,
- Win32.WinUser.WM_ERASEBKGND,
- Hdc_To_Wparam(DISPLAY_HDC),
- 0);
- --
- -- get dimensions of client window, and compute scale factors
- --
- BRESULT := Win32.WinUser.GetClientRect(HWND, CLIENT_RECT'access);
- INSTANCE(INSTANCE_INDEX).X_SCALE := ZOOM_TYPE(CLIENT_RECT.RIGHT) /
- ZOOM_TYPE(INSTANCE(INSTANCE_INDEX).X_SIZE);
- INSTANCE(INSTANCE_INDEX).Y_SCALE := ZOOM_TYPE(CLIENT_RECT.BOTTOM) /
- ZOOM_TYPE(INSTANCE(INSTANCE_INDEX).Y_SIZE);
- X_LIMIT := INSTANCE(INSTANCE_INDEX).X_OFFSET +
- INSTANCE(INSTANCE_INDEX).X_SIZE;
- Y_LIMIT := INSTANCE(INSTANCE_INDEX).Y_OFFSET +
- INSTANCE(INSTANCE_INDEX).Y_SIZE;
-
- INDEX := 0;
- for ROW in 0..Y_LIMIT loop
- WY := Scale(ROW-INSTANCE(INSTANCE_INDEX).Y_OFFSET,
- INSTANCE(INSTANCE_INDEX).Y_SCALE);
- X := 0;
- loop
- VALUE := INSTANCE(INSTANCE_INDEX).PCX_BYTES(INDEX);
- INDEX := INDEX + 1;
- if (VALUE and repeat_signature) = repeat_signature then
- COUNT := VALUE and repeat_count_mask;
- if ROW >= INSTANCE(INSTANCE_INDEX).Y_OFFSET then
- VALUE := INSTANCE(INSTANCE_INDEX).PCX_BYTES(INDEX);
- for I in 1..COUNT loop
- if X >= INSTANCE(INSTANCE_INDEX).X_OFFSET and
- X < X_LIMIT then
- Display_Byte(DISPLAY_HDC,
- INSTANCE_INDEX,
- VALUE,
- X-INSTANCE(INSTANCE_INDEX).X_OFFSET,
- WY);
- end if;
- X := X + 8;
- end loop;
- else -- not in the Y_OFFSET range yet
- X := X + 8 * INT(COUNT);
- end if;
- INDEX := INDEX + 1;
- else
- if ROW >= INSTANCE(INSTANCE_INDEX).Y_OFFSET and
- X >= INSTANCE(INSTANCE_INDEX).X_OFFSET and
- X < X_LIMIT then
- Display_Byte(DISPLAY_HDC,
- INSTANCE_INDEX,
- VALUE,
- X-INSTANCE(INSTANCE_INDEX).X_OFFSET,
- WY);
- end if;
- X := X + 8;
- end if;
- exit when X >= INSTANCE(INSTANCE_INDEX).BITS_PER_LINE;
- end loop;
- end loop;
-
- IRESULT := Win32.WinUser.ReleaseDC(HWND, DISPLAY_HDC);
- end Display;
-
- --
- -- Zoom to the new RECT provided. This RECT refers to the small rectangle used
- -- to select the image.
- --
- procedure Zoom_In(HWND : HWND;
- RECT : RECT) is
-
- PUSH_OK : BOOLEAN;
- INSTANCE_INDEX : INTEGER;
- IRESULT : INT;
-
- begin
- null;
- --
- -- Find the occurence of this image.
- --
- INSTANCE_INDEX := Find_Instance(HWND);
- PUSH_OK := Push(INSTANCE_INDEX);
- if PUSH_OK then
-
- if INSTANCE(INSTANCE_INDEX).X_SCALE < 0.01 or
- INSTANCE(INSTANCE_INDEX).Y_SCALE < 0.01
- then
- IRESULT := Win32.WinUser.MessageBox(Win32.WinUser.GetFocus,
- CP(zoom_err),
- CP(info_msg3),
- Win32.WinUser.MB_ICONINFORMATION);
- INSTANCE(INSTANCE_INDEX).X_SCALE := 1.0;
- INSTANCE(INSTANCE_INDEX).Y_SCALE := 1.0;
- end if;
-
- INSTANCE(INSTANCE_INDEX).X_OFFSET := INT(ZOOM_TYPE(RECT.LEFT) /
- INSTANCE(INSTANCE_INDEX).X_SCALE) + INSTANCE(INSTANCE_INDEX).X_OFFSET;
- INSTANCE(INSTANCE_INDEX).Y_OFFSET := INT(ZOOM_TYPE(RECT.TOP) /
- INSTANCE(INSTANCE_INDEX).Y_SCALE) + INSTANCE(INSTANCE_INDEX).Y_OFFSET;
-
- INSTANCE(INSTANCE_INDEX).X_SIZE := INT(ZOOM_TYPE(RECT.RIGHT - RECT.LEFT) /
- INSTANCE(INSTANCE_INDEX).X_SCALE);
- INSTANCE(INSTANCE_INDEX).X_SIZE :=
- (INSTANCE(INSTANCE_INDEX).X_SIZE / 8) * 8;
- INSTANCE(INSTANCE_INDEX).Y_SIZE := INT(ZOOM_TYPE(RECT.BOTTOM - RECT.TOP) /
- INSTANCE(INSTANCE_INDEX).Y_SCALE);
-
- Display(HWND);
- end if;
- end Zoom_In;
-
- --
- -- Zoom to the previous level.
- --
- procedure Zoom_Out(HWND : HWND) is
-
- POP_OK : BOOLEAN;
- INSTANCE_INDEX : INTEGER;
-
- begin
- null;
- --
- -- Find the occurence of this image.
- --
- INSTANCE_INDEX := Find_Instance(HWND);
- POP_OK := Pop(INSTANCE_INDEX);
- if POP_OK then
- Display(HWND);
- end if;
- end Zoom_Out;
-
-
- --
- -- This procedure displays the initial PCX image in a child window.
- --
- procedure Initial_Display(HINST : HINSTANCE;
- HWND : HWND;
- PCX_FILENAME : LPCSTR) is
-
- use type Interfaces.C.SIZE_T;
-
- LEN : Win32.Strings.SIZE_T;
- PCX_HANDLE : INT;
- BYTES_READ : INT;
- LOCATION : INT;
- FILE_SIZE : INT;
- BYTES_TO_READ : INT;
- BRESULT : BOOL;
- IRESULT : INT;
- CLIENT_RECT : aliased RECT;
- WINWIDTH_X : INT;
- WINWIDTH_Y : INT;
- ASPECT : FLOAT;
- SCREENMAX_X : INT;
- SCREENMAX_Y : INT;
- CHILDHWND : Win32.WinDef.HWND;
- INSTANCE_INDEX : INTEGER;
-
- begin
- --
- -- Open the file.
- --
- LEN := Win32.Strings.StrLen(PCX_FILENAME);
- if LEN /= 0 then
- PCX_HANDLE := Open(PCX_FILENAME, rd_only);
- MAX_WINDOWS := MAX_WINDOWS + 1;
- INSTANCE_INDEX := MAX_WINDOWS;
- INSTANCE(INSTANCE_INDEX).STACK_PTR := 1;
- --
- -- Read in the header and the bytes of the PCX file.
- --
- BYTES_READ := Read(PCX_HANDLE, INSTANCE(INSTANCE_INDEX).PCX_HEADER'address,
- INSTANCE(INSTANCE_INDEX).PCX_HEADER'size / 8);
- LOCATION := Lseek(PCX_HANDLE, 0, seek_cur);
- FILE_SIZE := Lseek(PCX_HANDLE, 0, seek_end);
- LOCATION := Lseek(PCX_HANDLE, LOCATION, seek_set);
- BYTES_TO_READ := FILE_SIZE - INSTANCE(INSTANCE_INDEX).PCX_HEADER'size / 8;
- if BYTES_TO_READ > max_pcx_file then
- IRESULT := Win32.WinUser.MessageBox(HWND,
- CP(error_msg2),
- CP(title_msg),
- Win32.WinUser.MB_OK);
- return;
- end if;
- BYTES_READ := Read(PCX_HANDLE,
- INSTANCE(INSTANCE_INDEX).PCX_BYTES'address,
- BYTES_TO_READ);
- IRESULT := Close(PCX_HANDLE);
- --
- -- Init the display parameters.
- --
- INSTANCE(INSTANCE_INDEX).X_OFFSET := 0;
- INSTANCE(INSTANCE_INDEX).Y_OFFSET := 0;
- INSTANCE(INSTANCE_INDEX).X_SIZE := (INT(
- INSTANCE(INSTANCE_INDEX).PCX_HEADER.XMAX) / 8) * 8;
- INSTANCE(INSTANCE_INDEX).Y_SIZE := INT(
- INSTANCE(INSTANCE_INDEX).PCX_HEADER.YMAX);
- INSTANCE(INSTANCE_INDEX).BITS_PER_LINE := INT(
- INSTANCE(INSTANCE_INDEX).PCX_HEADER.BYTES_PER_LINE) * 8;
-
- --
- -- Create a new window to display the PCX file.
- --
- WINWIDTH_X := INT(INSTANCE(INSTANCE_INDEX).PCX_HEADER.XMAX) / 3;
- WINWIDTH_Y := INT(INSTANCE(INSTANCE_INDEX).PCX_HEADER.YMAX) / 3;
- ASPECT := FLOAT(INSTANCE(INSTANCE_INDEX).PCX_HEADER.XMAX) /
- FLOAT(INSTANCE(INSTANCE_INDEX).PCX_HEADER.YMAX);
- SCREENMAX_X := Win32.WinUser.GetSystemMetrics(Win32.WinUser.SM_CXSCREEN);
- SCREENMAX_Y := Win32.WinUser.GetSystemMetrics(Win32.WinUser.SM_CYSCREEN);
- if WINWIDTH_Y > SCREENMAX_Y then
- WINWIDTH_Y := SCREENMAX_Y;
- WINWIDTH_X := INT(FLOAT(WINWIDTH_Y) * ASPECT);
- end if;
- if WINWIDTH_X > SCREENMAX_X then
- WINWIDTH_X := SCREENMAX_X;
- WINWIDTH_Y := INT(FLOAT(WINWIDTH_X) / ASPECT);
- end if;
- INSTANCE(INSTANCE_INDEX).X_SCALE := ZOOM_TYPE(WINWIDTH_X) /
- ZOOM_TYPE(INSTANCE(INSTANCE_INDEX).X_SIZE);
- INSTANCE(INSTANCE_INDEX).Y_SCALE := ZOOM_TYPE(WINWIDTH_Y) /
- ZOOM_TYPE(INSTANCE(INSTANCE_INDEX).Y_SIZE);
- INSTANCE(INSTANCE_INDEX).CHILDHWND := PcxChild.CreateWindow(HINST,
- HWND,
- WINWIDTH_X,
- WINWIDTH_Y,
- PCX_FILENAME);
- end if;
- end Initial_Display;
-
- -------------------------------------------------------------------------------
- --
- -- THIS FILE AND ANY ASSOCIATED DOCUMENTATION IS FURNISHED "AS IS" WITHOUT
- -- WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- -- TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- -- PURPOSE. The user assumes the entire risk as to the accuracy and the
- -- use of this file.
- --
- -- Copyright (c) Intermetrics, Inc. 1995
- -- Royalty-free, unlimited, worldwide, non-exclusive use, modification,
- -- reproduction and further distribution of this file is permitted.
- --
- -------------------------------------------------------------------------------
-
- end PcxOps;
-