
Unit grafiti0;

INTERFACE
USES  WINDOWS,types,common,fft;//crt,graph,

var
    flst : FillSettingsType;

TYPE irecmat = ARRAY[1..13,1..10] OF integer;

     grstype = RECORD
              cwin:                             integer;
              xpmin,xpmax,ypmin,ypmax:          integer;
              xwmin,xwmax,ywmin,ywmax:          real;
              winxmin,winxmax,winymin,winymax : integer;
              sfx,sfy:                          real;
              numticx, numticy:                 integer;
              winmap:                           irecmat;
              scrres:                           integer;
              grinit:                           integer;
            END;

VAR   grstat : grstype;
     grcolor : integer;
      grmode : boolean;

const    mga_setup: irecmat =                  {720x348 Hercules}

   ((100,580, 44,284,  0,719,  0,343,30,30),
    (100,700, 36,316,  0,719,  0,343,30,35),
    (100,580, 20,140,  0,719,  0,171,30,15),
    (100,580,196,316,  0,719,172,343,30,15),
    (100,340, 44,284,  0,359,  0,343,15,30),
    (460,700, 44,284,360,719,  0,343,15,30),
    (100,340, 20,140,  0,359,  0,171,15,15),
    (460,700, 20,140,360,719,  0,171,15,15),
    (100,340,196,316,  0,359,172,343,15,15),
    (460,700,196,316,360,719,172,343,15,15),
    ( 56,652, 42,347,  0,652,  0,347,25,20),
    ( 56,652,189,298,  0,582,155,347,25,15),
    (590,718, 42,347,582,718,  0,347, 6,10));

    cga_setup: irecmat =                       {640x200 CgaHi}

  ((100,500, 36,164,  0,639, 0,199,25,16),
   ( 88,568, 20,180,  0,639, 0,199,25,20),
   (100,500, 12, 76,  0,639, 0, 95,25, 8),
   (100,500,116,180,  0,639,96,199,25, 8),
   (100,300, 36,164,  0,319, 0,199,10,16),
   (414,614, 36,164,320,639, 0,199,10,16),
   (100,300, 12, 76,  0,319, 0, 95,10, 8),
   (414,614, 12, 76,320,639, 0, 95,10, 8),
   (100,300,116,180,  0,319,96,199,10, 8),
   (414,614,116,180,320,639,96,199,10, 8),
   ( 56,500, 42,199,  0,500, 0,199,25,20),
   ( 56,500, 87,150,  0,518,67,199,25, 8),
   (525,638, 42,199,518,638, 0,199, 6,10));

   IBM8514Hi_setup: irecmat=                          {1024x768}

 ((160, 800, 138, 626,   0, 1023,   0, 767, 40, 61),
  (141, 909,  77, 639,   0, 1023,   0, 767, 40, 77),
  (160, 800,  46, 286,   0, 1023,   0, 365, 40, 30),
  (160, 800, 446, 686,   0, 1023, 366, 767, 40, 30),
  (160, 480, 138, 626,   0,  611,   0, 767, 16, 61),
  (663, 983, 138, 626, 612, 1023,   0, 767, 16, 61),
  (160, 480,  46, 286,   0,  611,   0, 365, 16, 30),
  (663, 983,  46, 286, 612, 1023,   0, 365, 16, 30),
  (160, 480, 446, 686,   0,  611, 366, 767, 16, 30),
  (663, 983, 446, 686, 612, 1023, 366, 767, 16, 30),
  ( 56, 800,  42, 767,   0,  800,   0, 767, 25, 20),
  ( 56, 800, 445, 688,   0,  829, 368, 767, 25, 20),
  (840,1022,  42, 767, 829, 1022,   0, 767,  6, 10));


    VGAHi_setup: irecmat=                              {640x480}

 ((100, 500,  86, 390,   0, 639,   0, 478, 25, 38),    {segment, oscylogram}
  ( 88, 568,  48, 432,   0, 639,   0, 478, 25, 48),    {segment, spektrum}
  (100, 500,  29, 181,   0, 639,   0, 228, 25, 19),
  (100, 500, 278, 430,   0, 639, 230, 478, 25, 19),
  (100, 300,  86, 390,   0, 319,   0, 478, 10, 38),
  (414, 614,  86, 390, 320, 639,   0, 478, 10, 38),
  (100, 300,  29, 181,   0, 319,   0, 228, 10, 19),
  (414, 614,  29, 181, 320, 639,   0, 228, 10, 19),
  (100, 300, 278, 430,   0, 319, 230, 478, 10, 19),
  (414, 614, 278, 430, 320, 639, 230, 478, 10, 19),
  ( 56, 500,  42, 479,   0, 500,   0, 479, 25, 20),
  ( 56, 500, 278, 430,   0, 518, 230, 479, 25, 19),
  (525, 638,  42, 479, 518, 638,   0, 479,  6, 10));


    VGAmed_setup: irecmat=                              {640x350}

 ((100, 500,  63, 287,   0, 639,   0, 348, 25, 28),
  ( 88, 568,  35, 315,   0, 639,   0, 348, 25, 35),
  (100, 500,  21, 133,   0, 639,   0, 166, 25, 14),
  (100, 500, 203, 315,   0, 639, 168, 348, 25, 14),
  (100, 300,  63, 287,   0, 319,   0, 348, 10, 28),
  (414, 614,  63, 287, 320, 639,   0, 348, 10, 28),
  (100, 300,  21, 133,   0, 319,   0, 166, 10, 14),
  (414, 614,  21, 133, 320, 639,   0, 166, 10, 14),
  (100, 300, 203, 315,   0, 319, 168, 348, 10, 14),
  (414, 614, 203, 315, 320, 639, 168, 348, 10, 14),
  ( 56, 500,  42, 349,   0, 500,   0, 349, 25, 20),
  ( 56, 500, 190, 301,   0, 518, 156, 349, 25, 14),
  (525, 638,  42, 349, 518, 638,   0, 349,  6, 10));

