inplong.pas 7.7 KB

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