inplong.pas 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. Unit InpLong;
  2. (*--
  3. TInputLong is a derivitave of TInputline designed to accept LongInt
  4. numeric input. Since both the upper and lower limit of acceptable numeric
  5. input can be set, TInputLong may be used for Integer, Word, or Byte input
  6. as well. Option flag bits allow optional hex input and display. A blank
  7. field may optionally be rejected or interpreted as zero.
  8. Methods
  9. constructor Init(var R : TRect; AMaxLen : Integer;
  10. LowerLim, UpperLim : LongInt; Flgs : Word);
  11. Calls TInputline.Init and saves the desired limits and Flags. Flags may
  12. be a combination of:
  13. ilHex will accept hex input (preceded by '$') as well as decimal.
  14. ilBlankEqZero if set, will interpret a blank field as '0'.
  15. ilDisplayHex if set, will display numeric as hex when possible.
  16. constructor Load(var S : TStream);
  17. procedure Store(var S : TStream);
  18. The usual Load and Store routines. Be sure to call RegisterType(RInputLong)
  19. to register the type.
  20. FUNCTION DataSize : Word; virtual;
  21. PROCEDURE GetData(var Rec); virtual;
  22. PROCEDURE SetData(var Rec); virtual;
  23. The transfer methods. DataSize is Sizeof(LongInt) and Rec should be
  24. the address of a LongInt.
  25. FUNCTION RangeCheck : Boolean; virtual;
  26. Returns True if the entered string evaluates to a number >= LowerLim and
  27. <= UpperLim.
  28. PROCEDURE Error; virtual;
  29. Error is called when RangeCheck fails. It displays a messagebox indicating
  30. the label (if any) of the faulting view, as well as the allowable range.
  31. PROCEDURE HandleEvent(var Event : TEvent); virtual;
  32. HandleEvent filters out characters which are not appropriate to numeric
  33. input. Tab and Shift Tab cause a call to RangeCheck and a call to Error
  34. if RangeCheck returns false. The input must be valid to Tab from the view.
  35. There's no attempt made to stop moving to another view with the mouse.
  36. FUNCTION Valid(Cmd : Word) : Boolean; virtual;
  37. if TInputline.Valid is true and Cmd is neither cmValid or cmCancel, Valid
  38. then calls RangeCheck. If RangeCheck is false, then Error is called and
  39. Valid returns False.
  40. ----*)
  41. {$i platform.inc}
  42. {$ifdef PPC_FPC}
  43. {$H-}
  44. {$else}
  45. {$F+,O+,E+,N+}
  46. {$endif}
  47. {$X+,R-,I-,Q-,V-}
  48. {$ifndef OS_LINUX}
  49. {$S-}
  50. {$endif}
  51. Interface
  52. uses Objects, Drivers, Views, Dialogs, MsgBox;
  53. {flags for TInputLong constructor}
  54. const
  55. ilHex = 1; {will enable hex input with leading '$'}
  56. ilBlankEqZero = 2; {No input (blank) will be interpreted as '0'}
  57. ilDisplayHex = 4; {Number displayed as hex when possible}
  58. Type
  59. TInputLong = Object(TInputLine)
  60. ILOptions : Word;
  61. LLim, ULim : LongInt;
  62. constructor Init(var R : TRect; AMaxLen : Sw_Integer;
  63. LowerLim, UpperLim : LongInt; Flgs : Word);
  64. constructor Load(var S : TStream);
  65. procedure Store(var S : TStream);
  66. FUNCTION DataSize : Sw_Word; virtual;
  67. PROCEDURE GetData(var Rec); virtual;
  68. PROCEDURE SetData(var Rec); virtual;
  69. FUNCTION RangeCheck : Boolean; virtual;
  70. PROCEDURE Error; virtual;
  71. PROCEDURE HandleEvent(var Event : TEvent); virtual;
  72. FUNCTION Valid(Cmd : Word) : Boolean; virtual;
  73. end;
  74. PInputLong = ^TInputLong;
  75. const
  76. RInputLong : TStreamRec = (
  77. ObjType: 711;
  78. VmtLink: Ofs(Typeof(TInputLong)^);
  79. Load : @TInputLong.Load;
  80. Store : @TInputLong.Store);
  81. Implementation
  82. uses
  83. FVConsts;
  84. {-----------------TInputLong.Init}
  85. constructor TInputLong.Init(var R : TRect; AMaxLen : Sw_Integer;
  86. LowerLim, UpperLim : LongInt; Flgs : Word);
  87. begin
  88. if not TInputLine.Init(R, AMaxLen) then fail;
  89. ULim := UpperLim;
  90. LLim := LowerLim;
  91. if Flgs and ilDisplayHex <> 0 then Flgs := Flgs or ilHex;
  92. ILOptions := Flgs;
  93. if ILOptions and ilBlankEqZero <> 0 then Data^ := '0';
  94. end;
  95. {-------------------TInputLong.Load}
  96. constructor TInputLong.Load(var S : TStream);
  97. begin
  98. TInputLine.Load(S);
  99. S.Read(ILOptions, Sizeof(ILOptions)+Sizeof(LLim)+Sizeof(ULim));
  100. end;
  101. {-------------------TInputLong.Store}
  102. procedure TInputLong.Store(var S : TStream);
  103. begin
  104. TInputLine.Store(S);
  105. S.Write(ILOptions, Sizeof(ILOptions)+Sizeof(LLim)+Sizeof(ULim));
  106. end;
  107. {-------------------TInputLong.DataSize}
  108. FUNCTION TInputLong.DataSize:Sw_Word;
  109. begin
  110. DataSize := Sizeof(LongInt);
  111. end;
  112. {-------------------TInputLong.GetData}
  113. PROCEDURE TInputLong.GetData(var Rec);
  114. var code : Integer;
  115. begin
  116. Val(Data^, LongInt(Rec), code);
  117. end;
  118. FUNCTION Hex2(B : Byte) : String;
  119. Const
  120. HexArray : array[0..15] of char = '0123456789ABCDEF';
  121. begin
  122. Hex2[0] := #2;
  123. Hex2[1] := HexArray[B shr 4];
  124. Hex2[2] := HexArray[B and $F];
  125. end;
  126. FUNCTION Hex4(W : Word) : String;
  127. begin Hex4 := Hex2(Hi(W))+Hex2(Lo(W)); end;
  128. FUNCTION Hex8(L : LongInt) : String;
  129. begin Hex8 := Hex4(LongRec(L).Hi)+Hex4(LongRec(L).Lo); end;
  130. function FormHexStr(L : LongInt) : String;
  131. var
  132. Minus : boolean;
  133. S : string[20];
  134. begin
  135. Minus := L < 0;
  136. if Minus then L := -L;
  137. S := Hex8(L);
  138. while (Length(S) > 1) and (S[1] = '0') do Delete(S, 1, 1);
  139. S := '$' + S;
  140. if Minus then System.Insert('-', S, 2);
  141. FormHexStr := S;
  142. end;
  143. {-------------------TInputLong.SetData}
  144. PROCEDURE TInputLong.SetData(var Rec);
  145. var
  146. L : LongInt;
  147. S : string;
  148. begin
  149. L := LongInt(Rec);
  150. if L > ULim then L := ULim
  151. else if L < LLim then L := LLim;
  152. if ILOptions and ilDisplayHex <> 0 then
  153. S := FormHexStr(L)
  154. else
  155. Str(L : -1, S);
  156. if Length(S) > MaxLen then S[0] := chr(MaxLen);
  157. Data^ := S;
  158. end;
  159. {-------------------TInputLong.RangeCheck}
  160. FUNCTION TInputLong.RangeCheck : Boolean;
  161. var
  162. L : LongInt;
  163. code : Integer;
  164. begin
  165. if (Data^ = '') and (ILOptions and ilBlankEqZero <> 0) then
  166. Data^ := '0';
  167. Val(Data^, L, code);
  168. RangeCheck := (Code = 0) and (L >= LLim) and (L <= ULim);
  169. end;
  170. {-------------------TInputLong.Error}
  171. PROCEDURE TInputLong.Error;
  172. var
  173. SU, SL : string[40];
  174. PMyLabel : PLabel;
  175. Labl : string;
  176. I : Integer;
  177. function FindIt(P : PView) : boolean;{$ifdef PPC_BP}far;{$endif}
  178. begin
  179. FindIt := (Typeof(P^) = Typeof(TLabel)) and (PLabel(P)^.Link = PView(@Self));
  180. end;
  181. begin
  182. Str(LLim : -1, SL);
  183. Str(ULim : -1, SU);
  184. if ILOptions and ilHex <> 0 then
  185. begin
  186. SL := SL+'('+FormHexStr(LLim)+')';
  187. SU := SU+'('+FormHexStr(ULim)+')';
  188. end;
  189. if Owner <> Nil then
  190. PMyLabel := PLabel(Owner^.FirstThat(@FindIt))
  191. else PMyLabel := Nil;
  192. if PMyLabel <> Nil then PMyLabel^.GetText(Labl)
  193. else Labl := '';
  194. if Labl <> '' then
  195. begin
  196. I := Pos('~', Labl);
  197. while I > 0 do
  198. begin
  199. System.Delete(Labl, I, 1);
  200. I := Pos('~', Labl);
  201. end;
  202. Labl := '"'+Labl+'"';
  203. end;
  204. MessageBox(Labl + ^M^J'Value not within range '+SL+' to '+SU, Nil,
  205. mfError+mfOKButton);
  206. end;
  207. {-------------------TInputLong.HandleEvent}
  208. PROCEDURE TInputLong.HandleEvent(var Event : TEvent);
  209. begin
  210. if (Event.What = evKeyDown) then
  211. begin
  212. case Event.KeyCode of
  213. kbTab, kbShiftTab
  214. : if not RangeCheck then
  215. begin
  216. Error;
  217. SelectAll(True);
  218. ClearEvent(Event);
  219. end;
  220. end;
  221. if Event.CharCode <> #0 then {a character key}
  222. begin
  223. Event.Charcode := Upcase(Event.Charcode);
  224. case Event.Charcode of
  225. '0'..'9', #1..#$1B : ; {acceptable}
  226. '-' : if (LLim >= 0) or (CurPos <> 0) then
  227. ClearEvent(Event);
  228. '$' : if ILOptions and ilHex = 0 then ClearEvent(Event);
  229. 'A'..'F' : if Pos('$', Data^) = 0 then ClearEvent(Event);
  230. else ClearEvent(Event);
  231. end;
  232. end;
  233. end;
  234. TInputLine.HandleEvent(Event);
  235. end;
  236. {-------------------TInputLong.Valid}
  237. FUNCTION TInputLong.Valid(Cmd : Word) : Boolean;
  238. var
  239. Rslt : boolean;
  240. begin
  241. Rslt := TInputLine.Valid(Cmd);
  242. if Rslt and (Cmd <> 0) and (Cmd <> cmCancel) then
  243. begin
  244. Rslt := RangeCheck;
  245. if not Rslt then
  246. begin
  247. Error;
  248. Select;
  249. SelectAll(True);
  250. end;
  251. end;
  252. Valid := Rslt;
  253. end;
  254. end.