VAR GraphDriver, GraphMode: integer;


//procedure initGraphicsDriver(s: string);
//procedure returnTextmode;
//procedure clr_box(x,y,w,h,c:integer);
procedure clear_text(s: string);
procedure clear_line;
procedure uniWriteString(s: string; n: integer);
procedure uniWriteInt(i: integer; n: integer);
procedure uniWriteReal(r: real; m,n: integer);
procedure uniGotoXY(x,y: integer);
function uniWhereX:integer;
function uniWhereY:integer;
//Procedure set_scr_res(resolution: integer);
PROCEDURE win_map_init;
FUNCTION num_exp(realnum: real):integer;
PROCEDURE win_init(win:    integer);
PROCEDURE f_min_max(VAR dataset:array of double;numdat:integer; VAR minval,maxval:realType);
PROCEDURE scale_win(x1, x2, y1, y2:  real);
PROCEDURE clr_win;
PROCEDURE clr_graph;
PROCEDURE dr_x_ax;
PROCEDURE dr_y_ax;
PROCEDURE convert_num(innum,sigdig:  real;VAR outstr:  string);
PROCEDURE lab_y_ax;
PROCEDURE lab_x_ax(time_interval:real);
PROCEDURE dr_grd;
PROCEDURE line_plot_data(VAR dataset: rAryType;numdat:  integer);
PROCEDURE rt_line_plot(dataval: real;var last_dataval: real;data_loc: integer);
PROCEDURE title_x_ax(xtitle: string);
PROCEDURE title_window(wintitle: string);
PROCEDURE title_y_ax(ytitle: string);
procedure build_bar_graph(bg_num:integer;lsv,hsv,llim,hlim,setpnt: real;
                          tag:string);
procedure update_bar_graph(bg_num:integer;lsv,hsv,llim,hlim,cv:real;var lv:real);

IMPLEMENTATION
uses visualization;
var grinitdone: boolean;
type
    loc4_type = array[0..1,0..3] of integer;
    loc_type = array[0..1] of integer;
    tag_type = string[6];

function crtmode:byte;
var   Crt_mode     :byte ;     //absolute $0040:$0049;
//      result: byte;
begin
   if crt_mode < 7 then result := crt_mode
   else
     if grmode then result := 8
     else
       result := 7;
   crtmode := result;
end;

    (*
procedure initGraphicsDriver(s: string);
var error:integer;
begin
   detectGraph(GraphDriver,GraphMode);
   case GraphDriver of
     ega : graphMode:=1;
   ega64 : graphMode:=1;
 egaMono : graphMode:=3;
     cga : graphMode:=4;
     vga : graphMode:=2;
 ibm8514 : graphMode:=1;
hercMono : graphMode:=0;
    else writeln('Dla tej karty nie opracowano grafiki');
   end;{case}
   initGraph(GraphDriver,GraphMode,s);
   error:=GraphResult; if error<>0 then writeln(graphErrorMsg(error));
   if error=0 then
    OutText('Wykryto karte '+GetDriverName);
   restoreCRTMode;
end;
    *)      (*
procedure returnTextMode;
begin
  grmode := FALSE;
  RestoreCRTMode;
END;    *)

