Index: cprs/trunk/CPRS-Chart/Templates/uTemplateFields.pas
===================================================================
--- cprs/trunk/CPRS-Chart/Templates/uTemplateFields.pas	(revision 456)
+++ cprs/trunk/CPRS-Chart/Templates/uTemplateFields.pas	(revision 829)
@@ -5,9 +5,11 @@
 uses
   Forms, SysUtils, Classes, Dialogs, StdCtrls, ExtCtrls, Controls, Contnrs,
-  Graphics, ORClasses, ComCtrls, ORDtTm;
+  Graphics, ORClasses, ComCtrls, ORDtTm, uDlgComponents, TypInfo, ORFn, StrUtils;
 
 type
   TTemplateFieldType = (dftUnknown, dftEditBox, dftComboBox, dftButton, dftCheckBoxes,
-                        dftRadioButtons, dftDate, dftNumber, dftHyperlink, dftWP, dftText);
+    dftRadioButtons, dftDate, dftNumber, dftHyperlink, dftWP, dftText,
+// keep dftScreenReader as last entry - users can not create this type of field
+    dftScreenReader);
 
   TTmplFldDateType = (dtUnknown, dtDate, dtDateTime, dtDateReqTime,
@@ -30,5 +32,5 @@
     FID: string;
     FFont: TFont;
-    FPanel: TPanel;
+    FPanel: TDlgFieldPanel;
     FControls: TStringList;
     FIndents: TStringList;
@@ -47,4 +49,5 @@
     procedure SetFieldValues(const Value: string);
     procedure SetAutoDestroyOnPanelFree(const Value: boolean);
+    function StripCode(var txt: string; code: char): boolean;
   protected
     procedure UpDownChange(Sender: TObject);
@@ -57,5 +60,6 @@
     constructor Create(AParent: TWinControl; AID, Text: string);
     destructor Destroy; override;
-    function GetPanel(MaxLen: integer; AParent: TWinControl): TPanel;
+    function GetPanel(MaxLen: integer; AParent: TWinControl;
+                      OwningCheckBox: TCPRSDialogParentCheckBox): TDlgFieldPanel;
     function GetText: string;
     property Text: string read FText write FText;
@@ -174,9 +178,38 @@
 procedure ConvertCodes2Text(sl: TStrings; Short: boolean);
 function StripEmbedded(iItems: string): string;
+procedure StripScreenReaderCodes(var Text: string); overload;
+procedure StripScreenReaderCodes(SL: TStrings); overload;
+function HasScreenReaderBreakCodes(SL: TStrings): boolean;
 
 const
-  TemplateFieldBeginSignature = '{FLD:';
+  TemplateFieldSignature = '{FLD';
+  TemplateFieldBeginSignature = TemplateFieldSignature + ':';
   TemplateFieldEndSignature = '}';
+  ScreenReaderCodeSignature = '{SR-';
+  ScreenReaderCodeType = '  Screen Reader Code';
+  ScreenReaderCodeCount = 2;
+  ScreenReaderShownCount = 1;
+  ScreenReaderStopCode = ScreenReaderCodeSignature + 'STOP' + TemplateFieldEndSignature;
+  ScreenReaderStopCodeLen = Length(ScreenReaderStopCode);
+  ScreenReaderStopCodeID = '-43';
+  ScreenReaderStopName = 'SCREEN READER STOP CODE **';
+  ScreenReaderStopCodeLine = ScreenReaderStopCodeID + U + ScreenReaderStopName + U + ScreenReaderCodeType;
+  ScreenReaderContinueCode = ScreenReaderCodeSignature + 'CONT' + TemplateFieldEndSignature;
+  ScreenReaderContinueCodeLen = Length(ScreenReaderContinueCode);
+  ScreenReaderContinueCodeOld = ScreenReaderCodeSignature + 'CONTINUE' + TemplateFieldEndSignature;
+  ScreenReaderContinueCodeOldLen = Length(ScreenReaderContinueCodeOld);
+  ScreenReaderContinueCodeID = '-44';
+  ScreenReaderContinueCodeName = 'SCREEN READER CONTINUE CODE ***';
+  ScreenReaderContinueCodeLine = ScreenReaderContinueCodeID + U + ScreenReaderContinueCodeName + U + ScreenReaderCodeType;
   MissingFieldsTxt = 'One or more required fields must still be entered.';
+
+  ScreenReaderCodes:     array[0..ScreenReaderCodeCount] of string  =
+      (ScreenReaderStopCode, ScreenReaderContinueCode, ScreenReaderContinueCodeOld);
+  ScreenReaderCodeLens:  array[0..ScreenReaderCodeCount] of integer =
+      (ScreenReaderStopCodeLen, ScreenReaderContinueCodeLen, ScreenReaderContinueCodeOldLen);
+  ScreenReaderCodeIDs:   array[0..ScreenReaderShownCount] of string  =
+      (ScreenReaderStopCodeID, ScreenReaderContinueCodeID);
+  ScreenReaderCodeLines: array[0..ScreenReaderShownCount] of string  =
+      (ScreenReaderStopCodeLine, ScreenReaderContinueCodeLine); 
 
   TemplateFieldTypeCodes: array[TTemplateFieldType] of string[1] =
@@ -191,18 +224,20 @@
                          {  dftHyperlink    }  'H',
                          {  dftWP           }  'W',
-                         {  dftText         }  'T');
+                         {  dftText         }  'T',
+                         {  dftScreenReader }  'S');
 
   TemplateFieldTypeDesc: array[TTemplateFieldType, boolean] of string =
                          {  dftUnknown      } (('',''),
-                         {  dftEditBox      }  ('Edit Box',       'Edit'),
-                         {  dftComboBox     }  ('Combo Box',      'Combo'),
-                         {  dftButton       }  ('Button',         'Button'),
-                         {  dftCheckBoxes   }  ('Check Boxes',    'Check'),
-                         {  dftRadioButtons }  ('Radio Buttons',  'Radio'),
-                         {  dftDate         }  ('Date',           'Date'),
-                         {  dftNumber       }  ('Number',         'Num'),
-                         {  dftHyperlink    }  ('Hyperlink',      'Link'),
-                         {  dftWP           }  ('Word Processing','WP'),
-                         {  dftWP           }  ('Display Text',   'Text'));
+                         {  dftEditBox      }  ('Edit Box',           'Edit'),
+                         {  dftComboBox     }  ('Combo Box',          'Combo'),
+                         {  dftButton       }  ('Button',             'Button'),
+                         {  dftCheckBoxes   }  ('Check Boxes',        'Check'),
+                         {  dftRadioButtons }  ('Radio Buttons',      'Radio'),
+                         {  dftDate         }  ('Date',               'Date'),
+                         {  dftNumber       }  ('Number',             'Num'),
+                         {  dftHyperlink    }  ('Hyperlink',          'Link'),
+                         {  dftWP           }  ('Word Processing',    'WP'),
+                         {  dftText         }  ('Display Text',       'Text'),
+                         {  dftScreenReader }  ('Screen Reader Stop', 'SRStop'));
 
   TemplateDateTypeDesc: array[TTmplFldDateType, boolean] of string =
