PageRenderTime 58ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/SN-NG4.1/tk/generic/tkObj.c

https://gitlab.com/OpenSourceMirror/sourcenav
C | 660 lines | 349 code | 73 blank | 238 comment | 58 complexity | acf0bdee13b72ae750dd01586b49c899 MD5 | raw file
  1. /*
  2. * tkObj.c --
  3. *
  4. * This file contains procedures that implement the common Tk object
  5. * types
  6. *
  7. * Copyright (c) 1997 Sun Microsystems, Inc.
  8. *
  9. * See the file "license.terms" for information on usage and redistribution
  10. * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11. *
  12. * RCS: @(#) $Id$
  13. */
  14. #include "tkInt.h"
  15. /*
  16. * The following structure is the internal representation for pixel objects.
  17. */
  18. typedef struct PixelRep {
  19. double value;
  20. int units;
  21. Tk_Window tkwin;
  22. int returnValue;
  23. } PixelRep;
  24. #define SIMPLE_PIXELREP(objPtr) \
  25. ((objPtr)->internalRep.twoPtrValue.ptr2 == 0)
  26. #define SET_SIMPLEPIXEL(objPtr, intval) \
  27. (objPtr)->internalRep.twoPtrValue.ptr1 = (VOID *) (intval); \
  28. (objPtr)->internalRep.twoPtrValue.ptr2 = 0
  29. #define GET_SIMPLEPIXEL(objPtr) \
  30. ((int) (objPtr)->internalRep.twoPtrValue.ptr1)
  31. #define SET_COMPLEXPIXEL(objPtr, repPtr) \
  32. (objPtr)->internalRep.twoPtrValue.ptr1 = 0; \
  33. (objPtr)->internalRep.twoPtrValue.ptr2 = (VOID *) repPtr
  34. #define GET_COMPLEXPIXEL(objPtr) \
  35. ((PixelRep *) (objPtr)->internalRep.twoPtrValue.ptr2)
  36. /*
  37. * The following structure is the internal representation for mm objects.
  38. */
  39. typedef struct MMRep {
  40. double value;
  41. int units;
  42. Tk_Window tkwin;
  43. double returnValue;
  44. } MMRep;
  45. /*
  46. * Prototypes for procedures defined later in this file:
  47. */
  48. static void DupMMInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
  49. Tcl_Obj *copyPtr));
  50. static void DupPixelInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
  51. Tcl_Obj *copyPtr));
  52. static void FreeMMInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
  53. static void FreePixelInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
  54. static int SetMMFromAny _ANSI_ARGS_((Tcl_Interp *interp,
  55. Tcl_Obj *objPtr));
  56. static int SetPixelFromAny _ANSI_ARGS_((Tcl_Interp *interp,
  57. Tcl_Obj *objPtr));
  58. static int SetWindowFromAny _ANSI_ARGS_((Tcl_Interp *interp,
  59. Tcl_Obj *objPtr));
  60. /*
  61. * The following structure defines the implementation of the "pixel"
  62. * Tcl object, used for measuring distances. The pixel object remembers
  63. * its initial display-independant settings.
  64. */
  65. static Tcl_ObjType pixelObjType = {
  66. "pixel", /* name */
  67. FreePixelInternalRep, /* freeIntRepProc */
  68. DupPixelInternalRep, /* dupIntRepProc */
  69. NULL, /* updateStringProc */
  70. SetPixelFromAny /* setFromAnyProc */
  71. };
  72. /*
  73. * The following structure defines the implementation of the "pixel"
  74. * Tcl object, used for measuring distances. The pixel object remembers
  75. * its initial display-independant settings.
  76. */
  77. static Tcl_ObjType mmObjType = {
  78. "mm", /* name */
  79. FreeMMInternalRep, /* freeIntRepProc */
  80. DupMMInternalRep, /* dupIntRepProc */
  81. NULL, /* updateStringProc */
  82. SetMMFromAny /* setFromAnyProc */
  83. };
  84. /*
  85. * The following structure defines the implementation of the "window"
  86. * Tcl object.
  87. */
  88. static Tcl_ObjType windowObjType = {
  89. "window", /* name */
  90. (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
  91. (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
  92. NULL, /* updateStringProc */
  93. SetWindowFromAny /* setFromAnyProc */
  94. };
  95. /*
  96. *----------------------------------------------------------------------
  97. *
  98. * Tk_GetPixelsFromObj --
  99. *
  100. * Attempt to return a pixel value from the Tcl object "objPtr". If the
  101. * object is not already a pixel value, an attempt will be made to convert
  102. * it to one.
  103. *
  104. * Results:
  105. * The return value is a standard Tcl object result. If an error occurs
  106. * during conversion, an error message is left in the interpreter's
  107. * result unless "interp" is NULL.
  108. *
  109. * Side effects:
  110. * If the object is not already a pixel, the conversion will free
  111. * any old internal representation.
  112. *
  113. *----------------------------------------------------------------------
  114. */
  115. int
  116. Tk_GetPixelsFromObj(interp, tkwin, objPtr, intPtr)
  117. Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  118. Tk_Window tkwin;
  119. Tcl_Obj *objPtr; /* The object from which to get pixels. */
  120. int *intPtr; /* Place to store resulting pixels. */
  121. {
  122. int result;
  123. double d;
  124. PixelRep *pixelPtr;
  125. static double bias[] = {
  126. 1.0, 10.0, 25.4, 25.4 / 72.0
  127. };
  128. if (objPtr->typePtr != &pixelObjType) {
  129. result = SetPixelFromAny(interp, objPtr);
  130. if (result != TCL_OK) {
  131. return result;
  132. }
  133. }
  134. if (SIMPLE_PIXELREP(objPtr)) {
  135. *intPtr = GET_SIMPLEPIXEL(objPtr);
  136. } else {
  137. pixelPtr = GET_COMPLEXPIXEL(objPtr);
  138. if (pixelPtr->tkwin != tkwin) {
  139. d = pixelPtr->value;
  140. if (pixelPtr->units >= 0) {
  141. d *= bias[pixelPtr->units] * WidthOfScreen(Tk_Screen(tkwin));
  142. d /= WidthMMOfScreen(Tk_Screen(tkwin));
  143. }
  144. if (d < 0) {
  145. pixelPtr->returnValue = (int) (d - 0.5);
  146. } else {
  147. pixelPtr->returnValue = (int) (d + 0.5);
  148. }
  149. pixelPtr->tkwin = tkwin;
  150. }
  151. *intPtr = pixelPtr->returnValue;
  152. }
  153. return TCL_OK;
  154. }
  155. /*
  156. *----------------------------------------------------------------------
  157. *
  158. * FreePixelInternalRep --
  159. *
  160. * Deallocate the storage associated with a pixel object's internal
  161. * representation.
  162. *
  163. * Results:
  164. * None.
  165. *
  166. * Side effects:
  167. * Frees objPtr's internal representation and sets objPtr's
  168. * internalRep to NULL.
  169. *
  170. *----------------------------------------------------------------------
  171. */
  172. static void
  173. FreePixelInternalRep(objPtr)
  174. Tcl_Obj *objPtr; /* Pixel object with internal rep to free. */
  175. {
  176. PixelRep *pixelPtr;
  177. if (!SIMPLE_PIXELREP(objPtr)) {
  178. pixelPtr = GET_COMPLEXPIXEL(objPtr);
  179. ckfree((char *) pixelPtr);
  180. }
  181. SET_SIMPLEPIXEL(objPtr, 0);
  182. }
  183. /*
  184. *----------------------------------------------------------------------
  185. *
  186. * DupPixelInternalRep --
  187. *
  188. * Initialize the internal representation of a pixel Tcl_Obj to a
  189. * copy of the internal representation of an existing pixel object.
  190. *
  191. * Results:
  192. * None.
  193. *
  194. * Side effects:
  195. * copyPtr's internal rep is set to the pixel corresponding to
  196. * srcPtr's internal rep.
  197. *
  198. *----------------------------------------------------------------------
  199. */
  200. static void
  201. DupPixelInternalRep(srcPtr, copyPtr)
  202. register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
  203. register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
  204. {
  205. PixelRep *oldPtr, *newPtr;
  206. copyPtr->typePtr = srcPtr->typePtr;
  207. if (SIMPLE_PIXELREP(srcPtr)) {
  208. SET_SIMPLEPIXEL(copyPtr, GET_SIMPLEPIXEL(srcPtr));
  209. } else {
  210. oldPtr = GET_COMPLEXPIXEL(srcPtr);
  211. newPtr = (PixelRep *) ckalloc(sizeof(PixelRep));
  212. newPtr->value = oldPtr->value;
  213. newPtr->units = oldPtr->units;
  214. newPtr->tkwin = oldPtr->tkwin;
  215. newPtr->returnValue = oldPtr->returnValue;
  216. SET_COMPLEXPIXEL(copyPtr, newPtr);
  217. }
  218. }
  219. /*
  220. *----------------------------------------------------------------------
  221. *
  222. * SetPixelFromAny --
  223. *
  224. * Attempt to generate a pixel internal form for the Tcl object
  225. * "objPtr".
  226. *
  227. * Results:
  228. * The return value is a standard Tcl result. If an error occurs during
  229. * conversion, an error message is left in the interpreter's result
  230. * unless "interp" is NULL.
  231. *
  232. * Side effects:
  233. * If no error occurs, a pixel representation of the object is
  234. * stored internally and the type of "objPtr" is set to pixel.
  235. *
  236. *----------------------------------------------------------------------
  237. */
  238. static int
  239. SetPixelFromAny(interp, objPtr)
  240. Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  241. Tcl_Obj *objPtr; /* The object to convert. */
  242. {
  243. Tcl_ObjType *typePtr;
  244. char *string, *rest;
  245. double d;
  246. int i, units;
  247. PixelRep *pixelPtr;
  248. string = Tcl_GetStringFromObj(objPtr, NULL);
  249. d = strtod(string, &rest);
  250. if (rest == string) {
  251. /*
  252. * Must copy string before resetting the result in case a caller
  253. * is trying to convert the interpreter's result to pixels.
  254. */
  255. char buf[100];
  256. error:
  257. sprintf(buf, "bad screen distance \"%.50s\"", string);
  258. Tcl_ResetResult(interp);
  259. Tcl_AppendResult(interp, buf, NULL);
  260. return TCL_ERROR;
  261. }
  262. while ((*rest != '\0') && isspace(UCHAR(*rest))) {
  263. rest++;
  264. }
  265. switch (*rest) {
  266. case '\0':
  267. units = -1;
  268. break;
  269. case 'm':
  270. units = 0;
  271. break;
  272. case 'c':
  273. units = 1;
  274. break;
  275. case 'i':
  276. units = 2;
  277. break;
  278. case 'p':
  279. units = 3;
  280. break;
  281. default:
  282. goto error;
  283. }
  284. /*
  285. * Free the old internalRep before setting the new one.
  286. */
  287. typePtr = objPtr->typePtr;
  288. if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
  289. (*typePtr->freeIntRepProc)(objPtr);
  290. }
  291. objPtr->typePtr = &pixelObjType;
  292. i = (int) d;
  293. if ((units < 0) && (i == d)) {
  294. SET_SIMPLEPIXEL(objPtr, i);
  295. } else {
  296. pixelPtr = (PixelRep *) ckalloc(sizeof(PixelRep));
  297. pixelPtr->value = d;
  298. pixelPtr->units = units;
  299. pixelPtr->tkwin = NULL;
  300. pixelPtr->returnValue = i;
  301. SET_COMPLEXPIXEL(objPtr, pixelPtr);
  302. }
  303. return TCL_OK;
  304. }
  305. /*
  306. *----------------------------------------------------------------------
  307. *
  308. * Tk_GetMMFromObj --
  309. *
  310. * Attempt to return an mm value from the Tcl object "objPtr". If the
  311. * object is not already an mm value, an attempt will be made to convert
  312. * it to one.
  313. *
  314. * Results:
  315. * The return value is a standard Tcl object result. If an error occurs
  316. * during conversion, an error message is left in the interpreter's
  317. * result unless "interp" is NULL.
  318. *
  319. * Side effects:
  320. * If the object is not already a pixel, the conversion will free
  321. * any old internal representation.
  322. *
  323. *----------------------------------------------------------------------
  324. */
  325. int
  326. Tk_GetMMFromObj(interp, tkwin, objPtr, doublePtr)
  327. Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  328. Tk_Window tkwin;
  329. Tcl_Obj *objPtr; /* The object from which to get mms. */
  330. double *doublePtr; /* Place to store resulting millimeters. */
  331. {
  332. int result;
  333. double d;
  334. MMRep *mmPtr;
  335. static double bias[] = {
  336. 10.0, 25.4, 1.0, 25.4 / 72.0
  337. };
  338. if (objPtr->typePtr != &mmObjType) {
  339. result = SetMMFromAny(interp, objPtr);
  340. if (result != TCL_OK) {
  341. return result;
  342. }
  343. }
  344. mmPtr = (MMRep *) objPtr->internalRep.otherValuePtr;
  345. if (mmPtr->tkwin != tkwin) {
  346. d = mmPtr->value;
  347. if (mmPtr->units == -1) {
  348. d /= WidthOfScreen(Tk_Screen(tkwin));
  349. d *= WidthMMOfScreen(Tk_Screen(tkwin));
  350. } else {
  351. d *= bias[mmPtr->units];
  352. }
  353. mmPtr->tkwin = tkwin;
  354. mmPtr->returnValue = d;
  355. }
  356. *doublePtr = mmPtr->returnValue;
  357. return TCL_OK;
  358. }
  359. /*
  360. *----------------------------------------------------------------------
  361. *
  362. * FreeMMInternalRep --
  363. *
  364. * Deallocate the storage associated with a mm object's internal
  365. * representation.
  366. *
  367. * Results:
  368. * None.
  369. *
  370. * Side effects:
  371. * Frees objPtr's internal representation and sets objPtr's
  372. * internalRep to NULL.
  373. *
  374. *----------------------------------------------------------------------
  375. */
  376. static void
  377. FreeMMInternalRep(objPtr)
  378. Tcl_Obj *objPtr; /* MM object with internal rep to free. */
  379. {
  380. ckfree((char *) objPtr->internalRep.otherValuePtr);
  381. objPtr->internalRep.otherValuePtr = NULL;
  382. }
  383. /*
  384. *----------------------------------------------------------------------
  385. *
  386. * DupMMInternalRep --
  387. *
  388. * Initialize the internal representation of a pixel Tcl_Obj to a
  389. * copy of the internal representation of an existing pixel object.
  390. *
  391. * Results:
  392. * None.
  393. *
  394. * Side effects:
  395. * copyPtr's internal rep is set to the pixel corresponding to
  396. * srcPtr's internal rep.
  397. *
  398. *----------------------------------------------------------------------
  399. */
  400. static void
  401. DupMMInternalRep(srcPtr, copyPtr)
  402. register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
  403. register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
  404. {
  405. MMRep *oldPtr, *newPtr;
  406. copyPtr->typePtr = srcPtr->typePtr;
  407. oldPtr = (MMRep *) srcPtr->internalRep.otherValuePtr;
  408. newPtr = (MMRep *) ckalloc(sizeof(MMRep));
  409. newPtr->value = oldPtr->value;
  410. newPtr->units = oldPtr->units;
  411. newPtr->tkwin = oldPtr->tkwin;
  412. newPtr->returnValue = oldPtr->returnValue;
  413. copyPtr->internalRep.otherValuePtr = (VOID *) newPtr;
  414. }
  415. /*
  416. *----------------------------------------------------------------------
  417. *
  418. * SetMMFromAny --
  419. *
  420. * Attempt to generate a mm internal form for the Tcl object
  421. * "objPtr".
  422. *
  423. * Results:
  424. * The return value is a standard Tcl result. If an error occurs during
  425. * conversion, an error message is left in the interpreter's result
  426. * unless "interp" is NULL.
  427. *
  428. * Side effects:
  429. * If no error occurs, a mm representation of the object is
  430. * stored internally and the type of "objPtr" is set to mm.
  431. *
  432. *----------------------------------------------------------------------
  433. */
  434. static int
  435. SetMMFromAny(interp, objPtr)
  436. Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  437. Tcl_Obj *objPtr; /* The object to convert. */
  438. {
  439. Tcl_ObjType *typePtr;
  440. char *string, *rest;
  441. double d;
  442. int units;
  443. MMRep *mmPtr;
  444. string = Tcl_GetStringFromObj(objPtr, NULL);
  445. d = strtod(string, &rest);
  446. if (rest == string) {
  447. /*
  448. * Must copy string before resetting the result in case a caller
  449. * is trying to convert the interpreter's result to mms.
  450. */
  451. error:
  452. Tcl_AppendResult(interp, "bad screen distance \"", string,
  453. "\"", (char *) NULL);
  454. return TCL_ERROR;
  455. }
  456. while ((*rest != '\0') && isspace(UCHAR(*rest))) {
  457. rest++;
  458. }
  459. switch (*rest) {
  460. case '\0':
  461. units = -1;
  462. break;
  463. case 'c':
  464. units = 0;
  465. break;
  466. case 'i':
  467. units = 1;
  468. break;
  469. case 'm':
  470. units = 2;
  471. break;
  472. case 'p':
  473. units = 3;
  474. break;
  475. default:
  476. goto error;
  477. }
  478. /*
  479. * Free the old internalRep before setting the new one.
  480. */
  481. typePtr = objPtr->typePtr;
  482. if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
  483. (*typePtr->freeIntRepProc)(objPtr);
  484. }
  485. objPtr->typePtr = &mmObjType;
  486. mmPtr = (MMRep *) ckalloc(sizeof(MMRep));
  487. mmPtr->value = d;
  488. mmPtr->units = units;
  489. mmPtr->tkwin = NULL;
  490. mmPtr->returnValue = d;
  491. objPtr->internalRep.otherValuePtr = (VOID *) mmPtr;
  492. return TCL_OK;
  493. }
  494. /*
  495. *----------------------------------------------------------------------
  496. *
  497. * TkGetWindowFromObj --
  498. *
  499. * Attempt to return a Tk_Window from the Tcl object "objPtr". If the
  500. * object is not already a Tk_Window, an attempt will be made to convert
  501. * it to one.
  502. *
  503. * Results:
  504. * The return value is a standard Tcl object result. If an error occurs
  505. * during conversion, an error message is left in the interpreter's
  506. * result unless "interp" is NULL.
  507. *
  508. * Side effects:
  509. * If the object is not already a Tk_Window, the conversion will free
  510. * any old internal representation.
  511. *
  512. *----------------------------------------------------------------------
  513. */
  514. int
  515. TkGetWindowFromObj(interp, tkwin, objPtr, windowPtr)
  516. Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  517. Tk_Window tkwin; /* A token to get the main window from. */
  518. register Tcl_Obj *objPtr; /* The object from which to get boolean. */
  519. Tk_Window *windowPtr; /* Place to store resulting window. */
  520. {
  521. register int result;
  522. Tk_Window lastWindow;
  523. result = SetWindowFromAny(interp, objPtr);
  524. if (result != TCL_OK) {
  525. return result;
  526. }
  527. lastWindow = (Tk_Window) objPtr->internalRep.twoPtrValue.ptr1;
  528. if (tkwin != lastWindow) {
  529. Tk_Window foundWindow = Tk_NameToWindow(interp,
  530. Tcl_GetStringFromObj(objPtr, NULL), tkwin);
  531. if (foundWindow == NULL) {
  532. return TCL_ERROR;
  533. }
  534. objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkwin;
  535. objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) foundWindow;
  536. }
  537. *windowPtr = (Tk_Window) objPtr->internalRep.twoPtrValue.ptr2;
  538. return result;
  539. }
  540. /*
  541. *----------------------------------------------------------------------
  542. *
  543. * SetWindowFromAny --
  544. *
  545. * Attempt to generate a Tk_Window internal form for the Tcl object
  546. * "objPtr".
  547. *
  548. * Results:
  549. * The return value is a standard Tcl result. If an error occurs during
  550. * conversion, an error message is left in the interpreter's result
  551. * unless "interp" is NULL.
  552. *
  553. * Side effects:
  554. * If no error occurs, a standard window value is stored as "objPtr"s
  555. * internal representation and the type of "objPtr" is set to Tk_Window.
  556. *
  557. *----------------------------------------------------------------------
  558. */
  559. static int
  560. SetWindowFromAny(interp, objPtr)
  561. Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  562. register Tcl_Obj *objPtr; /* The object to convert. */
  563. {
  564. Tcl_ObjType *typePtr;
  565. /*
  566. * Free the old internalRep before setting the new one.
  567. */
  568. Tcl_GetStringFromObj(objPtr, NULL);
  569. typePtr = objPtr->typePtr;
  570. if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
  571. (*typePtr->freeIntRepProc)(objPtr);
  572. }
  573. objPtr->typePtr = &windowObjType;
  574. objPtr->internalRep.twoPtrValue.ptr1 = NULL;
  575. objPtr->internalRep.twoPtrValue.ptr2 = NULL;
  576. return TCL_OK;
  577. }