{------------------------------------------------------------------}
{    Clear a Box                                                   }
{------------------------------------------------------------------}
(*procedure clr_box(x,y,w,h,c:integer);
begin
  GetFillSettings(flst);
  setfillstyle(1,c);
  bar(x,y,x+w,y-h);
  with flst do setFillStyle(pattern,color);
end;
       *)
procedure clear_text(s: string);
var l: integer;
begin
  l := length(s);
//  x := GetX; y := GetY;
//  Clr_Box(x,y+7,l*9,7,0);
//  MoveTo(x,y);
end;

procedure clear_line;

begin
//  col := wherex;
 // row := wherey;
  //gotoxy(1,row);
  case crtmode of
    0,1,2,3,7: ;//clreol;
    4,5,6,8: begin
           // x := GetX; y := GetY;
            //MoveTo(0,y);
//            Clr_Box(0,y+8,GetMaxX,8,0);
          END;
  end;
//  gotoxy(col,row);
end;


 procedure uniWriteString(s: string; n: integer);
 begin
   IF (CrtMode < 4) OR (CrtMode=7) THEN
 //    write(s:n)
   ELSE
     Begin
       Clear_Text(s);
//       OutText(s);
     end;
 end;

procedure uniWriteInt(i: integer; n: integer);
var s: string;
begin
  Str(i:n,s);
  uniwriteString(s,n);
end;

procedure uniWriteReal(r: real; m,n: integer);
var s: string;
begin
  Str(r:m:n,s);
  uniWriteString(s,n);
end;

procedure uniGotoXY(x,y: integer);
begin
  IF (crtmode< 4) OR (crtMode=7) THEN
//    Gotoxy(x,y)
  ELSE
  BEGIN
//    MoveTo((x-1)*8,(y-1)*8);
  END;
end;

function uniWhereX:integer;
//var result: integer;
begin
  IF (crtmode< 4) OR (crtMode=7) THEN
//    result := whereX
  ELSE
  BEGIN
//    result := ((GetX) div 8)+1;
  END;
  uniWhereX := result;
end;

function uniWhereY:integer;
//var result: integer;
begin
  IF (crtmode< 4) OR (crtMode=7) THEN
//    result := whereY
  ELSE
  BEGIN
//    result := ((GetY) div 8)+1;
  END;
  uniWhereY := result;
end;

            (*
Procedure set_scr_res(resolution: integer);
begin
  with grstat do
  begin
    scrres := resolution;
    if  GraphDriver = hercmono then GraphMode := 0
    else
     if resolution = 0 then GraphMode := 0
     else
    case GraphDriver of
                 vga : GraphMode:=resolution;
                 cga : GraphMode:=4;
         ega,Ibm8514 : graphMode:=1;
                else   GraphMode:=1;
    end;{case}
    SetGraphMode(GraphMode) ;
    grmode := TRUE;
  end;
end;

    *)
PROCEDURE win_map_init;

BEGIN
  WITH grstat DO
  BEGIN
//if graphDriver=HercMono then winmap:=mga_setup else winmap:=cga_setup;
//if (GraphDriver = ega) and (GraphMode =0) then winmap := cga_setup;
//if (GraphDriver = ega) and (GraphMode =1) then winmap := vgaMed_setup;
//if (GraphDriver = vga) and (GraphMode = vgaMed) then winmap := vgaMed_setup;
//if (GraphDriver = vga) and (GraphMode = vgaHi) then winmap := vgaHi_setup;
//if (GraphDriver = IBM8514) then  winmap := IBM8514Hi_setup;
//if (GraphDriver = IBM8514) and (GraphMode = IBM8514Lo) then
 winmap := vgaHi_setup;


    grinit := 999;
    cwin := 1;
    xpmin :=    winmap[cwin,1] ;     xpmax := winmap[cwin,2];
    ypmin :=    winmap[cwin,3];      ypmax := winmap[cwin,4];
    winxmin := winmap[cwin,5];    winxmax := winmap[cwin,6];
    winymin :=  winmap[cwin,7];    winymax := winmap[cwin,8];
    numticx :=  winmap[cwin,9];    numticy := winmap[cwin,10];
    sfx := (xpmax - xpmin)/(100);
    sfy := (ypmax - ypmin)/(100);
  END;
END;

FUNCTION num_exp(realnum: real):integer;

VAR numstr:        STRING[23];
    i,code,eloc:   integer;
    sign:          String[1];

