WmGraphics.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * (c) Copyright 1989, 1990, 1991, 1992 OPEN SOFTWARE FOUNDATION, INC.
  25. * ALL RIGHTS RESERVED
  26. */
  27. /*
  28. * Motif Release 1.2
  29. */
  30. /*
  31. * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
  32. /*
  33. * Included Files:
  34. */
  35. #include "WmGlobal.h"
  36. #include <stdio.h>
  37. #include <X11/Xlib.h>
  38. #include <X11/StringDefs.h>
  39. #include <X11/Xutil.h>
  40. #include <X11/Intrinsic.h>
  41. #include <X11/X.h>
  42. #include <Xm/Xm.h>
  43. #define RLIST_EXTENSION_SIZE 10
  44. #ifndef MIN
  45. #define MAX(x,y) ((x)>(y)?(x):(y))
  46. #endif
  47. /*
  48. * include extern functions
  49. */
  50. #include "WmGraphics.h"
  51. #include "WmError.h"
  52. /*
  53. * Global Variables:
  54. */
  55. /*
  56. * Macros:
  57. */
  58. /* test if > 0 and return 1 if true, 0 if false. */
  59. #define GE1(x) ((x)>0?1:0)
  60. /*************************************<->*************************************
  61. *
  62. * Procedure: BevelRectangle (prTop, prBot, x, y,
  63. * width, height, top_wid, right_wid, bot_wid, left_wid)
  64. *
  65. * Description:
  66. * -----------
  67. * Generate data for top- and bottom-shadow bevels on a box.
  68. *
  69. * Inputs:
  70. * ------
  71. * prTop - ptr to top shadow RList
  72. * prBot - ptr to bottom shadow RList
  73. * x,y - position of rectangle to bevel
  74. * width - (outside) width of rectangle
  75. * height - (outside) height of rectangle
  76. * top_wid - width of beveling on top side of rectangle
  77. * right_wid - width of beveling on right side of rectangle
  78. * bot_wid - width of beveling on bottom side of rectangle
  79. * left_wid - width of beveling on left side of rectangle
  80. *
  81. * Outputs:
  82. * -------
  83. * prTop - top shadows for this rectangle added to list
  84. * prBot - bottom shadows for this rectangle added to list
  85. *
  86. *
  87. * Comments:
  88. * --------
  89. *
  90. *************************************<->***********************************/
  91. void BevelRectangle (RList *prTop, RList *prBot, int x, int y, unsigned int width, unsigned int height, unsigned int top_wid, unsigned int right_wid, unsigned int bot_wid, unsigned int left_wid)
  92. {
  93. XRectangle *prect; /* pointer to "current" rectangle */
  94. int count; /* counter used for beveling operation */
  95. int join1, join2; /* used to compute "good" bevel joints */
  96. int x1, y1, len; /* used to compute bevel parameters */
  97. int *piTop, *piBot;
  98. /* build the rectangles to implement the beveling on each side */
  99. /* top side */
  100. if (((prTop->used + (top_wid + left_wid)) > prTop->allocated) &&
  101. (!ExtendRList (prTop, MAX (top_wid+left_wid, RLIST_EXTENSION_SIZE))))
  102. {
  103. return; /* not enough memory */
  104. }
  105. piTop = &(prTop->used);
  106. prect = &(prTop->prect[*piTop]);
  107. join1 = left_wid;
  108. join2 = right_wid;
  109. x1 = x;
  110. y1 = y;
  111. len = width;
  112. for (count=top_wid; count>0; count--, prect++, (*piTop)++)
  113. {
  114. prect->x = x1;
  115. prect->y = y1;
  116. prect->width = len;
  117. prect->height = 1;
  118. x1 += GE1(--join1);
  119. y1 += 1;
  120. len -= GE1(join1) + GE1(--join2);
  121. }
  122. /* left side */
  123. join1 = top_wid;
  124. join2 = bot_wid;
  125. x1 = x;
  126. y1 = y+GE1(join1);
  127. len = height-GE1(join1);
  128. for (count=left_wid; count >0; count--, prect++, (*piTop)++)
  129. {
  130. prect->x = x1;
  131. prect->y = y1;
  132. prect->width = 1;
  133. prect->height = len;
  134. x1 += 1;
  135. y1 += GE1(--join1);
  136. len -= GE1(join1) + GE1(--join2);
  137. }
  138. /* bottom side */
  139. if (((prBot->used + (bot_wid + right_wid)) > prBot->allocated) &&
  140. (!ExtendRList(prBot, MAX (bot_wid+right_wid, RLIST_EXTENSION_SIZE))))
  141. {
  142. return;
  143. }
  144. piBot = &(prBot->used);
  145. prect = &(prBot->prect[*piBot]);
  146. join1 = left_wid;
  147. join2 = right_wid;
  148. x1 = x+GE1(join1);
  149. y1 = y+height-1;
  150. len = width-GE1(join1);
  151. /* fudge fat bottom shadow to overwrite corner of skinny left shadow */
  152. if (GE1(join1) && (bot_wid > left_wid)) {
  153. len++;
  154. x1--;
  155. join1++;
  156. }
  157. for (count=bot_wid; count >0; count--, prect++, (*piBot)++)
  158. {
  159. prect->x = x1;
  160. prect->y = y1;
  161. prect->width = len;
  162. prect->height = 1;
  163. x1 += GE1(--join1);
  164. y1 -= 1;
  165. len -= GE1(join1) + GE1(--join2);
  166. }
  167. /* right side */
  168. join1 = top_wid;
  169. join2 = bot_wid;
  170. x1 = x+width-1;
  171. y1 = y+GE1(join1);
  172. len = height - GE1(join1) - GE1(join2);
  173. /* fudge fat right shadow to overwrite corner of skinny top shadow */
  174. if (GE1(join1) && (right_wid > top_wid)) {
  175. len++;
  176. y1--;
  177. join1++;
  178. }
  179. for (count=right_wid; count >0; count--, prect++, (*piBot)++)
  180. {
  181. prect->x = x1;
  182. prect->y = y1;
  183. prect->width = 1;
  184. prect->height = len;
  185. x1 -= 1;
  186. y1 += GE1(--join1);
  187. len -= GE1(join1) + GE1(--join2);
  188. }
  189. } /* END OF FUNCTION BevelRectangle */
  190. /*************************************<->*************************************
  191. *
  192. * Procedure: BevelDepressedRectangle (prTop, prBot, x, y,
  193. * width, height, top_wid, right_wid, bot_wid, left_wid
  194. * in_wid)
  195. *
  196. * Description:
  197. * -----------
  198. * Generate data for top- and bottom-shadow bevels on a rectangle with
  199. * the center part depressed.
  200. *
  201. * Inputs:
  202. * ------
  203. * prTop - ptr to top shadow RList
  204. * prBot - ptr to bottom shadow RList
  205. * x,y - position of rectangle to bevel
  206. * width - (outside) width of rectangle
  207. * height - (outside) height of rectangle
  208. * top_wid - width of beveling on top side of rectangle
  209. * right_wid - width of beveling on right side of rectangle
  210. * bot_wid - width of beveling on bottom side of rectangle
  211. * left_wid - width of beveling on left side of rectangle
  212. * in_wid - width of depressed beveling inside of rectangle
  213. *
  214. * Outputs:
  215. * -------
  216. * prTop - top shadows for this rectangle added to list
  217. * prBot - bottom shadows for this rectangle added to list
  218. *
  219. *
  220. * Comments:
  221. * --------
  222. *
  223. *************************************<->***********************************/
  224. void BevelDepressedRectangle (RList *prTop, RList *prBot, int x, int y, unsigned int width, unsigned int height, unsigned int top_wid, unsigned int right_wid, unsigned int bot_wid, unsigned int left_wid, unsigned int in_wid)
  225. {
  226. XRectangle *prect; /* pointer to "current" rectangle */
  227. int count; /* counter used for beveling operation */
  228. int join1, join2; /* used to compute "good" bevel joints */
  229. int x1, y1, len; /* used to compute bevel parameters */
  230. int *piTop, *piBot;
  231. /*
  232. * Build the rectangles to implement the beveling on each side
  233. * First, guarantee that there is enough memory.
  234. */
  235. if (((prTop->used + (top_wid + left_wid)) > prTop->allocated) &&
  236. (!ExtendRList (prTop, MAX (top_wid+left_wid, RLIST_EXTENSION_SIZE))))
  237. {
  238. return; /* not enough memory */
  239. }
  240. if (((prBot->used + (bot_wid + right_wid)) > prBot->allocated) &&
  241. (!ExtendRList(prBot, MAX (bot_wid+right_wid, RLIST_EXTENSION_SIZE))))
  242. {
  243. return; /* not enought memory */
  244. }
  245. /* top side (normal beveling) */
  246. piTop = &(prTop->used);
  247. prect = &(prTop->prect[*piTop]);
  248. join1 = left_wid;
  249. join2 = right_wid;
  250. x1 = x;
  251. y1 = y;
  252. len = width;
  253. for (count=top_wid - in_wid; count>0; count--, prect++, (*piTop)++)
  254. {
  255. prect->x = x1;
  256. prect->y = y1;
  257. prect->width = len;
  258. prect->height = 1;
  259. x1 += GE1(--join1);
  260. y1 += 1;
  261. len -= GE1(join1) + GE1(--join2);
  262. }
  263. /* top side (inverted beveling) */
  264. piBot = &(prBot->used);
  265. prect = &(prBot->prect[*piBot]);
  266. for (count=in_wid; count>0; count--, prect++, (*piBot)++)
  267. {
  268. prect->x = x1;
  269. prect->y = y1;
  270. prect->width = len;
  271. prect->height = 1;
  272. x1 += GE1(--join1);
  273. y1 += 1;
  274. len -= GE1(join1) + GE1(--join2);
  275. }
  276. /* left side (normal beveling) */
  277. piTop = &(prTop->used);
  278. prect = &(prTop->prect[*piTop]);
  279. join1 = top_wid;
  280. join2 = bot_wid;
  281. x1 = x;
  282. y1 = y+GE1(join1);
  283. len = height-GE1(join1);
  284. for (count=left_wid-in_wid; count >0; count--, prect++, (*piTop)++)
  285. {
  286. prect->x = x1;
  287. prect->y = y1;
  288. prect->width = 1;
  289. prect->height = len;
  290. x1 += 1;
  291. y1 += GE1(--join1);
  292. len -= GE1(join1) + GE1(--join2);
  293. }
  294. /* left side (inverted beveling) */
  295. piBot = &(prBot->used);
  296. prect = &(prBot->prect[*piBot]);
  297. for (count=in_wid; count >0; count--, prect++, (*piBot)++)
  298. {
  299. prect->x = x1;
  300. prect->y = y1;
  301. prect->width = 1;
  302. prect->height = len;
  303. x1 += 1;
  304. y1 += GE1(--join1);
  305. len -= GE1(join1) + GE1(--join2);
  306. }
  307. /* bottom side (normal beveling) */
  308. piBot = &(prBot->used);
  309. prect = &(prBot->prect[*piBot]);
  310. join1 = left_wid;
  311. join2 = right_wid;
  312. x1 = x+GE1(join1);
  313. y1 = y+height-1;
  314. len = width-GE1(join1);
  315. /* fudge fat bottom shadow to overwrite corner of skinny left shadow */
  316. if (GE1(join1) && (bot_wid > left_wid)) {
  317. len++;
  318. x1--;
  319. join1++;
  320. }
  321. for (count=bot_wid-in_wid; count >0; count--, prect++, (*piBot)++)
  322. {
  323. prect->x = x1;
  324. prect->y = y1;
  325. prect->width = len;
  326. prect->height = 1;
  327. x1 += GE1(--join1);
  328. y1 -= 1;
  329. len -= GE1(join1) + GE1(--join2);
  330. }
  331. /* bottom side (inverted beveling) */
  332. piTop = &(prTop->used);
  333. prect = &(prTop->prect[*piTop]);
  334. for (count=in_wid; count >0; count--, prect++, (*piTop)++)
  335. {
  336. prect->x = x1;
  337. prect->y = y1;
  338. prect->width = len;
  339. prect->height = 1;
  340. x1 += GE1(--join1);
  341. y1 -= 1;
  342. len -= GE1(join1) + GE1(--join2);
  343. }
  344. /* right side (normal beveling) */
  345. piBot = &(prBot->used);
  346. prect = &(prBot->prect[*piBot]);
  347. join1 = top_wid;
  348. join2 = bot_wid;
  349. x1 = x+width-1;
  350. y1 = y+GE1(join1);
  351. len = height - GE1(join1) - GE1(join2);
  352. /* fudge fat right shadow to overwrite corner of skinny top shadow */
  353. if (GE1(join1) && (right_wid > top_wid)) {
  354. len++;
  355. y1--;
  356. join1++;
  357. }
  358. for (count=right_wid-in_wid; count >0; count--, prect++, (*piBot)++)
  359. {
  360. prect->x = x1;
  361. prect->y = y1;
  362. prect->width = 1;
  363. prect->height = len;
  364. x1 -= 1;
  365. y1 += GE1(--join1);
  366. len -= GE1(join1) + GE1(--join2);
  367. }
  368. /* right side (inverted beveling) */
  369. piTop = &(prTop->used);
  370. prect = &(prTop->prect[*piTop]);
  371. for (count=in_wid; count >0; count--, prect++, (*piTop)++)
  372. {
  373. prect->x = x1;
  374. prect->y = y1;
  375. prect->width = 1;
  376. prect->height = len;
  377. x1 -= 1;
  378. y1 += GE1(--join1);
  379. len -= GE1(join1) + GE1(--join2);
  380. }
  381. } /* END OF FUNCTION BevelDepressedRectangle */
  382. /*************************************<->*************************************
  383. *
  384. * Procedure: StretcherCorner (prTop, prBot, x, y, cnum,
  385. * swidth, cwidth, cheight);
  386. *
  387. * Description:
  388. * -----------
  389. * Generate data to draw a corner of the stretcher border.
  390. *
  391. * Inputs:
  392. * ------
  393. * prTop - ptr to top shadow RList
  394. * prBot - ptr to bottom shadow RList
  395. * x,y - position of rectangle enclosing the cornern
  396. * cnum - corner number; which corner to draw
  397. * ASSUMES only NW, NE, SE, SW for mwm ()
  398. * swidth - width (thickness) of border (includes bevels)
  399. * cwidth - corner width from corner to end of horizontal run
  400. * cheight - corner height from corner to end of vertical run
  401. *
  402. * Outputs:
  403. * -------
  404. * prTop - array filled in for top shadows
  405. * prBot - array filledin for bottom shadows
  406. *
  407. * Comments:
  408. * --------
  409. * o Uses only 1 pixel bevels. Beveling is hard coded.
  410. * o XFillRectangles assumed as an optimization to take
  411. * advantage of the block mover hardware.
  412. *
  413. *************************************<->***********************************/
  414. void StretcherCorner (RList *prTop, RList *prBot, int x, int y, int cnum, unsigned int swidth, unsigned int cwidth, unsigned int cheight)
  415. {
  416. XRectangle *prect; /* pointer to "current" rectangle */
  417. int *piTop, *piBot;
  418. switch (cnum) {
  419. case STRETCH_NORTH_WEST:
  420. if (((prTop->used + 4) > prTop->allocated) &&
  421. (!ExtendRList (prTop, (unsigned int) RLIST_EXTENSION_SIZE)))
  422. {
  423. return;
  424. }
  425. piTop = &(prTop->used);
  426. prect = &(prTop->prect[*piTop]);
  427. prect->x = x; /* top (row 1) */
  428. prect->y = y;
  429. prect->width = cwidth;
  430. prect->height = 1;
  431. prect++;
  432. (*piTop)++;
  433. prect->x = x+1; /* top (row 2) */
  434. prect->y = y+1;
  435. prect->width = cwidth-2;
  436. prect->height = 1;
  437. prect++;
  438. (*piTop)++;
  439. prect->x = x; /* left (col 1) */
  440. prect->y = y+1;
  441. prect->width = 1;
  442. prect->height = cheight-1;
  443. prect++;
  444. (*piTop)++;
  445. prect->x = x+1; /* left (col 2) */
  446. prect->y = y+2;
  447. prect->width = 1;
  448. prect->height = cheight-3;
  449. (*piTop)++;
  450. if (((prBot->used + 4) > prBot->allocated) &&
  451. (!ExtendRList (prBot, (unsigned int) RLIST_EXTENSION_SIZE)))
  452. {
  453. return;
  454. }
  455. piBot = &(prBot->used);
  456. prect = &(prBot->prect[*piBot]); /* bottom shadow parts */
  457. prect->x = x+1; /* bottom end */
  458. prect->y = y+cheight-1;
  459. prect->width = swidth-1;
  460. prect->height = 1;
  461. prect++;
  462. (*piBot)++;
  463. if (wmGD.frameStyle == WmRECESSED)
  464. {
  465. prect->x = x+swidth-1; /* right inside */
  466. prect->y = y+swidth-1;
  467. prect->width = 1;
  468. prect->height = cheight-swidth;
  469. prect++;
  470. (*piBot)++;
  471. prect->x = x+swidth; /* bottom inside */
  472. prect->y = y+swidth-1;
  473. prect->width = cwidth-swidth;
  474. prect->height = 1;
  475. prect++;
  476. (*piBot)++;
  477. }
  478. prect->x = x+cwidth-1; /* right end */
  479. prect->y = y+1;
  480. prect->width = 1;
  481. prect->height = swidth-1-((wmGD.frameStyle == WmSLAB)? 0 : 1);
  482. (*piBot)++;
  483. break;
  484. case STRETCH_NORTH_EAST:
  485. if (((prTop->used + 4) > prTop->allocated) &&
  486. (!ExtendRList (prTop, (unsigned int) RLIST_EXTENSION_SIZE)))
  487. {
  488. return;
  489. }
  490. piTop = &(prTop->used);
  491. prect = &(prTop->prect[*piTop]);
  492. prect->x = x; /* top (row 1) */
  493. prect->y = y;
  494. prect->width = cwidth;
  495. prect->height = 1;
  496. prect++;
  497. (*piTop)++;
  498. prect->x = x+1; /* top (row 2) */
  499. prect->y = y+1;
  500. prect->width = cwidth-2;
  501. prect->height = 1;
  502. prect++;
  503. (*piTop)++;
  504. prect->x = x; /* left end */
  505. prect->y = y+1;
  506. prect->width = 1;
  507. prect->height = swidth-1;
  508. prect++;
  509. (*piTop)++;
  510. if (wmGD.frameStyle == WmRECESSED)
  511. {
  512. prect->x = x+cwidth-swidth; /* left inside (col 1) */
  513. prect->y = y+swidth;
  514. prect->width = 1;
  515. prect->height = cheight-swidth;
  516. (*piTop)++;
  517. }
  518. if (((prBot->used + 4) > prBot->allocated) &&
  519. (!ExtendRList (prBot, (unsigned int) RLIST_EXTENSION_SIZE)))
  520. {
  521. return;
  522. }
  523. piBot = &(prBot->used);
  524. prect = &(prBot->prect[*piBot]); /* bottom shadow parts */
  525. /* bottom end */
  526. prect->x = x+cwidth-swidth+((wmGD.frameStyle == WmSLAB)? 0 : 1);
  527. prect->y = y+cheight-1;
  528. prect->width = swidth-((wmGD.frameStyle == WmSLAB)? 0 : 1);
  529. prect->height = 1;
  530. prect++;
  531. (*piBot)++;
  532. prect->x = x+cwidth-1; /* right (col 2) */
  533. prect->y = y+1;
  534. prect->width = 1;
  535. prect->height = cheight-2;
  536. prect++;
  537. (*piBot)++;
  538. prect->x = x+cwidth-2; /* right (col 1) */
  539. prect->y = y+2;
  540. prect->width = 1;
  541. prect->height = cheight-3;
  542. prect++;
  543. (*piBot)++;
  544. if (wmGD.frameStyle == WmRECESSED)
  545. {
  546. prect->x = x+1; /* bottom inside (row 2) */
  547. prect->y = y+swidth-1;
  548. prect->width = cwidth-swidth;
  549. prect->height = 1;
  550. (*piBot)++;
  551. }
  552. break;
  553. case STRETCH_SOUTH_EAST:
  554. if (((prTop->used + 4) > prTop->allocated) &&
  555. (!ExtendRList (prTop, (unsigned int) RLIST_EXTENSION_SIZE)))
  556. {
  557. return;
  558. }
  559. piTop = &(prTop->used);
  560. prect = &(prTop->prect[*piTop]);
  561. if (wmGD.frameStyle == WmRECESSED)
  562. {
  563. prect->x = x; /* top inside */
  564. prect->y = y+cheight-swidth;
  565. prect->width = cwidth-swidth+1;
  566. prect->height = 1;
  567. prect++;
  568. (*piTop)++;
  569. prect->x = x+cwidth-swidth; /* left inside */
  570. prect->y = y;
  571. prect->width = 1;
  572. prect->height = cheight-swidth;
  573. prect++;
  574. (*piTop)++;
  575. }
  576. /* top end */
  577. prect->x = x+cwidth-swidth+
  578. ((wmGD.frameStyle == WmSLAB)? 0 : 1);
  579. prect->y = y;
  580. prect->width = swidth-2+((wmGD.frameStyle == WmSLAB)? 1 : 0);;
  581. prect->height = 1;
  582. prect++;
  583. (*piTop)++;
  584. prect->x = x; /* left end */
  585. prect->y = y+cheight-swidth+
  586. ((wmGD.frameStyle == WmSLAB)? 0 : 1);
  587. prect->width = 1;
  588. prect->height = swidth-2+((wmGD.frameStyle == WmSLAB)? 1 : 0);
  589. (*piTop)++;
  590. if (((prBot->used + 4) > prBot->allocated) &&
  591. (!ExtendRList (prBot, (unsigned int) RLIST_EXTENSION_SIZE)))
  592. {
  593. return;
  594. }
  595. piBot = &(prBot->used);
  596. prect = &(prBot->prect[*piBot]); /* bottom shadow parts */
  597. prect->x = x+1; /* bottom - row 1 */
  598. prect->y = y+cheight-2;
  599. prect->width = cwidth-1;
  600. prect->height = 1;
  601. prect++;
  602. (*piBot)++;
  603. prect->x = x; /* bottom - row 2 */
  604. prect->y = y+cheight-1;
  605. prect->width = cwidth;
  606. prect->height = 1;
  607. prect++;
  608. (*piBot)++;
  609. prect->x = x+cwidth-2; /* right - column 1 */
  610. prect->y = y+1;
  611. prect->width = 1;
  612. prect->height = cheight-3;
  613. prect++;
  614. (*piBot)++;
  615. prect->x = x+cwidth-1; /* right - column 2 */
  616. prect->y = y;
  617. prect->width = 1;
  618. prect->height = cheight-2;
  619. (*piBot)++;
  620. break;
  621. case STRETCH_SOUTH_WEST:
  622. if (((prTop->used + 4) > prTop->allocated) &&
  623. (!ExtendRList (prTop, (unsigned int) RLIST_EXTENSION_SIZE)))
  624. {
  625. return;
  626. }
  627. piTop = &(prTop->used);
  628. prect = &(prTop->prect[*piTop]);
  629. prect->x = x; /* top end */
  630. prect->y = y;
  631. prect->width = swidth;
  632. prect->height = 1;
  633. prect++;
  634. (*piTop)++;
  635. prect->x = x; /* left (col 1) */
  636. prect->y = y+1;
  637. prect->width = 1;
  638. prect->height = cheight-1;
  639. prect++;
  640. (*piTop)++;
  641. prect->x = x+1; /* left (col 2) */
  642. prect->y = y+1;
  643. prect->width = 1;
  644. prect->height = cheight-2;
  645. prect++;
  646. (*piTop)++;
  647. if (wmGD.frameStyle == WmRECESSED)
  648. {
  649. prect->x = x+swidth; /* top inside (row 2) */
  650. prect->y = y+cheight-swidth;
  651. prect->width = cwidth-swidth;
  652. prect->height = 1;
  653. (*piTop)++;
  654. }
  655. if (((prBot->used + 4) > prBot->allocated) &&
  656. (!ExtendRList (prBot, (unsigned int) RLIST_EXTENSION_SIZE)))
  657. {
  658. return;
  659. }
  660. piBot = &(prBot->used);
  661. prect = &(prBot->prect[*piBot]); /* bottom shadow parts */
  662. if (wmGD.frameStyle == WmRECESSED)
  663. {
  664. prect->x = x+swidth-1; /* right inside (col 2) */
  665. prect->y = y+1;
  666. prect->width = 1;
  667. prect->height = cheight-swidth;
  668. prect++;
  669. (*piBot)++;
  670. }
  671. prect->x = x+cwidth-1; /* right end */
  672. prect->y = y+cheight-swidth+
  673. ((wmGD.frameStyle == WmSLAB)? 0 : 1);
  674. prect->width = 1;
  675. prect->height = swidth-((wmGD.frameStyle == WmSLAB)? 0 : 1);
  676. prect++;
  677. (*piBot)++;
  678. prect->x = x+2; /* bottom (row 1) */
  679. prect->y = y+cheight-2;
  680. prect->width = cwidth-3;
  681. prect->height = 1;
  682. prect++;
  683. (*piBot)++;
  684. prect->x = x+1; /* bottom (row 2) */
  685. prect->y = y+cheight-1;
  686. prect->width = cwidth-2;
  687. prect->height = 1;
  688. (*piBot)++;
  689. break;
  690. }
  691. } /* END OF FUNCTION StretcherCorner */
  692. /*************************************<->*************************************
  693. *
  694. * DrawStringInBox (dpy, win, gc, pbox, str)
  695. *
  696. *
  697. * Description:
  698. * -----------
  699. * Draws a null-terminated string inside the specified box (rectangle)
  700. *
  701. *
  702. * Inputs:
  703. * ------
  704. * dpy - ptr to Display
  705. * win - an X Window
  706. * gc - graphics context to use
  707. * pfs - pointer to XFontStruct for the font in "gc"
  708. * pbox - ptr to XRectangle that encloses text
  709. * str - String to write
  710. *
  711. * Outputs:
  712. * -------
  713. * none
  714. *
  715. * Comments:
  716. * --------
  717. * o Assumes 8-bit text for now.
  718. * o Algorithm:
  719. * get length of String
  720. * if String is short than box width then
  721. * draw string centered in box
  722. * otherwise
  723. * draw string left justified and clipped to box
  724. * o The clip_x_origin, clip_y_origin, and clip_mask are reset to None
  725. * upon exit.
  726. * o Due to bugs and / or misunderstanding, I gave up on trying to
  727. * extract the XFontStruct from the GC. I just made it a separate
  728. * parameter.
  729. *
  730. *************************************<->***********************************/
  731. void DrawStringInBox (Display *dpy, Window win, GC gc, XFontStruct *pfs, XRectangle *pbox, String str)
  732. {
  733. XGCValues gcv;
  734. int textWidth;
  735. int xCenter;
  736. XRectangle clipBox;
  737. /* compute text position */
  738. textWidth = XTextWidth(pfs, str, strlen(str));
  739. if (textWidth < (int) pbox->width) { /* center text if there's room */
  740. xCenter = (int) pbox->x + ((int) pbox->width - textWidth) / 2 ;
  741. WmDrawString(dpy, win, gc, xCenter, (pbox->y + pfs->ascent),
  742. str, strlen(str));
  743. }
  744. else { /* left justify & clip text */
  745. clipBox.x = 0; /* set up clip rectangle */
  746. clipBox.y = 0;
  747. clipBox.width = pbox->width;
  748. clipBox.height = pbox->height;
  749. XSetClipRectangles (dpy, gc, pbox->x, pbox->y, /* put into gc */
  750. &clipBox, 1, Unsorted);
  751. WmDrawString(dpy, win, gc, pbox->x, (pbox->y + pfs->ascent),
  752. str, strlen(str));
  753. gcv.clip_x_origin = 0; /* erase clip_mask from gc */
  754. gcv.clip_y_origin = 0;
  755. gcv.clip_mask = None;
  756. XChangeGC (dpy, gc,
  757. GCClipXOrigin | GCClipYOrigin | GCClipMask, &gcv);
  758. }
  759. } /* END OF FUNCTION DrawStringInBox */
  760. /*************************************<->*************************************
  761. *
  762. * ExtendRList (prl, amt)
  763. *
  764. *
  765. * Description:
  766. * -----------
  767. * Extends the size of the RList
  768. *
  769. *
  770. * Inputs:
  771. * ------
  772. * prl - ptr to Display
  773. * amt - how much to extend it by
  774. *
  775. * Outputs:
  776. * -------
  777. * Returns True if succeeded, false otherwise.
  778. *
  779. * Comments:
  780. * --------
  781. *
  782. *************************************<->***********************************/
  783. Boolean ExtendRList (RList *prl, unsigned int amt)
  784. {
  785. unsigned int total, count;
  786. XRectangle *pNewRect;
  787. Boolean rval;
  788. total = prl->allocated + amt;
  789. if ( (pNewRect = (XRectangle *) XtMalloc (total * sizeof(XRectangle)))
  790. == NULL)
  791. {
  792. Warning (((char *)GETMESSAGE(28, 1, "Insufficient memory for graphics data")));
  793. rval = False;
  794. }
  795. else
  796. {
  797. prl->allocated = total;
  798. rval = True;
  799. if (prl->used != 0) { /* copy from old structure */
  800. count = prl->used * sizeof(XRectangle);
  801. (void) memcpy ((void *)pNewRect, (void *)prl->prect, count);
  802. if (prl->prect != NULL)
  803. XtFree ((char *)prl->prect);
  804. prl->prect = pNewRect;
  805. }
  806. }
  807. return (rval);
  808. } /* END OF FUNCTION ExtendRList */
  809. /*************************************<->*************************************
  810. *
  811. * AllocateRList (amt)
  812. *
  813. *
  814. * Description:
  815. * -----------
  816. * Allocates an RList of size "amt"
  817. *
  818. *
  819. * Inputs:
  820. * ------
  821. * amt - number of XRectangles to allocate in list
  822. *
  823. * Outputs:
  824. * -------
  825. * Returns ptr to new RList structure if success, returns NULL ptr otherwise
  826. *
  827. * Comments:
  828. * --------
  829. *
  830. *************************************<->***********************************/
  831. RList *AllocateRList (unsigned int amt)
  832. {
  833. RList *prl;
  834. if ((prl = (RList *) XtMalloc (sizeof (RList))) != NULL)
  835. {
  836. if ( (prl->prect = (XRectangle *) XtMalloc (amt * sizeof(XRectangle)))
  837. == NULL)
  838. {
  839. XtFree ((char *)prl);
  840. prl = NULL;
  841. }
  842. else
  843. {
  844. prl->allocated = amt;
  845. prl->used = 0;
  846. }
  847. }
  848. return (prl);
  849. } /* END OF FUNCTION AllocateRList */
  850. /*************************************<->*************************************
  851. *
  852. * FreeRList (prl)
  853. *
  854. *
  855. * Description:
  856. * -----------
  857. * Frees an RList
  858. *
  859. *
  860. * Inputs:
  861. * ------
  862. * prl - ptr to RList to free
  863. *
  864. * Outputs:
  865. * -------
  866. *
  867. * Comments:
  868. * --------
  869. *
  870. *************************************<->***********************************/
  871. void FreeRList (RList *prl)
  872. {
  873. if (prl)
  874. {
  875. if (prl->prect)
  876. XtFree ((char *)prl->prect);
  877. XtFree ((char *)prl);
  878. }
  879. }/* END OF FUNCTION FreeRList */
  880. /*************************************<->*************************************
  881. *
  882. * WmDrawString
  883. *
  884. *
  885. * Description:
  886. * -----------
  887. * Draws a string
  888. *
  889. *
  890. * Inputs:
  891. * ------
  892. * (same parameters used by XDrawString and XDrawImageString)
  893. *
  894. * Outputs:
  895. * -------
  896. *
  897. * Comments:
  898. * --------
  899. * o If wmGD.cleanText is True, then the text is drawn using
  900. * XDrawImageString. This provides some clean space around the text
  901. * if the background area is stippled -- especially useful on
  902. * B/W displays.
  903. *
  904. *************************************<->***********************************/
  905. void WmDrawString (Display *dpy, Drawable d, GC gc, int x, int y, char *string, unsigned int length)
  906. {
  907. if (ACTIVE_PSD->cleanText)
  908. {
  909. XDrawImageString(dpy, d, gc, x, y, string, length);
  910. }
  911. else
  912. {
  913. XDrawString(dpy, d, gc, x, y, string, length);
  914. }
  915. }/* END OF FUNCTION WmDrawString */
  916. /*************************************<->*************************************
  917. *
  918. * WmXmDrawString
  919. *
  920. *
  921. * Description:
  922. * -----------
  923. * Draws a string
  924. *
  925. *
  926. * Inputs:
  927. * ------
  928. * (subset of parameters used by XmStringDraw and XmStringDrawImage)
  929. *
  930. * Outputs:
  931. * -------
  932. *
  933. * Comments:
  934. * --------
  935. * o If wmGD.cleanText is True, then the text is drawn using
  936. * XmStringDrawImage. This provides some clean space around the text
  937. * if the background area is stippled -- especially useful on
  938. * B/W displays.
  939. *
  940. *************************************<->***********************************/
  941. void WmDrawXmString (Display *dpy, Window w, XmFontList xmfontlist,
  942. XmString xmstring, GC gc, Position x, Position y,
  943. Dimension width, XRectangle *pbox, Boolean bCenter)
  944. {
  945. Dimension textWidth;
  946. int alignment;
  947. textWidth = XmStringWidth(xmfontlist, xmstring);
  948. alignment = bCenter ? XmALIGNMENT_CENTER : XmALIGNMENT_BEGINNING;
  949. if (textWidth >= pbox->width) /* can't center text if no room */
  950. { /* left justify & clip text */
  951. alignment = XmALIGNMENT_BEGINNING;
  952. }
  953. if (ACTIVE_PSD->cleanText)
  954. {
  955. XmStringDrawImage(dpy, w, xmfontlist, xmstring, gc, x, y, width,
  956. alignment, XmSTRING_DIRECTION_L_TO_R,
  957. pbox);
  958. }
  959. else
  960. {
  961. XmStringDraw (dpy, w, xmfontlist, xmstring, gc, x, y, width,
  962. alignment, XmSTRING_DIRECTION_L_TO_R, pbox);
  963. }
  964. } /* END OF FUNCTION WmDrawXmString */
  965. /*************************************<->*************************************
  966. *
  967. * WmInstallBitmapIntoXmCache (pchName, bitmap, width, height)
  968. *
  969. *
  970. * Description:
  971. * -----------
  972. * Installs all or part of a pixmap into the Xm cache. This pixmap
  973. * may be retrieved later by a call to XmGetPixmap.
  974. *
  975. * Inputs:
  976. * ------
  977. * pchName = pointer to name of bitmap
  978. * bitmap = depth-1 pixmap
  979. * width = width of portion to install
  980. * height = height of portion to install
  981. *
  982. * Outputs:
  983. * -------
  984. * none
  985. *
  986. * Comments:
  987. * --------
  988. * This always installs the Northwest corner of the passed in bitmap.
  989. * If the width and height match the size of the bitmap, then the
  990. * whole thing is installed in the cache.
  991. *
  992. *************************************<->***********************************/
  993. void WmInstallBitmapIntoXmCache (unsigned char *pchName,
  994. Pixmap bitmap, unsigned int width, unsigned int height)
  995. {
  996. XImage *pImage;
  997. pImage = XGetImage (DISPLAY, bitmap, 0, 0, width, height, 1L, XYBitmap);
  998. XmInstallImage (pImage, (char *)pchName);
  999. } /* END OF FUNCTION WmInstallBitmapIntoXmCache */
  1000. /*************************************<->*************************************
  1001. *
  1002. * WmInstallBitmapDataIntoXmCache (pSD, pchName, pData)
  1003. *
  1004. *
  1005. * Description:
  1006. * -----------
  1007. * Installs built-in bitmap data into the Xm Pixmap cache. The image
  1008. * may be retrieved later by a call to XmGetPixmap.
  1009. *
  1010. * Inputs:
  1011. * ------
  1012. * pSD = pointer to screen data
  1013. * pchName = pointer to name of bitmap
  1014. * pData = pointer to the bitmap data
  1015. *
  1016. * Outputs:
  1017. * -------
  1018. * none
  1019. *
  1020. * Comments:
  1021. * --------
  1022. * This is principally for putting built-in pixmap data into the Xm
  1023. * cache to allow for uniform access to pixmap creation.
  1024. *
  1025. * ***WARNING***
  1026. * Do NOT call XmDestroyPixmap on images cached via this routine unless
  1027. * pData passed in points to malloc'ed memory. XmDestroyPixmap could
  1028. * try to free this data.
  1029. *
  1030. *************************************<->***********************************/
  1031. void WmInstallBitmapDataIntoXmCache (WmScreenData *pSD,
  1032. unsigned char *pchName, char *pData, unsigned int width,
  1033. unsigned int height)
  1034. {
  1035. XImage *pImage;
  1036. if ((pImage = (XImage *) XtMalloc (sizeof (XImage))))
  1037. {
  1038. pImage->width = width;
  1039. pImage->height = height;
  1040. pImage->xoffset = 0;
  1041. pImage->data = pData;
  1042. pImage->format = XYBitmap;
  1043. pImage->byte_order = MSBFirst;
  1044. pImage->bitmap_pad = 8;
  1045. pImage->bitmap_bit_order = LSBFirst;
  1046. pImage->bitmap_unit = 8;
  1047. pImage->depth = 1;
  1048. pImage->bytes_per_line = (width/8) + ((width%8) != 0 ? 1 : 0);
  1049. pImage->obdata = NULL;
  1050. XmInstallImage(pImage, (char *)pchName);
  1051. }
  1052. } /* END OF FUNCTION WmInstallBitmapDataIntoXmCache */