@@ -226,5 +261,6 @@
                    { dftHyperlink    }  'LINK',
                    { dftWP           }  'WRDP',
-                   { dftTExt         }  'TEXT');
+                   { dftTExt         }  'TEXT',
+                   { dftScreenReader }  'SRST');
 
   TemplateFieldDateCodes: array[TTmplFldDateType] of string[1] =
@@ -239,25 +275,10 @@
   MaxTFWPLines = 20;
   MaxTFEdtLen = 70;
-
-type
-  TFieldPanel = class(TPanel)  {This is the panel associated with the child}
-  private                      {dialog checkboxes in reminders dialogs}
-    FOnDestroy: TNotifyEvent;
-    FCanvas: TControlCanvas;    {used to draw focus rect}
-    function GetFocus: boolean;
-    procedure SetTheFocus(const Value: boolean);
-  protected                     {used to draw focus rect}
-    procedure Paint; override;  {used to draw focus rect}
-  public
-    destructor Destroy; override;
-    property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy;
-    property Focus:  boolean read GetFocus write SetTheFocus; {to draw focus rect}
-    property OnKeyPress;        {to click the checkbox when spacebar is pressed}
-  end;
-
+  
 implementation
 
 uses
-  ORFn, rTemplates, ORCtrls, mTemplateFieldButton, dShared, uConst, uCore, rCore, Windows;
+  rTemplates, ORCtrls, mTemplateFieldButton, dShared, uConst, uCore, rCore, Windows,
+  VAUtils, VA508AccessibilityManager, VA508AccessibilityRouter;
 
 const