BEGIN

  str(realnum,numstr);
  eloc := pos('E',numstr);
  sign := copy(numstr,eloc+1,1);
  if length(numstr) <= 18 then
    numstr := copy(numstr,eloc+2,2)
  else
    numstr := copy(numstr,eloc+2,3);
  val(numstr,i,code);
  IF sign = '-' THEN i:= (-i);
  num_exp := i;
END;


PROCEDURE win_init(win:    integer);

BEGIN
  WITH grstat DO
  BEGIN
    if grinit <> 999 then win_map_init;
    if (win < 1) or (win > 13) then win := 1;
    cwin := win;
    xpmin := winmap[win,1] ;     xpmax := winmap[win,2];
    ypmin := winmap[win,3];      ypmax := winmap[win,4];
    winxmin := winmap[win,5];    winxmax := winmap[win,6];
    winymin := winmap[win,7];    winymax := winmap[win,8];
    numticx := winmap[win,9];    numticy := winmap[win,10];
  END;
END;

PROCEDURE f_min_max(VAR dataset:array of double;numdat:integer;VAR minval,maxval:realType);

VAR   i: integer;

BEGIN
  minval := dataset[0];
  maxval := dataset[0];
  FOR i:= 1 TO numdat DO
  BEGIN
    IF dataset[i] < minval THEN minval := dataset[i];
    IF dataset[i] > maxval THEN maxval := dataset[i];

  END;
END;


PROCEDURE scale_win(x1, x2, y1, y2:  real);

BEGIN
  WITH grstat DO
  BEGIN
    if grinit <> 999 then win_map_init;
    xwmin := x1; xwmax := x2; ywmin := y1; ywmax := y2;
    if abs(xwmax-xwmin) > 1.0e-16 then
      sfx := (xpmax - xpmin)/(xwmax - xwmin)
    else
      uniwritestring('Error graphxx.mod - attempt to scale x-coord window to 0',0);
    if abs(ywmax-ywmin) > 1.0e-16 then
      sfy := (ypmax - ypmin)/(ywmax - ywmin)
    else
      uniwritestring('Error graphxx.mod - attempt to scale y-coord window to 0',0);

  END;
END;

PROCEDURE clr_win;
 var myRect:Trect;
BEGIN
  WITH grstat DO
  BEGIN
    if grinit <> 999 then win_map_init;
    myRect:=Rect(winxmin,winymin,winxmax,winymax);
    form2.Canvas.rectangle(myrect);
form2.canvas.fillRect(myRect)//    SetViewPort(winxmin,winymin,winxmax,winymax,TRUE);
//    ClearViewport;
//    SetViewPort(0,0,GetX,GetY,true);
  END;
END;

PROCEDURE clr_graph;

BEGIN
  WITH grstat DO
  BEGIN
    if grinit <> 999 then win_map_init;
//    SetViewport(xpmin+1,ypmin,xpmax,ypmax-1,TRUE);
//    ClearViewport;
//    SetViewPort(0,0,GetX,GetY,true);
  END;
END;

PROCEDURE dr_x_ax;

VAR  x1,x2,y1,y2 : integer;
        ticlen,i : integer;
              dX : real;

BEGIN
  WITH grstat DO
  BEGIN
     if grinit <> 999 then win_map_init;
     x1 := xpmin ;
     x2 := xpmax ;
     y2 := ypmax ;
//     SetColor(grcolor);
//     line(x1,y2,x2,y2);
     y1 := ypmax; dX:=(xpmax-xpmin)/numticX;
     FOR i:= 0 TO numticx DO
     BEGIN
       x1 := round(xpmin+i*dX);
       IF (i MOD 5) = 0 THEN ticlen := 3 ELSE ticlen := 1;
       y2 := y1 + ticlen;
//       line(x1,y1-ticlen,x1,y2);
     END;
  END;
END;

PROCEDURE dr_y_ax;
VAR   x1,x2,y1,y2 : integer;
         ticlen,i : integer;
               dY : real;
BEGIN
  WITH grstat DO
  BEGIN
     if grinit <> 999 then win_map_init;
     x1 := xpmin ;
     y1 := ypmin ;
     y2 := ypmax ;
//     SetColor(grColor);
//     line(x1,y1,x1,y2);
     dY:=(ypmax-ypmin)/numTicY;
     ticLen:=2;
     FOR i:= 0 TO numticy DO
     BEGIN
       y1 := round(ypmin+i*dy);
       x2 := x1 - ticlen;
       if i mod 2 =0 then ticLen:=5 else ticLen:=2;
//       line(x1,y1,x2,y1);
     END;
  END;
END;

