inplong.pas 7.6 KB

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