@@ -279,20 +300,4 @@
   FieldIDLen = 6;
   NewLine = 'NL';
-
-type
-  TFieldLabel = class(TLabel)
-  private
-    FExclude: boolean;
-  public
-    property Exclude: boolean read FExclude;
-  end;
-  
-  TWebLabel = class(TFieldLabel)
-  private
-    FAddr: string;
-    procedure Clicked(Sender: TObject);
-  public
-    procedure Init(Addr: string);
-  end;
 
 function GetNewFieldID: string;
@@ -694,5 +699,5 @@
   Result := (msg <> '');
   if(Result) then
-    ShowMessage(msg);
+    ShowMsg(msg);
 end;
 
@@ -861,5 +866,5 @@
           AList.Add('');
         AList.Add('The following inactive template fields were found:');
-        AList.AddStrings(InactiveList);
+        FastAddStrings(InactiveList, AList);
       end;
       if(AList.Count > 0) then
@@ -1079,8 +1084,7 @@
   dbox: TORDateBox;
   dcbo: TORDateCombo;
-  lbl: TFieldLabel;
+  lbl: TCPRSTemplateFieldLabel;
   re: TRichEdit;
-  pnl: TPanel;
-  ud: TUpDown;
+  pnl: TCPRSDialogNumber;
   DefDate: TFMDateTime;
   ctrl: TControl;
@@ -1123,5 +1127,6 @@
       dftEditBox:
         begin
-          edt := TEdit.Create(nil);
+          edt := TCPRSDialogFieldEdit.Create(nil);
+          (edt as ICPRSDialogComponent).RequiredField := Required;
           edt.Parent := Entry.FPanel;
           edt.BorderStyle := bsNone;
@@ -1135,4 +1140,5 @@
           edt.Tag := CtrlID;
           edt.OnChange := Entry.DoChange;
+          UpdateColorsFor508Compliance(edt, TRUE);
           ctrl := edt;
         end;
@@ -1140,5 +1146,6 @@
       dftComboBox:
         begin
-          cbo := TORComboBox.Create(nil);
+          cbo := TCPRSDialogComboBox.Create(nil);
+          (cbo as ICPRSDialogComponent).RequiredField := Required;
           cbo.Parent := Entry.FPanel;
           cbo.TemplateField := TRUE;
@@ -1165,4 +1172,5 @@
             cbo.DropDownCount := cbo.Items.Count;
           end;
+          UpdateColorsFor508Compliance(cbo, TRUE);
           ctrl := cbo;
         end;
@@ -1171,4 +1179,5 @@
         begin
           btn := TfraTemplateFieldButton.Create(nil);
+          (btn as ICPRSDialogComponent).RequiredField := Required;
           btn.Parent := Entry.FPanel;
           {Clear out embedded fields}
@@ -1179,4 +1188,5 @@
           btn.Tag := CtrlID;
           btn.OnChange := Entry.DoChange;
+          UpdateColorsFor508Compliance(btn);
           ctrl := btn;
         end;
@@ -1192,5 +1202,7 @@
             for i := 0 to TmpSL.Count-1 do
             begin
-              cb := TORCheckBox.Create(nil);
+              cb := TCPRSDialogCheckBox.Create(nil);
+              if i = 0 then
+                (cb as ICPRSDialogComponent).RequiredField := Required;
               cb.Parent := Entry.FPanel;
               cb.Caption := TmpSL[i];
@@ -1210,4 +1222,5 @@
                 cb.StringData := NewLine;
               cb.OnClick := Entry.DoChange;
+              UpdateColorsFor508Compliance(cb);
               inc(Index);
               Entry.FControls.InsertObject(Index, '', cb);
@@ -1228,5 +1241,6 @@
           if FDateType in DateComboTypes then
           begin
-            dcbo := TORDateCombo.Create(nil);
+            dcbo := TCPRSDialogDateCombo.Create(nil);
+            (dcbo as ICPRSDialogComponent).RequiredField := Required;
             dcbo.Parent := Entry.FPanel;
             dcbo.Tag := CtrlID;
@@ -1237,9 +1251,11 @@
             dcbo.TemplateField := TRUE;
             dcbo.OnChange := Entry.DoChange;