PROCEDURE convert_num(innum,sigdig:real; VAR outstr:string);

VAR n,n1,n2:   integer;

BEGIN
  n1 := num_exp(innum);
  n2 := num_exp(sigdig);

CASE n1 OF
 -1,-2,-3,-4 : BEGIN
                IF n2<0 THEN n2:=-n2 ELSE n2:=0;
                n:=n2+1;
                str(innum:n:n2,outstr);
              END;

       0,1,2: BEGIN
                IF n2<0 THEN n2:=-n2 ELSE n2:=0;
                n:=n1+n2;
                str(innum:n:n2,outstr);
              END;

       3,4,5: BEGIN
                innum:=innum/1000.0;
                n1:=n1-3;
                n2:=n2-3;
                IF n2<0 THEN n2:=-n2 ELSE n2:=0;
                n:=n1+n2;
                str(innum:n:n2,outstr);
                outstr := outstr + 'k';
             END;

      6,7,8:  BEGIN
                innum:=innum/1000000.0;
                n1:=n1-6;
                n2:=n2-6;
                IF n2<0 THEN n2:=-n2 ELSE n2:=0;
                n:=n1+n2;
                str(innum:n:n2,outstr);
                outstr:=outstr+'m';
              END;
       ELSE   str(innum:8,outstr);
  END;
END;



PROCEDURE lab_y_ax;

VAR rowloc,colloc :  integer;
     i :  integer;
   labval,sigdig,dyp,dYw :     real;
               labvalstr :   string;

BEGIN
  WITH grstat DO
  BEGIN
    if grinit <> 999 then win_map_init;
    dYw:=(ywmax-ywmin)/numTicY;
    sigdig:=dYw/5;
    dYp:=(yPmax-yPmin)/numticY;
    FOR i:=0 TO numticy DO
    BEGIN
     if i mod 2 =0 then
      begin
       labval := ywmin+(i*dYw);
       convert_num(labval,sigdig,labvalstr);
       colloc := round((xpmin -4)/8 - length(labvalstr));
       unigotoxy(colloc,rowloc);
       uniwritestring(labvalstr,0);
      end;{if}
    END;
  END;
END;

PROCEDURE lab_x_ax(time_interval:real);

VAR rowloc,colloc:   integer;
    i :   integer;
labval,sigdig,dXp,dXw   :      real;
    labvalstr           :    string;

BEGIN
  WITH grstat DO
  BEGIN
    if grinit <> 999 then win_map_init;
    dXw:=(xwmax - xwmin)/(numticx);
    sigdig := time_interval*dXw;
    dXp:=(xPmax-xPmin)/numTicX;
    rowloc  := round((ypmax + 4)/8  + 1);
    FOR i:=0 TO numticx DO
    BEGIN
      IF (i MOD 5) = 0 THEN
      BEGIN
        labval := (xwmin + i*dXw) * time_interval;
        convert_num(labval,sigdig,labvalstr);
        colloc :=  round((xpmin + 4)/8 + (i*dXp+4)/8);
        colloc := colloc - round(length(labvalstr)/2);
        unigotoxy(colloc,rowloc);
        uniwritestring(labvalstr,0);
      END; {MOD condition}
    END;   { i DO loop}
  END;  {WITH grastat}
END;  {lab_x_ax}

PROCEDURE dr_grd;

VAR   x1,y1,i: integer;

BEGIN
  WITH grstat DO
  BEGIN
    if grinit <> 999 then win_map_init;
    FOR i:= 1 TO numticx DO
    BEGIN
      IF (i MOD 5) = 0 THEN
      BEGIN
        x1 := round(xpmin + (i/numticx)*(xpmax-xpmin));
        y1 := ypmin;
        WHILE y1 < ypmax DO
        BEGIN
          y1 := y1 + 2;
//          setcolor(grcolor);
//          line(x1,y1,x1,y1);
        END;
      END;
    END;
      FOR i:= 0 TO numticy-1 DO
      BEGIN
        IF (i MOD 2) = 0 THEN
        BEGIN
          y1 := round(ypmin + (i/numticy)*(ypmax-ypmin));
          x1 := xpmin;
          WHILE x1 < xpmax DO
          BEGIN
            x1 := x1 + 8 ;
//            setcolor(grcolor);
//            line(x1,y1,x1,y1);
          END;
        END;
      END;
   END;
END;



PROCEDURE line_plot_data(VAR dataset: rAryType;
                         numdat:  integer);

VAR i,x1,x2,y1,y2,ypsize :   integer;

BEGIN
  WITH grstat DO
  BEGIN
