home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / hc / barbutto.sit / BarButton / card_5475.txt < prev    next >
Text File  |  1987-11-23  |  38KB  |  1,415 lines

  1. -- card: 5475 from stack: in
  2. -- bmap block id: 0
  3. -- flags: 0000
  4. -- background id: 5228
  5. -- name: Card 6
  6.  
  7.  
  8. -- part 3 (field)
  9. -- low flags: 00
  10. -- high flags: 2007
  11. -- rect: left=19 top=75 right=293 bottom=491
  12. -- title width / last selected line: 0
  13. -- icon id / first selected line: 0 / 0
  14. -- text alignment: 0
  15. -- font id: 3
  16. -- text size: 9
  17. -- style flags: 0
  18. -- line height: 12
  19. -- part name: 
  20.  
  21.  
  22. -- part 5 (field)
  23. -- low flags: 00
  24. -- high flags: 0000
  25. -- rect: left=19 top=37 right=76 bottom=491
  26. -- title width / last selected line: 0
  27. -- icon id / first selected line: 0 / 0
  28. -- text alignment: 1
  29. -- font id: 3
  30. -- text size: 9
  31. -- style flags: 0
  32. -- line height: 12
  33. -- part name: 
  34.  
  35.  
  36. -- part 6 (button)
  37. -- low flags: 00
  38. -- high flags: 2000
  39. -- rect: left=119 top=313 right=342 bottom=152
  40. -- title width / last selected line: 0
  41. -- icon id / first selected line: 26425 / 26425
  42. -- text alignment: 1
  43. -- font id: 0
  44. -- text size: 12
  45. -- style flags: 0
  46. -- line height: 16
  47. -- part name: New Button
  48. ----- HyperTalk script -----
  49. on mouseUp
  50.   go next card
  51. end mouseUp
  52.  
  53. on mousedown
  54.   if the optionkey is down then put script of me into bkgnd field lowerpane
  55. end mousedown
  56.  
  57.  
  58. -- part contents for background part 1
  59. ----- text -----
  60. VESTIGIAL CARD: This is the complete text of the Lightspeed Pascal source of the BarButton XCMD.  If you want to recompile with modifications, be sure the files DA PasLib and MacTraps are in the Project, and Build and Save As a Code resource of type 'XCMD'.  Then ResEdit the XCMD into your stack.
  61. This XCMD was written more as an experiment than anything else.
  62. If you would like your own custom version, and don't feel like writing it yourself, give me a call.  There are many simple tasks that Hypercard cannot do well, or quickly, or at all.  But XCMD's and XFCN's can avoid most of these deficencies.
  63.  
  64. Infosynthesis
  65. 2960 Ferry Street
  66. Eugene, OR 97405
  67. (503) 344-3322
  68. {BarButton adjusts the size of the bar contained within rect passed in "It", and using the }
  69. {options in the first 4 parameters.}
  70. UNIT Main;
  71.  
  72. INTERFACE
  73.  
  74. USES
  75. HyperXCMD;
  76.  
  77.  
  78. -- part contents for background part 2
  79. ----- text -----
  80.  
  81.  
  82. {BarButton adjusts the size of the bar contained within rect in first 4}
  83. {parameters.}
  84. UNIT Main;
  85.  
  86. INTERFACE
  87.  
  88. USES
  89. HyperXCMD;
  90.  
  91. PROCEDURE Main (ParamPtr : XCmdPtr);
  92.  
  93. IMPLEMENTATION
  94.  
  95. {-------------------------------------------------------------------------------}
  96. PROCEDURE BarButton (ParamPtr : XCmdPtr);
  97. FORWARD;
  98.  
  99. PROCEDURE Main;
  100. BEGIN
  101. BarButton(ParamPtr);
  102. END;
  103.  
  104. PROCEDURE BarButton;
  105.  
  106. CONST
  107. leftToRight = 1;
  108. rightToLeft = 2;
  109. bottomToTop = 3;
  110. topToBottom = 4;
  111.  
  112. VAR
  113. str : Str255;
  114. ButtonRect, DrawRect, BlankRect, ViewRect, TextRect : rect;
  115. InRect, newLoc, dummy, ShowValue, SuppressDisplay : boolean;
  116. spot, oldspot, TextPoint : point;
  117. direction, maximumValue, minimumValue, CurrentValue, InitialValue : integer;
  118. theInfo : FontInfo;
  119. TextHeight, TextWidth, ButtonHeight, ButtonWidth : integer;
  120. proportion : real;
  121.  
  122. {-------------------------------------------------------------------------------}
  123. PROCEDURE DoJsr (addr : ProcPtr);
  124. INLINE
  125. $205F, $4E90;
  126. { Jump subroutine to a procedure.   Pop address into A0, JSR (A0) }
  127.  
  128. {-------------------------------------------------------------------------------}
  129. PROCEDURE ZeroToPas (zeroStr : Ptr;
  130. VAR pasStr : Str255);
  131. {Fill the Pascal string with the contents of the zero-terminated}
  132. {   string.  You create the Pascal string and pass it in as a VAR }
  133. {   parameter.  Useful for converting the arguments of any XCMD to }
  134. {   Pascal strings.}
  135. BEGIN
  136. WITH paramPtr^ DO
  137. BEGIN
  138. inArgs[1] := ORD(zeroStr);
  139. inArgs[2] := ORD(@pasStr);
  140. request := xreqZeroToPas;
  141. DoJsr(entryPoint);
  142. END;
  143. END;
  144.  
  145. {-------------------------------------------------------------------------------}
  146. FUNCTION StrToNum (str : Str31) : LongInt;
  147. {  Convert a string of ASCII decimal digits to a signed long integer.}
  148. {   Negative sign is allowed.  }
  149. BEGIN
  150. WITH paramPtr^ DO
  151. BEGIN
  152. inArgs[1] := ORD(@str);
  153. request := xreqStrToNum;
  154. DoJsr(entryPoint);
  155. StrToNum := outArgs[1];
  156. END;
  157. END;
  158.  
  159. {-------------------------------------------------------------------------------}
  160. FUNCTION PasToZero (str : Str255) : Handle;
  161. {  Convert a Pascal string to a zero-terminated string.  Returns a handle}
  162. {   to a new zero-terminated string.  The caller must dispose the handle. }
  163. BEGIN
  164. WITH paramPtr^ DO
  165. BEGIN
  166. inArgs[1] := ORD(@str);
  167. request := xreqPasToZero;
  168. DoJsr(entryPoint);
  169. PasToZero := Handle(outArgs[1]);
  170. END;
  171. END;
  172.  
  173. {-------------------------------------------------------------------------------}
  174. FUNCTION EvalExpr (expr : Str255) : Handle;
  175. {  Evaluate a HyperCard expression and return the answer.  The answer is}
  176. {   a handle to a zero-terminated string. }
  177. BEGIN
  178. WITH paramPtr^ DO
  179. BEGIN
  180. inArgs[1] := ORD(@expr);
  181. request := xreqEvalExpr;
  182. DoJsr(entryPoint);
  183. EvalExpr := Handle(outArgs[1]);
  184. END;
  185. END;
  186.  
  187. {-------------------------------------------------------------------------------}
  188. FUNCTION NumToStr (num : LongInt) : Str31;
  189. {  Convert a signed long integer to a Pascal string.  }
  190. VAR
  191. str : Str31;
  192. BEGIN
  193. WITH paramPtr^ DO
  194. BEGIN
  195. inArgs[1] := num;
  196. inArgs[2] := ORD(@str);
  197. request := xreqNumToStr;
  198. DoJsr(entryPoint);
  199. NumToStr := str;
  200. END;
  201. END;
  202.  
  203. {-------------------------------------------------------------------------------}
  204. FUNCTION IntExpr (theString : str255) : integer;
  205. TYPE
  206. Ptr31 = ^str31;
  207. Hand31 = ^Ptr31;
  208.  
  209. VAR
  210. tempHand : handle;
  211. ShortStr : str31;
  212. ShortPtr : Ptr31;
  213. ShortHand : Hand31;
  214. NumLong : longint;
  215. LongStr : str255;
  216.  
  217. BEGIN
  218. tempHand := EvalExpr(theString);
  219. ZeroToPas(tempHand^, LongStr);
  220. ShortStr := LongStr;
  221. NumLong := StrToNum(ShortStr);
  222. IntExpr := loword(NumLong);
  223. DisposHandle(tempHand);
  224. END;
  225.  
  226. {-------------------------------------------------------------------------------}
  227. FUNCTION DePad (str : str255) : str255;
  228. VAR
  229. c : integer;
  230.  
  231. BEGIN
  232. FOR c := length(str) DOWNTO 1 DO
  233. IF ord(str[c]) = 32 THEN
  234. Delete(str, c, 1);
  235. DePad := str;
  236. END;
  237.  
  238. {-------------------------------------------------------------------------------}
  239. PROCEDURE DisplayValue;
  240. BEGIN
  241. IF ShowValue THEN
  242. BEGIN
  243. TextFont(systemfont);{Chicago}
  244. TextSize(12);
  245. str := Depad(StringOf(CurrentValue));
  246. CASE direction OF
  247. leftToRight, rightToLeft : 
  248. MoveTo(TextPoint.h, TextPoint.v);
  249. bottomToTop, topToBottom : 
  250. MoveTo(TextPoint.h - StringWidth(str) DIV 2, TextPoint.v);
  251. END;
  252. EraseRect(TextRect);
  253. DrawString(str);
  254. END;
  255. END;{DisplayValue}
  256.  
  257. {-------------------------------------------------------------------------------}
  258. PROCEDURE ComputeValue;
  259.  
  260. BEGIN
  261. WITH ViewRect DO
  262. CASE direction OF
  263. leftToRight : 
  264. proportion := (oldspot.h - left) * 1.0 / (right - left);
  265. rightToLeft : 
  266. proportion := (right - oldspot.h) * 1.0 / (right - left);
  267. bottomToTop : 
  268. proportion := (bottom - oldspot.v) * 1.0 / (bottom - top);
  269. topToBottom : 
  270. proportion := (oldspot.v - top) * 1.0 / (bottom - top);
  271. END;
  272.  
  273. IF proportion < 0 THEN
  274. proportion := 0;
  275. IF proportion > 1.0 THEN
  276. proportion := 1.0;
  277.  
  278. CurrentValue := round(proportion * (maximumValue - minimumValue) + minimumValue);
  279. DisplayValue;
  280. END;{ComputeValue}
  281.  
  282. {-------------------------------------------------------------------------------}
  283. BEGIN
  284. ButtonRect.left := IntExpr('item 1 of It');
  285. ButtonRect.top := IntExpr('item 2 of It');
  286. ButtonRect.right := IntExpr('item 3 of It');
  287. ButtonRect.bottom := IntExpr('item 4 of It');
  288. ButtonHeight := ButtonRect.bottom - ButtonRect.top;
  289. ButtonWidth := ButtonRect.right - ButtonRect.left;
  290.  
  291. ViewRect := ButtonRect;
  292. InsetRect(ViewRect, 1, 1);
  293. DrawRect := ViewRect;
  294. BlankRect := DrawRect;
  295.  
  296. WITH ButtonRect DO
  297. IF right - left > bottom - top THEN
  298. direction := leftToRight
  299. ELSE
  300. direction := bottomToTop;
  301. maximumValue := 100;
  302. minimumValue := 0;
  303. ShowValue := FALSE;
  304. SuppressDisplay := FALSE;
  305. InitialValue := -32767;{Hopefully no one will actually use that value!}
  306.  
  307. WITH ParamPtr^ DO
  308. BEGIN
  309. IF paramCount > 0 THEN
  310. BEGIN
  311. ZeroToPas(params[1]^, str);
  312. direction := StrToNum(str);
  313. IF (direction >= -4) AND (direction <= -1) THEN
  314. BEGIN
  315. SuppressDisplay := TRUE;
  316. direction := -direction;
  317. END;
  318. IF (direction < 1) OR (direction > 4) THEN
  319. direction := leftToRight;
  320. IF paramCount > 1 THEN
  321. BEGIN
  322. ZeroToPas(params[2]^, str);
  323. maximumValue := StrToNum(str);
  324. ShowValue := TRUE;
  325. IF paramCount > 2 THEN
  326. BEGIN
  327. ZeroToPas(params[3]^, str);
  328. minimumValue := StrToNum(str);
  329. IF minimumValue >= maximumValue THEN
  330. minimumValue := maximumValue + 10;
  331. IF paramCount > 3 THEN
  332. BEGIN
  333. ZeroToPas(params[4]^, str);
  334. InitialValue := StrToNum(str);
  335. END;{end of reading initial value}
  336. END;{end of reading third parameter}
  337. END;{end of reading second parameter}
  338. END;{end of reading first parameter}
  339. END;{with ParamPtr^}
  340. IF SuppressDisplay THEN
  341. ShowValue := FALSE;
  342.  
  343. IF InitialValue = -32767 THEN
  344. GetMouse(spot){Get current loc of mouse}
  345. ELSE
  346. BEGIN{force initial value of bar without mousedown}
  347. proportion := (InitialValue - minimumValue) * 1.0 / (maximumValue - minimumValue);
  348. IF proportion < 0 THEN
  349. proportion := 0;
  350. IF proportion > 1.0 THEN
  351. proportion := 1.0;
  352. CASE direction OF
  353. leftToRight : 
  354. spot.h := round(DrawRect.left + proportion * ButtonWidth);
  355. rightToLeft : 
  356. spot.h := round(DrawRect.right - proportion * ButtonWidth);
  357. bottomToTop : 
  358. spot.v := round(DrawRect.bottom - proportion * ButtonHeight);
  359. topToBottom : 
  360. spot.v := round(DrawRect.top + proportion * ButtonHeight);
  361. END;{end of case direction}
  362. END;{end of forcing initial value}
  363.  
  364. CASE direction OF
  365. leftToRight : 
  366. BEGIN
  367. DrawRect.right := spot.h;
  368. BlankRect.left := spot.h;
  369. END;
  370. rightToLeft : 
  371. BEGIN
  372. DrawRect.left := spot.h;
  373. BlankRect.right := spot.h;
  374. END;
  375. bottomToTop : 
  376. BEGIN
  377. DrawRect.top := spot.v;
  378. BlankRect.bottom := spot.v;
  379. END;
  380. topToBottom : 
  381. BEGIN
  382. DrawRect.bottom := spot.v;
  383. BlankRect.top := spot.v;
  384. END;
  385. END;{end of case direction}
  386.  
  387. IF ShowValue THEN{Set up stuff for ShowValue}
  388. BEGIN
  389. IF StringWidth(DePad(StringOf(maximumValue))) >= StringWidth(DePad(StringOf(minimumValue))) THEN
  390. TextWidth := StringWidth(DePad(StringOf(maximumValue)))
  391. ELSE
  392. TextWidth := StringWidth(DePad(StringOf(minimumValue)));
  393.  
  394. GetFontInfo(theInfo);
  395. TextHeight := theInfo.ascent;{numbers don't have descenders}
  396.  
  397. CASE direction OF
  398. leftToRight, rightToLeft : 
  399. BEGIN
  400. TextRect.top := ButtonRect.top + ButtonHeight DIV 2 - TextHeight DIV 2 - TextHeight DIV 4;
  401. TextRect.left := ButtonRect.right + 1;
  402. TextPoint.h := TextRect.left + TextHeight DIV 4;
  403. TextRect.bottom := TextRect.top + TextHeight + TextHeight DIV 2;
  404. TextPoint.v := TextRect.bottom - TextHeight DIV 4;
  405. END;
  406. bottomToTop, topToBottom : 
  407. BEGIN
  408. TextRect.top := ButtonRect.bottom + 2;
  409. TextPoint.h := ButtonRect.left + ButtonWidth DIV 2;
  410. TextRect.left := TextPoint.h - TextWidth DIV 2 - TextHeight DIV 4;
  411. TextRect.bottom := TextRect.top + TextHeight + TextHeight DIV 2 - 4;
  412. TextPoint.v := TextRect.bottom - TextHeight DIV 4;
  413. END;
  414. END;
  415. TextRect.right := TextRect.left + TextWidth + TextHeight DIV 2;
  416. END;{end setting up ShowValue stuff}
  417.  
  418. oldspot := spot;
  419. dummy := SectRect(ViewRect, DrawRect, DrawRect);
  420. PaintRect(DrawRect);
  421. dummy := SectRect(ViewRect, BlankRect, BlankRect);
  422. EraseRect(BlankRect);
  423. DrawRect := ViewRect;{now will be used for the redrawing}
  424. InsetRect(ButtonRect, -10, -10);
  425. IF InitialValue > -32767 THEN
  426. BEGIN{Display forced starting value}
  427. CurrentValue := InitialValue;
  428. DisplayValue;
  429. END
  430. ELSE
  431. BEGIN
  432. ComputeValue;{Display first real value if requested}
  433. REPEAT
  434. GetMouse(spot);
  435. InRect := PtInRect(spot, ButtonRect) AND Button;
  436. IF InRect THEN
  437. BEGIN
  438. newLoc := TRUE;{guilty unless proven innocent}
  439. CASE direction OF
  440.  
  441. leftToRight, rightToLeft : 
  442. BEGIN
  443. IF spot.h = oldspot.h THEN{no horizontal movement; don't redraw at all}
  444. newLoc := FALSE
  445. ELSE
  446. BEGIN
  447. IF spot.h > oldspot.h THEN{moving right}
  448. BEGIN
  449. DrawRect.right := spot.h;
  450. DrawRect.left := oldspot.h;
  451. END
  452. ELSE{moving left}
  453. BEGIN
  454. DrawRect.left := spot.h;
  455. DrawRect.right := oldspot.h;
  456. END;
  457. END;{end new horizontal loc}
  458. DrawRect.top := ViewRect.top;{restore top and bottom in case SectRect wiped them out with empty rect}
  459. DrawRect.bottom := ViewRect.bottom;
  460. END;{end horizontal case}
  461.  
  462. bottomToTop, topToBottom : 
  463. BEGIN
  464. IF spot.v = oldspot.v THEN{no vertical movement; don't redraw at all}
  465. newLoc := FALSE
  466. ELSE
  467. BEGIN
  468. IF spot.v > oldspot.v THEN{moving down}
  469. BEGIN
  470. DrawRect.bottom := spot.v;
  471. DrawRect.top := oldspot.v;
  472. END
  473. ELSE{moving up}
  474. BEGIN
  475. DrawRect.top := spot.v;
  476. DrawRect.bottom := oldspot.v;
  477. END;
  478. END;{end new vertical loc}
  479. DrawRect.left := ViewRect.left;{restore left and right in case SectRect wiped them out with empty rect}
  480. DrawRect.right := ViewRect.right;
  481. END;{end vertical case}
  482. END;{case block}
  483.  
  484. dummy := SectRect(ViewRect, DrawRect, DrawRect);
  485. IF newLoc THEN{Redraw if necessary}
  486. BEGIN
  487. InvertRect(DrawRect);
  488. IF ShowValue THEN
  489. ComputeValue;{Display current value if requested}
  490. END;
  491. oldspot := spot;{today becomes yesterday}
  492. END;{end InRect}
  493.  
  494. UNTIL NOT Button;{loop until mouseUp}
  495. ComputeValue;{Put result in "the Result" even if they don't want it displayed}
  496. END;{end of event loop for real values}
  497.  
  498. str := NumToStr(CurrentValue);
  499. paramPtr^.returnValue := PasToZero(str);
  500. END;{end BarButton}
  501.  
  502. END.
  503.  
  504. -- part contents for card part 2
  505. ----- text -----
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513. sdsdfsdfsdsfsdf
  514.  
  515. -- part contents for background part 5
  516. ----- text -----
  517. This XCMD was written more as an experiment than anything else.
  518. If you would like your own custom version, and don't feel like writing it yourself, give me a call.  There are many simple tasks that Hypercard cannot do well, or quickly, or at all.  But XCMD's and XFCN's can avoid most of these deficencies.
  519.  
  520. Infosynthesis
  521. 2960 Ferry Street
  522. Eugene, OR 97405
  523. (503) 344-3322
  524. {BarButton adjusts the size of the bar contained within rect passed in "It", and using the }
  525. {options in the first 4 parameters.}
  526. UNIT Main;
  527.  
  528. INTERFACE
  529.  
  530. USES
  531. HyperXCMD;
  532.  
  533. PROCEDURE Main (ParamPtr : XCmdPtr);
  534.  
  535. IMPLEMENTATION
  536.  
  537. {-------------------------------------------------------------------------------}
  538. PROCEDURE BarButton (ParamPtr : XCmdPtr);
  539. FORWARD;
  540.  
  541. PROCEDURE Main;
  542. BEGIN
  543. BarButton(ParamPtr);
  544. END;
  545.  
  546. PROCEDURE BarButton;
  547.  
  548. CONST
  549. leftToRight = 1;
  550. rightToLeft = 2;
  551. bottomToTop = 3;
  552. topToBottom = 4;
  553.  
  554. VAR
  555. str : Str255;
  556. ButtonRect, DrawRect, BlankRect, ViewRect, TextRect : rect;
  557. InRect, newLoc, dummy, ShowValue, SuppressDisplay : boolean;
  558. spot, oldspot, TextPoint : point;
  559. direction, maximumValue, minimumValue, CurrentValue, InitialValue : integer;
  560. theInfo : FontInfo;
  561. TextHeight, TextWidth, ButtonHeight, ButtonWidth : integer;
  562. proportion : real;
  563.  
  564. {-------------------------------------------------------------------------------}
  565. PROCEDURE DoJsr (addr : ProcPtr);
  566. INLINE
  567. $205F, $4E90;
  568. { Jump subroutine to a procedure.   Pop address into A0, JSR (A0) }
  569.  
  570. {-------------------------------------------------------------------------------}
  571. PROCEDURE ZeroToPas (zeroStr : Ptr;
  572. VAR pasStr : Str255);
  573. {Fill the Pascal string with the contents of the zero-terminated}
  574. {   string.  You create the Pascal string and pass it in as a VAR }
  575. {   parameter.  Useful for converting the arguments of any XCMD to }
  576. {   Pascal strings.}
  577. BEGIN
  578. WITH paramPtr^ DO
  579. BEGIN
  580. inArgs[1] := ORD(zeroStr);
  581. inArgs[2] := ORD(@pasStr);
  582. request := xreqZeroToPas;
  583. DoJsr(entryPoint);
  584. END;
  585. END;
  586.  
  587. {-------------------------------------------------------------------------------}
  588. FUNCTION StrToNum (str : Str31) : LongInt;
  589. {  Convert a string of ASCII decimal digits to a signed long integer.}
  590. {   Negative sign is allowed.  }
  591. BEGIN
  592. WITH paramPtr^ DO
  593. BEGIN
  594. inArgs[1] := ORD(@str);
  595. request := xreqStrToNum;
  596. DoJsr(entryPoint);
  597. StrToNum := outArgs[1];
  598. END;
  599. END;
  600.  
  601. {-------------------------------------------------------------------------------}
  602. FUNCTION PasToZero (str : Str255) : Handle;
  603. {  Convert a Pascal string to a zero-terminated string.  Returns a handle}
  604. {   to a new zero-terminated string.  The caller must dispose the handle. }
  605. BEGIN
  606. WITH paramPtr^ DO
  607. BEGIN
  608. inArgs[1] := ORD(@str);
  609. request := xreqPasToZero;
  610. DoJsr(entryPoint);
  611. PasToZero := Handle(outArgs[1]);
  612. END;
  613. END;
  614.  
  615. {-------------------------------------------------------------------------------}
  616. FUNCTION EvalExpr (expr : Str255) : Handle;
  617. {  Evaluate a HyperCard expression and return the answer.  The answer is}
  618. {   a handle to a zero-terminated string. }
  619. BEGIN
  620. WITH paramPtr^ DO
  621. BEGIN
  622. inArgs[1] := ORD(@expr);
  623. request := xreqEvalExpr;
  624. DoJsr(entryPoint);
  625. EvalExpr := Handle(outArgs[1]);
  626. END;
  627. END;
  628.  
  629. {-------------------------------------------------------------------------------}
  630. FUNCTION NumToStr (num : LongInt) : Str31;
  631. {  Convert a signed long integer to a Pascal string.  }
  632. VAR
  633. str : Str31;
  634. BEGIN
  635. WITH paramPtr^ DO
  636. BEGIN
  637. inArgs[1] := num;
  638. inArgs[2] := ORD(@str);
  639. request := xreqNumToStr;
  640. DoJsr(entryPoint);
  641. NumToStr := str;
  642. END;
  643. END;
  644.  
  645. {-------------------------------------------------------------------------------}
  646. FUNCTION IntExpr (theString : str255) : integer;
  647. TYPE
  648. Ptr31 = ^str31;
  649. Hand31 = ^Ptr31;
  650.  
  651. VAR
  652. tempHand : handle;
  653. ShortStr : str31;
  654. ShortPtr : Ptr31;
  655. ShortHand : Hand31;
  656. NumLong : longint;
  657. LongStr : str255;
  658.  
  659. BEGIN
  660. tempHand := EvalExpr(theString);
  661. ZeroToPas(tempHand^, LongStr);
  662. ShortStr := LongStr;
  663. NumLong := StrToNum(ShortStr);
  664. IntExpr := loword(NumLong);
  665. DisposHandle(tempHand);
  666. END;
  667.  
  668. {-------------------------------------------------------------------------------}
  669. FUNCTION DePad (str : str255) : str255;
  670. VAR
  671. c : integer;
  672.  
  673. BEGIN
  674. FOR c := length(str) DOWNTO 1 DO
  675. IF ord(str[c]) = 32 THEN
  676. Delete(str, c, 1);
  677. DePad := str;
  678. END;
  679.  
  680. {-------------------------------------------------------------------------------}
  681. PROCEDURE DisplayValue;
  682. BEGIN
  683. IF ShowValue THEN
  684. BEGIN
  685. TextFont(systemfont);{Chicago}
  686. TextSize(12);
  687. str := Depad(StringOf(CurrentValue));
  688. CASE direction OF
  689. leftToRight, rightToLeft : 
  690. MoveTo(TextPoint.h, TextPoint.v);
  691. bottomToTop, topToBottom : 
  692. MoveTo(TextPoint.h - StringWidth(str) DIV 2, TextPoint.v);
  693. END;
  694. EraseRect(TextRect);
  695. DrawString(str);
  696. END;
  697. END;{DisplayValue}
  698.  
  699. {-------------------------------------------------------------------------------}
  700. PROCEDURE ComputeValue;
  701.  
  702. BEGIN
  703. WITH ViewRect DO
  704. CASE direction OF
  705. leftToRight : 
  706. proportion := (oldspot.h - left) * 1.0 / (right - left);
  707. rightToLeft : 
  708. proportion := (right - oldspot.h) * 1.0 / (right - left);
  709. bottomToTop : 
  710. proportion := (bottom - oldspot.v) * 1.0 / (bottom - top);
  711. topToBottom : 
  712. proportion := (oldspot.v - top) * 1.0 / (bottom - top);
  713. END;
  714.  
  715. IF proportion < 0 THEN
  716. proportion := 0;
  717. IF proportion > 1.0 THEN
  718. proportion := 1.0;
  719.  
  720. CurrentValue := round(proportion * (maximumValue - minimumValue) + minimumValue);
  721. DisplayValue;
  722. END;{ComputeValue}
  723.  
  724. {-------------------------------------------------------------------------------}
  725. BEGIN
  726. ButtonRect.left := IntExpr('item 1 of It');
  727. ButtonRect.top := IntExpr('item 2 of It');
  728. ButtonRect.right := IntExpr('item 3 of It');
  729. ButtonRect.bottom := IntExpr('item 4 of It');
  730. ButtonHeight := ButtonRect.bottom - ButtonRect.top;
  731. ButtonWidth := ButtonRect.right - ButtonRect.left;
  732.  
  733. ViewRect := ButtonRect;
  734. InsetRect(ViewRect, 1, 1);
  735. DrawRect := ViewRect;
  736. BlankRect := DrawRect;
  737.  
  738. WITH ButtonRect DO
  739. IF right - left > bottom - top THEN
  740. direction := leftToRight
  741. ELSE
  742. direction := bottomToTop;
  743. maximumValue := 100;
  744. minimumValue := 0;
  745. ShowValue := FALSE;
  746. SuppressDisplay := FALSE;
  747. InitialValue := -32767;{Hopefully no one will actually use that value!}
  748.  
  749. WITH ParamPtr^ DO
  750. BEGIN
  751. IF paramCount > 0 THEN
  752. BEGIN
  753. ZeroToPas(params[1]^, str);
  754. direction := StrToNum(str);
  755. IF (direction >= -4) AND (direction <= -1) THEN
  756. BEGIN
  757. SuppressDisplay := TRUE;
  758. direction := -direction;
  759. END;
  760. IF (direction < 1) OR (direction > 4) THEN
  761. direction := leftToRight;
  762. IF paramCount > 1 THEN
  763. BEGIN
  764. ZeroToPas(params[2]^, str);
  765. maximumValue := StrToNum(str);
  766. ShowValue := TRUE;
  767. IF paramCount > 2 THEN
  768. BEGIN
  769. ZeroToPas(params[3]^, str);
  770. minimumValue := StrToNum(str);
  771. IF minimumValue >= maximumValue THEN
  772. minimumValue := maximumValue + 10;
  773. IF paramCount > 3 THEN
  774. BEGIN
  775. ZeroToPas(params[4]^, str);
  776. InitialValue := StrToNum(str);
  777. END;{end of reading initial value}
  778. END;{end of reading third parameter}
  779. END;{end of reading second parameter}
  780. END;{end of reading first parameter}
  781. END;{with ParamPtr^}
  782. IF SuppressDisplay THEN
  783. ShowValue := FALSE;
  784.  
  785. IF InitialValue = -32767 THEN
  786. GetMouse(spot){Get current loc of mouse}
  787. ELSE
  788. BEGIN{force initial value of bar without mousedown}
  789. proportion := (InitialValue - minimumValue) * 1.0 / (maximumValue - minimumValue);
  790. IF proportion < 0 THEN
  791. proportion := 0;
  792. IF proportion > 1.0 THEN
  793. proportion := 1.0;
  794. CASE direction OF
  795. leftToRight : 
  796. spot.h := round(DrawRect.left + proportion * ButtonWidth);
  797. rightToLeft : 
  798. spot.h := round(DrawRect.right - proportion * ButtonWidth);
  799. bottomToTop : 
  800. spot.v := round(DrawRect.bottom - proportion * ButtonHeight);
  801. topToBottom : 
  802. spot.v := round(DrawRect.top + proportion * ButtonHeight);
  803. END;{end of case direction}
  804. END;{end of forcing initial value}
  805.  
  806. CASE direction OF
  807. leftToRight : 
  808. BEGIN
  809. DrawRect.right := spot.h;
  810. BlankRect.left := spot.h;
  811. END;
  812. rightToLeft : 
  813. BEGIN
  814. DrawRect.left := spot.h;
  815. BlankRect.right := spot.h;
  816. END;
  817. bottomToTop : 
  818. BEGIN
  819. DrawRect.top := spot.v;
  820. BlankRect.bottom := spot.v;
  821. END;
  822. topToBottom : 
  823. BEGIN
  824. DrawRect.bottom := spot.v;
  825. BlankRect.top := spot.v;
  826. END;
  827. END;{end of case direction}
  828.  
  829. IF ShowValue THEN{Set up stuff for ShowValue}
  830. BEGIN
  831. IF StringWidth(DePad(StringOf(maximumValue))) >= StringWidth(DePad(StringOf(minimumValue))) THEN
  832. TextWidth := StringWidth(DePad(StringOf(maximumValue)))
  833. ELSE
  834. TextWidth := StringWidth(DePad(StringOf(minimumValue)));
  835.  
  836. GetFontInfo(theInfo);
  837. TextHeight := theInfo.ascent;{numbers don't have descenders}
  838.  
  839. CASE direction OF
  840. leftToRight, rightToLeft : 
  841. BEGIN
  842. TextRect.top := ButtonRect.top + ButtonHeight DIV 2 - TextHeight DIV 2 - TextHeight DIV 4;
  843. TextRect.left := ButtonRect.right + 1;
  844. TextPoint.h := TextRect.left + TextHeight DIV 4;
  845. TextRect.bottom := TextRect.top + TextHeight + TextHeight DIV 2;
  846. TextPoint.v := TextRect.bottom - TextHeight DIV 4;
  847. END;
  848. bottomToTop, topToBottom : 
  849. BEGIN
  850. TextRect.top := ButtonRect.bottom + 2;
  851. TextPoint.h := ButtonRect.left + ButtonWidth DIV 2;
  852. TextRect.left := TextPoint.h - TextWidth DIV 2 - TextHeight DIV 4;
  853. TextRect.bottom := TextRect.top + TextHeight + TextHeight DIV 2 - 4;
  854. TextPoint.v := TextRect.bottom - TextHeight DIV 4;
  855. END;
  856. END;
  857. TextRect.right := TextRect.left + TextWidth + TextHeight DIV 2;
  858. END;{end setting up ShowValue stuff}
  859.  
  860. oldspot := spot;
  861. dummy := SectRect(ViewRect, DrawRect, DrawRect);
  862. PaintRect(DrawRect);
  863. dummy := SectRect(ViewRect, BlankRect, BlankRect);
  864. EraseRect(BlankRect);
  865. DrawRect := ViewRect;{now will be used for the redrawing}
  866. InsetRect(ButtonRect, -10, -10);
  867. IF InitialValue > -32767 THEN
  868. BEGIN{Display forced starting value}
  869. CurrentValue := InitialValue;
  870. DisplayValue;
  871. END
  872. ELSE
  873. BEGIN
  874. ComputeValue;{Display first real value if requested}
  875. REPEAT
  876. GetMouse(spot);
  877. InRect := PtInRect(spot, ButtonRect) AND Button;
  878. IF InRect THEN
  879. BEGIN
  880. newLoc := TRUE;{guilty unless proven innocent}
  881. CASE direction OF
  882.  
  883. leftToRight, rightToLeft : 
  884. BEGIN
  885. IF spot.h = oldspot.h THEN{no horizontal movement; don't redraw at all}
  886. newLoc := FALSE
  887. ELSE
  888. BEGIN
  889. IF spot.h > oldspot.h THEN{moving right}
  890. BEGIN
  891. DrawRect.right := spot.h;
  892. DrawRect.left := oldspot.h;
  893. END
  894. ELSE{moving left}
  895. BEGIN
  896. DrawRect.left := spot.h;
  897. DrawRect.right := oldspot.h;
  898. END;
  899. END;{end new horizontal loc}
  900. DrawRect.top := ViewRect.top;{restore top and bottom in case SectRect wiped them out with empty rect}
  901. DrawRect.bottom := ViewRect.bottom;
  902. END;{end horizontal case}
  903.  
  904. bottomToTop, topToBottom : 
  905. BEGIN
  906. IF spot.v = oldspot.v THEN{no vertical movement; don't redraw at all}
  907. newLoc := FALSE
  908. ELSE
  909. BEGIN
  910. IF spot.v > oldspot.v THEN{moving down}
  911. BEGIN
  912. DrawRect.bottom := spot.v;
  913. DrawRect.top := oldspot.v;
  914. END
  915. ELSE{moving up}
  916. BEGIN
  917. DrawRect.top := spot.v;
  918. DrawRect.bottom := oldspot.v;
  919. END;
  920. END;{end new vertical loc}
  921. DrawRect.left := ViewRect.left;{restore left and right in case SectRect wiped them out with empty rect}
  922. DrawRect.right := ViewRect.right;
  923. END;{end vertical case}
  924. END;{case block}
  925.  
  926. dummy := SectRect(ViewRect, DrawRect, DrawRect);
  927. IF newLoc THEN{Redraw if necessary}
  928. BEGIN
  929. InvertRect(DrawRect);
  930. IF ShowValue THEN
  931. ComputeValue;{Display current value if requested}
  932. END;
  933. oldspot := spot;{today becomes yesterday}
  934. END;{end InRect}
  935.  
  936. UNTIL NOT Button;{loop until mouseUp}
  937. ComputeValue;{Put result in "the Result" even if they don't want it displayed}
  938. END;{end of event loop for real values}
  939.  
  940. str := NumToStr(CurrentValue);
  941. paramPtr^.returnValue := PasToZero(str);
  942. END;{end BarButton}
  943.  
  944. END.
  945.  
  946. -- part contents for card part 3
  947. ----- text -----
  948. {BarButton adjusts the size of the bar contained in rect in variable "It",}
  949. {and according to options in first 4 parameters.}
  950.  
  951. unit Main;
  952.  
  953. interface
  954.  type
  955.   XCmdPtr = ^XCmdBlock;
  956.   XCmdBlock = record
  957.     paramCount : INTEGER;
  958.     params : array[1..16] of Handle;
  959.     returnValue : Handle;
  960.     passFlag : BOOLEAN;
  961.  
  962.     entryPoint : ProcPtr;    { to call back to HyperCard }
  963.     request : INTEGER;
  964.     result : INTEGER;
  965.     inArgs : array[1..8] of LongInt;
  966.     outArgs : array[1..4] of LongInt;
  967.    end;
  968.  
  969.  procedure Main (ParamPtr : XCmdPtr);
  970.  
  971.  
  972. implementation
  973.  
  974. {-------------------------------------------------------------------------------}
  975.  procedure BarButton (ParamPtr : XCmdPtr);
  976.  FORWARD;
  977.  
  978.  procedure Main;
  979.  begin
  980.   BarButton(ParamPtr);
  981.  end;
  982.  
  983.  procedure BarButton;
  984.  
  985.   const
  986.  { request codes for sending commands back to Hypercard}
  987.    xreqEvalExpr = 2;
  988.    xreqPasToZero = 7;
  989.    xreqZeroToPas = 8;
  990.    xreqStrToNum = 10;
  991.    xreqNumToStr = 14;
  992.  
  993. { four directions for the bar, as specified in first parameter }
  994.    leftToRight = 1;
  995.    rightToLeft = 2;
  996.    bottomToTop = 3;
  997.    topToBottom = 4;
  998.  
  999.   type
  1000.    Str19 = string[19];
  1001.    Str31 = string[31];
  1002.  
  1003.   var
  1004.    str : Str255;
  1005.    ButtonRect, DrawRect, BlankRect, ViewRect, TextRect : rect;
  1006.    InRect, newLoc, dummy, ShowValue, SuppressDisplay : boolean;
  1007.    spot, oldspot, TextPoint : point;
  1008.    direction, maximumValue, minimumValue, CurrentValue, InitialValue : integer;
  1009.    theInfo : FontInfo;
  1010.    TextHeight, TextWidth, ButtonHeight, ButtonWidth : integer;
  1011.    proportion : real;
  1012.  
  1013. {-------------------------------------------------------------------------------}
  1014. { Jump subroutine to a procedure.   Pop address into A0, JSR (A0) }
  1015.   procedure DoJsr (addr : ProcPtr);
  1016.   inline
  1017.    $205F, $4E90;
  1018.  
  1019. {-------------------------------------------------------------------------------}
  1020. {Fill the Pascal string with the contents of the zero-terminated}
  1021. {   string.  You create the Pascal string and pass it in as a VAR }
  1022. {   parameter.  Useful for converting the arguments of any XCMD to }
  1023. {   Pascal strings.}
  1024.  
  1025.   procedure ZeroToPas (zeroStr : Ptr;
  1026.      var pasStr : Str255);
  1027.   begin
  1028.    with paramPtr^ do
  1029.     begin
  1030.      inArgs[1] := ORD(zeroStr);
  1031.      inArgs[2] := ORD(@pasStr);
  1032.      request := xreqZeroToPas;
  1033.      DoJsr(entryPoint);
  1034.     end;
  1035.   end;
  1036.  
  1037. {-------------------------------------------------------------------------------}
  1038. {  Convert a string of ASCII decimal digits to a signed long integer.}
  1039. {   Negative sign is allowed.  }
  1040.  
  1041.   function StrToNum (str : Str31) : LongInt;
  1042.   begin
  1043.    with paramPtr^ do
  1044.     begin
  1045.      inArgs[1] := ORD(@str);
  1046.      request := xreqStrToNum;
  1047.      DoJsr(entryPoint);
  1048.      StrToNum := outArgs[1];
  1049.     end;
  1050.   end;
  1051.  
  1052. {-------------------------------------------------------------------------------}
  1053. {  Convert a Pascal string to a zero-terminated string.  Returns a handle}
  1054. {   to a new zero-terminated string.  The caller must dispose the handle. }
  1055.  
  1056.   function PasToZero (str : Str255) : Handle;
  1057.   begin
  1058.    with paramPtr^ do
  1059.     begin
  1060.      inArgs[1] := ORD(@str);
  1061.      request := xreqPasToZero;
  1062.      DoJsr(entryPoint);
  1063.      PasToZero := Handle(outArgs[1]);
  1064.     end;
  1065.   end;
  1066.  
  1067. {-------------------------------------------------------------------------------}
  1068. {  Evaluate a HyperCard expression and return the answer.  The answer is}
  1069. {   a handle to a zero-terminated string. }
  1070.  
  1071.   function EvalExpr (expr : Str255) : Handle;
  1072.   begin
  1073.    with paramPtr^ do
  1074.     begin
  1075.      inArgs[1] := ORD(@expr);
  1076.      request := xreqEvalExpr;
  1077.      DoJsr(entryPoint);
  1078.      EvalExpr := Handle(outArgs[1]);
  1079.     end;
  1080.   end;
  1081.  
  1082. {-------------------------------------------------------------------------------}
  1083. {  Convert a signed long integer to a Pascal string.  }
  1084.  
  1085.   function NumToStr (num : LongInt) : Str31;
  1086.    var
  1087.     str : Str31;
  1088.   begin
  1089.    with paramPtr^ do
  1090.     begin
  1091.      inArgs[1] := num;
  1092.      inArgs[2] := ORD(@str);
  1093.      request := xreqNumToStr;
  1094.      DoJsr(entryPoint);
  1095.      NumToStr := str;
  1096.     end;
  1097.   end;
  1098.  
  1099. {-------------------------------------------------------------------------------}
  1100. { Convert parameter string to 2-byte integer }
  1101.  
  1102.   function IntExpr (theString : str255) : integer;
  1103.    type
  1104.     Ptr31 = ^str31;
  1105.     Hand31 = ^Ptr31;
  1106.  
  1107.    var
  1108.     tempHand : handle;
  1109.     ShortStr : str31;
  1110.     NumLong : longint;
  1111.     LongStr : str255;
  1112.  
  1113.   begin
  1114.    tempHand := EvalExpr(theString);
  1115.    ZeroToPas(tempHand^, LongStr);
  1116.    ShortStr := LongStr;
  1117.    NumLong := StrToNum(ShortStr);
  1118.    IntExpr := loword(NumLong);
  1119.    DisposHandle(tempHand);
  1120.   end;
  1121.  
  1122. {-------------------------------------------------------------------------------}
  1123. {Remove spaces from string returned by Pascal's StringOf function}
  1124.  
  1125.   function DePad (str : str255) : str255;
  1126.    var
  1127.     c : integer;
  1128.  
  1129.   begin
  1130.    for c := length(str) downto 1 do
  1131.     if ord(str[c]) = 32 then
  1132.      Delete(str, c, 1);
  1133.    DePad := str;
  1134.   end;
  1135.  
  1136. {-------------------------------------------------------------------------------}
  1137. {Display the integer value of the bar within TextRect}
  1138.  
  1139.   procedure DisplayValue;
  1140.   begin
  1141.    if ShowValue then
  1142.     begin
  1143.      TextFont(systemfont);{Chicago}
  1144.      TextSize(12);
  1145.      str := Depad(StringOf(CurrentValue));
  1146.      case direction of
  1147.      leftToRight, rightToLeft : 
  1148.      MoveTo(TextPoint.h, TextPoint.v);
  1149.      bottomToTop, topToBottom : 
  1150.      MoveTo(TextPoint.h - StringWidth(str) div 2, TextPoint.v);
  1151.      end;
  1152.      EraseRect(TextRect);
  1153.      DrawString(str);
  1154.     end;
  1155.   end;{DisplayValue}
  1156.  
  1157. {-------------------------------------------------------------------------------}
  1158. {Compute the current value of the current position of the Bar}
  1159.  
  1160.   procedure ComputeValue;
  1161.  
  1162.   begin
  1163.    with ViewRect do
  1164.     case direction of
  1165.      leftToRight : 
  1166.      proportion := (oldspot.h - left) * 1.0 / (right - left);
  1167.      rightToLeft : 
  1168.      proportion := (right - oldspot.h) * 1.0 / (right - left);
  1169.      bottomToTop : 
  1170.      proportion := (bottom - oldspot.v) * 1.0 / (bottom - top);
  1171.      topToBottom : 
  1172.      proportion := (oldspot.v - top) * 1.0 / (bottom - top);
  1173.     end;
  1174.  
  1175.    if proportion < 0 then
  1176.     proportion := 0;
  1177.    if proportion > 1.0 then
  1178.     proportion := 1.0;
  1179.  
  1180.    CurrentValue := round(proportion * (maximumValue - minimumValue) + minimumValue);
  1181.    DisplayValue;
  1182.   end;{ComputeValue}
  1183.  
  1184. {-------------------------------------------------------------------------------}
  1185. {This is the main BarButton routine.  First look up the rect passed in the first}
  1186. {four items of Hypercard's "It" variable.  }
  1187.  
  1188.  begin
  1189.   ButtonRect.left := IntExpr('item 1 of It');
  1190.   ButtonRect.top := IntExpr('item 2 of It');
  1191.   ButtonRect.right := IntExpr('item 3 of It');
  1192.   ButtonRect.bottom := IntExpr('item 4 of It');
  1193.   ButtonHeight := ButtonRect.bottom - ButtonRect.top;
  1194.   ButtonWidth := ButtonRect.right - ButtonRect.left;
  1195.  
  1196. {Set up two more rects; one will be filled with black, the other erased.}
  1197.   ViewRect := ButtonRect;
  1198.   InsetRect(ViewRect, 1, 1);
  1199.   DrawRect := ViewRect;
  1200.   BlankRect := DrawRect;
  1201.  
  1202.   with ButtonRect do
  1203.    if right - left > bottom - top then
  1204.     direction := leftToRight
  1205.    else
  1206.     direction := bottomToTop;
  1207.  
  1208. {Set the default values, and read each parameter for new values.}
  1209.   maximumValue := 100;
  1210.   minimumValue := 0;
  1211.   ShowValue := FALSE;
  1212.   SuppressDisplay := FALSE;
  1213.   InitialValue := -32767;{Hopefully no one will actually use that value!}
  1214.  
  1215.   with ParamPtr^ do
  1216.    begin
  1217.     if paramCount > 0 then
  1218.      begin
  1219.      ZeroToPas(params[1]^, str);
  1220.      direction := StrToNum(str);
  1221.      if (direction >= -4) and (direction <= -1) then
  1222.      begin
  1223.      SuppressDisplay := TRUE;
  1224.      direction := -direction;
  1225.      end;
  1226.      if (direction < 1) or (direction > 4) then
  1227.      direction := leftToRight;
  1228.      if paramCount > 1 then
  1229.      begin
  1230.      ZeroToPas(params[2]^, str);
  1231.      maximumValue := StrToNum(str);
  1232.      ShowValue := TRUE;
  1233.      if paramCount > 2 then
  1234.      begin
  1235.      ZeroToPas(params[3]^, str);
  1236.      minimumValue := StrToNum(str);
  1237.      if minimumValue >= maximumValue then
  1238.      minimumValue := maximumValue + 10;
  1239.      if paramCount > 3 then
  1240.      begin
  1241.      ZeroToPas(params[4]^, str);
  1242.      InitialValue := StrToNum(str);
  1243.      end;{end of reading fourth parameter = initial value}
  1244.      end;{end of reading third parameter = minimum value}
  1245.      end;{end of reading second parameter = maximum value}
  1246.      end;{end of reading first parameter = direction of bar}
  1247.    end;{with ParamPtr^}
  1248.   if SuppressDisplay then{if first parameter < 0, suppress display of numeric value}
  1249.    ShowValue := FALSE;
  1250.  
  1251.   if InitialValue = -32767 then
  1252.    GetMouse(spot){Get current loc of mouse if no initial value specified}
  1253.   else
  1254.    begin{force initial value of bar without mousedown}
  1255.     proportion := (InitialValue - minimumValue) * 1.0 / (maximumValue - minimumValue);
  1256.     if proportion < 0 then
  1257.      proportion := 0;
  1258.     if proportion > 1.0 then
  1259.      proportion := 1.0;
  1260.     case direction of
  1261.      leftToRight : 
  1262.      spot.h := round(DrawRect.left + proportion * ButtonWidth);
  1263.      rightToLeft : 
  1264.      spot.h := round(DrawRect.right - proportion * ButtonWidth);
  1265.      bottomToTop : 
  1266.      spot.v := round(DrawRect.bottom - proportion * ButtonHeight);
  1267.      topToBottom : 
  1268.      spot.v := round(DrawRect.top + proportion * ButtonHeight);
  1269.     end;{end of case direction}
  1270.    end;{end of forcing initial value}
  1271.  
  1272.   case direction of{compute size of bar regardless}
  1273.    leftToRight : 
  1274.     begin
  1275.      DrawRect.right := spot.h;
  1276.      BlankRect.left := spot.h;
  1277.     end;
  1278.    rightToLeft : 
  1279.     begin
  1280.      DrawRect.left := spot.h;
  1281.      BlankRect.right := spot.h;
  1282.     end;
  1283.    bottomToTop : 
  1284.     begin
  1285.      DrawRect.top := spot.v;
  1286.      BlankRect.bottom := spot.v;
  1287.     end;
  1288.    topToBottom : 
  1289.     begin
  1290.      DrawRect.bottom := spot.v;
  1291.      BlankRect.top := spot.v;
  1292.     end;
  1293.   end;{end of case direction}
  1294.  
  1295.   if ShowValue then{Set up stuff for ShowValue}
  1296.    begin
  1297.     if StringWidth(DePad(StringOf(maximumValue))) >= StringWidth(DePad(StringOf(minimumValue))) then
  1298.      TextWidth := StringWidth(DePad(StringOf(maximumValue)))
  1299.     else
  1300.      TextWidth := StringWidth(DePad(StringOf(minimumValue)));
  1301.  
  1302.     GetFontInfo(theInfo);
  1303.     TextHeight := theInfo.ascent;{numbers don't have descenders}
  1304.  
  1305.     case direction of
  1306.      leftToRight, rightToLeft : 
  1307.      begin
  1308.      TextRect.top := ButtonRect.top + ButtonHeight div 2 - TextHeight div 2 - TextHeight div 4 + 2;
  1309.      TextRect.left := ButtonRect.right + 1;
  1310.      TextPoint.h := TextRect.left + TextHeight div 4;
  1311.      TextRect.bottom := TextRect.top + TextHeight + TextHeight div 2 - 2;
  1312.      TextPoint.v := TextRect.bottom - TextHeight div 4;
  1313.      end;
  1314.      bottomToTop, topToBottom : 
  1315.      begin
  1316.      TextRect.top := ButtonRect.bottom + 2;
  1317.      TextPoint.h := ButtonRect.left + ButtonWidth div 2;
  1318.      TextRect.left := TextPoint.h - TextWidth div 2 - TextHeight div 4;
  1319.      TextRect.bottom := TextRect.top + TextHeight + TextHeight div 2 - 4;
  1320.      TextPoint.v := TextRect.bottom - TextHeight div 4;
  1321.      end;
  1322.     end;
  1323.     TextRect.right := TextRect.left + TextWidth + TextHeight div 2;
  1324.    end;{end setting up ShowValue stuff}
  1325.  
  1326.   oldspot := spot;
  1327.   dummy := SectRect(ViewRect, DrawRect, DrawRect);
  1328.   PaintRect(DrawRect);
  1329.   dummy := SectRect(ViewRect, BlankRect, BlankRect);
  1330.   EraseRect(BlankRect);
  1331.   DrawRect := ViewRect;{now will be used for the redrawing}
  1332.   InsetRect(ButtonRect, -10, -10);{allow user to miss rect by 10 pixels}
  1333.   if InitialValue > -32767 then{force initial value}
  1334.    begin{Display forced starting value}
  1335.     CurrentValue := InitialValue;
  1336.     DisplayValue;
  1337.    end
  1338.   else
  1339.    begin
  1340.     ComputeValue;{Display first real value if requested}
  1341.     repeat
  1342.      GetMouse(spot);{Get current position of mouse}
  1343.      InRect := PtInRect(spot, ButtonRect) and Button;
  1344.      if InRect then
  1345.      begin
  1346.      newLoc := TRUE;{guilty unless proven innocent}
  1347.      case direction of
  1348.  
  1349.      leftToRight, rightToLeft : 
  1350.      begin
  1351.      if spot.h = oldspot.h then{no horizontal movement; don't redraw at all}
  1352.      newLoc := FALSE
  1353.      else
  1354.      begin
  1355.      if spot.h > oldspot.h then{moving right}
  1356.      begin
  1357.      DrawRect.right := spot.h;
  1358.      DrawRect.left := oldspot.h;
  1359.      end
  1360.      else{moving left}
  1361.      begin
  1362.      DrawRect.left := spot.h;
  1363.      DrawRect.right := oldspot.h;
  1364.      end;
  1365.      end;{end new horizontal loc}
  1366.      DrawRect.top := ViewRect.top;{restore top and bottom in case SectRect wiped them out with empty rect}
  1367.      DrawRect.bottom := ViewRect.bottom;
  1368.      end;{end horizontal case}
  1369.  
  1370.      bottomToTop, topToBottom : 
  1371.      begin
  1372.      if spot.v = oldspot.v then{no vertical movement; don't redraw at all}
  1373.      newLoc := FALSE
  1374.      else
  1375.      begin
  1376.      if spot.v > oldspot.v then{moving down}
  1377.      begin
  1378.      DrawRect.bottom := spot.v;
  1379.      DrawRect.top := oldspot.v;
  1380.      end
  1381.      else{moving up}
  1382.      begin
  1383.      DrawRect.top := spot.v;
  1384.      DrawRect.bottom := oldspot.v;
  1385.      end;
  1386.      end;{end new vertical loc}
  1387.      DrawRect.left := ViewRect.left;{restore left and right in case SectRect wiped them out with empty rect}
  1388.      DrawRect.right := ViewRect.right;
  1389.      end;{end vertical case}
  1390.      end;{case block}
  1391.  
  1392.      dummy := SectRect(ViewRect, DrawRect, DrawRect);
  1393.      if newLoc then{Redraw if necessary}
  1394.      begin
  1395.      InvertRect(DrawRect);{Invert only the change in position}
  1396.      if ShowValue then
  1397.      ComputeValue;{Display current value if requested}
  1398.      end;
  1399.      oldspot := spot;{today becomes yesterday}
  1400.      end;{end InRect}
  1401.  
  1402.     until not Button;{loop until mouseUp}
  1403.     ComputeValue;{Put result in "the Result" even if they don't want it displayed}
  1404.    end;{end of event loop for real values}
  1405.  
  1406.   str := NumToStr(CurrentValue);{convert last value to string}
  1407.   paramPtr^.returnValue := PasToZero(str);{put string in "the result"}
  1408.  end;{end BarButton}
  1409.  
  1410. end.
  1411.  
  1412. -- part contents for card part 5
  1413. ----- text -----
  1414. VESTIGIAL CARD: This is the complete text of the Lightspeed Pascal source of the BarButton XCMD.  If you want to recompile with modifications, be sure the files DA PasLib and MacTraps are in the Project, and then "Build and Save As" a Code resource of type 'XCMD'.  Then ResEdit the XCMD into your stack.
  1415.