+            UpdateColorsFor508Compliance(dcbo, TRUE);
             ctrl := dcbo;
           end
           else
           begin
-            dbox := TORDateBox.Create(nil);
+            dbox := TCPRSDialogDateBox.Create(nil);
+            (dbox as ICPRSDialogComponent).RequiredField := Required;
             dbox.Parent := Entry.FPanel;
             dbox.Tag := CtrlID;
@@ -1254,4 +1270,5 @@
             dbox.Width := (wdth * tmp) + 18;
             dbox.OnChange := Entry.DoChange;
+            UpdateColorsFor508Compliance(dbox, TRUE);
             ctrl := dbox;
           end;
@@ -1260,31 +1277,22 @@
       dftNumber:
         begin
-          pnl := TPanel.Create(nil);
+          pnl := TCPRSDialogNumber.CreatePanel(nil);
+          (pnl as ICPRSDialogComponent).RequiredField := Required;
           pnl.Parent := Entry.FPanel;
           pnl.BevelOuter := bvNone;
           pnl.Tag := CtrlID;
-          edt := TEdit.Create(pnl);
-          edt.Parent := pnl;
-          edt.BorderStyle := bsNone;
-          edt.Height := ht;
-          edt.Width := (wdth * 5 + 4);
-          edt.Top := 0;
-          edt.Left := 0;
-          edt.AutoSelect := True; 
-          ud := TUpDown.Create(pnl);
-          ud.Parent := pnl;
-          ud.Associate := edt;
-          ud.Min := MinVal;
-          ud.Max := MaxVal;
-          ud.Min := MinVal; // Both ud.Min settings are needeed!
+          pnl.Edit.Height := ht;
+          pnl.Edit.Width := (wdth * 5 + 4);
+          pnl.UpDown.Min := MinVal;
+          pnl.UpDown.Max := MaxVal;
+          pnl.UpDown.Min := MinVal; // Both ud.Min settings are needeed!
           i := Increment;
           if i < 1 then i := 1;
-          ud.Increment := i;
-          ud.Thousands := FALSE;
-          ud.Position := StrToIntDef(EditDefault, 0);
-          edt.Tag := Integer(ud);
-          edt.OnChange := Entry.UpDownChange;
-          pnl.Height := edt.Height;
-          pnl.Width := edt.Width + ud.Width;
+          pnl.UpDown.Increment := i;
+          pnl.UpDown.Position := StrToIntDef(EditDefault, 0);
+          pnl.Edit.OnChange := Entry.UpDownChange;
+          pnl.Height := pnl.Edit.Height;
+          pnl.Width := pnl.Edit.Width + pnl.UpDown.Width;
+          UpdateColorsFor508Compliance(pnl, TRUE);
           ctrl := pnl;
         end;
@@ -1293,10 +1301,10 @@
         begin
           if (FFldType = dftHyperlink) and User.WebAccess then
-            lbl := TWebLabel.Create(nil)
+            lbl := TCPRSDialogHyperlinkLabel.Create(nil)
           else
-            lbl := TFieldLabel.Create(nil);
+            lbl := TCPRSTemplateFieldLabel.Create(nil);
           lbl.Parent := Entry.FPanel;
           lbl.ShowAccelChar := FALSE;
-          lbl.FExclude := FSepLines;
+          lbl.Exclude := FSepLines;
           if (FFldType = dftHyperlink) then
           begin
@@ -1313,7 +1321,8 @@
             lbl.Caption := STmp;
           end;
-          if lbl is TWebLabel then
-            TWebLabel(lbl).Init(FURL);
+          if lbl is TCPRSDialogHyperlinkLabel then
+            TCPRSDialogHyperlinkLabel(lbl).Init(FURL);
           lbl.Tag := CtrlID;
+          UpdateColorsFor508Compliance(lbl);
           ctrl := lbl;
         end;
@@ -1321,5 +1330,6 @@
       dftWP:
         begin
-          re := TRichEdit.Create(nil);
+          re := TCPRSDialogRichEdit.Create(nil);
+          (re as ICPRSDialogComponent).RequiredField := Required;
           re.Parent := Entry.FPanel;
           re.Tag := CtrlID;
@@ -1339,4 +1349,5 @@
           re.Lines.Text := Items;
           re.OnChange := Entry.DoChange;
+          UpdateColorsFor508Compliance(re, TRUE);
           ctrl := re;
         end;