//    SetViewport(xpmin,ypmin,xpmax,ypmax, false);
    ypsize:=ypmax-ypmin;
    y1 := ypsize - round((dataset[0] - ywmin) * sfy);
    x1:=0;
//    SetColor(grcolor);
    FOR i := 1 TO numdat DO
    BEGIN
     x2 := round((i) * sfx);
     y2 := ypsize - round((dataset[i] - ywmin) * sfy);
//     line(x1,y1,x2,y2);
     x1:=x2;
     y1:=y2;
    END;
//    SetViewPort(0,0,GetX,GetY,true);
  END;
END;


PROCEDURE rt_line_plot(dataval: real;
                       var last_dataval: real;
                         data_loc:  integer);

VAR x1,x2,y1,y2,ypsize :   integer;

BEGIN
  WITH grstat DO
  BEGIN
//    SetViewport(xpmin,ypmin,xpmax,ypmax,True);
    ypsize := ypmax - ypmin;
    x1 := round((data_loc-1) * sfx);
    x2 := round((data_loc) * sfx);
    y1 := ypsize - round((last_dataval - ywmin) * sfy);
    y2 := ypsize - round((dataval - ywmin) * sfy);
//    SetColor(grcolor);
//    line(x1,y1,x2,y2);
//    SetViewPort(0,0,GetX,GetY,true);
  end;
  last_dataval := dataval;
END;


function row_coll_off(title:string):integer;
   var maxWidth, remain : integer;
 begin
  if grstat.grinit <> 999 then win_map_init;
  with grstat do maxwidth := round((xpmax - xpmin)/8);
  remain := 79 - maxwidth;
  delete(title,maxwidth,remain);
  row_coll_off := round(0.1+length(title)/2);
 end;{row_coll_off}

PROCEDURE title_x_ax(xtitle: string);

VAR rowloc,colloc:integer;
BEGIN
  WITH grstat DO
  BEGIN
   colloc := round(0.1 + (xpmin + (xpmax - xpmin)/2)/8) - row_coll_off(xtitle);
   rowloc := round(0.1 + (ypmax + 20)/8);
   unigotoxy(colloc,rowloc);
   uniwritestring(xtitle,0);
  END;
END;

PROCEDURE title_window(wintitle: string);

VAR rowloc,colloc:integer;
BEGIN
 WITH grstat DO
 BEGIN
  colloc := round(0.1 + (xpmin + (xpmax - xpmin)/2)/8)-row_coll_off(wintitle);
  rowloc := round(0.1 + (ypmin - 8)/8);
  unigotoxy(colloc,rowloc);
  uniwritestring(wintitle,0);
 END;
END;


PROCEDURE title_y_ax(ytitle: string);

VAR rowloc,colloc,i:integer;
          titlechar:String[1];
BEGIN
  WITH grstat DO
  BEGIN
    colloc := round(0.1 + (winxmin )/8)+2;
    rowloc := round(0.1 + (ypmin + (ypmax - ypmin)/2)/8)- row_coll_off(ytitle);
    FOR i:=1 TO length(ytitle) DO
    BEGIN
      titlechar := copy(ytitle,i,1);
      unigotoxy(colloc,rowloc+i);
      uniwritestring(titlechar,0);
    END;
  END;
END;


{------------------------------------------------------------------}
{    Fill a Box with a Solid Color                                 }
{------------------------------------------------------------------}
procedure fill_box(x,y,w,h,c: integer);
begin
//  GetFillSettings(flst);
//  setfillstyle(1,c);
//  bar(x,y,x+w,y-h);
//  with flst do setFillStyle(pattern,color);
end;


{------------------------------------------------------------------}
{    Update Bargraph                                               }
{------------------------------------------------------------------}
procedure update_bar_graph(bg_num:   integer;
                           lsv,hsv,llim,hlim,cv:  real;
                       var lv:                    real);

const
  mh: loc_type= (80,160);
  bar_width: loc_type=  (10,20);
  bar_loc_x:loc4_type = ((38,110,182,254),(55,215,375,535));
  bar_loc_y: loc_type = (124,228);
  bar_color: loc_type = (2,1);
  bar_val_col: loc4_type = ((4,13,22,31),(6,26,46,66));
  bar_val_row: loc_type = (17,31);
  cur_val_color: loc_type = (1,1);
  hi_alarm_color: loc_type = (2,1);
  lo_alarm_color: loc_type = (3,1);
  background_color: loc_type = (0,0);
  limit_stat_col: loc4_type = ((2,11,20,29),(6,26,46,66));
  limit_stat_row: loc_type = (19,33);

