[Back to WIN-OS2 SWAG index]  [Back to Main SWAG index]  [Original]


            (***************************************************)
            (*                 The Color Window                *)
            (*-------------------------------------------------*)
            (*  Copyright (c) 1995-`97 UNIVERSAL SOFTWARE Inc  *)
            (*               All Rights Reserved               *)
            (***************************************************)

{ example program at the end !! }

unit ColorWin;

{$S-}

INTERFACE

uses
 WinTypes,
 WinProcs,
 oWindows;

(************************************************************)
(****************** TpCrt types, consts, vars ***************)
(************************************************************)

type
 { the color window object }
 pColorWin=^tColorWin;
 tColorWin=object(tWindow)
  ScreenSize:tPoint;
  CharBuffer:pChar;
  AttrBuffer:pChar;
  TextAttr:byte;
  TextChar:char;
  CharSize:tPoint;
  CharAscent:integer;
  Range:tPoint;        { scrollbar ranges }
  Origin:tPoint;       { client area origin }
  ClientSize:tPoint;   { client area dimensions }
  { colorwin methods }
  procedure Byte2bkRgb(c:byte; var bkRGB:tColorRef);
  procedure Byte2fgRgb(c:byte; var fgRGB:tColorRef);
  procedure Byte2rgb(c:byte; var bkRGB:tColorRef; var fgRGB:tColorRef);
  constructor Init(AParent:pWindowsObject; aTitle:pChar);
  destructor Done; virtual;
  procedure SetupWindow; virtual;
  function GetClassName: pChar; virtual;
  procedure GetWindowClass(var aWndClass: tWndClass); virtual;
  procedure wmSize(var Msg:tMessage); virtual wm_First+wm_Size;
  {---}
  function GetNewPos(Action:word; Pos,Page,_Range, Thumb:integer):integer;
  procedure wmVScroll(var Msg:tMessage); virtual wm_First+wm_VScroll;
  procedure wmHScroll(var Msg:tMessage); virtual wm_First+wm_HScroll;
  {---}
  procedure SetScrollBars;
  function CharPtr(X,Y:integer):pChar;
  function AttrPtr(X,Y:integer):pChar;
  procedure Paint(PaintDC:hDC; var PS:tPaintStruct); virtual;
  procedure ClrScr;
  {\-clear current window}
  procedure ScrollTo(X,Y:integer);
  procedure FastWrite(St:string; Row,Col,_Attr:byte);
  {\-write St at Row,Col in Attr (video attribute)}
  procedure FastFill(Number:word; Ch:char; Row,Col,_Attr:byte);
  {\-fill Number chs at Row,Col in Attr (video attribute)}
  procedure FastCenter(St:string; Row,_Attr:byte);
  {\-write St centered on window Row in Attr (video attribute)}
 end;

IMPLEMENTATION

{ Double word record }
type
 LongRec=record
  Lo,Hi:integer;
 end;

const
 vgaColor:array[0..15] of tColorRef=(
  $00000000,   { Black }
  $00800000,   { Dark Cyan }
  $00008000,   { Dark Green}
  $00808000,   { Dark Blue }
  $00000080,   { Dark red }
  $00800080,   { Dark violet }
  $00008080,   { Brown }
  $00C0C0C0,   { light Gray }
  $00808080,   { Dark Gray }
  $00FF0000,   { light blue }
  $0000FF00,   { light green }
  $00FFFF00,   { Blue }
  $000000FF,   { light red }
  $00FF00FF,   { violet }
  $0000FFFF,   { yellow }
  $00FFFFFF    { White }
 );

type
 BufPtr=^BufferArray;
 BufferArray=array[0..MaxInt] of char;

function Min(X,Y:integer):integer;
{Return the smaller of two integer values}
begin
 if X <Y then Min:=X else Min:=Y;
end;

function Max(X,Y:integer):integer;
{Return the larger of two integer values}
begin
  if X >Y then Max:=X else Max:=Y;
end;

(*** colorwin ***)
constructor tColorWin.Init(aParent:pWindowsObject; aTitle:pChar);
begin
 inherited Init(aParent,aTitle);
 Attr.Style:=Attr.Style or ws_HScroll or ws_VScroll or cs_ByteAlignClient;
             {ws_Border or ws_Child or ws_Visible or
             ws_HScroll or ws_VScroll or
             cs_ByteAlignClient;}
 with ScreenSize do begin
  X:=80;  { screen width \ in chars }
  Y:=25;  { screen height/          }
  TextAttr:=$03;
  TextChar:='*';
  CharSize.X:=0;
  CharSize.Y:=0;
  CharAscent:=0;
  Origin.X:=0;
  Origin.Y:=0;
  Range.X:=0;
  Range.Y:=0;
  GetMem(CharBuffer,(ScreenSize.X*ScreenSize.Y)+1);
  GetMem(AttrBuffer,(ScreenSize.X*ScreenSize.Y)+1);
  FillChar(CharBuffer^,ScreenSize.X*ScreenSize.Y,TextChar);
  FillChar(AttrBuffer^,ScreenSize.X*ScreenSize.Y,char(TextAttr));
 end;
end;

destructor tColorWin.Done;
begin
 with ScreenSize do begin
  FreeMem(CharBuffer, X*Y);
  FreeMem(AttrBuffer, X*Y);
 end;
 inherited Done;
end;

procedure tColorWin.SetupWindow;
var
 DC:hDC;
 Metrics:tTextMetric;

begin
 inherited SetupWindow;
 DC:=GetDC(hWindow);
 SelectObject(DC,GetStockObject(System_Fixed_Font));
 GetTextMetrics(DC,Metrics);
 with Metrics, CharSize  do begin
  X:=tmMaxCharWidth;
  Y:=tmHeight+tmExternalLeading;
  CharAscent:=tmAscent;
 end;
 DeleteDC(DC);
 SetScrollRange(hWindow,sb_Horz,0,ScreenSize.X-1,false);
 SetScrollRange(hWindow,sb_Vert,0,ScreenSize.Y-1,false);
end;

function tColorWin.GetClassName:pChar;
begin
 GetClassName:='ColorWin';
end;

procedure tColorWin.GetWindowClass(var aWndClass:tWndClass);
begin
 inherited GetWindowClass(aWndClass);
 aWndClass.hIcon:=LoadIcon(0,idi_Application);
end;

procedure tColorWin.wmSize(var Msg:tMessage);
var
 x,y:integer;

begin
 with Msg do begin
  x:=LoWord(Msg.lParam);
  y:=HiWord(Msg.lParam);
 end;
 ClientSize.X:=X div CharSize.X;
 ClientSize.Y:=Y div CharSize.Y;
 Range.X:=Max(0,ScreenSize.X-ClientSize.X);
 Range.Y:=Max(0,ScreenSize.Y-ClientSize.Y);
 Origin.X:=Min(Origin.X, Range.X);
 Origin.Y:=Min(Origin.Y, Range.Y);
 SetScrollBars;
end;

function tColorWin.CharPtr(X,Y:integer):pChar;
{Return pointer to the Char at (X,Y) in the screen buffer}
begin
 CharPtr:=@CharBuffer[Y*ScreenSize.X+X];
end;

function tColorWin.AttrPtr(X,Y:integer):pChar;
{Return pointer to the Attr at (X,Y) in the screen buffer}
begin
 AttrPtr:=@AttrBuffer[Y*ScreenSize.X+X];
end;

procedure tColorWin.SetScrollBars;
{Update scroll bars}
begin
 SetScrollRange(hWindow, sb_Horz, 0, Max(0,Range.X), false);
 SetScrollPos(hWindow, sb_Horz, Origin.X, true);
 SetScrollRange(hWindow, sb_Vert, 0, Max(0,Range.Y), false);
 SetScrollPos(hWindow, sb_Vert, Origin.Y, true);
end;

procedure tColorWin.ScrollTo(X,Y:integer);
{Scroll window to given origin}
begin
 X:=Max(0,Min(X,Range.X));
 Y:=Max(0,Min(Y,Range.Y));
 if (X <>Origin.X) or (Y <>Origin.Y) then begin
  if X <>Origin.X then SetScrollPos(hWindow,sb_Horz,X,true);
  if Y <>Origin.Y then SetScrollPos(hWindow,sb_Vert,Y,true);
  ScrollWindow(hWindow,(Origin.X-X)*CharSize.X,(Origin.Y-Y)*CharSize.Y, nil,nil);
  Origin.X:=X;
  Origin.Y:=Y;
  UpdateWindow(hWindow);
 end;
end;

procedure tColorWin.Byte2bkRgb(c:byte; var bkRGB:tColorRef);
begin
 bkRGB:=vgaColor[c shr 4];
end;

procedure tColorWin.Byte2fgRgb(c:byte; var fgRGB:tColorRef);
begin
 fgRGB:=vgaColor[c and $F];
end;

procedure tColorWin.Byte2rgb(c:byte; var bkRGB:tColorRef; var fgRGB:tColorRef);
begin
 bkRGB:=vgaColor[c shr 4];
 fgRGB:=vgaColor[c and $F];
end;

procedure tColorWin.ClrScr;
{Clear the screen}
var
 _y:integer;

begin
 FillChar(CharBuffer^,ScreenSize.X*ScreenSize.Y,TextChar);
 FillChar(AttrBuffer^,ScreenSize.X*ScreenSize.Y,char(TextAttr));
 Longint(Origin):=0;
 SetScrollBars;
 InvalidateRect(hWindow,nil,false {true});
 UpdateWindow(hWindow);
end;

procedure tColorWin.Paint(PaintDC:hDC; var PS:tPaintStruct);
{wm_Paint message handler}
var
 X1,X2,Y1,Y2:integer;
 bkRGB,fgRGB:tColorRef;
 i:integer;

begin
 SelectObject(PaintDC, GetStockObject(System_Fixed_Font));
 {---}
 MoveTo(PaintDC, ScreenSize.X*CharSize.X,0);
 LineTo(PaintDC, ScreenSize.X*CharSize.X,ScreenSize.Y*CharSize.Y);
 LineTo(PaintDC, 0,ScreenSize.Y*CharSize.Y);
 X1:=Max(0, PS.rcPaint.left div CharSize.X+Origin.X);
 X2:=Min((PS.rcPaint.right+CharSize.X-1) div CharSize.X+Origin.X,ScreenSize.X);
 Y1:=Max(0, PS.rcPaint.top div CharSize.Y+Origin.Y-1);
 Y2:=Min((PS.rcPaint.bottom+CharSize.Y-1) div CharSize.Y+Origin.Y,ScreenSize.Y);
 while Y1 <Y2 do begin
  for i:=X1 to X2 do begin
   Byte2rgb(byte(AttrPtr(i,Y1)^),bkRGB,fgRGB);
   SetTextColor(PaintDC,fgRGB);
   SetBkColor(PaintDC,bkRGB);
   if i <ScreenSize.X then
    TextOut(PaintDC,(i-Origin.X)*CharSize.X,(Y1-Origin.Y)*CharSize.Y,CharPtr(i,Y1), 1);
  end;
  Inc(Y1);
 end;
end;

procedure tColorWin.FastWrite(St:string; Row,Col,_Attr:byte);
begin
 Move(St[1],CharPtr(pred(Col),pred(Row))^,Length(St));
 FillChar(AttrPtr(pred(Col),pred(Row))^,Length(St),char(_Attr));
end;

procedure tColorWin.FastFill(Number:word; Ch:char; Row,Col,_Attr:byte);
begin
 if Number >(ScreenSize.X*ScreenSize.Y-(Row*ScreenSize.X+Col)) then
  Number:=ScreenSize.X*ScreenSize.Y-(Row*ScreenSize.X+Col);
 FillChar(CharPtr(pred(Col),pred(Row))^,Number,Ch);
 FillChar(AttrPtr(pred(Col),pred(Row))^,Number,_Attr);
end;

procedure tColorWin.FastCenter(St:string; Row,_Attr:byte);
var
 sL:byte absolute St;

begin
 if sL >succ(ScreenSize.X-ScreenSize.X) then
  sL:=succ(ScreenSize.X-ScreenSize.X);
 FastWrite(St,ScreenSize.Y+Row,ScreenSize.X+
  succ((succ(ScreenSize.X-ScreenSize.X)-sL) shr 1),_Attr);
end;

function tColorWin.GetNewPos(Action:word; Pos,Page,_Range, Thumb:integer):integer;
begin
 case Action of
  sb_LineUp: GetNewPos:=Pos-1;
  sb_LineDown: GetNewPos:=Pos+1;
  sb_PageUp: GetNewPos:=Pos-Page;
  sb_PageDown: GetNewPos:=Pos+Page;
  sb_Top: GetNewPos:=0;
  sb_Bottom: GetNewPos:=_Range;
  sb_ThumbPosition: GetNewPos:=Thumb;
 else
  GetNewPos:=Pos;
 end;
end;

procedure tColorWin.wmHScroll(var Msg:tMessage);
{wm_HScroll handler}
var
 X:integer;

begin
 X:=Origin.X;
 X:=GetNewPos(Msg.wParam, X, ClientSize.X div 2, Range.X, Msg.lParamLo);
 ScrollTo(X, Origin.Y);
end;

procedure tColorWin.wmVScroll(var Msg:tMessage);
{wm_VScroll handler}
var
 Y:integer;

begin
 Y:=Origin.Y;
 Y:=GetNewPos(Msg.wParam, Y, ClientSize.Y, Range.Y, Msg.lParamLo);
 ScrollTo(Origin.X, Y);
end;

end.

{ ----------------------   CUT  ----------------------- }

              (************************************************)
              (* The Demostration Module for tColorWin object *)
              (************************************************)

uses
 WinTypes,
 WinProcs,
 oWindows,
 ColorWin;     {-tColorWin object}

const
 AppName:pChar='tColorWin demo';
 CaptionText:pChar='Color Window test..';

 {===[ This application does nothing but shows you ]===}
 {===[ how to use tColorWin object                 ]===}

type
 tMyApp=object(tApplication)
  procedure InitMainWindow; virtual;
 end;

 pMyWin=^tMyWin;
 tMyWin=object(tColorWin)
  procedure SetupWindow; virtual;
 end;

procedure tMyWin.SetupWindow;
var
 i:byte;

begin
 inherited SetupWindow;
 for i:=1 to 15 do
  FastWrite('Test string for check ColorWin. Don`t panic! ;-)',i,2,i);
end;

procedure tMyApp.InitMainWindow;
begin
 MainWindow:=New(pMyWin,Init(nil,CaptionText));
end;

var
 MyApp:tMyApp;

begin
 MyApp.Init(AppName);
 MyApp.Run;
 MyApp.Done;
end.

[Back to WIN-OS2 SWAG index]  [Back to Main SWAG index]  [Original]