@@ -1358,5 +1369,5 @@
     Result := FLocked;
     if(not FLocked) then
-      ShowMessage('Template Field ' + FFldName + ' is currently being edited by another user.');
+      ShowMsg('Template Field ' + FFldName + ' is currently being edited by another user.');
   end
   else
@@ -1707,4 +1718,5 @@
 const
   EOL_MARKER = #182;
+  SR_BREAK   = #186;
 
 procedure PanelDestroy(AData: Pointer; Sender: TObject);
@@ -1737,12 +1749,17 @@
   FControls.Text := Text;
   if(FControls.Count > 1) then
+  begin
     for i := 1 to FControls.Count-1 do
       FControls[i] := EOL_MARKER + FControls[i];
+    if not ScreenReaderSystemActive then
+      StripScreenReaderCodes(FControls);
+  end;
   FFirstBuild := TRUE;
-  FPanel := TFieldPanel.Create(AParent.Owner);
+  FPanel := TDlgFieldPanel.Create(AParent.Owner);
   FPanel.Parent := AParent;
   FPanel.BevelOuter := bvNone;
   FPanel.Caption := '';
   FPanel.Font.Assign(FFont);
+  UpdateColorsFor508Compliance(FPanel, TRUE);
   idx := 0;
   while (idx < FControls.Count) do
@@ -1771,5 +1788,12 @@
           FControls[idx] := copy(txt,1,i-1);
           if(Fld.Required) then
+          begin
+            if ScreenReaderSystemActive then
+            begin
+              if Fld.FFldType in [dftCheckBoxes, dftRadioButtons] then
+                FControls[idx] := FControls[idx] + ScreenReaderStopCode;
+            end;
             FControls[idx] := FControls[idx] + '*';
+          end;
           Fld.CreateDialogControls(Self, idx, CtrlID);
           FControls.Insert(idx+1,copy(txt,i,MaxInt));
@@ -1789,4 +1813,20 @@
     end;
     inc(idx);
+  end;
+  if ScreenReaderSystemActive then
+  begin
+    idx := 0;
+    while (idx < FControls.Count) do
+    begin
+      txt := FControls[idx];
+      i := pos(ScreenReaderStopCode, txt);
+      if i > 0 then
+      begin
+        FControls[idx] := copy(txt, 1, i-1);
+        txt := copy(txt, i + ScreenReaderStopCodeLen, MaxInt);
+        FControls.Insert(idx+1, SR_BREAK + txt);
+      end;
+      inc(idx);
+    end;
   end;
 end;
@@ -1867,7 +1907,7 @@
           ind := 0;
       end;
-      if(Ctrl is TFieldLabel) then
-      begin
-        if not TFieldLabel(Ctrl).Exclude then begin
+      if(Ctrl is TCPRSTemplateFieldLabel) then
+      begin
+        if not TCPRSTemplateFieldLabel(Ctrl).Exclude then begin
           if emField <> '' then begin
             iField := GetTemplateField(emField,FALSE);
@@ -1884,9 +1924,9 @@
                             end;
             else {case}
-              Result := TFieldLabel(Ctrl).Caption
+              Result := TCPRSTemplateFieldLabel(Ctrl).Caption
             end; {case iField.FldType}
             end {if emField}
           else
-            Result := TFieldLabel(Ctrl).Caption;
+            Result := TCPRSTemplateFieldLabel(Ctrl).Caption;
         end;
       end
@@ -2014,7 +2054,8 @@
 end;
 
-function TTemplateDialogEntry.GetPanel(MaxLen: integer; AParent: TWinControl): TPanel;
-var
-  i, x, y, cnt, idx, ind, yinc, ybase, MaxX: integer; 
+function TTemplateDialogEntry.GetPanel(MaxLen: integer; AParent: TWinControl;
+                                       OwningCheckBox: TCPRSDialogParentCheckBox): TDlgFieldPanel;
+var
+  i, x, y, cnt, idx, ind, yinc, ybase, MaxX: integer;
   MaxTextLen: integer;  {Max num of chars per line in pixels}
   MaxChars: integer;    {Max num of chars per line}
@@ -2022,33 +2063,77 @@
   ctrl: TControl;
   LastLineBlank: boolean;