var  gb: integer;
     cur_pix : integer;
     last_pix: integer;
begin
  if crtmode = 8 then gb := 1 else gb := 0;
  if cv > hsv then cv := hsv;
  if cv < lsv then cv := lsv;
  if cv <> lv then
  begin
    cur_pix :=
         round(((cv-lsv)*mh[gb])/(hsv-lsv));
    last_pix :=
         round(((lv-lsv)*mh[gb])/(hsv-lsv));

    if cur_pix > last_pix then
      fill_box(bar_loc_x[gb,bg_num],bar_loc_y[gb] - last_pix,
               bar_width[gb],cur_pix - last_pix,bar_color[gb])
    else
      fill_box(bar_loc_x[gb,bg_num],bar_loc_y[gb] - cur_pix,
               bar_width[gb],last_pix - cur_pix,0);
//    textcolor(cur_val_color[gb]);
    unigotoxy(bar_val_col[gb,bg_num],bar_val_row[gb]);
    uniwritereal(cv,4,1);
  end;
  unigotoxy(limit_stat_col[gb,bg_num],limit_stat_row[gb]);
  if cv >= hlim then
  begin
//    textcolor(hi_alarm_color[gb]);
    uniwritestring(' HiAlarm ',9);
  end;
  if cv <= llim then
  begin
//    textcolor(lo_alarm_color[gb]);
    uniwritestring(' LoAlarm ',9);
  end;
  if (cv < hlim) and (cv > llim) then
  begin
//    textcolor(cur_val_color[gb]);
   uniwritestring(' OK   ',9);
  end;
  lv := cv;
end;

{----------------------------------------------------------------------------}
{   Draw Empty Box                                                           }
{----------------------------------------------------------------------------}
procedure draw_empty_box(x,y,w,h,c: integer);
begin
//  SetColor(c);
  //line(x,y,x+w,y);
//  line(x+w,y,x+w,y-h);
//  line(x+w,y-h,x,y-h);
  //line(x,y-h,x,y);
end;

{----------------------------------------------------------------------------}
{  Draw  Y-Axis for History Graph and Bar Graphs                             }
{----------------------------------------------------------------------------}
procedure draw_y_axis(axis_num,c: integer);
const  num_tic: loc_type =     (10,10);
       tic_len: loc_type =     (3,6);
       tic_space: loc_type =   (8,16);
       start_tic_x:loc4_type = ((36,108,180,252),(50,210,370,530));
       start_tic_y: loc_type = (124,228);
       ax_h: loc_type =        (80,160);
var gb,i,y: integer;


begin
  if crtmode = 8 then gb := 1 else gb := 0;
//  SetColor(c);
//  line(start_tic_x[gb,axis_num],start_tic_y[gb],
//       start_tic_x[gb,axis_num],start_tic_y[gb] - ax_h[gb]);
  y := start_tic_y[gb];
  for i:= 0 to num_tic[gb] do
  begin
//    setcolor(c);
  //  line(start_tic_x[gb,axis_num],y,
//         start_tic_x[gb,axis_num]-tic_len[gb], y);
    y := y - tic_space[gb];
  end;
end;

{----------------------------------------------------------------------------}
{    Label Y-Axis of History Graphs and Bar Graphs                           }
{----------------------------------------------------------------------------}
procedure label_y_axis(bg_num,c: integer; min_val,max_val: real);

const
  label_row: loc4_type = ((6,11,16,21),(9,19,29,39));
  label_col: loc4_type = ((2,11,20,29),(3,23,43,63));

var  gb,i,j:       integer;
     label_val: real;
begin
  if crtmode = 8 then gb := 1 else gb := 0;
//  textcolor(c);
  begin
    for i:= 0 to 2 do
    begin
      case i of
        0:label_val := max_val;
        1:label_val := min_val + (max_val - min_val)/2;
        2:label_val := min_val;
      end;
      unigotoxy(label_col[gb,bg_num],label_row[gb,i]);
      uniwritereal(label_val,3,0);
    end;

  end;
end;

{----------------------------------------------------------------------------}
{    Draw Limit and Setpoint Markers                                         }
{----------------------------------------------------------------------------}
procedure draw_limits(bg_num: integer; lsv,hsv,llim,hlim,setpnt: real);
const
  mh: loc_type = (80,160);
  lim_width: loc_type =  (4,8);
  lim_height: loc_type = (3,6);
  lim_loc_x:loc4_type = ((65,137,209,281),(85,245,405,565));
  lim_loc_y: loc_type = (124,228);
  llim_color: loc_type = (1,1);
  sp_color: loc_type = (3,1);

