inplong.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  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_UNIX}
  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));
  100. S.Read(LLim, Sizeof(LLim));
  101. S.Read(ULim, Sizeof(ULim));
  102. end;
  103. {-------------------TInputLong.Store}
  104. procedure TInputLong.Store(var S : TStream);
  105. begin
  106. TInputLine.Store(S);
  107. S.Write(ILOptions, Sizeof(ILOptions));
  108. S.Write(LLim, Sizeof(LLim));
  109. S.Write(ULim, Sizeof(ULim));
  110. end;
  111. {-------------------TInputLong.DataSize}
  112. FUNCTION TInputLong.DataSize:Sw_Word;
  113. begin
  114. DataSize := Sizeof(LongInt);
  115. end;
  116. {-------------------TInputLong.GetData}
  117. PROCEDURE TInputLong.GetData(var Rec);
  118. var code : Integer;
  119. begin
  120. Val(Data^, LongInt(Rec), code);
  121. end;
  122. FUNCTION Hex2(B : Byte) : String;
  123. Const
  124. HexArray : array[0..15] of char = '0123456789ABCDEF';
  125. begin
  126. Hex2[0] := #2;
  127. Hex2[1] := HexArray[B shr 4];
  128. Hex2[2] := HexArray[B and $F];
  129. end;
  130. FUNCTION Hex4(W : Word) : String;
  131. begin Hex4 := Hex2(Hi(W))+Hex2(Lo(W)); end;
  132. FUNCTION Hex8(L : LongInt) : String;
  133. begin Hex8 := Hex4(LongRec(L).Hi)+Hex4(LongRec(L).Lo); end;
  134. function FormHexStr(L : LongInt) : String;
  135. var
  136. Minus : boolean;
  137. S : string[20];
  138. begin
  139. Minus := L < 0;
  140. if Minus then L := -L;
  141. S := Hex8(L);
  142. while (Length(S) > 1) and (S[1] = '0') do Delete(S, 1, 1);
  143. S := '$' + S;
  144. if Minus then System.Insert('-', S, 2);
  145. FormHexStr := S;
  146. end;
  147. {-------------------TInputLong.SetData}
  148. PROCEDURE TInputLong.SetData(var Rec);
  149. var
  150. L : LongInt;
  151. S : string;
  152. begin
  153. L := LongInt(Rec);
  154. if L > ULim then L := ULim
  155. else if L < LLim then L := LLim;
  156. if ILOptions and ilDisplayHex <> 0 then
  157. S := FormHexStr(L)
  158. else
  159. Str(L : -1, S);
  160. if Length(S) > MaxLen then S[0] := chr(MaxLen);
  161. Data^ := S;
  162. end;
  163. {-------------------TInputLong.RangeCheck}
  164. FUNCTION TInputLong.RangeCheck : Boolean;
  165. var
  166. L : LongInt;
  167. code : Integer;
  168. begin
  169. if (Data^ = '') and (ILOptions and ilBlankEqZero <> 0) then
  170. Data^ := '0';
  171. Val(Data^, L, code);
  172. RangeCheck := (Code = 0) and (L >= LLim) and (L <= ULim);
  173. end;
  174. {-------------------TInputLong.Error}
  175. PROCEDURE TInputLong.Error;
  176. var
  177. SU, SL : string[40];
  178. PMyLabel : PLabel;
  179. Labl : string;
  180. I : Integer;
  181. function FindIt(P : PView) : boolean;{$ifdef PPC_BP}far;{$endif}
  182. begin
  183. FindIt := (Typeof(P^) = Typeof(TLabel)) and (PLabel(P)^.Link = PView(@Self));
  184. end;
  185. begin
  186. Str(LLim : -1, SL);
  187. Str(ULim : -1, SU);
  188. if ILOptions and ilHex <> 0 then
  189. begin
  190. SL := SL+'('+FormHexStr(LLim)+')';
  191. SU := SU+'('+FormHexStr(ULim)+')';
  192. end;
  193. if Owner <> Nil then
  194. PMyLabel := PLabel(Owner^.FirstThat(@FindIt))
  195. else PMyLabel := Nil;
  196. if PMyLabel <> Nil then PMyLabel^.GetText(Labl)
  197. else Labl := '';
  198. if Labl <> '' then
  199. begin
  200. I := Pos('~', Labl);
  201. while I > 0 do
  202. begin
  203. System.Delete(Labl, I, 1);
  204. I := Pos('~', Labl);
  205. end;
  206. Labl := '"'+Labl+'"';
  207. end;
  208. MessageBox(Labl + ^M^J'Value not within range '+SL+' to '+SU, Nil,
  209. mfError+mfOKButton);
  210. end;
  211. {-------------------TInputLong.HandleEvent}
  212. PROCEDURE TInputLong.HandleEvent(var Event : TEvent);
  213. begin
  214. if (Event.What = evKeyDown) then
  215. begin
  216. case Event.KeyCode of
  217. kbTab, kbShiftTab
  218. : if not RangeCheck then
  219. begin
  220. Error;
  221. SelectAll(True);
  222. ClearEvent(Event);
  223. end;
  224. end;
  225. if Event.CharCode <> #0 then {a character key}
  226. begin
  227. Event.Charcode := Upcase(Event.Charcode);
  228. case Event.Charcode of
  229. '0'..'9', #1..#$1B : ; {acceptable}
  230. '-' : if (LLim >= 0) or (CurPos <> 0) then
  231. ClearEvent(Event);
  232. '$' : if ILOptions and ilHex = 0 then ClearEvent(Event);
  233. 'A'..'F' : if Pos('$', Data^) = 0 then ClearEvent(Event);
  234. else ClearEvent(Event);
  235. end;
  236. end;
  237. end;
  238. TInputLine.HandleEvent(Event);
  239. end;
  240. {-------------------TInputLong.Valid}
  241. FUNCTION TInputLong.Valid(Cmd : Word) : Boolean;
  242. var
  243. Rslt : boolean;
  244. begin
  245. Rslt := TInputLine.Valid(Cmd);
  246. if Rslt and (Cmd <> 0) and (Cmd <> cmCancel) then
  247. begin
  248. Rslt := RangeCheck;
  249. if not Rslt then
  250. begin
  251. Error;
  252. Select;
  253. SelectAll(True);
  254. end;
  255. end;
  256. Valid := Rslt;
  257. end;
  258. end.