+  sLbl: TCPRSDialogStaticLabel;
+  nLbl: TVA508ChainedLabel;
+  sLblHeight: integer;
+  TabOrdr: integer;
+
 const
   FOCUS_RECT_MARGIN = 2; {The margin around the panel so the label won't
                         overlay the focus rect on its parent panel.}
+
+  procedure Add2TabOrder(ctrl: TWinControl);
+  begin
+    ctrl.TabOrder := TabOrdr;
+    inc(TabOrdr);
+  end;
+
+  function StripSRCode(var txt: string; code: string; len: integer): integer;
+  begin
+    Result := pos(code, txt);
+    if Result > 0 then
+    begin
+      delete(txt,Result,len);
+      dec(Result);
+    end
+    else
+      Result := -1;
+  end;
+
   procedure DoLabel(Atxt: string);
   var
-    lbl: TLabel;
-
-  begin
-    lbl := TLabel.Create(nil);
-    lbl.Parent := FPanel;
-    lbl.ShowAccelChar := FALSE;
-    lbl.Caption := Atxt;
-    lbl.Left := x;
-    lbl.Top := y;
-    inc(x, lbl.Width);
-  end;
-
-  procedure NextLine;
-  begin
-    if(MaxX < x) then
-      MaxX := x;
-    x := FOCUS_RECT_MARGIN;  {leave two pixels on the left for the Focus Rect}
-    inc(y, yinc);
-    yinc := ybase;
-  end;
-
-begin
-  MaxTextLen := MaxLen - (FOCUS_RECT_MARGIN * 2);{save room for the focus rectangle on the panel}
-  if(FFirstBuild or (FPanel.Width <> MaxLen)) then
+    ctrl: TControl;
+    tempLbl: TVA508ChainedLabel;
+
+  begin
+    if ScreenReaderSystemActive then
+    begin
+      if assigned(sLbl) then
+      begin
+        tempLbl := TVA508ChainedLabel.Create(nil);
+        if assigned(nLbl) then
+          nLbl.NextLabel := tempLbl
+        else
+          sLbl.NextLabel := tempLbl;
+        nLbl := tempLbl;
+        ctrl := nLbl;
+      end
+      else
+      begin
+        sLbl := TCPRSDialogStaticLabel.Create(nil);
+        ctrl := sLbl;
+      end;
+    end
+    else
+      ctrl := TLabel.Create(nil);
+    SetOrdProp(ctrl, ShowAccelCharProperty, ord(FALSE));
+    SetStrProp(ctrl, CaptionProperty, Atxt);
+    ctrl.Parent := FPanel;
+    ctrl.Left := x;
+    ctrl.Top := y;
+    if ctrl = sLbl then
+    begin
+      Add2TabOrder(sLbl);
+      sLbl.Height := sLblHeight;
+      ScreenReaderSystem_CurrentLabel(sLbl);
+    end;
+    if ScreenReaderSystemActive then
+      ScreenReaderSystem_AddText(Atxt);
+    UpdateColorsFor508Compliance(ctrl);
+    inc(x, ctrl.Width);
+  end;
+
+  procedure Init;
+  var
+    lbl : TLabel;
   begin
     if(FFirstBuild) then
@@ -2061,15 +2146,96 @@
     //ybase := FontHeightPixel(FFont.Handle) + 1 + (FOCUS_RECT_MARGIN * 2);  AGP commentout line for
                                                                            //reminder spacing
-    ybase := FontHeightPixel(FFont.Handle);
+    ybase := FontHeightPixel(FFont.Handle) + 2;
     yinc := ybase;
     LastLineBlank := FALSE;