var  gb: integer;
     lim_pix : integer;


    {---------------------------------------------------------------------}
    {   Draw High Limit Setpoint Marker                                   }
    {---------------------------------------------------------------------}
procedure draw_hlim(x_coord, y_coord: integer);
const hlim_color: loc_type = (2,1);
var i, x1,x2,y1,y2: integer;
begin
  x1 := x_coord;
  x2 := x_coord + lim_width[gb];
  y1 := y_coord;
  for i := 0 to lim_height[gb] do
  begin
//    setcolor(hlim_color[gb]);
//    line(x1,y1,x2,y1);
    x1 := x1 + 1;
    y1 := y1 - 1;
  end;
end;


    {---------------------------------------------------------------------}
    {    Draw Low Limit Setpoint Marker                                   }
    {---------------------------------------------------------------------}
procedure draw_llim(x_coord, y_coord: integer);
const llim_color: loc_type = (3,1);
var i,x1,x2,y1,y2: integer;
begin
  x1 := x_coord;
  x2 := x_coord + lim_width[gb];
  y1 := y_coord;
  for i:= 0 to lim_height[gb] do
  begin
//    setcolor(llim_color[gb]);
//    line(x1,y1,x2,y1);
    x1 := x1 + 1;
    y1 := y1 + 1;
  end;
end;
    {---------------------------------------------------------------------}
    {    Draw Setpoint Marker                                             }
    {---------------------------------------------------------------------}
Procedure draw_setpoint(x_coord, y_coord: integer);
const setpoint_color: loc_type = (1,1);
var x1,x2,y1,y2,y3: integer;
begin
  x1 := x_coord;
  x2 := x_coord + lim_width[gb] + 1;
  y1 := y_coord;
  y2 := y_coord + lim_height[gb];
  y3 := y_coord - lim_height[gb];
//  setcolor(setpoint_color[gb]);
//  line(x1,y1,x2,y1);
//  line(x2,y2,x2,y3);
end;

begin
  if crtmode = 8 then gb := 1 else gb := 0;
  lim_pix := round(((hlim-lsv)*mh[gb])/(hsv-lsv));
  draw_hlim(lim_loc_x[gb,bg_num],lim_loc_y[gb] - lim_pix);

  lim_pix := round(((llim-lsv)*mh[gb])/(hsv-lsv));
  draw_llim(lim_loc_x[gb,bg_num],lim_loc_y[gb] - lim_pix);
  if setpnt <> lsv then
  begin
    lim_pix := round(((setpnt-lsv)*mh[gb])/(hsv-lsv));
    draw_setpoint(lim_loc_x[gb,bg_num],lim_loc_y[gb] - lim_pix);
  end;
end;

{-------------------------------------------------------------------------}
{   Build a Bar Graph                                                     }
{-------------------------------------------------------------------------}
procedure build_bar_graph(bg_num:                   integer;
                          lsv,hsv,llim,hlim,setpnt: real;
                          tag:                      string);

const
  bg_height: loc_type= (117,234);
  bg_width: loc_type=  (68,140);
  bg_loc_x:loc4_type = ((6,78,150,222),(5,165,325,485));
  bar_width: loc_type=  (10,20);
  bar_loc_x:loc4_type = ((38,110,182,254),(55,215,375,535));
  bar_loc_y: loc_type = (124,228);
  bar_color: loc_type = (2,1);
  bg_loc_y: loc_type = (137,266);
  line_color: loc_type = (3,1);
  tag_row: loc_type = (4,7);
  tag_col:loc4_type = ((3,12,21,30),(6,26,46,66));

var  gb: integer;
begin
  if crtmode = 8 then gb := 1 else gb := 0;

//  clr_box(bg_loc_x[gb,bg_num],bg_loc_y[gb],bg_width[gb]+2,bg_height[gb],0);
  draw_empty_box(bg_loc_x[gb,bg_num],bg_loc_y[gb],
                 bg_width[gb],bg_height[gb],
                 line_color[gb]);
  draw_y_axis( bg_num,line_color[gb]);
  draw_limits(bg_num,lsv,hsv,llim,hlim,setpnt);
  label_y_axis(bg_num,line_color[gb],lsv,hsv);
  fill_box(bar_loc_x[gb,bg_num],bar_loc_y[gb] + 1,
               bar_width[gb],1,bar_color[gb]);
  unigotoxy(tag_col[gb,bg_num],tag_row[gb]);
  uniwritestring(tag,6);
end;


INITIALIZATION
  grmode := FALSE;
END.