+    sLbl := nil;
+    nLbl := nil;
+    TabOrdr := 0;
+    if ScreenReaderSystemActive then
+    begin
+      ScreenReaderSystem_CurrentCheckBox(OwningCheckBox);
+      lbl := TLabel.Create(nil);
+      try
+        lbl.Parent := FPanel;
+        sLblHeight := lbl.Height + 2;
+      finally
+        lbl.Free;
+      end;
+
+    end;
+  end;
+
+  procedure Text508Work;
+  var
+    ContinueCode: boolean;
+  begin
+    if StripCode(txt, SR_BREAK) then
+    begin
+      ScreenReaderSystem_Stop;
+      nLbl := nil;
+      sLbl := nil;
+    end;
+
+    ContinueCode := FALSE;
+    while StripSRCode(txt, ScreenReaderContinueCode, ScreenReaderContinueCodeLen) >= 0 do
+      ContinueCode := TRUE;
+    while StripSRCode(txt, ScreenReaderContinueCodeOld, ScreenReaderContinueCodeOldLen) >= 0 do
+      ContinueCode := TRUE;
+    if ContinueCode then
+      ScreenReaderSystem_Continue;
+  end;
+
+  procedure Ctrl508Work(ctrl: TControl);
+  var
+    lbl: TCPRSTemplateFieldLabel;
+  begin
+    if (Ctrl is TCPRSTemplateFieldLabel) and (not (Ctrl is TCPRSDialogHyperlinkLabel)) then
+    begin
+      lbl := Ctrl as TCPRSTemplateFieldLabel;
+      if trim(lbl.Caption) <> '' then
+      begin
+        ScreenReaderSystem_CurrentLabel(lbl);
+        ScreenReaderSystem_AddText(lbl.Caption);
+      end
+      else
+      begin
+        lbl.TabStop := FALSE;
+        ScreenReaderSystem_Stop;
+      end;
+    end
+    else
+    begin
+      if ctrl is TWinControl then
+        Add2TabOrder(TWinControl(ctrl));
+      if Supports(ctrl, ICPRSDialogComponent) then
+        ScreenReaderSystem_CurrentComponent(ctrl as ICPRSDialogComponent);
+    end;
+    sLbl := nil;
+    nLbl := nil;
+  end;
+
+  procedure NextLine;
+  begin
+    if(MaxX < x) then
+      MaxX := x;
+    x := FOCUS_RECT_MARGIN;  {leave two pixels on the left for the Focus Rect}
+    inc(y, yinc);
+    yinc := ybase;
+  end;
+
+begin
+  MaxTextLen := MaxLen - (FOCUS_RECT_MARGIN * 2);{save room for the focus rectangle on the panel}
+  if(FFirstBuild or (FPanel.Width <> MaxLen)) then
+  begin
+    Init;
     for i := 0 to FControls.Count-1 do
     begin
       txt := FControls[i];
-      if(copy(txt,1,1) = EOL_MARKER) then
+      if ScreenReaderSystemActive then
+        Text508Work;
+      if StripCode(txt,EOL_MARKER) then
       begin
         if((x <> 0) or LastLineBlank) then
           NextLine;
-        delete(txt,1,1);
         LastLineBlank := (txt = '');
       end;
@@ -2120,4 +2286,6 @@
         if(assigned(ctrl)) then
         begin
+          if ScreenReaderSystemActive then
+            Ctrl508Work(ctrl);
           idx := FIndents.IndexOfObject(Ctrl);
           if idx >= 0 then
@@ -2137,5 +2305,5 @@
           inc(x, Ctrl.Width + 4);
           if yinc <= Ctrl.Height then
-            yinc := Ctrl.Height + 1;
+            yinc := Ctrl.Height + 2;
           if (x < MaxLen) and ((Ctrl is TRichEdit) or
              ((Ctrl is TLabel) and (pos(CRLF, TLabel(Ctrl).Caption) > 0))) then
@@ -2150,4 +2318,6 @@
   if(FFieldValues <> '') then
     SetFieldValues(FFieldValues);
+  if ScreenReaderSystemActive then
+    ScreenReaderSystem_Stop;
   Result := FPanel;
 end;
@@ -2162,16 +2332,25 @@
   i, idx: integer;
   obj: TObject;
+  max: integer;
 
 begin
   if(assigned(FPanel)) then
   begin
-    for i := FPanel.ControlCount-1 downto 0 do
-      if(FPanel.Controls[i] is TLabel) then
+    max := FPanel.ControlCount-1;
+    for i := max downto 0 do
+    begin
+// deleting TVA508StaticText can delete several TVA508ChainedLabel components
+      if i < FPanel.ControlCount then
       begin
         obj := FPanel.Controls[i];
-        idx := FControls.IndexOfObject(obj);
-        if idx < 0 then
-          obj.Free;
-      end;
+        if (not (obj is TVA508ChainedLabel)) and
+           ((obj is TLabel) or (obj is TVA508StaticText)) then
+        begin
+          idx := FControls.IndexOfObject(obj);
+          if idx < 0 then
+            obj.Free;
+        end;
+      end;
+    end;
   end;
 end;
@@ -2188,8 +2367,8 @@
     M.Data := Self;
     M.Code := @PanelDestroy;
-    TFieldPanel(FPanel).OnDestroy := TNotifyEvent(M);
+    FPanel.OnDestroy := TNotifyEvent(M);
   end
   else
-    TFieldPanel(FPanel).OnDestroy := nil;
+    FPanel.OnDestroy := nil;
 end;
 
@@ -2232,4 +2411,5 @@
         begin
           Done := FALSE;
+          TORCheckBox(Ctrl).Checked := FALSE;        //<-PSI-06-170-ADDED THIS LINE - v27.23 - RV
           if(cnt = 0) then
             cnt := DelimCount(AText, '|') + 1;
@@ -2278,72 +2458,24 @@
 end;
 
+function TTemplateDialogEntry.StripCode(var txt: string; code: char): boolean;
+var
+  p: integer;
+begin
+  p := pos(code, txt);
+  Result := (p > 0);
+  if Result then
+  begin
+    while p > 0 do
+    begin
+      delete(txt, p, 1);
+      p := pos(code, txt);
+    end;
+  end;
+end;
+
 procedure TTemplateDialogEntry.UpDownChange(Sender: TObject);
 begin
   EnsureText(TEdit(Sender), TUpDown(TEdit(Sender).Tag));
   DoChange(Sender);
-end;
-
-{ TFieldPanel }
-
-destructor TFieldPanel.Destroy;
-begin
-  if(assigned(FOnDestroy)) then
-    FOnDestroy(Self);
-  inherited;
-end;
-
-{intercept the paint event to draw the focus rect if FFocused is true}
-function TFieldPanel.GetFocus: boolean;
-begin
-  result := Focused;
-end;
-
-procedure TFieldPanel.Paint;
-var
-  DC: HDC;
-  R: TRect;
-
-begin
-  inherited;
-  if(Focused) then
-  begin
-    if(not assigned(FCanvas)) then
-      FCanvas := TControlCanvas.Create;
-    DC := GetWindowDC(Handle);
-    try
-      FCanvas.Handle := DC;
-      R := ClientRect;
-      InflateRect(R, -1, -1);
-      FCanvas.DrawFocusRect(R);
-    finally
-      ReleaseDC(Handle, DC);
-    end;
-  end;
-end;
-
-procedure TFieldPanel.SetTheFocus(const Value: boolean);
-begin
-  if Value then
-    SetFocus;
-end;
-
-{ TWebLabel }
-
-procedure TWebLabel.Clicked(Sender: TObject);
-begin
-  GotoWebPage(FAddr);
-end;
-
-procedure TWebLabel.Init(Addr: string);
-begin
-  FAddr := Addr;
-  OnClick := Clicked;
-  Font.Assign(TORExposedControl(Parent).Font);
-  Font.Color := clActiveCaption;
-  Font.Style := Font.Style + [fsUnderline];
-  AdjustBounds; // make sure we have the right width
-  AutoSize := FALSE;
-  Height := Height + 1; // Courier New doesn't support underline unless it's higher
-  Cursor := crHandPoint;
 end;
 
@@ -2371,4 +2503,48 @@
 end;
 
+procedure StripScreenReaderCodes(var Text: string);
+var
+  p, j: integer;
+begin
+  for j := low(ScreenReaderCodes) to high(ScreenReaderCodes) do
+  begin
+    p := 1;
+    while (p > 0) do
+    begin
+      p := posex(ScreenReaderCodes[j], Text, p);
+      if p > 0 then
+        delete(Text, p, ScreenReaderCodeLens[j]);
+    end;
+  end;
+end;
+
+procedure StripScreenReaderCodes(SL: TStrings);
+var
+  temp: string;
+  i: integer;
+
+begin
+  for i := 0 to SL.Count - 1 do
+  begin
+    temp := SL[i];
+    StripScreenReaderCodes(temp);
+    SL[i] := temp;
+  end;
+end;
+
+function HasScreenReaderBreakCodes(SL: TStrings): boolean;
+var
+  i: integer;
+
+begin
+  Result := TRUE;
+  for i := 0 to SL.Count - 1 do
+  begin
+    if pos(ScreenReaderCodeSignature, SL[i]) > 0 then
+      exit;
+  end;
+  Result := FALSE;
+end;
+
 initialization
 
